Calling into the bootloader section

For my current project I want to write data into flash. Not into EEProm. The reason being that I have way more flash than EEProm. (I am aware of AVR105 - Power Efficient High Endurance Parameter Storage in Flash).

I understand that in order to write to Flash I need to have the code that will do this in the bootloader section. I also know how to compile and upload a bootloader. In addition I understand how a bootloader will write to flash.

The issue that I do not get is: how do I get the compiler/linker to create a program that is aware of the code in the bootloader section and will call it accordingly?

A crude solution would be to disassemble the "bootloader code" and to use a suitable function pointer to call it. Another means would be to trigger a reset (e.g. by watchdog) in order to get controll to the bootloader.

However these methods are somewhat fragile / overly complicated.

Obviously I am missing some deeper knowledge about C compiler / linker in order to accomplish the task in a better way. What I want is a means to tell the compiler and/or linker that my program consists of two parts. One part in the bootloader section. Ideally I would prefer to be able to call back and forth between both program parts. However the sufficient minimal requirement would be that the main program can call into the bootloader part for flashing.

Another interesting (but not so important) question would be how to best determine at runtime how much of the flash memory is allocated by the main program.

Has anyone any hints for these two qeuestions? I already analyzed the Arduino bootloader and some others but I just do not seem to get it.

Udo

I think you want to use a custom linker script. Put the application code in one section and the bootloader code in a separate section, then use the linker script to place the separate bootloader section in the appropriate place in memory.

Best way to start is to study the existing linker script (for example, look in the hardware/tools/avr/avr/lib/ldscripts subdirectory of your Arduino installation) and look at the GNU documentation for the LD program:

http://sourceware.org/binutils/docs/ld/index.html

-- Check out our new shield: http://www.ruggedcircuits.com/html/gadget_shield.html

Udo,

I would probably use a function pointer. You'd have to figure out the correct address and set the function pointer to that value.

It might make it easier if you set up a vector, like those used for interrupts, in the bootloader. That way, the address wouldn't change if you changed the bootloader.

Regards,

-Mike

@rugged_circuits: I started reading. This looks complicated though. This will take some time to sift in.

@Mike: how would you setup such a vector in a way the main program can find it. A somewhat clumsy way would be to prepend it with a guid, search the guid in memory and then grab the following word. Not the most elegant approach though. Probably you have a better idea for that, do you?

Udo

Udo,

I've never looked at the bootloader code, so I'm just guessing here, but I'd start the bootloader with a jump around the vector, then have the vector, then the rest of the bootloader. Since you know the starting address for the bootloader, you can calculate the number of bytes past the starting address for the vector (probably just the length of the jump instruction). That's the address you'd put in the function pointer.

Of course, the vector would just be a jump instruction to the start of your flash-writing routine.

Regards,

-Mike

@Mike: I start to get it. In Assembler this would be pretty straightforward for me. But with C I do not know how to do this. Maybe I will implement the whole part in Assembler.

Thanks a lot for your help,
Udo

Here are some options:

  • Include your flash writing subroutine in the bootloader and grab the entry point from the compiler/link symbol table. Since the bootloader is static you can rely on this entry point being fixed and available to use for your "C" function pointer.

  • Have the bootloader write the entry point to a "known" EEPROM location (or flash if you like). Then read this from within your sketch and assign it to a function pointer. You can expand on this with flags/checksum or whatever to verify that the bootloader is flash capable.

@BenF: I understand your point. But my idea is to have all in "one program" that can be flashed together. This basically implies that the bootloader will not be that static. Especially since it will contain code that I may need to rework several times. The idea to tell the main program through some predefined memory location is something I will consider. Maybe I will use ram for this. Since the bootloader is always processed first it should be possible that I pass the desired vector through ram. I think the ISR vector table or the stack might be a good place to start with :)

Thanks for this hint. Udo

If you will not be using a bootloader per say, you can add a section attribute to your “flash read/write” function to move it into the flash bootloader area. This attribute should be used with the function prototype. If you add “<avr/boot.h>”, there is a macro called “BOOTLOADER_SECTION” that can be used for this purpose.

Then you need to add a linker option to assign a load address for this section. The option you need is as follows:

-Wl,–section-start=.bootloader=0x???

where 0x??? is the address in flash where you want to place the .bootloader section.

This way you get a binary that will be uploaded in part to standard flash and in part to the bootloader section. You can also reference the symbolic names of your “flash read/write” functions from within your C/C++ source and leave for the compiler to figure out the offsets at compile time.

@BenF: this was exactly what I have been searching for. Thanks a lot!

Udo