A bootloader is a code that is executed before an Operating System, or in the case of an Arduino, before your program starts to run. The concept of bootloaders is universal to virtually all electronics such as laptops, smartphones, and other devices. A bootloader package the instructions to boot the system kernel and most of them have their own debugging or modification environment. As the bootloader runs before any piece of software on your device, it makes it extremely processor specific and every Arduino chip has its own bootloader. Many makers out there will never need to change or program their Arduino’s bootloader. Some, however, will be forced to do this.
One reason to program the bootloader might be that, when using the device, the user did something wrong that damaged it. Perhaps the company forgot to program it at factory level, or perhaps the user burned the Atmega.
Another reason to do this is if the user needs to set different fues. They are essentially configuration parameters, or like the chip’s BIOS. They control functions like which oscillator to use, and what speed to run at (i.e. the internal 8MHz oscillator, or an external crystal), brownout detection, and the size of the flash.
Just one good reason: the brownout detector
A brownout is a short dip in the power supply. Many microcontrollers have brownout detection on-chip, often, like in the Atmel AVR, with programmable threshold levels. The brownout is the feature that will reset the microcontroller if the voltage of the circuit gets below a threshold. Without this feature, when this occurs, RAM memory may be corrupted. Therefore, the brown-out is not the villain. Nevertheless, there are two conditions the user will not want it.
The first case the user will not like to have the BOD enabled is if the chip operate at a voltage near the detection threshold. On that case, the microcontroller may get a confused reading and reset itself at the normal voltage level. For the Atmega328P-PU the detection level begin at 1.7V and goes up to 4.5V, depending on how the fuses were set. That could be a problem for a smartwatch operating at 3.3V.
The second case is if the system needs to consume the lowest power possible. As it was seen on previous posts (see links below the page), at first the smartwatch project was consuming 16uA (without the display, just the Atmega, plus EEPROM and RTC module). Just a look at the microcontroller’s datasheet, here, and it is possible to see that the brown-out detecting costs around 15uA. Disabling it could lower the power to 1uA. So now, to improve the project it is needed to disable this feature, and for that, the user needs to reprogram the fuses.
It should be easy, but NO!
There are innumerous articles on how program fuse bytes for the Atmega all over the internet. There is just the need for an AVR programmer, like one mentioned on this website, a PC (or Linux) program similar to the Avrdude (here) or its windowed version, the WinAVR (here), and some patience. The real problem is that the first time the user find this problem, he probably will not have a programmer! So how can that be made?
To program the bootloader without specific device, it is only possible with an Arduino. It is possible to insert a code inside the Arduino Uno and make it work as an AVRISP. However, as I found out, the Arduino as ISP loads the bootloader correctly, but fails to change the fuses for some unknown reason. I will describe that odyssey, in case you are at your house trying to make this project work.
Compile the code to the Uno
On the examples menu, there is a code named “ArduinoISP”. Compile it and send to the Arduino Uno. Really easy so far. Now connect six wires from the Uno to the Arduino Pro Mini (bare bones), also called Atmega328P-PU for now.
- Arduino Uno Pin 13 to Atmega328P-PU pin 19 (SCK) *
- Arduino Uno Pin 12 to Atmega328P-PU pin 18 (MISO)*
- Arduino Uno Pin 11 to Atmega328P-PU pin 17 (MOSI) *
- Arduino Uno Pin 10 to Atmega328P-PU pin 1 (RESET)*
- Arduino Uno Pin VCC to Atmega328P-PU (VCC)**
- Arduino Uno Pin GND to Atmega328P-PU (GND)**
Install WinAVR and enter the command line
Just follow the steps of the WinAVR website, install it and open the command line (cmd). With the Arduino Uno connected to your PC’s USB port and the Atmega328P-PU connected to the UNO, type the following line.
avrdude –P COM5 –b 19200 -c arduino -p atmega328p -U lock:w:0x3f:m -U efuse:w:0xFF:m -U hfuse:w:0xD6:m -U lfuse:w:0xFF:m
Now you may experience several errors. The part “-U lock:w:0x3f:m” means you will first unlock the fuses to be able to write them. Perhaps your microcontroller does not need this instruction. The “-c arduino” means your programmer is a Uno, but if that doesn’t work, you can try “-c avrisp”. Also, the command “-p atmega328p” tells which microcontroller you are bootloading. If that does not work, you can try “-p m328p”.
The ideal was to program 0xFF to the EFUSE. However, that instruction was not working and the command line was accusing errors. Every time I wrote 0xFF to the EFUSE, the microcontroller read 0x05, as if I did not program it at all. So how could I disable the brown-put detector if I could not write the fuse that controls it?
I figured out that the brown-out is activated and set using the last three bits of the EFUSE. To disable it I had to write “1” to each bit, meaning that any command to write “XXXXX111” to the fuse, where X is any value, would work. As 111 is equivalent to 7, 0x07, 0x0F, 0x27, 0x2F, …, 0xFF, all of these would work. For some reason I still don’t know, the only command that worked was “-U efuse:w:0x07:m”. My line was:
avrdude –P COM5 –b 19200 -c arduino -p atmega328p -U lock:w:0x3f:m -U efuse:w:0x07:m -U hfuse:w:0xD6:m -U lfuse:w:0xFF:m
NOTE: You may have problems if you put the arguments –P and –b after –c or at the end of the command line. The order here makes all the difference.
Other fuses to program – fuse calculator
One thing to note is that if the user needs to set new fuses, he can figure out how to program each feature of the chip by looking at AVR Fuses Calculator available online. You can check out one here.
How to send the code to the Pro Mini
Now that everything is set, the user can send the code to its Arduino Pro Mini. I used to program it via FTDI tool. However, after setting these fuses, I was not able to do that anymore. For some reason, there is only one way to program it. You have to use that same Arduino Uno as an AVRISP.
Open the code on the Arduino IDE platform and (if you did not do anything more than I wrote here) your board might be set to the Arduino Uno on its communications port (USB) that you used to program it (ArduinoISP). Now change that board to Arduino Pro Mini (still leaving the Uno connected), open your code and click “Upload using Programmer”. This will tell the compiler to make the program for the Pro Mini, but sending the code through the Uno. I read on the internet some people think that you should leave “Arduino Uno” as the board, but that is wrong, because the Uno has a clock of 16 MHz and the Pro Mini 8 MHz If you leave that way, you will see your Pro Mini with its clock halved. Now it is done! You will see a message telling the program was uploaded.
Now it is time to place your probes between the battery (or power supply) and the VCC from the breadboard to see how much current your circuit is drawing. If you are testing just the Atmega328P-Pu, it should be around 0.1 to 0.6uA. If it is the microcontroller plus the EEPROM and the real-time clock PCF8563, it should be at a maximum of 0.7uA. If you are testing with the display, it could be around a few uA. For me however it was 238uA with the display sleeping, because my module is not very efficient. Nevertheless, I improved it, resulting in just 1.1uA, and I will make a tutorial about this soon. Thanks for reading!