CodeWarrior Tutorial for FRDM-KL25Z: USB CDC with the Freescale Freedom Board

Version 6

    This tutorial was extracted from Erich Styger blog http://mcuoneclipse.wordpress.com with his agreement.

     

    Freescale.bmpKinetis-L.jpg

     

    In “A shell for the Freedom board” I used the UART-to-USB OpenSDA capability of the Freescale FRDM-KL25Z FRDM-KL25Z Freedom board: The KL25Z processor uses the OpenSDA K20 microprocessor as Serial-to-USB converter. But this only works because of the P&E OpenSDA USB CDC (Communication Device Class) implementation. If I create my board without OpenSDA, I need a different approach: I want to do USB CDC with the KL25Z.

    freescale-cdc-device.pngUSB CDC Device on COM22

     

     

     

    For several months I’m using successfully my Processor Expert FSL_USB_CDC component since early this year, in several projects and with different boards. What is missing is support for the Kinetis KL25Z. So this is what this tutorial is about. It takes you maybe around 30 minutes, and you will have USB support with your Freedom board. As for myself, after learning all the knowledge needed, it takes me less than 10 minutes.

     

    I’m using CodeWarrior for MCU10.3 with my Processor Expert components. If you followed my earlier Freedom Board tutorials, then I hope you are familiar with loading more user components. Otherwise, have a look at the section “Additional Processor Expert Component Installation” in this post. In this tutorial I’m using following components:

     

    • FSL_USB_Stack: Freescale USB Stack as Processor Expert component.
    • Wait: Universal realtime waiting functions.
    • Optional: LED: Universal LED driver.

     

     

    :!:  The FSL_USB_Stack Processor Expert component has been updated to version V1.008 to support the KL25Z

     

     

    Step 1: Creating the Project (or reuse an existing one)

     

    In this tutorial I start from a clean sheet and create a new project. Of course it is possible to add USB CDC support to any of the other tutorials I have published for the Freedom KL25Z board, e.g. Tutorial: Enlightening the Freedom KL25Z Board. In that case, you can skip this step.

     

    To create a new project, I select the menu File > New > Bareboard Project and give it a project name :

     

    new-bareboard-project.png

    New Bareboard Project

     

     

     

     

     

     

    Next is to select the device:

     

    selecting-device.png

    Selecting Device

     

     

     

     

    I’m going to debug the board with OpenSDA only, so I deselect the default P&E Multilink, and select Open Source SDA:

     

    opensda-selection.png

    OpenSDA Selection

      

        

     

     

    The next dialog is about the language and build tools options: I go with the defaults:

     

    language-and-build-tools-options.png

    Language and Build Tools Options

     

     

     

    In the next dialog I make sure I select Processor Expert:

     

    processor-expert-project-option.png

    Processor Expert Project Option

     

     

     

    Pressing Finish will create the project:

     

    project-created.png

    Project created

     

     

     

     

    :idea:  Hint: In case the extra Processor Expert views are not already open: I use the menu ‘Processor Expert > Show Views’.

     

     

     

    Step 2: Adding the Components

     

    The next step is to add my other component(s): I select the component(s) in the Components Library view and add it to my project. If I already have the Wait component in my project, of course no need to add it again.

     

    selecting-and-adding-components.png

    Selecting and Adding Components

     

     

     

    This will add the components to my project. And the USB component shows a red (x) telling me that it needs to be configured:

     

    need-to-configure-the-fsl_usb_stack.png

    Need to configure the FSL_USB_Stack

     

     

     

     

    I need to component Inspector to configure the properties.

     

     

    :idea:  Idea: The context menu ‘Inspector’ on a component opens the Component Inspector View.

     

     

    If I inspect the properties of the USB component, it shows me that I need to set up the CPU and the USBInit property:

     

    need-to-configure-component.png

    Need to configure component

     

     

     

    So I select the CPU for my KL25Z board, and select Init_USB_OTG_VAR0 to initialize the USB peripheral for it:

     

    usb-component-configured-for-kl25z.png

    USB component configured for KL25Z

     

     

     

    :?:  No idea why Freescale has decided to name that Kinetis component as ‘Init_USB_OTG_VAR0′. A name like ‘Init_USB_OTG_Kinetis’ would have been *much* easier to use and remember.

     

     

    The next thing is to inspect the USBInit component. And it is good to pay close attention to the warnings:

     

    warnings-in-usbinit.png

    Warnings in USBInit

     

     

     

     

    Enabling the Clock gateensures that the USB module is clocked. And as I have no external clock pin, I select to use the PLL/FLL clock source:

     

    enabled-clock-gate-and-configured-clock-source.png

    Enabled Clock Gate and configured clock source

     

     

     

    The inspector informs me about a very important thing: the USB module requires a 48 MHz clock. So I need to make sure that this is configured properly.

     

    :!:  Warning: Failing to configure the USB clock properly is probably the most common source of failure. For myself I can count endless hours debugging and inspecting my projects, and in many cases I made a mistake in the clock configuration. Unlike many other USB enabled devices, the Freescale ones need an external crystal, and that crystal has to be used to generate a very stable and accurate clock signal. Otherwise it will *not* work.

     

     

    Step 3: Configuring the Clock

     

    According to the FRDM-KL25Z Schematics (SPF-27556_D).pdf have a 8 MHz crystal on the board:

     

    8-mhz-crystal.png

    8 MHz Crystal on FRDM-KL25Z

     

     

     

    :!:  IMPORTANT: I’m using in this post the ‘white’ pre-production Freedom Board. The black production board board has several differences (see Completing the FRDM-KL25Z Board). An important difference is that the black board has the 1.0MOhm resistor R25 nearby the 8 MHz: with that resistor *not* populated, the clock will *not* run in high gain mode. So for the black Freedom board with that resistor *not* populated, the clock mode has to be in ‘low power’ mode. 

     

     

    The configuration of the clock is in the CPU component. For this I select the CPU to configure the properties:

     

    cpu-component-to-configure-the-clocks.png

    CPU component to configure the clocks

     

     

     

    I can have multiple oscillator settings, but here I just need one. So I enable the ‘System oscillator 0′ setting, and configure it to use an 8 MHz external crystal in High gain mode (for the white pre-production board which has the R25 (see above) populated, but in Low Power mode for the black production board:

     

    setting-8-mhz-external-crystal.png

    Setting 8 MHz external crystal with High Gain (White board only!!!)

     

     

     

    As the black Freedom board has no R25 populated, the Oscillator operating mode has to be ‘Low power’ instead:

     

    low-power-oscillator-mode-required-if-r25-not-populated-black-freedom-board1.png

    Low Power Oscillator Mode required if R25 not populated (black Freedom board)

     

     

     

    Next is to select the PEE (PLL Engaged External) clock mode: in this mode, the PLL is using the external reference clock. Remember that the USB block needs an 48 MHz PLL signal? So I need to configure it to 96 MHz as it will be divided by a factor of 2 until it reaches the USB block:

     

    pee-mcg-mode.png

    PEE MCG Mode

     

     

     

    With my clock changes, the core clock is not set correctly:

     

    error-for-core-clock.png

    Error for core clock

     

     

     

    With my base clock of 8 MHz, I can set the CPU core clock to 48 MHz and a Bus clock of 24 MHz:

     

    core-and-bus-clock.png

    Core and Bus Clock

     

     

     

    Now I could think that everything is just fine. But there is one possible glitch, and maybe this is even a silicon problem (?): I need to *disable* the Internal and External reference clock, otherwise my board will crash during clock configuration. So I need to *disable* the reference clocks:

     

    internal-and-external-reference-clock-disabled.png

    Internal and External Reference Clock disabled

     

     

     

    Checking my USB module again, it shows that it is now properly clocked with 48 MHz:

     

    usb-with-48-mhz-pll-clock.png

    USB with 48 MHz PLL clock

     

     

     

    :???:  Processor Expert still warns about the need for 48 MHz clock, even I have it set up with 48 MHz? Anyway, the important thing is that it *is* clocked with 48 MHz.

     

     

     

    Step 4: Adding Application Code

     

    I keep things very simple here: no RTOS. All what I add in Processor Expert is a simple loop-back which does an echo of what I type into the terminal window.

    To show the current enumeration status, I’m using my code from my earlier Tutorial: Enlightening the Freedom KL25Z Board.

     

     

    :!:  Hint: An easy way to copy Processor Expert components from one project to another is using copy-paste. If you do not want to use the LEDs, then simply remove the code for the LEDs in the code below.

     

     

     

    I’m adding the function CDC_Run() to the ProcessorExpert.c as below and call it from main():

     

     

     

    001/** ###################################################################
    002**     Filename    : ProcessorExpert.c
    003**     Project     : ProcessorExpert
    004**     Processor   : MKL25Z128VLK4
    005**     Version     : Driver 01.01
    006**     Compiler    : GNU C Compiler
    007**     Date/Time   : 2012-10-07, 12:33, # CodeGen: 0
    008**     Abstract    :
    009**         Main module.
    010**         This module contains user's application code.
    011**     Settings    :
    012**     Contents    :
    013**         No public methods
    014**
    015** ###################################################################*/
    016/* MODULE ProcessorExpert */
    017
    018/* Including needed modules to compile this module/procedure */
    019#include "Cpu.h"
    020#include "Events.h"
    021#include "WAIT1.h"
    022#include "USB1.h"
    023#include "USBInit1.h"
    024#include "Tx1.h"
    025#include "Rx1.h"
    026#include "LED1.h"
    027#include "LED2.h"
    028#include "LED3.h"
    029#include "GPIO1.h"
    030#include "GPIO2.h"
    031/* Including shared modules, which are used for whole project */
    032#include "PE_Types.h"
    033#include "PE_Error.h"
    034#include "PE_Const.h"
    035#include "IO_Map.h"
    036
    037/* User includes (#include below this line is not maintained by Processor Expert) */
    038static uint8_t cdc_buffer[USB1_DATA_BUFF_SIZE];
    039static uint8_t in_buffer[USB1_DATA_BUFF_SIZE];
    040
    041static void CDC_Run(void) {
    042int i;
    043
    044for(;;) {
    045while(USB1_App_Task(cdc_buffer, sizeof(cdc_buffer))==ERR_BUSOFF) {
    046/* device not enumerated */
    047LED1_Neg(); LED2_Off();
    048WAIT1_Waitms(10);
    049}
    050LED1_Off(); LED2_Neg();
    051if (USB1_GetCharsInRxBuf()!=0) {
    052i = 0;
    053while(   i<sizeof(in_buffer)-1
    054&& USB1_GetChar(&in_buffer[i])==ERR_OK
    055)
    056{
    057i++;
    058}
    059in_buffer[i] = '\0';
    060(void)USB1_SendString((unsigned char*)"echo: ");
    061(void)USB1_SendString(in_buffer);
    062(void)USB1_SendString((unsigned char*)"\r\n");
    063} else {
    064WAIT1_Waitms(10);
    065}
    066}
    067}
    068
    069/*lint -save  -e970 Disable MISRA rule (6.3) checking. */
    070int main(void)
    071/*lint -restore Enable MISRA rule (6.3) checking. */
    072{
    073/* Write your local variable definition here */
    074
    075/*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/
    076PE_low_level_init();
    077/*** End of Processor Expert internal initialization.                    ***/
    078
    079CDC_Run();
    080
    081/*** Don't write any code pass this line, or it will be deleted during code generation. ***/
    082/*** RTOS startup code. Macro PEX_RTOS_START is defined by the RTOS component. DON'T MODIFY THIS CODE!!! ***/
    083#ifdef PEX_RTOS_START
    084PEX_RTOS_START();                  /* Startup of the selected RTOS. Macro is defined by the RTOS component. */
    085#endif
    086/*** End of RTOS startup code.  ***/
    087/*** Processor Expert end of main routine. DON'T MODIFY THIS CODE!!! ***/
    088for(;;){}
    089/*** Processor Expert end of main routine. DON'T WRITE CODE BELOW!!! ***/
    090} /*** End of main routine. DO NOT MODIFY THIS TEXT!!! ***/
    091
    092/* END ProcessorExpert */
    093/*
    094** ###################################################################
    095**
    096**     This file was created by Processor Expert 10.0 [05.03]
    097**     for the Freescale Kinetis series of microcontrollers.
    098**
    099** ###################################################################
    100*/

     

     

     

    Step 5: Running the Application

     

    Now I can generate code for my drivers, e.g right click on the ProcessorExpert.pe file and selecting "Generate Processor Expert Code":

     

    generate-processor-expert-code.png

    Generate Processor Expert Code

     

     

     

    Followed by building the sources (menu Project > Build Project ). And then download/debug it.

     

    With the USB plug disconnected, the red LED is on:

     

    usb-disconnected.png

    USB disconnected: red LED on

     

     

     

     

    With connecting the USB cable to the KL25Z, it enumerates the device and the green LED is on:

     

    usb-enumerated.png

    USB enumerated: green LED on

     

     

    Additionally it has been enumerated as device on my host machine:

     

    freescale-cdc-device.png

    Freescale CDC Device

     

     

     

    In case it is the first time you use such a CDC device: the driver .inf file is generated in the ‘Documentation’ folder (for details see USB CDC, reloaded):

     

    cdc-inf-driver-files.png

    cdc.inf driver files

       

     

     

    I connect to the virtual CDC COM port with a terminal program. And the application will echo what I send to it:

     

    terminal-connection-with-echo.png

    Terminal Connection with Echo

     

     

     

    Summary

     

    Setting up and using an USB stack is definitely not a trivial task, as a lot of settings needs to work correctly. I hope that with the above information it should be much easier to do this now for the Freescale FRDM-KL25Z board. Using Processor Expert makes things definitely a lot easier. While the above project is bare-metal (no RTOS), it is easy to add an RTOS to it. That’s actually how I use it like in the Freedom Shell project.

     

    The above project can be downloaded here or from the link on http://www.steinerberg.com/EmbeddedComponents/Examples/Examples.htm

     

    Happy USB Freedom :-)