www.mikrocontroller.net

Forum: Mikrocontroller und Elektronik AT91-SAM7EX256 External Interrupt

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

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: 11.04.2008 13:54

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: 14.04.2008 11:08

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: 08.05.2008 10:37

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: 09.05.2008 14:28

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 Email-Adresse ist freiwillig. Wenn Sie automatisch per Email über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Suchfunktion und Betreffsuche benutzen - vielleicht gibt es schon einen ähnlichen Beitrag
  • Aussagekräftigen Betreff wählen
  • Im Betreff angeben um welchen Controllertyp es geht (AVR, PIC, ...)
  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
  • JPEG-Dateien (.jpg) nur für Fotos verwenden, Schaltpläne, Screenshots usw. als PNG oder GIF anhängen

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [pre]vorformatierter Text (z.B. Code in anderen Sprachen)[/pre]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel






webmaster@mikrocontroller.netImpressumWerbung auf Mikrocontroller.net