I am just trying to build a custom bootloader for avr. I know that the bootloader functions can be shared with the application program. I am really confused with the main function though. Do bootloader and application program, both have main function? If not, how to write two separate programs with only one main function

Application Program:

    #include <avr/io.h> // application program at 0x0000
    #include <string.h>
    int main()

Bootloader Program:

    #include <avr/io.h>
    #include <avr/boot.h>
    void uart_init();
    void (*funcptr)( void ) = 0x0000;
    int main(void)
       //Boot or Goto Application program
    void uart_init()
       //UART initialization code;

I'd keep them separated.

What you can do is:

  • Create two programs, your bootloader and your application
  • Make sure these two programs are linked to different locations (e.g. bootloader to 0x0 (reset vector) and application to 0x20000 (application address).
  • The bootloader will be started after a reset and immediately after that it will decide if it should start the bootloader routines or if it should branch to the application. Only do what's absolutely necessary to make that decision (the rules for making that decision are up to you; e.g. some special value in flash or a button press).
  • \$\begingroup\$ Bootloader can only be loaded into the bottom section of controller and BOOTRST flag should be enabled to load it after restart. How can we write into the 0x00 address? Is it even possible \$\endgroup\$ – gzix May 30 '14 at 6:31
  • \$\begingroup\$ Which part exactely do you use? I'm not familiar with the BOOTRST fuse and would like to look it up for your specific part. If I understand correctly, this fuse will cause the processor to start from a different address. You will need to tell the linker where to put your bootloader or application. For the 32bit parts (AT32...) this is done via a linker setting + some code named trampoline (which just does a jump opcode). \$\endgroup\$ – Tom L. May 30 '14 at 6:37
  • \$\begingroup\$ Ya, BOOTRST will make the controller to run the code in boot section after restart. Then we can make a jump to application code from boot code \$\endgroup\$ – gzix May 30 '14 at 6:44
  • \$\begingroup\$ In that case you will need to link the bootloader code to the boot section and the application code to the "normal" application section. Is this a flag you can program as often as you want? Because then you could use it as an indicator if the bootloader should be entered or not and you would not need to make the jump manually. \$\endgroup\$ – Tom L. May 30 '14 at 7:02
  • \$\begingroup\$ This flag can be set only using a programmer and can't be changed internally. Whenever u endup with some problem while writing application code, corrupted application code will spoil the entire use and u again need a external programmer if u start the application code after restart. In such a case, BOOTRST comes for your rescue \$\endgroup\$ – gzix May 30 '14 at 7:33

Combining bootloader and main program into one binary makes no sense unless you want achieve something very very special. Bootloader is normally used to flash/upgrade main program via "normal" interface (USB, UART) and the BL code is typically uploaded only once via ISP/JTAG. BL code may also support encryption not to provide your code to everybody who is flashing your device (firmware upgrade).

When booting bootloader code is entered (depends on FUSEs), you should make quick decision if jump to main code or stay in bootloader. Arduino default bootloader uses timeouts waiting for Stk protocol header on serial which is very annoying because it prolongs every booting process by couple of seconds. I prefer when a UI is present (button, ...) quickly test if user wants to make firmware flash (hold button after power cycle or so).


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.