Mirror with some correction
Dependencies: mbed FastIO FastPWM USBDevice
FreescaleIAP/IAP.s@76:7f5912b6340e, 2017-02-03 (annotated)
- Committer:
- mjr
- Date:
- Fri Feb 03 20:50:02 2017 +0000
- Revision:
- 76:7f5912b6340e
- Parent:
- 60:f38da020aa13
- Child:
- 77:0b96f6867312
Rework flash driver to make it truly stable (hopefully to 100% reliability); host-loaded configuration; performance improvements; more performance diagnostics.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
mjr | 76:7f5912b6340e | 1 | ; FreescaleIAP assembly functions |
mjr | 76:7f5912b6340e | 2 | ; |
mjr | 76:7f5912b6340e | 3 | ; Put all code here in READWRITE memory, to ensure that it goes in RAM |
mjr | 59:94eb9265b6d7 | 4 | ; rather than flash. |
mjr | 59:94eb9265b6d7 | 5 | AREA iapexec_asm_code, CODE, READWRITE |
mjr | 76:7f5912b6340e | 6 | |
mjr | 76:7f5912b6340e | 7 | ;--------------------------------------------------------------------------- |
mjr | 76:7f5912b6340e | 8 | ; iapEraseSector(FTFA_Type *FTFA, uint32_t address) |
mjr | 76:7f5912b6340e | 9 | ; R0 = FTFA pointer |
mjr | 76:7f5912b6340e | 10 | ; R1 = starting address |
mjr | 59:94eb9265b6d7 | 11 | |
mjr | 76:7f5912b6340e | 12 | EXPORT iapEraseSector |
mjr | 76:7f5912b6340e | 13 | iapEraseSector |
mjr | 76:7f5912b6340e | 14 | ; save registers |
mjr | 76:7f5912b6340e | 15 | STMFD R13!,{R1,R4,LR} |
mjr | 76:7f5912b6340e | 16 | |
mjr | 76:7f5912b6340e | 17 | ; Ensure that no interrupts occur while we're erasing. This is |
mjr | 76:7f5912b6340e | 18 | ; vitally important, because the flash controller doesn't allow |
mjr | 76:7f5912b6340e | 19 | ; anyone to read from flash while an erase is in progress. Most |
mjr | 76:7f5912b6340e | 20 | ; of the program code is in flash, which means that any interrupt |
mjr | 76:7f5912b6340e | 21 | ; would invoke flash code, causing the CPU to fetch from flash, |
mjr | 76:7f5912b6340e | 22 | ; violating the no-read-during-erase rule. The CPU instruction |
mjr | 76:7f5912b6340e | 23 | ; fetch would fail, causing the CPU to lock up. |
mjr | 76:7f5912b6340e | 24 | CPSID I ; interrupts off |
mjr | 76:7f5912b6340e | 25 | DMB ; data memory barrier |
mjr | 76:7f5912b6340e | 26 | ISB ; instruction synchronization barrier |
mjr | 76:7f5912b6340e | 27 | |
mjr | 76:7f5912b6340e | 28 | ; wait for any previous command to complete |
mjr | 76:7f5912b6340e | 29 | BL iapWait |
mjr | 60:f38da020aa13 | 30 | |
mjr | 76:7f5912b6340e | 31 | ; clear any errors |
mjr | 76:7f5912b6340e | 32 | BL iapClearErrors |
mjr | 76:7f5912b6340e | 33 | |
mjr | 76:7f5912b6340e | 34 | ; set up the command parameters |
mjr | 76:7f5912b6340e | 35 | MOVS R4,#0 |
mjr | 76:7f5912b6340e | 36 | STRB R4,[R0,#1] ; FTFA->FCNFG <- 0 |
mjr | 76:7f5912b6340e | 37 | MOVS R4,#9 ; command = erase sector (9) |
mjr | 76:7f5912b6340e | 38 | STRB R4,[R0,#7] ; FTFA->FCCOB0 <- command |
mjr | 76:7f5912b6340e | 39 | |
mjr | 76:7f5912b6340e | 40 | STRB R1,[R0,#4] ; FTFA->FCCOB3 <- address bits 16-23 |
mjr | 59:94eb9265b6d7 | 41 | |
mjr | 76:7f5912b6340e | 42 | MOVS R1,R1,LSR #8 ; address >>= 8 |
mjr | 76:7f5912b6340e | 43 | STRB R1,[R0,#5] ; FTFA->FCCOB2 <- address bits 8-15 |
mjr | 76:7f5912b6340e | 44 | |
mjr | 76:7f5912b6340e | 45 | MOVS R1,R1,LSR #8 ; address >>= 8 |
mjr | 76:7f5912b6340e | 46 | STRB R1,[R0,#6] ; FTFA->FCCOB1 <- address bits 0-7 |
mjr | 59:94eb9265b6d7 | 47 | |
mjr | 76:7f5912b6340e | 48 | ; execute and wait for completion |
mjr | 76:7f5912b6340e | 49 | BL iapExec |
mjr | 76:7f5912b6340e | 50 | BL iapWait |
mjr | 76:7f5912b6340e | 51 | |
mjr | 76:7f5912b6340e | 52 | ; restore interrupts |
mjr | 76:7f5912b6340e | 53 | CPSIE I |
mjr | 59:94eb9265b6d7 | 54 | |
mjr | 59:94eb9265b6d7 | 55 | ; pop registers and return |
mjr | 76:7f5912b6340e | 56 | LDMFD R13!,{R1,R4,PC} |
mjr | 76:7f5912b6340e | 57 | |
mjr | 76:7f5912b6340e | 58 | ;--------------------------------------------------------------------------- |
mjr | 76:7f5912b6340e | 59 | ; iapProgramBlock(TFA_Type *ftfa, uint32_t address, const void *src, uint32_t length) |
mjr | 76:7f5912b6340e | 60 | ; R0 = FTFA pointer |
mjr | 76:7f5912b6340e | 61 | ; R1 = flash address |
mjr | 76:7f5912b6340e | 62 | ; R2 = source data pointer |
mjr | 76:7f5912b6340e | 63 | ; R3 = data length in bytes |
mjr | 76:7f5912b6340e | 64 | |
mjr | 76:7f5912b6340e | 65 | EXPORT iapProgramBlock |
mjr | 76:7f5912b6340e | 66 | iapProgramBlock |
mjr | 76:7f5912b6340e | 67 | ; save registers |
mjr | 76:7f5912b6340e | 68 | STMFD R13!, {R1,R2,R3,R4,LR} |
mjr | 76:7f5912b6340e | 69 | |
mjr | 76:7f5912b6340e | 70 | ; Turn off interrupts while we're working. Flash reading |
mjr | 76:7f5912b6340e | 71 | ; while writing doesn't seem to be forbidden the way it is |
mjr | 76:7f5912b6340e | 72 | ; while erasing (see above), but even so, each longword |
mjr | 76:7f5912b6340e | 73 | ; transfer requires writing to 10 separate registers, so |
mjr | 76:7f5912b6340e | 74 | ; there's a lot of static state involved - we don't want |
mjr | 76:7f5912b6340e | 75 | ; any other code sneaking in and changing anything on us. |
mjr | 76:7f5912b6340e | 76 | CPSID I ; interrupts off |
mjr | 76:7f5912b6340e | 77 | DMB ; data memory barrier |
mjr | 76:7f5912b6340e | 78 | ISB ; instruction synchronization barrier |
mjr | 76:7f5912b6340e | 79 | |
mjr | 76:7f5912b6340e | 80 | ; wait for any previous command to complete |
mjr | 76:7f5912b6340e | 81 | BL iapWait |
mjr | 76:7f5912b6340e | 82 | |
mjr | 76:7f5912b6340e | 83 | ; iterate over the data |
mjr | 76:7f5912b6340e | 84 | LpLoop |
mjr | 76:7f5912b6340e | 85 | CMPS R3,#3 ; at least one longword left (>= 4 bytes)? |
mjr | 76:7f5912b6340e | 86 | BLS LpDone ; no, done |
mjr | 76:7f5912b6340e | 87 | |
mjr | 76:7f5912b6340e | 88 | ; clear any errors from the previous command |
mjr | 76:7f5912b6340e | 89 | BL iapClearErrors |
mjr | 76:7f5912b6340e | 90 | |
mjr | 76:7f5912b6340e | 91 | ; set up the command parameters |
mjr | 76:7f5912b6340e | 92 | MOVS R4,#0 |
mjr | 76:7f5912b6340e | 93 | STRB R4,[R0,#1] ; FTFA->FCNFG <- 0 |
mjr | 76:7f5912b6340e | 94 | MOVS R4,#6 ; command = program longword (6) |
mjr | 76:7f5912b6340e | 95 | STRB R4,[R0,#7] ; FTFA->FCCOB0 <- command |
mjr | 76:7f5912b6340e | 96 | |
mjr | 76:7f5912b6340e | 97 | MOVS R4,R1 ; R4 <- current address |
mjr | 76:7f5912b6340e | 98 | STRB R4,[R0,#4] ; FTFA->FCCOB3 <- address bits 16-23 |
mjr | 76:7f5912b6340e | 99 | |
mjr | 76:7f5912b6340e | 100 | MOVS R4,R4,LSR #8 ; address >>= 8 |
mjr | 76:7f5912b6340e | 101 | STRB R4,[R0,#5] ; FTFA->FCCOB2 <- address bits 8-15 |
mjr | 76:7f5912b6340e | 102 | |
mjr | 76:7f5912b6340e | 103 | MOVS R4,R4,LSR #8 ; address >>= 8 |
mjr | 76:7f5912b6340e | 104 | STRB R4,[R0,#6] ; FTFA->FCCOB1 <- address bits 0-7 |
mjr | 76:7f5912b6340e | 105 | |
mjr | 76:7f5912b6340e | 106 | LDRB R4,[R2] ; R4 <- data[0] |
mjr | 76:7f5912b6340e | 107 | STRB R4,[R0,#8] ; FTFA->FCCOB7 <- data[0] |
mjr | 76:7f5912b6340e | 108 | |
mjr | 76:7f5912b6340e | 109 | LDRB R4,[R2,#1] ; R4 <- data[1] |
mjr | 76:7f5912b6340e | 110 | STRB R4,[R0,#9] ; FTFA->FCCOB6 <- data[1] |
mjr | 76:7f5912b6340e | 111 | |
mjr | 76:7f5912b6340e | 112 | LDRB R4,[R2,#2] ; R4 <- data[2] |
mjr | 76:7f5912b6340e | 113 | STRB R4,[R0,#0xA] ; FTFA->FCCOB5 <- data[2] |
mjr | 76:7f5912b6340e | 114 | |
mjr | 76:7f5912b6340e | 115 | LDRB R4,[R2,#3] ; R4 <- data[3] |
mjr | 76:7f5912b6340e | 116 | STRB R4,[R0,#0xB] ; FTBA->FCCOB4 <- data[3] |
mjr | 76:7f5912b6340e | 117 | |
mjr | 76:7f5912b6340e | 118 | ; execute the command |
mjr | 76:7f5912b6340e | 119 | BL iapExec |
mjr | 76:7f5912b6340e | 120 | |
mjr | 76:7f5912b6340e | 121 | ; advance to the next longword |
mjr | 76:7f5912b6340e | 122 | ADDS R1,R1,#4 ; flash address += 4 |
mjr | 76:7f5912b6340e | 123 | ADDS R2,R2,#4 ; source data pointer += 4 |
mjr | 76:7f5912b6340e | 124 | SUBS R3,R3,#4 ; data length -= 4 |
mjr | 76:7f5912b6340e | 125 | B LpLoop ; back for the next iteration |
mjr | 76:7f5912b6340e | 126 | |
mjr | 76:7f5912b6340e | 127 | LpDone |
mjr | 76:7f5912b6340e | 128 | ; restore interrupts |
mjr | 76:7f5912b6340e | 129 | CPSIE I |
mjr | 76:7f5912b6340e | 130 | |
mjr | 76:7f5912b6340e | 131 | ; pop registers and return |
mjr | 76:7f5912b6340e | 132 | LDMFD R13!, {R1,R2,R3,R4,PC} |
mjr | 76:7f5912b6340e | 133 | |
mjr | 76:7f5912b6340e | 134 | |
mjr | 76:7f5912b6340e | 135 | ;--------------------------------------------------------------------------- |
mjr | 76:7f5912b6340e | 136 | ; iapClearErrors(FTFA_Type *FTFA) - clear errors from previous command |
mjr | 76:7f5912b6340e | 137 | ; R0 = FTFA pointer |
mjr | 76:7f5912b6340e | 138 | |
mjr | 76:7f5912b6340e | 139 | iapClearErrors |
mjr | 76:7f5912b6340e | 140 | ; save registers |
mjr | 76:7f5912b6340e | 141 | STMFD R13!, {R2,R3,LR} |
mjr | 76:7f5912b6340e | 142 | |
mjr | 76:7f5912b6340e | 143 | LDRB R2, [R0] ; R2 <- FTFA->FSTAT |
mjr | 76:7f5912b6340e | 144 | MOVS R3, #0x30 ; FPVIOL (0x10) | ACCERR (0x20) |
mjr | 76:7f5912b6340e | 145 | ANDS R2, R2, R3 ; R2 &= error bits |
mjr | 76:7f5912b6340e | 146 | BEQ Lc0 ; if all zeros, no need to reset anything |
mjr | 76:7f5912b6340e | 147 | STRB R2, [R0] ; write the 1 bits back to clear the error status |
mjr | 76:7f5912b6340e | 148 | Lc0 |
mjr | 76:7f5912b6340e | 149 | ; restore registers and return |
mjr | 76:7f5912b6340e | 150 | LDMFD R13!, {R2,R3,PC} |
mjr | 76:7f5912b6340e | 151 | |
mjr | 76:7f5912b6340e | 152 | |
mjr | 76:7f5912b6340e | 153 | ;--------------------------------------------------------------------------- |
mjr | 76:7f5912b6340e | 154 | ; iapWait(FTFA_Type *FTFA) - wait for command to complete |
mjr | 76:7f5912b6340e | 155 | ; R0 = FTFA pointer |
mjr | 76:7f5912b6340e | 156 | |
mjr | 76:7f5912b6340e | 157 | iapWait |
mjr | 76:7f5912b6340e | 158 | ; save registers |
mjr | 76:7f5912b6340e | 159 | STMFD R13!, {R1,R2,LR} |
mjr | 76:7f5912b6340e | 160 | |
mjr | 76:7f5912b6340e | 161 | ; the CCIF bit is SET when the command completes |
mjr | 76:7f5912b6340e | 162 | Lw0 |
mjr | 76:7f5912b6340e | 163 | LDRB R1, [R0] ; R1 <- FTFA->FSTAT |
mjr | 76:7f5912b6340e | 164 | MOVS R2, #0x80 ; CCIF (0x80) |
mjr | 76:7f5912b6340e | 165 | TSTS R1, R2 ; test R1 & CCIF |
mjr | 76:7f5912b6340e | 166 | BEQ Lw0 ; if zero, the command is still running |
mjr | 76:7f5912b6340e | 167 | |
mjr | 76:7f5912b6340e | 168 | LwDone |
mjr | 76:7f5912b6340e | 169 | ; pop registers and return |
mjr | 59:94eb9265b6d7 | 170 | LDMFD R13!, {R1,R2,PC} |
mjr | 76:7f5912b6340e | 171 | |
mjr | 76:7f5912b6340e | 172 | |
mjr | 76:7f5912b6340e | 173 | ;--------------------------------------------------------------------------- |
mjr | 76:7f5912b6340e | 174 | ; iapExec(FTFA_Type *FTFA) |
mjr | 76:7f5912b6340e | 175 | ; R0 = FTFA pointer |
mjr | 76:7f5912b6340e | 176 | |
mjr | 76:7f5912b6340e | 177 | iapExec |
mjr | 76:7f5912b6340e | 178 | ; save registers |
mjr | 76:7f5912b6340e | 179 | STMFD R13!, {R1,LR} |
mjr | 76:7f5912b6340e | 180 | |
mjr | 76:7f5912b6340e | 181 | ; write the CCIF bit to launch the command |
mjr | 76:7f5912b6340e | 182 | MOVS R1, #0x80 ; CCIF (0x80) |
mjr | 76:7f5912b6340e | 183 | STRB R1, [R0] ; FTFA->FSTAT = CCIF |
mjr | 76:7f5912b6340e | 184 | |
mjr | 76:7f5912b6340e | 185 | ; wait until command completed |
mjr | 76:7f5912b6340e | 186 | BL iapWait |
mjr | 76:7f5912b6340e | 187 | |
mjr | 76:7f5912b6340e | 188 | ; pop registers and return |
mjr | 76:7f5912b6340e | 189 | LDMFD R13!, {R1,PC} |
mjr | 59:94eb9265b6d7 | 190 | |
mjr | 59:94eb9265b6d7 | 191 | END |
mjr | 59:94eb9265b6d7 | 192 |