Bin noch neu beim AT91SAM7X und bitte die triviale Frage nach der Realisierung eines Interrupts zu entschuldigen, aber ich finde im Netz einfach keine Anleitung für Dummies. Wenn der Joystick links gedrückt wird (PA15), soll die LED (PB21) per externem Interrupt angehen (von "Hand" setzen der LED mit AT91C_BASE_PIOB->PIO_CODR=AT91C_PIO_PB21 funktioniert und den Joystick mit AT91C_BASE_PIOB->PIO_PDSR&AT91C_PIO_PA23 abfragen klappt auch). Folgender Code mit Interrupt (der nicht beim Tastendruck aufgerufen wird) funktioniert leider nicht: #include "AT91SAM7X256.h" //+********************************************************************* **************** void ex_int_handler (void) { unsigned int dummy; //status lesen um INT zu löschen dummy = AT91C_BASE_PIOA->PIO_ISR; AT91C_BASE_PIOB->PIO_CODR= AT91C_PIO_PB21; //led einschalten //printf("Interrupt occured\r\n\r"); *AT91C_AIC_EOICR = 0; /* Ende des Interrupts*/ AT91C_BASE_AIC->AIC_EOICR = 0; } //+********************************************************************* **************** int main(void) { AT91C_BASE_PIOB->PIO_OER=LED1; AT91C_BASE_PIOB->PIO_SODR = LED1; AT91C_BASE_PIOA->PIO_PDR=AT91C_PIO_PA23; AT91C_BASE_PIOA->PIO_ODR=AT91C_PIO_PA23; AT91C_BASE_PIOA->PIO_CODR=AT91C_PIO_PA23; AT91C_BASE_PIOA->PIO_PPUER=AT91C_PIO_PA23; AT91C_BASE_PIOA->PIO_ASR=AT91C_PIO_PA23; AT91C_BASE_PIOA->PIO_OWDR=AT91C_PIO_PA23; AT91C_BASE_PIOA->PIO_IER=AT91C_PIO_PA23; AT91C_BASE_AIC->AIC_SMR[AT91C_ID_PIOA]=AT91C_AIC_SRCTYPE_INT_POSITIVE_ED GE|0; AT91C_BASE_AIC->AIC_SVR[AT91C_ID_PIOA]=(unsigned int)ex_int_handler; AT91C_BASE_AIC->AIC_IECR=(1<<AT91C_ID_PIOA); while(1); return 0; } Wäre supertoll, wenn jemand den Code komplettieren würde (irgend etwas fehlt bestimmt) oder einen Link auf einen funktionierenden setzen könnte...
Im Moment teste ich
void ex_int_handler (void)
{
volatile unsigned int dummy;
dummy = 135;
printf("Ein Interrupt trat auf");
dummy =AT91C_BASE_PIOB->PIO_ISR;
dummy =dummy;
AT91C_BASE_AIC->AIC_IVR = 0;
AT91C_BASE_AIC->AIC_ICCR = AT91C_ID_SYS;
AT91C_BASE_AIC->AIC_EOICR = 0;
}
und
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_PIOA);
AT91C_BASE_PIOA->PIO_ODR = INTTAST;
AT91C_BASE_PIOA->PIO_PER = INTTAST;
AT91C_BASE_PIOA->PIO_SODR=INTTAST;
AT91C_BASE_AIC->AIC_IDCR=(1<<AT91C_ID_PIOA);
AT91C_BASE_AIC->AIC_SVR[AT91C_ID_PIOA]=(unsigned int)ex_int_handler ;
AT91C_BASE_AIC->AIC_SMR[AT91C_ID_PIOA]=AT91C_AIC_SRCTYPE_INT_POSITIVE_ED
GE|AT91C_AIC_PRIOR_LOWEST;
AT91C_BASE_AIC->AIC_ICCR=(1<<AT91C_ID_PIOA);
AT91C_BASE_PIOA->PIO_IER=INTTAST;
AT91C_BASE_AIC->AIC_IECR=(1<<AT91C_ID_PIOA);
aber die Zuweisung AT91C_BASE_AIC->AIC_SVR[AT91C_ID_PIOA]=(unsigned
int)ex_int_handler; scheint irgendwie den Interrupt aufzurufen (Ausgabe
"Ein Interrupt trat auf") und dann bleibt das Programm auch irgendwie im
Interrupt hängen und kommt nicht weiter in die Hauptprogrammschleife.
Alleine schaffe ich das wohl wirklich nicht und bräuchte einen Hinweis
(oder Link zu einem lauffähigen Ext-Interrupt-Sample oder einer leicht
verständlichen Doku zum Thema).
im Anhang ein Beispiel-Projekt (allerdings für iar workbench). gruss gerhard
Tja, da müßte ich meinen Chef schon überreden können, das Geld für den
Compiler auszugeben...
Das Anpassen allein schon von __ramfunc mit #define RAMFUNC
_attribute_ ((long_call, section (".ramsection"))) und Anpassen des
Linkers mit
.data : AT (_etext)
{
_data =3D . ;
KEEP(*(.vectram)) /* added by mthomas */=09
*(.data)
SORT(CONSTRUCTORS)
. =3D ALIGN(4);
*(.ramsection) /* here your ramsection will be located */
} >DATA
. =3D ALIGN(4);
klappt bei mir nicht wirklich (von den ganzen, übrigen Anpassungen für
den gcc ganz abgesehen...) :(
Aber vielleicht liest den Thread hier ja noch jemand, der mit dem gcc
einen externen Interrupt hinbekommen hat...
Weiß inzwischen zwar woran es liegt (an ethernut; brauche ich leider wegen tcpip) kann es aber auch nicht ändern, weil das ethernut und die dort veränderten Interruptregister für mich nicht mal eben in ein paar Stunden zu durchschauen sind. Ohne ethernut läuft bei mir folgendes Mini-Testprogramm jetzt:
1 | void ex_int_handler (void) |
2 | {
|
3 | volatile unsigned int dummy; |
4 | |
5 | dummy = AT91C_BASE_PIOA->PIO_ISR; |
6 | AT91C_BASE_AIC->AIC_EOICR=AT91C_BASE_TC0->TC_SR; |
7 | AT91C_BASE_AIC->AIC_ICCR=(1<<AT91C_ID_TC0); |
8 | *AT91C_AIC_EOICR=0; |
9 | AT91C_BASE_PIOB->PIO_CODR=AT91C_PIO_PB19;// LED1 hier zum Int.-Test anmachen |
10 | AT91C_BASE_AIC->AIC_EOICR = 0; |
11 | }
|
und in
1 | main(){ |
2 | ...
|
3 | AT91C_BASE_PIOA->PIO_PER=INTTAST; |
4 | AT91C_BASE_PIOA->PIO_ODR =INTTAST; |
5 | AT91C_BASE_PIOA->PIO_CODR=INTTAST; |
6 | AT91C_BASE_PIOA->PIO_PPUER=INTTAST; |
7 | AT91C_BASE_PIOA->PIO_ASR=INTTAST; |
8 | AT91C_BASE_PIOA->PIO_OWDR=INTTAST; |
9 | AT91C_BASE_AIC->AIC_SMR[AT91C_ID_PIOA]=AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE | 0; |
10 | AT91C_BASE_AIC->AIC_SVR[AT91C_ID_PIOA]=(unsigned int)ex_int_handler; |
11 | AT91C_BASE_PIOA->PIO_IFER=INTTAST; |
12 | int io_status = AT91C_BASE_PIOA->PIO_ISR; |
13 | AT91C_BASE_AIC->AIC_IECR=(1 << AT91C_ID_PIOA); |
14 | AT91C_BASE_PIOA->PIO_IER=INTTAST; |
15 | ...
|
16 | while(1){ |
17 | ... // hier LED2 blinken lassen |
18 | }
|
Hatte ein ähnl. Problem dass der Controller MANCHMAL nicht mehr aus der
ExtIrq Routine rauskam.
Lag daran, dass mein "Schalter" nur ein Draht war, welcher wohl beim
Kontaktieren manchmal nur ganz kurze Pulse lieferte, die für den AIC zu
schnell wieder weg waren um ausgewertet zu werden.
Lies sich durch eine leere Spurious IRQ ISR beheben wie im SAM7
Datenblatt unter 22.7.6 Spurious Interrupt beschrieben.
...
AT91C_BASE_AIC->AIC_SPU = (int)IRQSpuriousHandler; //Spurious
interrupt muss abgefangen werden (Spurious fliegt wenn IRQ Source nicht
mehr findbar, zb durch ganz kurze Peaks am ExtIrq)
....
void IRQSpuriousHandler(void)
{
int dummy; //status lesen um INT zu löschen
dummy = AT91C_BASE_AIC->AIC_IVR;
EndOfInterrupt();
}
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.