cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F2/F4 USB-MSC >4gb limitation

pedro23
Senior
Posted on July 18, 2016 at 11:48

Hi.

I have added USB Host support for MSC. It is working ok with USBs under 4gb... but it is not detected properly with USB-sticks over 4gb. I'm using library version 2.2.0, microcontroller are F2/F4 (project is done for 2 different boards). As note i'm using also FatFsR0.11a This is what my debug output echoes...

USB OTG FS MSC Host
> USB Host library started.
USB Host Library v2.2.0
> Device Attached
> Full speed device detected
VID : 0951h
PID : 1607h
> Mass storage device connected
Manufacturer : Kingston
Product : DataTraveler 2.0
Serial Number : 001D0F0C7365A9B0D5360657
> Enumeration completed
Enumeracion hecha
> File System initialized.
> Disk capacity : 3724541440 Bytes

In this case the usb-stick had 8Gb I have spent some time checking different posts i saw some posts with something similar for SD cards but I didnt find anything about USB sticks. Checking the code MSCapacity is set to uint32_t but it is sectors

typedef struct __MassStorageParameter
{
uint32_t MSCapacity;
uint32_t MSSenseKey; 
uint16_t MSPageLength;
uint8_t MSBulkOutEp;
uint8_t MSBulkInEp;
uint8_t MSWriteProtect;
} MassStorageParameter_TypeDef;

Debugging the code here it is assigned but i'm reading the USBH_DataInBuffer

uint8_t USBH_MSC_ReadCapacity10(USB_OTG_CORE_HANDLE *pdev)
{
....
if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_OK)
{
/*assign the capacity*/
(((uint8_t*)&USBH_MSC_Param.MSCapacity )[3]) = USBH_DataInBuffer[0];
(((uint8_t*)&USBH_MSC_Param.MSCapacity )[2]) = USBH_DataInBuffer[1];
(((uint8_t*)&USBH_MSC_Param.MSCapacity )[1]) = USBH_DataInBuffer[2];
(((uint8_t*)&USBH_MSC_Param.MSCapacity )[0]) = USBH_DataInBuffer[3];
/*assign the page length*/
(((uint8_t*)&USBH_MSC_Param.MSPageLength )[1]) = USBH_DataInBuffer[6];
(((uint8_t*)&USBH_MSC_Param.MSPageLength )[0]) = USBH_DataInBuffer[7];
/* Commands successfully sent and Response Received */ 
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
status = USBH_MSC_OK; 
}

this is what i get om USBH_DataInBuffer 0690X000006039yQAA.jpg 15663103 sectors with 512 bytes each =7.46gb, thats right but i see it as 3724 because it is too big for 32bits addressing. Is there a fix for this limitation?, any tip?. would it work if i create a partition under 4gb? We need only 100mb of the usb space, but the problem is that customers can put any kind of usb-stick, it is not easy to find actually usb sticks under 4gb, and force them to create a partition under 4gb when they are normal users is not a nice thing. Thanks in advance
6 REPLIES 6
pedro23
Senior
Posted on July 18, 2016 at 12:28

I have fixed the displaying of drive capacity with

DebugString(''> File System initialized.
'');
Debugprintf(''> Disk : %u sectors
'', USBH_MSC_Param.MSCapacity);
Debugprintf(''> %d sector size
'', USBH_MSC_Param.MSPageLength);
Debugprintf(''> Total: %u Mb 
'', USBH_MSC_Param.MSCapacity/1024*USBH_MSC_Param.MSPageLength);

But it is a detail... really cant work with current 2.2.0 version properly since

status = USBH_MSC_Read10(&USB_OTG_Core, buff,sector,512 * count);

is a 32 bits address for space address greater than 32 bits

