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:
Dot
Date:
Mon Jul 18 06:08:23 2016 +0000
Revision:
18:c9396799d565
Parent:
16:30f4c724da60
Found using printf of serial and hard coded UART baud rate.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sissors 8:00cefe0d59ed 1 #include "FreescaleIAP.h"
Sissors 8:00cefe0d59ed 2
Sissors 8:00cefe0d59ed 3 //#define IAPDEBUG
Sissors 8:00cefe0d59ed 4
Sissors 8:00cefe0d59ed 5 #ifdef TARGET_K64F
Sissors 8:00cefe0d59ed 6 //For K64F
Sissors 8:00cefe0d59ed 7 # include "MK64F12.h"
Sissors 8:00cefe0d59ed 8 # define USE_ProgramPhrase 1
Sissors 8:00cefe0d59ed 9 # define FTFA FTFE
Sissors 8:00cefe0d59ed 10 # define FTFA_FSTAT_FPVIOL_MASK FTFE_FSTAT_FPVIOL_MASK
Sissors 8:00cefe0d59ed 11 # define FTFA_FSTAT_ACCERR_MASK FTFE_FSTAT_ACCERR_MASK
Sissors 8:00cefe0d59ed 12 # define FTFA_FSTAT_RDCOLERR_MASK FTFE_FSTAT_RDCOLERR_MASK
Sissors 8:00cefe0d59ed 13 # define FTFA_FSTAT_CCIF_MASK FTFE_FSTAT_CCIF_MASK
Sissors 8:00cefe0d59ed 14 # define FTFA_FSTAT_MGSTAT0_MASK FTFE_FSTAT_MGSTAT0_MASK
Sissors 8:00cefe0d59ed 15 #else
Sissors 8:00cefe0d59ed 16 //Different names used on at least the K20:
Sissors 8:00cefe0d59ed 17 # ifndef FTFA_FSTAT_FPVIOL_MASK
Sissors 8:00cefe0d59ed 18 # define FTFA FTFL
Sissors 8:00cefe0d59ed 19 # define FTFA_FSTAT_FPVIOL_MASK FTFL_FSTAT_FPVIOL_MASK
Sissors 8:00cefe0d59ed 20 # define FTFA_FSTAT_ACCERR_MASK FTFL_FSTAT_ACCERR_MASK
Sissors 8:00cefe0d59ed 21 # define FTFA_FSTAT_RDCOLERR_MASK FTFL_FSTAT_RDCOLERR_MASK
Sissors 8:00cefe0d59ed 22 # define FTFA_FSTAT_CCIF_MASK FTFL_FSTAT_CCIF_MASK
Sissors 8:00cefe0d59ed 23 # define FTFA_FSTAT_MGSTAT0_MASK FTFL_FSTAT_MGSTAT0_MASK
Sissors 8:00cefe0d59ed 24 # endif
Sissors 8:00cefe0d59ed 25 #endif
Sissors 8:00cefe0d59ed 26
Sissors 8:00cefe0d59ed 27
Sissors 8:00cefe0d59ed 28 enum FCMD {
Sissors 8:00cefe0d59ed 29 Read1s = 0x01,
Sissors 8:00cefe0d59ed 30 ProgramCheck = 0x02,
Sissors 8:00cefe0d59ed 31 ReadResource = 0x03,
Sissors 8:00cefe0d59ed 32 ProgramLongword = 0x06,
Sissors 8:00cefe0d59ed 33 ProgramPhrase = 0x07,
Sissors 8:00cefe0d59ed 34 EraseSector = 0x09,
Sissors 8:00cefe0d59ed 35 Read1sBlock = 0x40,
Sissors 8:00cefe0d59ed 36 ReadOnce = 0x41,
Sissors 8:00cefe0d59ed 37 ProgramOnce = 0x43,
Sissors 8:00cefe0d59ed 38 EraseAll = 0x44,
Sissors 8:00cefe0d59ed 39 VerifyBackdoor = 0x45
Sissors 8:00cefe0d59ed 40 };
Sissors 8:00cefe0d59ed 41
Sissors 8:00cefe0d59ed 42 inline void run_command(void);
Sissors 8:00cefe0d59ed 43 bool check_boundary(int address, unsigned int length);
Sissors 8:00cefe0d59ed 44 bool check_align(int address);
Sissors 8:00cefe0d59ed 45 IAPCode verify_erased(int address, unsigned int length);
Sissors 8:00cefe0d59ed 46 IAPCode check_error(void);
Sissors 8:00cefe0d59ed 47 IAPCode program_word(int address, char *data);
Sissors 8:00cefe0d59ed 48
Dot 18:c9396799d565 49 __attribute__((section(".ARM.__at_0x7268"))) IAPCode erase_sector(int address) {
Sissors 8:00cefe0d59ed 50 #ifdef IAPDEBUG
Sissors 8:00cefe0d59ed 51 printf("IAP: Erasing at %x\r\n", address);
Sissors 8:00cefe0d59ed 52 #endif
Sissors 8:00cefe0d59ed 53 if (check_align(address))
Sissors 8:00cefe0d59ed 54 return AlignError;
Sissors 8:00cefe0d59ed 55
Sissors 8:00cefe0d59ed 56 //Setup command
Sissors 8:00cefe0d59ed 57 FTFA->FCCOB0 = EraseSector;
Sissors 8:00cefe0d59ed 58 FTFA->FCCOB1 = (address >> 16) & 0xFF;
Sissors 8:00cefe0d59ed 59 FTFA->FCCOB2 = (address >> 8) & 0xFF;
Sissors 8:00cefe0d59ed 60 FTFA->FCCOB3 = address & 0xFF;
Sissors 8:00cefe0d59ed 61
Sissors 8:00cefe0d59ed 62 run_command();
Sissors 8:00cefe0d59ed 63
Sissors 8:00cefe0d59ed 64 return check_error();
Sissors 8:00cefe0d59ed 65 }
Sissors 8:00cefe0d59ed 66
Dot 15:89e2c76e5eed 67 __attribute__((section(".ARM.__at_0x7300"))) IAPCode program_flash(int address, char *data, unsigned int length) {
Sissors 8:00cefe0d59ed 68 #ifdef IAPDEBUG
Sissors 8:00cefe0d59ed 69 printf("IAP: Programming flash at %x with length %d\r\n", address, length);
Sissors 8:00cefe0d59ed 70 #endif
Sissors 8:00cefe0d59ed 71 if (check_align(address))
Sissors 8:00cefe0d59ed 72 return AlignError;
Sissors 8:00cefe0d59ed 73
Sissors 8:00cefe0d59ed 74 IAPCode eraseCheck = verify_erased(address, length);
Sissors 8:00cefe0d59ed 75 if (eraseCheck != Success)
Sissors 8:00cefe0d59ed 76 return eraseCheck;
Sissors 8:00cefe0d59ed 77
Sissors 8:00cefe0d59ed 78 IAPCode progResult;
Sissors 8:00cefe0d59ed 79 #ifdef USE_ProgramPhrase
Sissors 8:00cefe0d59ed 80 for (int i = 0; i < length; i+=8) {
Sissors 8:00cefe0d59ed 81 progResult = program_word(address + i, data + i);
Sissors 8:00cefe0d59ed 82 if (progResult != Success)
Sissors 8:00cefe0d59ed 83 return progResult;
Sissors 8:00cefe0d59ed 84 }
Sissors 8:00cefe0d59ed 85 #else
Sissors 8:00cefe0d59ed 86 for (int i = 0; i < length; i+=4) {
Sissors 8:00cefe0d59ed 87 progResult = program_word(address + i, data + i);
Sissors 8:00cefe0d59ed 88 if (progResult != Success)
Sissors 8:00cefe0d59ed 89 return progResult;
Sissors 8:00cefe0d59ed 90 }
Sissors 8:00cefe0d59ed 91 #endif
Sissors 8:00cefe0d59ed 92 return Success;
Sissors 8:00cefe0d59ed 93 }
Sissors 8:00cefe0d59ed 94
Dot 15:89e2c76e5eed 95 __attribute__((section(".ARM.__at_0x7500"))) uint32_t flash_size(void) {
Sissors 8:00cefe0d59ed 96 uint32_t retval = (SIM->FCFG2 & 0x7F000000u) >> (24-13);
Sissors 8:00cefe0d59ed 97 if (SIM->FCFG2 & (1<<23)) //Possible second flash bank
Sissors 8:00cefe0d59ed 98 retval += (SIM->FCFG2 & 0x007F0000u) >> (16-13);
Sissors 8:00cefe0d59ed 99 return retval;
Sissors 8:00cefe0d59ed 100 }
Sissors 8:00cefe0d59ed 101
Dot 15:89e2c76e5eed 102 __attribute__((section(".ARM.__at_0x7600"))) IAPCode program_word(int address, char *data) {
Sissors 8:00cefe0d59ed 103 #ifdef IAPDEBUG
Sissors 8:00cefe0d59ed 104 #ifdef USE_ProgramPhrase
Sissors 8:00cefe0d59ed 105 printf("IAP: Programming word at %x, %d - %d - %d - %d - %d - %d - %d - %d\r\n", address, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
Sissors 8:00cefe0d59ed 106 #else
Sissors 8:00cefe0d59ed 107 printf("IAP: Programming word at %x, %d - %d - %d - %d\r\n", address, data[0], data[1], data[2], data[3]);
Sissors 8:00cefe0d59ed 108 #endif
Sissors 8:00cefe0d59ed 109
Sissors 8:00cefe0d59ed 110 #endif
Sissors 8:00cefe0d59ed 111 if (check_align(address))
Sissors 8:00cefe0d59ed 112 return AlignError;
Sissors 8:00cefe0d59ed 113 #ifdef USE_ProgramPhrase
Sissors 8:00cefe0d59ed 114 FTFA->FCCOB0 = ProgramPhrase;
Sissors 8:00cefe0d59ed 115 FTFA->FCCOB1 = (address >> 16) & 0xFF;
Sissors 8:00cefe0d59ed 116 FTFA->FCCOB2 = (address >> 8) & 0xFF;
Sissors 8:00cefe0d59ed 117 FTFA->FCCOB3 = address & 0xFF;
Sissors 8:00cefe0d59ed 118 FTFA->FCCOB4 = data[3];
Sissors 8:00cefe0d59ed 119 FTFA->FCCOB5 = data[2];
Sissors 8:00cefe0d59ed 120 FTFA->FCCOB6 = data[1];
Sissors 8:00cefe0d59ed 121 FTFA->FCCOB7 = data[0];
Sissors 8:00cefe0d59ed 122 FTFA->FCCOB8 = data[7];
Sissors 8:00cefe0d59ed 123 FTFA->FCCOB9 = data[6];
Sissors 8:00cefe0d59ed 124 FTFA->FCCOBA = data[5];
Sissors 8:00cefe0d59ed 125 FTFA->FCCOBB = data[4];
Sissors 8:00cefe0d59ed 126 #else
Sissors 8:00cefe0d59ed 127 //Setup command
Sissors 8:00cefe0d59ed 128 FTFA->FCCOB0 = ProgramLongword;
Sissors 8:00cefe0d59ed 129 FTFA->FCCOB1 = (address >> 16) & 0xFF;
Sissors 8:00cefe0d59ed 130 FTFA->FCCOB2 = (address >> 8) & 0xFF;
Sissors 8:00cefe0d59ed 131 FTFA->FCCOB3 = address & 0xFF;
Sissors 8:00cefe0d59ed 132 FTFA->FCCOB4 = data[3];
Sissors 8:00cefe0d59ed 133 FTFA->FCCOB5 = data[2];
Sissors 8:00cefe0d59ed 134 FTFA->FCCOB6 = data[1];
Sissors 8:00cefe0d59ed 135 FTFA->FCCOB7 = data[0];
Sissors 8:00cefe0d59ed 136 #endif
Sissors 8:00cefe0d59ed 137 run_command();
Sissors 8:00cefe0d59ed 138
Sissors 8:00cefe0d59ed 139 return check_error();
Sissors 8:00cefe0d59ed 140 }
Sissors 8:00cefe0d59ed 141
Sissors 8:00cefe0d59ed 142 /* Clear possible flags which are set, run command, wait until done */
Dot 15:89e2c76e5eed 143 __attribute__((section(".ARM.__at_0x7700"))) inline void run_command(void) {
Sissors 8:00cefe0d59ed 144 //Clear possible old errors, start command, wait until done
Sissors 8:00cefe0d59ed 145 __disable_irq(); //Disable IRQs, preventing IRQ routines from trying to access flash (thanks to https://mbed.org/users/mjr/)
Sissors 8:00cefe0d59ed 146 FTFA->FSTAT = FTFA_FSTAT_FPVIOL_MASK | FTFA_FSTAT_ACCERR_MASK | FTFA_FSTAT_RDCOLERR_MASK;
Sissors 8:00cefe0d59ed 147 FTFA->FSTAT = FTFA_FSTAT_CCIF_MASK;
Sissors 8:00cefe0d59ed 148 while (!(FTFA->FSTAT & FTFA_FSTAT_CCIF_MASK));
Sissors 8:00cefe0d59ed 149 __enable_irq();
Sissors 8:00cefe0d59ed 150 }
Sissors 8:00cefe0d59ed 151
Sissors 8:00cefe0d59ed 152
Sissors 8:00cefe0d59ed 153
Sissors 8:00cefe0d59ed 154 /* Check if no flash boundary is violated
Sissors 8:00cefe0d59ed 155 Returns true on violation */
Dot 15:89e2c76e5eed 156 __attribute__((section(".ARM.__at_0x7800"))) bool check_boundary(int address, unsigned int length) {
Sissors 8:00cefe0d59ed 157 int temp = (address+length - 1) / SECTOR_SIZE;
Sissors 8:00cefe0d59ed 158 address /= SECTOR_SIZE;
Sissors 8:00cefe0d59ed 159 bool retval = (address != temp);
Sissors 8:00cefe0d59ed 160 #ifdef IAPDEBUG
Sissors 8:00cefe0d59ed 161 if (retval)
Sissors 8:00cefe0d59ed 162 printf("IAP: Boundary violation\r\n");
Sissors 8:00cefe0d59ed 163 #endif
Sissors 8:00cefe0d59ed 164 return retval;
Sissors 8:00cefe0d59ed 165 }
Sissors 8:00cefe0d59ed 166
Sissors 8:00cefe0d59ed 167 /* Check if address is correctly aligned
Sissors 8:00cefe0d59ed 168 Returns true on violation */
Dot 15:89e2c76e5eed 169 __attribute__((section(".ARM.__at_0x7900"))) bool check_align(int address) {
Sissors 8:00cefe0d59ed 170 bool retval = address & 0x03;
Sissors 8:00cefe0d59ed 171 #ifdef IAPDEBUG
Sissors 8:00cefe0d59ed 172 if (retval)
Sissors 8:00cefe0d59ed 173 printf("IAP: Alignment violation\r\n");
Sissors 8:00cefe0d59ed 174 #endif
Sissors 8:00cefe0d59ed 175 return retval;
Sissors 8:00cefe0d59ed 176 }
Sissors 8:00cefe0d59ed 177
Sissors 8:00cefe0d59ed 178 /* Check if an area of flash memory is erased
Sissors 8:00cefe0d59ed 179 Returns error code or Success (in case of fully erased) */
Dot 15:89e2c76e5eed 180 __attribute__((section(".ARM.__at_0x7A00"))) IAPCode verify_erased(int address, unsigned int length) {
Sissors 8:00cefe0d59ed 181 #ifdef IAPDEBUG
Sissors 8:00cefe0d59ed 182 printf("IAP: Verify erased at %x with length %d\r\n", address, length);
Sissors 8:00cefe0d59ed 183 #endif
Sissors 8:00cefe0d59ed 184
Sissors 8:00cefe0d59ed 185 if (check_align(address))
Sissors 8:00cefe0d59ed 186 return AlignError;
Sissors 8:00cefe0d59ed 187
Sissors 8:00cefe0d59ed 188 //Setup command
Sissors 8:00cefe0d59ed 189 FTFA->FCCOB0 = Read1s;
Sissors 8:00cefe0d59ed 190 FTFA->FCCOB1 = (address >> 16) & 0xFF;
Sissors 8:00cefe0d59ed 191 FTFA->FCCOB2 = (address >> 8) & 0xFF;
Sissors 8:00cefe0d59ed 192 FTFA->FCCOB3 = address & 0xFF;
Sissors 8:00cefe0d59ed 193 FTFA->FCCOB4 = (length >> 10) & 0xFF;
Sissors 8:00cefe0d59ed 194 FTFA->FCCOB5 = (length >> 2) & 0xFF;
Sissors 8:00cefe0d59ed 195 FTFA->FCCOB6 = 0;
Sissors 8:00cefe0d59ed 196
Sissors 8:00cefe0d59ed 197 run_command();
Sissors 8:00cefe0d59ed 198
Sissors 8:00cefe0d59ed 199 IAPCode retval = check_error();
Sissors 8:00cefe0d59ed 200 if (retval == RuntimeError) {
Sissors 8:00cefe0d59ed 201 #ifdef IAPDEBUG
Sissors 8:00cefe0d59ed 202 printf("IAP: Flash was not erased\r\n");
Sissors 8:00cefe0d59ed 203 #endif
Sissors 8:00cefe0d59ed 204 return EraseError;
Sissors 8:00cefe0d59ed 205 }
Sissors 8:00cefe0d59ed 206 return retval;
Sissors 8:00cefe0d59ed 207
Sissors 8:00cefe0d59ed 208 }
Sissors 8:00cefe0d59ed 209
Sissors 8:00cefe0d59ed 210 /* Check if an error occured
Sissors 8:00cefe0d59ed 211 Returns error code or Success*/
Dot 15:89e2c76e5eed 212 __attribute__((section(".ARM.__at_0x7B00"))) IAPCode check_error(void) {
Sissors 8:00cefe0d59ed 213 if (FTFA->FSTAT & FTFA_FSTAT_FPVIOL_MASK) {
Sissors 8:00cefe0d59ed 214 #ifdef IAPDEBUG
Sissors 8:00cefe0d59ed 215 printf("IAP: Protection violation\r\n");
Sissors 8:00cefe0d59ed 216 #endif
Sissors 8:00cefe0d59ed 217 return ProtectionError;
Sissors 8:00cefe0d59ed 218 }
Sissors 8:00cefe0d59ed 219 if (FTFA->FSTAT & FTFA_FSTAT_ACCERR_MASK) {
Sissors 8:00cefe0d59ed 220 #ifdef IAPDEBUG
Sissors 8:00cefe0d59ed 221 printf("IAP: Flash access error\r\n");
Sissors 8:00cefe0d59ed 222 #endif
Sissors 8:00cefe0d59ed 223 return AccessError;
Sissors 8:00cefe0d59ed 224 }
Sissors 8:00cefe0d59ed 225 if (FTFA->FSTAT & FTFA_FSTAT_RDCOLERR_MASK) {
Sissors 8:00cefe0d59ed 226 #ifdef IAPDEBUG
Sissors 8:00cefe0d59ed 227 printf("IAP: Collision error\r\n");
Sissors 8:00cefe0d59ed 228 #endif
Sissors 8:00cefe0d59ed 229 return CollisionError;
Sissors 8:00cefe0d59ed 230 }
Sissors 8:00cefe0d59ed 231 if (FTFA->FSTAT & FTFA_FSTAT_MGSTAT0_MASK) {
Sissors 8:00cefe0d59ed 232 #ifdef IAPDEBUG
Sissors 8:00cefe0d59ed 233 printf("IAP: Runtime error\r\n");
Sissors 8:00cefe0d59ed 234 #endif
Sissors 8:00cefe0d59ed 235 return RuntimeError;
Sissors 8:00cefe0d59ed 236 }
Sissors 8:00cefe0d59ed 237 #ifdef IAPDEBUG
Sissors 8:00cefe0d59ed 238 printf("IAP: No error reported\r\n");
Sissors 8:00cefe0d59ed 239 #endif
Sissors 8:00cefe0d59ed 240 return Success;
Sissors 8:00cefe0d59ed 241 }