1
\$\begingroup\$

I-m trying to accomplish best USB speed through STM32H743 MCU to PC. First of all I was testing just receiving data. I was sending sending 8192 bytes from MCU to the pc without any other tasks, and the speed is 60 megabytes per minute - which is fine for me. I was doing it like this:

 while(1) { CDC_send_alot((uint8_t*)&nandtest[0],8192); } USBD_StatusTypeDef CDC_send_alot(const void *buf, uint16_t len) { USBD_StatusTypeDef result; while (1) { result = CDC_Transmit_FS((void*)buf, len); if (result != USBD_BUSY) // this should break if USB reset or disconnect occurred break; } if (result == USBD_OK && (len % 64 == 0)) { // Send ZLP while(1) { result = CDC_Transmit_FS(0, 0); if (result != USBD_BUSY) break; } } return result; } 

nandtest here just an empty buffer. CDC_send_alot is a sub I'm using for send big packets also for control ZLP.

But the problem comes when I read SDHC card with sdio protocol and send the data to PC. I'm getting huge delays between packages. Screenshot of reading SDHC card

So the speed drops from 60 megabytes/minute to 15 megabyets/minute. The question is how can avoid this delays between READ SDHC CARD DATA -> send to PC?

I-m using standard HAL library generated by CubeMX2. Is it possible to read and send synchronously?

\$\endgroup\$
3
  • 2
    \$\begingroup\$ You can implement DMA (Direct Memory Access) for SDIO transfers. This allows data to be transferred between the SDIO peripheral and memory without CPU intervention, reducing the delay between read operations. The HAL library provides functions for setting up and using DMA with SDIO. \$\endgroup\$ Commented Nov 17, 2023 at 15:34
  • \$\begingroup\$ @liaifat85 thanks for your answer, unfortuntly im using software SDIO not hardware one. And i cant use hardware because of some limitation \$\endgroup\$ Commented Nov 17, 2023 at 17:43
  • \$\begingroup\$ @liaifat85 also if im using gpio pins to read SDIO, can use DMA on gpio pins??? \$\endgroup\$ Commented Nov 17, 2023 at 17:50

2 Answers 2

1
\$\begingroup\$

My suggestion to speed up the transfers is using FreeRTOS (which is very easy to add in CubeMX) and creating two tasks: One to read from the SD card and the other to transfer data over USB and retry the transfer in case the USB stack is busy. The tasks should be easy to synchronize via a Stream Buffer, which is a FreeRTOS module. It will allow you to continue reading from the SD card until the buffer is full and resume reading once the buffer has been freed up by the USB task. The USB task will also get automatically blocked by the stream buffer "read" function until the SD card reading task has placed something into the buffer.

\$\endgroup\$
4
  • \$\begingroup\$ Michael thanks for your answer, is i add freeRTOS ,will i have to rewrite the whole project? \$\endgroup\$ Commented Nov 20, 2023 at 19:24
  • \$\begingroup\$ @KlimDuda I hope not! But it will need to be restructured. For example, you will need to move some parts of your code to task functions rather than the loop in main(). I can't think of any parts that will need to be deleted. \$\endgroup\$ Commented Nov 21, 2023 at 1:07
  • \$\begingroup\$ Michael please tell me i cant find any info of using USB OTG with freertos is it possible or not? if i simpy put CDC_Transmit_FS into freertos task, will it work? \$\endgroup\$ Commented Nov 22, 2023 at 20:23
  • \$\begingroup\$ @KlimDuda, yes, it should work. Make sure to check the return value of the call though and try to call it again if the return value indicates that the USB bus was busy when you tried to send data. \$\endgroup\$ Commented Nov 29, 2023 at 19:18
3
\$\begingroup\$

I cant use hardware because of some limitation

You can't have your cake and eat it too. The software only reads the card at the lower speed. Nothing to do with USB. Maybe use a better MCU if the one you have can't read the cards at the speed you want? And what is the limitation you speak of? If it's a layout "bug", then sorry but you'll have to fix the layout to make hardware SDIO functional. Otherwise you won't get the speeds you expect. As simple as that. Don't involve USB in it. First get the reading from the card fast enough and using few CPU cycles. Only then add USB into the mix.

Is it possible to read and send synchronously?

That's absolutely not what you want. You want a DMA SDIO read, then interrupt on completion, and that interrupt can trigger the USB transaction. The USB controller will read the buffer that the DMA wrote to, if you set things up right. So the interrupt has very little to do before the USB controller has a transaction ready.

Or the interrupt can wake up a high-priority thread that issues the USB transaction. If there is no multithreading, then the main thread should halt waiting for interrupts, and the interrupts can do all the work.

But, the idea is that as soon as the USB request is submitted, the SDIO should immediately be configured for another read, with DMA pointing to another USB buffer. You'll want several buffers and flip between them. Two is not enough, since SDHC cards sometimes have latencies that much exceed the duration of two back-to-back USBHS transfers. And as soon as there's no data ready for a transaction, you'll have to wait until the next frame (or microframe - I don't recall at the moment).

So, stalling the USB transfers penalizes transfer rate. That's why you'd want to have say 4 or 8 buffers completely filled from SDIO before the first bulk read transfer begins on the bus. And any time there's an underrun, you should again wait for all buffers to be filled before resuming the USB transaction. This can be adjusted dynamically of course. When there's no more data to read in a request, not all buffers may be full, so that needs to be accommodated.

\$\endgroup\$
1
  • \$\begingroup\$ thanks for your answer but i cant use hardwaare sdio because of ports its using, its already occupied by another interfeces in our project. Also my software speed of reading sdio is good enough ts around 200 nano seconds per clock, my mcu's mhz is 480mhz, which is good as well. Is it any another way to solve the problem? \$\endgroup\$ Commented Nov 20, 2023 at 19:23

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.