mikrocontroller.net

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


Autor: proc (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: proc (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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).

Autor: gerhard (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
im Anhang ein Beispiel-Projekt (allerdings für iar workbench).

gruss
gerhard

Autor: proc (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Proc Proc (proc)
Datum:

Bewertung
0 lesenswert
nicht 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:
void ex_int_handler (void) 
{ 
  volatile unsigned int dummy;  

  dummy = AT91C_BASE_PIOA->PIO_ISR; 
  AT91C_BASE_AIC->AIC_EOICR=AT91C_BASE_TC0->TC_SR;         
  AT91C_BASE_AIC->AIC_ICCR=(1<<AT91C_ID_TC0);              
  *AT91C_AIC_EOICR=0;                                      
  AT91C_BASE_PIOB->PIO_CODR=AT91C_PIO_PB19;// LED1 hier zum Int.-Test anmachen
  AT91C_BASE_AIC->AIC_EOICR = 0;
}  
und in
main(){
 ...
  AT91C_BASE_PIOA->PIO_PER=INTTAST;    
  AT91C_BASE_PIOA->PIO_ODR =INTTAST; 
  AT91C_BASE_PIOA->PIO_CODR=INTTAST; 
  AT91C_BASE_PIOA->PIO_PPUER=INTTAST; 
  AT91C_BASE_PIOA->PIO_ASR=INTTAST; 
  AT91C_BASE_PIOA->PIO_OWDR=INTTAST; 
  AT91C_BASE_AIC->AIC_SMR[AT91C_ID_PIOA]=AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE | 0; 
  AT91C_BASE_AIC->AIC_SVR[AT91C_ID_PIOA]=(unsigned int)ex_int_handler; 
  AT91C_BASE_PIOA->PIO_IFER=INTTAST; 
  int io_status = AT91C_BASE_PIOA->PIO_ISR; 
  AT91C_BASE_AIC->AIC_IECR=(1 << AT91C_ID_PIOA); 
  AT91C_BASE_PIOA->PIO_IER=INTTAST;   
 ...
  while(1){
   ... // hier LED2 blinken lassen
  }


Autor: juhu (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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();
   }

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.