Customize Arduino Nano ATmega328p Bootloader


I watched the following video on how to change bootloader of an Arduino Uno with a 20MHz resonator: Arduino Uno 20MHz Bootloader

But I need to customize the bootloader of an Arduino Nano with ATmega328p, so that it can work with 20MHz crystal, and following fuse bits: LOW: 0xFF HIGH: 0xD1 EXTENDED: 0xFF

There is no omake file in the same directory. So even if I make changes to the "ATmegaBOOT_168.c" file in the atmega folder, how can I run omake?!

Also, I was wondering if I could make changes to the "ATmegaBOOT_168.c" file so that I could extend the time out of the bootloader?

And also, is there a way to jump to bootloader from the application? Does this command work in my application? asm volatile (" jmp 30720");


Don't bother messing with that obsolete "ATmegaBOOT" bootloader. Use Optiboot instead:

  • 1.5 kB smaller
  • Watchdog reset compatible

MiniCore already has a 20 MHz optiboot bootloader that's as easy to use as just selecting Tools > Clock > 20 MHz external. You can adjust fuses in the boards.txt if necessary.

MiniCore uses the slightly modified optiboot that allows writing to flash from the application. If you want the official optiboot source it's here:

omake is specific to the Optiboot bootloader, while the Nano is still supplied with the older ATmegaBoot bootloader. You can put Optiboot on a nano (at which point you should call it an Uno in the board menu.) However, even with Optiboot, "omake" is no longer working because the Arduino install no longer includes "make." So you'd need to start by installing some tools :-(

Optiboot is somewhat heavily documented (compared to ATmegaboot, anyway) at its github home:

I was wondering if I could make changes to the "ATmegaBOOT_168.c" file so that I could extend the time out of the bootloader?

It looks like you should modify the MAX_TIME_COUNT setting in the Makefile, for ATmegaBoot. Optiboot uses the watchdog timer, so it could be increase up to 8 seconds max.

Awesome. Thanks alot Pert. I was confused how come the MegaCore doesn’t support 328p, till you showed me the MiniCore :slight_smile:

I changed the fuse bits in the board.txt and uploaded the bootloader. Then I uploaded a sketch and worked fine.

Only my last question remains: How to jump to bootloader from the application using a command?

The reason I need to jump to bootloader using a command it that the board that I am using doesn’t have reset line exposed, so I can’t use DTR to trigger the reset line and prepare the board for a new sketch.

Currently I am using BitBurner to upload sketches as hex files. I was wondering whether I could use an AVRdude argument to jump to bootloader?


Only my last question remains: How to jump to bootloader from the application using a command? I can't use DTR to trigger the reset line and prepare the board for a new sketch.

It's complicated. The preferred method of causing a reset from a program is to turn on the watchdog timer, and then wait for it to cause a reset. But this won't start the bootloader, because IT uses the watchdog reset to start the sketch. Jumping to the bootloader start address MIGHT work, but it leaves a lot of interrupts/etc turned on, and the bootload reads the last "reset reason" to decide what to do, all of which means that things will be a a relatively "random" state.

It seems like the solution would be to modify the bootloader so that it is activated after a watchdog reset. I suppose this means that it should jump directly to the application section after the flashing process is complete rather than resetting.

I have very dim understanding of how that all works but I know it is possible because the Ariadne bootloader does allow you to initiate an upload after a watchdog reset:

Now I seem to have encountered other issues. The first time I uploaded the bootloader through Atmel-ICE programmer and Arduino IDE, I can subsequently upload a hex file of a sketch through BitBurner without any problem. Later, when I wanted to upload another sketch through BitBurner, it can't do it. I used a jumper between my DTR line with a 100nF cap in series with Reset line of my MCU, and still can't upload a sketch!

Do you know what could be the problem? BTW, my board runs sketches at 100000 buadrate. Could that be a problem?

Also, I followed this forum and I think I managed to kick my board into bootloader:

//Before main()
typedef void (*do_reboot_t)(void);
const do_reboot_t do_reboot = (do_reboot_t)((FLASHEND-511)>>1);

//somewhere in loop()
// Goto Bootloader
case 55:
    #ifdef WDT_DIAG
        printf_P(PSTR("\n\n*WDT-Bootloader Requested\n\n"));

    //Jump to Bootloader


Now, if I want to kick my board into bootloader and upload a new sketch right away, can I edit the optiboot.c file and do something like the following?

/* main program starts here */
int main(void) {
  //Execute case 55
  uint8_t ch;

If yes, how do I recompile the new optiboot.c?


Sorry, my bad with uploading sketches through DTR line. I just had set the wrong fuse bits. Now I can upload sketches no problem.

My only problem remains with kicking my board into bootloader mode within application code and upload sketches.

Alright, I figured it out and got everything working.

So, once I get into "case b" of my code, the program jumps into bootloader and then I quickly uploaded a new hex file through BitBurner:

//Before main()/void setup()
typedef void (*do_reboot_t)(void);
const do_reboot_t do_reboot = (do_reboot_t)((FLASHEND-511)>>1);

//somewhere in while(1)/void loop()
// Goto Bootloader
case b:
    //Jump to Bootloader


Since I needed to do everything quickly, I wrote a batch file that would do the following:

  • Send a string to my board through a terminal program to make my code get into case b and jump to bootloader
  • Upload the hex file onto my board through BitBurner