USB CDC with FreeRTOS

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

cross mob
HaEl_4692376
Level 1
Level 1
5 replies posted First question asked First reply posted

Hi,

I am using the USB CDC code example, but using it with FreeRTOS. Therefore, I am not going to be polling.

I am able to get it all working, and the code runs as expected. I have a few corner cases, and a few questions highlighted.

Device starts with USB plugged in, enumerates, everything works great. If I unplug the USB cable from my kit, the task consumes all the CPU with the while loop:

/* Wait until component is ready to send data to host. */

while (0u == Cy_USB_Dev_CDC_IsReady(USBUART_COM_PORT, &usb_cdcContext))

{

}

So I added the following check:

if (isUsbReady() && (CY_USB_DEV_CONFIGURED == usb_devContext.state))

where isUsbReady is:

bool isUsbReady(void)

{

    return (Cy_USB_Dev_GetConfiguration(&usb_devContext));

}

This does not seem to solve my issue. Same issue happens.

If I start the program with the USB unplugged, it works just fine.

So is there a way to register a callback to notify the program and set a flag when a USB is unplugged after being enumerated?

The second case I am trying to solve:

How do I register a callback to interrupt when there is a character coming in from the terminal? So instead of polling, I interrupt and retrieve the character.

The last case is about low power. I have a tickless FreeRTOS implementation, so it goes to sleep. Is there an example project showing the proper transition for the USB in an out of sleep?

Thanks,

H-

0 Likes
1 Solution
RodolfoGL
Employee
Employee
250 solutions authored 250 sign-ins 5 comments on KBA

For your first question, there is a function called Cy_USB_Dev_Connect. It requires a timeout argument. By default it uses blocking delay function, which is not ideal for RTOS environment. However, you can overwrite it using the Cy_USB_Dev_OverwriteHandleTimeout(). You can implement something like this to overwrite the blocking delay:

int32_t MyTimeoutHandler(int32_t ms)

{

     vTaskDelay(1/portTICK_PERIOD_MS);

     return --ms;

}

Besides that, at the moment you unplug your USB cable, you should call the USB Suspend and USB Resume APIs, specially if low power is required. Please refer to this code example:

https://www.cypress.com/documentation/code-examples/ce223305-psoc-6-mcu-usb-suspend-and-resume

You don't need to necessary go to deep-sleep, but do not use any USB APIs when suspended.

For your second question, you can register a data endpoint callback for the CDC OUT endpoint, by using the function Cy_USBFS_Dev_Drv_RegisterEndpointCallback(). This callback will be executed when an endpoint transfer is completed on the given endpoint. But keep in mind that the USB generates an interrupt every 1 ms, so if you put your device on sleep, it will wake-up every 1 ms. Because of that you will not save much power using a callback, instead of polling.

View solution in original post

3 Replies
RodolfoGL
Employee
Employee
250 solutions authored 250 sign-ins 5 comments on KBA

For your first question, there is a function called Cy_USB_Dev_Connect. It requires a timeout argument. By default it uses blocking delay function, which is not ideal for RTOS environment. However, you can overwrite it using the Cy_USB_Dev_OverwriteHandleTimeout(). You can implement something like this to overwrite the blocking delay:

int32_t MyTimeoutHandler(int32_t ms)

{

     vTaskDelay(1/portTICK_PERIOD_MS);

     return --ms;

}

Besides that, at the moment you unplug your USB cable, you should call the USB Suspend and USB Resume APIs, specially if low power is required. Please refer to this code example:

https://www.cypress.com/documentation/code-examples/ce223305-psoc-6-mcu-usb-suspend-and-resume

You don't need to necessary go to deep-sleep, but do not use any USB APIs when suspended.

For your second question, you can register a data endpoint callback for the CDC OUT endpoint, by using the function Cy_USBFS_Dev_Drv_RegisterEndpointCallback(). This callback will be executed when an endpoint transfer is completed on the given endpoint. But keep in mind that the USB generates an interrupt every 1 ms, so if you put your device on sleep, it will wake-up every 1 ms. Because of that you will not save much power using a callback, instead of polling.

Thank you for fast response. Your suggestion worked as expected.

For the suspend and resume, I was able to implement in my program.

Is there a document to cover the low power transition overall. Not from a main file, but a distributed architecture, where each task handles it's own hardware control for mode transition.

Seems I am missing something in the transition and if i enable the callback, it locks up, and when I disable it, the rest of my program works as expected. Therefore, I am missing a declaration or a scope of a call back somewhere.

0 Likes

Yes, we have this App Note:

https://www.cypress.com/file/385936/download

It explains the power transition on PSoC 6.

Basically each peripheral can have their own Power Management callbacks. You can also refer to this code example:

https://www.cypress.com/documentation/code-examples/ce219881-psoc-6-mcu-switching-between-power-mode...

When you say "if I enable the callback, it locks up". Which callback are you referring to?