Forum: Mikrocontroller und Digitale Elektronik AT91SAM7 + uVsion3 IR-Handling


von Tom W. (nericoh)


Lesenswert?

Hallo zusammen,

wie immer gilt: ich hab das Forum gründlich nach passenden Threads 
durchsucht und keinen finden können, der sich genau mit meiner 
Problematik befasst. Falls ich was übersehen habe, bitte ich um kurzen 
Hinweis !

Problemstellung:
ich möchte mit dem PIT des AT91SAM7 unter uVision3 zyklische Interrupts 
auslösen und verarbeiten. Folgendermaßen bin ich vorgegangen:
1
//init of Advanced Interrupt Controller
2
*AT91C_AIC_IECR  = 0x00000002;    //enable PIT IR
3
AT91C_AIC_SMR[1] = 0x00000007;    //set priority of PIT IR
4
AT91C_AIC_SVR[1] = (AT91_REG) ISR_periph; //set adress to branch to if peripheral IR occurs
5
6
//init of  Periodic Internal Timer
7
*AT91C_PITC_PIMR   = ( 0x000FFFFF & ( TIMER_PARA_MicroCycle * (TIMER_PARA_SysClock / (16 * 1000) ) ) ) ;  //set cycle of timer
8
*AT91C_PITC_PIMR   |= 0x03000000;  //enable the timer and the corresponding IR
9
10
__irq void ISR_periph (void)   //executed every time a peripheral IR occurs
11
{       
12
  if ( *AT91C_PITC_PISR )          //IR caused by Periodic Interval Timer ?  
13
  {           
14
    count++;
15
16
    if (count >= 2)    
17
    {  
18
      SET_PWR_LED(ON);            
19
    }   
20
21
    *AT91C_AIC_ICCR    = 0x00000002;  //clear the IR-Bit
22
    tempvar   = *AT91C_PITC_PIVR;    //reading PIVR resets the timer ir
23
24
  }
25
26
  *AT91C_AIC_EOICR   = 0xFFFFFFFF;   //end of IR
27
}

Soweit funktioniert das auch: die Power-LED geht an, deshalb weiß ich, 
dass die ISR mehr als nur einmal angesprungen wird.
Jetzt kommt das eigentliche Problem: laut Datasheet des Controllers soll 
in der ISR als erstes das "Interrupt Vector Register" (AIC_IVR) gelesen 
werden: "The read of AIC_IVR is the entry point of the interrupt 
handling which allows the AIC to consider that the interrupt has been 
taken into account by the software." Zwar funktioniert mein IR-Managment 
auch ohne diesen Lesezugriff. Allerdings möchte ich IRs auch 
verschachteln können (s. Beitrag "AT91SAM7 -> Interrupts verschachteln (nested IRs)"), 
was mir bisher nicht gelingt, vermutlich u.a. weil ich das IVR nicht 
lese. Daher nun die ISR mit IVR-Zugriff:
1
__irq void ISR_periph (void)   //executed every time a peripheral IR occurs
2
{       
3
  tempvar = *AT91C_AIC_IVR;    //reading IVR as entry point of ISR
4
5
  if ( *AT91C_PITC_PISR )          //IR caused by Periodic Interval Timer ?  
6
  {           
7
    count++;
8
9
    if (count >= 2)    
10
    {  
11
      SET_PWR_LED(ON);            
12
    }   
13
14
    *AT91C_AIC_ICCR    = 0x00000002;  //clear the IR-Bit
15
    tempvar   = *AT91C_PITC_PIVR;    //reading PIVR resets the timer ir
16
17
  }
18
19
  *AT91C_AIC_EOICR   = 0xFFFFFFFF;   //end of IR
20
}

Ergebnis: die ISR wird nur noch ein einziges Mal angesprungen. Das 
stelle ich dadurch fest, dass da die LED nun nur noch angeht, wenn ich 
"SET_PWR_LED(ON);" vor der if-Bedingung ausführe.

Hat irgendjemand einen Tip für mich, wodran es hapert? Spielt das 
"__irq" möglicherweise eine Rolle? Habe das in anderen Beispielen so 
bisher nie gesehen. Lasse ich das weg, gelingt mir aber auch ohne den 
IVR-Zugriff kein zyklisches Aufrufen der ISR.

Gruß,
Tom

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.