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:
nyatla
Date:
Tue Sep 30 14:00:43 2014 +0000
Revision:
6:186db0d96fcf
Parent:
4:59c57c566685
Child:
7:474d231b2f35
Modification of FRDM-K64F ; add ProgramPhrase FCMD;

Who changed what in which revision?

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