IRQ Wrapper Arm Cortex-R4 (Renesas EC-1)

Hello everyone!

I use the following wrapper for all IRQs in my project so that they can be traded via OS:

void r_rspi0_transmit_interrupt_entry( void )
__asm volatile (
“PUSH {r0-r1} \t\n”
“LDR r0, =pxISRFunction \t\n”
“LDR R1, =r_rspi0_transmit_interrupt \t\n”
“STR R1, [r0] \t\n”
“POP {r0-r1} \t\n”
"B FreeRTOS_IRQ_Handler "

This works perfectly!

Now I would also like to use a timer IRQ without this wrapper. How can I implement this?

If I handle the Interupt service routine without a wrapper, i.e. directly call r_rspi0_transmit_interrupt, then I get stuck somewhere and my WatchDog task is no longer called.

Why do you want to do that? Is there a problem that you are trying to solve?

I need an 8µs raster cyclically every millisecond for a duration of 168µs. With the wrapper, the jitter is too high for my application. I would therefore like to use the timer IRQ without wrapper and the others with wrapper.

What is the priority of this interrupt? Is it more than configMAX_API_CALL_INTERRUPT_PRIORITY?

Which FreeRTOS port are you using?

I am using FreeRTOS Kernel V10.2.1

The define “configMAX_API_CALL_INTERRUPT_PRIORITY” does not exist in this version.
I have tested with the highest and lowest IRQ priority of the timer without success.

Regardless of this, my timer IRQ must be highly prioritized so that the jitter is minimal and the timing is predictable.

Can you check which file in the portable directory are you using?

I am using /main/portable/GCC/ARM_CRx_No_GIC

The files correspond to this commit:


Thank you for sharing this info. All this interrupt handler does it store the used registers before calling the application interrupt handler. Are you saving the registers that are used in the ISR? Are you writing it in C or assembly?

The wrapper is written in assembly and saves and restores the registers.
My timer IRQ is written in C and does not handle the registers.
Do I also have to take care of the registers in the timer IRQ (C code)?
If so, do you have an example C code for me?

yes, of course. Any interrupt must be completly transparent to the interrupted thread of execution, so all registers that are being manipulated by the ISR must be properly saved and restored.

Doing this in C normally requires saving/restoring ALL registers as there is no prediction what registers are being used in the ISR due to optimization.

The best way is to write entry point in assembly. You can refer the code of FreeRTOS_IRQ_Handler.

I have provided the function with the following attribute:

void EventTimerIRQ_Handler( void ) __attribute__ ((interrupt));

Now the GCC compiler generates function entry and exit sequences.

I am now able to use IRQs directly and via wrapper.

The jitter of my timer IRQ has improved, but is still too high. But that’s a separate topic :wink:

Thank you very much for your support!

Glad that you worked it out and thank you for sharing your solution!

How is the FreeRTOS actually called? From an interrupt? If so, what priority does it have and how can I change it?

you probably meant to write "how is the FreeRTOS SCHEDULER actually called?

Normally from the service interrupt handler, but it depends on whether nested interrupts are supported or not.

EDIT: You can not change the priority of the service interrupt. It must have lowest interrupt priority for FreeRTOS to work.

Finding: the function “portDISABLE_INTERRUPTS()” is called at various points in the code, causing jitter regardless of my interrupt priority.

The No_GIC port does not support partial masking of interrupts, so this is the expected behavior.

You might see if you can alter to port to handle that ability (assuming the processor has an interrupt controller that would support it). The Cortex-M were nice in that they all supported the same interrupt controller (at least close enough), the bigger R family doesn’t, so the “generic” ports aren’t as functional, but need versions for each type of controller.

It looks like the Renesas EC-1 interrupt controller does support Richard’s suggestion. The VIC’s PRLM register lets you mask interrupts by priority level, and the PRLC register lets you unmask them again.