Skip to content

Update SD card connection / sharing options#14325

Merged
thinkyhead merged 10 commits intoMarlinFirmware:bugfix-2.0.xfrom
gloomyandy:pr_noinitusbsdcard
Jun 26, 2019
Merged

Update SD card connection / sharing options#14325
thinkyhead merged 10 commits intoMarlinFirmware:bugfix-2.0.xfrom
gloomyandy:pr_noinitusbsdcard

Conversation

@gloomyandy
Copy link
Contributor

Description

Recent changes to Marlin mean that when using a shared SD card Marlin will mount it at boot time. This fix changes the HAL startup code so that it no longer initially makes the SD card available over USB. Without this a host system will see the card, start reading it and then find it is no longer available (which causes errors). The card can be made availabe via USB to a host system by releasing the card either via the LCD or via gcode M22

Benefits

Stops hosts from getting errors while trying to mount the USB SD card.

Related Issues

#14318

@forkoz
Copy link
Contributor

forkoz commented Jun 19, 2019

that's a bum change. I need the SD over USB first before I go to print something. having commented out SD exclusivity until printing it doesn't affect me much yet but I'm basically going to have to reverse this in my builds.

I think a better change would be config option to mount SD at startup which then turns off mounting SD over USB at startup.

@gloomyandy
Copy link
Contributor Author

@forkoz Well that is a bigger issue and will need input from @thinkyhead this change is simply to make things work as well as they can with how things are at the moment.

I do agree that having a simple configuration option to decide if the card should be mounted at boot time makes sense. That may also help folks that do not have a display.

This is especially true if it turns out that Macs don't like SD cards coming and going (which looks like it may be the case).

@thinkyhead
Copy link
Member

thinkyhead commented Jun 19, 2019

The recent change I made was to help out in the case where you have enabled SDSUPPORT but you have set SD_DETECT_PIN to -1. I had to do this because an SD card extension cord has made the SD_DETECT_PIN useless on one printer. Now it tries to mount the SD card when it boots up, which is what you'd want.

I do agree that having a simple configuration option to decide if the card should be mounted at boot time makes sense. That may also help folks that do not have a display.

So, is it the case for all such boards that mounting the SD card associated with the SDSUPPORT feature causes the on-board SD card to become inaccessible to the connected computer? I have a couple of boards that I could test this behavior with.

Instead of this change, we should just check the new SD flags that we set in the pins files and if there is also an on-board SD card then I will skip the new mounting behavior. That will be better for almost all 32-bit boards.

@thinkyhead
Copy link
Member

thinkyhead commented Jun 19, 2019

So… which options should we check before deciding to mount the SD card reader accessory at startup? Here are the candidates…

LPC_SD_LCD      - Using SD card on the LCD for printing
LPC_SD_ONBOARD  - Using built-in SD card for printing
USB_SD_ONBOARD  - USB access to onboard SD card. (Requires LPC_SD_ONBOARD)
SHARED_SD_CARD  - SD card is used for printing, but also accessible via USB.
USB_SD_DISABLED - Override and disable USB access to the onboard SD card.

So maybe Marlin should only try to mount the SD card when…

NONE(SHARED_SD_CARD, LPC_SD_ONBOARD) \
  && (ENABLED(USB_SD_DISABLED) || !PIN_EXISTS(ONBOARD_SD_CS))

@gloomyandy
Copy link
Contributor Author

@thinkyhead Yes having both the USB code and Marlin access the SD card at the same time is not safe, so if Marlin mounts the card at boot time then the USB code should not, I think that will be true for all cards that can share the card via USB. In theory it should be fine to have Marlin mount the card at boot and have the USB code present an "empty" sd card reader to the host, then switch things later if required. However although this works fine on WIndows/LInux it looks like a Mac may not like it. Also I think allowing the user to choose if the card should be available to the host or to Marlin at boot would be nice and I think this change allows that?

