Forum: Compiler & IDEs Interrupts bei LPC2294 ARM Mikrocontroller


von Hammoud (Gast)


Lesenswert?

Hi,
Meine Versuche einen Timer des LPC2294 als Intervall -Timer zu
programmieren schlugen bislang fehl. Der Timer wird richtig
initialisiert und nach der vorgegebenen Zeit wird auch ein Interrupt
ausgelöst. Problem ist nur, dass die ISR des Timers nie ausgeführt
wird.
In der ISR wird lediglich die Systemuhr aktualisiert und das
Interrupt-Flag gelöscht. Die von mir definierte ISR sieht
folgendermaßen aus:

// this function is to be called when a timer interrupt is generated
void __attribute__((interrupt("IRQ"))) timerIntHandler(void);

void timerIntHandler(void)
{
     timeNow+= ####;  // #### is the time between 2 timer interrupts
     T0IR = (1<<0);   // Clear interrupt flag by writing 1 to Bit 0
     VICVectAddr = 0; // Acknowledge Interrupt
}

Die Adresse dieser Funktion wird auch in den entsprechenden
Interrupt-Vektor geschrieben:

VICVectAddr0 = (unsigned long)timerIntHandler;

Ich habe mehrmals gecheckt, ob irgend etwas bei der Initialisierung
vergessen wurde und meiner Meinung nach müsste alles richtig sein.

Ich würde mich freuen, wenn der eine oder andere einen Tipp parat hat.

PS: ARM-gcc-Toolchain

Vielen Dank
Hammoud

von Jens Altenburg (Gast)


Lesenswert?

Hallo,

interessant wäre nicht nur die ISR Routine sondern die Initialisierung
selbst. Der VIC braucht noch die dazugehörige Interruptfreigabe.
Beim LPC2138 sieht das in etwa so aus:

   VICIntSelect &= ~0x10;
   VICIntEnable  =  0x10;
   VICVectCntl0  =  0x24;  /* vectored interrupt control reg */
   VICVectAddr0  =  (unsigned long)timerIntHandler;
   TOTCR = 0;              /* stop timer */
   T0PR  = 0;              /* prescaler */
   T0MR0 = wert;           /* set match register */
   T0MCR = 1;              /* interrupt bei match */
   T0TCR = 1;              /* start timer */
   ... global interrupt enable nicht vergessen

Beim LPC2294 vorher mal im Datenblatt nachschauen.

MfG

Jens

von Zoltan (Gast)


Lesenswert?

uint32_t timetick; // globale Variable

// Timer Counter 0 Interrupt initialisieren
void init_timer (void)
{
T0MR0 = 14999; // 1mSec = 15.000-1 counts
T0MCR = 3; // Interrupt and Reset on MR0
T0TCR = 1; // Timer0 Enable
VICVectCntl0 = 0x20 | 4; // IRQ Slot0 für Timer 0 (VIC-Channel 4)
VICVectAddr0 = (uint32_t)tc0; // IRQ Slot0 auf Funktion tc0 setzen
VICIntEnable = 0x00000010; // Enable Timer0 Interrupt (Bit4=1)
}

// Timer Counter 0 Interrupt executes each 1ms @ 60 MHz CPU Clock
void tc0 (void) __irq
{
++timetick; // Interrupt-Aktion: Zeitvariable erhöhen
T0IR = 1; // Clear interrupt flag
VICVectAddr = 0; // Acknowledge Interrupt
}

von Martin (Gast)


Lesenswert?

Sieht ziemlich richtig aus.
Verwendest du den Keil?
Ich habe hier eine Initialisierungsroutine für einen LPC2138. Versuch
die mal. Die Routinen sehen ziemlich kompatibel aus. Es kann sein, dass
der Prozessor bei irgendeiner Reihenfolge ein Problem hat.

Diese Routine hat bei mir funktioniert:

  VICVectAddr1 = (unsigned long)timercomp_irq;          // set
interrupt vector in 1
  VICVectCntl1 = 0x20 | 4;   // Vic UART0
  VICIntEnable = 0x0000010;                  // Enable Timer Interrupt

  T0TCR=0x2; // Timer Reset
  T0CTCR=0x0; // Timermode
  T0MR0=119; // Vergleichsregister    // Überlauf bei 2µs
  T0MCR=3;   // IRQ-Vergleich 0, Timer=0 im Vergleichsregister 0
  T0TCR=0x1; // Timer startet





void timercomp_irq(void) __irq
{
  T0IR=0x01;
  if(flag==1)
  {
  IOCLR0=x;
  flag=2;
  }
  else
  {
  IOSET0=x;
  flag=1;
  }
VICVectAddr = 0; // Acknowledge Interrupt
}



Schreib uns, ob du es geschafft hast.

Tschüss
Martin

von Axel Stab (Gast)


Lesenswert?

Hallo,

wir haben mit dem Timer-Demo unter dem folgenden Link schnell einen
brauchbaren Timer-Interrupt hinbekommen:

http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/

Allerdings haben wir jetzt mit mehrkanaligem Match-IRQ Betrieb Probleme
(Rücksetzen der IRQ-Bits), scheint am Chip zu liegen, in den Erratas
steht auch eine ganze Menge...

Viel Erfolg!


Hier Auszüge aus unserem Code:

/* Setup the Timer Counter 0 Interrupt */
void init_timer0 (void) {
  T0PR = 5;//T0 prescaler: clk/(1+prescaler) => 1 tick = 0,1 us
  T0MR0 = 10000;                           // 1mSec = 10000 counts
  T0MR1 = 10000000;                           // 1Sec = 10 mio counts
  T0MR2 = 10000000;
  T0MCR = ( 0x01 | 0x08 | 0x40 );        // Interrupt on MR0 + MR1 +
MR2
  T0TCR = 1;                                  // Timer0 Enable
  VICVectAddr0 = (unsigned long)tc0;          // set interrupt vector
in 0
  VICVectCntl0 = 0x20 | 4;                    // use it for Timer 0
Interrupt
  VICIntEnable = 0x00000010;                  // Enable Timer0
Interrupt
  timerticks = 0;
}


void _attribute_ ((interrupt("IRQ"))) tc0 (void) {

  if ( T0IR & 0x01 ) {
    //Match Register 0: 1ms-Interrupt

    i_timerticks |= 0x04;

  T0MR0 += 10000;
    T0IR     = 0x01;                          // Clear interrupt flag
    VICVectAddr = 0;                            // Acknowledge
Interrupt
  }


}

von Joachim Klein (Gast)


Lesenswert?

Hallo,

die Zeile:

    VICVectAddr = 0;

muss ausserhalb des if body stehen, sonst wird der Interrupt Controller
nicht zurück gesetzt, außer die if Bedingung ist erfüllt.

Gruß, Joachim

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.