Mirror with some correction

Dependencies:   mbed FastIO FastPWM USBDevice

Committer:
mjr
Date:
Thu May 12 05:57:53 2016 +0000
Revision:
59:94eb9265b6d7
Parent:
2:c174f9ee414a
Child:
60:f38da020aa13
Replaced library malloc with custom version that's slightly more efficient and makes more memory available overall

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mjr 2:c174f9ee414a 1 #include "FreescaleIAP.h"
mjr 2:c174f9ee414a 2
mjr 2:c174f9ee414a 3 //#define IAPDEBUG
mjr 2:c174f9ee414a 4
mjr 2:c174f9ee414a 5 enum FCMD {
mjr 2:c174f9ee414a 6 Read1s = 0x01,
mjr 2:c174f9ee414a 7 ProgramCheck = 0x02,
mjr 2:c174f9ee414a 8 ReadResource = 0x03,
mjr 2:c174f9ee414a 9 ProgramLongword = 0x06,
mjr 2:c174f9ee414a 10 EraseSector = 0x09,
mjr 2:c174f9ee414a 11 Read1sBlock = 0x40,
mjr 2:c174f9ee414a 12 ReadOnce = 0x41,
mjr 2:c174f9ee414a 13 ProgramOnce = 0x43,
mjr 2:c174f9ee414a 14 EraseAll = 0x44,
mjr 2:c174f9ee414a 15 VerifyBackdoor = 0x45
mjr 2:c174f9ee414a 16 };
mjr 2:c174f9ee414a 17
mjr 2:c174f9ee414a 18 static inline void run_command(FTFA_Type *);
mjr 2:c174f9ee414a 19 bool check_boundary(int address, unsigned int length);
mjr 2:c174f9ee414a 20 bool check_align(int address);
mjr 2:c174f9ee414a 21 IAPCode check_error(void);
mjr 2:c174f9ee414a 22
mjr 2:c174f9ee414a 23 FreescaleIAP::FreescaleIAP()
mjr 2:c174f9ee414a 24 {
mjr 2:c174f9ee414a 25 }
mjr 2:c174f9ee414a 26
mjr 2:c174f9ee414a 27 FreescaleIAP::~FreescaleIAP()
mjr 2:c174f9ee414a 28 {
mjr 2:c174f9ee414a 29 }
mjr 2:c174f9ee414a 30
mjr 59:94eb9265b6d7 31 // We use an assembly language implementation of the EXEC function in
mjr 59:94eb9265b6d7 32 // order to satisfy the requirement (mentioned in the hardware reference)
mjr 59:94eb9265b6d7 33 // that code that writes to Flash must reside in RAM. There's a potential
mjr 59:94eb9265b6d7 34 // for a deadlock if the code that triggers a Flash write operation is
mjr 59:94eb9265b6d7 35 // itself stored in Flash, as an instruction fetch to Flash can deadlock
mjr 59:94eb9265b6d7 36 // against the erase/write. In practice this seems to be rare, but I
mjr 59:94eb9265b6d7 37 // seem to be able to trigger it once in a while. (Which is to say that
mjr 59:94eb9265b6d7 38 // I can trigger occasional lock-ups during writes. It's not clear that
mjr 59:94eb9265b6d7 39 // the Flash bus deadlock is the actual cause, but the timing strongly
mjr 59:94eb9265b6d7 40 // suggests this.)
mjr 59:94eb9265b6d7 41 //
mjr 59:94eb9265b6d7 42 // The mbed tools don't have a way to put a C function in RAM. The mbed
mjr 59:94eb9265b6d7 43 // assembler can, though. So to get our invoking code into RAM, we have
mjr 59:94eb9265b6d7 44 // to write it in assembly. Fortunately, the code involved is very simple:
mjr 59:94eb9265b6d7 45 // just a couple of writes to the memory-mapped Flash controller register,
mjr 59:94eb9265b6d7 46 // and a looped read and bit test from the same location to wait until the
mjr 59:94eb9265b6d7 47 // operation finishes.
mjr 59:94eb9265b6d7 48 //
mjr 59:94eb9265b6d7 49 #define USE_ASM_EXEC 1
mjr 59:94eb9265b6d7 50 #if USE_ASM_EXEC
mjr 59:94eb9265b6d7 51 extern "C" void iapExecAsm(volatile uint8_t *);
mjr 59:94eb9265b6d7 52 #endif
mjr 59:94eb9265b6d7 53
mjr 2:c174f9ee414a 54 // execute an FTFA command
mjr 2:c174f9ee414a 55 static inline void run_command(FTFA_Type *ftfa)
mjr 2:c174f9ee414a 56 {
mjr 59:94eb9265b6d7 57 // Disable interupts. It's critical that we don't service any
mjr 59:94eb9265b6d7 58 // interrupts while a Flash operation is taking place because
mjr 59:94eb9265b6d7 59 // an ISR would normally be a C routine located in Flash, so
mjr 59:94eb9265b6d7 60 // fetching its instructions could deadlock against the write
mjr 59:94eb9265b6d7 61 // or erase operation we're performing.
mjr 2:c174f9ee414a 62 __disable_irq();
mjr 59:94eb9265b6d7 63
mjr 59:94eb9265b6d7 64 #if USE_ASM_EXEC
mjr 59:94eb9265b6d7 65 // Call our RAM-based assembly routine to do this work. The
mjr 59:94eb9265b6d7 66 // assembler routine implements the same ftfa->FSTAT register
mjr 59:94eb9265b6d7 67 // operations in the C alternative code below.
mjr 59:94eb9265b6d7 68 iapExecAsm(&ftfa->FSTAT);
mjr 59:94eb9265b6d7 69
mjr 59:94eb9265b6d7 70 #else // USE_ASM_EXEC
mjr 2:c174f9ee414a 71 // Clear possible old errors, start command, wait until done
mjr 2:c174f9ee414a 72 ftfa->FSTAT = FTFA_FSTAT_FPVIOL_MASK | FTFA_FSTAT_ACCERR_MASK | FTFA_FSTAT_RDCOLERR_MASK;
mjr 2:c174f9ee414a 73 ftfa->FSTAT = FTFA_FSTAT_CCIF_MASK;
mjr 2:c174f9ee414a 74 while (!(ftfa->FSTAT & FTFA_FSTAT_CCIF_MASK));
mjr 59:94eb9265b6d7 75
mjr 59:94eb9265b6d7 76 #endif // USE_ASM_EXEC
mjr 2:c174f9ee414a 77
mjr 59:94eb9265b6d7 78 // done with the Flash access - re-enable interrupts
mjr 2:c174f9ee414a 79 __enable_irq();
mjr 2:c174f9ee414a 80 }
mjr 2:c174f9ee414a 81
mjr 2:c174f9ee414a 82
mjr 2:c174f9ee414a 83 IAPCode FreescaleIAP::erase_sector(int address) {
mjr 2:c174f9ee414a 84 #ifdef IAPDEBUG
mjr 2:c174f9ee414a 85 printf("IAP: Erasing at %x\r\n", address);
mjr 2:c174f9ee414a 86 #endif
mjr 2:c174f9ee414a 87 if (check_align(address))
mjr 2:c174f9ee414a 88 return AlignError;
mjr 2:c174f9ee414a 89
mjr 2:c174f9ee414a 90 //Setup command
mjr 2:c174f9ee414a 91 FTFA->FCCOB0 = EraseSector;
mjr 2:c174f9ee414a 92 FTFA->FCCOB1 = (address >> 16) & 0xFF;
mjr 2:c174f9ee414a 93 FTFA->FCCOB2 = (address >> 8) & 0xFF;
mjr 2:c174f9ee414a 94 FTFA->FCCOB3 = address & 0xFF;
mjr 2:c174f9ee414a 95
mjr 2:c174f9ee414a 96 run_command(FTFA);
mjr 2:c174f9ee414a 97
mjr 2:c174f9ee414a 98 return check_error();
mjr 2:c174f9ee414a 99 }
mjr 2:c174f9ee414a 100
mjr 2:c174f9ee414a 101 IAPCode FreescaleIAP::program_flash(int address, const void *vp, unsigned int length) {
mjr 2:c174f9ee414a 102
mjr 2:c174f9ee414a 103 const char *data = (const char *)vp;
mjr 2:c174f9ee414a 104
mjr 2:c174f9ee414a 105 #ifdef IAPDEBUG
mjr 2:c174f9ee414a 106 printf("IAP: Programming flash at %x with length %d\r\n", address, length);
mjr 2:c174f9ee414a 107 #endif
mjr 2:c174f9ee414a 108 if (check_align(address))
mjr 2:c174f9ee414a 109 return AlignError;
mjr 2:c174f9ee414a 110
mjr 2:c174f9ee414a 111 IAPCode eraseCheck = verify_erased(address, length);
mjr 2:c174f9ee414a 112 if (eraseCheck != Success)
mjr 2:c174f9ee414a 113 return eraseCheck;
mjr 2:c174f9ee414a 114
mjr 2:c174f9ee414a 115 IAPCode progResult;
mjr 2:c174f9ee414a 116 for (int i = 0; i < length; i+=4) {
mjr 2:c174f9ee414a 117 progResult = program_word(address + i, data + i);
mjr 2:c174f9ee414a 118 if (progResult != Success)
mjr 2:c174f9ee414a 119 return progResult;
mjr 2:c174f9ee414a 120 }
mjr 2:c174f9ee414a 121
mjr 2:c174f9ee414a 122 return Success;
mjr 2:c174f9ee414a 123 }
mjr 2:c174f9ee414a 124
mjr 2:c174f9ee414a 125 uint32_t FreescaleIAP::flash_size(void) {
mjr 2:c174f9ee414a 126 uint32_t retval = (SIM->FCFG2 & 0x7F000000u) >> (24-13);
mjr 2:c174f9ee414a 127 if (SIM->FCFG2 & (1<<23)) //Possible second flash bank
mjr 2:c174f9ee414a 128 retval += (SIM->FCFG2 & 0x007F0000u) >> (16-13);
mjr 2:c174f9ee414a 129 return retval;
mjr 2:c174f9ee414a 130 }
mjr 2:c174f9ee414a 131
mjr 2:c174f9ee414a 132 IAPCode FreescaleIAP::program_word(int address, const char *data) {
mjr 2:c174f9ee414a 133 #ifdef IAPDEBUG
mjr 2:c174f9ee414a 134 printf("IAP: Programming word at %x, %d - %d - %d - %d\r\n", address, data[0], data[1], data[2], data[3]);
mjr 2:c174f9ee414a 135 #endif
mjr 2:c174f9ee414a 136 if (check_align(address))
mjr 2:c174f9ee414a 137 return AlignError;
mjr 2:c174f9ee414a 138
mjr 2:c174f9ee414a 139 //Setup command
mjr 2:c174f9ee414a 140 FTFA->FCCOB0 = ProgramLongword;
mjr 2:c174f9ee414a 141 FTFA->FCCOB1 = (address >> 16) & 0xFF;
mjr 2:c174f9ee414a 142 FTFA->FCCOB2 = (address >> 8) & 0xFF;
mjr 2:c174f9ee414a 143 FTFA->FCCOB3 = address & 0xFF;
mjr 2:c174f9ee414a 144 FTFA->FCCOB4 = data[3];
mjr 2:c174f9ee414a 145 FTFA->FCCOB5 = data[2];
mjr 2:c174f9ee414a 146 FTFA->FCCOB6 = data[1];
mjr 2:c174f9ee414a 147 FTFA->FCCOB7 = data[0];
mjr 2:c174f9ee414a 148
mjr 2:c174f9ee414a 149 run_command(FTFA);
mjr 2:c174f9ee414a 150
mjr 2:c174f9ee414a 151 return check_error();
mjr 2:c174f9ee414a 152 }
mjr 2:c174f9ee414a 153
mjr 2:c174f9ee414a 154 /* Check if no flash boundary is violated
mjr 2:c174f9ee414a 155 Returns true on violation */
mjr 2:c174f9ee414a 156 bool check_boundary(int address, unsigned int length) {
mjr 2:c174f9ee414a 157 int temp = (address+length - 1) / SECTOR_SIZE;
mjr 2:c174f9ee414a 158 address /= SECTOR_SIZE;
mjr 2:c174f9ee414a 159 bool retval = (address != temp);
mjr 2:c174f9ee414a 160 #ifdef IAPDEBUG
mjr 2:c174f9ee414a 161 if (retval)
mjr 2:c174f9ee414a 162 printf("IAP: Boundary violation\r\n");
mjr 2:c174f9ee414a 163 #endif
mjr 2:c174f9ee414a 164 return retval;
mjr 2:c174f9ee414a 165 }
mjr 2:c174f9ee414a 166
mjr 2:c174f9ee414a 167 /* Check if address is correctly aligned
mjr 2:c174f9ee414a 168 Returns true on violation */
mjr 2:c174f9ee414a 169 bool check_align(int address) {
mjr 2:c174f9ee414a 170 bool retval = address & 0x03;
mjr 2:c174f9ee414a 171 #ifdef IAPDEBUG
mjr 2:c174f9ee414a 172 if (retval)
mjr 2:c174f9ee414a 173 printf("IAP: Alignment violation\r\n");
mjr 2:c174f9ee414a 174 #endif
mjr 2:c174f9ee414a 175 return retval;
mjr 2:c174f9ee414a 176 }
mjr 2:c174f9ee414a 177
mjr 2:c174f9ee414a 178 /* Check if an area of flash memory is erased
mjr 2:c174f9ee414a 179 Returns error code or Success (in case of fully erased) */
mjr 2:c174f9ee414a 180 IAPCode FreescaleIAP::verify_erased(int address, unsigned int length) {
mjr 2:c174f9ee414a 181 #ifdef IAPDEBUG
mjr 2:c174f9ee414a 182 printf("IAP: Verify erased at %x with length %d\r\n", address, length);
mjr 2:c174f9ee414a 183 #endif
mjr 2:c174f9ee414a 184
mjr 2:c174f9ee414a 185 if (check_align(address))
mjr 2:c174f9ee414a 186 return AlignError;
mjr 2:c174f9ee414a 187
mjr 2:c174f9ee414a 188 //Setup command
mjr 2:c174f9ee414a 189 FTFA->FCCOB0 = Read1s;
mjr 2:c174f9ee414a 190 FTFA->FCCOB1 = (address >> 16) & 0xFF;
mjr 2:c174f9ee414a 191 FTFA->FCCOB2 = (address >> 8) & 0xFF;
mjr 2:c174f9ee414a 192 FTFA->FCCOB3 = address & 0xFF;
mjr 2:c174f9ee414a 193 FTFA->FCCOB4 = (length >> 10) & 0xFF;
mjr 2:c174f9ee414a 194 FTFA->FCCOB5 = (length >> 2) & 0xFF;
mjr 2:c174f9ee414a 195 FTFA->FCCOB6 = 0;
mjr 2:c174f9ee414a 196
mjr 2:c174f9ee414a 197 run_command(FTFA);
mjr 2:c174f9ee414a 198
mjr 2:c174f9ee414a 199 IAPCode retval = check_error();
mjr 2:c174f9ee414a 200 if (retval == RuntimeError) {
mjr 2:c174f9ee414a 201 #ifdef IAPDEBUG
mjr 2:c174f9ee414a 202 printf("IAP: Flash was not erased\r\n");
mjr 2:c174f9ee414a 203 #endif
mjr 2:c174f9ee414a 204 return EraseError;
mjr 2:c174f9ee414a 205 }
mjr 2:c174f9ee414a 206 return retval;
mjr 2:c174f9ee414a 207
mjr 2:c174f9ee414a 208 }
mjr 2:c174f9ee414a 209
mjr 2:c174f9ee414a 210 /* Check if an error occured
mjr 2:c174f9ee414a 211 Returns error code or Success*/
mjr 2:c174f9ee414a 212 IAPCode check_error(void) {
mjr 2:c174f9ee414a 213 if (FTFA->FSTAT & FTFA_FSTAT_FPVIOL_MASK) {
mjr 2:c174f9ee414a 214 #ifdef IAPDEBUG
mjr 2:c174f9ee414a 215 printf("IAP: Protection violation\r\n");
mjr 2:c174f9ee414a 216 #endif
mjr 2:c174f9ee414a 217 return ProtectionError;
mjr 2:c174f9ee414a 218 }
mjr 2:c174f9ee414a 219 if (FTFA->FSTAT & FTFA_FSTAT_ACCERR_MASK) {
mjr 2:c174f9ee414a 220 #ifdef IAPDEBUG
mjr 2:c174f9ee414a 221 printf("IAP: Flash access error\r\n");
mjr 2:c174f9ee414a 222 #endif
mjr 2:c174f9ee414a 223 return AccessError;
mjr 2:c174f9ee414a 224 }
mjr 2:c174f9ee414a 225 if (FTFA->FSTAT & FTFA_FSTAT_RDCOLERR_MASK) {
mjr 2:c174f9ee414a 226 #ifdef IAPDEBUG
mjr 2:c174f9ee414a 227 printf("IAP: Collision error\r\n");
mjr 2:c174f9ee414a 228 #endif
mjr 2:c174f9ee414a 229 return CollisionError;
mjr 2:c174f9ee414a 230 }
mjr 2:c174f9ee414a 231 if (FTFA->FSTAT & FTFA_FSTAT_MGSTAT0_MASK) {
mjr 2:c174f9ee414a 232 #ifdef IAPDEBUG
mjr 2:c174f9ee414a 233 printf("IAP: Runtime error\r\n");
mjr 2:c174f9ee414a 234 #endif
mjr 2:c174f9ee414a 235 return RuntimeError;
mjr 2:c174f9ee414a 236 }
mjr 2:c174f9ee414a 237 #ifdef IAPDEBUG
mjr 2:c174f9ee414a 238 printf("IAP: No error reported\r\n");
mjr 2:c174f9ee414a 239 #endif
mjr 2:c174f9ee414a 240 return Success;
mjr 2:c174f9ee414a 241 }