A couple of points on the changes...

  1. I'm not sure the setting of SHARED_SD_CARD is correct in the conditionals file. The SD card will only be shared if USB_SD_ONBOARD is enabled and if LPC_SD_ONBOARD is enabled and if SDSUPPORT is enabled. For instance some users use the LCD SD card for Marlin (LPC_SD_LCD) but still make the on board SD card available via USB (USB_SD_ONBOARD) at the moment this would trigger the removal of the SD detect pin etc, which is probably not desired. Does that make sense?

  2. Should we allow for the user to force INIT_SDCARD_ON_BOOT manually (in the configuration file) if they want to have Marlin mount the shared SD card on boot? This may not work on a Mac, but I think some users would like to be able to do that. If so then I think the conditionals file will require an extra test to avoid a warning.

Final thought, do you think we should drop the LPC_ prefix for these settings? I suspect that we will need similar settings for other boards at some point.

@AnHardt
Copy link
Contributor

AnHardt commented Jun 19, 2019

Yes having both the USB code and Marlin access the SD card at the same time is not safe, so if Marlin mounts the card at boot time then the USB code should not ...

No.
At least not as long as both of the accessors are only reading. Not mounting the disk at all feels like chopping off the complete arm at the shoulder, when a finger is trapped.
Can we find a more surgical mechanism? Like cutting off at the elbow, the wrist or only the finger?

How about mounting as if the write protect on the sd-card is set until some wants to write?

How about disabling write access (writing and deleting) for Marlin completely, if the card can be accessed via USB (and EEPROM simulation and Power Loss Recovery are solved otherwise).

Can we protect the blocks used by the files we have to write to by file system flags (readonly, system, hidden, ...)? The files, we have to write to, are more or less fix in size.

Can we effectively protect the file Marlin reads from by setting 'readonly' while printing?

Is there a mechanism we can use to tell the USB side something has changed - so caches are invalid? Simulated 'card detect'?

@gloomyandy
Copy link
Contributor Author

@AnHardt

No.
At least not as long as both of the accessors are only reading. Not mounting the disk at all feels like chopping off the complete arm at the shoulder, when a finger is trapped.
Can we find a more surgical mechanism? Like cutting off at the elbow, the wrist or only the finger?

Well this is pretty much what we have had until now and so far we have had very few complaints. Anything other than pure read only for both is probably heading for problems (and certainly complexity) at some point. Pure read only for both does not seem very useful.

You are very limited in terms of communicating things to the host system, basically you can say the disk has been removed or inserted. But that tends to trigger a lot of activity from most host systems often the reading of many thousands of blocks so it can be slow. Also the way that different host systems react to this sort of thing seems to vary. In the case of the Mac it seems it does not like change at all!

Honestly if you really want a shared file system then it would be better to use something like MTP (rather than MSC) as the sharing mechanism, that works at a file level and is designed for this sort of thing. But when I last looked there did not seem to be any open source MTP implementation available and it needs more resources to manage the file/handle mapping.

@gloomyandy
Copy link
Contributor Author

@thinkyhead I've just pushed some changes to the shared card logic and also allowed for the user to force mounting of the shared SD card by Marlin. Please review.

I've tested most of the configurations and with this logic they seem to do what I would expect. The SD card will be mounted by Marlin on boot in all cases except when the card is shared. In that case the card will be made available to the host. In the case of both card readers being enabled Marlin will mount the LCD card and the host will mount the onboard card.

@AnHardt
Copy link
Contributor

AnHardt commented Jun 19, 2019

Well this is pretty much what we have had until now and so far we have had very few complaints.

That (especially in Marlin) is not an indicator for a initially good concept for what to do - just for a simple / fast / easy / more or less working implementation. It just was done by someone, Everyone was glad it worked somehow. But nobody else thought about that in dept. At least that's the usual way here.

@forkoz
Copy link
Contributor

forkoz commented Jun 20, 2019

I've had few issues sharing the SD between marlin and the host since the crashes have been fixed. I only make marlin de-host the SD when printing. Between prints I regularly delete files / add new ones then hit refresh. Only instances of legit corruption were when the printer crashed. Scandisk fixed it. Occasionally the scrolling long file names feature will meld names together after a bunch of deletes but I'm not sure if that is a bug in that feature or the file system.

