Hello, i have a problem. There are allways difficulties in programms with IRQ und FIQ. So i wrote this code to investigate where the problem is.
I use two Timer, Timer0 and Timer1 to generate interrupts.
Timer0 generates a periodic normal IRQ every 2000 cycles.
Inside the IRQ routine there is a for(i=80;i;i--) loop with port toggling. So i can watch on my 2-channel storage oszilloscope when this toggling is interrupted by the fast interrupt.
Timer1 generates a periodic fast interrupt FIQ every 1000 cycles.
I interprete the microcontroller datasheet that FIQ has the higher pririty and can interrupt IRQ. Am i right???
Unfortunaltely i can not post a oszilloscope screenshot in this forum.
So i try to describe the result: On channel 1 there is a train of 40 pulses. Duration is about 33us. You can see, after pulse 31 there a little gap. This is the moment FIQ is started and returns to IRQ. Then the left 9 pulses are there. Than there is a low level for about 17us. This looks all the way i expected things to take place.
On channel 2 there is a port toggling every 25us. Sometimes the port toggling is replaced by a single needle pulse.
Whats going on there. Unfortunaltely i have no idea where the problem occurs. I expanded FIQ-stack-size from 4 to 80. (startup.s)
//************************************************************************* #include <ADuC7026.h> //************************************************************************* void Port_init(void); void PLL_init(void); void Timer_init(void); void interrupt_init(void); //************************************************************************* int main (void) { Port_init(); PLL_init(); Timer_init(); interrupt_init(); while(1) { GP4DAT ^= 0x00040000; // P4.2 toggling => program is in main loop } } //************************************************************************* void IRQ_Handler()__irq __ram // Timer 0 => Interrupt { unsigned int i; T0CLRI = 0; for(i=80;i;i--) GP4DAT ^= 0x00010000; // P4.0 shows's Interrupt } //************************************************************************* void FIQ_Handler()__fiq __ram // Timer 1 => Fast Interrupt { T1CLRI = 0; GP4DAT ^= 0x00020000; // P4.1 show's Fast Interrupt } //************************************************************************* void interrupt_init(void) { IRQEN = RTOS_TIMER_BIT; // Timer 0 => Interrupt FIQEN = GP_TIMER_BIT; // Timer 1 => Fast Interrupt } //************************************************************************* void Timer_init(void) { T0LD = 2000 - 1; // Timer 0 => periodic Interrupt 2000 cycles T1LD = 1000 - 1; // Timer 1 => periodic Fast Interrupt 1000 cycles T0CON = 0xC0; // Enabled,Periodic,CLK/1 T1CON = 0xC0; // Enabled,Periodic,Binary and CLK/1 } //************************************************************************* void PLL_init(void) { PLLKEY1 = 0xAA; PLLCON = 0x01; // clear Bit5 OSEL => External 32.768kHz crystal PLLKEY2 = 0x55; while(~IRQSIG & PLL_LOCK_BIT){} // waiting for PLL lock } //************************************************************************* void Port_init(void) { GP4DAT |= 0x01000000; // P4.0 is output GP4DAT |= 0x02000000; // P4.1 is output GP4DAT |= 0x04000000; // P4.2 is output } //*************************************************************************
Correct. The Set/Cler registers are not a way to get atomic operation.
It is a way to be able to isolate arbitrary sets of bits on a port, and have different tasks/ISR own different bits and work on them without having their changes overwritten by another task/ISR.
In your case, you don't need any atomic updates - you just need to make sure that one task/ISR doesn't overwrite bits owned by another task/ISR. You will get task isolation without the additional burden of creating critical sections, i.e. with a minimum of overhead.
If you look at Georg Bunter text a bit more closely, you'll notice that he says "so it is not necessary to have an atomic toggle instruction." There is no claim that you will get an atomic access - just that this is a good workaround to remove your need of atomic access.
Fair enough - I misinterpreted his text as claiming that his code was a viable alternative to an atomic toggle instruction !
In the specific case under discussion, this is a more efficient solution. However, "specific cases" often have a nasty habit of subsequently being used where they're not appropriate :-)
David.