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:
Sun May 11 13:01:44 2014 +0000
Revision:
1:702fd2d53c17
Parent:
0:8eef5a3e83ca
Child:
2:70ade1638644
Can program arbitrary length, verifies erased first

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sissors 0:8eef5a3e83ca 1 #include "FreescaleIAP.h"
Sissors 0:8eef5a3e83ca 2
Sissors 0:8eef5a3e83ca 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 0:8eef5a3e83ca 64 IAPCode program_word(int address, char *data) {
Sissors 0:8eef5a3e83ca 65 #ifdef IAPDEBUG
Sissors 0:8eef5a3e83ca 66 printf("IAP: Programming word at %x, %d - %d - %d - %d\r\n", address, data[0], data[1], data[2], data[3]);
Sissors 0:8eef5a3e83ca 67 #endif
Sissors 0:8eef5a3e83ca 68 if (check_align(address))
Sissors 0:8eef5a3e83ca 69 return AlignError;
Sissors 0:8eef5a3e83ca 70
Sissors 0:8eef5a3e83ca 71 //Setup command
Sissors 0:8eef5a3e83ca 72 FTFA->FCCOB0 = ProgramLongword;
Sissors 0:8eef5a3e83ca 73 FTFA->FCCOB1 = (address >> 16) & 0xFF;
Sissors 0:8eef5a3e83ca 74 FTFA->FCCOB2 = (address >> 8) & 0xFF;
Sissors 0:8eef5a3e83ca 75 FTFA->FCCOB3 = address & 0xFF;
Sissors 0:8eef5a3e83ca 76 FTFA->FCCOB4 = data[3];
Sissors 0:8eef5a3e83ca 77 FTFA->FCCOB5 = data[2];
Sissors 0:8eef5a3e83ca 78 FTFA->FCCOB6 = data[1];
Sissors 0:8eef5a3e83ca 79 FTFA->FCCOB7 = data[0];
Sissors 0:8eef5a3e83ca 80
Sissors 0:8eef5a3e83ca 81 run_command();
Sissors 0:8eef5a3e83ca 82
Sissors 0:8eef5a3e83ca 83 return check_error();
Sissors 0:8eef5a3e83ca 84 }
Sissors 0:8eef5a3e83ca 85
Sissors 0:8eef5a3e83ca 86 /* Clear possible flags which are set, run command, wait until done */
Sissors 0:8eef5a3e83ca 87 inline void run_command(void) {
Sissors 0:8eef5a3e83ca 88 //Clear possible old errors, start command, wait until done
Sissors 0:8eef5a3e83ca 89 FTFA->FSTAT = FTFA_FSTAT_FPVIOL_MASK | FTFA_FSTAT_ACCERR_MASK | FTFA_FSTAT_RDCOLERR_MASK;
Sissors 0:8eef5a3e83ca 90 FTFA->FSTAT = FTFA_FSTAT_CCIF_MASK;
Sissors 0:8eef5a3e83ca 91 while (!(FTFA->FSTAT & FTFA_FSTAT_CCIF_MASK));
Sissors 0:8eef5a3e83ca 92 }
Sissors 0:8eef5a3e83ca 93
Sissors 0:8eef5a3e83ca 94
Sissors 0:8eef5a3e83ca 95
Sissors 0:8eef5a3e83ca 96 /* Check if no flash boundary is violated
Sissors 0:8eef5a3e83ca 97 Returns true on violation */
Sissors 0:8eef5a3e83ca 98 bool check_boundary(int address, unsigned int length) {
Sissors 0:8eef5a3e83ca 99 address &= ~1023;
Sissors 0:8eef5a3e83ca 100 int temp = (address+length - 1) & (~1023);
Sissors 0:8eef5a3e83ca 101 bool retval = (address != temp);
Sissors 0:8eef5a3e83ca 102 #ifdef IAPDEBUG
Sissors 0:8eef5a3e83ca 103 if (retval)
Sissors 0:8eef5a3e83ca 104 printf("IAP: Boundary violation\r\n");
Sissors 0:8eef5a3e83ca 105 #endif
Sissors 0:8eef5a3e83ca 106 return retval;
Sissors 0:8eef5a3e83ca 107 }
Sissors 0:8eef5a3e83ca 108
Sissors 0:8eef5a3e83ca 109 /* Check if address is correctly aligned
Sissors 0:8eef5a3e83ca 110 Returns true on violation */
Sissors 0:8eef5a3e83ca 111 bool check_align(int address) {
Sissors 0:8eef5a3e83ca 112 bool retval = address & 0x03;
Sissors 0:8eef5a3e83ca 113 #ifdef IAPDEBUG
Sissors 0:8eef5a3e83ca 114 if (retval)
Sissors 0:8eef5a3e83ca 115 printf("IAP: Alignment violation\r\n");
Sissors 0:8eef5a3e83ca 116 #endif
Sissors 0:8eef5a3e83ca 117 return retval;
Sissors 0:8eef5a3e83ca 118 }
Sissors 0:8eef5a3e83ca 119
Sissors 1:702fd2d53c17 120 /* Check if an area of flash memory is erased
Sissors 1:702fd2d53c17 121 Returns error code or Success (in case of fully erased) */
Sissors 1:702fd2d53c17 122 IAPCode verify_erased(int address, unsigned int length) {
Sissors 1:702fd2d53c17 123 #ifdef IAPDEBUG
Sissors 1:702fd2d53c17 124 printf("IAP: Verify erased at %x with length %d\r\n", address, length);
Sissors 1:702fd2d53c17 125 #endif
Sissors 1:702fd2d53c17 126
Sissors 1:702fd2d53c17 127 if (check_align(address))
Sissors 1:702fd2d53c17 128 return AlignError;
Sissors 1:702fd2d53c17 129
Sissors 1:702fd2d53c17 130 //Setup command
Sissors 1:702fd2d53c17 131 FTFA->FCCOB0 = Read1s;
Sissors 1:702fd2d53c17 132 FTFA->FCCOB1 = (address >> 16) & 0xFF;
Sissors 1:702fd2d53c17 133 FTFA->FCCOB2 = (address >> 8) & 0xFF;
Sissors 1:702fd2d53c17 134 FTFA->FCCOB3 = address & 0xFF;
Sissors 1:702fd2d53c17 135 FTFA->FCCOB4 = (length >> 10) & 0xFF;
Sissors 1:702fd2d53c17 136 FTFA->FCCOB5 = (length >> 2) & 0xFF;
Sissors 1:702fd2d53c17 137 FTFA->FCCOB6 = 0;
Sissors 1:702fd2d53c17 138
Sissors 1:702fd2d53c17 139 run_command();
Sissors 1:702fd2d53c17 140
Sissors 1:702fd2d53c17 141 IAPCode retval = check_error();
Sissors 1:702fd2d53c17 142 if (retval == RuntimeError) {
Sissors 1:702fd2d53c17 143 #ifdef IAPDEBUG
Sissors 1:702fd2d53c17 144 printf("IAP: Flash was not erased\r\n");
Sissors 1:702fd2d53c17 145 #endif
Sissors 1:702fd2d53c17 146 return EraseError;
Sissors 1:702fd2d53c17 147 }
Sissors 1:702fd2d53c17 148 return retval;
Sissors 1:702fd2d53c17 149
Sissors 1:702fd2d53c17 150 }
Sissors 1:702fd2d53c17 151
Sissors 1:702fd2d53c17 152 /* Check if an error occured
Sissors 1:702fd2d53c17 153 Returns error code or Success*/
Sissors 0:8eef5a3e83ca 154 IAPCode check_error(void) {
Sissors 0:8eef5a3e83ca 155 if (FTFA->FSTAT & FTFA_FSTAT_FPVIOL_MASK) {
Sissors 0:8eef5a3e83ca 156 #ifdef IAPDEBUG
Sissors 0:8eef5a3e83ca 157 printf("IAP: Protection violation\r\n");
Sissors 0:8eef5a3e83ca 158 #endif
Sissors 0:8eef5a3e83ca 159 return ProtectionError;
Sissors 0:8eef5a3e83ca 160 }
Sissors 0:8eef5a3e83ca 161 if (FTFA->FSTAT & FTFA_FSTAT_ACCERR_MASK) {
Sissors 0:8eef5a3e83ca 162 #ifdef IAPDEBUG
Sissors 0:8eef5a3e83ca 163 printf("IAP: Flash access error\r\n");
Sissors 0:8eef5a3e83ca 164 #endif
Sissors 0:8eef5a3e83ca 165 return AccessError;
Sissors 0:8eef5a3e83ca 166 }
Sissors 0:8eef5a3e83ca 167 if (FTFA->FSTAT & FTFA_FSTAT_RDCOLERR_MASK) {
Sissors 0:8eef5a3e83ca 168 #ifdef IAPDEBUG
Sissors 0:8eef5a3e83ca 169 printf("IAP: Collision error\r\n");
Sissors 0:8eef5a3e83ca 170 #endif
Sissors 0:8eef5a3e83ca 171 return CollisionError;
Sissors 0:8eef5a3e83ca 172 }
Sissors 1:702fd2d53c17 173 if (FTFA->FSTAT & FTFA_FSTAT_MGSTAT0_MASK) {
Sissors 1:702fd2d53c17 174 #ifdef IAPDEBUG
Sissors 1:702fd2d53c17 175 printf("IAP: Runtime error\r\n");
Sissors 1:702fd2d53c17 176 #endif
Sissors 1:702fd2d53c17 177 return RuntimeError;
Sissors 1:702fd2d53c17 178 }
Sissors 0:8eef5a3e83ca 179 #ifdef IAPDEBUG
Sissors 0:8eef5a3e83ca 180 printf("IAP: No error reported\r\n");
Sissors 0:8eef5a3e83ca 181 #endif
Sissors 0:8eef5a3e83ca 182 return Success;
Sissors 0:8eef5a3e83ca 183 }