Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

don't use atmega328p spec for atmega328pb it can lead to catastrophic UB #487

Open
Vollbrecht opened this issue Jan 3, 2024 · 0 comments

Comments

@Vollbrecht
Copy link
Contributor

Vollbrecht commented Jan 3, 2024

i try to break all issues regarding this topic down into the following.

  1. avr-hal doesn't have a dedicated atmega328pb spec
  2. for testing in CI it uses atmega328p spec
  3. adding one spec manual with the correct pre-link-args of -mmcu=atmega328pb will fail to link on many toolchains ( more on that later)

example of UB introduced when using -mmcu=atmega328p in combination with avr-device feature atmega328pb. When creating a PCINT3 interrupt it silently fails to correctly create the correct vector jump table for the ISR defined with some code like this

#[avr_device::interrupt(atmega328pb)]
fn PCINT3() {
   // some code 
}

the pac is absolutely correct and you can manipulate all registers with just atmega328p link args. You will not get a warning it just silently accepts it but the resulting elf will not work correctly. Similar behavior is to be accepted on all features added on the atmega328pb.

To solve the problem please use a custom spec with the correct pre-link-args of -mmcu=atmega328pb

90% of people will then run into a new problem that it will not link. This is duo to the fact that most tool-chains - even the latest available prebuild avr-gcc on microchips site doesn't have full correct support of atmega328pb. ( debians avr-gcc is using version 5.4 ) i think its a problem even with avr-gcc up to version 10.

If you want to stay on your avr-gcc version you can manually patch it by

  1. downloading the latest ATmega support pack from microchips website
  2. Unzip 3 relevant files :
 unzip -j Atmel.ATmega_DFP.x.y.zzz.atpack \
 gcc/dev/atmega328pb/avr5/crtatmega328pb.o \
 gcc/dev/atmega328pb/avr5/libatmega328pb.a \
 include/avr/iom328pb.h
  1. cd into your base avr toolchain folder ( either something like /usr/avr/ or if you manual downloaded as AVR 8-Bit toolchain from here into /avr8-gnu-toolchain-<target>
  2. Place the .o and .a files into /usr/avr/lib/avr5/ ( system install) or /avr/lib/avr5 (microchip install)
  3. Place the .h file into /usr/avr/include/avr/ (system install) or /avr/include/avr/ (microchip isntall)
  4. patch /usr/avr/include/avr/io.h to include the correct avr header by adding
 #elif defined (__AVR_ATmega328PB__) || defined (__AVR_ATmega328__)
 #  include <avr/iom328pb.h>

With that you should be ready to compile and have a your rust code don't get linked into a big UB hell that will kill even atmel-ice and any other debugger when trying to find the cause =)

@Vollbrecht Vollbrecht changed the title don't use atmega328p spec for atmega328pb it can lead to catastropical UB don't use atmega328p spec for atmega328pb it can lead to catastrophic UB Jan 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant