Using OpenOCD r717 and the JTAG interface, the flash memory of the HP20B was modified.
First, one of the unused pages near the end of memory was modified. Page 0x1fe (address 0x1fe00 - 0x1feff) is blank in the stock HP firmware (all bytes 0xff). A 256 byte text file was generated, and OpenOCD's telnet interface used to program the flash. The process was simple.
First, the page is written into the flash write buffer. The flash write buffer is one page (256 bytes) long and it will catch any writes to the flash memory region.
> load_image test.bin 0 256 byte written at address 0x00000000 downloaded 256 byte in 0.015625s
The flash module was commanded to write the page. The command consists of a key (0x5a), a page number (0x01fe), and a command (0x01==write page without erase).
> mww 0xffffff64 0x5a01fe01
The status of the flash module was examined to see if the command had completed. 0x01 indicates that the flash module is ready for the next command.
> mdw 0xffffff68 0xffffff68: 00000001
The entire flash memory was dumped to a file to verify that the 0x1fe page was indeed modified.
> dump_image flash_write_test.bin 0 0x20000 dumped 131072 byte in 10.968601s
An external diff utility was used to verify that the calculator's modified flash image was different than the stock flash image. It was!
Interestingly, the self test checksum still read as 213. The self test checksum routine must not checksum the entire flash memory. (I suspect that it checksums up to 0x1ec40, which contains a 0xd5 byte, matching the displayed checksum.) No operational change was noted in the calculator with the modified flash memory. None was expected, as page 0x1fe was blank in the stock flash image.
The next step was to modify part of the active flash memory. Page 0x1da was chosen, as it contains ASCII text. Specifically, one of the on screen prompts visible in the test menu was modified. For this experiment, the flash write command was 0x5101da03, which would first erase page 0x1da and then program it. As in the first experiment, the entire flash image was dumped and compared to stock to verify that the modification occured. Once again, the flash image was different. This modification also affected the checksum, which is now displayed as “16.213”.
Placing the calculator into the test mode revealed that the modified prompts were in place. No other changes were noticeable in the operation of the calculator. (None were expected, as the modifications were minor and limited to known text prompts.)
The method described here is tedious and slow–it is limited to programming one page (256 bytes) at a time.
There are two non-volatile bits in the AT91SAM7L128 that can be modified by the user. Bit 0 is a protection bit that locks out the JTAG port. Bit 0 should always remain clear (0) for our purposes! Bit 1 selects the memory map at boot time. If bit 1 is clear (0), the internal Atmel SAM-BA rom will be mapped to address 0 and will run at boot. Setting bit 1 to 1 will map the on-chip flash memory to address 0 at boot, allowing the firmware to run.
The GPNVM bits can be modified over the JTAG interface as the flash memory was modified in the above experiment. The backup plan, should something go horribly wrong, is to use the ERASE pin to erase the entire flash memory and GPNVM bits. (ERASE will leave your calculator blank, with NO HP FIRMWARE AT ALL. It will also clear the GPNVM bits, which would enable JTAG access and configure the chip to boot into the SAM-BA bootloader.) The ERASE pin has not been tested at this time. (I'm not going to try it until I can reflash the entire image through the JTAG port, just in case…)
OpenOCD scripts have been written to toggle GPNVM bit 1. They can be run from the OpenOCD telnet interface by typing “script flash_boot.cfg” or “script samba_boot.cfg”. It was noticed that running the SAM-BA bootloader increased the current drain of the calculator. (I have not had any success establishing a connection between the SAM-BA windows program and the SAM-BA bootloader. UPDATE: I did manage to get SAM-BA to connect! Works better when there are no solder bridges between the serial TX and RX lines. SAM-BA is more like SLOW-BA. Estimate 15 minutes to upload the 128kB flash to the PC.)
Note from Cyrille: I do not know why you are experiencing this. programming 128KB with sam-ba takes around 15s for me. And I have programmed over 500 calculators! Were you using a PC running windows or something else? did you get the latest sam-ba from Atmel? what cable are you using?
Answer from newell: Windows 2k, dual P3-450, tested with both SAM-BA v2.8 (current) and v2.7 (previous version, first to support the '7L128?). Cable is a couple of wirewrap wires tacked to the circuit board, running through a MAX3232 circuit powered by an external 3V power supply to translate to RS-232 level. The lash-up obviously works, as I'm able to connect to SAM-BA with Hyperterminal. (The chip reports bootloader v1.4.) Tired of messing with it, so I'm currently using a little app to break the bin file into 256 byte pages, then generating an OpenOCD script to burn a page at a time. Takes about 30s to burn and verify 128kB with a USB JTAG adapter through the OpenOCD script. I'd love to see what version of windows, SAM-BA, and bootloader ROM others are using. My SAM-BA burn times for 128kB are about 14 minutes, and about the same to transfer 128kB from the calc to the PC. (I may attempt to test on a faster computer to help narrow down this SAM-BA situation.)
# Set GPNVM bit 1, which will map flash memory to 0 # This will allow application code to boot, instead of SAM-BA soft_reset_halt # Set GPNVM bit 1 mww 0xffffff64 0x5a00010b # Show current GPNVM bits mww 0xffffff64 0x5a00000d sleep 100 mdw 0xffffff6c soft_reset_halt mdw 0 0x10
# Clear GPNVM bit 1, which will map SAM-BA ROM to 0 # This will prevent flash memory from booting. soft_reset_halt # Clear GPNVM bit 1 mww 0xffffff64 0x5a00010c # Show current GPNVM bits mww 0xffffff64 0x5a00000d sleep 100 mdw 0xffffff6c soft_reset_halt mdw 0 0x10