IAP code for Freescale platforms

Dependents:   18_PT1000 RDA5807M-FM-Radio flashaccess TF_conops_BAEFLAGIMAN ... more

K22F

Due to the default clock setup of the K22F, flash write access is there disabled. In the future I might add a workaround, but for now see: https://developer.mbed.org/questions/52738/Error-with-FreescaleIAP-code-with-K22F/

Be careful with which flash you are erasing/overwriting!

Example code:

#include "mbed.h"
#include "FreescaleIAP.h"


int main() {
    int address = flash_size() - SECTOR_SIZE;           //Write in last sector
    
    int *data = (int*)address;
    printf("Starting\r\n"); 
    erase_sector(address);
    int numbers[10] = {0, 1, 10, 100, 1000, 10000, 1000000, 10000000, 100000000, 1000000000};
    program_flash(address, (char*)&numbers, 40);        //10 integers of 4 bytes each: 40 bytes length
    printf("Resulting flash: \r\n");
    for (int i = 0; i<10; i++)
        printf("%d\r\n", data[i]);
    
    printf("Done\r\n\n");
        

    while (true) {
    }
}

For an example on using this for a bootloader, check out: http://developer.mbed.org/users/Sissors/code/Bootloader_K64F/

If you want to permanently store a variable between resets, you can run into the problem of how to define the value the first time. Since the mbed drag-and-drop loader seems to issue a full-chip erase, you cannot first upload a program to set the initial value, and then switch to the regular program: The full-chip erase will also erase your initial value. One option is to use the same statements as used in the bootloader example to force it to program initial values for your variables on your memory address. This should work fine, however it is target dependent where you want to program it (generally your last sector), so it makes for a less nice example program. You can also try to detect if it is the initial run by looking at the state of the flash, by default this is all '1's. The following example does this:

#include "mbed.h"
#include "FreescaleIAP.h"

int main() {    
    
    int address = flash_size() - SECTOR_SIZE;           //Write in last sector
    int *data = (int*)address;
    
    //By default flash is initialized at 0xFF, this is signed -1, so now we know
    //the program runs for the first time. You of course need to make sure your program
    //never writes -1 to this variable if you use this method
    
    //Alternatively you could also do the same, but with a seperate "initial run" variable added,
    //so your other variables can take any value
    if (data[0] == -1) {
        printf("Initial run\r\n");
        printf("Writing 42 and 42\r\n");
        erase_sector(address);
        int newvalues[2] = {42, 42};
        program_flash(address,(char*) newvalues, 8);     //Two integers of 4 bytes = 8 bytes
        while(1);
    }
    printf("Current = %d and %d, new is %d and %d\r\n", data[0], data[1], data[0]+1, data[1]-1);
    int newvalues[2] = {data[0]+1, data[1]-1};
    erase_sector(address);
    program_flash(address, (char*) newvalues, 8);
    while(1);
}
Committer:
Sissors
Date:
Wed Mar 16 20:20:17 2016 +0000
Revision:
11:ab8a833a25eb
Parent:
10:111637082023
Disabled debug

Who changed what in which revision?

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