Forum: Mikrocontroller und Digitale Elektronik Externer Interrupt auf AT91SAM7X-EK mit Eclipse


You were forwarded to this site from EmbDev.net. Back to EmbDev.net
von proc (Gast)


Lesenswert?

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...

von proc (Gast)


Lesenswert?

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).

von gerhard (Gast)


Angehängte Dateien:

Lesenswert?

im Anhang ein Beispiel-Projekt (allerdings für iar workbench).

gruss
gerhard

von proc (Gast)


Lesenswert?

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...

von Proc P. (proc)


Lesenswert?

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
  }

von juhu (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.