The way it is stock causes extra work since the whole arm is cut off when marlin mounts the card. Only benefit is possible saving of files I will use only once, maybe twice at best. In a multi setting/material world the gcode isn't getting re-used much at least in my opinion. I might sing a different tune if I still used eeprom.dat, except those settings are being purged now whenever I flash new fw anyway.

Both readers used is an interesting concept. One would be for settings/fw and the other for gcode? If so, marlin would have to swap around cards with the host and itself in any case since you want to be able to add fw/gcode to the appropriate place but also read settings. Or possibly you only share the fw card and manually load the gcode SD, in which case andy's solution works well. On a personal level I haven't removed the SD in months and do everything over the cable, others may be doing the same via octoprint/esp, etc.

Copy link
Contributor Author

@gloomyandy gloomyandy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will not work correctly in the case of a user specifying USB_SD_ONBOARD and LPC_SD_LCD. In that case the USB option is active and INIT_SDCARD_ON_BOOT will be true (as it is in effect just an ordinary SD card case), but we will need to make the onboard SD card available via USB.

@gloomyandy
Copy link
Contributor Author

So just to confirm I have now tested the current state of the PR and it does not work correctly with the default settings for an SKR V1.3 board (which is to use the LCD SD card for Marlin and to share the onboard SD card with host via USB). Inserting/removing the SD card from the LCD reader is not detected (instead the menu has the Init SD item which it should not have), also when you Init SD the shared onboard SD card is no longer available to a host system, again this is not correct as in this configuration we are not sharing the any SD card between Marlin and the host.

Reverting the last commits to Conditionals_post.cpp and to main.cpp so that they now read...
Conditionals_post.cpp

#if ALL(USB_SD_ONBOARD, SDSUPPORT, LPC_SD_ONBOARD)
  #undef SD_DETECT_PIN
  #define SHARED_SD_CARD
#endif

#if ENABLED(SDSUPPORT) && DISABLED(SHARED_SD_CARD)
  #define INIT_SDCARD_ON_BOOT
#endif

and
main.cpp

  #if DISABLED(USB_SD_DISABLED) && !BOTH(SHARED_SD_CARD, INIT_SDCARD_ON_BOOT)
    MSC_SD_Init(0);                         // Enable USB SD card access
  #endif

restores the correct operation. Do you want me to update the PR?

@thinkyhead
Copy link
Member

Do you want me to update the PR?

Sure! And then I'll merge it to at least deal with the main issue.

@thinkyhead
Copy link
Member

thinkyhead commented Jun 20, 2019

#if ALL(USB_SD_ONBOARD, SDSUPPORT, LPC_SD_ONBOARD)

Again, note that USB_SD_ONBOARD will never be set unless the other two are.
So those other two don't need to be here.

@gloomyandy
Copy link
Contributor Author

#if ALL(USB_SD_ONBOARD, SDSUPPORT, LPC_SD_ONBOARD)

Again, note that USB_SD_ONBOARD will never be set unless the other two are.
So those other two don't need to be here.

@thinkyhead actually USB_SD_ONBOARD can be set without the others, in fact this is the default for some boards! Here is the code that does exactly that:
from the SKR V1.3 pins file....

#if !ANY(LPC_SD_LCD, LPC_SD_ONBOARD, LPC_SD_CUSTOM_CABLE)
  #undef USB_SD_DISABLED
  #define USB_SD_ONBOARD
  #define LPC_SD_LCD
#endif

The default configuration (from Configuration_Adv.h is to have none of "LPC_SD_LCD, LPC_SD_ONBOARD, LPC_SD_CUSTOM_CABLE" defined. As you can see in this case LPC_SD_ONBOARD will not be set, but USB_SD_ONBOARD is set!

Also some folks explicitly set USB_SD_ONBOARD but do not set SDSUPPORT, in this mode Marlin does not use an SD card, but the setting of USB_SD_ONBOARD means that the onboard SD card is still shared over USB and can be used to update the firmware. This is actually a useful mode it you don't use the SD card for Marlin, but want to be able to easily perform firmware updates. This option is not in the configuration files, but some users definitely use it (I've had conversations on Facebook and elsewhere about this setup).

