XIRQ on FreeRTOS #347
-
Hello, I'm trying to create a small demo application for FreeRTOS on NeoRV32 using XIRQ from external buttons (3) on a Xilinx chip. I set XIRQ_NUM_CH to 3 and map the 3 LSBs of xirq_i to my xirq input from the button. I let XIRQ_TRIGGER_TYPE and TRIGGER_POLARITY by defaut to trigger on rising-edge only. For the soft running on FreeRTOS, I wrote the following (I already check the return of each function and calls are working fine) : neorv32_xirq_setup();
neorv32_xirq_install(0, &vXirqHandlerChannel0);
neorv32_xirq_install(1, &vXirqHandlerChannel1);
neorv32_xirq_install(2, &vXirqHandlerChannel2);
// Allow IRQ to trigger CPU interrupt
neorv32_xirq_global_enable();
// Enable global interrupts
neorv32_cpu_eint();
// configure trap handler entry point
neorv32_cpu_csr_write(CSR_MTVEC, (uint32_t)&freertos_risc_v_trap_handler); Unfortunately, the XIRQ is not triggering on FreeRTOS software and my handlers are never called. When I trigger the XIRQ by using a button, the processor seems to freeze (I use demo_blinky in parallel and when I press the button, the led stop blinking and UART freeze). I tried the baremetal c application demo_xirq and XIRQ are working fine, so my HW looks fine. I also tried to replace Thanks for your help! |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 6 replies
-
Hey there!
So both generics are set to all-one, right?
First of all you should do
Unfortunately, this is correct... We had a discussion about this some time ago in #130. The FreeRTOS kernel has no "default" support for any interrupts beyond the timer (MTI) and the external (MEI) interrupt. For any other interrupts (including the NEORV32 fast interrupt requests - one of those is used by the XIRQ) the kernel will get stuck. Which version of FreeRTOS are you using? I am using a rather old one (10.4.1), which works in the following way: The kernel checks if the interrupt was triggered by the machine timer. If not, it goes here: test_if_external_interrupt: /* If there is a CLINT and the mtimer interrupt is not pending then check to see if an external interrupt is pending. */
addi t1, t1, 4 /* 0x80000007 + 4 = 0x8000000b == Machine external interrupt. */
bne a0, t1, as_yet_unhandled /* Something as yet unhandled. */ Since the interrupt source is a fast interrupt request and not the "external interrupt" the kernel will get stuck here: as_yet_unhandled:
csrr t0, mcause /* For viewing in the debugger only. */
j as_yet_unhandled (from |
Beta Was this translation helpful? Give feedback.
-
I have updated my FreeRTOS to version V10.4.4, which has much better RISC-V support! 😄 The NEORV32 example project from The new FreeRTOS version provides a "hook" for all non-default interrupts: So I have modified the default "blink" NEORV32 demo: This is a simple edit to enable XIRQ channels 0 and 1. Note that this is done on low-level without using the default XIRQ functions, as these rely on the NEORV32 RTE, which we cannot use here. static void prvSetupHardware( void )
{
// install the freeRTOS trap handler
neorv32_cpu_csr_write(CSR_MTVEC, (uint32_t)&freertos_risc_v_trap_handler);
// enable XIRQ channels 0 and 1 (LOW LEVEL!)
NEORV32_XIRQ.IPR = 0; // clear all pending IRQs
NEORV32_XIRQ.SCR = 0; // acknowledge (clear) XIRQ interrupt
NEORV32_XIRQ.IER = 0x00000003UL; // enable channels 0 and 1
neorv32_cpu_irq_enable(XIRQ_FIRQ_ENABLE); // enable XIRQ's FIRQ channel
// clear GPIO.out port
neorv32_gpio_port_set(0);
// init UART at default baud rate, no parity bits, ho hw flow control
neorv32_uart0_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
// check available hardware extensions and compare with compiler flags
neorv32_rte_check_isa(0); // silent = 0 -> show message if isa mismatch
} Then I have defined a simple handler for the FreeRTOS-provided void freertos_risc_v_application_interrupt_handler(void) {
// acknowledge XIRQ (FRIST!)
NEORV32_XIRQ.IPR = 0; // clear pending interrupt
NEORV32_XIRQ.SCR = 0; // acknowledge XIRQ interrupt
// try to acknowledge/clear all pending interrupt sources (SECOND!)
neorv32_cpu_csr_write(CSR_MIP, 0);
// debug output
neorv32_uart0_printf("\n<IRQ> mcause = 0x%x </IRQ>\n", neorv32_cpu_csr_read(CSR_MCAUSE));
} You could use this a "trampoline" to check I have tested this with a simple button for XIRQ channel 0 and the freeRTOS blinky example and it works:
|
Beta Was this translation helpful? Give feedback.
-
First of all, a huge thanks for your time! You did an amazing work!
Absolutely.
It's the case!
Currently using v10.4.4, such as your second answer 👍🏼
Now I understand why the OS was kind of "freezing" !
This is clearly what I missed to hook with the external IRQ. Now that I can use Thanks a lot for your help, you're doing an amazing work with NeoRV32 and stuff! I'll try this asap and make a feedback here, but it should work!! 😄 |
Beta Was this translation helpful? Give feedback.
I have updated my FreeRTOS to version V10.4.4, which has much better RISC-V support! 😄
The NEORV32 example project from
sw/example/demo_freeRTOS
works without problems with this newer version.The new FreeRTOS version provides a "hook" for all non-default interrupts:
https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/356fff8028734dc50a46972b2e315e2871b0a12e/portable/GCC/RISC-V/portASM.S#L360-L362
So I have modified the default "blink" NEORV32 demo:
This is a simple edit to enable XIRQ channels 0 and 1. Note that this is done on low-level without using the default XIRQ functions, as these rely on the NEORV32 RTE, which we cannot use here.