Xtensa Port Support for High Priority C-Handler Interrupt

(Enhancement Request Follows)

I’m using the FreeRTOS Xtensa maintained port

https://urldefense.com/v3/https://github.com/FreeRTOS/FreeRTOS-Kernel/tree/main/portable/ThirdParty/XCC/Xtensa;!!A3Ni8CS0y2Y!uxPcnXoDk-h3EMh07dd-k2Hzv0jOU8DmIQxtmbhUVED9kbwbi6FhBnFGuDEfglw7YXc$

The port does not allow C-Handlers to be registered for high priority interrupts. According to the Xtensa Programmers Guide

3.4High-Priority Interrupts
Some Xtensa processors also have high-priority interrupts, which are any interrupt with a priority level above EXCMLEVEL. Xtensa processors do not route high-priority interrupts through the usual UserExceptionVector or KernelExceptionVector. Each high-priority interrupt level has its own vector address, exception program counter register (EPCn), and exception program state register (EPSn), where n corresponds to the priority level, 2 through 15.

3.5Can I Write High-Priority Interrupt Handlers In C?
Technically you can write high-priority interrupt handlers in C, but Cadence strongly discourages it. XTOS can dispatch high-priority handlers written in C. However, this convenience brings a significant performance penalty of about 100-200 cycles4 on dispatch and nearly as much on handler exit, depending on processor configuration. This is largely due to the need to save and restore the entire address register file and various other exception-related states. The impact is potentially smaller when implementing the handler using the Call0 ABI, but XTOS is not optimized for its use, and the Call0 ABI has performance and size implications when used by the main application.

The XTOS does allow C-Handlers to be registered for XEA2 architectures. See the following API for more details
xtos-set-inthandler.c
int32_t
xtos_set_interrupt_handler(uint32_t intnum,
xtos_handler handler,
void * param,
xtos_handler * pprev)

However, the XCC port will not allow high priority C-Handlers

xtensa_intr.c

xt_exc_handler xt_set_exception_handler(int n, xt_exc_handler f)

/*
  This function registers a handler for the specified interrupt. The "arg"
  parameter specifies the argument to be passed to the handler when it is
  invoked. The function returns the address of the previous handler.
  On error, it returns 0.
*/
xt_handler xt_set_interrupt_handler(int n, xt_handler f, void * arg)
{
    xt_handler_table_entry * entry;
    xt_handler               old;

    if( n < 0 || n >= XCHAL_NUM_INTERRUPTS )
        return 0;       /* invalid interrupt number */
    if( Xthal_intlevel[n] > XCHAL_EXCM_LEVEL )
        return 0;       /* priority level too high to safely handle in C */

I modified XCHAL_EXCM_LEVEL to be equal to the highest priority interrupt and C-Handler functionality does work.

It would be nice if the port were changed to have a configuration option to allow this.

I’m not sure what the implication of doing this would be - presumably the high priority handlers would not be able to perform context switches, but maybe that is not a problem. I can ask the maintainers to take a look.