Example of a Serial bootloader for the K64F platform

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers bootloader.cpp Source File

bootloader.cpp

00001 #include "mbed.h"
00002 #include "FreescaleIAP.h"
00003 
00004 //Could be nicer, but for now just erase all preceding sectors
00005 #define NUM_SECTORS        15
00006 #define TIMEOUT            10000000
00007 #define BUFFER_SIZE        16
00008 
00009 void setupserial();
00010 void write(char *value);
00011 
00012 __attribute__((section(".ARM.__at_0x10000"))) void bootloader(void)
00013 {
00014     setupserial();
00015     write("\n\n\rBootloader\r\n");
00016     write("Continue? (y/n)");
00017     
00018     //Wait until data arrived, if it is 'y', continue
00019     while(!(UART0->S1 & UART_S1_RDRF_MASK));
00020     if (UART0->D != 'y')
00021         return;
00022     
00023     //Disable IRQs, enable ones have been removed from FreescaleIAP
00024     __disable_irq();
00025     
00026     //Erase all sectors we use for the user program
00027     write("Erasing sectors!\r\n");
00028     for (int i = 0; i<NUM_SECTORS; i++)
00029         erase_sector(SECTOR_SIZE * i);
00030 
00031     write("Done erasing, send file!\r\n");
00032 
00033     
00034     char buffer[BUFFER_SIZE];
00035     uint32_t count = 0;
00036     uint8_t buffercount = 0;
00037     uint32_t timeout = 0;
00038     
00039     //Wait until data is sent
00040     while(!(UART0->S1 & UART_S1_RDRF_MASK));
00041     
00042     //Data receive loop
00043     while(1) {
00044         //Check if there is new data
00045         if (UART0->S1 & UART_S1_RDRF_MASK) {
00046             //Place data in buffer
00047             buffer[buffercount] = UART0->D;
00048             buffercount++;
00049             
00050             //Reset timeout
00051             timeout = 0;
00052 
00053             //We write per BUFFER_SIZE chars
00054             if (buffercount == BUFFER_SIZE) {
00055                 //NMI Handler is at bytes 8-9-10-11, we overwrite this to point to bootloader function
00056                 if (count == 0) {
00057                     buffer[8] = 0x01;
00058                     buffer[9] = 0x00;
00059                     buffer[10] = 0x01;
00060                     buffer[11] = 0x00;
00061                 }
00062                 
00063                 //Program the buffer into the flash memory
00064                 if (program_flash(count, buffer, BUFFER_SIZE) != 0) {
00065                     write("Error!\r\n");   
00066                     break;
00067                 }
00068                 
00069                 //Reset buffercount for next buffer
00070                 write("#");
00071                 buffercount = 0;
00072                 count += BUFFER_SIZE;
00073             }
00074         } else {
00075             //No new data, increase timeout
00076             timeout++;
00077             
00078             //We have received no new data for a while, assume we are done
00079             if (timeout > TIMEOUT) {
00080                 //If there is data left in the buffer, program it
00081                 if (buffercount != 0) {
00082                     for (int i = buffercount; i<BUFFER_SIZE; i++) {
00083                         buffer[i] = 0xFF;
00084                     }
00085                     program_flash(count, buffer, BUFFER_SIZE);
00086                 }
00087                 break;          //We should be done programming :D
00088             }
00089         }
00090     }
00091     write("Done programming!\r\n");
00092     NVIC_SystemReset();
00093     
00094     //Shouldn't arrive here
00095     while(1);
00096 }
00097 
00098 __attribute__((section(".ARM.__at_0x10080"))) static void setupserial(void) {
00099         //Setup USBTX/USBRX pins (PTB16/PTB17)
00100         SIM->SCGC5 |= 1 << SIM_SCGC5_PORTB_SHIFT;
00101         PORTB->PCR[16] = (PORTB->PCR[16] & 0x700) | (3 << 8);
00102         PORTB->PCR[17] = (PORTB->PCR[17] & 0x700) | (3 << 8);
00103 
00104         //Setup UART (ugly, copied resulting values from mbed serial setup)
00105         SIM->SCGC4 |= SIM_SCGC4_UART0_MASK;
00106 
00107         UART0->BDH = 3;
00108         UART0->BDL = 13;
00109         UART0->C4 = 8;
00110         UART0->C2 = 12;  //Enables UART
00111 
00112     }
00113 
00114 __attribute__((section(".ARM.__at_0x100A0"))) static void write(char *value)
00115 {
00116         int i = 0;
00117         //Loop through string and send everything
00118         while(*(value+i) != '\0') {
00119             while(!(UART0->S1 & UART_S1_TDRE_MASK));
00120             UART0->D = *(value+i);
00121             i++;
00122         }
00123     }