In both of these cases USB_SD_ONBOARD will be set but we will not be sharing the SD card between Marlin and a host. The only time we actually share access to the card is when all three are defined.

Anyway I will update the PR...

@thinkyhead
Copy link
Member

thinkyhead commented Jun 20, 2019

All the pins files that have these options do this:
image
…and that is all the option does.

So there is an explicit linkage between LPC_SD_ONBOARD and USB_SD_ONBOARD.

image

@gloomyandy
Copy link
Contributor Author

You are missing the first part of the if statement in the code that you quoted. Again from the SKR V1.3 pins file....

#if !ANY(LPC_SD_LCD, LPC_SD_ONBOARD, LPC_SD_CUSTOM_CABLE)
  #undef USB_SD_DISABLED
  #define USB_SD_ONBOARD
  #define LPC_SD_LCD
#endif

#if ENABLED(LPC_SD_LCD)

  #define SCK_PIN          P0_15
  #define MISO_PIN         P0_17
  #define MOSI_PIN         P0_18
  #define SS_PIN           P0_16   // Chip select for SD card used by Marlin
  #define ONBOARD_SD_CS    P0_06   // Chip select for "System" SD card

#elif ENABLED(LPC_SD_ONBOARD)

  #if ENABLED(USB_SD_ONBOARD)
    // When sharing the SD card with a PC we want the menu options to
    // mount/unmount the card and refresh it. So we disable card detect.
    #define SHARED_SD_CARD
    #undef SD_DETECT_PIN
    //#define SD_DETECT_PIN  P0_27   // (57) open-drain
  #endif

So in the default case (the first if statement) we will have LPC_SD_LCD defined and USB_SD_ONBOARD defined but we will not have LPC_SD_ONBOARD defined. Note that in this case SHARED_SD_CARD is NOT set (as we take the first part of the following if statement), which is correct for this configuration. So in that case there is no linkage between USB_SD_ONBOARD and LPC_SD_ONBOARD.

Basically SHARED_SD_CARD should not be set unless USB_SD_ONBOARD, LPC_SD_ONBOARD and SDSUPPORT are all defined. This is the only situation in which both Marlin and the host both have access to the SD card. In all other cases the card is not shared.

@thinkyhead
Copy link
Member

thinkyhead commented Jun 20, 2019

So in the default case (the first if statement) we will have LPC_SD_LCD defined and USB_SD_ONBOARD defined but we will not have LPC_SD_ONBOARD defined.

Right. And I think that is an error because it then has no effect.

@thinkyhead
Copy link
Member

thinkyhead commented Jun 20, 2019

I see that the LPC_SPI / SD options were added to the configuration files. While this then allows a user to set LPC_SD_ONBOARD themselves, you will note that in the pins file the test #if !ANY(LPC_SD_LCD, LPC_SD_ONBOARD, LPC_SD_CUSTOM_CABLE) will skip forcing USB_SD_ONBOARD to be set. The user will have to set it in their configuration. Where you see it is only permitted (and only relevant) for LPC_SD_ONBOARD.

@gloomyandy
Copy link
Contributor Author

gloomyandy commented Jun 20, 2019

Why do you think that is an error? I don't see any problem with it at all. It is saying I want to use the SD card on the LCD for Marlin (LPC_SD_LCD), but I want to share the SD card on the board over USB (USB_SD_ONBOARD) this allows for conventional Marlin use of the LCD SD card, but provides the on board SD card to a PC for easy firmware updates. What is wrong with that?

you will note that #if !ANY(LPC_SD_LCD, LPC_SD_ONBOARD, LPC_SD_CUSTOM_CABLE) will skip forcing USB_SD_ONBOARD to be set.

in the following default case...

#if !ANY(LPC_SD_LCD, LPC_SD_ONBOARD, LPC_SD_CUSTOM_CABLE)
  #undef USB_SD_DISABLED
  #define USB_SD_ONBOARD
  #define LPC_SD_LCD
#endif

It explicitly sets both USB_SD_ONBOARD and LPC_SD_LCD which is a valid combination as described above. So I don't think there is an actual problem here as such.

@gloomyandy
Copy link
Contributor Author

I would say though that this...

    #if ENABLED(LPC_SD_ONBOARD)
      //#define USB_SD_ONBOARD    // Provide the onboard SD card to the host as a USB mass storage device.
    #endif

In the configuration files is probably confusing. It is certainly valid to set USB_SD_ONBOARD in other circumstances. Like the above example of using the LCD SD card reader. Perhaps the

if ENABLED(LPC_SD_ONBOARD)

Should be removed?

@thinkyhead
Copy link
Member

First thing is first. I want to preserve the existing logic for these options before modifying any other logic or behavior. That is why I keep asserting these points.

LPC_SD_LCD and USB_SD_ONBOARD might be ok to enable together. But enabling LPC_SD_LCD causes USB_SD_ONBOARD to have no effect.

Go back to the current code search for where USB_SD_ONBOARD is being used. You will discover that it is only being mentioned in the pins_MY_BOARD.h files. And what is it doing there? It is only ever being used when LPC_SD_ONBOARD is set. What is the only effect of USB_SD_ONBOARD? It causes SHARED_SD_CARD to be set and SD_DETECT_PIN to be removed.

Let us start from this point, where the existing logic (unchanged!) has simply been migrated over to the Conditionals_post.h file instead of being repeated in several pins files. And then I will be ready to look at what other meanings or combinations might be used together and what effects those other meanings and combinations may have on LPC and beyond.

@gloomyandy
Copy link
Contributor Author

gloomyandy commented Jun 21, 2019

I'm not sure that all of the original logic was actually maintained when it was migrated from the pins file. At least some of the clarity was lost. I think to fully understand this you need to step back to how it was before then...

The configuration scheme as used in the pins files came from @p3p and was based on my original PR to his Marlin branch. At the time it only applied to the MKS SBase and RAMPS_RE_ARM. Here is my understanding of how it works.

For reference this is how the configuration options looked before they were moved to the config files...

/**
 * The SBase can share the on-board SD card with a PC via USB the following
 * definitions control this feature:
 */
//#define USB_SD_DISABLED
#define USB_SD_ONBOARD        // Provide the onboard SD card to the host as a USB mass storage device

/**
 * There are a number of configurations available for the SBase SD card reader.
 * - A custom cable can be used to allow access to the LCD based SD card.
 * - A standard cable can be used for access to the LCD SD card (but no SD detect).
 * - The onboard SD card can be used and optionally shared with a PC via USB.
 */

//#define LPC_SD_CUSTOM_CABLE // Use a custom cable to access the SD
//#define LPC_SD_LCD          // Marlin uses the SD drive attached to the LCD
#define LPC_SD_ONBOARD        // Marlin uses the SD drive attached to the control board

See:

First we have the defines that control making an SD card available over USB. USB_SD_DISABLED and USB_SD_ONBOARD. These two settings are mutually exclusive, only one from this set should ever be defined. All other settings are invalid. Note that in effect this means we have two bits of data defining only two states which is overkill but I think Chris probably had in mind that there is a possible further option USB_SD_LCD (make the LCD SD card reader available via USB) that is not currently available. but which would make sense to have.

We then have the settings that define which SD card is used by Marlin, in this case we have three again mutually exclusive settings LPC_SD_CUSTOM_CABLE, LPC_SD_LCD and LPC_SD_ONBOARD. Note again only a single one of these should ever be defined other combinations are invalid.

If in either case none of the available options has been selected then a default case should apply. As you can see above the default was explicit when the defines were in the pins file. I think this is currently true for the LPC_ settings, but I'm not sure that it is always being correctly set in the USB_ case.

That is pretty much it. There is no limitation on how the above two sets can be combined. So there are six possible configurations, all of which are valid (though the custom cable options may only apply to some boards).

From this you can see that LPC_SD_LCD and USB_SD_ONBOARD is a valid combination. Yes it is true that USB_SD_ONBOARD is not used directly in code with this setup, but the fact that USB_SD_DISABLED is not set is the important part. So having USB_SD_ONBOARD defined when LPC_SD_LCD is also defined is not strictly required, however I think it should be as it ......
a) Follows the rules about having exactly one of USB_SD_DISABLED or USB_SD_ONBOARD defined.
b) It describes what is actually happening, the onboard SD card is being made available by USB.
c) Is future proof in case USB_SD_LCD ever gets added.

