www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik AT91-SAM7EX256 External Interrupt


Autor: Kalle Noname (Firma: FH-Wolfenbuettel) (pixelkalle)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin,

ich versuche gerade meinen AT91-Sam7EX256 dazu zu bringen eine bestimmte 
Funktion auszuführen, wenn an einem Pin (PA29) vom PioB ein 
Flankenwechsel von Low auf High bzw. umgekehrt eintritt.
Da der Flankenwechsel evtl. sehr schnell auftritt würde ich das gerne 
mit dem FIQ machen, versuche mich aber erstmal am normalen IRQ. Nur 
leider klappts net. Der Prozi bleibt in der ISR hängen und kommt nicht 
wieder raus. Habe schon den ganzen Vormittag nach HowTo's oder 
Code-Exampeln gesucht, welche aber alle nur über den Timer Counter reden 
- bring mir aber nix. Ich brauch ja den Externen Interrupt. Mein Code 
sieht gerade so aus:
void initISR(void){
*AT91C_PMC_PCER = (1 << AT91C_ID_PIOA) |  /* Enable Clock for PIO    */
      (1 << AT91C_ID_IRQ0);   /* Enable Clock for IRQ */
  
//First disable IRQ for PIOA
AT91C_BASE_AIC->AIC_IDCR = 1 << AT91C_ID_PIOA;
//Save interrupt handler routine vector
AT91C_BASE_AIC->AIC_SVR[AT91C_ID_PIOA] = (unsigned int)ISR_Test;
  
  
//Store in Source Mode Register, set priority
AT91C_BASE_AIC->AIC_SMR[AT91C_ID_PIOA] = AT91C_AIC_SRCTYPE_POSITIVE_EDGE | AT91C_AIC_PRIOR_HIGHEST;
  
//Enable den Interrupt für Pin29 
AT91C_BASE_PIOA->PIO_IER = (AT91C_PIO_PA29);
  
//Re-enable the interrupt
AT91C_BASE_AIC->AIC_IECR = (1 << AT91C_ID_PIOA);

}

Die Aufgerufene Funktion ISR_Test() enthält lediglich eine Debug ausgabe 
für ein FTDI Kabel (bisher). Die Funktion wird aufgerufen sobald die 
initISR(); Funktion aufgerufen wird - allerdings nur einmal. Also nicht 
wiederholt.

Fehlt mir in der ISR sowas wie eine Rücksprungadresse? Register Sichern? 
Macht der ARM das nicht selbst? Ich übernehm jetzt mal keine Garantie 
das alles was da oben steht auch wichtig ist - eigentlich bin ich ja 
mehr HighLevel...

Vielleicht hat ja jemand von euch ein Codebeispiel für eine ISR mit 
externem Interrupt (also ein von einem PIN)

Regards,

Kalle

