Building the Firmware
The goal here is to create the file
foo.ordered.hex, which will be the file needed by the Arduino or other program that flashes the new firmware.
This is the overall process:
We start with
foo.c, the source file discussed in the previous two posts. When this is compiled, we end up with a relocatable image,
foo.obj, but for reasons outlined next, we need to keep the assembler file (which is needed to generate that relocatable image). So that's the first step at the top left of the diagram, where we generate
foo.hex. (Of course,
foo will be replaced with the real name of our project.)
This file has the data which will be inserted into a "canonical" disassembled image. For now, that image is
1500W_master_rep.a51. I've created that file from IDA Pro, by disassembling an image I obtained from an Elcon/TC charger. For this image, the data of interest happens to start at address 0xD76. In order to force the data to be linked at that address, we need to edit the assembler source for foo.c slightly. This is done by a sed script (sed is a Stream EDitor, a Cygwin utility). It inserts an ORG statement, and also deletes two lines which cause problems. So that's the second step, where we generate
foo.a51. Don't be too concerned about the number of steps; once everything is set up, most of it is done automatically, either by the Keil development environment, or by the Cygwin script
combine.sh.
We use a second Keil project (sorry, I can't find a way to combine these two projects). This project takes the two
.a51 files, assembles them, links them, and produces two output files: an executable (which we don't need), and the
foo.hex file. Alas, this
foo.hex file needs a little massaging, mainly to combine the various odd-sized segments so that the final
foo.ordered.hex has contiguous lines that all have 16 bytes of data in them. That makes the processing of that file much easier. This is done by two calls to
objcopy (one converts from hex to binary, the other from binary to hex; in the process, the massaging is accomplished.) The script file
combine.sh does this for us, as well as the assemble and link process via a batch file generated from the second Keil project. Phew!
The two Keil project files needed have paths embedded in them, so it's best to generate these as needed. The first one, foo.uv2, is the one you'll be using most of the time. From Project / New uVision Project... enter the name of the project; use the same name as the .c file but with .uv2 extension. You will be asked for the CPU; there are an amazing range of these. Find NXP then near the end of the list of NXP processors, select P89LPC938. When it offers to add the standard startup files, choose No.
You should now have a new project. At left should be a Project Workspace with a Target 1 and a Source Group 1 under that. Right mouse on that source group and select Add Files to Group. Add your
foo.c file.
Because we end up with two project files, the next step is important. Use Project / Options for target Target 1. Click on the Output tab. In the text box next to Name of Executable, enter "dummy" (without the quotes). This is so that it doesn't overwrite important files with the name
foo. Now you can use the build toolbar icons to do the compile. Even after you have fixed all compile time errors, there could well be some sort of error message about a file not being found. This is normal, and can be ignored. However, you should see the file
foo.SRC with a recent time stamp. You should run the combine.sh script now, even though it will bomb out with errors, to generate
foo.a51. To invoke it, in a Cygwin window, change to the directory with
foo.c and enter this command:
./combine.sh foo
You should see
foo.a51 with a recent time stamp.
To create the second project, begin again with Project / New uVision Project and give it the name
foo_combine.uv2. Select the CPU as before, and choose No for the startup files as before. Right mouse button on the Source Group 1 and add these files:
foo.a51, and
1500W_master_rep.a51. Choose Project / Options for Target Target 1, and click on the Output tab. This time, ensure that the Name of Executable is
foo . Also tick these two boxes:
Create Batch File, and
Create Hex File.
Use the Rebuild All Target Files toolbar icon to build everything. This should create
foo.hex with a recent timestamp, and the file
Target 1.BAT. The latter file is needed by the combine.sh script to do the compile and link with the updated
foo.a51 file, when you make changes to
foo.c later. Finally, run the
combine.sh script again, passing
foo as before. You should now have
foo.ordered.hex, ready for flashing.
Later when you make changes to foo.c, you just need to use the first projrect (
foo.uv2, not
foo_combine.uv2) to regenerate
foo.SRC. Then run the
combine.sh script again, and the
foo.ordered.hex file should pop out with no further effort.
The
ElconTCfirmware.zip file should contain the files you need.