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:
Mon May 12 19:45:04 2014 +0000
Revision:
2:70ade1638644
Parent:
1:702fd2d53c17
Child:
3:0f127a8ba79b
Added flash_size function

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