2024-12-30 11:00 PM - edited 2024-12-30 11:06 PM
Following on from this question USB FS speed vs USB HS with internal FS Phy with DMA it seems that USB HS has access to DMA but there is no information on how this is configured. I do not see any additional DMA options appear in Cube IDE when I have enabled the above options.
Note I have enabled the option: Enable internal IP DMA
I would like to setup the following pipeline:
I cannot see how to configure the number 2: the Memory to USB DMA transfer
Is this configurable in CubeIDE or perhaps only in software? Given the crucial role this plays in the board's operation, I want to confirm its feasibility before proceeding. If not, I would change to a STM32 that would allow this scheme.
Regards,
2024-12-31 12:37 AM
The OTG_HS module's DMA is internal to that module, i.e. it is not related to the general-purpose DMA modules.
That's why OTG_HS is a busmaster on the bus matrix.
The OTG_HS's DMA has no option to avoid increment of address, so you can't fetch data from a single address. Also there's no provision to trigger it from external trigger source like some peripheral's (such as I2S) signal.
In other words, you cannot achieve complete automatism as you've outlined. You need to use the general-purpose DMA to transfer data to RAM, and then use the OTG_HS's DMA to transfer that through USB with periodic software intervention restarting that DMA.
JW
2024-12-31 11:53 AM
USB has its own DMA (inside the USB block). This USB DMA cannot be used for any other peripheral.
Bring the USB stack alive, with DMA. So, you can now send and receive data via USB. But if you want to send data from peripherals (e.g. I2S3 or SPI3) - they might need their own DMA. So, these peripherals put/get data to/from DMA buffer and USB DMA uses another DMA buffer.
The FW needs now a "trigger", e.g. Callback, that USB has transferred into USB DMA buffer. Now you have to copy the data fo/from USB buffer to peripheral buffers. Or: you map the USB DMA buffer to the peripheral buffers (with a smart buffer management in SW).
USB with DMA is like an engine running in background, transferring data to/from a USB buffer. You have to move the data from other buffers into/from their location into the USB buffers. The trigger is SW code, e.g. checking in which USB Callback you are (in order to know which next half-buffer to fill with data for USB).
2025-01-01 07:53 AM
Thanks @waclawek.jan and @tjaekel for the helpful comments. Yes, the bus matrix really helps understand these capabilities—thanks for pointing that out—I am learning!
So it seems this is well within the capabilities of the MCU using double buffering and half-complete callback to trigger to USB OTG HS DMA. Maybe something like this?
Create three buffers:
When the buffer is half full, use a callback to trigger the USB OTG HS DMA
When the buffer is full, use a callback to trigger the USB OTG HS DMA to read from the buffer at an offset:
I will use circular buffers and let this run until I have collected enough samples.
Do you see any potential issues or pitfalls with the approach? As long as all the incoming data is received and sent out without any missed bytes, this should work.
Regards,
2025-01-01 12:08 PM
Yes, you are on the right track.
With circular buffers, used for DMAs to/from peripherals and also used in USB stack/driver - you should have two callbacks: one for half, one for complete. You can also consider it as "triggers called" for the first and the second half of the double buffer.
You would fill the new data for next USB transfer into the "other" buffer, e.g. complete is triggered on USB Tx, now it is free: USB will send out next the first half but the second half is free now. Fill in new data into the free buffer.
Do not write data into the half buffer which is used next (by USB DMA), you would overwrite buffer when it is in progress to be sent out.
Yes, you have to consider the buffer size (how much new data to collect). USB uses a fix sized buffer which depends on the USB protocol you use. For instance: USB VCP might have a buffer size of N times 64bytes, USB Audio should have a buffer size of N times the audio format (e.g. 48 x 2 x 2 = 192 bytes, for 48 KHz (every 1 ms), 2 channels and 2 bytes (16bit) per audio PCM word).
I mean: the USB will have a fix and protocol dependent buffer size. You have to "wait" for such much data that the entire USB half buffer can be filled. But depending on the USB protocol you use, e.g. USB Audio, there is also a timing relation, e.g. every 1 ms you have to fill such a complete USB half buffer.
Which USB protocol do you want to use?
USB VCP (UART) is a bit easier, USB Audio (as ISOchronous transfer, every 1 ms an USB packet) a bit trickier.