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

Interrupt handler symbol name incorrect? #9

Open
nh2 opened this issue Aug 6, 2018 · 6 comments
Open

Interrupt handler symbol name incorrect? #9

nh2 opened this issue Aug 6, 2018 · 6 comments

Comments

@nh2
Copy link

nh2 commented Aug 6, 2018

The README shows

pub unsafe extern "avr-interrupt" fn _ivr_timer1_compare_a() {

as interrupt handler for timer1 but that didn't work for me on the Arduino Uno Rev3.

Every time the interrupt arrived, the board did a full reset because no interrupt handler was correctly defined.

This worked:

pub unsafe extern "C" fn __vector_11() {

as that is what ISR(TIMER1_COMPA_vect) (see e.g. here) expands to when used from the Arduino IDE.

@nh2
Copy link
Author

nh2 commented Aug 7, 2018

I just learned it should be

pub unsafe extern "avr-interrupt" fn __vector_11() {

instead of

pub unsafe extern "C" fn __vector_11() {

because otherwise the ISR can be called only once.

I suspect that is about

Patching into the vector table is only one part of the problem. The compiler uses, by convention, a set of registers when it's normally executing compiler-generated code. It's important that these registers, as well as the status register, get saved and restored. The extra code needed to do this is enabled by tagging the interrupt function with __attribute__((signal)).

from http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html

In particular TIFR1 becomes 6 with extern "C" and 4 with extern "avr-interrupt".

@nh2
Copy link
Author

nh2 commented Aug 8, 2018

By the way, I implemented Arduino's micros() logic and counter/interrupt approach in Rust for a project here, in case anybody is interested:

https://github.com/nh2/quadcopter-simulation/blob/8a3652b8a704877156e91c0691ce8ce37588eb53/arduino-accel-rust/src/main.rs#L216

Would be nice to move much of that into ruduino later.

@dylanmckay
Copy link
Member

I wonder if the interrupt vector symbol name depends on the assembly code chosen for the IVT table.

For example, here's the objdump output of a hello world executable compiled with avr-gcc with an -mmcu specified. This will correspond to some assembly code (probably in the device-specific CRT) that will jump to interrupt functions like jmp __vector_11. I don't think we have an interrupt table included by default in avr-rust executables - there isn't any CRT loading done in Rust.

00000000 <__vectors>:
   0:   0c 94 34 00     jmp     0x68    ; 0x68 <__ctors_end>
   4:   0c 94 3e 00     jmp     0x7c    ; 0x7c <__bad_interrupt>
   8:   0c 94 3e 00     jmp     0x7c    ; 0x7c <__bad_interrupt>
   c:   0c 94 3e 00     jmp     0x7c    ; 0x7c <__bad_interrupt>
  10:   0c 94 3e 00     jmp     0x7c    ; 0x7c <__bad_interrupt>
  14:   0c 94 3e 00     jmp     0x7c    ; 0x7c <__bad_interrupt>
  18:   0c 94 3e 00     jmp     0x7c    ; 0x7c <__bad_interrupt>
  1c:   0c 94 3e 00     jmp     0x7c    ; 0x7c <__bad_interrupt>
  20:   0c 94 3e 00     jmp     0x7c    ; 0x7c <__bad_interrupt>
  24:   0c 94 3e 00     jmp     0x7c    ; 0x7c <__bad_interrupt>
  28:   0c 94 3e 00     jmp     0x7c    ; 0x7c <__bad_interrupt>
  2c:   0c 94 3e 00     jmp     0x7c    ; 0x7c <__bad_interrupt>
  30:   0c 94 3e 00     jmp     0x7c    ; 0x7c <__bad_interrupt>
  34:   0c 94 3e 00     jmp     0x7c    ; 0x7c <__bad_interrupt>
  38:   0c 94 3e 00     jmp     0x7c    ; 0x7c <__bad_interrupt>
  3c:   0c 94 3e 00     jmp     0x7c    ; 0x7c <__bad_interrupt>
  40:   0c 94 3e 00     jmp     0x7c    ; 0x7c <__bad_interrupt>
  44:   0c 94 3e 00     jmp     0x7c    ; 0x7c <__bad_interrupt>
  48:   0c 94 3e 00     jmp     0x7c    ; 0x7c <__bad_interrupt>
  4c:   0c 94 3e 00     jmp     0x7c    ; 0x7c <__bad_interrupt>
  50:   0c 94 3e 00     jmp     0x7c    ; 0x7c <__bad_interrupt>
  54:   0c 94 3e 00     jmp     0x7c    ; 0x7c <__bad_interrupt>
  58:   0c 94 3e 00     jmp     0x7c    ; 0x7c <__bad_interrupt>
  5c:   0c 94 3e 00     jmp     0x7c    ; 0x7c <__bad_interrupt>
  60:   0c 94 3e 00     jmp     0x7c    ; 0x7c <__bad_interrupt>
  64:   0c 94 3e 00     jmp     0x7c    ; 0x7c <__bad_interrupt>

Perhaps the README is using a different IVT jump table with different interrupt function symbol names?

It raises a good question - how to go about standardising it

@shepmaster
Copy link
Member

if the interrupt vector symbol name depends on the assembly code chosen for the IVT table.

Yes, it certainly does. The one shown comes from my custom assembly, which has the aim of not linking to any avr-gcc code whatsoever. This means I get to pick more expressive names.

@dylanmckay
Copy link
Member

Raised #12 for coming up with a single, ecosystem-wide way to define interrupts.

@lord-ne
Copy link

lord-ne commented Aug 25, 2021

Does the function actually need to be declared unsafe?

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

4 participants