ec521
Revision 0:e2f78ce2a5cf, committed 2018-04-22
- Comitter:
- gaving
- Date:
- Sun Apr 22 19:20:10 2018 +0000
- Commit message:
- For EC521 only
Changed in this revision
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