USB CDC with the FRDM-K20D50M

Good news for everyone owning the FRDM-K20D50M board: I have extended the FSL_USB_Stack with USB CDC device class support for the K20D50M :-).

USB CDC Test Application with the FRDM-K20D50M

USB CDC Test Application with the FRDM-K20D50M

Demo Application

The demo projects is made with Processor Expert components so it can be easily copied or ported to another board:

FRDM-K20D50M USB CDC Application Components

FRDM-K20D50M USB CDC Application Components

I have created a demo application which echoes the entered text back on the console, with incrementing a counter:

USB CDC Test Application with the FRDM-K20D50M

USB CDC Test Application with the FRDM-K20D50M

FSL_USB_Stack with FSL_USB_CDC_Device

With just two additional Processor Expert components, it is possible to add USB CDC functionality to an existing projects in just a few minutes. See “USB Component Splitted and Updated” for architectural information. The component has now added a Kinetis K20D50 option:

Kinetis K20D50 in FSL_USB_CDC_Device Component

Kinetis K20D50 in FSL_USB_CDC_Device Component

💡 The FSL_USB_CDC_Device component features now an optional timeout feature. With this, it is easer to use the component in a bare-metal environment. It is using the extra ‘Timeout’ component which implements a timer based timeout to avoid stalling of the stack.

USB Clock Configuration

The most difficult part is the clock configuration. The USB block needs a 48 MHz clock to sample the 24 MHz USB signal. In the CPU component properties, I configured the System oscillator 0 to use the external 8 MHz crystal in Low power mode:

System Oscillator Settings

System Oscillator Settings

The MCG Is set to PEE and 48 MHz PLL output clock:

MCG Settings

MCG Settings

