avr-rust / ruduino

Reusable components for the Arduino Uno.
Apache License 2.0
702 stars 50 forks source link

Interrupt handler symbol name incorrect? #9

Open nh2 opened 6 years ago

nh2 commented 6 years ago

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 commented 6 years ago

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 commented 6 years ago

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 commented 6 years ago

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 commented 6 years ago

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 commented 6 years ago

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

lord-ne commented 3 years ago

Does the function actually need to be declared unsafe?