3 Replies Latest reply on Apr 29, 2020 7:42 AM by RodolfoG_11

    USB CDC with FreeRTOS

    HaEl_4692376

      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-

        • 1. Re: USB CDC with FreeRTOS
          RodolfoG_11

          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.

          2 of 2 people found this helpful
          • 2. Re: USB CDC with FreeRTOS
            HaEl_4692376

            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.

            • 3. Re: USB CDC with FreeRTOS
              RodolfoG_11

              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-modes

               

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

              1 of 1 people found this helpful