Nios II VIC for interrupts

Hi, the current freeRTOS only supports IIC for NiosII. VIC is about 4x faster. I have over 10 interrupts in my design and I really need the VIC for performance. I saw the feature request #115 created 1 year and 9 months ago. Could someone give me a hint on how to implement it? I am sure someone has done it. My understanding of IIC is that all interrupts(hardware + softare) go through the exception vector(usually address 0x20 or anything defined in Qsys). Task switch inside a tick is through a software “trap”. freeRTOS stores the TCB+stack for each task in different regions. How do people handle this? Thanks, Mark

Nios II VIC for interrupts

I think the software “trap” for task switch can use a hardware interrupt to. With the VIC shadow register sets, it should speed up task swiching.

Nios II VIC for interrupts

Co-operative scheduling(configUSE_PREEMPTION=0) works with VIC :-), still need to get the hardware interrup handler working.

Nios II VIC for interrupts

Hi Mark – thanks for the info. I need to get the Interactive site working again so we can share.

Nios II VIC for interrupts

Hi Richard, the reason I use co-operative scheduling is that I only need to deal with the software “trap” exception/scheduler and figure out how to use the VIC instead(no context switching in the timer interrupt for now), so I am aiming at one target instead of 2 :-). I am going to report back when I found something.

Nios II VIC for interrupts

