2019-01-09 12:27 AM
I’m using the STM32L476 discovery kit to test an application where a battery-powered product powers up a USB memory stick, connects to it, writes some data, and then shuts the stick down again, removing power. I've used the STM32 Cube to generate the code and I have the application largely working, data writes fine when I am single-stepping in the debugger, however, if I let it free-run it looks like the power to the stick is being removed prematurely, as the file system on the USB memory stick is being corrupted. Is there a correct way to check if all transfers have been completed on the USB and the stick is idle, before stopping USB? I am using USBH_MSC_IsReady, but it seems to not be sufficient.
For now, simply adding a 1 second delay before USBH_Stop seems to solve the problem, however, this isn't ideal in a product, and I have no idea if this is long enough.
Code below
void writeToStick(void)
{
uint32_t i;
uint8_t success = TRUE;
/* Init host Library, add supported class and start the library. */
MX_USB_HOST_Init();
while (USBH_MSC_IsReady(&hUsbHostFS) == 0)
{
MX_USB_HOST_Process();
}
//initialise FAT file system
MX_FATFS_Init();
MX_USB_HOST_Process();
fileError = f_mount(&USBHFatFS, (TCHAR const*)USBHPath, 0);
MX_USB_HOST_Process();
fileError = f_open(&MyFile, "STM32.TXT", FA_CREATE_ALWAYS | FA_WRITE);
if (fileError == FR_OK)
{
//write our 100-byte buffer until we have 1 Mb of data
for (i=0; i < (1024*10); i++)
{
if(f_write(&MyFile, wtext, sizeof(wtext)-1, (void *)&wbytes) != FR_OK)
{
success = FALSE;
}
}
//an f_ close should do an f_sync as well, flushing file buffers
f_close(&MyFile);
//wait for USB buffers to flush
while (USBH_MSC_IsReady(&hUsbHostFS) == 0)
{
MX_USB_HOST_Process();
}
}
//unmount file system
fileError = f_mount(NULL, (TCHAR const*)USBHPath, 1);
MX_USB_HOST_Process();
//wait again, in case some more buffers need flushing
while (USBH_MSC_IsReady(&hUsbHostFS) == 0)
{
MX_USB_HOST_Process();
}
//unlink driver
MX_FATFS_DeInit();
MX_USB_HOST_Process();
//and wait again, just in case
while (USBH_MSC_IsReady(&hUsbHostFS) == 0)
{
MX_USB_HOST_Process();
}
//stop the USB, and remove power
USBH_Stop(&hUsbHostFS);
/* De-Init */
USBH_DeInit(&hUsbHostFS);
}
2019-01-14 03:59 AM
After discussion with the ST gurus and some more testing, we have found the following :
1) The corruption doesn't happen on a Sandisk memory stick, provided you shut down in an orderly fashion. (close file, call f_mount(NULL,USBHPath), call USBH_Stop)
2) On my cheaper memory stick, it's usually the last 4kb that gets corrupted, which checkdisk will find for you and put in FOUND.000.
3) If you close the file after writing, then re-open as read-only, read 512 bytes out, and then close, before proceeding with shutdown, then the problem doesn't happen. Whether this flushes some sort of buffer in the memory stick or the stack I don't know, but I did also try only reading back 2 bytes this way, which didn't appear to fix it. Many examples I've seen do a complete readback + verify of the file, which seems excessive.