A fork of Erik Olieman's bootloader for the KL05Z32. The bootloader is placed in the 29th sector allowing for 28kB of program memory. The 32nd sector is left empty after the bootloader to allow for use of the non volatile storage without the risk of overwriting it during serial firmware update.

Dependencies:   mbed-dev

Fork of Bootloader_K64F by Erik -

This is a simple boot loader which resides at the end of the flash banks of your uController. It has be ported to work with the KL05Z. Porting the code to another Free scale uController requires the following changes:

Step 1 Change the address of the following function address

If your uController of choice has a flash size other than 32kB then you will likely want to change the addresses of following functions (current addresses displayed).

bootloader.cpp
0x7000 bootloader
0x7080 setupserial
0x70A0 write

FreescaleIAP.cpp
0x7268 erase_sector
0x7300 program_flash
0x7500 flash_size
0x7600 program_word
0x7700 run_command
0x7800 check_boundary
0x7900 check_align
0x7A00 verify_erased
0x7B00 check_error

Step 2 Follow the serial_api HAL file of your target

You will be unable to access anything that you don't define yourself in the bootloader. For this reason you need to create a function for serial. Look up and follow your target's serial_api.c file.

__attribute__((section(".ARM.__at_0x7080"))) static void setupserial(void) {
        //Setup USBRX/USBTX pins (PTB1/PTB2)
        //Enable Port B Clock
        SIM->SCGC5 |= 1 <<SIM_SCGC5_PORTB_SHIFT;                   
        //Select MCGFLLCLK clock
        SIM->SOPT2 |= 1 <<SIM_SOPT2_UART0SRC_SHIFT;
        //Select Pins PB1 & PB2 to their ALT3 function (RX & TX respectively)
        PORTB->PCR[1] = (PORTB->PCR[1] & ~0x700) | (3 << 8);
        PORTB->PCR[2] = (PORTB->PCR[2] & ~0x700) | (3 << 8);
        //Set UART0 Clock to be enabled
        SIM->SCGC4 |= SIM_SCGC4_UART0_MASK;
        //Set UART Baud Rate Register
        //Value's gathered expirimentally   
        UART0->BDH = 1;
        UART0->BDL = 56;   
        //Enable UART0
        UART0->C2 |= (UARTLP_C2_RE_MASK | UARTLP_C2_TE_MASK);
}

To set the correct baudrate you need to determine the right values for BDH & BDL registers for your clock speed. An easy way to do that is by simply printing them with the clock speed that you want like so:

#include "mbed.h"

Serial pc(USBTX, USBrX);

int main()
{
    while (1) {
        pc.printf("BDH: %d \n", UART0->BDH); // print the value of BDH Register
        pc.printf("BDL: %d \n", UART0->BDL); // print the value of BDL Register
        pc.printf("SOPT2: %d \n", SIM->SOPT2); // print the value of SOPT2 Register
        pc.printf("SCGC5: %d \n", SIM->SCGC5); // print the value of SCGC5 Register
        pc.printf("SCGC4: %d \n", SIM->SCGC4); // print the value of SCGC4 Register
        pc.printf("C2: %d \n", UART0->C2); // print the value of C2 Register
        pc.printf("C4: %d \n", UART0->C4); // print the value of C4 Register
        wait(.5);
    }
}

Step 3 Include bootloader.cpp in your first firmware

Before you can update firmware using serial you first must update the firmware using SWD along with the bootloader included in your binary.

#include "mbed.h"
extern void bootloader(void);
//...
main(){
//...
bootloader();
}

Step 4 Include reference to bootloader in serial updates

Once the bootloader is on the uControler you should not include the bootloader in binaries that you want to update over serial. Instead you can access the bootloader by using the following:

#include "mbed.h"

void *(*bootloader)(void) = (void *(*)(void))0x7001; //Address of bootloader + 1 (For some reason)
//...
main(){
//...
bootloader();
}

IF YOU ARE PROGRAMMING USING A PROGRAMMER (SWD OR JTAG) AND NOT SERIAL MAKE SURE TO INCLUDE THE BOOTLOADER OR OTHERWISE IT WILL MOST LIKELY BE ERASED OR OVERWRITTEN

