This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28335, FPU Full Context Save/Restore.

I was thumbing through the FPU Primer (spraan9.pdf) and found the section 'Interrupt Context Save and Restore'. I then realized that I am performing context switches but not preserving the FPU registers during the context save and restore.

We have an in-house written task switcher that uses Timer 2 to switch between tasks.  Several of these threads are using floating point calculations so I am very concerned.

In the spraam9.dpf document, there is a comment that says that the SAVE and RESTORE instructions should only be used within 'High Priority Interrupts'.

'RB must be saved if it is used in the interrupt and the FPU registers are copied to their shadow registers using the SAVE instruction. SAVE and RESTORE should only be used in high-priority interrupts.'

 How do I know which interrupts are considered to be 'high' and 'low' priorities? I do not recall any documentation or chart that classifies interrupts sources as being catagorized as 'high' or 'low'. Can someone help clarify this?

Also, in the same document, it mentions a couple of pragmas that are used to identify your interrupts as 'high' and 'low' priority.

// Specify a High-Priority Interrupt:
#pragma INTERRUPT (function_name, HPI)

// Specify a Low-Priority Interrupt:
#pragma INTERRUPT (function_name, LPI)

Do I need to use these pragmas on all of my C interrupt routines so that the FPU state is properly saved and restored?

Here are the macros that I used to preserve and restore registers during a context save (does not include the FPU registers):

I$$SAVE .macro
    ;ASP
    PUSH   AR1H:AR0H  ; Save remaining registers.
    PUSH   XAR2    
    PUSH   XAR3   
    PUSH   XAR4  
    PUSH   XAR5  
    PUSH   XAR6  
    PUSH   XAR7  
    PUSH   XT
    PUSH   RPC

        .endm

I$$REST .macro

    POP    RPC
    POP    XT
    POP    XAR7  
    POP    XAR6  
    POP    XAR5  
    POP    XAR4  
    POP    XAR3   
    POP    XAR2    
    POP    AR1H:AR0H
    ;NASP
    IRET 

        .endm

Here is the recommended context save and restore instructions:

High Priority Context save:

    ASP                                   ; Align stack
    PUSH RB                        ; Save RB if used <-- New for FPU
    PUSH AR1H:AR0H       ; Save if used
    PUSH XAR2
    PUSH XAR3
    PUSH XAR4
    PUSH XAR5
    PUSH XAR6
    PUSH XAR7
    PUSH XT
    SPM 0                              ; Set C28 modes
    CLRC AMODE
    CLRC PAGE0,OVM
    SAVE RNDF32=1          ; FPU registers <--

High Priority Context restore:

    RESTORE            ; FPU registers ; <-- new for FPU
    POP XT                 ; Restore registers
    POP XAR7
    POP XAR6
    POP XAR5
    POP XAR4
    POP XAR3
    POP XAR2
    POP AR1H:AR0H
    POP RB                           ; Restore RB ; <-- new for FPU
    NASP                               ; Un-align stack
    IRET                                 ; Return

  • In this context a high priority interrupt is defined as an interrupt that cannot itself be interrupted.    A low-priority interrupt is defined as an interrupt that allows itself to be interrupted.

    The compiler assumes low-priority by default for C coded interrupts (which is the safest and will always work).  If you have interrupts you know will not themselves be interrupted then you can improve performance by using the pragma to specify they are high priority.

    -Lori

  • Lori,

    Thank you for the quick response. After I posted I went back and found the definition in the FPU primer.

    Since we are task switching between C threads performing floating point calculations, I believe that we should always use the low-priority context switching scheme.

    The reason I believe that to be the case is that a thread might be in the middle of a floating point calculation when it is interrupted. Another thread might then use the FPU for more floating point calculations. The interrupted thread may need to retrieve FPU results after it resumes execution, the state of the FPU must be saved to the stack. If I am understanding the FPU shadow registers (using SAVE and RESTORE), that provides a single copy of the FPU and therefore the interrupt that executes these commands must itself not be interrupted.

    If you have any other advice about multi-threading and working with the FPU it would be appreciated.

    Thank you.