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.