ramloader - an open source RAM loader for NXP LPC controllers
By Marc Prager (firstname.lastname@example.org)
WARNING: The author is NOT your friendly neighbour. He has harsh opinions and these opinions may be expressed here or in the program's output.
A long time ago I programmed on 8051 devices (yes, I liked this uC). At that time I used a EPROM-simulator to feed the programs into the 8051's external "ROM". I liked this style of program development. When I switched to the ARM7TDMI around 2006 I liked the NXP (Philips Semiconductors at that time) LPC2106 for its enormous contiguous RAM of 64kiB because that allowed to use a similar concept. I wrote a program that allows downloading the program image into RAM and then execute that image out of RAM. It turned out the ARMv4 instruction set is powerfull enought to implement such a program without any RAM requirements whatsoever. The full RAM was available for execution. The only thing I had to do was to tailor a linker script towards ramloader usage. These linker scripts got more and more elaborate over the years and I adapted to various kinds of LPCs (LPC21xx, LPC23, LPC17xx). It turned out, that even with 16kiB of RAM many useful programs can be developed without FLASH usage.
This kind of embedded programming lead to my style of program development/debugging. I do very frequent program downloading and testing (fine grained testing in my opinion) and almost never use a debugger. Oh. In fact, I've never used a debugger on the LPC's ever.
In 2013 I got very excited about the LPC800 devices. I decided to implement a ramloader for this device, despite the low RAM size. However, for this device it was important to overcome the limitations imposed by the ISP bootloader. ramloader lets you use EVERY byte of RAM, even the areas that the ISP handler uses. Because it's no longer running at that time.
You need 2 parts for executing programs in ram. One part is programmed into the target uC's FLASH. The other part is on your development system. I call both of these ramloader to maximize confusion. The program is part of my 'c-linux' project project and can be found there.
The protocol is kept as simple as possible. It's a binary protocol, not text. Smallest transfer units are bytes. Every command consists of one command byte and 0 to 256 bytes of parameters. Responses are similar. Reading and writing is done at consecutive addresses. Every byte written increases the address by 1. I prefer not to use setAddress but rather reset_address. This simplifies downloading to different RAM locations. Remember, RAM starts at different addresses for different LPC families and RAM never starts at 0.
Command name encoding response comment
hello 0x00 'A' Just for a simple check
reset_address 0x01 <0xA5> Resets destination address to uC's RAM start
write 0x02 <256 data bytes> <sumL> <sumH> Writes 256 bytes of data into the uC's RAM
read 0x03 <256 data bytes> Reads 256 bytes of data.
execute 0x04 Executes program
sync 0x05 <code> ~<code> Reliable check for ramloader
fill 0x06 <fillByte> 'F' Fill uC RAM (4k)
setAddress 0x07 <32-bit-addr, LE> 'A' Set destination address (4 bytes, LSB first)
So far I wrote ramloader programs for the following families:
Each family requires its own ramloader program because of architectural differences and different peripherals and pin-out.
Invocation is in the most simple case (recent LPC controller, USB-to-serial converter = /dev/ttyUSB0):
$ ramloader <binary-image>
Download and compile
The following tools need to be installed on your system:
After downloading, you can verify the the hash sum of the downloaded archive. (Compare to md5sum.txt).
- reasonable recent binutils.
- Of course you should use a *nix operating system, but you may figure out what make.sh does on other systems, too.
To generate the executable (.bin) image, the following steps are required:
$ tar xfj ramloader800.tar.bz2
$ cd ramloader800
Last modified: 2014-01-14