Looking for a USB CDC implementation using DMA - Second attempt

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
GuGa_1322886
Level 4
Level 4
5 solutions authored 25 sign-ins First comment on KBA

Hello,

This is my second attempt of the initial post I made here.
I got a quick answer from Ektra and a link for this example that should implement DMA transfers: PSoC™ 6 MCU: USB audio recorder. So, I mark the answer as a solution and proceed to download and work with that code.

What was the problem?
In short, the code in this example is not implemented to use DMA. The code is missing the mandatory DMA initialization functions, and the USB device is managed in manual mode by the CPU. In fact, in Device Configurator you can remove all the DMA settings and change the USB mode to Manual CPU, recompile and run the program. It works as well as before.

Thanks to GOOGLE I located this other example that didn't make it to github CE225786 USB AudioRecorder.
This second example seemed to put me on the right track. The PDF readme reads:

"Design and Implementation
The PDM-to-PCM hardware block can sample one or two PDM digital microphones. In this application, the hardware block is
configured to sample stereo audio at 48 ksps with 16-bit resolution. The sample audio data is eventually transferred to the USB
data endpoint buffer. Figure 2 shows the overall transfers performed by the application.

The first DMA transfer reads from the PDM/PCM RX FIFO and writes to a buffer in the SRAM. This buffer is populated with 16-
bit interleaved data (left and right channels). The second DMA transfer reads from this buffer and writes to the USB Data Endpoint
buffer. The second DMA transfer is handled automatically by the USBFS driver, while the first DMA transfer is part of the
application layer."

But, here too the example falls short. Despite of what the readme file says, only the PDM device transfers are implemented using DMA. The code is missing the DMA initialization calls for the USB device, which is handled in manual CPU mode.

The USB documentation in MTB CAT1 page is sparese and incomplete. With the gazilion registers in the USB side, it's a trial and error to find which registers should be connected to DMA  as destination for IN endpoints or source for OUT endpoints, and what additional actions, if any, must be taken to start transfers, and what are the callbacks to register to get notification of incoming/outgoing data. So far I've not been able to get this configuration tick.

1 Solution
Ekta_N
Moderator
Moderator
Moderator
750 replies posted First like given 250 solutions authored

Hello @GuGa_1322886 

The USB Audio recorder code example does use Automatic DMA mode for data transfer. 

Both the code examples pointed out by you are very similar in the application, the difference being that the first one does not use FREERTOS and the other one uses it.  In both, the code example from the PDM mic is transferred from the SRAM to the USB Endpoint and vice versa using DMA. The code example you have attached is compatible with Modustoolbox 1.0 and has not been updated to make it compatible with the latest version. In fact, we have an updated USB audio recorder code example that uses DMA and FREERTOS both: PSoC 6 MCU: USB Audio Device (FreeRTOS)

If you open the device configurator of the project and check the configuration for USBFS you will notice that it is configured for Automatic DMA, check the code preview for the same and you would notice that the DMA is initialized and is a part of the generated source. If you change the configuration to Manual mode the DMA descriptor vanishes from code preview:

Ekta_0-1658169604827.pngEkta_1-1658169750391.png

 

 In Automatic DMA mode, DMA handles data transfers between the driver SRAM endpoints buffer and the USB block hardware buffer. The USB block generates DMA requests automatically. The USB block generates DMA requests automatically. You can refer to the USBFS PDL documentation https://infineon.github.io/psoc6pdl/pdl_api_reference_manual/html/group__group__usbfs__dev__drv.html

Ekta_2-1658170126679.png

Currently, we do not have this code example for using the CDC Class using the DMA but I have forwarded this request to the code example development team.

Best Regards
Ekta

 

 



View solution in original post

0 Likes
4 Replies
Ekta_N
Moderator
Moderator
Moderator
750 replies posted First like given 250 solutions authored

Hello @GuGa_1322886 

The USB Audio recorder code example does use Automatic DMA mode for data transfer. 

