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 20:18:21 2014 +0000
Revision:
4:59c57c566685
Parent:
3:0f127a8ba79b
Child:
6:186db0d96fcf
Disable IRQs during flash commands

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 4:59c57c566685 107 __disable_irq(); //Disable IRQs, preventing IRQ routines from trying to access flash (thanks to https://mbed.org/users/mjr/)
Sissors 0:8eef5a3e83ca 108 FTFA->FSTAT = FTFA_FSTAT_FPVIOL_MASK | FTFA_FSTAT_ACCERR_MASK | FTFA_FSTAT_RDCOLERR_MASK;
Sissors 0:8eef5a3e83ca 109 FTFA->FSTAT = FTFA_FSTAT_CCIF_MASK;
Sissors 0:8eef5a3e83ca 110 while (!(FTFA->FSTAT & FTFA_FSTAT_CCIF_MASK));
Sissors 4:59c57c566685 111 __enable_irq();
Sissors 0:8eef5a3e83ca 112 }
Sissors 0:8eef5a3e83ca 113
Sissors 0:8eef5a3e83ca 114
Sissors 0:8eef5a3e83ca 115
Sissors 0:8eef5a3e83ca 116 /* Check if no flash boundary is violated
Sissors 0:8eef5a3e83ca 117 Returns true on violation */
Sissors 0:8eef5a3e83ca 118 bool check_boundary(int address, unsigned int length) {
Sissors 2:70ade1638644 119 int temp = (address+length - 1) / SECTOR_SIZE;
Sissors 2:70ade1638644 120 address /= SECTOR_SIZE;
Sissors 0:8eef5a3e83ca 121 bool retval = (address != temp);
Sissors 0:8eef5a3e83ca 122 #ifdef IAPDEBUG
Sissors 0:8eef5a3e83ca 123 if (retval)
Sissors 0:8eef5a3e83ca 124 printf("IAP: Boundary violation\r\n");
Sissors 0:8eef5a3e83ca 125 #endif
Sissors 0:8eef5a3e83ca 126 return retval;
Sissors 0:8eef5a3e83ca 127 }
Sissors 0:8eef5a3e83ca 128
Sissors 0:8eef5a3e83ca 129 /* Check if address is correctly aligned
Sissors 0:8eef5a3e83ca 130 Returns true on violation */
Sissors 0:8eef5a3e83ca 131 bool check_align(int address) {
Sissors 0:8eef5a3e83ca 132 bool retval = address & 0x03;
Sissors 0:8eef5a3e83ca 133 #ifdef IAPDEBUG
Sissors 0:8eef5a3e83ca 134 if (retval)
Sissors 0:8eef5a3e83ca 135 printf("IAP: Alignment violation\r\n");
Sissors 0:8eef5a3e83ca 136 #endif
Sissors 0:8eef5a3e83ca 137 return retval;
Sissors 0:8eef5a3e83ca 138 }
Sissors 0:8eef5a3e83ca 139
Sissors 1:702fd2d53c17 140 /* Check if an area of flash memory is erased
Sissors 1:702fd2d53c17 141 Returns error code or Success (in case of fully erased) */
Sissors 1:702fd2d53c17 142 IAPCode verify_erased(int address, unsigned int length) {
Sissors 1:702fd2d53c17 143 #ifdef IAPDEBUG
Sissors 1:702fd2d53c17 144 printf("IAP: Verify erased at %x with length %d\r\n", address, length);
Sissors 1:702fd2d53c17 145 #endif
Sissors 1:702fd2d53c17 146
Sissors 1:702fd2d53c17 147 if (check_align(address))
Sissors 1:702fd2d53c17 148 return AlignError;
Sissors 1:702fd2d53c17 149
Sissors 1:702fd2d53c17 150 //Setup command
Sissors 1:702fd2d53c17 151 FTFA->FCCOB0 = Read1s;
Sissors 1:702fd2d53c17 152 FTFA->FCCOB1 = (address >> 16) & 0xFF;
Sissors 1:702fd2d53c17 153 FTFA->FCCOB2 = (address >> 8) & 0xFF;
Sissors 1:702fd2d53c17 154 FTFA->FCCOB3 = address & 0xFF;
Sissors 1:702fd2d53c17 155 FTFA->FCCOB4 = (length >> 10) & 0xFF;
Sissors 1:702fd2d53c17 156 FTFA->FCCOB5 = (length >> 2) & 0xFF;
Sissors 1:702fd2d53c17 157 FTFA->FCCOB6 = 0;
Sissors 1:702fd2d53c17 158
Sissors 1:702fd2d53c17 159 run_command();
Sissors 1:702fd2d53c17 160
Sissors 1:702fd2d53c17 161 IAPCode retval = check_error();
Sissors 1:702fd2d53c17 162 if (retval == RuntimeError) {
Sissors 1:702fd2d53c17 163 #ifdef IAPDEBUG
Sissors 1:702fd2d53c17 164 printf("IAP: Flash was not erased\r\n");
Sissors 1:702fd2d53c17 165 #endif
Sissors 1:702fd2d53c17 166 return EraseError;
Sissors 1:702fd2d53c17 167 }
Sissors 1:702fd2d53c17 168 return retval;
Sissors 1:702fd2d53c17 169
Sissors 1:702fd2d53c17 170 }
Sissors 1:702fd2d53c17 171
Sissors 1:702fd2d53c17 172 /* Check if an error occured
Sissors 1:702fd2d53c17 173 Returns error code or Success*/
Sissors 0:8eef5a3e83ca 174 IAPCode check_error(void) {
Sissors 0:8eef5a3e83ca 175 if (FTFA->FSTAT & FTFA_FSTAT_FPVIOL_MASK) {
Sissors 0:8eef5a3e83ca 176 #ifdef IAPDEBUG
Sissors 0:8eef5a3e83ca 177 printf("IAP: Protection violation\r\n");
Sissors 0:8eef5a3e83ca 178 #endif
Sissors 0:8eef5a3e83ca 179 return ProtectionError;
Sissors 0:8eef5a3e83ca 180 }
Sissors 0:8eef5a3e83ca 181 if (FTFA->FSTAT & FTFA_FSTAT_ACCERR_MASK) {
Sissors 0:8eef5a3e83ca 182 #ifdef IAPDEBUG
Sissors 0:8eef5a3e83ca 183 printf("IAP: Flash access error\r\n");
Sissors 0:8eef5a3e83ca 184 #endif
Sissors 0:8eef5a3e83ca 185 return AccessError;
Sissors 0:8eef5a3e83ca 186 }
Sissors 0:8eef5a3e83ca 187 if (FTFA->FSTAT & FTFA_FSTAT_RDCOLERR_MASK) {
Sissors 0:8eef5a3e83ca 188 #ifdef IAPDEBUG
Sissors 0:8eef5a3e83ca 189 printf("IAP: Collision error\r\n");
Sissors 0:8eef5a3e83ca 190 #endif
Sissors 0:8eef5a3e83ca 191 return CollisionError;
Sissors 0:8eef5a3e83ca 192 }
Sissors 1:702fd2d53c17 193 if (FTFA->FSTAT & FTFA_FSTAT_MGSTAT0_MASK) {
Sissors 1:702fd2d53c17 194 #ifdef IAPDEBUG
Sissors 1:702fd2d53c17 195 printf("IAP: Runtime error\r\n");
Sissors 1:702fd2d53c17 196 #endif
Sissors 1:702fd2d53c17 197 return RuntimeError;
Sissors 1:702fd2d53c17 198 }
Sissors 0:8eef5a3e83ca 199 #ifdef IAPDEBUG
Sissors 0:8eef5a3e83ca 200 printf("IAP: No error reported\r\n");
Sissors 0:8eef5a3e83ca 201 #endif
Sissors 0:8eef5a3e83ca 202 return Success;
Sissors 0:8eef5a3e83ca 203 }