NEWER New Optiboot bootloader

Supported processors are burned into the compiler. You need a newer toolset.

Hello,

Newer toolset?

I made the hex file with atmel studio 7. The IDE is package version 1.6.9

What exactly should I update?

In the past, I have just copied the toolset from Atmel Studio to the correct location in the Arduino IDE directory. I have also copied the entirety of... http://www.atmel.com/tools/ATMELAVRTOOLCHAINFORWINDOWS.aspx ...to the correct location in the Arduino IDE directory. I believe I have even posted detailed instructions on this forum.

Yup... http://forum.arduino.cc/index.php?topic=168152.msg1252235#msg1252235 But that may be out-of-date.

The easiest way to get a PB working is to pretend that it's just a 328P. After that is "working" (bootloader burnt, sketches uploading successfully) you can start to think about how to access the PB features... (in fact, the current optiboot PB support pretends to be a mere P, because of the state of the Arduino IDE compiler/etc.)

(The AS7 (7.0.943) that I installed TODAY does seem to support the 328PB.)

westfw: in fact, the current optiboot PB support pretends to be a mere P, because of the state of the Arduino IDE compiler/etc. (The AS7 (7.0.943) that I installed TODAY does seem to support the 328PB.)

Yes, I saw that line in our code -> optibootxmini328pb.build.mcu=atmega328p

I try to get a solution to get it work under the Arduino IDE.

Regards, Maverick

Hello

I have downloaded the newest Optiboot from github and placed it under 'Documents/Arduino/hardware/'. However whenever I try to burn the bootloader (Optiboot 28pins, 8Mhz) to an atmega328p with an USBasp I get the following error:

java.lang.NullPointerException
    at cc.arduino.packages.uploaders.SerialUploader.burnBootloader(SerialUploader.java:363)
    at processing.app.Editor.lambda$handleBurnBootloader$42(Editor.java:2752)
    at java.lang.Thread.run(Thread.java:745)
Error while burning bootloader.

Also when I try to compile Blink, I get:

panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x1 addr=0x0 pc=0x4b39ba]

goroutine 1 [running]:
arduino.cc/builder.(*SetupBuildProperties).Run(0x692034, 0x12054000, 0x0, 0x0)
    c:/jenkins/workspace/arduino-builder-windows/src/arduino.cc/builder/setup_build_properties.go:86 +0x10ba
arduino.cc/builder.(*ContainerSetupHardwareToolsLibsSketchAndProps).Run(0x692034, 0x12054000, 0x0, 0x0)
    c:/jenkins/workspace/arduino-builder-windows/src/arduino.cc/builder/container_setup.go:59 +0x4e6
arduino.cc/builder.runCommands(0x12054000, 0x12025dc4, 0x3, 0x3, 0x1, 0x0, 0x0)
    c:/jenkins/workspace/arduino-builder-windows/src/arduino.cc/builder/builder.go:181 +0xe2
arduino.cc/builder.(*ParseHardwareAndDumpBuildProperties).Run(0x12025df0, 0x12054000, 0x0, 0x0)
    c:/jenkins/workspace/arduino-builder-windows/src/arduino.cc/builder/builder.go:170 +0x157
arduino.cc/builder.RunParseHardwareAndDumpBuildProperties(0x12054000, 0x0, 0x0)
    c:/jenkins/workspace/arduino-builder-windows/src/arduino.cc/builder/builder.go:217 +0x35
main.main()
    c:/jenkins/workspace/arduino-builder-windows/src/arduino.cc/arduino-builder/main.go:307 +0xfd7
arduino-builder returned 2

Error compiling for board Optiboot on 28-pin cpus.

Obviously the paths are wrong (There is no C:\jenkins\workspace). I'm sure I've missed a huge step during install, how can I fix this?

Did it work for normal platform builds before you tried to add the ne optiboot? What ide version are you using?

westfw: Did it work for normal platform builds before you tried to add the ne optiboot? What ide version are you using?

When "Atmega328 on a breadboard 8Mhz" (from tutorial) is selected I can burn the bootloader and upload sketches without problems, is that what you mean?

I'm using Arduino IDE 1.6.9

@westfw Could You complete optiboot for the 328PB?

@westfw I am using WinAVR-20100110 to compile optiboot. I am now sanity checking my output by comparing the original hex file with my compiled version. They match up except for this line:

Original :087FD000E7DFEE27FF2709940B

Fresh compile 087FD000E7DFE0E0FF27099460

The most important bit being E7DFEE27FF270994 versus E7DFE0E0FF270994 (E27 or 0E0) Is this a relevant difference? And what does it mean?

