AT91SAM7 + uVsion3 IR-Handling

OP #1767548
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren