@@ -45,6 +45,11 @@ static bool ejected[LUN_COUNT] = { [0 ... (LUN_COUNT - 1)] = true};
4545static bool eject_once [LUN_COUNT ] = { [0 ... (LUN_COUNT - 1 )] = false};
4646static bool locked [LUN_COUNT ] = { [0 ... (LUN_COUNT - 1 )] = false};
4747
48+ // Set to true if a write was in a file data or metadata area,
49+ // as opposed to in the filesystem metadata area (e.g., dirty bit).
50+ // Used to determine if an auto-reload is warranted.
51+ static bool content_write [LUN_COUNT ] = { [0 ... (LUN_COUNT - 1 )] = false};
52+
4853#include "tusb.h"
4954
5055static const uint8_t usb_msc_descriptor_template [] = {
@@ -141,6 +146,7 @@ static fs_user_mount_t *get_vfs(int lun) {
141146 if (lun == SDCARD_LUN ) {
142147 const char * path_under_mount ;
143148 fs_user_mount_t * sdcard = filesystem_for_path ("/sd" , & path_under_mount );
149+ // If "/sd" is on the root filesystem, nothing has been mounted there.
144150 if (sdcard != root && (sdcard -> blockdev .flags & MP_BLOCKDEV_FLAG_NATIVE ) != 0 ) {
145151 return sdcard ;
146152 } else {
@@ -290,34 +296,50 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t *
290296 if (vfs == NULL ) {
291297 return -1 ;
292298 }
299+
293300 disk_write (vfs , buffer , lba , block_count );
294301 // Since by getting here we assume the mount is read-only to
295- // MicroPython let's update the cached FatFs sector if it's the one
302+ // CircuitPython let's update the cached FatFs sector if it's the one
296303 // we just wrote.
304+ if
297305 #if FF_MAX_SS != FF_MIN_SS
298- if (vfs -> fatfs .ssize == MSC_FLASH_BLOCK_SIZE ) {
306+ (vfs -> fatfs .ssize == MSC_FLASH_BLOCK_SIZE )
299307 #else
300308 // The compiler can optimize this away.
301- if (FF_MAX_SS == FILESYSTEM_BLOCK_SIZE ) {
302- #endif
309+ (FF_MAX_SS == FILESYSTEM_BLOCK_SIZE )
310+ #endif
311+ {
303312 if (lba == vfs -> fatfs .winsect && lba > 0 ) {
304313 memcpy (vfs -> fatfs .win ,
305314 buffer + MSC_FLASH_BLOCK_SIZE * (vfs -> fatfs .winsect - lba ),
306315 MSC_FLASH_BLOCK_SIZE );
307316 }
308317 }
309318
319+ // A write to an lba below fatbase is in the filesystem metadata (BPB) area or the "Reserved Region",
320+ // and is probably setting or clearing the dirty bit. This should not trigger auto-reload.
321+ // All other writes will trigger auto-reload.
322+ if (lba >= vfs -> fatfs .fatbase ) {
323+ content_write [lun ] = true;
324+ }
325+
310326 return block_count * MSC_FLASH_BLOCK_SIZE ;
311327}
312328
313329// Callback invoked when WRITE10 command is completed (status received and accepted by host).
314330// used to flush any pending cache.
315331void tud_msc_write10_complete_cb (uint8_t lun ) {
316- (void )lun ;
317-
318- // This write is complete; initiate an autoreload.
319332 autoreload_resume (AUTORELOAD_SUSPEND_USB );
320- autoreload_trigger ();
333+
334+ // This write is complete; initiate an autoreload if this was a file data or metadata write,
335+ // not just a dirty-bit write.
336+ if (content_write [lun ] &&
337+ // Fast path: lun == 0 is CIRCUITPY, which can always trigger auto-reload if enabled.
338+ // Don't autoreload if this lun was mounted by the user: that will cause a VM stop and an unmount.
339+ (lun == 0 || !gc_ptr_on_heap (get_vfs (lun )))) {
340+ autoreload_trigger ();
341+ content_write [lun ] = false;
342+ }
321343}
322344
323345// Invoked when received SCSI_CMD_INQUIRY
@@ -337,7 +359,7 @@ bool tud_msc_test_unit_ready_cb(uint8_t lun) {
337359 return false;
338360 }
339361
340- #if CIRCUITPY_SDCARDIO
362+ #if CIRCUITPY_SDCARD_USB
341363 if (lun == SDCARD_LUN ) {
342364 automount_sd_card ();
343365 }
0 commit comments