Does anyone know if there is a version of optiboot for the ATTiny 4313? I went through the old optiboot thread searching for it. No luck. Incidentally, I have 1Kbyte of flash remaining.

The most important bit being E7DF EE27 FF27 0994 versus E7DF E0E0 FF27 0994 (E27 or 0E0)

The original has an instruction:

    7fd0:       e7 df           rcall   .-50            ; 0x7fa0                                                                               
  __asm__ __volatile__ (                                                        
    7fd2:       ee 27           eor     r30, r30                                
    7fd4:       ff 27           eor     r31, r31                                
    7fd6:       09 94           ijmp

With the EE27 instruction being the "eor r30, r30" - an exclusive or with yourself is one way to clear the register. The new version has "e0e0" instead, which is "ldi r30, 0" - which does the same thing (zero the register.) So you should be fine...

version of optiboot for the ATTiny 4313?

Not that I know of. You might check the version mentioned in https://github.com/Optiboot/optiboot/issues/177; it apparently supports 110 chips (but I haven't gotten a chance to look at it at all.)

@westfw Ah, that's why the version wasn't updated: the behavior is the same. Thanks!

@westFW Thanks! 326 bytes... That is tiny.

After some long period on Arduino IDE v1.0.6 with replaced toolchain to v3.4.2 (avr-gcc v4.7.2), I've decided to move to the Atmel AVR Toolchain v3.5.3.1700 with avr-gcc v4.9.2. I had to resolve two simple problems: 1. avr-gcc v4.9.2 doesn't support optimizing option -mshort-calls; there is -mrelax instead 2. problem with eeprom_write_byte and eeprom_read_byte (undefined reference); LIBS = -l$(MCU_TARGER) solves it. As I'm writting this I found in response #75 the same solution for my 2nd problem and also (partially - I'm not satisfied with) for my question. The question is: "How to achieve at least the same size of image without modifying source code?" I have modified optiboot and its size with 4.7.2 is 706B, with 4.9.2 it is 738B. Is there any option for another optimizing step (any switch) or the 4.9.2 simply produces bigger code and this possibility is closed?

EDIT: I tried BareMinimum sketch and the size is the same.

EDIT2: I'm currently working with ATmega1284P but as I see the optiboot for ATmega328P does not fit into 512B. It is 525B now.

First partial success or nearly full success! Going throughout the ASM code I realised that the main harms are caused by optimizing the watchdogConfig(). So the attribute noinline produces smaller code, now it's 708B which is very close to 706B, but for the UNO it is 494B to previous 488B. And as I see the original optiboot code on the GitHub it already has defined as noinline. :( :confused: :) :D 8)

I've decided to move to the Atmel AVR Toolchain v3.5.3.1700 with avr-gcc v4.9.2. I see the optiboot for ATmega328P does not fit into 512B.

I'm using Atmel 3.5.2_444 (which is also gcc 4.9.2), and the stock optiboot for 328 compiles to 464 bytes. Are you using the latest source from the github repository at https://github.com/Optiboot/optiboot, the source from the IDE distribution, or something else? (The change to -mrelax was made over two years ago. The version distributed with the IDE hasn't been updated in forever, and isn't particularly expected to be updated...)

No, not latest source. I think, I started with 4.6 version and did several modifications. My version is probably little bit far from actual official optiboot. I missed the switch -mrelax because I'm using gcc 4.7.2 for the years, since Arduino IDE 1.0.6 was released. This version of IDE uses gcc 4.3.2 which was very old at this time. So, I replaced the whole AVR toolchain with gcc 4.7.2 to be same as Atmel Studio 6.1 has. I don't want to critize the Arduino 1.6.x versions but the reason why I'm not using it is that there is a lot of bugs and the changes in SW don't offer me a benefit concerning to ATmega. I have modified core for my needs focused mainly to a size. I know about the difference in size of UNO bootloader: official 464 vs mine 488. I cannot say why at now. I have a dozen genuine UNOs but never changed the bootloader and I would use original in case. Mainly I am interesting in 1284P. I have my own variant. My bootloader allows to upload into EEPROM and reads the fuses and lock etc. to utilize 1kB of boot space.

