Closed stefano-zanotti-88 closed 2 years ago
The optimization of "PINx |= bit;" to "SBI" by the compiler, even though it's technically incorrect for some registers has been well-discussed in assorted fora. The truth is that C doesn't really have any concept of data whose written value is "unrelated" to the read value. I'm loathe to introduce conditional compilation or inline asm until this becomes an actual problem on a "popular" Optiboot configuration, though I agree that it's currently a bug for mega1280/2560/etc if you want to use a high-numbered port for the LED...
OK. A brief comment explaining the (non-)issue would be useful though.
To toggle a pin, optiboot.c uses an OR mask: https://github.com/Optiboot/optiboot/blob/81bdd404ff70b76fed716a10bbde90149d98e647/optiboot/bootloaders/optiboot/optiboot.c#L1270
However, it seems that in order to toggle a pin you just need to write 1 to the bit you need, and should write 0 to all the others. Actually, by or-ing, you are also toggling all the bits that are currently high (which changes the state of the outputs, and messes with the pullup state of the inputs). This might not cause problems in many cases, but it really depends on what those pins do on a specific board, which is outside of the bootloader's control.
See here: https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf Section 13.1:
I've tried to compile a simple test on an ATmega328PB, and this is the generated asm:
So it seems that the "wrong" PIN|= is compact, while the proper one PIN= uses more flash, though it still wins over a naive PORT^=
This also depends on the specific PORT/part. On an ATmega2560:
the proper way is also the most compact.
From experimentation in Atmel Studio's simulator, it seems that PIN= and PIN|= are equivalent, when the latter is optimized to SBI rather than STS, but I'm not sure if this can be relied upon (actually, it might also be that the compiler optimization to SBI should be illegal when writing to PIN). When PIN|= is compiled to STS, undesirable pin toggles happen indeed (in the simulator).
I think it would be safer to switch to using PIN= Alternatively, it might be worth considering a conditional optimization similar to this: https://github.com/Optiboot/optiboot/blob/81bdd404ff70b76fed716a10bbde90149d98e647/optiboot/bootloaders/optiboot/optiboot.c#L807-L811 To at least use PIN= when PIN|= would be compiled to STS