Autor: embedded-os (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
schau mal diesen SAM7... code an (läuft auf S.., XC.. & SE..) - 
vielleicht hilft er dir, auch wenn die org. Register-definition nicht 
verwendet wird.

INIT
-----
    AT91S_PIO_PER        = AT91S_SPI_CD_pin;      // enable GPIO of CD
    AT91S_PIO_ODR        = AT91S_SPI_CD_pin;      // output disable CD
    AT91S_PIO_OWDR       = AT91S_SPI_CD_pin;      // write disable  CD
    AT91S_PIO_PUER       = AT91S_SPI_CD_pin;      // pullup enable  CD
    AT91S_PMC_PCER       = (1 << AT91S_ID_PIO);   // enable clock on 
PIO-interface A for reading

    AT91S_AIC_IDCR       = (1 << AT91S_ID_PIO);   // disable the 
interrupt on the interrupt controller
    AT91S_PIO_IFER       = AT91S_SPI_CD_pin;
    AT91S_PIO_IER        = AT91S_SPI_CD_pin;
    AT91S_PIO_IMR        = AT91S_SPI_CD_pin;
    AT91S_AIC_SVR->s[AT91S_ID_PIO] = (U32)(FFSPort_MMC_ISR);// Save the 
interrupt handler routine pointer and the interrupt priority
    AT91S_AIC_SMR->s[AT91S_ID_PIO] = 
AT91S_AIC_SRCTYPE_INT_HIGHLEVEL_SENSITIVE | PIOPort_INT_PRIO;   // Store 
the Source Mode Register
    AT91S_AIC_ICCR       = (1 << AT91S_ID_PIO);   // Clear the interrupt 
on the interrupt controller
    AT91S_AIC_IECR       = (1 << AT91S_ID_PIO);   // Enable the 
interrupt on the interrupt controller


ISR
------

void FFSPort_MMC_ISR(void)
{
    if(AT91S_PIO_ISR & AT91S_SPI_CD_pin) {
        if(AT91S_PIO_PDSR & AT91S_SPI_CD_pin)     // card-lost or 
card-inserted
            FFSPort_MMC_CDi = 1;                  // remember a 
lost-card interrupt
    }
#ifndef _IAR_SYSTEMS_ICC_
    AT91S_AIC_EOICR = 0;                          // End-of-Interrupt
#endif
}

Autor: Kalle Noname (Firma: FH-Wolfenbuettel) (pixelkalle)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hiho.

Danke. Ich war schon ein wenig weitergekommen. Aber über ein Problem bin 
ich noch nicht weggekommen: Selbst wenn ich die "initISR" Funktion 
wieder aufrufe, wird der Interrupt nur einmal ausgeführt - also um 
nochmal in die ISR zu springen muss ich die CPU resetten.

Was muss ich wo wieder auf null drehen damit der Interrupt wieder 
freigeschaltet ist?

MFG

Kalle

Autor: proc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe ein ähnliches Problem (siehe 
Beitrag "Externer Interrupt auf AT91SAM7X-EK mit Eclipse" )

Bei mir wird der Interrupt zur Zeit offenbar einmal mit initISR() 
aufgerufen und verbleibt dann darin ohne je in's Hauptprogramm zu 
gelangen.

Irgendwo im Internet muß es doch ein Beispiel für einen externen 
Interrupt geben oder hier jemanden, der sowas schon mal gemacht hat!?
(Oder wenigstens ein Tutorial außer dem Datenblatt, das aufzeigt, welche 
Register man alle wie setzen muß) !!??



P.S. Am Ende der ISR soll wohl AIC_EOICR gecleart werden um aus dem IR 
wieder herauszukommen (aber was noch?):

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;/*  Interrupt Ack*/
  AT91C_BASE_AIC->AIC_ICCR  = (1 << AT91C_ID_TC0);/*  Interrupt Ack*/
  *AT91C_AIC_EOICR = 0;/* End of Interrupt*/ //bzw.:
  AT91C_BASE_AIC->AIC_EOICR = 0;
}

Autor: Proc Proc (proc)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Weiß inzwischen woran es liegt (an ethernut; brauche ich leider wegen 
tcpip) kann es aber auch nicht "reparieren".

Ohne ethernut läuft bei mir folgendes Testprogramm:
void ex_int_handler (void) 
{ 
  volatile unsigned int ulDummy;    
  AT91C_BASE_AIC->AIC_IDCR = 0xFFFFFFFF; 
  AT91C_BASE_AIC->AIC_ICCR = 0x04000000; 
  AT91C_BASE_PIOB->PIO_CODR=AT91C_PIO_PB19;  // LED1 im Interrupt zum Test anmachen
  asm("mrs r7,CPSR"); 
  asm("bic r7,r7,#0x80");
  asm("msr CPSR,r7"); 
  AT91C_BASE_AIC->AIC_IECR = 0x04000000; 
  AT91C_BASE_AIC->AIC_IVR = 0x0;
  AT91C_BASE_AIC->AIC_EOICR = 0x0;
  ulDummy = AT91C_BASE_PITC->PITC_PIVR;
  AT91C_BASE_AIC->AIC_EOICR = ulDummy;

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


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.