cancel
Showing results for 
Search instead for 
Did you mean: 

USB Mass storage - using ST Mass_Storage example code

infoinfo988
Associate II
Posted on August 15, 2011 at 13:32

Hi,

I'm trying to implement USB mass storage and mass storage bootloader on STM32F103RBT but ...

I have a problem with the adapted the code from STM32_USB-FS-Device_Lib_V3.3.0 Mass_Storage example.

The ISTR_RESET interrupt is received (MASS_Reset() gets called) when I connect the USB cable to a host PC but no other USB interrupts take place.

I think that the code is correctly implemented:

- Peripiheral clock is enabled and Interrupts are enabled

- USB clock initialised to 1.5 of system clock of 72Mhz (checked that sys clock is 72Mhz)

The startup code calls the following routines:

  MAL_Config();

  Set_USBClock();  //USB clock setup

  USB_Interrupts_Config();  /NVIC setup

  USB_Init();

Has anyone implemented USB mass storage successfully? What interrupts would you expect to receive after ISTR_RESET?

Thanks.

7 REPLIES 7
infoinfo988
Associate II
Posted on August 16, 2011 at 00:19

Problem: Receiving only USB_ISTR Reset message and no other USB interrupts

Resolution: Add a 1.5K pull-up to D+

infoinfo988
Associate II
Posted on August 16, 2011 at 14:33

The original post was too long to process during our migration. Please click on the provided URL to read the original post. https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I6aK&d=%2Fa%2F0X0000000brD%2FNiLeBjBU5zqHLp1EMy_7ueoM2cHaK22aH9CmceZO25w&asPdf=false
tsuneo
Senior
Posted on August 16, 2011 at 16:24

Maybe, your debug output disturbs the firmware from responding to the host in time. Switch off all the debug output, temporarily.

Host expects that the device responds to control transfers in time. The minimum timeout is 50 ms. If your debug output delays the device response, it causes timeout on the host side.

As you are starting from ST example, the USB stack should work 🙂

For MSC-BOT (Mass-Storage Class, Bulk-Only Transport), the timeout of bulk IN/OUT endpoints is much longer (around 5 sec) than Control transfer. You may add the debug output to the bulk IN/OUT process, but not for the control transfer process.

Tsuneo

infoinfo988
Associate II
Posted on August 16, 2011 at 20:52

Thanks Tsuneo, that's a great tip!

