What if i have a processor expert project of my older freedom board and want to migrate or work on the same existing project on newer version of any freedom board? Do need to create from scratch till end: let’s see in this tutorial how to migrate between FRDM-KL25FRDM-KL25 to FRDM-KL46ZFRDM-KL46Z freedom board using Processor Expert tool.
Processor Expert provides an efficient development environment for rapid application development of the embedded applications. You can develop embedded applications for a wide range of microcontrollers and microprocessor systems using Processor Expert.
Processor Expert is integrated as a plug-in into the CodeWarrior IDE. You can access Processor Expert from the CodeWarrior IDE using the Processor Expert menu in the CodeWarrior IDE menu bar. The Processor Expert plug-in generates code from the embedded components and the CodeWarrior IDE manages the project files and compilation and debug processes.
Processor Expert generates all drivers during the code generation process. The generated files are automatically inserted into the active (default) target in the CodeWarrior project.
As a pre-requisite to work on this one should have sample code of KL25Z you can download this from HERE (alternately I have attached the project for quick reference) And your new Freedom board, as in my case I am having FRDM-KL46ZFRDM-KL46Z and latest version of Code Warrior tool.
A free version of Codewarrior can be downloaded following the link below in the Downloads section:
The Evaluation version is a 30 days Limited version and the Special Edition is Code Size Limited version (64KB for Kinetis MCUs with an ARM Cortex-M0+ core and 128KB for the Kinetis MCUs with an ARM Cortex-M4 core)
Before we start here are the features of our New FRDM-KL46ZFRDM-KL46Z board stating which all the peripherals available are on board to work on: Refer to the link for more details:
- MKL46Z256VLLZ4MKL46Z256VLLZ4 MCU (48 MHz, 256KB Flash, 32 KB RAM, Low power, 100LQFP package)
- Dual role USB interface with mini-B USB connector
- Open SDA
- 4 digit segment LCD module
- Capacitive touch slider
- Ambient light sensor
- MMA8451QMMA8451Q accelerometer
- MAG3110 MAG3110 Magnetometer
- 2 user LEDs
- 2 user push buttons
- Flexible power supply options – USB, coin cell battery, external source
- Battery-ready, power-measurement access points
- Easy access to MCU I/O via Arduino R3 compatible I/O connectors
- Programmable OpenSDA debug interface with multiple applications available including:
- Mass storage device flash programming interface
- P&E Debug interface provides run-control debugging and compatibility with IDE tools
- CMSIS-DAP interface: new ARM standard for embedded debug interface
- Data logging application
- Arduino R3 compatibility
Before we start on our project make sure the board is in Debug mode (refer to the blog how to load in Debug mode using OpenSDA)
Now let’s start on migrating the available sample code of KL25Z, I have selected the “pwm_led” project which is located in folder “~\Downloads\KL25 Sample Code\kl25_sc_rev10\klxx-sc-pex\projects\pwm_led\cw”
Open this project in code warrior in current workspace (you can drag and drop the “.project” present in pwm_led project folder).
I have rename the project as “pwm_led-KL25” and saved a copy in my current workspace to differentiate the original one.
You can see from above snap shot i have opened the project it has kinetis family MCU ‘MKL25Z128VLK4’ running at 8 MHz connected to external crystal, PEE(PLL engaged external) as MCG mode and core clock is 48 MHz, Bus clock is 24 MHz.
The components present in this project are module "PeriodicInterrupt" (component TimerUnit_LDD), Module "PWMTimerRG" (component name ‘PWMTimerRG’ of type TimerUnit_LDD ), and Module "PWMTimerB" (component name PWMTimerB of type TimerUnit_LDD).
Now create a new project for KL46Z board following below procedure (refer to the blog link for “how to create project using processor expert” )
- In the CodeWarrior, click File menu and select New > Bareboard Project in order to create a new project. The Project Wizard appears. Enter the name of the project “pwm-led migrate-kl46” and click Next.
- Now select the MCU exist on our KL46 board it is “MKL46Z256”
Kinetis L Series-> KL4x Family->KL46Z(48 MHz) Family->MKL46Z256 then Click Next.
- Select OpenSDA option to connect for this board for debugging and programming, then click Next.
- Select ‘Processor Expert’ option as we are creating the project using Processor Expert then click ‘Finish’
I have created the project by name “pwm-led migrate-kl46” as shown below is the component inspector showing CPU with default settings:
First we need to configure CPU parameter settings as shown below:
Under clock Settings->
System Oscillator: Enabled
Clock Source: External Oscillator
Clock Frequency: 8 MHz (as this board is connected to external crystal oscillator )
Under clock source settings-> clock source settings 0-> MCG settings->
MCG mode: FEI (FLL engaged internal)
FLL settings->FLL output[MHz] : 47.972352
Then automatically MCG output[MHz] gets selected to 47.972352
Then under Clock configurations->Clock configuration 0->System clocks->
Set
Core clock: 47.972352 MHz
Bus clock: 23.986176 MHz
Then all other parameters which were highlighted in RED gets cleared which means the settings are correct. These settings are as shown in above figure.
Since now our project skeleton is ready (i.e no component module peripherals has been added to our project) we need to add the required peripheral component module as per our requirement.
Copy all the three components present in KL25Z project as shown:
Paste the copied 3 components to our created project folder “pwm-led migrate-kl46” under ‘Components’ window as shown below:
Now select the first component ‘PeriodicInterrupt’ and change the settings as shown:
This is a Periodic interrupt timer module with counter direction as Down count, it uses internal clock source of 24 MHz as counter frequency. Make sure the interrupt is enabled and the period of the counter is set to 50 us (i.e this PIT will generate an interrupt on every 50us)
Note: there is an RGB LED connected to port pins in KL25Z board but in KL46Z board only 2 LED’s are connected no RGB is present in this. RED connected to PTE29 and Green is connected to PTD5, in order to connect the third LED i.e blue we need to connect it manually.
The second component is “PWMTimerRG” of type “TimerUnit_LDD” which is connected to RED and GREEN LED of KL25Z board its setting are as shown below:
This module is connected to TPM0 Flex Timer Module which runs in ‘UP” counter direction with period of 2.7306 ms with its interrupt disabled.
Further to this timer module we are taking 2 outputs by connecting them to two channels, one is connected to channel-2 (TPM0_C2) of timer module which leads to o/p port pin PTE29 and another connected to channel-5 (TPM0_C5) of timer module which in turn connects to PTD5 port pin.
We have selected these channel output port pins because the physical LED’s are connected in the board to particular GPIO pins i.e
Refer to below schematic there are two LED’s exist on board Red and Green connected to Port-E 29th bit (PTE29) and Port-D 5th bit (PTD5).
LED |
KL46 |
Green (LED1) |
PTD5 |
Red (LED2) |
PTE29 |
We should run this timer as PWM to do so it has to run in ‘compare’ mode. As this module is 16 bit timer running counts from 0000 to FFFF (0 to 65535 timer-ticks) and initial offset is given as ‘0’ timer-ticks so that the PWM starts from 0% of dutycycle. We access this ‘offset’ variable during programming and continuously change its value varying the duty cycle to 100%.
Next coming to third module “PWMTimerB” it is connected to ‘Blue’ LED in KL25Z board we need to connect this manually in case of KL46Z board and we are connecting it to PTE23 port pin which internal connected to TPM2- channel-1, its period is 2.7306 ms and ‘offset’ is set to ‘0’.
The PWM waveform will look like the below picture:
Now all our module settings have been done and we can now ‘generate’ the project to generate Processor Expert code, which creates all supporting header files and API’s required.
Now it’s time for us to write our application code, since RGB LED is not present in KL46Z board i am going to write my own application where i will be varying the brightness of LED present in KL46Z (i.e Red and Green) through varying the PWM duty cycle.
The place where i need to write my code is file “ProcessorExpert.c” located in ‘sources’ folder in my project folder which is shown in below picture.
Since we are writing fresh lines of code i delete all its content by pressing Ctrl-A and Delete then paste below line of code.
/* ###################################################################
** Filename : ProcessorExpert.c
** Project : ProcessorExpert
** Processor : MKL46Z256VMC4
** Version : Driver 01.01
** Compiler : GNU C Compiler
** Date/Time : 2014-06-06, 08:06, # CodeGen: 0
** Abstract :
** Main module.
** This module contains user's application code.
** Settings :
** Contents :
** No public methods
**
** ###################################################################*/
/*!
** @file ProcessorExpert.c
** @version 01.01
** @brief
** Main module.
** This module contains user's application code.
*/
/*!
** @addtogroup ProcessorExpert_module ProcessorExpert module documentation
** @{
*/
/* MODULE ProcessorExpert */
/* Including needed modules to compile this module/procedure */
#include "Cpu.h"
#include "Events.h"
#include "PeriodicInterrupt.h"
#include "PWMTimerRG.h"
#include "PWMTimerB.h"
/* Including shared modules, which are used for whole project */
#include "PE_Types.h"
#include "PE_Error.h"
#include "PE_Const.h"
#include "IO_Map.h"
volatile bool PeriodicEvent = FALSE; // interrupt for every 50us to write each inc timer value (0 to 65535 timer value)
LDD_TDeviceData *PWMTimerRG_DeviceData, *PWMTimerB_DeviceData;
LDD_TDeviceData *PeriodicInterrupt_DeviceData;
const int RedChannel = 0;
const int GreenChannel = 1;
const int BlueChannel = 0;
/******************************************************************************/
int main(void)
{
LDD_TError Error;
int PulseOffset = 0;
int dir = 0;
/*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/
PE_low_level_init();
/*** End of Processor Expert internal initialization. ***/
/* Intialize the timers */
PWMTimerRG_DeviceData = PWMTimerRG_Init(NULL);
PWMTimerB_DeviceData = PWMTimerB_Init(NULL);
PeriodicInterrupt_DeviceData = PeriodicInterrupt_Init(NULL);
/* Set initial compare value */
PWMTimerRG_SetOffsetTicks(PWMTimerRG_DeviceData, RedChannel, PulseOffset);
PWMTimerRG_SetOffsetTicks(PWMTimerRG_DeviceData, GreenChannel, PulseOffset);
PWMTimerB_SetOffsetTicks(PWMTimerB_DeviceData, BlueChannel, PulseOffset);
/* Turn on the timers */
Error = PWMTimerRG_Enable(PWMTimerRG_DeviceData);
if (Error != ERR_OK)
PE_DEBUGHALT();
Error = PWMTimerB_Enable(PWMTimerB_DeviceData);
if (Error != ERR_OK)
PE_DEBUGHALT();
Error = PeriodicInterrupt_Enable(PeriodicInterrupt_DeviceData);
if (Error != ERR_OK)
PE_DEBUGHALT();
PulseOffset = 0;
while (1)
{
if (PeriodicEvent) {
if(dir == 0) //incremental intensity
{
PulseOffset = PulseOffset + 1;
if(PulseOffset >= 65535)
{
dir = 1;
}
}
else // dir == 1 decrementing intensity
{
PulseOffset = PulseOffset - 1;
if(PulseOffset == 0)
dir = 0;
}
PWMTimerRG_SetOffsetTicks(PWMTimerRG_DeviceData, RedChannel,PulseOffset);
PWMTimerRG_SetOffsetTicks(PWMTimerRG_DeviceData, GreenChannel, PulseOffset);
PeriodicEvent = FALSE;
}
}
/*** 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!!! ***/
return 0;
} /*** End of main routine. DO NOT MODIFY THIS TEXT!!! ***/
/* END ProcessorExpert */
/*
** ###################################################################
**
** This file was created by Processor Expert 10.0 [05.03]
** for the Freescale Kinetis series of microcontrollers.
**
** ###################################################################
*/
Code explanation:
First initialise the timer as shown below line of code:
PWMTimerRG_DeviceData = PWMTimerRG_Init(NULL); // initialise timer concern to Red and Green LED
PWMTimerB_DeviceData = PWMTimerB_Init(NULL); // initialise timer concern to Blue LED
PeriodicInterrupt_DeviceData = PeriodicInterrupt_Init(NULL);// initialise the Periodic interrupt timer
Next we are giving initial value to the PWM output channels (Red channel, Green channel, Blue channel)
Function "PWMTimerRG_SetOffsetTicks()" does this job
'PulseOffset' = 0 initially so PWM starts from 0 value
PWMTimerRG_SetOffsetTicks(PWMTimerRG_DeviceData, RedChannel, PulseOffset);
PWMTimerRG_SetOffsetTicks(PWMTimerRG_DeviceData, GreenChannel, PulseOffset);
PWMTimerB_SetOffsetTicks(PWMTimerB_DeviceData, BlueChannel, PulseOffset);
Next we need to turn on the timers this is done using the function "PWMTimerRG_Enable()"
In while(1) loop we are writing PWM value from 0 to 65535 and again from 65535 to 0 using the function "PWMTimerRG_SetOffsetTicks()". this is done every periodically 50 us. 'PulseOffset' is variable which will take care of writing the PWM cycle value
As mentioned earlier the Periodic interrupt timer module will be generating an interrupt for every 50 us we need to create a variable “PeriodicEvent” as shown below in the file “Events.c”
extern volatile bool PeriodicEvent;
Add below lines of code inside a function as shown
“void PeriodicInterrupt_OnCounterRestart(LDD_TUserData *UserDataPtr)”
void PeriodicInterrupt_OnCounterRestart(LDD_TUserData *UserDataPtr)
{
/* Write your code here ... */
PeriodicEvent = TRUE;
}
Save all the files then clean and Build the project as shown below:
The build progress is shown below:
Now connect the board to USB through OpenSDA port of the board and Run the project as shown below:
You can see Run progress bar as shown below:
Below is the console window which shows the status of execution process
You can see the output which shows 2 LED’s Red and Green intensity is increased from 0% to 100% and again coming back from 100% to 0%. You can see the output waveform on CRO by connecting at led terminal as shown:
The output waveform seen through oscilloscope is as shown below along with setup:
Watch the video output which is attached in this blog. Created supporting project files have been enclosed too for quick reference.
So it is concluded that by using the processor expert migration of the project from different Freedom platform boards made easy.