Both the code examples pointed out by you are very similar in the application, the difference being that the first one does not use FREERTOS and the other one uses it.  In both, the code example from the PDM mic is transferred from the SRAM to the USB Endpoint and vice versa using DMA. The code example you have attached is compatible with Modustoolbox 1.0 and has not been updated to make it compatible with the latest version. In fact, we have an updated USB audio recorder code example that uses DMA and FREERTOS both: PSoC 6 MCU: USB Audio Device (FreeRTOS)

If you open the device configurator of the project and check the configuration for USBFS you will notice that it is configured for Automatic DMA, check the code preview for the same and you would notice that the DMA is initialized and is a part of the generated source. If you change the configuration to Manual mode the DMA descriptor vanishes from code preview:

Ekta_0-1658169604827.pngEkta_1-1658169750391.png

 

 In Automatic DMA mode, DMA handles data transfers between the driver SRAM endpoints buffer and the USB block hardware buffer. The USB block generates DMA requests automatically. The USB block generates DMA requests automatically. You can refer to the USBFS PDL documentation https://infineon.github.io/psoc6pdl/pdl_api_reference_manual/html/group__group__usbfs__dev__drv.html

Ekta_2-1658170126679.png

Currently, we do not have this code example for using the CDC Class using the DMA but I have forwarded this request to the code example development team.

Best Regards
Ekta

 

 



0 Likes
GuGa_1322886
Level 4
Level 4
5 solutions authored 25 sign-ins First comment on KBA

Hello Ekta,

Thanks for taking the time to write a detailed answer. I also took the time to go back to the original MTB Audio recorder example and step through it with the debugger. You are correct. I could see that indeed inside the USBFS driver DMA is handled internally.  Let me clarify that I did read several times the documentation that you pointed out, and also the DMA documentation where it says that to enable DMA user code must execute mandatory intialization function calls, like it is shown in the UART with DMA example. That is what I was looking for in the audio example. In the case of USB, obviously the DMA setup is handled behind the scenes by the USBFS driver. There should be a note about this in the sections that you pointed out.

Now if there is any gain in using DMA vs handling the IN EP load manually is another question.  That must be benchmarked.

Best regards,

GuGa

0 Likes
Ekta_N
Moderator
Moderator
Moderator
750 replies posted First like given 250 solutions authored

Hi @GuGa_1322886 

I have taken note of this and will provide feedback to the internal team.

Using DMA vs Handling the IN EP manually generally depends on the application and the type of transfer you are using. When using isochronous transfers (generally used for audio transmission) it is preferred to use DMA, while when using Bulk transfers or for transferring small amounts of non-continuous data it is preferred to manually load the USB endpoint.

Best Regards
Ekta

0 Likes
GuGa_1322886
Level 4
Level 4
5 solutions authored 25 sign-ins First comment on KBA

Hi Ekta,

I think that if someone takes the time to update the application note AN228753  to include the USB case to highlight the work done by the driver behind the scenes on behalf of the user, it will be the best place to have it all together in a single place.

What I'm learning using a SCB UART with DMA is that DMA is idealy suited to send and receive records of fix length. In my case I have to deal with a device that sends records of variable length @ 230400 bauds, some are of a few bytes, and some of more than 1kb, and having one interrupt per byte is very taxing to CPU usage. I need to find the way to offload much of the record receiving to hardware. After the first 8 bytes I know how long the rest of the record will be. At that point I need to set the next descriptor to wait for that many bytes before calling the end of transfer ISR, but at that point it is already too late, the active descriptor is already in use and can not be updated by the user code called from the previous End of Tranfer ISR. The logic to switch descriptors becomes very twisted, and complicated, risking loosing bytes in the process.

The same goes using the UART with interrupts. If I try to update the FIFO Level of the UART before exiting the ISR the UART ignores it. It seems that I need to deinit and reinit the UART for that to take effect, again risking loosing bytes.

Best regards,

GuGa

0 Likes