Archive

Posts Tagged ‘CDC’

KSDK USB CDC PRINTF

23/12/2015 18 comments

Previously I created a blog post on Printf to UART using Processor Expert, this is a great way to output debug info at runtime to a console using the OpenSDA USB debugger port as found for example on the FRDM K64F board. What if you don’t want to use this USB port or can’t because you don’t have one, for instance on a custom board perhaps. Well if your board provides a USB port that connects direct to the mpu’s USB pins this blog will help you configure all the Processor Expert components and code needed to output to that type of USB port. In this blog I will again use the FRDM K64F board but it has a second USB port that is directly connected to the USB pins of the of the MK64FN1M0VLL12 MCU. I am using KSDK 1.3.0 and Eclipse Neon but I will also try provide notes on how to do this in KSDK 1.2.0, if you want to know how to set up Eclipse you can follow the directions on my blog Toolchain: KSDK 1.2.0 with Eclipse 4.4 (Luna) and GNU ARM Plugin, although that blog covers an older version of Eclipse and KSDK, the steps work perfectly still as long as you download all the latest pieces of software mentioned in that blog.

PLEASE NOTE: I am not an expert with USB on Kinetis devices so I cannot provide any help on any other USB related projects such as Mass storage devices or HID devices. Please do not post comments/questions asking how to perform other types of USB projects.

 

FRDM_K64F_USB

 

  1. Ok to start, create a new Kinetis project.CreateProject_Name
  2. Select the board type. In my case I select the FRDM-K64F board.CreateProject_Board
  3. Select KSDK_1.3.0, Processor Expert and standalone.CreateProject_SDK
  4. Select “GNU C Compiler” and click Finish.CreateProject_Compiler
  5. Switch to Processor Expert perspective and add the component “fsl_usb_framework”. Note this will also automatically add the referenced components “Init_FMC” and “fsl_debug_console”.
    Note: In KSDK 1.2.0 the “Init_FMC” is not automatically added for you but you still add it manually then afterwards.PE_fsl_usb_framework
  6. If you get prompted on how you want to add the “Init_FMC” component, select “New component [KSDK 1.3.0/Init_FMC_VAR1]…”PE_fsl_usb_framework_sharedComp
  7. On the Components window select “usbFmw1:usb_framework” and set the properties as below. Its important that the USB clock is set to 48 MHz. Its also very important that MPU is disabled as the MPU protects the Bus from USB read/writes. Make sure the Mode is set to “DEVICE” then Enable “USBCFG_DEV_CDC” under the Device class driver section.
    Note: In KSDK 1.2.0 the option to disable the MPU is not available on this component, you will need to manually add the component “Init_MPU” and disable it from there.fsl_usb_framework_Properties
  8. Now select the component “FMC:Init_FMC”, this should be already set correctly for us but just note that the important bit here is that the access protection on Master 4 which protects USB memory access areas must be set to “Read only”.
    Note: in KSDK 1.2.0 this is not set for you, you must manually set Master 4 to Read only.Init_FMC_Properties
  9. Next select the “DbgCs1:fsl_debug_console” component, make sure the “Baud rate” is set to 115,200. It’s not important what Pins the Receiver and Transmitter are set to as this will get overridden in code when we initialise this component manually. VERY IMPORTANT, make sure the “Auto initialization” is disabled, as said, we will manually do this in code.fsl_debug_console_Properties
  10. Ok one last configuration then, select the “Cpu:MK64FN1MOVLL12” component (or whatever MPU you are using). Switch to the “Build Options” tab and make sure you set a Heap size because usb stack uses malloc which uses a function called _sbrk(). This function checks if there is heap memory available to allocate to the malloc. The FRDM K64F board has enough memory available for me to set the Heap size to its max on this screen of 0xFFFF, Also make sure you have at least 0x400 allocated to the Stack.
    Note: KSDK 1.2.0 has a bug and does not implement a _sbrk() function, you will need to create your own _sbrk() function to get this to work. See the end of this Blog on how to do this.Cpu_HeapSize
  11. Now generate code from Processor Expert.Components
  12. On the Project Explorer window, expand the folder \SDK\usb\usb_core\device\sources. Create a folder under the sources folder called “classes”.Import the following 3 folders into the classes folder from the path “C:\Freescale\KSDK_1.3.0\usb\usb_core\device\sources\classes”
    • cdc
    • common
    • include

    import_usb_classes

     

  13. We need to add these new folders into the includes. Open up the project properties and add the following 4 folders under “C/C++ Build >> Settings >> Cross ARM C Compiler >> Includes”.Project_Settings_includesOn the Project Explorer window again, Open up the file “\SDK\platform\utilities\fsl_debug_console.c”.  Note around line 49 the following #if block:
#if (defined(USB_INSTANCE_COUNT) &&  (defined(BOARD_USE_VIRTUALCOM)))
  #include "usb_device_config.h"
  #include "usb.h"
  #include "usb_device_stack_interface.h"
  #include "usb_descriptor.h"
  #include "virtual_com.h"
#endif