/**
* @brief USBH_MSC_Read10 
* Issue the read command to the device. Once the response received, 
* it updates the status to upper layer
* @param dataBuffer : DataBuffer will contain the data to be read
* @param address : Address from which the data will be read
* @param nbOfbytes : NbOfbytes to be read
* @retval Status
*/
uint8_t USBH_MSC_Read10(USB_OTG_CORE_HANDLE *pdev,
uint8_t *dataBuffer,
uint32_t address,
uint32_t nbOfbytes)
{
uint8_t index;
static USBH_MSC_Status_TypeDef status = USBH_MSC_BUSY;
uint16_t nbOfPages;
status = USBH_MSC_BUSY;
if(HCD_IsDeviceConnected(pdev))
{
switch(USBH_MSC_BOTXferParam.CmdStateMachine)
{
case CMD_SEND_STATE:
/*Prepare the CBW and relevant field*/
USBH_MSC_CBWData.field.CBWTransferLength = nbOfbytes;
USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_IN;
USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH;
USBH_MSC_BOTXferParam.pRxTxBuff = dataBuffer;
for(index = CBW_CB_LENGTH - 1; index != 0; index--)
{
USBH_MSC_CBWData.field.CBWCB[index] = 0x00;
}
USBH_MSC_CBWData.field.CBWCB[0] = OPCODE_READ10; 
/*logical block address*/
USBH_MSC_CBWData.field.CBWCB[2] = (((uint8_t*)&address)[3]);
USBH_MSC_CBWData.field.CBWCB[3] = (((uint8_t*)&address)[2]);
USBH_MSC_CBWData.field.CBWCB[4] = (((uint8_t*)&address)[1]);
USBH_MSC_CBWData.field.CBWCB[5] = (((uint8_t*)&address)[0]);
/*USBH_MSC_PAGE_LENGTH = 512*/
nbOfPages = nbOfbytes/ USBH_MSC_PAGE_LENGTH; 
/*Transfer length */
USBH_MSC_CBWData.field.CBWCB[7] = (((uint8_t *)&nbOfPages)[1]) ; 
USBH_MSC_CBWData.field.CBWCB[8] = (((uint8_t *)&nbOfPages)[0]) ; 
USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SEND_CBW;
/* Start the transfer, then let the state machine 
manage the other transactions */
USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_USB_TRANSFERS;
USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_BUSY;
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_WAIT_STATUS;
status = USBH_MSC_BUSY;
break;
case CMD_WAIT_STATUS:
if((USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_OK) && \
(HCD_IsDeviceConnected(pdev)))
{ 
/* Commands successfully sent and Response Received */ 
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
status = USBH_MSC_OK; 
}
else if (( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_FAIL ) && \
(HCD_IsDeviceConnected(pdev)))
{
/* Failure Mode */
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
}
else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_PHASE_ERROR )
{
/* Failure Mode */
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
status = USBH_MSC_PHASE_ERROR; 
}
else
{
/* Wait for the Commands to get Completed */
/* NO Change in state Machine */
}
break;
default:
break;
}
}
return status;
}

Same with write:

