В тази статия се описва как да се заобиколи проблем при прекомпилиране на bootloader-а на Ардуино при използване на gcc версии 4.х. Също така има кратко описание какво е bootloader и защо бихте искали да го промените и компилирате наново. Ако желаете превод на български, моля оставете коментар.
Some time ago I needed to recompile the Arduino bootloader for the ATmega8 MCU. Unfortunately I run into one problem – the generated executable code was too big. I write this to share the workaround I’ve found. If you don’t know what I’m talking about, but are curious to learn scroll down for a quick explanation.
Basically when trying to compile the bootloader it doesn’t fit in the 1KB designated space. The error spewed out is something like:
address 0x203e of ATmegaBOOT.elf section .text is not within region text.
The problem turns out to be a bug in more recent versions of avr-gcc. The binary in the Arduino distribution was compiled using the 3.x branch which isn’t affected and I was using a newer 4.x version. One way to handle this would be to install the complete 3.x toolchain but that doesn’t look like much fun.
Reading the bug description more closely showed that the problem is inlining functions more that once even though the -Os option is passed to the compiler to optimize for minimum size. Curiously for some other architectures even inlining a function twice can be smaller that not inlining, but for the AVR this is not the case. So until the gcc gurus figure out how to get this problem solved properly I have found a temporary workaround. At least with the Arduino bootloader adding -finline-limit=1 to the gcc parameters seems to do the trick. The code is again less that 1KB and happily fits in the bootloader section.
So, what the hell is a bootloader and why would I want to recompile it? I’m glad you asked :)!
The ATmega8 is a small computer – everything needed on a single chip. To make it useful, as with any computer, we need to put some program in it. More precisely on the internal flash memory. One way to do this would be using a special cable or adapter called a programmer. If we don’t have such cable or we want the user of the device to be able to change the software in the field there is another way. We can use any of the built-in peripherals to get the program, the most popular choice being the USART module aka ‘the serial port’. But there’s one catch – in order to do this we need to write a very small program that reads the data from our peripheral of choice and writes it to the flash memory. This small program is called a bootloader. When I say small in the case above this meant less than 1KB of the total 8KB of flash in the ATmega8.
If you have acquired an Arduino or Arduino like board it most probably already has the bootloader programmed into the chip. Thanks to its help you can just plug in the USB cable in your PC, and have your sketch uploaded to the board. The USB cable actually connects to a USB/UART converter chip, or more precisely the FT232RL, so from the viewpoint of the ATmega we are talking through a serial connection. One of the very important parameters of a serial link is its speed usually measured in bits/second. When we configure the serial link speed in the AtMega MCU we use the frequency of the CPU, or the CPU clock as a base, Usually this clock signal is run through a divider, so the „UART clock“ (i.e. the UART speed) is set as a fraction of the CPU clock. So if we change the CPU clock, but want to keep the same speed, we need to change the divider used. Since this divider is specified in the bootloader source code a recompile of the bootloader is needed.
By default the Arduino has a 16MHz external crystal (the shiny metal box that has written 16.000 on top) and that’s the frequency it runs at. In my case I wanted to run it at 4MHz or even at 1MHz instead. Why would anyone want to do this? Why run a CPU that is perfectly capable of running at 16MHz at only 1? The reason is power consumption. The lower the frequency the lower the voltage supply that is required. And the lower the voltage – the lower the power. For example certain parts of the ATMega family that have a V suffix, like the ATmega88V can work from as low as 1.8V if the CPU frequency is kept under 4MHz.
When a device is going to be battery powered it is important to make the batteries last as long as possible. One thing that helps to accomplish this goal is to run the CPU at the lowest frequency that satisfies the application’s need for computing power. Taken to the extreme this means 0Hz, or completely stopping the CPU. And this is exactly what should be done if the CPU isn’t needed for the moment – put in in power-down mode.
I got a little carried away here, but ways to minimize the power consumption is such an interesting topic. Do you have any power saving tips to share?