cancel
Showing results for 
Search instead for 
Did you mean: 

USB host, mass storage class - how to tell when memory stick has completed writes and is safe to power down.

JGerb
Associate III

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);

}

1 REPLY 1
JGerb
Associate III

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.