cancel
Showing results for 
Search instead for 
Did you mean: 

Problem with STM32F401 OTG FS MSC using SDIO uSD card

davidharrison69
Associate II
Posted on May 26, 2015 at 21:23

Hi, all. I have an STM32F401Discovery Kit using an STM32F401VCT6.

I have wired an external SD card connector and have successfully implemented Elm-Chan's FATFs using the SDIO SD card interface. All works well, I can mount the card, and read files.

I have also successfully implemented a generic two way USB OTG_FS HID with IN and OUT Endpoints to transfer raw data buffers of 64 bytes both ways. So far so good.

The problem comes when I try the MSC class (taken from ST's MSC class library).

When the SCSI STORAGE_Read function calls SDReadMultiBlocks followed by SDWaitReadOperation(), SDWaitReadOperation() never returns - it blocks.

After putting in many printf statements it turns out that the SDIO DMA2_Stream3_IRQHandler is never fired, thus the DMAEndOfTransfer flasg is not set which is why SDWaitReadOperation() blocks. I am using Clive's SDReadMultiBlocksFIXED function to properly handle LBA addresses.

So my question is - why does the SDIO DMA read operation work by itself when called from FATFs, but not when called from the USB MSC Class?

I have read elsewhere in this forum

(

/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Inprove%20the%20speed%20of%20the%20Mass%20storage%20%20as%20u%20disk&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=2050

)

that someone used double buffering when using SDIO concurrently with USB.

Is that the solution to my problem?

null
5 REPLIES 5
Posted on May 26, 2015 at 22:57

That the NVIC side hasn't been enabled?

Not sure I've got the DMA interrupt enabled on the example I have working on the 401C. Attached is what I have working from a quick mash of the FATFS and MSC examples. This uses a STM32F4-DIS-BB board, but I've electively removed the Card Detect code as I don't know what you have wired. This seemed to function Ok on a 16GB MicroSD card posting 600-700 KBps numbers.

The DMA interrupt is somewhat problematic, at least on the write side, because it fires long before the data has actually traverses the SDIO bus. I also seem to recall race conditions if you heavily instrument the code, and the DMA transfer is basically configured as a length-less transfer on the SDIO. See SD_LowLevel_DMA_RxConfig() as it throws away the length.

Might walk over the code tomorrow as it looks to be something I haven't touched in two years.

________________

Attachments :

usbdemo_401c_disco_rev1_bb.hex : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I0RC&d=%2Fa%2F0X0000000bhf%2FFQERuJOrY4aj011XOINucW8QFqvb.LQcdAY.N_kRmOw&asPdf=false
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
davidharrison69
Associate II
Posted on May 27, 2015 at 16:37

Clive, thanks for the example hex code usbdemo_401c_disco_rev1_bb.hex.

When programmed with that hex file my STM32F401 Discovery board does act as an USB MSC class and I can see the disk drive and its contents in Windows.

Yes the NVIC side is enabled and my DMA enabled

SDReadMultiBlocksFIXED

function works fine from FATFS, just not from the USB MSC class.

The printf instrumentation is output through a high speed 460800 baudUSART1 on PORT.

Could you please make available the source code for your

usbdemo_401c_disco_rev1_bb.hex

file please. I'd really appreciate it.

Thanks, David.

That the NVIC side hasn't been enabled?

Not sure I've got the DMA interrupt enabled on the example I have working on the 401C. Attached is what I have working from a quick mash of the FATFS and MSC examples. This uses a STM32F4-DIS-BB board, but I've electively removed the Card Detect code as I don't know what you have wired. This seemed to function Ok on a 16GB MicroSD card posting 600-700 KBps numbers.

The DMA interrupt is somewhat problematic, at least on the write side, because it fires long before the data has actually traverses the SDIO bus. I also seem to recall race conditions if you heavily instrument the code, and the DMA transfer is basically configured as a length-less transfer on the SDIO. See SD_LowLevel_DMA_RxConfig() as it throws away the length.

Might walk over the code tomorrow as it looks to be something I haven't touched in two years.

Hi, all. I have an STM32F401Discovery Kit using an STM32F401VCT6.

I have wired an external SD card connector and have successfully implemented Elm-Chan's FATFs using the SDIO SD card interface. All works well, I can mount the card, and read files.

I have also successfully implemented a generic two way USB OTG_FS HID with IN and OUT Endpoints to transfer raw data buffers of 64 bytes both ways. So far so good.

The problem comes when I try the MSC class (taken from ST's MSC class library).

When the SCSI STORAGE_Read function calls SDReadMultiBlocks followed by SDWaitReadOperation(), SDWaitReadOperation() never returns - it blocks.

After putting in many printf statements it turns out that the SDIO DMA2_Stream3_IRQHandler is never fired, thus the DMAEndOfTransfer flasg is not set which is why SDWaitReadOperation() blocks. I am using Clive's SDReadMultiBlocksFIXED function to properly handle LBA addresses.

So my question is - why does the SDIO DMA read operation work by itself when called from FATFs, but not when called from the USB MSC Class?

I have read elsewhere in this forum

(

https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https%3a//my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Inprove%20the%20speed%20of%20the%20Mass%20storage%20%20as%20u%20disk&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A...

)

that someone used double buffering when using SDIO concurrently with USB.

Is that the solution to my problem?

Posted on May 27, 2015 at 20:51

Could you please make available the source code for your

usbdemo_401c_disco_rev1_bb.hex

file please. I'd really appreciate it.

https://drive.google.com/file/d/0B7OY5pub_GfIc2F1MTd6RDBVemM/view?usp=sharing

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
davidharrison69
Associate II
Posted on May 27, 2015 at 21:48

Clive, thanks for that. However, just a short while ago I was able to get my own build working as USB MSC. The changes I made were to make the Rx DMA buffer size 0 (I don't why we have to do that - could you explain that please?

Also I changed the DMA2_Stream3_IRQn NVIC_IRQChannelPreemptionPriority from 0 to 1. Both the SDIO_IRQn and the DMA2_Stream3_IRQn priorities had been set to 0.

I also removed most of the uartprintf instrumentation.

I now have the challenge of combining my previous HID code with the working MSC code to make a USB HID/MSC composite device. I have done this successfully before on the STM32F3 and Microchip PIC32 platforms so It shouldn't be too hard. Of course the STM32F4 USB code is completely different from the STM32F3 USB code so I can't just copy it.

However, I am well read on USB (2.0) so I am up to the challenge. I'll report my results.

Could you please make available the source code for your usbdemo_401c_disco_rev1_bb.hex file please. I'd really appreciate it.

https://drive.google.com/file/d/0B7OY5pub_GfIc2F1MTd6RDBVemM/view?usp=sharing

Hamid.Wasti
Associate III
Posted on May 28, 2015 at 10:55

> The DMA interrupt is somewhat problematic, at least on the write side, because it fires long before the data has actually traverses the SDIO bus.

 

In a totally different application where I faced this problem, I dealt with it by having the DMA interrupt start a one-shot timer. Everything I needed to do in the ''SPI transfer complete'' interrupt, I did in the timer's interrupt.

This is a nice trick that can come in handy in some instances. In that case, the SPI was running at a glacial 32KHz, so waiting for 16 bit times took about 500 microseconds. The additional cost for setting up the timer and processing another interrupt were trivial. It will be a different story if the SPI port is running at 18MHz.