Virtual COM for cyfx3s_fatfs example as an alternative to UART module

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

cross mob
lock attach
Attachments are accessible only for community members.
Corrado90
Level 1
Level 1
5 sign-ins First reply posted First question asked

Dear community,

I have to implement a virtual COM with the FX3 as an alternative to the UART module for the cyfx3s_fatfs example; so I need a set of API similar to CyU3PUartReceiveBytes and CyU3PUartTransmitBytes and the possibility to write buffer with DMA (as in cyfx3s_fatfs) but working through an USB Virtual COM.
I started working with UsbUart example by modifing the DMA configuration and sockets (in attached) to use the "void CyFxUartSendBuffer(uint8_t *Buffer_Print,uint8_t cnt_read)" function, but without results.
Please, someone could give me some ideas or code example?
Consider that is my first time with this MCU, this architecture and in general with the USB.

Many thanks in advance, regards,
Corrado90

0 Likes
1 Solution
Hemanth
Moderator
Moderator
Moderator
First like given First question asked 750 replies posted

Hi Corrado90,

In the attached firmware, you can comment the following section as you are not using UART block:

if (glIsApplnActive)
        {
            /* While the application is active, check for data sent during the last 50 ms. If no data
               has been sent to the host, use the channel wrap-up feature to send any partial buffer to
               the USB host.
            */
            if (glPktsPending == 0)
            {
                /* Disable UART Receiver Block */
                UART->lpp_uart_config = regValueDs;

                CyU3PDmaChannelSetWrapUp (&glChHandleUarttoUsb);

                /* Enable UART Receiver Block */
                UART->lpp_uart_config = regValueEn;
            }

            glPktsPending = 0;
        }

In CyFxUartSendBuffer(), you cannot use APIs CyU3PDmaChannelSetupSendBuffer() and CyU3PDmaChannelWaitForCompletion() - as they are for DMA override mode. Please refer https://community.cypress.com/t5/Knowledge-Base-Articles/DMA-Channel-in-Override-Mode-in-FX3-CX3-KBA...

Instead you can use CyU3PDmaChannelCommitBuffer() when you get DMA callback. When you are not using override mode, for MANUAL_IN channel you get PROD event when a DMA buffer is available from producer and for MANUAL_OUT you get CONS event when a buffer is consumed by consumer. For these events to be available you can refer to UsbBulkSrcSink example of FX3 SDK (You can only refer to DMA channel creation part and callback function part of the firmware). In your firmware you will have to take care of dmaCfg.notification and dmaCfg.cb accordingly.

For your use case, Override mode is not suitable for USB to CPU channel. For CPU to USB channel you can either go with override mode(as in the case of cyfx3s_fatfs example) or normal mode (as in UsbBulkSrcSink example).

Path for UsbBulkSrcSink: {FX3_SDK_Installation_Path}\1.3\firmware\basic_examples\cyfxbulksrcsink

Regards,

Hemanth

View solution in original post

0 Likes
3 Replies
Hemanth
Moderator
Moderator
Moderator
First like given First question asked 750 replies posted

Hi Corrado90,

In the attached firmware, you can comment the following section as you are not using UART block:

if (glIsApplnActive)
        {
            /* While the application is active, check for data sent during the last 50 ms. If no data
               has been sent to the host, use the channel wrap-up feature to send any partial buffer to
               the USB host.
            */
            if (glPktsPending == 0)
            {
                /* Disable UART Receiver Block */
                UART->lpp_uart_config = regValueDs;

                CyU3PDmaChannelSetWrapUp (&glChHandleUarttoUsb);

                /* Enable UART Receiver Block */
                UART->lpp_uart_config = regValueEn;
            }

            glPktsPending = 0;
        }

In CyFxUartSendBuffer(), you cannot use APIs CyU3PDmaChannelSetupSendBuffer() and CyU3PDmaChannelWaitForCompletion() - as they are for DMA override mode. Please refer https://community.cypress.com/t5/Knowledge-Base-Articles/DMA-Channel-in-Override-Mode-in-FX3-CX3-KBA...

Instead you can use CyU3PDmaChannelCommitBuffer() when you get DMA callback. When you are not using override mode, for MANUAL_IN channel you get PROD event when a DMA buffer is available from producer and for MANUAL_OUT you get CONS event when a buffer is consumed by consumer. For these events to be available you can refer to UsbBulkSrcSink example of FX3 SDK (You can only refer to DMA channel creation part and callback function part of the firmware). In your firmware you will have to take care of dmaCfg.notification and dmaCfg.cb accordingly.

For your use case, Override mode is not suitable for USB to CPU channel. For CPU to USB channel you can either go with override mode(as in the case of cyfx3s_fatfs example) or normal mode (as in UsbBulkSrcSink example).

Path for UsbBulkSrcSink: {FX3_SDK_Installation_Path}\1.3\firmware\basic_examples\cyfxbulksrcsink

Regards,

Hemanth
0 Likes
lock attach
Attachments are accessible only for community members.

Hi Hemanth,

thanks to your answer I was able to implement a working project! In attached you can find the updated version.
Please could you give me some advices / ideas to improve it or to make a more robust design? 
e.g.: Is the DMA properly configured and correctly used? I missed something with DMA? How to detect that the Virtual COM port is open in a terminal before sending something?

Many thanks in advance, regards,
Corrado

 

0 Likes
Hemanth
Moderator
Moderator
Moderator
First like given First question asked 750 replies posted

Hi Corrado,

I can see a possible problem in your project.

In for (;;)
{

you make calls to VirtualUartPutChar() which uses glChHandleCPUtoUsb channel.

But think of below sequence:

1. In for (;;), VirtualUartPutChar() is called

2. CPU has finished executing CyU3PDmaChannelGetBuffer() followed by CyU3PMemCopy (buf_p.buffer, (uint8_t*)InString, len);  in VirtualUartPutChar()

3. Now there is a dma callback due to PROD event.

4. Now your app thread will be pre-empted by DMA thread to complete the DMA callback.

5. Within the callback you make another call to CyU3PDmaChannelGetBuffer(), which will give the same DMA buffer as retuned in step 2

6. After DMA callback finishes, the app thread you created is served. Now you do CyU3PDmaChannelCommitBuffer() - which is not valid. As the buffer is already committed in the DMA callback.

Please check this scenario.

Regards,

Hemanth
0 Likes