ec521

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
gaving
Date:
Sun Apr 22 19:20:10 2018 +0000
Commit message:
For EC521 only

Changed in this revision

FreescaleIAP/FreescaleIAP.cpp Show annotated file Show diff for this revision Revisions of this file
FreescaleIAP/FreescaleIAP.h Show annotated file Show diff for this revision Revisions of this file
FreescaleIAP/mbed.bld Show annotated file Show diff for this revision Revisions of this file
flashwrite.cpp Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r e2f78ce2a5cf FreescaleIAP/FreescaleIAP.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FreescaleIAP/FreescaleIAP.cpp	Sun Apr 22 19:20:10 2018 +0000
@@ -0,0 +1,239 @@
+#include "FreescaleIAP.h"
+
+//#define IAPDEBUG
+
+#ifdef TARGET_K64F
+//For K64F
+#   include "MK64F12.h"
+#   define USE_ProgramPhrase 1
+#   define FTFA                        FTFE
+#   define FTFA_FSTAT_FPVIOL_MASK      FTFE_FSTAT_FPVIOL_MASK 
+#   define FTFA_FSTAT_ACCERR_MASK      FTFE_FSTAT_ACCERR_MASK
+#   define FTFA_FSTAT_RDCOLERR_MASK    FTFE_FSTAT_RDCOLERR_MASK
+#   define FTFA_FSTAT_CCIF_MASK        FTFE_FSTAT_CCIF_MASK
+#   define FTFA_FSTAT_MGSTAT0_MASK     FTFE_FSTAT_MGSTAT0_MASK
+#else
+//Different names used on at least the K20:
+#   ifndef FTFA_FSTAT_FPVIOL_MASK
+#       define FTFA                        FTFL
+#       define FTFA_FSTAT_FPVIOL_MASK      FTFL_FSTAT_FPVIOL_MASK 
+#       define FTFA_FSTAT_ACCERR_MASK      FTFL_FSTAT_ACCERR_MASK
+#       define FTFA_FSTAT_RDCOLERR_MASK    FTFL_FSTAT_RDCOLERR_MASK
+#       define FTFA_FSTAT_CCIF_MASK        FTFL_FSTAT_CCIF_MASK
+#       define FTFA_FSTAT_MGSTAT0_MASK     FTFL_FSTAT_MGSTAT0_MASK
+#   endif
+#endif
+
+
+enum FCMD {
+    Read1s = 0x01,
+    ProgramCheck = 0x02,
+    ReadResource = 0x03,
+    ProgramLongword = 0x06,
+    ProgramPhrase = 0x07,    
+    EraseSector = 0x09,
+    Read1sBlock = 0x40,
+    ReadOnce = 0x41,
+    ProgramOnce = 0x43,
+    EraseAll = 0x44,
+    VerifyBackdoor = 0x45
+    };
+
+inline void run_command(void);
+bool check_boundary(int address, unsigned int length);
+bool check_align(int address);
+IAPCode verify_erased(int address, unsigned int length);
+IAPCode check_error(void);
+IAPCode program_word(int address, char *data);
+    
+__attribute__((section(".ARM.__at_0x11000"))) IAPCode erase_sector(int address) {
+    #ifdef IAPDEBUG
+    printf("IAP: Erasing at %x\r\n", address);
+    #endif
+    if (check_align(address))
+        return AlignError;
+    
+    //Setup command
+    FTFA->FCCOB0 = EraseSector;
+    FTFA->FCCOB1 = (address >> 16) & 0xFF;
+    FTFA->FCCOB2 = (address >> 8) & 0xFF;
+    FTFA->FCCOB3 = address & 0xFF;
+    
+    run_command();
+    
+    return check_error();
+}
+
+__attribute__((section(".ARM.__at_0x11100"))) IAPCode program_flash(int address, char *data, unsigned int length) {
+    #ifdef IAPDEBUG
+    printf("IAP: Programming flash at %x with length %d\r\n", address, length);
+    #endif
+    if (check_align(address))
+        return AlignError;
+        
+    IAPCode eraseCheck = verify_erased(address, length);
+    if (eraseCheck != Success)
+        return eraseCheck;
+    
+    IAPCode progResult;
+#ifdef USE_ProgramPhrase
+    for (int i = 0; i < length; i+=8) {
+        progResult = program_word(address + i, data + i);
+        if (progResult != Success)
+            return progResult;
+    }
+#else
+    for (int i = 0; i < length; i+=4) {
+        progResult = program_word(address + i, data + i);
+        if (progResult != Success)
+            return progResult;
+    }
+#endif    
+    return Success;
+}
+
+__attribute__((section(".ARM.__at_0x11300"))) uint32_t flash_size(void) {
+    uint32_t retval = (SIM->FCFG2 & 0x7F000000u) >> (24-13);
+    if (SIM->FCFG2 & (1<<23))           //Possible second flash bank
+        retval += (SIM->FCFG2 & 0x007F0000u) >> (16-13);
+    return retval;
+}
+
+__attribute__((section(".ARM.__at_0x11400"))) IAPCode program_word(int address, char *data) {
+    #ifdef IAPDEBUG
+    #ifdef USE_ProgramPhrase
+    printf("IAP: Programming word at %x, %d - %d - %d - %d - %d - %d - %d - %d\r\n", address, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
+    #else
+    printf("IAP: Programming word at %x, %d - %d - %d - %d\r\n", address, data[0], data[1], data[2], data[3]);
+    #endif
+    
+    #endif
+    if (check_align(address))
+        return AlignError;
+#ifdef USE_ProgramPhrase
+    FTFA->FCCOB0 = ProgramPhrase;
+    FTFA->FCCOB1 = (address >> 16) & 0xFF;
+    FTFA->FCCOB2 = (address >> 8) & 0xFF;
+    FTFA->FCCOB3 = address & 0xFF;
+    FTFA->FCCOB4 = data[3];
+    FTFA->FCCOB5 = data[2];
+    FTFA->FCCOB6 = data[1];
+    FTFA->FCCOB7 = data[0];
+    FTFA->FCCOB8 = data[7];
+    FTFA->FCCOB9 = data[6];
+    FTFA->FCCOBA = data[5];
+    FTFA->FCCOBB = data[4];    
+#else
+    //Setup command
+    FTFA->FCCOB0 = ProgramLongword;
+    FTFA->FCCOB1 = (address >> 16) & 0xFF;
+    FTFA->FCCOB2 = (address >> 8) & 0xFF;
+    FTFA->FCCOB3 = address & 0xFF;
+    FTFA->FCCOB4 = data[3];
+    FTFA->FCCOB5 = data[2];
+    FTFA->FCCOB6 = data[1];
+    FTFA->FCCOB7 = data[0];
+#endif    
+    run_command();
+    
+    return check_error();
+}
+
+/* Clear possible flags which are set, run command, wait until done */
+__attribute__((section(".ARM.__at_0x11500"))) inline void run_command(void) {
+    //Clear possible old errors, start command, wait until done
+    FTFA->FSTAT = FTFA_FSTAT_FPVIOL_MASK | FTFA_FSTAT_ACCERR_MASK | FTFA_FSTAT_RDCOLERR_MASK;
+    FTFA->FSTAT = FTFA_FSTAT_CCIF_MASK;
+    while (!(FTFA->FSTAT & FTFA_FSTAT_CCIF_MASK));
+}    
+    
+    
+
+/* Check if no flash boundary is violated
+   Returns true on violation */
+__attribute__((section(".ARM.__at_0x11600"))) bool check_boundary(int address, unsigned int length) {
+    int temp = (address+length - 1) / SECTOR_SIZE;
+    address /= SECTOR_SIZE;
+    bool retval = (address != temp);
+    #ifdef IAPDEBUG
+    if (retval)
+        printf("IAP: Boundary violation\r\n");
+    #endif
+    return retval;
+}
+
+/* Check if address is correctly aligned
+   Returns true on violation */
+__attribute__((section(".ARM.__at_0x11700"))) bool check_align(int address) {
+    bool retval = address & 0x03;
+    #ifdef IAPDEBUG
+    if (retval)
+        printf("IAP: Alignment violation\r\n");
+    #endif
+    return retval;
+}
+
+/* Check if an area of flash memory is erased
+   Returns error code or Success (in case of fully erased) */
+__attribute__((section(".ARM.__at_0x11800"))) IAPCode verify_erased(int address, unsigned int length) {
+    #ifdef IAPDEBUG
+    printf("IAP: Verify erased at %x with length %d\r\n", address, length);
+    #endif
+    
+    if (check_align(address))
+        return AlignError;
+    
+    //Setup command
+    FTFA->FCCOB0 = Read1s;
+    FTFA->FCCOB1 = (address >> 16) & 0xFF;
+    FTFA->FCCOB2 = (address >> 8) & 0xFF;
+    FTFA->FCCOB3 = address & 0xFF;
+    FTFA->FCCOB4 = (length >> 10) & 0xFF;
+    FTFA->FCCOB5 = (length >> 2) & 0xFF;
+    FTFA->FCCOB6 = 0;
+    
+    run_command();
+    
+    IAPCode retval = check_error();
+    if (retval == RuntimeError) {
+        #ifdef IAPDEBUG
+        printf("IAP: Flash was not erased\r\n");
+        #endif
+        return EraseError;
+    }
+    return retval;
+        
+}
+
+/* Check if an error occured 
+   Returns error code or Success*/
+__attribute__((section(".ARM.__at_0x11900"))) IAPCode check_error(void) {
+    if (FTFA->FSTAT & FTFA_FSTAT_FPVIOL_MASK) {
+        #ifdef IAPDEBUG
+        printf("IAP: Protection violation\r\n");
+        #endif
+        return ProtectionError;
+    }
+    if (FTFA->FSTAT & FTFA_FSTAT_ACCERR_MASK) {
+        #ifdef IAPDEBUG
+        printf("IAP: Flash access error\r\n");
+        #endif
+        return AccessError;
+    }
+    if (FTFA->FSTAT & FTFA_FSTAT_RDCOLERR_MASK) {
+        #ifdef IAPDEBUG
+        printf("IAP: Collision error\r\n");
+        #endif
+        return CollisionError;
+    }
+    if (FTFA->FSTAT & FTFA_FSTAT_MGSTAT0_MASK) {
+        #ifdef IAPDEBUG
+        printf("IAP: Runtime error\r\n");
+        #endif
+        return RuntimeError;
+    }
+    #ifdef IAPDEBUG
+    printf("IAP: No error reported\r\n");
+    #endif
+    return Success;
+}
\ No newline at end of file
diff -r 000000000000 -r e2f78ce2a5cf FreescaleIAP/FreescaleIAP.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FreescaleIAP/FreescaleIAP.h	Sun Apr 22 19:20:10 2018 +0000
@@ -0,0 +1,59 @@
+#ifndef FREESCALEIAP_H
+#define FREESCALEIAP_H
+
+#include "mbed.h"
+
+#if defined(TARGET_KLXX) | defined(TARGET_K20D50M)
+#define SECTOR_SIZE     1024
+#elif (TARGET_K22F)
+#define SECTOR_SIZE     2048
+#elif defined(TARGET_K64F)
+#define SECTOR_SIZE     4096
+#else
+#warning FreescaleIAP unknown target, using default 1024B
+#define SECTOR_SIZE     1024
+#endif
+
+enum IAPCode {
+    BoundaryError = -99,    //Commands may not span several sectors
+    AlignError,             //Data must be aligned on longword (two LSBs zero)
+    ProtectionError,        //Flash sector is protected
+    AccessError,            //Something went wrong
+    CollisionError,         //During writing something tried to flash which was written to
+    LengthError,            //The length must be multiples of 4
+    RuntimeError,           
+    EraseError,             //The flash was not erased before writing to it
+    Success = 0
+    };
+
+/** Erase a flash sector
+ *
+ * The size erased depends on the used device
+ *
+ * @param address address in the sector which needs to be erased
+ * @param return Success if no errors were encountered, otherwise one of the error states
+ */
+IAPCode erase_sector(int address);
+
+/** Program flash
+ *
+ * Before programming the used area needs to be erased. The erase state is checked
+ * before programming, and will return an error if not erased.
+ *
+ * @param address starting address where the data needs to be programmed (must be longword alligned: two LSBs must be zero)
+ * @param data pointer to array with the data to program
+ * @param length number of bytes to program (must be a multiple of 4. must be a multiple of 8 when K64F)
+ * @param return Success if no errors were encountered, otherwise one of the error states
+ */
+IAPCode program_flash(int address, char *data, unsigned int length);
+
+/**
+ * Returns size of flash memory
+ * 
+ * This is the first address which is not flash
+ *
+ * @param return length of flash memory in bytes
+ */
+uint32_t flash_size(void);
+
+#endif
\ No newline at end of file
diff -r 000000000000 -r e2f78ce2a5cf FreescaleIAP/mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FreescaleIAP/mbed.bld	Sun Apr 22 19:20:10 2018 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/994bdf8177cb
\ No newline at end of file
diff -r 000000000000 -r e2f78ce2a5cf flashwrite.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flashwrite.cpp	Sun Apr 22 19:20:10 2018 +0000
@@ -0,0 +1,28 @@
+#include "mbed.h"
+#include "FreescaleIAP.h"
+ 
+int flashwrite() {    
+    
+    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);
+}
diff -r 000000000000 -r e2f78ce2a5cf main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Apr 22 19:20:10 2018 +0000
@@ -0,0 +1,10 @@
+#include "mbed.h"
+
+extern void flashwrite(void);
+
+int main() 
+{   
+    flashwrite();
+    while(1);
+}
+ 
\ No newline at end of file