Mirror with some correction
Dependencies: mbed FastIO FastPWM USBDevice
Diff: FreescaleIAP/FreescaleIAP.cpp
- Revision:
- 60:f38da020aa13
- Parent:
- 59:94eb9265b6d7
- Child:
- 76:7f5912b6340e
--- a/FreescaleIAP/FreescaleIAP.cpp Thu May 12 05:57:53 2016 +0000 +++ b/FreescaleIAP/FreescaleIAP.cpp Fri May 13 21:28:41 2016 +0000 @@ -54,13 +54,6 @@ // execute an FTFA command static inline void run_command(FTFA_Type *ftfa) { - // Disable interupts. It's critical that we don't service any - // interrupts while a Flash operation is taking place because - // an ISR would normally be a C routine located in Flash, so - // fetching its instructions could deadlock against the write - // or erase operation we're performing. - __disable_irq(); - #if USE_ASM_EXEC // Call our RAM-based assembly routine to do this work. The // assembler routine implements the same ftfa->FSTAT register @@ -71,12 +64,9 @@ // 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)); + while (!(ftfa->FSTAT & FTFA_FSTAT_CCIF_MASK)) ; #endif // USE_ASM_EXEC - - // done with the Flash access - re-enable interrupts - __enable_irq(); } @@ -86,14 +76,34 @@ #endif if (check_align(address)) return AlignError; + + // divide the sector address into the three bytes for the three + // registers first, to reduce the risk of the operation being + // corrupted + uint8_t temp1 = (address >> 16) & 0xFF; + uint8_t temp2 = (address >> 8) & 0xFF; + uint8_t temp3 = address & 0xFF; - //Setup command + // clear interrupts while working + __disable_irq(); + + // wait for any previous commands to clear + while (!(FTFA->FSTAT & FTFA_FSTAT_CCIF_MASK)) ; + + // clear previous errors + FTFA->FSTAT = FTFA_FSTAT_FPVIOL_MASK | FTFA_FSTAT_ACCERR_MASK | FTFA_FSTAT_RDCOLERR_MASK; + + // set up the command FTFA->FCCOB0 = EraseSector; - FTFA->FCCOB1 = (address >> 16) & 0xFF; - FTFA->FCCOB2 = (address >> 8) & 0xFF; - FTFA->FCCOB3 = address & 0xFF; + FTFA->FCCOB1 = temp1; + FTFA->FCCOB2 = temp2; + FTFA->FCCOB3 = temp3; + + // execute it + run_command(FTFA); - run_command(FTFA); + // re-enable interrupts + __enable_irq(); return check_error(); } @@ -135,19 +145,45 @@ #endif if (check_align(address)) return AlignError; + + + // figure the three bytes of the address first + uint8_t temp1 = (address >> 16) & 0xFF; + uint8_t temp2 = (address >> 8) & 0xFF; + uint8_t temp3 = address & 0xFF; - //Setup command + // get the data bytes into temps as well + uint8_t temp4 = data[3]; + uint8_t temp5 = data[2]; + uint8_t temp6 = data[1]; + uint8_t temp7 = data[0]; + + // interrupts off while working + __disable_irq(); + + // wait for any previous commands to clear + while (!(FTFA->FSTAT & FTFA_FSTAT_CCIF_MASK)) ; + + // clear previous errors + FTFA->FSTAT = FTFA_FSTAT_FPVIOL_MASK | FTFA_FSTAT_ACCERR_MASK | FTFA_FSTAT_RDCOLERR_MASK; + + // Set up the 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]; - + FTFA->FCCOB1 = temp1; + FTFA->FCCOB2 = temp2; + FTFA->FCCOB3 = temp3; + FTFA->FCCOB4 = temp4; + FTFA->FCCOB5 = temp5; + FTFA->FCCOB6 = temp6; + FTFA->FCCOB7 = temp7; + + // execute the command run_command(FTFA); + // interrupts on + __enable_irq(); + + // return error indication return check_error(); } @@ -185,17 +221,39 @@ if (check_align(address)) return AlignError; - //Setup command + // get the address into temps + uint8_t temp1 = (address >> 16) & 0xFF; + uint8_t temp2 = (address >> 8) & 0xFF; + uint8_t temp3 = address & 0xFF; + + // get the length into temps as well + uint8_t temp4 = (length >> 10) & 0xFF; + uint8_t temp5 = (length >> 2) & 0xFF; + + // interrupts off while working + __disable_irq(); + + // wait for any previous commands to clear + while (!(FTFA->FSTAT & FTFA_FSTAT_CCIF_MASK)) ; + + // clear previous errors + FTFA->FSTAT = FTFA_FSTAT_FPVIOL_MASK | FTFA_FSTAT_ACCERR_MASK | FTFA_FSTAT_RDCOLERR_MASK; + + // Set up the 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->FCCOB1 = temp1; + FTFA->FCCOB2 = temp2; + FTFA->FCCOB3 = temp3; + FTFA->FCCOB4 = temp4; + FTFA->FCCOB5 = temp5; FTFA->FCCOB6 = 0; + // execute run_command(FTFA); + // interrupts on + __enable_irq(); + IAPCode retval = check_error(); if (retval == RuntimeError) { #ifdef IAPDEBUG