Committer:
Sissors
Date:
Fri Aug 22 15:14:52 2014 +0000
Revision:
0:9396d3376435
Child:
1:782a3ddc329e
versie 1

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sissors 0:9396d3376435 1 #include "mbed.h"
Sissors 0:9396d3376435 2 #include "FastPWM.h"
Sissors 0:9396d3376435 3 #include "FastIO.h"
Sissors 0:9396d3376435 4
Sissors 0:9396d3376435 5 #define TIME_REG LPC_TIM2->TC
Sissors 0:9396d3376435 6 FastPWM output(p21);
Sissors 0:9396d3376435 7 FastIn<p22> input;
Sissors 0:9396d3376435 8 void initTimer2();
Sissors 0:9396d3376435 9
Sissors 0:9396d3376435 10
Sissors 0:9396d3376435 11 int main()
Sissors 0:9396d3376435 12 {
Sissors 0:9396d3376435 13 //Ticks to be measured
Sissors 0:9396d3376435 14 unsigned int tick_width = 100;
Sissors 0:9396d3376435 15
Sissors 0:9396d3376435 16 unsigned int measured_timed[3];
Sissors 0:9396d3376435 17
Sissors 0:9396d3376435 18 initTimer2();
Sissors 0:9396d3376435 19
Sissors 0:9396d3376435 20 while (true) {
Sissors 0:9396d3376435 21 //Setup PWM
Sissors 0:9396d3376435 22 output.period_ticks(tick_width);
Sissors 0:9396d3376435 23 output.pulsewidth_ticks(tick_width/2);
Sissors 0:9396d3376435 24 wait_us(10);
Sissors 0:9396d3376435 25
Sissors 0:9396d3376435 26 //Start measuring at first rising edge
Sissors 0:9396d3376435 27 while(!input);
Sissors 0:9396d3376435 28 while(input);
Sissors 0:9396d3376435 29 measured_timed[0] = TIME_REG;
Sissors 0:9396d3376435 30 while(!input);
Sissors 0:9396d3376435 31 measured_timed[1] = TIME_REG;
Sissors 0:9396d3376435 32 while(input);
Sissors 0:9396d3376435 33 measured_timed[2] = TIME_REG;
Sissors 0:9396d3376435 34
Sissors 0:9396d3376435 35 printf("\r\nPulsewidth = %d ticks, which is %2.1fMHz\r\n", tick_width, (float)SystemCoreClock / (float)tick_width / 1000000.0f);
Sissors 0:9396d3376435 36 printf("Measured period = %d ticks, pulsewidth = %d ticks\r\n", measured_timed[2]-measured_timed[0], measured_timed[1]-measured_timed[0]);
Sissors 0:9396d3376435 37
Sissors 0:9396d3376435 38 //If more than 20% too large, consider it a fail
Sissors 0:9396d3376435 39 if ((measured_timed[2] - measured_timed[0]) > 1.2 * tick_width) {
Sissors 0:9396d3376435 40 printf("Period setting failed\r\n");
Sissors 0:9396d3376435 41 while(1);
Sissors 0:9396d3376435 42 }
Sissors 0:9396d3376435 43
Sissors 0:9396d3376435 44 //Setup next tick
Sissors 0:9396d3376435 45 tick_width--;
Sissors 0:9396d3376435 46
Sissors 0:9396d3376435 47 }
Sissors 0:9396d3376435 48 }
Sissors 0:9396d3376435 49
Sissors 0:9396d3376435 50 //Semi copy-pasted from: https://mbed.org/users/garyr/code/Counter/file/e619b6823668/Timer2.cpp
Sissors 0:9396d3376435 51 //We init timer at full clock speed, don't do anything else
Sissors 0:9396d3376435 52 void initTimer2() {
Sissors 0:9396d3376435 53 LPC_SC->PCONP |= (1<<22); // Power on the Timer2
Sissors 0:9396d3376435 54 LPC_SC->PCLKSEL1 &= ~(3<<12);
Sissors 0:9396d3376435 55 LPC_SC->PCLKSEL1 |= (1<<12); // Select CCLK for Timer2
Sissors 0:9396d3376435 56 LPC_TIM2->TCR = 2;
Sissors 0:9396d3376435 57 LPC_TIM2->TCR = 1; // Enable Timer2
Sissors 0:9396d3376435 58 }