Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Altera_Forum
Honored Contributor I
875 Views

Fixed timer interrupt: Main code flips output pin twice?

Hi all, 

 

 

I have a periodic fixed timer (100ms) interrupt that seems to work fine but the main code is flipping the output pin twice. I basically want to show a pattern of LED (in my BeMicro MAX10) like this every second, low means LED on, there are 8 LEDs: 

 

 

11100111 one second delay and next 

11011011 one second delay and next 

10111101 one second delay and next 

01111110 one second delay and go to first 

 

 

I'm using the modulus operator (%) to change the pattern but it triggers (mostly) twice. Like: 

 

 

11100111 one second delay and next 

11011011 no delay 

10111101 no delay 

01111110 one second delay and go to first 

 

 

 

 

 

 

The picture attached shows when the isr executes by toggling an output pin (yellow trace). The blue trace is when the code inside the if(ticks % 10==0 && flag==1) executes. I'm pretty new at FPGAs and Nios. BTW I'm using "Reduced device drivers" and "Small C library" for the BSP. 

 

 

What Am I missing? 

 

 

 

 

 

--- Quote Start ---  

 

//=========== Global variables ==================================== 

volatile unsigned int ticks=0; 

volatile unsigned int flag=0; 

volatile unsigned char port0Val=0; 

 

 

//=========== main() Function ====================================== 

 

 

int main() 

 

 

char led_patern[4]={0b11100111,0b11011011,0b10111101,0b01111110}; 

int i=1; 

 

 

alt_ic_isr_register(TIMER_0_IRQ_INTERRUPT_CONTROLLER_ID, TIMER_0_IRQ, timer_isr, 0, 0); 

 

 

 

 

//timer registers are 16-bits wide 

IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER_0_BASE, 1); //interrupt enable 

 

 

// PORT0 is 5 bits wide 

// PORT0 bit 0 = PIN_B1, BeMicro J5-2 

// PORT0 bit 1 = PIN_A2, BeMicro J5-4 

// PORT0 bit 2 = PIN_A3, BeMicro J5-5 

// PORT0 bit 3 = PIN_A4, BeMicro J5-6 

// PORT0 bit 4 = PIN_A5, BeMicro J5-10 

IOWR(PORT0_BASE,5,0b11111); //5=outclear - ALL LOW 

//IOWR(PORT0_BASE,4,0b11111); //4=outset - ALL HIGH 

 

 

while(1) 

 

if(ticks % 10==0 && flag==1) 

 

 

port0Val = IORD(PORT0_BASE,0); //toggle port0 pin 2 -----> BLUE TRACE <-------- 

if((port0Val & 0b00100)==0b00100) 

IOWR(PORT0_BASE,5,0b00100); //5=outclear 

else 

IOWR(PORT0_BASE,4,0b00100); //4=outset 

 

 

 

 

IOWR(LEDS_BASE,0,*(led_patern+i)); //a low value turns LED on 

 

 

i++; 

if(i>3) 

i=0; 

 

 

flag=0; 

 

 

 

 

 

return 0; 

 

 

 

 

 

 

//============== Interrupt Service Function =========================== 

void timer_isr() 

 

 

port0Val = IORD(PORT0_BASE,0); //toggle port0 pin 0 -----> YELLOW TRACE <-------- 

if((port0Val & 0b00001)==1) 

IOWR(PORT0_BASE,5,0b00001); //5=outclear register, 0x01=0b00001 

else 

IOWR(PORT0_BASE,4,0b00001); //4=outset register, 0x01=0b00001 

 

 

ticks++; 

 

 

flag=1; 

 

 

IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_0_BASE, 0); // clear TimeOut flag 

 

 

 

 

 

--- Quote End ---  

0 Kudos
1 Reply
Altera_Forum
Honored Contributor I
25 Views

The flaw is with the condition if(ticks % 10==0 && flag==1)  

Infact your code basically loops on this instruction. So, you have a rough 50% probabilty that the irq triggers between the two ANDed conditions. 

When you find both conditions true you toggle the blue trace. At this point tick%10==0 stays true until the next irq; but if irq triggers just after you evaluated tick and before you evaluate flag, at the end you would again have the whole if conditional true and would toggle the output one more time. 

To solve the problem, put the tick%10 condition inside the isr and set flag according to it.
Reply