Difference between revisions of "83Plus:OS:Raw Flash Commands"
Line 2: | Line 2: | ||
The TI-83+ through TI-84+SE has a flash chip whose data can be erased and rewritten. Issuing write and erase commands is done through memory-mapped writes. The flash chip will not accept any commands unless flash is unlocked. Additionally, any read from flash while issuing a command sequence will abort the command sequence. Consequentially, command sequences can only be issued from RAM and interrupts must be disabled. | The TI-83+ through TI-84+SE has a flash chip whose data can be erased and rewritten. Issuing write and erase commands is done through memory-mapped writes. The flash chip will not accept any commands unless flash is unlocked. Additionally, any read from flash while issuing a command sequence will abort the command sequence. Consequentially, command sequences can only be issued from RAM and interrupts must be disabled. | ||
− | == Flash Commands == | + | == Basic Flash Commands == |
It takes the flash chip a long time to perform a write or erase operation. During this time, it is impossible to read data from the flash chip, because all reads will simply report a status byte. | It takes the flash chip a long time to perform a write or erase operation. During this time, it is impossible to read data from the flash chip, because all reads will simply report a status byte. | ||
Line 137: | Line 137: | ||
ld a, 30h | ld a, 30h | ||
ld (0), a | ld (0), a | ||
− | will resume the erase operation. According to the data sheet, you can start writing data to another sector and resume the erase later. | + | will resume the erase operation. According to the data sheet, you can actually start writing data to another sector and resume the erase later. |
+ | |||
+ | == Autoselect Mode == | ||
+ | The flash chips support a set of commands known as the autoselect commands. These commands are intended to allow the flash chip to identify itself to a manufacturer and to verify that sectors are protected. However, they are also usable in-system. To use the autoselect commands, you must first unlock flash. | ||
+ | |||
+ | The basic code for an autoselect operation is | ||
+ | ; First bus cycle---unlock | ||
+ | ld a, 0AAh | ||
+ | ld (0AAAh), a | ||
+ | ; Second bus cycle---unlock | ||
+ | ld a, 55h | ||
+ | ld (0555h), a | ||
+ | ; Third bus cycle---write command | ||
+ | ld a, 090h | ||
+ | ld (0AAAh), a | ||
+ | ; Read autoselect code | ||
+ | ld a, (address) | ||
+ | ld b, a | ||
+ | ld a, 0F0h | ||
+ | ld (0000h), a | ||
+ | where address is the code for the autoselect command. Address 0 returns the Manufacturer ID; address 2 returns the device ID. Known manufacturer IDs are | ||
+ | {|- | ||
+ | |<u>Manufacturer</u> | ||
+ | |<u>ID</u> | ||
+ | |- | ||
+ | |AMD | ||
+ | |01 | ||
+ | |- | ||
+ | |Fujitsu | ||
+ | |04 | ||
+ | |- | ||
+ | |Unknown, used in new units | ||
+ | |7F | ||
+ | |} | ||
+ | Though the manufacturer ID changes from unit to unit, the device ID should be consistent: | ||
+ | {|- | ||
+ | |<u>Flash Chip Size</u> | ||
+ | |<u>ID</u> | ||
+ | |- | ||
+ | |512 K | ||
+ | |23 | ||
+ | |- | ||
+ | |1 MB | ||
+ | |DA | ||
+ | |- | ||
+ | |2 MB | ||
+ | |C4 | ||
+ | |} | ||
+ | Thus, a TI-83+SE and a TI-84+SE should both have C4 for the device ID; a TI-84+ should have DA for the device ID; and a TI-83+ should have 23 for the device. Unfortunately, I have only tested this for a TI-84+SE. | ||
+ | |||
+ | If you swap the first page of any sector into the 4000h memory bank and read from 4004h, it will return whether or not that sector is protected by the flash chip's built-in write/erase lock. Since TI does not use that feature of the flash chip, it always returns 0 (a 1 would indicate that the sector is locked). |
Revision as of 00:19, 29 June 2011
The TI-83+ through TI-84+SE has a flash chip whose data can be erased and rewritten. Issuing write and erase commands is done through memory-mapped writes. The flash chip will not accept any commands unless flash is unlocked. Additionally, any read from flash while issuing a command sequence will abort the command sequence. Consequentially, command sequences can only be issued from RAM and interrupts must be disabled.
Contents
Basic Flash Commands
It takes the flash chip a long time to perform a write or erase operation. During this time, it is impossible to read data from the flash chip, because all reads will simply report a status byte.
Reset
You can reset the flash chip at any time by writing 0F0h to 0000h.
ld a, 0F0h ld (0), a
Reset the flash chip if a program or erase operation fails, to abort either of those, and to leave autoselect mode.
Writing
The design of flash memory is such that a 0 can be written over a 1, but the reverse is not possible. Any write attempting to do this will fail. To write a 1 over a 0, see the below.
writeFlashByte: ; Writes a byte to flash. Flash must be unlocked. Be aware that pressing CLEAR ; will abort the write. ; Inputs: ; - B: Byte to write ; - C: Page ; - HL: Address to write to. This will not be wrapped. ; Outputs: ; - NZ on failure ; Kills: ; - AF, BC ; Protips: ; - Calling writeFlashByteRaw instead will skip the page changing ; - Do push bc \ pop af afterwards to restore flags to pre-call values. That's ; right, documented side-effect programming! in a, (memPageAPort) ; save page push af ld a, c out (6), a di call writeFlashByteRaw ei pop bc ; restore page without screwing up flags ld a, b out (memPageAPort), a ret writeFlashByteRaw: ; Flash program sequence ld a, 0AAh ; First bus cycle---unlock ld (0AAAh), a ld a, 55h ; Second bus cycle---unlock ld (0555h), a ld a, 0A0h ; Third bus cycle---write command ld (0AAAh), a ld (hl), b ; Fourth bus cycle---program data ; Wait for the write operation to complete ld a, 0FDh ; This checks for the CLEAR key. out (keyPort), a ; If pressed, it aborts. inc hl dec hl programWaitLoop: in a, (keyPort) cp 0BFh jr z, abortProgram ld a, b xor (hl) bit 7, a jr z, programDone bit 5, (hl) jr z, programWaitLoop abortProgram: ld a, 0F0h ld (0000h), a inc a programDone: ret
Erasing
The design of flash memory is such that writing a 1 over a 0 is not possible, except in large blocks known as sectors. The flash chips TI likes to use have sectors that are almost all 64 K in size, except the last which, which is broken up into several sectors. Erase operations take a long time, during which running code from flash is impossible. If you want, you could probably make a something blink or something while you're waiting.
eraseSector: ; Erases a sector of flash. Note: Use eraseSectorRaw for the certificate. ; Inputs: ; - C: Page ; Outputs: ; - Z on fail (this is opposite of writeFlashByte) ; Kills: ; - AF, BC, HL in a, (memPageAPort) push af ld a, c out (memPageAPort), a ld hl, 4000h di call eraseSectorRaw ei pop bc ld a, b out (memPageAPort), a ret eraseSectorRaw: ; Flash program sequence ld a, 0AAh ; First bus cycle---unlock ld (0AAAh), a ld a, 55h ; Second bus cycle---unlock ld (0555h), a ld a, 080h ; Third bus cycle---write command ld (0AAAh), a ld a, 0AAh ; Fourth bus cycle---unlock (again) ld (0AAAh), a ld a, 55h ; Fifth bus cycle---unlock (again) ld (0555h), a ld a, 30h ; Do not change this value. In theory, you could superbrick your calculator. ld (hl), a ; Wait for the erase operation to complete ld a, 0FDh out (keyPort), a inc hl dec hl eraseWaitLoop: in a, (keyPort) cp 0BFh jr z, abortErase ld a, (hl) bit 7, a jr nz, eraseDone bit 5, a jr z, eraseWaitLoop abortErase: ld a, 0F0h ld (4000h), a xor a eraseDone: ret
Erase Suspend
The flash chip support suspending an erase operation in program. This allows you to read data from the flash chip again. I'm not sure why would want to do this, but
ld a, 0B0h ld (0), a
will suspend an erase operation. Then
ld a, 30h ld (0), a
will resume the erase operation. According to the data sheet, you can actually start writing data to another sector and resume the erase later.
Autoselect Mode
The flash chips support a set of commands known as the autoselect commands. These commands are intended to allow the flash chip to identify itself to a manufacturer and to verify that sectors are protected. However, they are also usable in-system. To use the autoselect commands, you must first unlock flash.
The basic code for an autoselect operation is
; First bus cycle---unlock ld a, 0AAh ld (0AAAh), a ; Second bus cycle---unlock ld a, 55h ld (0555h), a ; Third bus cycle---write command ld a, 090h ld (0AAAh), a ; Read autoselect code ld a, (address) ld b, a ld a, 0F0h ld (0000h), a
where address is the code for the autoselect command. Address 0 returns the Manufacturer ID; address 2 returns the device ID. Known manufacturer IDs are
Manufacturer | ID |
AMD | 01 |
Fujitsu | 04 |
Unknown, used in new units | 7F |
Though the manufacturer ID changes from unit to unit, the device ID should be consistent:
Flash Chip Size | ID |
512 K | 23 |
1 MB | DA |
2 MB | C4 |
Thus, a TI-83+SE and a TI-84+SE should both have C4 for the device ID; a TI-84+ should have DA for the device ID; and a TI-83+ should have 23 for the device. Unfortunately, I have only tested this for a TI-84+SE.
If you swap the first page of any sector into the 4000h memory bank and read from 4004h, it will return whether or not that sector is protected by the flash chip's built-in write/erase lock. Since TI does not use that feature of the flash chip, it always returns 0 (a 1 would indicate that the sector is locked).