sleemanj / optiboot

Small and Fast Bootloader for Arduino and other Atmel AVR chips
66 stars 13 forks source link

168PA selection doesn't invoke 168pa hex file? #25

Closed gwideman closed 2 years ago

gwideman commented 2 years ago

The ability to select a bunch of options to select the desired fuse settings and hex files is pretty awesome.

However, I hit a puzzle. I selected Processor version = ATMega168PA, but the bootloader burning process did a couple of anomalous-seeming things:

  1. "Device signature = 0x1e940b (probably m168p)" The signature reported is correct for 168PA, yet this reports 168P. I'm not sure whether the signatures are different, and I'm not even confident that the non-A 168P even exists. But be that as it may...

  2. AVRdude proceeds to read this file: "C:\Users\graham\AppData\Local\Arduino15\packages\diy_atmega8_series\hardware\avr\2020.10.9/bootloaders/ optiboot_atmega168p_16000000L_57600.hex"

OK, so it's fetching a 168p bootloader. But in that same directory are separate bootloaders named with 168pa and 168pb. If they are there, then wouldn't we expect them to be used in this case?

Well, I then compared the 168p, a68pa and 168pb hex files (for 16000000L_57600), and they all seem to have the same content.

Also, your boards.txt shows "build.mcu" values that are 168p for all of the p, pa and pb versions. I'm guessing that it's this build.mcu value that's used to compose the command for AVRdude to load the hex file. If true, then the pa and pb files never get invoked.

So I think the result is probably "all good", but just somewhat confusing because the menu offers these alternative p/pa/pb MCUs, and there are alternate p/pa/pb hex files in the bootloaders directory, but these alternatives don't seem to get invoked.

sleemanj commented 2 years ago

The signature bytes for 168P and PA have the same (0x1E 0x94 0x0B), so avrdude can not tell them apart. We have to tell avrdude what chip it's writing to (m168p as far as it can tell), that comes from build.mcu The same property is given to gcc when compiling (because Arduino does it that way). So when arduino compiles for 168PA it istead compiles for 168P, doesn't matter realy.

The 168PB does have ifferent signature bytes, but it is not supported by AVR-GCC nor Avrdude that I recall, so again we just have to tell it that it's a 168P, I would not be surprised if this didn't work, at least that it didn't upload.

Yes there are 168Px specfic bootloaders for completeness, they are not used (and as you found, probably identical).

gwideman commented 2 years ago

Thanks for confirming.

For what it's worth, having selected ATMega168PA etc in your menu, I ran into an issue that a sketch would not compile because a library (FreqMeasure) was looking for:

// Arduino Uno, Duemilanove, LilyPad, Mini, Fio, etc
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) 
  #define CAPTURE_USE_TIMER1       // ICP1 is pin 8

and evidently __AVR_ATmega168__ was not defined. I'm not sure where that's supposed to be defined, but it was missing in this case. (As a workaround I added "|| defined(ARDUINO_ATMEGA168_DIY)" to the #if defiined.)

sleemanj commented 2 years ago

Since you are compiling for P series the correct define would be __AVR_ATmega168P__ (but the one you added is fine too)

gwideman commented 2 years ago

Yes, I agree that __AVR_ATmega168P__ would be the correct define. But where does that variable normally get defined in the Arduino environment -- I assumed it should happen by virtue of selecting Board: "ATmega168/A/P/PA/PB" or Version: "Atmega168PA", no?

Hmmm, I guess I could "manually" define it in the sketch, before the include for the FreqMeasure library. (Why didn't I think of that before!?)

sleemanj commented 2 years ago

It comes from avr-gcc in the file which you'll find somewhere on your system lib/gcc/avr/7.3.0/device-specs/specs-atmega168p

By virtue of the machine being atmega168_diy.build.mcu=atmega168p in the boards.txt file

sleemanj commented 2 years ago

And no, you can't manually define it in your sketch, your sketch is not part of the compilation unit for the library, ther is no way to pass in defines from your sketch folder into libraries unfortunately, Arduino refuses to allow any way to do so.

gwideman commented 2 years ago

Ah, I see the problem (which I guess you already spotted): FreqMeasure is looking for AVR_ATmega168, but the specs file provides AVR_ATmega168P (with a P).

OK, so the proper fix is to change FreqMeasure to add that variable:

// Arduino Uno, Duemilanove, LilyPad, Mini, Fio, etc
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)  || defined(__AVR_ATmega168P__) 
  #define CAPTURE_USE_TIMER1       // ICP1 is pin 8

Got it. Thanks!

gwideman commented 2 years ago

And no, you can't manually define it in your sketch, your sketch is not part of the compilation unit for the library,

Yeah, I later realized that if I define the need variable in the sketch, it will take effect for the import of the header into the sketch, but not when the header is (earlier in the process) imported into the compilation of the library.