Hello,
Could you help to install the ST timer on the AT91Rm9200? I don't know how to setup the AIC registers correct. Maybe there are more than one big mistake.
void initialize_pit() { unsigned int flag, period, irq_id, mask, oldHandler, src_type, priority; volatile int status; void *newHandler; //period Timer0->ST_PIMR = period << 5; AT91F_ST_SetPeriodInterval(Timer0, period); //state //status = Timer0->ST_SR; //enable interrupt flag=1; Timer0->ST_IER = flag; AT91F_ST_EnableIt( Timer0, flag); //enable PMC AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC, 1 << AT91C_ID_IRQ0); //config AIC irq_id = 0; oldHandler = pAic->AIC_SVR[irq_id]; mask = 0x1 << irq_id; pAic->AIC_IDCR = mask ; pAic->AIC_SVR[irq_id] = (unsigned int) newHandler ; //* Store the Source Mode Register pAic->AIC_SMR[irq_id] = src_type | priority ; AT91F_AIC_ConfigureIt(pAic, irq_id, priority, src_type, newHandler); //enable AIC AT91F_AIC_EnableIt(pAic, 1); }
I hope somebody could help me with this problem...
best regards johannes
thanks...
Timer0 = 10000; //Periode für den Timer period = 5; AT91F_ST_SetPeriodInterval(Timer0, period); // Interrupt enablen - gesetzt wenn ST_IER=1 flag=1; AT91F_ST_EnableIt( Timer0, flag); //config AIC irq_id = 1; mask = 0x1 << irq_id; pAic->AIC_IDCR = mask ; pAic->AIC_SVR[irq_id] = (unsigned int) newHandler ; //* Store the Source Mode Register pAic->AIC_SMR[irq_id] = src_type | priority ; AT91F_AIC_ConfigureIt(pAic, irq_id, priority, src_type, newHandler); //enable AIC AT91F_AIC_EnableIt(pAic, irq_id);
Could you give me a small example for the newHandler?
Timer0 = AT91C_BASE_ST;
ok I only have to use such a function, which works,when the interrupt occurs - right?
void ST_interrupt(void) { AT91F_PIO_SetOutput(AT91C_BASE_PIOB, AT91B_LED1); AT91F_PIO_ClearOutput(AT91C_BASE_PIOB, AT91B_LED1); }
I'm afraid it is almost, but not quite that simple.
What an interrupt handler needs to do is explained in the device datasheet (I hope you have a copy of it), in the chapter about the AIC. An interrupt handler must, for example, indicate to the AIC that it has finished processing the current interrupt. The exact way to this (you guessed it) is described in the datasheet.
It is generally a very good idea to thoroughly read the chapters in the datasheet about the peripherals and features you are going to use. Some things aren't quite intuitive. And have a copy of the datasheet handy in order to read through the chapters again while programming the device.
thank for your answer - now this is my current code... could you tell me, what's wrong?
initialization of the pit timer
void initialize_pit() { unsigned int flag, period, irq_id, mask, src_type, priority; volatile int status; Timer0 = AT91C_BASE_ST; /* Base Address for the ST Timer */ //period for the pit timer period = 500; AT91F_ST_SetPeriodInterval(Timer0, period); // enable interrupts flag=1; AT91F_ST_EnableIt( Timer0, flag); //config AIC irq_id = 1; AT91F_AIC_ConfigureIt(pAic, irq_id, priority, src_type, ST_interrupt); //enable AIC AT91F_AIC_EnableIt(pAic, irq_id); }
pit timer interrupt handler
void ST_interrupt(void) { AT91C_BASE_AIC->AIC_IDCR = 0xFFFFFFFF; //disable all interrupts AT91C_BASE_AIC->AIC_ICCR = 0x00000001; // clear pit interrupt AT91F_PIO_SetOutput(AT91C_BASE_PIOC, AT91C_PIO_PC1); AT91F_PIO_ClearOutput(AT91C_BASE_PIOC, AT91C_PIO_PC1); AT91C_BASE_AIC->AIC_IECR = 0x00000001; // interrupt enable command AT91C_BASE_AIC->AIC_EOICR = 0x0; // end of interrupt }
main method
void timer() { unsigned int tick; // timer unsigned int pit_interval; // intveral pit timer initialize_pit(); *(AT91C_ST_PIMR) = pit_interval; // value for the pit timer tick = *(AT91C_ST_CRTR); //variable tick has the current value of the PIT timer while(1) { while (tick == *(AT91C_ST_CRTR)); tick = *(AT91C_ST_CRTR); } }
AT91F_AIC_ConfigureIt(pAic, irq_id, priority, src_type, ST_interrupt);
src_type and priority don't have any values assigned to them !
I'm pretty sure that the compiler is issuing warnings about variables being used before having been assigned a value here. Compiler warnings are there for a reason and usually indicate that there is a problem with your code.
void ST_interrupt(void) { AT91C_BASE_AIC->AIC_IDCR = 0xFFFFFFFF; //disable all interrupts AT91C_BASE_AIC->AIC_ICCR = 0x00000001;
This is unnecessary and useless at best. Since you probably want the ST interrupt to be level-sensitive, the AIC_ICCR will have no effect. The interrupt will be cleared by reading ST_SR instead.
You still have uninitialized variables. Have you turned on all compiler warnings, and then made sure to clean out any warnings you get?
Another thing:
while(1) { while (tick == *(AT91C_ST_CRTR)); tick = *(AT91C_ST_CRTR); }
Notice 1: The semicolon at the end of the while() line menas that you have a while statement with an empty body - the indented second line isn't part of the while loop...
Notice 2: Is your loop intended as a delay? If all you want is the tick variable to be updated when the timer steps, you should let the interrupt service routine (ISR) assign a new value to tick on each interrupt. But then again - if the specific register in the timer is tha value you need, there is no reason to make a copy of it to a variable.
ok - now I get no warnings or errors... but the call for the ST_interrupt routine doesn't work...
void timer() { unsigned int pit_interval; // intveral pit timer initialize_usart1(); initialize_pit(); *(AT91C_ST_PIMR) = pit_interval; // value for the pit timer while(1) { //do nothing } }
The ST_SR register tell's me only if there has been a interrupt since if red it the last time..
irq_id = 1; priority = 1; src_type = 0x01; AT91F_AIC_ConfigureIt(pAic, irq_id, priority, src_type, ST_interrupt);
that is my configuration for the AIC.
No - the ST_SR is the direct cause for the ST interrupt line being asserted. There's a "hard-wired" connection on the chip that says "(ST_SR AND ST_IMR) -> Status of the ST interrupt line.
You can find #defined values for the source type and the priority in AT91RM9200_inc.h.
0x01 for the source type isn't even a valid value, since the source type field consists of bits 5 and 6 in the AIC_SMR.
I set the value for the src_type to 1.
but what's the reason, that my ST_interrupt(void) method never run?
Is the only solution to say if(ST_SR == 1) go to ST_interrupt(void) ?
johannes
AT91F_AIC_EnableIt(pAic, irq_id);
Where's the definition of pAic, and where does it get a value assigned to it ?
The src_type field consists of bits 5 and 6 of the AIC_SMRx. So valid values for src_type are 0x00, 0x20, 0x40 and 0x60.
Something's still wrong with your code.
No, that would just mess up things completely. The solution is getting the AIC and the ST programmed correctly. Maybe you need to recapitulate the appropriate chapters in the datasheet instead of trying to depend on others trying poke through code snippets and find out what exactly is wrong with your code. Maybe having another look inside a C textbook might be a good idea, too - might be a good idea judging from the use of uninitialized local variables.
AT91PS_AIC pAic = AT91C_BASE_AIC;
that's the definition for AIC
__inline unsigned int AT91F_AIC_ConfigureIt ( AT91PS_AIC pAic, // \arg pointer to the AIC registers unsigned int irq_id, // \arg interrupt number to initialize unsigned int priority, // \arg priority to give to the interrupt unsigned int src_type, // \arg activation and sense of activation void (*newHandler) (void) ) // \arg address of the interrupt handler { unsigned int oldHandler; unsigned int mask ; oldHandler = pAic->AIC_SVR[irq_id]; mask = 0x1 << irq_id ; //* Disable the interrupt on the interrupt controller pAic->AIC_IDCR = mask ; //* Save the interrupt handler routine pointer and the interrupt priority pAic->AIC_SVR[irq_id] = (unsigned int) newHandler ; //* Store the Source Mode Register pAic->AIC_SMR[irq_id] = src_type | priority ; //* Clear the interrupt on the interrupt controller pAic->AIC_ICCR = mask ; return oldHandler; }
irq_id = 1; priority = 1; src_type = 1; AT91F_AIC_ConfigureIt(pAic, irq_id, priority, src_type, ST_interrupt);
What do you think happen when you do:
priority = 1; src_type = 0x01;
and then:
AT91F_AIC_ConfigureIt(pAic, irq_id, priority,src_type, ST_interrupt);
Think about the line:
pAic->AIC_SMR[irq_id] = src_type | priority ;
With src_type = 1 and priority = 1, what use do you think that or operation makes? Are you spending any time trying to understand the answers you receive? What does the data sheet say about initializing the AIC_SMR register with the value 1?
Also, you may want to use the __irq keyword for the interrupt service routine (or use some other way to make sure the the interrupt service routine is compiled in ARM mode and not in THUMB mode. I do not know what setting uVision uses as a default. Interrupt service routines must always be in ARM mode, however).
The priority level can be between 0 (lowest) and 7 (highest).
so I select the value 1 for the priority - I don't see any disadvantages about it.
SCR_TYPE 0 0 high-level sensitive 0 1 positive edge-triggerd (is this not right to use this mode)?
0 1 are the bits 5 and 6 so it's 0x0000 0001 or not?
Or is this configuration false for the ST timer?