/**
* @brief USBH_MSC_Write10 
* Issue the write command to the device. Once the response received, 
* it updates the status to upper layer
* @param dataBuffer : DataBuffer contains the data to write
* @param address : Address to which the data will be written
* @param nbOfbytes : NbOfbytes to be written
* @retval Status
*/
uint8_t USBH_MSC_Write10(USB_OTG_CORE_HANDLE *pdev, 
uint8_t *dataBuffer,
uint32_t address,
uint32_t nbOfbytes)
{
uint8_t index;
USBH_MSC_Status_TypeDef status = USBH_MSC_BUSY;
uint16_t nbOfPages;
if(HCD_IsDeviceConnected(pdev))
{ 
switch(USBH_MSC_BOTXferParam.CmdStateMachine)
{
case CMD_SEND_STATE: 
USBH_MSC_CBWData.field.CBWTransferLength = nbOfbytes;
USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_OUT;
USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH;
USBH_MSC_BOTXferParam.pRxTxBuff = dataBuffer;
for(index = CBW_CB_LENGTH - 1; index != 0; index--) 
{
USBH_MSC_CBWData.field.CBWCB[index] = 0x00;
}
USBH_MSC_CBWData.field.CBWCB[0] = OPCODE_WRITE10; 
/*logical block address*/
USBH_MSC_CBWData.field.CBWCB[2] = (((uint8_t*)&address)[3]) ;
USBH_MSC_CBWData.field.CBWCB[3] = (((uint8_t*)&address)[2]);
USBH_MSC_CBWData.field.CBWCB[4] = (((uint8_t*)&address)[1]);
USBH_MSC_CBWData.field.CBWCB[5] = (((uint8_t*)&address)[0]);
/*USBH_MSC_PAGE_LENGTH = 512*/
nbOfPages = nbOfbytes/ USBH_MSC_PAGE_LENGTH; 
/*Transfer length */
USBH_MSC_CBWData.field.CBWCB[7] = (((uint8_t *)&nbOfPages)[1]) ; 
USBH_MSC_CBWData.field.CBWCB[8] = (((uint8_t *)&nbOfPages)[0]) ; 
USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SEND_CBW;
/* Start the transfer, then let the state machine 
manage the other transactions */
USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_USB_TRANSFERS;
USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_BUSY;
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_WAIT_STATUS;
status = USBH_MSC_BUSY;
break;
case CMD_WAIT_STATUS:
if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_OK)
{ 
/* Commands successfully sent and Response Received */ 
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
status = USBH_MSC_OK; 
}
else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_FAIL )
{
/* Failure Mode */
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
}
else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_PHASE_ERROR )
{
/* Failure Mode */
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
status = USBH_MSC_PHASE_ERROR; 
}
break;
default:
break;
}
}
return status;
}

Do you have any fix for this?

pedro23
Senior
Posted on July 18, 2016 at 13:11

Checking this document (

http://www.usb.org/developers/docs/devclass_docs/usbmass-ufipdf

) from usb.org 4.7 READ(10) Command: 28h 0690X00000603A3QAI.jpg it is a 32 bits pointer... , limitation is in read10 command

/*logical block address*/
USBH_MSC_CBWData.field.CBWCB[2] = (((uint8_t*)&address)[3]);
USBH_MSC_CBWData.field.CBWCB[3] = (((uint8_t*)&address)[2]);
USBH_MSC_CBWData.field.CBWCB[4] = (((uint8_t*)&address)[1]);
USBH_MSC_CBWData.field.CBWCB[5] = (((uint8_t*)&address)[0]);

is there any implementation official or not of Write12/Read12 already? Thanks in advance.
Posted on July 18, 2016 at 15:12

READ(10)/WRITE(10) have a 32-bit *BLOCK* address, this equates to 2TB

The problem in most ST code is the use of 32-bit *BYTE* addressing, and the unnecessary conversion back-and-forth between BYTE and BLOCK numbers related to BLOCK storage media.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
pedro23
Senior
Posted on July 19, 2016 at 08:34

You are right, it is block number, is there any fix for this?

pedro23
Senior
Posted on July 19, 2016 at 10:54

Clive1 searching in the forums i have found

https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/DispForm.aspx?ID=23078&RootFolder=/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Where%20is%20the%20UsbMassStorage%20Examples%20%20Supt%20for%20stm32f4xx&Source=https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32...

and it is clearly an epic fail as you said.

The bug was in for usbd_msc_scsi.c mainly.

I'm using usbh_msc_scsi.c since i'm connecting an acting as a HOST. Checking the code i dont know if that bug is in this code too. I have been checking the code and it seems ok.

I'm using a 8gb usb-stick without any problem, but it is empty, not sure if it more than 4 being used :). Any tip or experience?

Thanks in advance.

pedro23
Senior
Posted on July 19, 2016 at 11:56

I have done tests with 32gb usb with 9gb used already. All worked ok. USCH_MSC library works ok then only problem detected was determine the size in bytes exposed in the second post.

Best regards