based on this section of code I can see that the code actually supports using USB and the use of the “VIRTUALCOM”. What is this “VIRTUALCOM”, well if you were to look at the code in the example KSDK project “C:\Freescale\KSDK_1.3.0\examples\twrk64f120m\demo_apps\usb\device\cdc\virtual_com\bm\kds” which is a project for demonstrating how to use USB CDC communication but without the use of the” fsl_debug” component or using Processor expert at all, then you will see that the “VIRTUALCOM” is the main piece of code written for sending and receiving messages over the USB CDC. Great, that means then that we can enable the “fsl_debug_console” to make use of it. So looking at this section of code in “fsl_debug_console.c”, it looks like all we need do is define a symbol for “BOARD_USE_VIRTUALCOM”.

  1. Open up the Properties of the project and under “C/C++ Build >> Settings >> Cross ARM C Compiler >> Preprocessor” add the symbol “BOARD_USE_VIRTUALCOM”. make sure to include the double quotes around the symbol.Project_Settings_Preprocessor
  2. Ok but now the code will complain that it can’t find the included files “usb_descriptor.h” and “virtual_com.h”, so where can this be found. Well actually you can find these files in the same directory where the “fsl_debug_console” files get imported from. So to fix this perform the following imports:import_virtual_com_headersimport_virtual_com_code

     

  3. One last thing to do is make sure we initialise the Debug Console component telling it to use the USB CDC. If you remember we intentionally disabled auto initialising the “fsl_debug_console” in processor expert. This was done for the purpose of providing us the ability to change the device used by the console. So at the start of your main function just after the call to “PE_low_level_init()”, make the call “DbgConsole_Init(BOARD_DEBUG_UART_INSTANCE, DEBUG_UART_BAUD, kDebugConsoleUSBCDC);”.

 

/* ###################################################################
**     Filename    : main.c
**     Project     : K64F_USB_CDC
**     Processor   : MK64FN1M0VLL12
**     Version     : Driver 01.01
**     Compiler    : GNU C Compiler
**     Date/Time   : 2015-12-12, 23:04, # CodeGen: 0
**     Abstract    :
**         Main module.
**         This module contains user's application code.
**     Settings    :
**     Contents    :
**         No public methods
**
** ###################################################################*/
/*!
** @file main.c
** @version 01.01
** @brief
**         Main module.
**         This module contains user's application code.
*/
/*!
**  @addtogroup main_module main module documentation
**  @{
*/
/* MODULE main */

/* Including needed modules to compile this module/procedure */
#include "Cpu.h"
#include "Events.h"
#include "clockMan1.h"
#include "pin_init.h"
#include "osa1.h"
#include "usbFmw1.h"
#include "DbgCs1.h"
#if CPU_INIT_CONFIG
  #include "Init_Config.h"
#endif
/* User includes (#include below this line is not maintained by Processor Expert) */

/*lint -save  -e970 Disable MISRA rule (6.3) checking. */
int main(void)
/*lint -restore Enable MISRA rule (6.3) checking. */
{
  /* Write your local variable definition here */

  /*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/
  PE_low_level_init();
  /*** End of Processor Expert internal initialization.                    ***/

  DbgConsole_Init(BOARD_DEBUG_UART_INSTANCE, DEBUG_UART_BAUD, kDebugConsoleUSBCDC);

  PRINTF("Hello CDC!");

  /*** Don't write any code pass this line, or it will be deleted during code generation. ***/
  /*** RTOS startup code. Macro PEX_RTOS_START is defined by the RTOS component. DON'T MODIFY THIS CODE!!! ***/
  #ifdef PEX_RTOS_START
    PEX_RTOS_START();                  /* Startup of the selected RTOS. Macro is defined by the RTOS component. */
  #endif
  /*** End of RTOS startup code.  ***/
  /*** Processor Expert end of main routine. DON'T MODIFY THIS CODE!!! ***/
  for(;;){}
  /*** Processor Expert end of main routine. DON'T WRITE CODE BELOW!!! ***/
} /*** End of main routine. DO NOT MODIFY THIS TEXT!!! ***/

/* END main */
/*!
** @}
*/
/*
** ###################################################################
**
**     This file was created by Processor Expert 10.5 [05.21]
**     for the Freescale Kinetis series of microcontrollers.
**
** ###################################################################
*/

 

  1. If you try to compile the code now you will get an error saying the Symbol ‘usb_device_board_init’ could not be resolved within the file “virtual_com.c”. If you navigate to the line where this error is caused all that need to be done is to set the value to NULL instead:

 

cdc_config.board_init_callback.callback = NULL;

 

That’s it then, after that you can make “PRINTF”, “SCANF” or “GETCHAR” calls in your code and it will output to the OTG usb port on your board. Please note, you must capitalise the calls to the functions “PRINTF”, “SCANF” or “GETCHAR” as these are specialised versions of the functions that reside inside the “fsl_debug_console.c” file.

 

You can get a copy of this project on my Github repo at https://github.com/wesleyhunter/centaurian/tree/master/Examples/Eclipse/FRDM-K64F/K64F_USB_CDC

 

Good luck, hope this works well for you all.

 

KSDK 1.2.0 _sbrk() function

 

To implement a _sbrk() function simply add the following block of code to your project:

 

void *_sbrk ( uint32_t incr )
{
	extern char   end __asm ("end");
	extern char   heap_limit __asm ("__HeapLimit");
	static char * heap_end;
	char *        prev_heap_end;

	if (heap_end == NULL)
		heap_end = & end;

	prev_heap_end = heap_end;

	heap_end += incr;

  return (void *) prev_heap_end;
}
Advertisements