Hi, i started to write a port for the NIOS2 with VIC (vectored interrupt controller) and the basic features (preemptive context switching with nested interrupt model, https://www.freertos.org/a00110.html#kernel_priority) already seems to work. Here the Hardware description for the Intel (aka Altera) Qsys System: – NIOS 2 Processor (NIOS II/f with shadow registers) @100MHz – VIC – Interval Timer (@ 1ms) for the RTOS tick – some other Timers and custum components with high priority interrupt and minimal latency requirements – and of course some RAM (onchip RAM, ca. 40k) Settings in the BSP Project / Editor:hal.linker.enable_exception_stack set to false (no performance improvement with VIC) – hal.linker.enable_interrupt_stack set to false (no performance improvement with VIC) – Timer for RTOS Tick (IRQ0) set to priority 1 (RIL = 1, lowest priority) – IRQ1 to IRQ7 set to higher prioritys, from RIL=9 to RIL=15 which is the high priority interrupt – The IRQ0 (RTOS Tick Timer) runs in the register set 0 (RSS=0) which is “normal” register set. This is set, because the context switch has to be customized for FreeRTOS anyway, and there will be no performance improvements with shadow registers – IRQ1 to IRQ7 are configured to use there own shadow register set (IRQ1=RRS2, IRQ2=RRS3, …, IRQ7=RRS8) – altera_vic_driver.enable_preemption set to true – altera_vic_driver.enable_preemption_into_new_register_set set to true Changes to the existing port for the NIOSII with IIC (internal interrupt controller): – with an VIC there are seprerated interrupt entry addresses for each interrupt. These addresses are stored in a vector table. The altera VIC driver of the BSP will create these table in the file altera_uC_VIC_vector_tbl.S when generating the BSP. It places the corresponding interrupt funnels at these addresses. The funnel normally will save and restore CPU context and call the ISR, definied by the “alticisr_register()” function. With shadow registers for each ISR its unnessaccry to save and restore context. So the funnel will be very slim. Instead of using the altera isr funnel for the first interrupt (ISR0 aka RTOS Tick) I jump to the context switch implementation of the RTOS port: ~~~ /* Include funnel macros header file */

include “alteravicfunnel.h”

.section .text, "xa"
.align 2
.globl UC_VIC_VECTOR_TABLE
UCVICVECTORTABLE: #ALTNORMALNONPREEMPTIVEINTERRUPT 16 jmpi isrhandler .word 0x0 .word 0x0 .word 0x0 ALTSHADOWNONPREEMPTIVEINTERRUPT 16 ALTSHADOWNONPREEMPTIVEINTERRUPT 16 ALTSHADOWNONPREEMPTIVEINTERRUPT 16 ALTSHADOWNONPREEMPTIVEINTERRUPT 16 ALTSHADOWNONPREEMPTIVEINTERRUPT 16 ALTSHADOWNONPREEMPTIVEINTERRUPT 16 ALTSHADOWNONPREEMPTIVEINTERRUPT 16 ~~~ – the context switch (written in assembler) is different in contrast to the existing port for the NIIS2 IIC for these reasons: 1. Separate entry point for non interrupt exceptions. This is important because the portYIELD macro of FreeRTOS will execute the “trap” instruction. Other exceptions has to be handled in an other way… 2. because of the nested interrupt model (configKERNELINTERRUPTPRIORITY and configMAXSYSCALLINTERRUPTPRIORITY are defined) the interrupt enable state of the current task has to be saved and restored inside the context switch. Also the global interrupt enable bit (PIE of the CPU status register) has to be set at the beginning of the context switch to allow interrupts with priorities above configMAXSYSCALLINTERRUPT_PRIORITY to execute (with there own shadow registers).
  • new implementation of the portDISABLEINTERRUPTS and portENABLEINTERRUPTS macro (used by the vTaskEnterCritical and vTaskExitCritical functions). These two macros should only disable and enable interrupts at or below configMAXSYSCALLINTERRUPTPRIORITY. Because a context switch can occur inside a critical section, the enable state of the interrupts has to be saved inside the task context, to restore it when portENABLEINTERRUPTS is called. http://www.openrtos.net/FreeRTOSSupportForumArchive/August2007/freertosQuestionabouttaskYIELD1791353.html
RE: Question about taskYIELD() Posted by Richard on August 3, 2007 It is the intended behaviour that the context switch occurs within the critical section – this allows the use of the scheduler locking mechanism. Each task should maintain its own interrupt status. Therefore a task that has interrupts disabled can call taskYIELD(), and switch to a task that may have interrupts enabled. When the original task next runs it starts with the interrupts in the state in which it expects to find them – disabled. Therefore this mechanism does not mean that interrupts remain disabled until the task executes again.
Remaining issues, limitations and questions: 1. Only one VIC is implemented (no daisy chain of multiple VIC). 2. I use the vTaskSetThreadLocalStoragePointer mechanism to store the interrupt state in the portDISABLEINTERRUPTS macro. I dont like this method because the state can be corrupted if someone call the API with index 0 from user space. Is there a better way or place to store this information? 3. In the VIC the priority of each interrupt (e.g. IRQ0 to IRQ7) can be configured individually. So for example IRQ3 could have a higher priority than IRQ4. I save a “irqdisablemask” variable initialized in the xPortStartScheduler functions (set corresponding bit of the variable if RIL <= configMAXSYSCALLINTERRUPTPRIORITY). At context switch I can disable necessary interrupts instantly with this mask and the INTENABLECLR register of the VIC. Therefore its not allowed to change the priority of any interrupt after starting the scheduler. 4. The altera_uC_VIC_vector_tbl.S is modified by hand and will be overwritten when the BSP is generated. I don’t find another way to use the custom ISR written in assembler beside the Altera VIC driver library. This topic is described in the “Embedded Peripherals IP User Guide” from Intel (Altera), chapter 37.7.4 “Positioning the ISR in Vector Table”:
… Positioning an ISR in a vector table is an advanced and error-prone technique, notdirectly supported by the HAL. You must exercise great caution to ensure that the ISRcode fits in the vector table entry. … The VIC Table-Resident example requires modifying a BSP-generated file,alteravic1vectortbl.S. If you regenerate the BSP after making these modifications, the Nios II Software Build Tools regenerate alteravic1vectortbl.S,and your changes are overwritten. …
As a workaround i just created a copy of the alterauCVICvectortbl.S with the modified content and copy them as a “BUILDPREPROCESS” target in the correct folder. I am grateful for any comments or improvements from you… Regards, Andy