Usually I try to understand the inside workings before trying out something more complex (as it normally just doesn't work out of the box). But in this case it did work altogether!

I've turned off the tracing in usb_core.c, usb_isr.c and usb_int.c but left the tracing in mass_mal.c. This was fixed the time outs and it seems that the correct calls are now made to the Mass_Storage functions.

It's interesting to see that the example STM code is not handling CNTR_SOFM and CNTR_ESOFM but only CNTR_CTRM  and CNTR_RESETM.

The plan now is to hopefully expose the on-board flash and other features of the system via the file system calls.

Here is the trace that's now generated at the mass_mal level (note that the calls to the actual read/write routines are not yet implemented):

Initialising USB

--> MAL_Init()

<-- MAL_Init()

--> MASS_init()

<-- MASS_init() - UNCONNECTED

##########################################

<-- MASS_Reset() - ATTACHED

#######--> MASS_Reset()

<-- MASS_Reset() - ATTACHED

######--> Mass_Storage_SetDeviceAddress() - Addressed

<-- Mass_Storage_SetDeviceAddress()

--> MASS_Data_Setup()

--> MASS_Data_Setup()

--> MASS_Data_Setup()

--> Mass_Storage_SetConfiguration() - CONFIGURED

<-- Mass_Storage_SetConfiguration() - ###########

<-- MASS_Data_Setup()

<-- Get_Max_Lun() 0

#--> MAL_GetStatus()

###--> MAL_GetStatus()

--> Mass_Storage_ClearFeature()

<-- Mass_Storage_ClearFeature()

#--> MAL_GetStatus()

--> MAL_GetStatus()

--> MAL_GetStatus()

#--> Mass_Storage_ClearFeature()

<-- Mass_Storage_ClearFeature()

--> Mass_Storage_ClearFeature()

<-- Mass_Storage_ClearFeature()

--> Mass_Storage_ClearFeature()

###############################

--> MAL_GetStatus()

#--> Mass_Storage_ClearFeature()

<-- Mass_Storage_ClearFeature()

--> Mass_Storage_ClearFeature()

<-- Mass_Storage_ClearFeature()

--> Mass_Storage_ClearFeature()

...

...

***** Lots more calls to Mass_Storage_ClearFeature()

...

...

<-- Mass_Storage_ClearFeature()

--> Mass_Storage_ClearFeature()

<-- Mass_Storage_ClearFeature()

--> Mass_Storage_ClearFeature()

<-- Mass_Storage_ClearFeature()

--> Mass_Storage_ClearFeature()

<-- Mass_Storage_ClearFeature()

##########################

--> MAL_GetStatus()

##################################

##################################

##################################

##################################

##################################

***** MAL_GetStatus() then gets called every few seconds

tsuneo
Senior
Posted on August 16, 2011 at 23:03

Your trace shows that the bulk OUT (and IN?) endpoint (EP) doesn't respond to host. And then, the host tries to reset the bulk pipe using Clear_Feature(ENDPOINT_HALT) request - ie. Mass_Storage_ClearFeature() is called on the device side, repeatedly.

Did you change the bulk EP address?

The address of the bulk IN/OUT endpoints are specified by the endpoint descriptors.

STM32_USB-FS-Device_Lib_V3.3.0\Project\Mass_Storage\src\usb_desc.c

const uint8_t MASS_ConfigDescriptor[MASS_SIZ_CONFIG_DESC] =

  {

    ...

    /* 18 */

    0x07,   /*Endpoint descriptor length = 7*/

    0x05,   /*Endpoint descriptor type */

    0x81,   /*Endpoint address (IN, address 1) */   <------------

    0x02,   /*Bulk endpoint type */

    0x40,   /*Maximum packet size (64 bytes) */

    0x00,

    0x00,   /*Polling interval in milliseconds */

    /* 25 */

    0x07,   /*Endpoint descriptor length = 7 */

    0x05,   /*Endpoint descriptor type */

    0x02,   /*Endpoint address (OUT, address 2) */   <------------

    0x02,   /*Bulk endpoint type */

    0x40,   /*Maximum packet size (64 bytes) */

    0x00,

    0x00     /*Polling interval in milliseconds*/

These bulk endpoints are enabled at MASS_Reset(). The EP addresses, ENDP1_TXADDR and ENDP2_RXADDR, are registered to the EPs, here.

STM32_USB-FS-Device_Lib_V3.3.0\Project\Mass_Storage\src\usb_prop.c

void MASS_Reset()

{

  ... 

#else

  ...

  /* Initialize Endpoint 1 */

  SetEPType(ENDP1, EP_BULK);

  SetEPTxAddr(ENDP1, ENDP1_TXADDR);   <------------

  SetEPTxStatus(ENDP1, EP_TX_NAK);

  SetEPRxStatus(ENDP1, EP_RX_DIS);

  /* Initialize Endpoint 2 */

  SetEPType(ENDP2, EP_BULK);

  SetEPRxAddr(ENDP2, ENDP2_RXADDR);    <------------

  SetEPRxCount(ENDP2, Device_Property.MaxPacketSize);

  SetEPRxStatus(ENDP2, EP_RX_VALID);

  SetEPTxStatus(ENDP2, EP_TX_DIS);

Tsuneo

infoinfo988
Associate II
Posted on August 17, 2011 at 13:12

Again spot on, Tsuneo!

This time it seems to be an error in the ST example code and the usb_conf.h file.

The addresses in the original usb_conf.h file are defined as:

#define ENDP1_TXADDR        (0x98)

#define ENDP2_RXADDR        (0xD8)

But the config descriptor in usb_desc.c contains the following (as expected):

 /* 18 */

    0x07,   /*Endpoint descriptor length = 7*/

    0x05,   /*Endpoint descriptor type */

    0x81,   /*Endpoint address (IN, address 1) */

    0x02,   /*Bulk endpoint type */

    0x40,   /*Maximum packet size (64 bytes) */

    0x00,

    0x00,   /*Polling interval in milliseconds */

    /* 25 */

    0x07,   /*Endpoint descriptor length = 7 */

    0x05,   /*Endpoint descriptor type */

    0x02,   /*Endpoint address (OUT, address 2) */

    0x02,   /*Bulk endpoint type */

    0x40,   /*Maximum packet size (64 bytes) */

    0x00,

    0x00     /*Polling interval in milliseconds*/

    /*32*/

I assume the fix is to change the usb_conf.h to define:

#define ENDP1_TXADDR        (0x01)

#define ENDP2_RXADDR        (0x02)

This leads to a question whether the Mass storage example in STM32_USB-FS-Device_Lib_V3.3.0 can run successfully and what other gotchas we'll find next? 🙂

infoinfo988
Associate II
Posted on August 17, 2011 at 23:39

Made some progress but have hit the next hurdle.....

I've found that there is another likely mistake in the STM32_USB-FS-Device_Lib_V3.3.0 base code that causes the f/w to crash.

In usb_sil.c there are calls to:

UserToPMABufferCopy(pBufferPointer, GetEPTxAddr(bEpAddr & 0x7F), wBufferSize);

and

PMAToUserBufferCopy(pBufferPointer, GetEPRxAddr(bEpAddr & 0x7F), DataLength);

The source address is calculated by calling GetEPTxAddr() and GetEPRxAddr(). These functions internally add PMAAddr  (0x40006000L) to the address.

However the implementation of PMAToUserBufferCopy() and UserToPMABufferCopy() in usb_mem.c also adds PMAAddr  (0x40006000L) to the address causing an overflow of the variable, then the subsequent read operation crashes.

The correct calls I assume in usb_sil.c should be:

UserToPMABufferCopy(pBufferPointer, _GetBTABLE()+bEpAddr*8, wBufferSize);

and

PMAToUserBufferCopy(pBufferPointer, _GetBTABLE()+bEpAddr*8+4, DataLength);

Could someone from ST or someone familiar with the USB code have a look at this please?

Based on the findings it seems to me that the USB Mass storage example code can't run properly without modifications.

Thanks