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.

How to use float in IRQ with FreeRTOS ?

Hello.

Is there possibility to use floating point coprocessor instructions in IRQ, with assumption that other task also use VFP?

Of course, task which use VFP began with vPortTaskUsesFPU() call, but it is not enough.

In IRQ handler, no VFP registers is saved to stack and poped back, and my tasks is not working correctly.

Is there any FreeRTOS port service functions to save VFP registers in IRQ and to restore VFP state after complete IRQ?

I use Keil MDK-ARM.

Regards,

  Vitaliy Bortsov

  • Hi Vitaliy,

    If the FPU is enabled, the compiler in T CCS6.x will automatically add assembly codes to store and restore the general registers and FPU related registers within all the ISRs. The following is what are inserted in the SCI ISR.

    To Store registers at the beginning of ISR:

    STMFD R13!, {R0, R1, R2, R3, R12, R14}
    VMRS R12, FPEXC
    STMFD R13!, {R12}
    VMRS R12, FPSCR
    STMFD R13!, {R12}
    VSTMDB R13!, {D0-D7}
    SUB R13, R13, #8

    Restore the register at the end of ISR:

    ADD R13, R13, #8
    VMOV R0, R13, D0
    LDMFD R13!, {R12}
    VMSR FPSCR, R12
    LDMFD R13!, {R12}
    VMSR FPEXC, R12
    LDMFD R13!, {R0, R1, R2, R3, R12, R14}
    SUBS PC, R14, #4

    I don't know if Keil compiler generates those kind of code too.

    Regards,

    QJ

  • Hello, QJ Wang

    With __irq prefix, Keil push R0, R1, R2, R3, R12, LR and pop those registers back after servicing IRQ handler.

    Maybe, it is more correct? Not all IRQ need VFP calculation and it is an user responsibility to do something.

    I just add two assembly functions:

        area |.text|, code, readonly
        arm
        export vPortSaveVFP
        export vPortRestoreVFP
    
    vPortSaveVFP FUNCTION
        FSTMIAD R0!, {D0-D15}
        FMRX    R1, FPSCR
        STM     R0, {R1}
        bx      lr
        ENDFUNC
    
    vPortRestoreVFP FUNCTION
        FLDMIAD R0!, {D0-D15}
        LDM     R0, {R1}
        FMXR    FPSCR, R1
        bx      lr
        ENDFUNC
    
        end
    

    and call them if my IRQ need VFP, like:

    #include <stdint.h>
    
    struct VFPguard {
        uint64_t d[16];
        uint32_t s;
    };
    
    __irq void handler(void)
    {
        VFPguard s;
        vPortSaveVFP(&s);
        my_hanldler_with_VFP_use();
        vPortRestoreVFP(&s);
    }

    But I would preffer to use C++ instead of C, and it seems like that:

    #include <cstdint>
    
    struct VFPguard {
    private:
        uint64_t d[16];
        uint32_t s;
    public:
        VFPguard() {vPortSaveVFP(this);}
        ~VFPguard() {vPortRestoreVFP(this);}
    };
    
    extern "C" __irq void handler()
    {
        VFPguard s;
        call_my_hanlder();
    }