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:
Sat Apr 23 18:24:07 2016 +0000
Revision:
8:00cefe0d59ed
Basic functionality works over HTTP!

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sissors 8:00cefe0d59ed 1 #ifndef FREESCALEIAP_H
Sissors 8:00cefe0d59ed 2 #define FREESCALEIAP_H
Sissors 8:00cefe0d59ed 3
Sissors 8:00cefe0d59ed 4 #include "mbed.h"
Sissors 8:00cefe0d59ed 5
Sissors 8:00cefe0d59ed 6 #if defined(TARGET_KLXX) | defined(TARGET_K20D50M)
Sissors 8:00cefe0d59ed 7 #define SECTOR_SIZE 1024
Sissors 8:00cefe0d59ed 8 #elif (TARGET_K22F)
Sissors 8:00cefe0d59ed 9 #define SECTOR_SIZE 2048
Sissors 8:00cefe0d59ed 10 #elif defined(TARGET_K64F)
Sissors 8:00cefe0d59ed 11 #define SECTOR_SIZE 4096
Sissors 8:00cefe0d59ed 12 #else
Sissors 8:00cefe0d59ed 13 #warning FreescaleIAP unknown target, using default 1024B
Sissors 8:00cefe0d59ed 14 #define SECTOR_SIZE 1024
Sissors 8:00cefe0d59ed 15 #endif
Sissors 8:00cefe0d59ed 16
Sissors 8:00cefe0d59ed 17 enum IAPCode {
Sissors 8:00cefe0d59ed 18 BoundaryError = -99, //Commands may not span several sectors
Sissors 8:00cefe0d59ed 19 AlignError, //Data must be aligned on longword (two LSBs zero)
Sissors 8:00cefe0d59ed 20 ProtectionError, //Flash sector is protected
Sissors 8:00cefe0d59ed 21 AccessError, //Something went wrong
Sissors 8:00cefe0d59ed 22 CollisionError, //During writing something tried to flash which was written to
Sissors 8:00cefe0d59ed 23 LengthError, //The length must be multiples of 4
Sissors 8:00cefe0d59ed 24 RuntimeError,
Sissors 8:00cefe0d59ed 25 EraseError, //The flash was not erased before writing to it
Sissors 8:00cefe0d59ed 26 Success = 0
Sissors 8:00cefe0d59ed 27 };
Sissors 8:00cefe0d59ed 28
Sissors 8:00cefe0d59ed 29 /** Erase a flash sector
Sissors 8:00cefe0d59ed 30 *
Sissors 8:00cefe0d59ed 31 * The size erased depends on the used device
Sissors 8:00cefe0d59ed 32 *
Sissors 8:00cefe0d59ed 33 * @param address address in the sector which needs to be erased
Sissors 8:00cefe0d59ed 34 * @param return Success if no errors were encountered, otherwise one of the error states
Sissors 8:00cefe0d59ed 35 */
Sissors 8:00cefe0d59ed 36 IAPCode erase_sector(int address);
Sissors 8:00cefe0d59ed 37
Sissors 8:00cefe0d59ed 38 /** Program flash
Sissors 8:00cefe0d59ed 39 *
Sissors 8:00cefe0d59ed 40 * Before programming the used area needs to be erased. The erase state is checked
Sissors 8:00cefe0d59ed 41 * before programming, and will return an error if not erased.
Sissors 8:00cefe0d59ed 42 *
Sissors 8:00cefe0d59ed 43 * @param address starting address where the data needs to be programmed (must be longword alligned: two LSBs must be zero)
Sissors 8:00cefe0d59ed 44 * @param data pointer to array with the data to program
Sissors 8:00cefe0d59ed 45 * @param length number of bytes to program (must be a multiple of 4. must be a multiple of 8 when K64F)
Sissors 8:00cefe0d59ed 46 * @param return Success if no errors were encountered, otherwise one of the error states
Sissors 8:00cefe0d59ed 47 */
Sissors 8:00cefe0d59ed 48 IAPCode program_flash(int address, char *data, unsigned int length);
Sissors 8:00cefe0d59ed 49
Sissors 8:00cefe0d59ed 50 /**
Sissors 8:00cefe0d59ed 51 * Returns size of flash memory
Sissors 8:00cefe0d59ed 52 *
Sissors 8:00cefe0d59ed 53 * This is the first address which is not flash
Sissors 8:00cefe0d59ed 54 *
Sissors 8:00cefe0d59ed 55 * @param return length of flash memory in bytes
Sissors 8:00cefe0d59ed 56 */
Sissors 8:00cefe0d59ed 57 uint32_t flash_size(void);
Sissors 8:00cefe0d59ed 58
Sissors 8:00cefe0d59ed 59 #endif