Here is a snippet for a fuses and lock.

    /* STK500 Universal Command */
        } else if(ch == STK_UNIVERSAL) {        // universal command - fuse & lock bits
            #if defined(BIGBOOT)
            /* read fuse and lock bits; it takes additional 80 bytes */
                uint8_t ucb1 = getch();         // universal command byte 1
                uint8_t ucb2 = getch();         // universal command byte 2
                getNch(2);                      // discard universal command byte 3-4
                uint8_t ucr  = 0;              // response

            /* mapping algorithm for function parameter, optimized to save a space:
                ucb1(0x50), ucb2(0x00) -> GET_LOW_FUSE_BITS     (0x0000)
                ucb1(0x58), ucb2(0x00) -> GET_LOCK_BITS         (0x0001)
                ucb1(0x50), ucb2(0x08) -> GET_EXTENDED_FUSE_BITS(0x0002)
                ucb1(0x58), ucb2(0x08) -> GET_HIGH_FUSE_BITS    (0x0003)
             */
                if((ucb1 & ~(0x08)) == 0x50 && (ucb2 & ~(0x08)) == 0x00) {
                    ucb1  = ((ucb1 & 0x08) ? 1 : 0) | (ucb2 >> 2);
                    ucr   = boot_lock_fuse_bits_get((uint16_t)ucb1);
                }
                putch(ucr);
            #else                               // universal command is ignored
                getNch(4);                      // 4 bytes of data/command
                putch(0x00);                    // response
            #endif

It should produce this:

    /* STK500 Universal Command */
        } else if(ch == STK_UNIVERSAL) {        // universal command - fuse & lock bits
   1fcb8:  86 35        cpi r24, 0x56   ; 86
   1fcba:  d1 f4        brne    .+52      ; 0x1fcf0 
            #if defined(BIGBOOT)
            /* read fuse and lock bits; it takes additional 82 bytes */
                uint8_t ucb1 = getch();         // universal command byte 1
   1fcbc:  c5 d0        rcall   .+394     ; 0x1fe48 
   1fcbe:  c8 2e        mov r12, r24
                uint8_t ucb2 = getch();         // universal command byte 2
   1fcc0:  c3 d0        rcall   .+390     ; 0x1fe48 
   1fcc2:  d8 2e        mov r13, r24
                getNch(2);                      // discard universal command byte 3-4
   1fcc4:  82 e0        ldi r24, 0x02   ; 2
   1fcc6:  da d0        rcall   .+436     ; 0x1fe7c 
                ucb1(0x50), ucb2(0x00) -> GET_LOW_FUSE_BITS     (0x0000)
                ucb1(0x58), ucb2(0x00) -> GET_LOCK_BITS         (0x0001)
                ucb1(0x50), ucb2(0x08) -> GET_EXTENDED_FUSE_BITS(0x0002)
                ucb1(0x58), ucb2(0x08) -> GET_HIGH_FUSE_BITS    (0x0003)
             */
                if((ucb1 & ~(0x08)) == 0x50 && (ucb2 & ~(0x08)) == 0x00) {
   1fcc8:  8c 2d        mov r24, r12
   1fcca:  87 7f        andi    r24, 0xF7   ; 247
   1fccc:  80 35        cpi r24, 0x50   ; 80
   1fcce:  71 f4        brne    .+28      ; 0x1fcec 
   1fcd0:  8d 2d        mov r24, r13
   1fcd2:  87 7f        andi    r24, 0xF7   ; 247
   1fcd4:  59 f4        brne    .+22      ; 0x1fcec 
                    ucb1  = ((ucb1 & 0x08) ? 1 : 0) | (ucb2 >> 2);
   1fcd6:  c3 fa        bst r12, 3
   1fcd8:  ee 27        eor r30, r30
   1fcda:  e0 f9        bld r30, 0
   1fcdc:  d6 94        lsr r13
   1fcde:  d6 94        lsr r13
   1fce0:  ed 29        or  r30, r13
                    ucr   = boot_lock_fuse_bits_get((uint16_t)ucb1);
   1fce2:  f0 e0        ldi r31, 0x00   ; 0
   1fce4:  40 92 57 00     sts 0x0057, r4
   1fce8:  84 91        lpm r24, Z
   1fcea:  cd cf        rjmp    .-102     ; 0x1fc86 
            #if defined(BIGBOOT)
            /* read fuse and lock bits; it takes additional 82 bytes */
                uint8_t ucb1 = getch();         // universal command byte 1
                uint8_t ucb2 = getch();         // universal command byte 2
                getNch(2);                      // discard universal command byte 3-4
                uint8_t ucr  = 0;              // response
   1fcec:  80 e0        ldi r24, 0x00   ; 0
   1fcee:  cb cf        rjmp    .-106     ; 0x1fc86 
                getNch(4);                      // 4 bytes of data/command
                putch(0x00);                    // response
            #endif

Feel free to use it.

...forgot to mention the boot_lock_fuse_bits_get() have to be used the original one from avr/boot.h.