Using Fast Interrupt mode with microblaze

almomo1 wrote on Thursday, November 29, 2018:

Hi!

I’m developing a real-time project with FreeRTOS and Microblaze; the design has to serve a lot of interrupts as fast as possible, so I enabled “Fast Interrupt Mode” on Xilinx Interrupt Controller (XIntc). Microblaze is set to Fast Interrupt mode too in the Block Design. “Fast Interrupt Mode” is a low-latency interrupt system where microblaze jumps directly to the address of the ISR, which is provided by the XIntc along with the interrupt high-level signal.

The first beta of my code doesn’t include Fast Interrupt, just normal ones and it works perfectly. Now, I want to serve interrupts in fast mode, so I did the following steps:

  1. FreeRTOS call to

XIntcConnect( &xInterruptControllerInstance, ucInterruptID, pxHandler, pvCallBackRef );

was replaced by

XIntcConnectFastHandler( &xInterruptControllerInstance, ucInterruptID, pxHandler );

  1. FreeRTOS application callback void vApplicationSetupTimerInterrupt( void ) was edited accordingly to support Fast Interrupt.

  2. All normal interrupt service routines in normal mode were left unchanged, but this pragma was added:

void DMA0RxISR(void) attribute((fastinterrupt));

The interrupts are actually triggered and I can debug step-by-step DMA0_Rx_ISR, but when this ISR is returned, the task yield is not performed and the notification sent to the second task never arrives. I checked that AXI_TIMER_0 interrupts are triggered, served and acknowledged.
It looks like scheduler is not taken control on the microblaze and can’t yield tasks. The design has 3 tasks and all of three starts as expected; Task 3 waits for Task 2 to end performing some process on data supplied by Task 1. Task1 gets data from DMA0 interface in the routine DMA0_Rx_ISR.

Does somebody know if further changes are needed in order to make fast interrupt work?

Maybe fast interrupt doesn’t work with FreeRTOS at all?

Thanks!

rtel wrote on Thursday, November 29, 2018:

I’ve not tried using fast interrupts and would have to look up the
hardware manual to understand what the differences are in interrupt
entry and exit…but with normal interrupt the kernel manages the
interrupt entry and exit code with some save and restore context macros.
If a context switch is performed then the restore context macro will
return control to a different task - are you using these macros on the
fast interrupt too? It might be that the fast interrupt will work fine
as long as you don’t use the FreeRTOS API from within its handler.

almomo1 wrote on Thursday, November 29, 2018:

No, I’m not using any macro specifically, in fact, I’m using exactly the same code for ISR in fast interrupt mode than in normal interrupt mode, maybe that’s the problem… Which macros are those? Where can I find them in the sources?

Thanks!

rtel wrote on Friday, November 30, 2018:

Did you see the interrupt sections on the FreeRTOS.org site?
https://www.freertos.org/RTOS-Xilinx-Microblaze-KC705.html#implementing_an_ISR
There are FreeRTOS specific functions to install interrupts, then they
get wrapped in the macros automatically - it is not something you have
to do manually.

almomo1 wrote on Friday, November 30, 2018:

I misunderstood you… I already have done everything stated in that link you posted (except for exceptions, which are not needed in my design) for normal interrupt mode. As I explained, all my system works perfectly in normal mode interrupt, so ISR routine puts the correct task in the “READY” state by calling portYIELD_FROM_ISR().
My problem is that the same code that works perfectly in normal interrupt mode doesn’t in fast interrupt mode, so I must be missing something I don’t know. When DMA ISR is executed, data is put on a queue which wakes up Task2, but the task never executes beyond xQueueReceive(xInfoQueue, &PacketInfo, portMAXDELAY) when in fast interrupt mode.

Regards!

richarddamon wrote on Friday, November 30, 2018:

The key thing that needs to happen which I think isn’t is that the stack frames built by the ISR in this fast interrupt mode need to be the same as the stack frames that were build by regular interrupt mode.

This frame is built by a combination of three things:

  1. The processor itself in servicing the interupt. If just the controller changed, and how it provides the address to go to, this may not be the issue, but something that needs to be looked at.

  2. The compiler generated preamble. The fastinterrupt may not generate the right stack frame compared to the regular service interrupt. You likely want to declare the ISRs exactly the same as the common ISR handler routine that did the vectoring to all the other ISRs, and if that was written in assembly, you may need an assembly shim on all your fast interrupts (and not mark them as fast interrupts),

  3. The code put at the beginning/end of the ISR (if any) to complete the state savingm and transfer to the schedule to change running taskl

rtel wrote on Friday, November 30, 2018:

I don’t think there is a FreeRTOS function to implement/install fast
interrupts, so presumably they don’t get wrapped in the necessary
save/restore context macros. Have you implemented that yourself?

almomo1 wrote on Monday, December 03, 2018:

  1. I think that is working well because the code stops at a breakpoint into the ISR; besides, I probed the inner signals and I checked the interrupt is served and acknowledged.
  2. That could be a possibility, as Xilinx’s SDK may be adding code for fast interrupt in “standalone” mode, not for RTOS. My ISRs are written in standard C, but I could easily port them to ASM if needed.
  3. As Richard Barry said, I didn’t wrap the ISR code in any save/restores context macro. Which macros are those? Is there any example or implementation I could have a look at to know how to proceed?

Thanks!

almomo1 wrote on Wednesday, December 12, 2018:

Any guidance about how to manually set those interrupt service routines?