2016-07-18 02:48 AM
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
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
2016-07-18 03:28 AM
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?
2016-07-18 04:11 AM
Checking this document (
http://www.usb.org/developers/docs/devclass_docs/usbmass-ufipdf
) from usb.org 4.7 READ(10) Command: 28h 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.
2016-07-18 06:12 AM
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.2016-07-18 11:34 PM
You are right, it is block number, is there any fix for this?
2016-07-19 01:54 AM
2016-07-19 02:56 AM
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