-
Hier mit retten von r24. Jetzt sollte nichts mehr kaputt gehen:
Code:
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <inttypes.h>
void foo( uint8_t whichISR )
{
volatile uint8_t isr = whichISR;
}
void _VECTOR(1)( void ) __attribute__ ((naked));
void _VECTOR(1)( void )
{
__asm__ __volatile__ ("push r24" ::);
foo(1);
__asm__ __volatile__ ("pop" ::);
__asm__ __volatile__ ("reti" ::);
}
void _VECTOR(2)( void ) __attribute__ ((naked));
void _VECTOR(2)( void )
{
__asm__ __volatile__ ("push r24" ::);
foo(2);
__asm__ __volatile__ ("pop" ::);
__asm__ __volatile__ ("reti" ::);
}
void _VECTOR(3)( void ) __attribute__ ((naked));
void _VECTOR(3)( void )
{
__asm__ __volatile__ ("push r24" ::);
foo(3);
__asm__ __volatile__ ("pop" ::);
__asm__ __volatile__ ("reti" ::);
}
Code:
.file "scratch.c"
.arch atmega48
__SREG__ = 0x3f
__SP_H__ = 0x3e
__SP_L__ = 0x3d
__tmp_reg__ = 0
__zero_reg__ = 1
.global __do_copy_data
.global __do_clear_bss
.section .debug_abbrev,"",@progbits
.Ldebug_abbrev0:
.section .debug_info,"",@progbits
.Ldebug_info0:
.section .debug_line,"",@progbits
.Ldebug_line0:
.text
.Ltext0:
.global foo
.type foo, @function
foo:
.LFB3:
.LM1:
/* prologue: frame size=1 */
push r28
push r29
in r28,__SP_L__
in r29,__SP_H__
sbiw r28,1
in __tmp_reg__,__SREG__
cli
out __SP_H__,r29
out __SREG__,__tmp_reg__
out __SP_L__,r28
/* prologue end (size=10) */
.LM2:
std Y+1,r24
/* epilogue: frame size=1 */
adiw r28,1
in __tmp_reg__,__SREG__
cli
out __SP_H__,r29
out __SREG__,__tmp_reg__
out __SP_L__,r28
pop r29
pop r28
ret
/* epilogue end (size=9) */
/* function foo size 20 (1) */
.LFE3:
.size foo, .-foo
.global __vector_1
.type __vector_1, @function
__vector_1:
.LFB4:
.LM3:
/* prologue: frame size=0 */
/* prologue: naked */
/* prologue end (size=0) */
.LM4:
/* #APP */
push r24
.LM5:
/* #NOAPP */
ldi r24,lo8(1)
rcall foo
.LM6:
/* #APP */
pop
.LM7:
reti
/* #NOAPP */
/* epilogue: frame size=0 */
/* epilogue: naked */
/* epilogue end (size=0) */
/* function __vector_1 size 8 (8) */
.LFE4:
.size __vector_1, .-__vector_1
.global __vector_2
.type __vector_2, @function
__vector_2:
.LFB5:
.LM8:
/* prologue: frame size=0 */
/* prologue: naked */
/* prologue end (size=0) */
.LM9:
/* #APP */
push r24
.LM10:
/* #NOAPP */
ldi r24,lo8(2)
rcall foo
.LM11:
/* #APP */
pop
.LM12:
reti
/* #NOAPP */
/* epilogue: frame size=0 */
/* epilogue: naked */
/* epilogue end (size=0) */
/* function __vector_2 size 8 (8) */
.LFE5:
.size __vector_2, .-__vector_2
.global __vector_3
.type __vector_3, @function
__vector_3:
.LFB6:
.LM13:
/* prologue: frame size=0 */
/* prologue: naked */
/* prologue end (size=0) */
.LM14:
/* #APP */
push r24
.LM15:
/* #NOAPP */
ldi r24,lo8(3)
rcall foo
.LM16:
/* #APP */
pop
.LM17:
reti
/* #NOAPP */
/* epilogue: frame size=0 */
/* epilogue: naked */
/* epilogue end (size=0) */
/* function __vector_3 size 8 (8) */
.LFE6:
.size __vector_3, .-__vector_3
.Letext0:
.section .debug_line
.long .LELT0-.LSLT0
.LSLT0:
.word 2
.long .LELTP0-.LASLTP0
.LASLTP0:
.byte 0x1
.byte 0x1
.byte 0xf6
.byte 0xf5
.byte 0xa
.byte 0x0
.byte 0x1
.byte 0x1
.byte 0x1
.byte 0x1
.byte 0x0
.byte 0x0
.byte 0x0
.byte 0x1
.ascii ".."
.byte 0
.ascii "C:/Programme/WinAVR/bin/../lib/gcc/avr/3.4.3/../../../../avr"
.ascii "/include"
.byte 0
.byte 0x0
.string "stdint.h"
.uleb128 0x2
.uleb128 0x0
.uleb128 0x0
.string "scratch.c"
.uleb128 0x1
.uleb128 0x0
.uleb128 0x0
.byte 0x0
.LELTP0:
.byte 0x0
.uleb128 0x3
.byte 0x2
.word .LM1
.byte 0x4
.uleb128 0x2
.byte 0x19
.byte 0x0
.uleb128 0x3
.byte 0x2
.word .LM2
.byte 0x15
.byte 0x0
.uleb128 0x3
.byte 0x2
.word .LM3
.byte 0x19
.byte 0x0
.uleb128 0x3
.byte 0x2
.word .LM4
.byte 0x15
.byte 0x0
.uleb128 0x3
.byte 0x2
.word .LM5
.byte 0x15
.byte 0x0
.uleb128 0x3
.byte 0x2
.word .LM6
.byte 0x15
.byte 0x0
.uleb128 0x3
.byte 0x2
.word .LM7
.byte 0x15
.byte 0x0
.uleb128 0x3
.byte 0x2
.word .LM8
.byte 0x1a
.byte 0x0
.uleb128 0x3
.byte 0x2
.word .LM9
.byte 0x15
.byte 0x0
.uleb128 0x3
.byte 0x2
.word .LM10
.byte 0x15
.byte 0x0
.uleb128 0x3
.byte 0x2
.word .LM11
.byte 0x15
.byte 0x0
.uleb128 0x3
.byte 0x2
.word .LM12
.byte 0x15
.byte 0x0
.uleb128 0x3
.byte 0x2
.word .LM13
.byte 0x1a
.byte 0x0
.uleb128 0x3
.byte 0x2
.word .LM14
.byte 0x15
.byte 0x0
.uleb128 0x3
.byte 0x2
.word .LM15
.byte 0x15
.byte 0x0
.uleb128 0x3
.byte 0x2
.word .LM16
.byte 0x15
.byte 0x0
.uleb128 0x3
.byte 0x2
.word .LM17
.byte 0x15
.byte 0x0
.uleb128 0x3
.byte 0x2
.word .Letext0
.byte 0x0
.uleb128 0x1
.byte 0x1
.LELT0:
.section .debug_info
.long 220
.word 2
.long .Ldebug_abbrev0
.byte 0x2
.uleb128 0x1
.long .Ldebug_line0
.word .Letext0
.word .Ltext0
.long .LASF10
.byte 0x1
.long .LASF11
.long .LASF12
.uleb128 0x2
.long .LASF0
.byte 0x1
.byte 0x6
.uleb128 0x3
.long .LASF13
.byte 0x1
.byte 0x46
.long 51
.uleb128 0x2
.long .LASF1
.byte 0x1
.byte 0x8
.uleb128 0x4
.string "int"
.byte 0x2
.byte 0x5
.uleb128 0x2
.long .LASF2
.byte 0x2
.byte 0x7
.uleb128 0x2
.long .LASF3
.byte 0x4
.byte 0x5
.uleb128 0x2
.long .LASF4
.byte 0x4
.byte 0x7
.uleb128 0x2
.long .LASF5
.byte 0x8
.byte 0x5
.uleb128 0x2
.long .LASF6
.byte 0x8
.byte 0x7
.uleb128 0x5
.long 152
.byte 0x1
.string "foo"
.byte 0x2
.byte 0x6
.byte 0x1
.word .LFB3
.word .LFE3
.byte 0x6
.byte 0x6c
.byte 0x93
.uleb128 0x1
.byte 0x6d
.byte 0x93
.uleb128 0x1
.uleb128 0x6
.long .LASF14
.byte 0x2
.byte 0x5
.long 40
.byte 0x1
.byte 0x68
.uleb128 0x7
.string "isr"
.byte 0x2
.byte 0x7
.long 152
.byte 0x2
.byte 0x91
.sleb128 1
.byte 0x0
.uleb128 0x8
.long 40
.uleb128 0x9
.byte 0x1
.long .LASF7
.byte 0x2
.byte 0xc
.byte 0x1
.word .LFB4
.word .LFE4
.byte 0x8
.byte 0x90
.uleb128 0x20
.byte 0x93
.uleb128 0x1
.byte 0x90
.uleb128 0x21
.byte 0x93
.uleb128 0x1
.uleb128 0x9
.byte 0x1
.long .LASF8
.byte 0x2
.byte 0x16
.byte 0x1
.word .LFB5
.word .LFE5
.byte 0x8
.byte 0x90
.uleb128 0x20
.byte 0x93
.uleb128 0x1
.byte 0x90
.uleb128 0x21
.byte 0x93
.uleb128 0x1
.uleb128 0x9
.byte 0x1
.long .LASF9
.byte 0x2
.byte 0x20
.byte 0x1
.word .LFB6
.word .LFE6
.byte 0x8
.byte 0x90
.uleb128 0x20
.byte 0x93
.uleb128 0x1
.byte 0x90
.uleb128 0x21
.byte 0x93
.uleb128 0x1
.byte 0x0
.section .debug_abbrev
.uleb128 0x1
.uleb128 0x11
.byte 0x1
.uleb128 0x10
.uleb128 0x6
.uleb128 0x12
.uleb128 0x1
.uleb128 0x11
.uleb128 0x1
.uleb128 0x25
.uleb128 0xe
.uleb128 0x13
.uleb128 0xb
.uleb128 0x3
.uleb128 0xe
.uleb128 0x1b
.uleb128 0xe
.byte 0x0
.byte 0x0
.uleb128 0x2
.uleb128 0x24
.byte 0x0
.uleb128 0x3
.uleb128 0xe
.uleb128 0xb
.uleb128 0xb
.uleb128 0x3e
.uleb128 0xb
.byte 0x0
.byte 0x0
.uleb128 0x3
.uleb128 0x16
.byte 0x0
.uleb128 0x3
.uleb128 0xe
.uleb128 0x3a
.uleb128 0xb
.uleb128 0x3b
.uleb128 0xb
.uleb128 0x49
.uleb128 0x13
.byte 0x0
.byte 0x0
.uleb128 0x4
.uleb128 0x24
.byte 0x0
.uleb128 0x3
.uleb128 0x8
.uleb128 0xb
.uleb128 0xb
.uleb128 0x3e
.uleb128 0xb
.byte 0x0
.byte 0x0
.uleb128 0x5
.uleb128 0x2e
.byte 0x1
.uleb128 0x1
.uleb128 0x13
.uleb128 0x3f
.uleb128 0xc
.uleb128 0x3
.uleb128 0x8
.uleb128 0x3a
.uleb128 0xb
.uleb128 0x3b
.uleb128 0xb
.uleb128 0x27
.uleb128 0xc
.uleb128 0x11
.uleb128 0x1
.uleb128 0x12
.uleb128 0x1
.uleb128 0x40
.uleb128 0xa
.byte 0x0
.byte 0x0
.uleb128 0x6
.uleb128 0x5
.byte 0x0
.uleb128 0x3
.uleb128 0xe
.uleb128 0x3a
.uleb128 0xb
.uleb128 0x3b
.uleb128 0xb
.uleb128 0x49
.uleb128 0x13
.uleb128 0x2
.uleb128 0xa
.byte 0x0
.byte 0x0
.uleb128 0x7
.uleb128 0x34
.byte 0x0
.uleb128 0x3
.uleb128 0x8
.uleb128 0x3a
.uleb128 0xb
.uleb128 0x3b
.uleb128 0xb
.uleb128 0x49
.uleb128 0x13
.uleb128 0x2
.uleb128 0xa
.byte 0x0
.byte 0x0
.uleb128 0x8
.uleb128 0x35
.byte 0x0
.uleb128 0x49
.uleb128 0x13
.byte 0x0
.byte 0x0
.uleb128 0x9
.uleb128 0x2e
.byte 0x0
.uleb128 0x3f
.uleb128 0xc
.uleb128 0x3
.uleb128 0xe
.uleb128 0x3a
.uleb128 0xb
.uleb128 0x3b
.uleb128 0xb
.uleb128 0x27
.uleb128 0xc
.uleb128 0x11
.uleb128 0x1
.uleb128 0x12
.uleb128 0x1
.uleb128 0x40
.uleb128 0xa
.byte 0x0
.byte 0x0
.byte 0x0
.section .debug_pubnames,"",@progbits
.long 67
.word 2
.long .Ldebug_info0
.long 224
.long 100
.string "foo"
.long 157
.string "__vector_1"
.long 179
.string "__vector_2"
.long 201
.string "__vector_3"
.long 0
.section .debug_aranges,"",@progbits
.long 16
.word 2
.long .Ldebug_info0
.byte 0x2
.byte 0x0
.word .Ltext0
.word .Letext0-.Ltext0
.word 0
.word 0
.section .debug_str,"MS",@progbits,1
.LASF5:
.string "long long int"
.LASF12:
.string "D:\\priv\\Tech\\atmel\\learning\\scratch\\default"
.LASF2:
.string "unsigned int"
.LASF10:
.string "GNU C 3.4.3"
.LASF4:
.string "long unsigned int"
.LASF6:
.string "long long unsigned int"
.LASF14:
.string "whichISR"
.LASF13:
.string "uint8_t"
.LASF1:
.string "unsigned char"
.LASF3:
.string "long int"
.LASF7:
.string "__vector_1"
.LASF8:
.string "__vector_2"
.LASF9:
.string "__vector_3"
.LASF0:
.string "signed char"
.LASF11:
.string "../scratch.c"
/* File "../scratch.c": code 44 = 0x002c ( 25), prologues 10, epilogues 9 */
-
Ok, wenn du jetzt etwas mehr machst in foo (auf die Variable isr müsstest du pollen, also könnte man auch gleich auf die IRQ-Flags pollen und das ganze Interrupt-Zeug weglassen, was aber wiederum nicht geht...).
foo verändert z.B. das SREG -- es wird nicht wieder hergestellt!. Und wenn sich foo entscheidet, R0, R1, R18..R27, R30 oder R31 anzupacken, werden die auch nicht gesichert...
Im Endeffekt schaffst du nur mit Assembler, das wasserdicht zu bekommen, weil du von avr-gcc nicht erfahren kannst, welche Register er benutzt (oder doch?).
-
Du hast recht. Man könnte in foo() einmal den Prolog der "normalen" ISR (SREG und Register sichern) sowie den Epilog (SREG und register restaurieren) reinschreiben. Also als Makro den inline Assembler Code für Prolog und Epilog.
Für die Übergabeparameter müssen dann nochmal die entsprechenden Register in der ISR gesichert/restauriert werden.
Unterm Strich bleibt dann doch zumindest eine gehörige Portin inline Assembler übrig.
-
Im Endeffekt wäre man also quasi bei einer reinen asm-Lösung...
Am besten gefällt mir bislang die Lösung von PickNick. Bleibt nur die Frage, wie man an den Ort der return-Adresse kommt.
Chertikov schreibt, er habe __builtin_return_address nicht implementiert, weil das eh niemand brauche *grrr*
-
Na ja
push
push
...
push
IN ZL, SPL
IN ZH, SPH
LDD R24, Z+ Offset // =lsb-byte Low(return addr)
(r24 >> 1) --> Vector-# // das geht jetz aber auf SREG
Offset hängt ab, was alles gepusht wird
Beim rechnen auf WORD /BYTE aufpassen, was man halt braucht.
-
Schon klar, wie's in asm ginge.
An diesen Offset komm ich eben nicht dran von C aus :-(
lst-nachschauen und hart reincodieren schliess ich jetzt man aus, weil es keine Möglichkeit gibt, das nach einem Rebuild auf Korrektheit zu prüfen (ausser jedes Mal das asm zu kontrollieren).
-
Würd' ich, glaub ich, nicht machen, aber du könntest den stack aufwärts lesen, bis du eine return addresse aus dem Vector-bereich hast. Das machst du beim ersten Interrupt einmal und merkst dir das dann Offset.
naja, es bleibt eine Sauerei.
-
1. In der VecTab stehen nur rjmp-Befehle. Auf dem Stack findet sich also keine return-Adresse, die in die VecTab zeigt.
2. Wer sagt, daß nicht eine Reg-Kombination gepusht wurde, die so interpretierbar wäre. Insbesondere wird R1 gepusht, das fast immer 0 sein dürfte, was die Wahrscheinlickeit einer Fehlinterpretation stark erhöht. Jedenfalls würd ich so was nicht als funktionierenden Code ansehen, auch dann, wenn er in einem speziellen Fall das tut, was man möchte.
-
Ja, stimmt, ist wahr.
Also, ich würde dann eher versuchen, die ganze Interrrupt-geschichte dem C aus der Hand zu nehmen und dann aber konsequent als assembler module extra zu machen, also eigentlich nur pro- und epilog, natürlich.
Dieses Modul ruft dann foo(vec-nr) als normale function auf.
-
Warum dann nicht einfach mit -mcall-prologues compilieren und die ISRs naked attributieren? Das hält foo() kurz und sorgt auch dafür, dass die Register sauber bleiben (und man bleibt weitestgehend bei C).
foo() und die ISR sollten dann in einer eigenen Datei sein, da sonst alles mit -call-prologues compiliert wird was boshafterweise auch zu größeren Code führen kann, da der gcc-avr bei der Parameterübergabe in Registern schon sehr gut optimiert.