When all of this logic was just in the pins file I think it was a little clearer. In the process of moving the configuration options I think the notion that the two sets have mutually exclusive values was lost (I think it was more obvious, though not explicitly stated or enforced when the settings were in the pins file). Also there was no direct linkage between the setting of LPC_SD_ONBAORD and USB_SD_ONBOARD. That #if was added when the settings were moved from the pins file into the configuration files. I think it should be removed. We also probably need to add some tests to ensure the mutual exclusive rules are followed.

I think some of the confusion here is because we are using simple enabled/disabled defines to describe what is in effect a multiple value variable. You may find it useful to look at the original pr as submitted to @p3p when I did the initial work on this feature. This did not use the current system for configuration and was I think clearer in its intention. @p3p came up with the current way of doing things before he submitted a PR to Marlin (and I can understand why as it reduced the number of defines a little). You can see the original configuration options here:
https://github.com/gloomyandy/Marlin/blob/pr_ga_usbsdcard/Marlin/src/pins/pins_MKS_SBASE.h#L186

So that's my best effort at describing how this all works. @p3p may have other comments.

EDITED: To fix typos and mistakes

@gloomyandy
Copy link
Contributor Author

No idea why this failed in the Travis tests....

The command "sudo -E apt-add-repository -y "ppa:ubuntu-toolchain-r/test"" failed and exited with 1 during .

Some sort of problem with Travis?

@thinkyhead
Copy link
Member

Thanks for going over those points. Is this now fully corrected and in line with your description?

I'll see if the Travis test needs a kick. It often fails due to non-code errors, and this seems more common since we switched to a different Linux distro for the build.

@gloomyandy
Copy link
Contributor Author

At the moment the actual code/logic is correct. But I have not made any changes to the configuration files or to the sanity checks (to enforce choosing one option only from each set etc.). I will have a go at doing that later if you want?

@AnHardt
Copy link
Contributor

AnHardt commented Jun 24, 2019

The HALs are intended to abstract processors or if possible processor families.
The pin-files are intended to abstract boards or board combos, like a RAMPS on a ReArm or RAMPS on a MEGA or RAMPS-FD on DUE or simply a RUMBA.

@gloomyandy
Copy link
Contributor Author

@GMagician sorry mixed folks up.

But doesn't each shield need to have a pins file anyway? In which case is it that much trouble to have the onboard defines in there? There are two reason I don't like having this override in the HAL...

  1. My understanding is that a HAL is supposed to be for a particular processor really not for a particular board. So having things that are specific to a particular board (rather then a processor) seems a little off to me. But maybe I've got this wrong?
  2. I don't like having basic information hidden away. So I'd much rather like to be able to see that the onboard SD card uses these pins in the pins file, rather than having to dig around in the HAL to find it.

If this definition is common to a set of boards then can't the pins file have a base pins definition with other shield specific stuff in the shield pins files? Haven't we already had this situation with the RAMPS/ReArm combination? How many of these are we talking about?

@GMagician
Copy link
Contributor

@AnHardt & @gloomyandy I understand that HAL should address processor specific parts but also I'm thinking at my case (and maybe this may be exctended).
Grand central M4 has an on board SD (this is a board) but uses shield boards. These shields board may be used in more than one board (ramps-fd and ruramps fd may also be used with DUE) but GCM4 onboard sd has nothing to do with shield pinout.
Then to support both DUE and GCM4 pins has to add if else to properly redirect sd pins when on board SD is required...but what if some new boards appears? a new if else to remap this board new pins.
Maybe have I to create a ramps-fd and ruramps4d duplicate with GCM4 pinout? or let if else proliferation?
@gloomyandy note that onboard sd pinout can't change since they are board dependent, not shield dependent. So nothing is hidden because nothing can be changed by users.

I would like to note that I have not approached SD implementation till now so maybe my info are wrong.
Now only thing that is workind is digital I/O, serial (not terminated but working) and DMA on AIN (almost ready). Next step will be timers, pwm and finally SD

