This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

EJECT FAILURE IN STM32 USB MASS STORAGE EXAMPLE

Hi all,
I am using the stm32usb_mem keil example for USB mass storage implementation.
It is working well as mass storage device.
I found that when i right click the device to use the eject option.
I got an error message "An error was encountered trying to eject Device(G:)".
The device cannot be removed.
Anyone can solve this problem.

Thanks
Aru

  • It seems that problem is that that example uses too small memory and when windows wants to eject it wants to write to disk but it is too small end there are problems.
    Try Memory_FlashFS\SD_File\ example.

  • Hi wild,
    Thanks for your reply.
    I checked the USB protocol while the eject process.
    I found that using debug message,the PC requests following commands SCSI_MEDIA_REMOVAL and
    SCSI_START AND STOP UNIT,SCSI_MODE_SELECT 10,but these commands are not implemented in the USB protocol.
    Can i know how to implement these commands that will be supported by USB protocol.
    Thanks

  • Hi Wild,
    Thanks for your reply.........
    I checked the USB protocol as your suggestion and found that the PC does not requests the
    SCSI_WRITE10 command during eject process.
    Can i know the location of Memory_FlashFS\SD_File\ example.
    Thanks

  • It is in folder where you installed MDK something like C:\Keil\ARM\Boards\"Vendor"\"Board"\RL\USB\Device\Memory_flashFS\SD_File\ (for example for NXP MCB2300 board C:\Keil\ARM\Boards\Keil\MCB2300\RL\USB\Device\Memory_FlashFS\SD_File\)

    Unfortunately not all boards have this example.

  • Sorry, I now saw you are talking about STM32 it should be in folder C:\Keil\ARM\Boards\Keil\MCBSTM32\RL\USB\Device\Memory_FlashFS\SD_File\

  • > I found that using debug message,the PC requests following commands SCSI_MEDIA_REMOVAL and SCSI_START AND STOP UNIT,SCSI_MODE_SELECT 10,but these commands are not implemented in the USB protocol.
    > Can i know how to implement these commands that will be supported by USB protocol.

    Does your drive have auto-eject capability?

    OS puts PREVENT ALLOW MEDIUM REMOVAL(PREVENT:01b - prohibit removal), to know the auto-eject capability of the drive on mount.

    a) Auto eject drive
    If the device succeeds on this command, OS assumes auto-eject capability of the reader.
    On drag-to-trash eject, OS writes the write cache to the media. And then, it puts this command sequence, to eject the media by command.

    - PREVENT ALLOW MEDIUM REMOVAL(PREVENT:00b - allow removal)
    - START STOP UNIT(IMMED:0, POWER CONDITION:0h(START_VALID), LOEJ:1, START:0) - unload medium

    [58.672,342] FS: Data Transfer (Bulk-OUT) Addr:04 Endp:1 - CBW: PREVENT ALLOW MEDIUM REMOVAL
                 55 53 42 43 91 00 00 00 00 00 00 00 00 00 06 1E
                 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    [58.672,520] FS: Data Transfer (Bulk-IN) Addr:04 Endp:1 - CSW - Status:Passed
                 55 53 42 53 91 00 00 00 00 00 00 00 00
    [58.672,681] FS: Data Transfer (Bulk-OUT) Addr:04 Endp:1 - CBW: START STOP UNIT
                 55 53 42 43 92 00 00 00 00 00 00 00 00 00 06 1B
                 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00
    [58.672,832] FS: Data Transfer (Bulk-IN) Addr:04 Endp:1 - CSW - Status:Passed
                 55 53 42 53 92 00 00 00 00 00 00 00 00
    

    After START STOP UNIT, the device should fail TEST UNIT READY and other commands, because of no media.

    b) Manual eject
    Manual eject reader should fail PREVENT ALLOW MEDIUM REMOVAL(PREVENT:01b) at the mount of a media.
    The Sense Data for this fail is,
    - Sense Key: ILLEGAL REQUEST (0x05)
    - ASC/ASCQ : INVALID COMMAND OPERATION CODE (0x20/0x00)

      0x70,    // response code
      0x00,    // obsolete
      0x05,    // sense key - ILLEGAL REQUEST
      0x00,    // information
      0x00,
      0x00,
      0x00,
      0x0A,    // additional sense length - 10 bytes
      0x00,    // command-specific info
      0x00,
      0x00,
      0x00,
      0x20,    // additional sense code - INVALID COMMAND OPERATION CODE
      0x00,    // additional sense code qualifier
      0x00,    // field replacement unit code
      0x00,    // sense key specific
      0x00,
      0x00
    


    On eject, OS writes the write cache to the media.
    And then, it polls completion of manual eject using TEST UNIT READY

    Tsuneo

  • Hi chinzei,
    Thanks for your explanation.
    I understand your words.
    This is my debug output.
    When the OS ejects the drive....
    SCSI_MEDIA_REMOVAL
    MSC_SetCSW
    SCSI_MODE_SELECT6
    fail
    MSC_SetCSW
    SCSI_START_STOP_UNIT
    MSC_SetCSW
    SCSI_MEDIA_REMOVAL
    MSC_SetCSW
    SCSI_MODE_SELECT6
    fail
    MSC_SetCSW
    MSC_RequestSense
    MSC_SetCSW
    MSC_TestUnitReady
    MSC_SetCSW

    CSW Status is Passed in these commands SCSI_MEDIA_REMOVAL and SCSI_START_STOP_UNIT,but failed in SCSI_MODE_SELECT6,because it is not implemented in this Keil example protocol.

    Can you find my mistake in this implementation

    this is my source code:

    void MSC_RequestSense (void) {

    if (!DataInFormat()) return;

    BulkBuf[ 0] = 0x70; /* Response Code */ BulkBuf[ 1] = 0x00; BulkBuf[ 2] = 0x02; /* Sense Key */ BulkBuf[ 3] = 0x00; BulkBuf[ 4] = 0x00; BulkBuf[ 5] = 0x00; BulkBuf[ 6] = 0x00; BulkBuf[ 7] = 0x0A; /* Additional Length */ BulkBuf[ 8] = 0x00; BulkBuf[ 9] = 0x00; BulkBuf[10] = 0x00; BulkBuf[11] = 0x00; BulkBuf[12] = 0x30; /* ASC */ BulkBuf[13] = 0x01; /* ASCQ */ BulkBuf[14] = 0x00; BulkBuf[15] = 0x00; BulkBuf[16] = 0x00; BulkBuf[17] = 0x00;

    BulkLen = 18; DataInTransfer();
    }

    void MSC_ModeSense6 (void) {

    if (!DataInFormat()) return;

    BulkBuf[ 0] = 0x03; BulkBuf[ 1] = 0x00; BulkBuf[ 2] = 0x00; BulkBuf[ 3] = 0x00;

    BulkLen = 4; DataInTransfer();
    }

    /* * MSC SCSI Mode Sense (10-Byte) Callback * Parameters: None (global variables) * Return Value: None */

    void MSC_ModeSense10 (void) {

    if (!DataInFormat()) return;

    BulkBuf[ 0] = 0x00; BulkBuf[ 1] = 0x06; BulkBuf[ 2] = 0x00; BulkBuf[ 3] = 0x00; BulkBuf[ 4] = 0x00; BulkBuf[ 5] = 0x00; BulkBuf[ 6] = 0x00; BulkBuf[ 7] = 0x00;

    BulkLen = 8; DataInTransfer();
    }

    void MSC_GetCBW (void) { DWORD n;

    for (n = 0; n < BulkLen; n++) { *((BYTE *)&CBW + n) = BulkBuf[n]; } if ((BulkLen == sizeof(CBW)) && (CBW.dSignature == MSC_CBW_Signature)) { /* Valid CBW */

    CSW.dTag = CBW.dTag;

    CSW.dDataResidue = CBW.dDataLength;

    if ((CBW.bLUN != 0) || (CBW.bCBLength < 1) || CBW.bCBLength > 16) {

    fail: CSW.bStatus = CSW_CMD_FAILED;

    MSC_SetCSW();

    } else {

    switch (CBW.CB[0]) {

    case SCSI_TEST_UNIT_READY:

    MSC_TestUnitReady();

    break;

    case SCSI_REQUEST_SENSE:

    MSC_RequestSense();

    break; case SCSI_FORMAT_UNIT:

    goto fail;

    case SCSI_INQUIRY:

    MSC_Inquiry();

    break;

    case SCSI_START_STOP_UNIT:

    CSW.bStatus = CSW_CMD_PASSED;

    MSC_SetCSW();

    // goto fail;

    case SCSI_MEDIA_REMOVAL:

    CSW.bStatus = CSW_CMD_PASSED;

    MSC_SetCSW();

    // goto fail;

    case SCSI_MODE_SELECT6:

    goto fail;

    case SCSI_MODE_SENSE6:

    MSC_ModeSense6();

    break; case SCSI_MODE_SELECT10:

    goto fail;

    case SCSI_MODE_SENSE10:

    MSC_ModeSense10();

    break; case SCSI_READ_FORMAT_CAPACITIES:

    MSC_ReadFormatCapacity();

    break; case SCSI_READ_CAPACITY:

    MSC_ReadCapacity();

    break; case SCSI_READ10:

    if (MSC_RWSetup()) {

    if ((CBW.bmFlags & 0x80) != 0) {

    BulkStage = MSC_BS_DATA_IN;

    MSC_MemoryRead();

    } else {

    USB_SetStallEP(MSC_EP_OUT);

    CSW.bStatus = CSW_PHASE_ERROR;

    MSC_SetCSW();

    }

    }

    break;

    case SCSI_WRITE10:

    if (MSC_RWSetup()) {

    if ((CBW.bmFlags & 0x80) == 0) {

    BulkStage = MSC_BS_DATA_OUT;

    } else {

    USB_SetStallEP(MSC_EP_IN);

    CSW.bStatus = CSW_PHASE_ERROR;

    MSC_SetCSW();

    }

    }

    break;

    case SCSI_VERIFY10:

    if (MSC_RWSetup()) {

    if ((CBW.bmFlags & 0x80) == 0) {

    BulkStage = MSC_BS_DATA_OUT;

    MemOK = TRUE;

    } else {

    CSW.bStatus = CSW_PHASE_ERROR;

    MSC_SetCSW();

    }

    }

    break;

    default:

    goto fail;

    }

    }

    } else {

    /* Invalid CBW */

    USB_SetStallEP(MSC_EP_IN);

    USB_SetStallEP(MSC_EP_OUT);

    BulkStage = MSC_BS_ERROR;

    }

    }

  • Hi Wild,
    Thanks for your reply
    Thanks

  • Are you working on this Keil example?
    "STM32 USB Mass Storage Device Example"
    http://www.keil.com/download/docs/362.asp

    In your code, SCSI_MEDIA_REMOVAL (PREVENT ALLOW MEDIUM REMOVAL) is always accepted, as follows.

    void MSC_GetCBW (void) {
      ...
      case SCSI_MEDIA_REMOVAL:
        CSW.bStatus = CSW_CMD_PASSED;
        MSC_SetCSW();
    //  goto fail;
    

    Does your drive have auto-eject capability?
    If it doesn't, fail this command, as the original code does.
    MSC device doesn't need to accept every SCSI command sent by host.
    It should fail on unsupported SCSI commands.

    Rather, a problem of the original example is,
    it always returns the same SenseData of NO SENSE (Key:0x00), NO ADDITIONAL SENSE INFORMATION (ASC/ASCQ=0x00/0x00). After fail of SCSI command, it should return typical SenseData, such as,

    Sense Key, ASC/ASCQ
    NOT_READY (0x02), MEDIUM_NOT_PRESENT (0x3A/0x00)
    ILLEGAL REQUEST (0x05), INVALID COMMAND OPERATION CODE (0x20/0x00)
    UNIT_ATTENTION (0x06), NOT_READY_TO_READY_CHANGE, MEDIUM_MAY_HAVE_CHANGED (0x28/0x00)
    etc.

    Tsuneo

  • Hi chinzei,
    Thanks for your reply....
    Yes,i am using this stm32usb_mem example.
    I need my drive should have auto eject capability.
    What are the commands and its value need to implement to work this example.
    Thanks a lot.......

  • > I need my drive should have auto eject capability.

    Er.., does your drive have auto eject mechanism, such as CD/DVD tray which ejects a medium automatically?
    Or, do you want, by right-click eject, the drive disappears from "My Computer" window?

    I observed the behavior of a couple of USB sticks on this issue (right-click, eject) on Windows.
    Typical responses are,

    PREVENT ALLOW MEDIUM REMOVAL(PREVENT:01b - prohibit removal): fails
    - ILLEGAL REQUEST, INVALID COMMAND OPERATION CODE

    PREVENT ALLOW MEDIUM REMOVAL(PREVENT:00b - allow removal): success

    START STOP UNIT(IMMED:0, POWER CONDITION:0h(START_VALID), LOEJ:1, START:0) : success

    After START STOP UNIT, the sticks fails all commands, including TEST UNIT READY, with NOT_READY, MEDIUM_NOT_PRESENT sense data.

    None of USB sticks disappear from "My Computer" by right-click eject

    Tsuneo

  • Hi chinzei,

    Thanks for your reply...

    >>Er.., does your drive have auto eject mechanism, such as CD/DVD tray which ejects a medium >>automatically?
    >>Or, do you want, by right-click eject, the drive disappears from "My Computer" window?

    I need device removal by right-click eject, the drive should disappears from "My Computer" window.

    How to implement the following commands in this example?

    PREVENT ALLOW MEDIUM REMOVAL(PREVENT:00b - allow removal): success

    START STOP UNIT(IMMED:0, POWER CONDITION:0h(START_VALID), LOEJ:1, START:0) : success

    After successfull execution of these commands...>>None of USB sticks disappear from "My Computer" by right-click eject

    Did the device remove from My computer?
    Thanks

  • > I need device removal by right-click eject, the drive should disappears from "My Computer" window.

    Umm...
    Though it isn't usual, there is no way other than soft-disconnect of the device.

    USB sticks emulate SD card readers.
    In the view point of USB, USB stick isn't a removable disk, because its medium (memory) isn't removable. But in practice, USB sticks have been implemented as removable. I believe it's because of safety, to cancel write cache. OS writes to removable disks immediately without any write cache. When a disk is accidentally plugged off, write cache increases possibility of file system inconsistency.

    After a removable drive ejects its medium, the drive itself still connects to the host PC. After CD, DVD or SD are ejected, you'll see the drive / card reader remain on "My Computer". Just like these drives, USB sticks also keep its emulated "drive" after eject. Just plug-off makes these "drives" disappear. That is, you have to plug off the stick to make it disappear.

    Firmware emulates plug-off using soft-disconnect.
    Call USB_Connect( FALSE ), after the device finishes SCSI_START_STOP_UNIT command.

    Tsuneo

  • Hi chinzei,
    Thanks for your reply...
    I ejected the media as your suggestion..
    The device is removed from PC and its file contents are not available..but I got an error during ejection...
    "An error was encountered trying to eject Device(G:)"
    I found from the debug message after execution of these commands:SCSI_MEDIA_REMOVAL SCSI_START_STOP_UNIT,OS sends these commands for another time.
    But the media is not available,it think the MEDIA is not responding and produce the error...
    Thanks

  • Hi Chinzei,
    Thank for your discussion...
    Now the device successfully removed from "My Computer"
    Thanks