Faster (less safe) interrupts on MPLAB

nobody wrote on Tuesday, July 18, 2006:

Hi,

I noticed the tick interrupt function prvTickISR() is not defined with the "#pragma interruptlow" key.
If the #pragma is used, the compiler adds context save and -restore routines. Considering that an interrupt can trigger a task switch, it is very possible that 2 context saves are performed from within the same interrupt, filling the stack with 99% equal data.
I moved the portSAVE_CONTEXT and portRESTORE_CONTEXT macros to my own port.h to enable inclusion in my own interrupt functions.

void vSerial2RxISR( void )
{
    // Make sure local variables are ‘static’ to prevent “variable creation” overhead
static portCHAR cChar,cWoken;

    /* Interrupts must have been enabled for the ISR to fire, so we have to
    save the context with interrupts enabled. */
    portSAVE_CONTEXT( portGLOBAL_INTERRUPT_FLAG );            // Save context the FreeRTOS way

    cWoken=pdFALSE;

    functional code of the interrupt…

    if (cWoken==pdTRUE)
    {        // Returned true, so a task is woken. Force taskswitch
//        taskYIELD();            // Not required since context already properly saved
        vTaskSwitchContext();        // Switch without context save/restore
    }
    portRESTORE_CONTEXT();
}

This is allowed since interrupts cannot be interrupted, thus intermediate calculation results in the interrupt function cannot be corrupted.
It is NOT allowed to use local variables on the stack, all variables used in the interrupt routine should be either global or static (as in the example).

Paul

rtel wrote on Tuesday, July 18, 2006:

Hi Paul,

It has been a while since I have looked at the MPLAB port files.  They are perhaps in need of a little refreshing, so I am reading your comments with interest.  If you would like to submit your changes I can include them in the download, naturally crediting you with the improvement work.

There was a discussion a little while back about a potential situation that could occur should a stack cross a page boundary, and a tick interrupt occur just as the boundary was being spanned.  It will probably be of interest to you but at the moment I don’t seem to be able to get the search facility on the forum to work properly.

Regards.

nobody wrote on Tuesday, July 18, 2006:

Hi,

I noticed :wink: I’m still running 3.2.4 for lack of MPLAB port bugs and no need for the new features.

In my project, a complete save or restore takes about 100 to 150 cycles, so there is also a considerable efficiency advantage if one of 2 consequtive save/restores can be omitted.

BTW, your documentation states you don’t know if MATH_DATA is application dependent, well it is. In my application MATH_DATA plus .tmpdata is 28 bytes, much more than the 19 in the demo. Introducing division instructions increases size for example. Depending on the math you do the variables defined in aarg.asm , barg.asm, temparg.asm and cmath18.asm are dynamically added, thus increasing MATH_DATA size.
.tmpdata seems to be pretty constant (8). I’m currently inquiring with microchip what’s stored there since the .map file only shows variables “__tmp_0” at the first address. (I don’t think there is 64bit computation going on internally.)

As far as the modifications are concerned, I’m curious about your reaction to my other post: “Superfluous instruction in MPLAB port”, which describes a possible bug in the save and restore routines. If you agree, that change should be included as well.

The port.h is mainly all the defines from port.c. I also added a nesting around the actual math_data and tmpdata save and restoration sections: SAVE_MATH_AND_TMP and RESTORE_MATH_AND_TMP. The definitions of these are directly behind portCOMPILER_MANAGED_MEMORY_SIZE, to make it less easy to forget to change all these 3 things (and not just add or remove ‘movff’ instructions and forget to change portCOMPILER_MANAGED_MEMORY_SIZE for example, which will definitely break your code as I found out the hard way).

I’ll send the file by e-mail.

Paul