@gloomyandy
Copy link
Contributor Author

@GMagician The problem is if you add this board specific code into your HAL then that means if there is another board with the same processor we will have to have another HAL to support it. Given that HALs are much bigger than the pins files I think it would be better to have additional pins files rather then additional HALs. But that is just my view.

As to the hidden information. What I mean is that as a user and a developer I would expect to find how all of the pins are being used in the pins file. I don't really want the HAL to go and reassign things as I wouldn't be expecting that.

@gloomyandy
Copy link
Contributor Author

I've tested pretty much everything I can, most things are fine. However there a few final issues....

  1. If you set USB_SD_DISABLED and set SD_CARD_CONNECTION to ONBOARD (so no USB sharing at all and Marlin uses the onboard Sd card reader) then many of the configurations will use the wrong SD_DETECT_PIN, they end up using the LCD SD card reader's pin, which really does not make any sense! I've pushed changes to the pins files to fix this. Where I know that there is a detect pin for the onboard reader, it will use it, otherwise it undefines the pin. I'm pretty sure this bug has been around for a while, most people will not have seen the error as they will have been sharing the SD card over USB as well (which will have undefined the detect pin).

  2. At the moment it is possible to have both USB_SD_DISABLED and USB_SD_ONBOARD undefined. This results in Marlin sharing the onboard Sd card over USB but without any chacks on shared access. I think this is an error as it can result in both Marlin and the USB host accessing the SD card at the same time. I was tempted to add a check for this (at least one option set), but noticed that this is the default setting in the AZTEEG_X5_MINI and AZSMZ_MINI pins files. I didn't want to cause problems with these boards so I've not changed anything. But I really don't think it is a good idea. Any thoughts on the best option here?

  3. As I mentioned earlier at the moment it is not possible/easy to set USB_SD_ONBOARD if SDSUPPORT is disabled. This seems like it should be a valid option. I don't see any real harm in moving the entire set of settings outside of the SDSUPPORT section, but would be interested in what others think?

@thinkyhead
Copy link
Member

I agree that USB_SD_ONBOARD is distinct from SDSUPPORT which only concerns Marlin being able to deal internally (and through hosts) with SD cards. It should not be dependent.

@thinkyhead
Copy link
Member

thinkyhead commented Jun 25, 2019

I've pushed changes to the pins files to fix this.

Make sure the stuff in Conditionals_post.h isn't going to conflict with that. It currently reads:

#if ENABLED(SDSUPPORT)
  #if SD_CONNECTION_IS(ONBOARD) && ENABLED(USB_SD_ONBOARD)
    #undef SD_DETECT_PIN
    #define SHARED_SD_CARD
  #endif
  #if DISABLED(SHARED_SD_CARD)
    #define INIT_SDCARD_ON_BOOT
  #endif
#endif

It looks like this will undo the SD_DETECT_PIN set in pins_BIGTREE_SKR_V1.3.h, but maybe that is intentional for the above case…? (i.e., It could be that the SD_DETECT_PIN being set in pins_BIGTREE_SKR_V1.3.h is only for the case DISABLED(USB_SD_ONBOARD).)

it is possible to have both USB_SD_DISABLED and USB_SD_ONBOARD undefined…

The only design restriction I know about is that they cannot both be enabled at the same time. Which option is it that causes at least one of these two options to be required? Would it be for every LPC1768 board?

If it is the case that at least one of these is required then they can be reduced to a single option. If it's enabled, you get one behavior. And if not, then you get the other.

@thinkyhead
Copy link
Member

…noticed that this is the default setting in the AZTEEG_X5_MINI and AZSMZ_MINI pins files…

I'm not sure, but I believe that if we follow the thinking that if neither option is enabled in the configs, then the board default should apply… And, if we want USB_SD_DISABLED and USB_SD_ONBOARD to really act as opposites… Then we just need to decide what the missing board defaults ought to be. The safest default would be USB_SD_DISABLED but it may be that for certain boards users have the opposite expectation.

I say, let's pick one and we can always switch it if we get complaints.

@gloomyandy
Copy link
Contributor Author

