Last time, I said that there were almost no differences between the IAP loader drafts 2 and 3. Well, turns out I was wrong. Just to remind you, draft 2 specifies that the program should be divided into two parts - one which contains the IAP loader and cannot be overwritten and the second one that contains the rest of the code and can be overwritten freely. Draft 3 adds the ability for the IAP loader to copy itself into RAM and run from there in order to allow it to rewrite itself in FLASH.
Problems
When I started work on the draft 3 I ran into two main problems. The first one, which I sort of expected, was that the IAP loader, together with all the functions it uses, can only barely fit into the RAM. I managed to squeeze it in by trimming some of the code, but I expect that there would be trouble if we, for example, wanted to allocate memory for some large buffer in some later version of the firmware. The second problem was more severe and, in the end, it made me abandon the idea of implementing draft 3 altogether. The trouble is that the micro often locks up in an error state when there is a transition from the code residing in FLASH to the code which is in RAM and vice-versa. I don't know what exactly causes this and it's probably not an unsolvable problem, but without a JTAG debugger and with my limited experience, trying to fix this would most likely take way too much time. The advantages that draft 3 has over the draft 2 are probably also not worth it, especially considering the approaching deadline on my project. Therefore, I decided to switch to working on implementing draft 2.Working on draft 2
Implementing this was actually quite simple. It was only necessary to modify the ldscript a little bit by including a new output section called .boot containing the IAP loader and all of the other functions it requires to work properly. These were tagged with __attribute__ ((section (".src"))) so that the linker can place them in the appropriate section. I also modified the write and erase IAP functions to prevent the user from overwriting the part of the FLASH memory containing the IAP loader. The .boot section is aligned to 1kB boundary so that it will span a whole sector or multiple whole sectors of FLASH because it can be erased only in a sector-sized blocks.The only problem I had while implementing this draft was with a constant reference table (or array, if you wish) which is used to speed up the CRC calculations. In the original code it was declared locally inside the CRC computing function and the linker somehow placed it in the rewritable part of the code. This caused the micro to freeze every time I tried to reprogram it. The solution was to declare the array globally and tag it with an attribute specifying that it should be placed together with the IAP code. I should keep this in mind in case I run into a similar problem sometime later.
In conclusion
Our IAP loader occupies two first sectors of the FLASH (so there are six left) and is protected from being overwritten. This, I think, is a fairly standard solution and how most other boot-loaders work and I am quite content with it. It is not really necessary to have the option of reprogramming the IAP loader itself right now and implementing this feature would probably be more trouble than it's worth. Right now, I can't say that the IAP loader works 100% yet. To do that I will have to test it properly first.Until next week...