Break Microcontroller LPC2124FBD64 Binary: Anatomy of a Full Read
Ask three suppliers for a binary of the same device and you will get three files of different sizes, all described with the same word. One is the full array including erased space, one is trimmed at the last non-blank byte, and one is a linker output that was never inside the chip at all.
For the customer this ambiguity is expensive, because only one of those files is safe to write to a replacement board. Reading a 256 kilobyte array produces a lot of structure, and most of it is not the program.
The regions, in the order they appear
A full read of this device contains, from address zero upward:
| Region | Content | Belongs in a reflash image |
|---|---|---|
| sector 0 low | eight exception vectors plus checksum word | yes, with the checksum intact |
| application | code, constant pools, initialised data image | yes |
| gap | erased flash, reads as all ones | optional, wasteful |
| parameter sectors | emulated settings block, if the product uses one | depends on the customer |
| top of array | boot loader and its reserved area | no |
The last row is the one that causes damage. The factory boot loader lives in the upper part of the array, and the flash controller will refuse to program or erase that region through the loader itself. Write a raw image that includes it through a debugger instead, and the region is either rejected or, worse, partially replaced with whatever the source device happened to contain, which is not the same silicon revision’s loader.
Why the tail is mostly ones
Erased flash reads as all ones, because a programmed bit is a zero and erasing returns every bit to its unprogrammed state. A device with 128 kilobytes of code in a 256 kilobyte array therefore produces a file that is half 0xFF.
That region is not noise. Its boundary is the single most useful piece of information in the whole read, because it tells you where the linker placed the end of the image and, by extension, how much room the product had left. A product whose image ends at ninety percent of the array has no space for a field update, no space for a second copy, and probably no boot loader of its own. A product that ends at forty percent does.
Trimming at that boundary produces a file that is the program plus its initialised data, which is what a replacement board needs.
The checksum word is part of the binary
The word at 0x14 exists so that the eight vectors sum to zero, and the boot loader refuses to start an image whose sum is not zero. A trimmed binary that omits it, or that carries a value computed for a different vector table, produces a device that accepts the write and then sits in the loader.
This is the most common reason a binary that verified correctly in the programmer fails to run, and it is worth checking before the file leaves the bench. The arithmetic is four additions and a negation.
The protection word is not part of the binary
At the other end of sector 0 sits the control word that decides whether the device can be read at all. A raw read of a device in an open state returns an erased word, and carrying that into a new image is harmless. A read of a device that was unlocked by erase also returns an erased word, and carrying that is equally harmless.
The trap is the intermediate case: a source device in a protected state cannot be read through the loader, so any read of it came from a debugger or an invasive method, and the interface that produced it may or may not have included the protection word. If the word is copied into a replacement image, the replacement is born locked, and the customer discovers it only when they try to program it a second time.
Zero it deliberately, and say so in the report.
Verification that means something
Comparing the written file against the source file proves that the programmer works. It does not prove the image runs, and running is the only property the customer cares about.
Three checks in order:
- Read back the first sector and confirm the vector sum is zero.
- Release reset and capture the first output on the port the product normally speaks on, at the timing the working unit produces it.
- Load the recovered image into a second, known-blank device and confirm the same behaviour, which separates a good image from a lucky one.
The third check is what an honest delivery includes. A single device that runs may be running from something other than the file.
Size tells you about the product
Comparing the code size against the array size is a cheap form of appraisal. On this device, 256 kilobytes is generous for a control application, and images that fill it usually contain one of four things: a graphics or font table, a protocol stack, a boot loader with a second image, or a large calibration table measured per unit.
Identifying which one is present is often more valuable to the customer than the code itself, because it tells them where the intellectual property actually sits. A product whose flash is three quarters lookup table is a product whose secret is the measurement that produced the table, not the program that indexes it.
Delivery format
Hand over three files rather than one: the raw full-array read, the trimmed image with a note on the boundary address, and a short map that names each region and its protection state. That set lets a customer program a replacement board, prove the copy is faithful, and understand what they received.
Related mechanics are in LPC2103FBD48 heximal work for the checksum rule, LPC2104FBD48 erase behaviour for what happens when the array is cleared before a read, and LPC2129FBD64 firmware recovery for the variant that also carries network parameters in the same image.
The one thing to get right
Never write a raw full-array image into a device without inspecting the top of it first. Everything else in this article is a matter of efficiency. That single rule is a matter of whether the replacement board survives its first power-up, and it costs about thirty seconds to check.