@thinkyhead thanks for the feedback on this. I have now updated the PR to include the above points...

By default the SD card will be shared by USB. I think most users will expect this to enable easy firmware updates. This feature is now controlled by a single define USB_SD_DISABLED which will disable the sharing if set. I don't really like using a negative configuration variable but in this case I think it makes sense. I have moved the setting of this define out of the test against SDSUPPORT and cleaned up the configuration and pins files.

It looks like this will undo the SD_DETECT_PIN set in pins_BIGTREE_SKR_V1.3.h, but maybe that is intentional for the above case…? (i.e., It could be that the SD_DETECT_PIN being set in pins_BIGTREE_SKR_V1.3.h is only for the case DISABLED(USB_SD_ONBOARD).)

Yes you are correct these settings are only intended for use when the SD card is not being shared over USB as well and the setting will be undone in the case of the card being shared.

gloomyandy and others added 9 commits June 26, 2019 01:35
Recent changes to Marlin mean that when using a shared SD card Marlin will mount it at boot time. This fix changes the HAL startup code so that it no longer initially makes the SD card available over USB. Without this a host system will see the card, start reading it and then find it is no longer available (which causes errors). The card can be made availabe via USB to a host system by releasing the card either via the LCD or via gcode M22
Only set shared state when the card is actually being shared, allow use of LCD SD card for MArlin, while still sharing onboard SD card over USB.

Base automatic setting of INIT_SDCARD_ON_BOOT on sharing state.

Allow for INIT_SDCARD_ON_BOOT to be forced by user.
@thinkyhead thinkyhead force-pushed the pr_noinitusbsdcard branch from 77a096b to 1d02d36 Compare June 26, 2019 06:37
@thinkyhead thinkyhead force-pushed the pr_noinitusbsdcard branch from 928364d to a087f49 Compare June 26, 2019 06:45
@thisiskeithb
Copy link
Contributor

Will this cover STM32F boards like the BigTreeTech SKR Mini 1.1 and the million other STM32F boards they keep creating?

@thinkyhead
Copy link
Member

So far this only pertains to LPC1768. We don't have SD card sharing control for other platforms at this time.

@thinkyhead thinkyhead merged commit 0641771 into MarlinFirmware:bugfix-2.0.x Jun 26, 2019
@thinkyhead thinkyhead changed the title Do not initially share the SD card over USB Update SD card connection / sharing options Jun 26, 2019
@gloomyandy gloomyandy deleted the pr_noinitusbsdcard branch June 26, 2019 13:32
@thinkyhead
Copy link
Member

I'm revisiting this PR in relation to #27815 where I'm working on completing the handling of multi-volume insert/remove. I want to make sure I'm handling MSC properly and not making a mess of it. So if anyone would like to help review that PR and provide insight to help us clear up glitches and put the final touches on this core part of the firmware, we'd appreciate your input!

//
#if ENABLED(SDSUPPORT)
#if SD_CONNECTION_IS(ONBOARD) && DISABLED(NO_SD_HOST_DRIVE)
#undef SD_DETECT_PIN
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Specifically, for the benefit of multi-volume I hope to keep the SD_DETECT_PIN and show the "Refresh" item only in the file listings of the shared volume, preferably only when it is currently mounted on the PC. This pin is useful and we can hide/show menu items by better criteria.

I'm not sure where we stand on volumes being shared with PC while mounted by the firmware (and so on) so could use guidance on what is safe. I am seeing some slowness in sharing the USB Flash Drive over MSC and contention between Marlin and the PC when it is later inserted — but otherwise it all works great! Our current work is in conjunction with multi-volume, looking for the best approach to elegantly claim / release media and track media sharing status.

Copy link
Member

@p3p p3p Apr 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main thing to remember is that MSC is a block level protocol, you cannot have block level access to a memory device from 2 hosts as they can both change low level data, MTP was supposed to be a solution to this as it is a "file" level protocol and doesn't handle the filesystem, though it has other problems. so a block device can only be used by 1 host at a time, even if it has multiple partitions.

The fact that Windows (as of when I wrote the LPC usb stuff) ignores the MSC/SCSI commands to control access and report removal complicates it even more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants