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:
Sat May 10 20:12:57 2014 +0000
Revision:
0:8eef5a3e83ca
Child:
1:702fd2d53c17
Version 1: Can erase and program words

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 0:8eef5a3e83ca 21 IAPCode check_error(void);
Sissors 0:8eef5a3e83ca 22
Sissors 0:8eef5a3e83ca 23 IAPCode erase_sector(int address) {
Sissors 0:8eef5a3e83ca 24 #ifdef IAPDEBUG
Sissors 0:8eef5a3e83ca 25 printf("IAP: Erasing at %x\r\n", address);
Sissors 0:8eef5a3e83ca 26 #endif
Sissors 0:8eef5a3e83ca 27 if (check_align(address))
Sissors 0:8eef5a3e83ca 28 return AlignError;
Sissors 0:8eef5a3e83ca 29
Sissors 0:8eef5a3e83ca 30 //Setup command
Sissors 0:8eef5a3e83ca 31 FTFA->FCCOB0 = EraseSector;
Sissors 0:8eef5a3e83ca 32 FTFA->FCCOB1 = (address >> 16) & 0xFF;
Sissors 0:8eef5a3e83ca 33 FTFA->FCCOB2 = (address >> 8) & 0xFF;
Sissors 0:8eef5a3e83ca 34 FTFA->FCCOB3 = address & 0xFF;
Sissors 0:8eef5a3e83ca 35
Sissors 0:8eef5a3e83ca 36 run_command();
Sissors 0:8eef5a3e83ca 37
Sissors 0:8eef5a3e83ca 38 return check_error();
Sissors 0:8eef5a3e83ca 39 }
Sissors 0:8eef5a3e83ca 40
Sissors 0:8eef5a3e83ca 41 IAPCode program_word(int address, char *data) {
Sissors 0:8eef5a3e83ca 42 #ifdef IAPDEBUG
Sissors 0:8eef5a3e83ca 43 printf("IAP: Programming word at %x, %d - %d - %d - %d\r\n", address, data[0], data[1], data[2], data[3]);
Sissors 0:8eef5a3e83ca 44 #endif
Sissors 0:8eef5a3e83ca 45 if (check_align(address))
Sissors 0:8eef5a3e83ca 46 return AlignError;
Sissors 0:8eef5a3e83ca 47
Sissors 0:8eef5a3e83ca 48 //Setup command
Sissors 0:8eef5a3e83ca 49 FTFA->FCCOB0 = ProgramLongword;
Sissors 0:8eef5a3e83ca 50 FTFA->FCCOB1 = (address >> 16) & 0xFF;
Sissors 0:8eef5a3e83ca 51 FTFA->FCCOB2 = (address >> 8) & 0xFF;
Sissors 0:8eef5a3e83ca 52 FTFA->FCCOB3 = address & 0xFF;
Sissors 0:8eef5a3e83ca 53 FTFA->FCCOB4 = data[3];
Sissors 0:8eef5a3e83ca 54 FTFA->FCCOB5 = data[2];
Sissors 0:8eef5a3e83ca 55 FTFA->FCCOB6 = data[1];
Sissors 0:8eef5a3e83ca 56 FTFA->FCCOB7 = data[0];
Sissors 0:8eef5a3e83ca 57
Sissors 0:8eef5a3e83ca 58 run_command();
Sissors 0:8eef5a3e83ca 59
Sissors 0:8eef5a3e83ca 60 return check_error();
Sissors 0:8eef5a3e83ca 61 }
Sissors 0:8eef5a3e83ca 62
Sissors 0:8eef5a3e83ca 63 /* Clear possible flags which are set, run command, wait until done */
Sissors 0:8eef5a3e83ca 64 inline void run_command(void) {
Sissors 0:8eef5a3e83ca 65 //Clear possible old errors, start command, wait until done
Sissors 0:8eef5a3e83ca 66 FTFA->FSTAT = FTFA_FSTAT_FPVIOL_MASK | FTFA_FSTAT_ACCERR_MASK | FTFA_FSTAT_RDCOLERR_MASK;
Sissors 0:8eef5a3e83ca 67 FTFA->FSTAT = FTFA_FSTAT_CCIF_MASK;
Sissors 0:8eef5a3e83ca 68 while (!(FTFA->FSTAT & FTFA_FSTAT_CCIF_MASK));
Sissors 0:8eef5a3e83ca 69 }
Sissors 0:8eef5a3e83ca 70
Sissors 0:8eef5a3e83ca 71
Sissors 0:8eef5a3e83ca 72
Sissors 0:8eef5a3e83ca 73 /* Check if no flash boundary is violated
Sissors 0:8eef5a3e83ca 74 Returns true on violation */
Sissors 0:8eef5a3e83ca 75 bool check_boundary(int address, unsigned int length) {
Sissors 0:8eef5a3e83ca 76 address &= ~1023;
Sissors 0:8eef5a3e83ca 77 int temp = (address+length - 1) & (~1023);
Sissors 0:8eef5a3e83ca 78 bool retval = (address != temp);
Sissors 0:8eef5a3e83ca 79 #ifdef IAPDEBUG
Sissors 0:8eef5a3e83ca 80 if (retval)
Sissors 0:8eef5a3e83ca 81 printf("IAP: Boundary violation\r\n");
Sissors 0:8eef5a3e83ca 82 #endif
Sissors 0:8eef5a3e83ca 83 return retval;
Sissors 0:8eef5a3e83ca 84 }
Sissors 0:8eef5a3e83ca 85
Sissors 0:8eef5a3e83ca 86 /* Check if address is correctly aligned
Sissors 0:8eef5a3e83ca 87 Returns true on violation */
Sissors 0:8eef5a3e83ca 88 bool check_align(int address) {
Sissors 0:8eef5a3e83ca 89 bool retval = address & 0x03;
Sissors 0:8eef5a3e83ca 90 #ifdef IAPDEBUG
Sissors 0:8eef5a3e83ca 91 if (retval)
Sissors 0:8eef5a3e83ca 92 printf("IAP: Alignment violation\r\n");
Sissors 0:8eef5a3e83ca 93 #endif
Sissors 0:8eef5a3e83ca 94 return retval;
Sissors 0:8eef5a3e83ca 95 }
Sissors 0:8eef5a3e83ca 96
Sissors 0:8eef5a3e83ca 97 IAPCode check_error(void) {
Sissors 0:8eef5a3e83ca 98 if (FTFA->FSTAT & FTFA_FSTAT_FPVIOL_MASK) {
Sissors 0:8eef5a3e83ca 99 #ifdef IAPDEBUG
Sissors 0:8eef5a3e83ca 100 printf("IAP: Protection violation\r\n");
Sissors 0:8eef5a3e83ca 101 #endif
Sissors 0:8eef5a3e83ca 102 return ProtectionError;
Sissors 0:8eef5a3e83ca 103 }
Sissors 0:8eef5a3e83ca 104 if (FTFA->FSTAT & FTFA_FSTAT_ACCERR_MASK) {
Sissors 0:8eef5a3e83ca 105 #ifdef IAPDEBUG
Sissors 0:8eef5a3e83ca 106 printf("IAP: Flash access error\r\n");
Sissors 0:8eef5a3e83ca 107 #endif
Sissors 0:8eef5a3e83ca 108 return AccessError;
Sissors 0:8eef5a3e83ca 109 }
Sissors 0:8eef5a3e83ca 110 if (FTFA->FSTAT & FTFA_FSTAT_RDCOLERR_MASK) {
Sissors 0:8eef5a3e83ca 111 #ifdef IAPDEBUG
Sissors 0:8eef5a3e83ca 112 printf("IAP: Collision error\r\n");
Sissors 0:8eef5a3e83ca 113 #endif
Sissors 0:8eef5a3e83ca 114 return CollisionError;
Sissors 0:8eef5a3e83ca 115 }
Sissors 0:8eef5a3e83ca 116 #ifdef IAPDEBUG
Sissors 0:8eef5a3e83ca 117 printf("IAP: No error reported\r\n");
Sissors 0:8eef5a3e83ca 118 #endif
Sissors 0:8eef5a3e83ca 119 return Success;
Sissors 0:8eef5a3e83ca 120 }