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 -

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers FreescaleIAP.cpp Source File

FreescaleIAP.cpp

00001 #include "FreescaleIAP.h"
00002 
00003 //#define IAPDEBUG
00004 
00005 #ifdef TARGET_K64F
00006 //For K64F
00007 #   include "MK64F12.h"
00008 #   define USE_ProgramPhrase 1
00009 #   define FTFA                        FTFE
00010 #   define FTFA_FSTAT_FPVIOL_MASK      FTFE_FSTAT_FPVIOL_MASK 
00011 #   define FTFA_FSTAT_ACCERR_MASK      FTFE_FSTAT_ACCERR_MASK
00012 #   define FTFA_FSTAT_RDCOLERR_MASK    FTFE_FSTAT_RDCOLERR_MASK
00013 #   define FTFA_FSTAT_CCIF_MASK        FTFE_FSTAT_CCIF_MASK
00014 #   define FTFA_FSTAT_MGSTAT0_MASK     FTFE_FSTAT_MGSTAT0_MASK
00015 #else
00016 //Different names used on at least the K20:
00017 #   ifndef FTFA_FSTAT_FPVIOL_MASK
00018 #       define FTFA                        FTFL
00019 #       define FTFA_FSTAT_FPVIOL_MASK      FTFL_FSTAT_FPVIOL_MASK 
00020 #       define FTFA_FSTAT_ACCERR_MASK      FTFL_FSTAT_ACCERR_MASK
00021 #       define FTFA_FSTAT_RDCOLERR_MASK    FTFL_FSTAT_RDCOLERR_MASK
00022 #       define FTFA_FSTAT_CCIF_MASK        FTFL_FSTAT_CCIF_MASK
00023 #       define FTFA_FSTAT_MGSTAT0_MASK     FTFL_FSTAT_MGSTAT0_MASK
00024 #   endif
00025 #endif
00026 
00027 
00028 enum FCMD {
00029     Read1s = 0x01,
00030     ProgramCheck = 0x02,
00031     ReadResource = 0x03,
00032     ProgramLongword = 0x06,
00033     ProgramPhrase = 0x07,    
00034     EraseSector = 0x09,
00035     Read1sBlock = 0x40,
00036     ReadOnce = 0x41,
00037     ProgramOnce = 0x43,
00038     EraseAll = 0x44,
00039     VerifyBackdoor = 0x45
00040     };
00041 
00042 inline void run_command(void);
00043 bool check_boundary(int address, unsigned int length);
00044 bool check_align(int address);
00045 IAPCode verify_erased(int address, unsigned int length);
00046 IAPCode check_error(void);
00047 IAPCode program_word(int address, char *data);
00048     
00049 __attribute__((section(".ARM.__at_0x7268"))) IAPCode erase_sector(int address) {
00050     #ifdef IAPDEBUG
00051     printf("IAP: Erasing at %x\r\n", address);
00052     #endif
00053     if (check_align(address))
00054         return AlignError;
00055     
00056     //Setup command
00057     FTFA->FCCOB0 = EraseSector;
00058     FTFA->FCCOB1 = (address >> 16) & 0xFF;
00059     FTFA->FCCOB2 = (address >> 8) & 0xFF;
00060     FTFA->FCCOB3 = address & 0xFF;
00061     
00062     run_command();
00063     
00064     return check_error();
00065 }
00066 
00067 __attribute__((section(".ARM.__at_0x7300"))) IAPCode program_flash(int address, char *data, unsigned int length) {
00068     #ifdef IAPDEBUG
00069     printf("IAP: Programming flash at %x with length %d\r\n", address, length);
00070     #endif
00071     if (check_align(address))
00072         return AlignError;
00073         
00074     IAPCode eraseCheck = verify_erased(address, length);
00075     if (eraseCheck != Success)
00076         return eraseCheck;
00077     
00078     IAPCode progResult;
00079 #ifdef USE_ProgramPhrase
00080     for (int i = 0; i < length; i+=8) {
00081         progResult = program_word(address + i, data + i);
00082         if (progResult != Success)
00083             return progResult;
00084     }
00085 #else
00086     for (int i = 0; i < length; i+=4) {
00087         progResult = program_word(address + i, data + i);
00088         if (progResult != Success)
00089             return progResult;
00090     }
00091 #endif    
00092     return Success;
00093 }
00094 
00095 __attribute__((section(".ARM.__at_0x7500"))) uint32_t flash_size(void) {
00096     uint32_t retval = (SIM->FCFG2 & 0x7F000000u) >> (24-13);
00097     if (SIM->FCFG2 & (1<<23))           //Possible second flash bank
00098         retval += (SIM->FCFG2 & 0x007F0000u) >> (16-13);
00099     return retval;
00100 }
00101 
00102 __attribute__((section(".ARM.__at_0x7600"))) IAPCode program_word(int address, char *data) {
00103     #ifdef IAPDEBUG
00104     #ifdef USE_ProgramPhrase
00105     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]);
00106     #else
00107     printf("IAP: Programming word at %x, %d - %d - %d - %d\r\n", address, data[0], data[1], data[2], data[3]);
00108     #endif
00109     
00110     #endif
00111     if (check_align(address))
00112         return AlignError;
00113 #ifdef USE_ProgramPhrase
00114     FTFA->FCCOB0 = ProgramPhrase;
00115     FTFA->FCCOB1 = (address >> 16) & 0xFF;
00116     FTFA->FCCOB2 = (address >> 8) & 0xFF;
00117     FTFA->FCCOB3 = address & 0xFF;
00118     FTFA->FCCOB4 = data[3];
00119     FTFA->FCCOB5 = data[2];
00120     FTFA->FCCOB6 = data[1];
00121     FTFA->FCCOB7 = data[0];
00122     FTFA->FCCOB8 = data[7];
00123     FTFA->FCCOB9 = data[6];
00124     FTFA->FCCOBA = data[5];
00125     FTFA->FCCOBB = data[4];    
00126 #else
00127     //Setup command
00128     FTFA->FCCOB0 = ProgramLongword;
00129     FTFA->FCCOB1 = (address >> 16) & 0xFF;
00130     FTFA->FCCOB2 = (address >> 8) & 0xFF;
00131     FTFA->FCCOB3 = address & 0xFF;
00132     FTFA->FCCOB4 = data[3];
00133     FTFA->FCCOB5 = data[2];
00134     FTFA->FCCOB6 = data[1];
00135     FTFA->FCCOB7 = data[0];
00136 #endif    
00137     run_command();
00138     
00139     return check_error();
00140 }
00141 
00142 /* Clear possible flags which are set, run command, wait until done */
00143 __attribute__((section(".ARM.__at_0x7700"))) inline void run_command(void) {
00144     //Clear possible old errors, start command, wait until done
00145     __disable_irq();            //Disable IRQs, preventing IRQ routines from trying to access flash (thanks to https://mbed.org/users/mjr/)
00146     FTFA->FSTAT = FTFA_FSTAT_FPVIOL_MASK | FTFA_FSTAT_ACCERR_MASK | FTFA_FSTAT_RDCOLERR_MASK;
00147     FTFA->FSTAT = FTFA_FSTAT_CCIF_MASK;
00148     while (!(FTFA->FSTAT & FTFA_FSTAT_CCIF_MASK));
00149     __enable_irq();
00150 }    
00151     
00152     
00153 
00154 /* Check if no flash boundary is violated
00155    Returns true on violation */
00156 __attribute__((section(".ARM.__at_0x7800"))) bool check_boundary(int address, unsigned int length) {
00157     int temp = (address+length - 1) / SECTOR_SIZE;
00158     address /= SECTOR_SIZE;
00159     bool retval = (address != temp);
00160     #ifdef IAPDEBUG
00161     if (retval)
00162         printf("IAP: Boundary violation\r\n");
00163     #endif
00164     return retval;
00165 }
00166 
00167 /* Check if address is correctly aligned
00168    Returns true on violation */
00169 __attribute__((section(".ARM.__at_0x7900"))) bool check_align(int address) {
00170     bool retval = address & 0x03;
00171     #ifdef IAPDEBUG
00172     if (retval)
00173         printf("IAP: Alignment violation\r\n");
00174     #endif
00175     return retval;
00176 }
00177 
00178 /* Check if an area of flash memory is erased
00179    Returns error code or Success (in case of fully erased) */
00180 __attribute__((section(".ARM.__at_0x7A00"))) IAPCode verify_erased(int address, unsigned int length) {
00181     #ifdef IAPDEBUG
00182     printf("IAP: Verify erased at %x with length %d\r\n", address, length);
00183     #endif
00184     
00185     if (check_align(address))
00186         return AlignError;
00187     
00188     //Setup command
00189     FTFA->FCCOB0 = Read1s;
00190     FTFA->FCCOB1 = (address >> 16) & 0xFF;
00191     FTFA->FCCOB2 = (address >> 8) & 0xFF;
00192     FTFA->FCCOB3 = address & 0xFF;
00193     FTFA->FCCOB4 = (length >> 10) & 0xFF;
00194     FTFA->FCCOB5 = (length >> 2) & 0xFF;
00195     FTFA->FCCOB6 = 0;
00196     
00197     run_command();
00198     
00199     IAPCode retval = check_error();
00200     if (retval == RuntimeError) {
00201         #ifdef IAPDEBUG
00202         printf("IAP: Flash was not erased\r\n");
00203         #endif
00204         return EraseError;
00205     }
00206     return retval;
00207         
00208 }
00209 
00210 /* Check if an error occured 
00211    Returns error code or Success*/
00212 __attribute__((section(".ARM.__at_0x7B00"))) IAPCode check_error(void) {
00213     if (FTFA->FSTAT & FTFA_FSTAT_FPVIOL_MASK) {
00214         #ifdef IAPDEBUG
00215         printf("IAP: Protection violation\r\n");
00216         #endif
00217         return ProtectionError;
00218     }
00219     if (FTFA->FSTAT & FTFA_FSTAT_ACCERR_MASK) {
00220         #ifdef IAPDEBUG
00221         printf("IAP: Flash access error\r\n");
00222         #endif
00223         return AccessError;
00224     }
00225     if (FTFA->FSTAT & FTFA_FSTAT_RDCOLERR_MASK) {
00226         #ifdef IAPDEBUG
00227         printf("IAP: Collision error\r\n");
00228         #endif
00229         return CollisionError;
00230     }
00231     if (FTFA->FSTAT & FTFA_FSTAT_MGSTAT0_MASK) {
00232         #ifdef IAPDEBUG
00233         printf("IAP: Runtime error\r\n");
00234         #endif
00235         return RuntimeError;
00236     }
00237     #ifdef IAPDEBUG
00238     printf("IAP: No error reported\r\n");
00239     #endif
00240     return Success;
00241 }