Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed FastIO FastPWM USBDevice
FreescaleIAP/IAP.s@60:f38da020aa13, 2016-05-13 (annotated)
- Committer:
- mjr
- Date:
- Fri May 13 21:28:41 2016 +0000
- Revision:
- 60:f38da020aa13
- Parent:
- 59:94eb9265b6d7
- Child:
- 76:7f5912b6340e
Try to bulletproof the Flash programming procedure by using techniques recommended in ARM forums; enhanced comments in main routine
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| mjr | 59:94eb9265b6d7 | 1 | ; Put this in READWRITE memory, to ensure that it goes in RAM |
| mjr | 59:94eb9265b6d7 | 2 | ; rather than flash. |
| mjr | 59:94eb9265b6d7 | 3 | AREA iapexec_asm_code, CODE, READWRITE |
| mjr | 59:94eb9265b6d7 | 4 | |
| mjr | 59:94eb9265b6d7 | 5 | ; iapExecAsm(FSTAT) |
| mjr | 59:94eb9265b6d7 | 6 | ; FSTAT = address of ftfa->FSTAT register |
| mjr | 59:94eb9265b6d7 | 7 | ; |
| mjr | 59:94eb9265b6d7 | 8 | ; Note: arguments passed in R0, R1... |
| mjr | 59:94eb9265b6d7 | 9 | EXPORT iapExecAsm |
| mjr | 59:94eb9265b6d7 | 10 | iapExecAsm |
| mjr | 60:f38da020aa13 | 11 | ; Do a layered call to our main handler routine. Advice on ARM |
| mjr | 60:f38da020aa13 | 12 | ; forums suggests that before we carry out the Flash write, we should |
| mjr | 60:f38da020aa13 | 13 | ; do an extra call layer from one RAM-resident code block to another |
| mjr | 60:f38da020aa13 | 14 | ; RAM-resident code block, with the inner block firing off the actual |
| mjr | 60:f38da020aa13 | 15 | ; FTFA execution. This supposedly will reduce the chances of core |
| mjr | 60:f38da020aa13 | 16 | ; lockup during the write. This strikes me as probably superstitious |
| mjr | 60:f38da020aa13 | 17 | ; in origin ("it was crashing and then I made some random changes to |
| mjr | 60:f38da020aa13 | 18 | ; the code that I can't remember and also knocked three times on the |
| mjr | 60:f38da020aa13 | 19 | ; desk and then it worked, so always knock three times on a desk"). |
| mjr | 60:f38da020aa13 | 20 | ; But I have indeed seen random crashes, and this is only a few bytes |
| mjr | 60:f38da020aa13 | 21 | ; of extra code, so what the heck. |
| mjr | 60:f38da020aa13 | 22 | ; |
| mjr | 60:f38da020aa13 | 23 | ; If there's a real justification for this, it's probably that the |
| mjr | 60:f38da020aa13 | 24 | ; extra call fills up the CPU instruction fetch/pre-fetch mechanism |
| mjr | 60:f38da020aa13 | 25 | ; with RAM addresses, flushing out any remaining Flash addresses that |
| mjr | 60:f38da020aa13 | 26 | ; might trigger an asynchronous Flash read from the CPU instruction |
| mjr | 60:f38da020aa13 | 27 | ; fetch mechanism. The big hazard with programming Flash through the |
| mjr | 60:f38da020aa13 | 28 | ; FTFA is that any read access to the Flash will fail while a write |
| mjr | 60:f38da020aa13 | 29 | ; operation is in progress. This will cause a CPU lockup if such a |
| mjr | 60:f38da020aa13 | 30 | ; read comes from the instruction fetcher. |
| mjr | 60:f38da020aa13 | 31 | ; |
| mjr | 60:f38da020aa13 | 32 | ; Simply push the link register, call our main routine, and return. |
| mjr | 60:f38da020aa13 | 33 | ; Arguments are in registers (R0, R1, ...), so they'll just pass |
| mjr | 60:f38da020aa13 | 34 | ; through to the callee. |
| mjr | 60:f38da020aa13 | 35 | STMFD R13!, {LR} |
| mjr | 60:f38da020aa13 | 36 | BL iapExecMain |
| mjr | 60:f38da020aa13 | 37 | LDMFD R13!, {PC} |
| mjr | 59:94eb9265b6d7 | 38 | |
| mjr | 60:f38da020aa13 | 39 | ; |
| mjr | 60:f38da020aa13 | 40 | ; Main routine |
| mjr | 60:f38da020aa13 | 41 | ; |
| mjr | 60:f38da020aa13 | 42 | iapExecMain |
| mjr | 59:94eb9265b6d7 | 43 | ; push R1, R2, link |
| mjr | 59:94eb9265b6d7 | 44 | STMFD R13!, {R1,R2,LR} |
| mjr | 60:f38da020aa13 | 45 | |
| mjr | 60:f38da020aa13 | 46 | ; Advice on ARM forums suggests that we should add a little artificial |
| mjr | 60:f38da020aa13 | 47 | ; delay here to avoid core lockup. The point seems to be to reduce the |
| mjr | 60:f38da020aa13 | 48 | ; chances that a bus operation related to instruction fetching will hit |
| mjr | 60:f38da020aa13 | 49 | ; the Flash while the write operation is executing. This seems as |
| mjr | 60:f38da020aa13 | 50 | ; superstitious as the extra layered call (see above), but just in case... |
| mjr | 60:f38da020aa13 | 51 | MOVS R1, #100 ; loop counter |
| mjr | 60:f38da020aa13 | 52 | L0 |
| mjr | 60:f38da020aa13 | 53 | SUBS R1, R1, #1 ; R1 = R1 - 1 |
| mjr | 60:f38da020aa13 | 54 | BNE L0 ; loop until we reach 0 |
| mjr | 59:94eb9265b6d7 | 55 | |
| mjr | 60:f38da020aa13 | 56 | ; NB - caller is responsible for doing this |
| mjr | 60:f38da020aa13 | 57 | ; clear old errors from status bits |
| mjr | 60:f38da020aa13 | 58 | ;MOVS R1, #0x70 ; FPVIOL (0x10) | ACCERR (0x20) | RDCOLOERR (0x40) |
| mjr | 60:f38da020aa13 | 59 | ;STRB R1, [R0] |
| mjr | 59:94eb9265b6d7 | 60 | |
| mjr | 59:94eb9265b6d7 | 61 | ; start command |
| mjr | 59:94eb9265b6d7 | 62 | MOVS R1, #0x80 ; CCIF (0x80) |
| mjr | 59:94eb9265b6d7 | 63 | STRB R1, [R0] |
| mjr | 59:94eb9265b6d7 | 64 | |
| mjr | 59:94eb9265b6d7 | 65 | ; wait until command completed - the CCIF bit is SET when the command completes |
| mjr | 59:94eb9265b6d7 | 66 | MOVS R2, #0x80 ; CCIF (0x80) |
| mjr | 59:94eb9265b6d7 | 67 | L1 |
| mjr | 59:94eb9265b6d7 | 68 | LDRB R1, [R0] |
| mjr | 59:94eb9265b6d7 | 69 | TSTS R1, R2 ; CCIF (0x80) |
| mjr | 59:94eb9265b6d7 | 70 | BEQ L1 |
| mjr | 59:94eb9265b6d7 | 71 | |
| mjr | 59:94eb9265b6d7 | 72 | ; pop registers and return |
| mjr | 59:94eb9265b6d7 | 73 | LDMFD R13!, {R1,R2,PC} |
| mjr | 59:94eb9265b6d7 | 74 | |
| mjr | 59:94eb9265b6d7 | 75 | END |
| mjr | 59:94eb9265b6d7 | 76 |