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:
Fri Jul 18 06:17:00 2014 +0000
Revision:
3:0f127a8ba79b
Parent:
2:70ade1638644
Child:
4:59c57c566685
Added K20D50M support

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