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

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 :-)