Noggin
Member
I'm proud of myself and did something that I think is way cool yesterday. I work for an engineering resources firm and we took over a project from another company that didn't deliver what they promised. The final product has been loaded with a bootloader and sealed in a low pressure air tight container. Hundreds of them are in boxes and waiting for our "go-ahead" for shipping. It would take something like 8000 man hours if they have to take the lid off the products. However, they can all be bootloaded simultaneously as they're on an ethernet type of network.
Here's the problem...
I had the source code and the compiler so I could do a compile, step through the code, and find out the address at which an instruction was located. So, I found in the code where the file size comparison was supposed to use a constant of 0x60000 instead of 0x20000. I then wrote a special application that would modify the bootloader. Bootloaded it in.... and wallah! It would allow files over 0x20000 to bootloader. Feeling like I had done a good job, I went home for the day.
Early the next morning, as a sanity check I tried to load a file of 0x27000 byte. It didn't work. Thats when I discovered that the MCU had banks! Damn time crunch! I didn't do my due diligence and it bit me in the ass. My patched bootloader was due the next morning (this morning in fact).
Ok... so I took a couple hours to brainstorm and came to the conclusion that major modifications to the bootloader was out of the question. If even one additional byte of code was added to the bootloader, it would make simple byte patches impossible. Additionally, there was no where near enough room to add a whole bootloader to the patch application. I just started on this project on Tuesday and I'm not familiar enough to reduce code bloat to the point that I'd be comfortable trying to do so.
My conclusion was that I had to modify the bootloader to write only to the second bank of flash. All file size comparisons were to be done to a value of 0x40000, application start addresses had to be changed to 0x140000, and all calls with anything to do with the bank 0 write registers had to be changed to bank 1 registers.
That didn't sound that bad, I could do that.
But it didn't work.... the MCU initialization code never initialized the bank 1 controller! That meant additional code had to be added! It threw EVERYTHING off! This stuff is what happens before int main is called, so I'm staring at dissassembly and machine language...
The first thing I tried was just changing the bank 0 init to bank 1 instead. That didn't seem to work though. It woulda been too easy anyway. However, I did notice that the init was the same for bank 0 as it needed to be for bank 1, so once I loaded the registers with the bank 0 init code and loaded up the bank 0 register, I didn't have to reload R0 and R1, I just had to load it into the bank 1 register.
That saved 2 instructions in the init code. 2 down, 1 to go....
The next peripherial that was initialized was the watchdog. Hmmm.... it gets initialized to be turned off. Awesome! I can just remove it!
Damn... datasheet says that it defaults to on unless turned off in init code.
Hmmm... set bit 15 to turn it off. Whats in R0? Dang, bit 15 is 0. Whats in R1? Dang, bit 15 is 0!
Ooooo.... but R1 is loaded into the flash control registers, and bit 15 in those registers is unused! I can change R1 to have a 1 in bit 15 and reuse it to disable the watchdog!
Success! Watchdog is off, flash control bank 0 and a 1 are both set!
So then I wrote a special app that would read the bootloader flash area and stream it out of the serial port. I loaded it in and read out the original bootloader and then I loaded in the newly compiled bootloader and read it out too. A file diff showed 13 words that had to be changed. Not a problem, I already had a patcher. Patched it up and tested it out on a few applications compiled for address 0x14000.
Proud of myself, and home by 9 PM. Modified bootloader application is due today at noon. Guess I should go in and verify with 100% certainty that the bootloader I'm going to be patching is in fact the EXACT same bootloader that I was given the source code for. If not, this will brick their machines.
Here's the problem...
- Two days ago we discovered that the bootloader in every unit was limiting the application code space to 128k (0x20000 bytes) although the design spec was for an application code space of 384k.
- Our current application was at 0x1E70B bytes. Not much room for additional features
I had the source code and the compiler so I could do a compile, step through the code, and find out the address at which an instruction was located. So, I found in the code where the file size comparison was supposed to use a constant of 0x60000 instead of 0x20000. I then wrote a special application that would modify the bootloader. Bootloaded it in.... and wallah! It would allow files over 0x20000 to bootloader. Feeling like I had done a good job, I went home for the day.
Early the next morning, as a sanity check I tried to load a file of 0x27000 byte. It didn't work. Thats when I discovered that the MCU had banks! Damn time crunch! I didn't do my due diligence and it bit me in the ass. My patched bootloader was due the next morning (this morning in fact).
Ok... so I took a couple hours to brainstorm and came to the conclusion that major modifications to the bootloader was out of the question. If even one additional byte of code was added to the bootloader, it would make simple byte patches impossible. Additionally, there was no where near enough room to add a whole bootloader to the patch application. I just started on this project on Tuesday and I'm not familiar enough to reduce code bloat to the point that I'd be comfortable trying to do so.
My conclusion was that I had to modify the bootloader to write only to the second bank of flash. All file size comparisons were to be done to a value of 0x40000, application start addresses had to be changed to 0x140000, and all calls with anything to do with the bank 0 write registers had to be changed to bank 1 registers.
That didn't sound that bad, I could do that.
But it didn't work.... the MCU initialization code never initialized the bank 1 controller! That meant additional code had to be added! It threw EVERYTHING off! This stuff is what happens before int main is called, so I'm staring at dissassembly and machine language...
The first thing I tried was just changing the bank 0 init to bank 1 instead. That didn't seem to work though. It woulda been too easy anyway. However, I did notice that the init was the same for bank 0 as it needed to be for bank 1, so once I loaded the registers with the bank 0 init code and loaded up the bank 0 register, I didn't have to reload R0 and R1, I just had to load it into the bank 1 register.
That saved 2 instructions in the init code. 2 down, 1 to go....
The next peripherial that was initialized was the watchdog. Hmmm.... it gets initialized to be turned off. Awesome! I can just remove it!
Damn... datasheet says that it defaults to on unless turned off in init code.
Hmmm... set bit 15 to turn it off. Whats in R0? Dang, bit 15 is 0. Whats in R1? Dang, bit 15 is 0!
Ooooo.... but R1 is loaded into the flash control registers, and bit 15 in those registers is unused! I can change R1 to have a 1 in bit 15 and reuse it to disable the watchdog!
Success! Watchdog is off, flash control bank 0 and a 1 are both set!
So then I wrote a special app that would read the bootloader flash area and stream it out of the serial port. I loaded it in and read out the original bootloader and then I loaded in the newly compiled bootloader and read it out too. A file diff showed 13 words that had to be changed. Not a problem, I already had a patcher. Patched it up and tested it out on a few applications compiled for address 0x14000.
Proud of myself, and home by 9 PM. Modified bootloader application is due today at noon. Guess I should go in and verify with 100% certainty that the bootloader I'm going to be patching is in fact the EXACT same bootloader that I was given the source code for. If not, this will brick their machines.