Bootloader for Tiny chips?

Does anyone know if there is an arduino compatible bootloader around for the ATTiny84?

I want to use the RESET pin as an extra I/O pin, but cant do this without a bootloader. Doing so disables the ability for it to be programmed via SPI, and as such would require an high voltage programmer to make any changes. By adding a bootloader, the reset pin would become unnecessary (I can just reset the power to the tiny chip just before the download starts).

I don't mind modifying a bootloader to suit the chip, the issue is finding one which can reside in normal programming memory as the ATTiny's dont have a NWWR bootloader section which throws optiboot out of the equation as far as I can tell.



I was thinking of using a software based UART, I know Optiboot has one for the slower baud rates. I could also possibly use the USI module configured as I2C and use another arduino as a USB-I2C adapter.

I was mainly hoping that someone has already come up with a way to use the ATTiny’s self programming mode.

Well that shows how much attention I was paying to the code. Apparently, optiboot already supports the Attiny84 (luminet) chip. I'm sure I read somewhere that it didn't work with virtual boot partitions...


Bear in mind that, as far as I know, no one has had success with Optiboot on an ATtiny84 processor. A few folks have tried but no one has reported success.

The luminet bootloader does work but it is highly specialized.

If you plan to use the internal oscillator, use serial for the transport, and disable RESET you could easily brick a processor. The internal oscillator is ±10%. A good rule of thumb is ±4.5% for serial communications. Assuming the un-tuned oscillator frequency is evenly distributed there is about a 50% chance of bricking.

Duly noted. I may end up running the serial communications at as low a BAUD rate as possible to try and reduce the risk of an issue. I will also experiment with the bootloader without disabling the reset to begin with, and then if I can get it working reliably, i will set the disable reset bit in the fuse.

Here is one for you, in the make file, there is a value for where the optiboot version number is stored in the program memory. It would appear that this number positions the optiboot version such that it overlaps part of the bootloader code. I have corrected it in my make file to move it to tuck in just after the end of the bootloader, but is it possible that this may be why there are so many issues with the attiny84 chip?

luminet: TARGET = luminet
luminet: MCU_TARGET = attiny84
luminet: AVR_FREQ = 1000000L
luminet: LDSECTIONS = -Wl,--section-start=.text=0x1d00 -Wl,--section-start=.version=0x1efe
luminet: $(PROGRAM)_luminet.hex
luminet: $(PROGRAM)_luminet.lst

This bit:
should be:
To prevent it overwriting and corrupting part of the bootloader

The other thing is that I would like to move the bootloader to start at 0x1DA0 rather than 0x1D00 as otherwise there is two pages of wasted space after the bootloader (128bytes).
I have figured out how to move the codes starting position using the makefile, but I get the impression it is not that simple. In the optiboot.c file there are the following two bits of code:

      if ((uint16_t)(void*)address == 0) {
        // This is the reset vector page. We need to live-patch the code so the
        // bootloader runs.
        // Move RESET vector to WDT vector
        uint16_t vect = buff[0] | (buff[1]<<8);
        rstVect = vect;
        wdtVect = buff[8] | (buff[9]<<8);
        vect -= 4; // Instruction is a relative jump (rjmp), so recalculate.
        buff[8] = vect & 0xff;
        buff[9] = vect >> 8;

        // Add jump to bootloader at RESET vector
        buff[0] = 0x7f;
        buff[1] = 0xce; // rjmp 0x1d00 instruction
      do {
        // Undo vector patch in bottom page so verify passes
        if (address == 0)       ch=rstVect & 0xff;
        else if (address == 1)  ch=rstVect >> 8;
        else if (address == 8)  ch=wdtVect & 0xff;
        else if (address == 9) ch=wdtVect >> 8;
        else ch = pgm_read_byte_near(address);
      } while (--length);

Could someon explain to me how they work so I can go about making the correction to account for the change in the start of the bootloader.

Ahh, I figured out how to make the change.


int main(void){
  __asm__ __volatile__ (
    "   rjmp  0x1D00\n"

Nicely explained it!

What’s the reason for needing a boot loader? It uses a fairly large amount of space on a chip with so little flash space!

I explained at the beginning. In the end, I will be disabling the Reset pin so that it can be used as an additional IO pin. However if you do this, you can no longer program it using ISP. Instead you have to use a high voltage programmer, which would blow up other things on the board (its a surface mount chip). The bootloader adds an additional way in which it can be programmed without the need for a high voltage programmer, or the reset pin (a power cycle should work to reset it for bootloading).

Optiboot isn't that bad in terms of size. The version I compiled leaves 7552 bytes (7.375kB) of flash for the sketch. I also moved where in the flash the bootloader was slightly which recovered an extra 128 bytes. That is still lots more space than there is on an attiny44.

Apologies, I somehow missed that part of your post…! I’m impressed with how small you got the bootloader though.

Perhaps you could (at the expense of board size) use resistors and zeners to clamp the off-chip voltage to 5v, which due to the resistors, would allow a HV programmer to program the chip at HV still? Or if you only need to change the program very occasionally, perhaps you could simply use solder bridges? Of course either way you’d need a HV programmer, but just an idea anyway :slight_smile:

I have succeeded!

With a bit of modification of Optiboot, a bit of optimisation, and a half rewrite of optiboots software UART, I now have an attiny84 with a so far reliable bootloader which only takes up 576byte of the 8k.

It is running at 9600 baud, so uploading is slow, but it works.

After a bit more testing, I will post the bootloader and source, along with a new Tiny core that I have been working on. It is largely based around the existing one, but rewritten so that Print matches Arduino 1.0, everything is configured through pins_arduino.h files (one for each type), and it should be much easier to add new processors - just a new pins_arduino.h file (i’ll make a thread for it once tested).

After a slight misshap and a bricked chip, I got the bootloader working with the reset pin disabled (just a power cycle is needed to enter bootloader mode).

What I hadn't realised the first time is that ArduinoISP burns the fuse FIRST, then the program space. Which means that it essentially disabled Serial Programming just before it burned the bootloader. Fortunately this site: helped me recover the original fuse settings. I then burned the bootloader without reset disabled, and then used the HV programmer from the link to burn the new fuse settings, disabling the reset pin. And it works :D

What I will do next time to avoid having to use the HVP is to burn the bootloader without the RSTDSBL bit set, then burn it again with it set. The second time won't change the program memory, but it will set the fuse.

Tom, this is great news. I have quite a few projects on Attiny84 and have been looking for a bootloading solution for quite some time now..

Do you plan to document this and release your modifications? edit: got too excited and didn't read carefully :)

I will be on holiday for the next couple of weeks, but after that I will post it :)

The internal oscillator is ±10%. A good rule of thumb is ±4.5% for serial communications.

running the serial communications at as low a BAUD rate as possible to try and reduce the risk of an issue.

10% is still 10% no matter what the bit rate. I don’t think running slower will help.