Nios® II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
12475 Discussions

endless loop in stock interrupt handler

Honored Contributor II

Hi people, 


a bit of information about my system first: 

- terasIC DE2-115 evaluation board with Cyclone IVE FPGA 

- Nios II/s CPU 

- also part of CPU block: SDRAM Controller, PIO, SysID, 2x Interval Timer, UART 

- QuartusII 12.0 sp1 community edition 

- no RTOS, just the altera BSP 

please let me know if you need more information which could be useful 


here is my problem: 

my program only executes the first few lines of my main function and loses itself in the interrupt handler afterwards. 

detailed description: 

The program starts running and a few timer interrupts occur and are handled successfully (Timer IRQ is 2, which corresponds to the value of 4 in the pending interrupt register), i.e. "alt_irq_handler" in alt_irq_handler.c is called and returns. After a few more handled interrupts, the alt_interrupt_handler routine is called again, but the pending interrupt register has the value 0 (which does not correspond to any IRQ?) and keeps looping in that interrupt routine forever -> program never returns to main again and is stuck 


A quick and dirty fix for this problem is to check for "pending register == 0" in the interrupt routine. This fix let's me execute my program, but actually I want to know where these interrupts come from and how to stop them... additionally my fix requires modification of BSP files, which is not what I want to do. 


looking forward to your comments! 

0 Kudos
7 Replies
Honored Contributor II

the best way is to look for the interrupt control registers and set values to disable all interrupts so you can be sure only your main program is running.

Honored Contributor II

thank you jacklsw86 for your hint! 


in general I have to use interrupts in my code, but here are my observations first: 


- when I disable all interrupts (via the PIE bit in the ctl0 register), my program executes 

- when I mask IRQ 2 via the ctl3 register, my program executes 

- when I check for pending==0 in the interrupt handler, my program executes 


IRQ2 is assigned to one of my timers. The timer creates interrupts via IRQ2 and as such, the pending register has to hold the value 4. This happens a few times and the interrupt handler finishes its execution as expected. 

But after a while (< 1s), the interrupt handler is called again and pending register holds the value 0 (this only happens, if IRQ2 is unmasked). 


How can a value of 0 be possible for the pending register? Why does disabling the timer IRQ solve my problem (as it executes fine a few times with pending set to 4)?
Honored Contributor II

What's the timer period?  

If you have a fast irq rate and a long interrupt handler, the irq could retrigger just after the previous isr has completed. 

Do you mind posting your code?
Honored Contributor II

I have two timers: 

- the timer with IRQ2 has a 1ms period (the only interrupt I see came from this timer) 

- the timer with IRQ3 also has a 1ms period (surprisingly enough, I never saw this timer trigger an interrupt?) 



the IRQ2-timer is also set as the sys_clk_timer in the altera BSP editor 


the interrupt handler I use in the moment, is the stock interrupt handler provided by the altera BSP: 

- alt_irq_handler() in alt_irq_handler.c  

here a shortened snippet from alt_irq_handler: 

active = alt_irq_pending (); do { i = 0; mask = 1; do { if (active & mask) { alt_irq.handler(alt_irq.context); break; } mask <<= 1; i++; } while (1); active = alt_irq_pending (); } while (active); ALT_OS_INT_EXIT(); the called handler for this particular IRQ is alt_avalon_timer_sc_irq (void* base) in alt_avalon_timer_sc.c 

shortened snippet of the code: 


IOWR_ALTERA_AVALON_TIMER_STATUS (base, 0); IORD_ALTERA_AVALON_TIMER_CONTROL (base); ALT_LOG_SYS_CLK_HEARTBEAT(); cpu_sr = alt_irq_disable_all(); alt_tick (); alt_irq_enable_all(cpu_sr);  

for the time being, my main() function does nothing else than controlling the blinking of an LED
Honored Contributor II

It seems like this problem is related to the FreeRTOS operating system I am using. 


This is my code: 




/* Standard includes. */ # include <stddef.h> # include <stdio.h> # include <string.h> /* Scheduler includes. */ # include "FreeRTOS.h" # include "task.h" # include "queue.h" /* NiosII includes. */ # include "system.h" # include "altera_avalon_pio_regs.h" int main() { unsigned int i = 200; unsigned int j = 0; unsigned char led=0x01; portBASE_TYPE res; printf("hello world!\n"); led =0xff; IOWR(LED_PIO_BASE,0,led); i=50000; while(i--); res = xTaskCreate( call_back1, ( signed char * ) "Task1", configMINIMAL_STACK_SIZE, NULL, 1, NULL ); if ( res != pdPASS ) printf("erro,fail to create task:%d\n", res); else printf("success to create task\n"); xTaskCreate( call_back2, ( signed char * ) "Task2", configMINIMAL_STACK_SIZE, NULL, 2, NULL ); led =0xaa; IOWR(LED_PIO_BASE,0,led); printf("start schedule\n"); vTaskStartScheduler(); while(1); } void call_back1(void* param) { for(;;) { IOWR(LED_PIO_BASE,0,0x0f); printf("run task1\n"); vTaskDelay(2000); } } void call_back2(void* param) { for(;;) { IOWR(LED_PIO_BASE,0,0xf0); printf("run task2\n"); vTaskDelay(1000); } }
Honored Contributor II

I am using altera software v12.0 sp1 and had an issue compiling the freeRTOS port for altera v12.0 first. 

Had to enable ALT_LEGACY_INTERRUPT_API_PRESENT to make it compilable. 


As my problem seems to be interrupt related, I rethaught my step and ported the Nios2-port of FreeRTOS to the new ALT_ENHANCED_INTERRUPT_API_PRESENT by changing the way it registers its interrupts (just had to swap one line of code) 


But I still have exactly the same problem (endless loop in isr). Honestly I have no more ideas how to solve this, it's driving me crazy 


Any hints which could push me into the right direction?
Honored Contributor II

I don't know freeRTOS, but you must be very careful in using interrupt control functions with an underlying OS. 

Infact, an OS relies on a high priority irq to schedule application tasks; application usually doesn't work with irq at the raw level, but the OS emulates the required hw behaviour through sort virtual IRQs and the scheduling process. 

For example, if you use sys timer irq or any other device required by OS, you may corrupt the OS itself and your system would stop working. 

What I mean is that under an OS, using raw IRQs is possible but is not recommended unless you have a comprehensive knowledge of your OS's ineer workings and you are aware of what you are doing.