❗ It should be possible to use a 96 MHz PLL clock and then divide it down in the USB peripheral to a clock of 48 MHz. This is what I did first, and lost a lot of time, because this did not work :-(. I have not investigated it further, but this is either a bug in the silicon or in Processor Expert? 48 MHz without prescaler in the USB worked.

Derived from this, the system clocks are set up like this:

System Clock Settings

System Clock Settings

❗ IMPORTANT: Do not forget to set the PLL/FLL clock choice to ‘PLL clock’ as shown as last item in above screenshot.

In the Init_USB_OTG, the clock gate has to be enabled and the PLL/FLL clock to be used with 48 MHz:

USB Init_USB_OTG Settings

USB Init_USB_OTG Settings

❗ From the settings it would be possible to use a 96 MHz PLL clock and then to scale it down ot 48 MHz. However, with this my device did *not* enumerate 😦

That’s it! The rest is just writing a small test application.

Sources

The above project and sources are available on GitHub here. The same repository hosts the updated FSL_USB_Stack and FSL_USB_CDC_Device Processor Expert components.

Happy CDCing 🙂

73 thoughts on “USB CDC with the FRDM-K20D50M

  1. Erich,

    Thanks a lot or the nice USB CDC PEx component! I could easily port your K20 project to the Kwikstik K40 and it seems to work 🙂 BTW, I had no problems to set the CPU clock to 96 MHz on the Kwikstik. Just noticed that the USB clock must be set twice to 48 MHz – I set it once in the CPU and again in the Init_USB_OTG – there the 96 MHz have to be divided by two to get 48 MHz.

    Best regards,
    Anguel

    Like

    • Hi Anguel,
      good to hear that things are useful for you. I have not tried it with my Kwikstik K40: I had issues with the USB to get up and running. It looks I had an early version of it with either a hardware or silicon bug.

      Like

      • BTW, it looks like advanced settings like packet sizes or self- vs bus-powered options cannot be set in properties. Are these hardcoded somewhere and is there an easy way to see them? Thanks a lot!

        Like

        • Some settings can be changed in the ‘Init’ subcomponent (like device vs host). Other things are hardcoded in the USB stack. You might have a look at USB1_Init() and the functions it calls.

          Like

  2. Thanks a lot, I will have a look. Are there actually other special benefits of your stack besides ease of use (e.g. better speed or bug fixes) vs. the original Freescale USB stack? As far as I understand your stack is based on the Freescale stack.

    Like

    • The main difference is: it integrates support for an RTOS (it is using the RTOS malloc() and free() routines, and as it is using Processor Expert, it is easier to integrate into the rest of a system (if using Processor Expert). Additionally I have removed many warnings detected by gcc, and made sure it works with higher optimizations. I have passed my fixes and extensions to Freescale, so their next stack should incorporate those fixes too.

      Like

  3. Thank you once again for the clarification, for the nice stack and all the invaluable tutorials! I hope that Freescale is aware of the fact that what you are doing is much better than any marketing work.

    Like

  4. Hi Eric,
    Have you run the FSL_USB_STACK with MQX Lite? I have a bare metal project that runs with the stack, and another project that uses MQX Lite. When I add the stack to the MQX Lite project, I get a lot of script errors when the PE components are compiled. All of the components are error free before the compile. Any ideas?

    Best Regards,

    George

    Like

    • Hi George,
      no, I have not used it yet with MQX-Lite. What comes to my mind is for sure the memory interface (malloc() and heap()) which would need to be adopted. I would need to check this (and to try it out).

      Like

    • Hi George,
      I have created a MQXLite project for the KL25Z (FRDM-KL25Z) and added the FSL USB stack (CDC). So far I’m running into the problem that both the USB Stack and MQXLite generate a file ‘user_config.h’ which gives a name conflict. I’m going to change the file name in the USB stack, and hopfully this is the only problem? Or what error message are you seeing?

      Like

    • Hi George,
      I have fixed this user_config.h file conflict: the USB stack on GitHub is using usb_user_config.h instead. I have created an MQX-Lite project with the USB stack, and it compiles fine. I have published it on https://github.com/ErichStyger/mcuoneclipse/tree/master/Examples. But there is one problem: as soon as I plugin the USB cable, the MQX RTOS causes a hard_fault, because Processor Expert is adding the USB interrupt directly to the vector table, and this causes to overwrite the kernel data structure. I’m hitting right now a wall, because that USB_Init component is not something I can change. Looks like using MQX-Lite is a lot harder than I thought 😦 Or do you have any suggestion?

      Like

      • Hi Eric,
        Thanks for getting the config.h conflict resolved. It looks like Freescale needs to make some adjustments in the USB_Init component.

        Like

        • Yes, I have created a ticket on this. the Init component directly installs the interrupt vector, and then it crashes on my machine. So this hopefully can be addressed sometimes in the future. But as of right now, it looks that MQX lite does not work with the init components if they install an interrupt.

          Like

        • Hi Niranjan,
          I don’t know if they have changed that for MQXLite. Soon after I have found that issue, I have decided to switch to FreeRTOS anyway. I’m not using MQX or MQXLite for a long time any more. I’m sorry, I won’t be able to help you much for anything around MQX or MQXlite as this is a world of the past for me.

          Like

  5. Eric,
    Could you give a quick tutorial on how to download the example projects and libraries that you put on your GIT site?
    Thanks, Greg

    Like

  6. Hi Erich ,
    I’m using KL25Z and USB CDC , i’m sending data continuously to terminal , but if terminal isn’t connected to KL25Z USB , then the card stalls , after it stalls i open terminal , it exits from stall but Tera Term can’t read received data .

    Like

  7. Hi Eric,
    Is there a way to adapt the FSL_USB_Stack PE component such that two FSL_USB_Stacks (one configured for a MSD host , and the other configured for a CDC device) can coexist on the same USB port, and be compiled in the same PE project? A soft switch (i.e. nonvolatile memory location or GPIO bit hard wired to a switch) could be used to select one of the two stack configurations to run when the processor boots. Currently there are expected pin and timer conflicts.

    Regards,

    George

    Like

    • Hi Georg,
      interesting idea, especially switching between host and device mode. For sure the current stack/component does not support this at run time. But you say that it would be ok to switch this at boot time? That sounds like a bootloader implementation: so the ‘bootloader’ runs in MSD host mode, and the application runs in CDC device mode. This would be supported today. Is this what you have in mind? Using the MSD host to bootload your application?

      Like

      • Hi Eric,

        The application (not the boot loader) needs the capability to switch between the host and device modes. Since the reboot time on an embedded system is usually fast, selecting the mode at boot time eliminates a lot of issues associated with trying to dynamically switch modes. There are other applications where the board could run as a device or host based on a selector at boot time.

        George

        Like

  8. Pingback: Tutorial: FreeMASTER Visualization and Run-Time Debugging | MCU on Eclipse

  9. Pingback: USB for the Freescale ARM Kinetis KL46Z and K21D50M | MCU on Eclipse

    • Hard to say, as it is really hard to tell which silicon Freescale is using: inside the same family (e.g. K20) there can be different dies, with different behaviour :-(. The differences are in some settings for the clocks and the USB module. You might give it try. I assume you are saying that the K20D50 did not work for you?

      Like

      • the K20D72 is working with a K20F120 processor, FYI. But I noticed when I run my program (which also has FreeRTOS, so the shell and command interpreter are hooked to USB_CDC), it seems it doesn’t fully start up (thread running the interpreter flashes an LED, lifted from one of your projects) until the USB port is plugged in and recognized by the computer. Problem is it’s a diagnostic port, it won’t be hooked up in the field, so is there a way to deal with that, or is it not a problem and just need to make sure threads blocking on USB_CDC don’t do anything unrelated that still needs to run regardless? (hope I’m making sense)

        Like

        • Thanks for the confirmation that it works on the K20D72.
          Where is your application blocked? While checking CDC1_App_Task()? It does not have to be blocked there (if you are using my example code. You need to periodically call it to empty the buffers once the cable is connected, but you the call to CDC1_App_Task() is non blocking. Does this make sense?

          Like

      • it’s stuck trying to print the help stuff before the task starts it’s infinite parsing loop. the call stack looks like this:

        9 CDC1_RunUsbEngine() CDC1.c:358 0x000163de
        8 CDC1_App_Task() CDC1.c:423 0x0001648e
        7 CDC1_SendChar() CDC1.c:196 0x00016248
        6 CLS1_SendChar() CLS1.c:678 0x000160e0
        5 CLS1_SendStr() CLS1.c:93 0x00015a36
        4 CLS1_ParseCommand() CLS1.c:244 0x00015b1a
        3 CLS1_IterateTable() CLS1.c:397 0x00015dfc
        2 CLS1_ParseWithCommandTable() CLS1.c:437 0x00015e7c
        1 ShellTask() Shell.c:60 0x00018682

        Stack levels 7, 8 & 9 var but it’s always in CLS1_SendChar() when I stop it…

        I guess that’s no big deal I just have to make sure the threads with this comm stuff don’t need to do anything else important (like, in this case, blinking an LED every second).

        Like

        • Hi Marc,
          have a look at the Shell (CLS1) properties: there is a property ‘Blocking Send’. I asssume it is set to ‘yes’ for you. This means it tries to send the string until it succeeds. Change that to ‘no’. Then it will try to send it, but if the buffer is blocked/full, it will return and not wait. This should solve your problem. Let me know if this works (or not).

          Like

      • yes I did have block on send set, and clearing that solved the problem, thanks. Still, when I re-run the program, I find I have to close the terminal connection (I’m using the terminal inside eclipse), and physically unplug the usb, then plug it back in, to get a good connection to the terminal. I suspect it’s the OS holding the device descriptor open. windows. gotta love it.

        Like

        • Yes, the OS keeps the device descriptors open which is a pain. Additionally, if you plug in the OpenSDA, then the USB bus gets reset. So this is the usual sequence I have to do:
          – I have COM port open, and then power-up or disconnec the cable.
          – I need first to close the COM port in the terminal program, then plugin the board
          – After that, I can open the COM port again.
          Failing that sequence means that the COM port will not work.

          Like

  10. I have difficulty to develop a MSC device bootloader on FRDM-K20D50M. There are many random errors there. Do you think it is possible related to the PLL/FLL to 50MHz, instead of 48MHz? The situation is the MSC bootloader can be enumerated on Windows XP, but reprots I/O error during copying file and programming.

    I can share my source if necessary.

    Like

  11. Hi, Erich

    I’m trying to follow you to add a USB CDC function to my FRDM-K20D50M board. But I have some problems with the Freescale CDC Device driver now. Please help me.

    I did like this,
    I connected the USB cable, then after a short while, the board showed up as “Unknown Device” in the “USB controller” section of the Device Manager. I tried to update its driver, by doing “Browse my computer…” -> “let me pick from a list…” -> “have disk”, and finally I pointed to the “cdc.inf” file in Documents folder. But when I clicked OK, it popped up a window saying that there’s no driver for the device in this folder.

    So I changed another way to install it. What I did is,
    I chose “Add legacy hardware” in Device Manager. Then, “pick up from a list” -> “show all device” -> “have disk”. Finally I browsed the same driver file “cdc.inf”. This time, the installation started, and in the COM section, the device shows up as a serial port device named “Freescale CDC Device”, but with a yellow exclamation point. I connect the USB cable again, then for this “Freescale CDC Device”, nothing changes. And the board still shows up as “Unknown device”.

    I tried to disconnect, connect the board, uninstall, reinstall many times. But it always doesn’t work. Note that on another PC, with the same board, there’s no problem. Do you know how to fix this problem?

    Please help me! Many thanks!

    Like

    • I just can think about that the problem must be your PC (if the board is fine otherwise). Are you using USB3 ports maybe? That could cause problems. Have you tried different USB cables and different USB ports on your PC?

      Like

      • Hi,
        I solved this problem yesterday. I just copy the generated .inf file from another PC on which the K20D50M works well to my own laptop. This time the driver installation is successful, so USB CDC is OK now:)
        My laptop is a mac with win7 installed using bootcamp. There is no USB3 port and I’m using CW10.6.

        Like

  12. Hi Eric,

    I have been using the FSL_USB_Stack with the CDC Device property without any problems (K20). I just updated the components for an existing project, and I am getting a number of compile errors associated with %substring out of string {“FREESCALE INC.”,15,1} (file: Drivers\FSL_USB_Stack\Device\app\cdc\usb_descriptor.c). The component inspector indicates there is an error on the FSL_USB_CDC_Device, but does not show anything in the properties or methods.This happens on CW10.5 and 10.6. Is this a known issue?

    Regards,

    George

    Like

  13. Hi Eric, I’m trying to make a USB CDC HOST application, using Processor Expert , CW10 and FRDM-k20DM board. Is it possible, because I’m stuck with device enumeration . I want to connect ACM USB device, but it is detected as DATA device.

    Like

        • Got it. I see that you are using the Freescale provided components for USB CDC host. I was never able to get them working, so I decided to create my own components. They do not support USB CDC host, but now it looks I should have a look at it if time permits.

          Like

        • As an upate, I worked on the last couple of week-ends on the USB CDC Host stack. I have it compile and running on the target.

          It is just that it does not enumerate (yet) properly. So I guess I still need to do some debugging….

          Like

        • Hi Erich, I have also worked on this and now my device enumerates properly. Later I will send you my code.

          Like

        • Here is my latest project. Device enumerate as ACM device and I think it works fine. The problem still left is in reading bytes from device. Sometimes I get 1 byte, sometimes 49. Just in few words my device is crypto module. After initialization I must send ping command and read the response. Initialization is done outside this project – its a Arch Linux custom Board , running my other firmware. After power down on my main CPU and board, K20 detects it and sends to main CPU command to shut down( I have battery pack and I need to save power) . Here is the challenge. Now instead of just being a pipe from main CPU to Crypto Module, K20 should simulate continuous work – in simple words just pinging the device and receive its answer( void CDC_Battery_Task()) . The answer is important for me, because device may initiate other command ( not just ping pong ). In this case I need to wake up my main CPU and do some other work. So I’m in state that my simple PING PONG won’t work because of not receiving proper count of bytes. 10x a lot again.

          P.S. I’m sorry to waste your time, but this is area that I feel so “not in my place”. I’m working mostly on Linux environment – U-boot, kernel and writing on custom boards.

          2014-08-10 7:44 GMT+03:00 MCU on Eclipse :

          > Erich Styger commented: “As an upate, I worked on the last couple of > week-ends on the USB CDC Host stack. I have it compile and running on the > target. It is just that it does not enumerate (yet) properly. So I guess I > still need to do some debugging….” >

          Like

    • I am looking to do this as well with a Teensy 3.1 board (Kinetis MX20DX256) that’s in the mail.

      Can you share your in-progress ACM startup code?

      I am hoping to make the Teensy host an e-ink tablet for use as a ultra-low-power GPS map. Reversing the host/device roles would be easier, but most tablets’ USB-OTG-Host IC’s and kernel drivers are simply not well implemented and leak excessive power.

      Like

  14. Pingback: USB with the Freescale FRDM-K22F Board | MCU on Eclipse

  15. Hello Erick,
    I want to add USB CDC to my custom board with MK60DX256.
    I follow your guide but I have a trouble in USB0:Init_USB_OTG.
    The problem is into USB_Init in the Module Clock Frequency that remains STOPPED (not 48 MHz).
    Could you help me?

    Thanks

    Like

    • Hi Frederico,
      this means that probably a clock setting in the CPU component is wrong. Usually on the bottom of the properties in the CPU component there is a setting for the USB clock. Is it configured properly?
      Erich

      Like

      • Hi Erick,

        thanks for your reply.

        In my project, if I open Component Inspector – Cpu, at the bottom I can’t find USB CLOCK SECTION (into PLL/FLL CLOCK SECTION). But if I open your CDC_TWR-K60N512, that settings appears.

        What was wrong?

        Thanks Federico

        P.S.: Before open this thred I posted the same question on Freescale Community: freescale community thread/341639

        Like

        • Hi Frederico,
          I posted an answer in that thread. It looks you have an older CodeWarrior (not 10.6 with Update 4) from your screenshots. And you are in Basic, not in Advanced mode, then some settings are hidden.

          Erich

          Like

  16. Hello, Erich

    Do you have any example of USB-CDC on Kinetis using your Processor Expert beans like this, but for KDS 3.0.0?

    Thanks!

    Like

  17. Hi Eric,

    I have been working from your example code and components from SourceForge (Components 2016-06-25.zip). Thank you for providing the example and components. I’m new to the Freescale/NXP devices and this is all helpful. I can get the example working to the point of the USB device being recognized and enumerated. I’m using PuTTY for the terminal and I get no response when sending to the Freedom board. I added a CDC1_SendString operation after WAIT1_Waitms(10) to see if transmitting would works and it does send a character with every cycle. By doing this I found that if I send a string amidst the incoming characters, I would get the correct response from the device – the echo with the variable value. I can’t find out why the CDC1 Rx buffer won’t receive without having preceding transmission. Any ideas?

    Thanks!

    Like

What do you think?

This site uses Akismet to reduce spam. Learn how your comment data is processed.