nRF54L15: high current consumption after using FPU, need information about FPU_IRQn interrupt vector.

Hi,

i am working on a project using the nRF54L15.

Hardware: custom board with nRF54L15

Software:

  • Wirepas SDK (1.6.2) 
  • nrfx drivers (version 3.9.0) with some customization to integrate it into the SDK
  • CMSIS DSP floating point libraries (Version 5.1)

I see in my current measurements that idle current increases by roughly 300µA after using the floating point unit. I already checked the developer zone for any similar tickets, and there are lots of them, though all are for other SoC, like nRF52 series. 

Most of these tickets suggest the high current consumption comes from unhandled FPU interrupts. I was already able to confirm that this is indeed the reason for the increased current. Now i'm trying to implement a solution for this.

The suggested solution from other tickets is to do something like the code below:

__STATIC_INLINE void pwr_mgmt_fpu_sleep_prepare(void)
     {
        uint32_t original_fpscr;

        CRITICAL_REGION_ENTER();
        original_fpscr = __get_FPSCR();
        /*
         * Clear FPU exceptions.
         * Without this step, the FPU interrupt is marked as pending,
         * preventing system from sleeping. Exceptions cleared:
         * - IOC - Invalid Operation cumulative exception bit.
         * - DZC - Division by Zero cumulative exception bit.
         * - OFC - Overflow cumulative exception bit.
         * - UFC - Underflow cumulative exception bit.
         * - IXC - Inexact cumulative exception bit.
         * - IDC - Input Denormal cumulative exception bit.
         */
        __set_FPSCR(original_fpscr & ~0x9Fu);
        __DMB();
        NVIC_ClearPendingIRQ(FPU_IRQn);
        CRITICAL_REGION_EXIT();

        /*
         * The last chance to indicate an error in FPU to the user 
         * as the FPSCR is now cleared
         *
         * This assert is related to previous FPU operations 
         * and not power management.
         *
         * Critical FPU exceptions signaled:
         * - IOC - Invalid Operation cumulative exception bit.
         * - DZC - Division by Zero cumulative exception bit.
         * - OFC - Overflow cumulative exception bit.
         */
        ASSERT((original_fpscr & 0x7) == 0);
     }

That is, 1. clear the FPU exception bits in FPSCR, 2. clear the pending IRQ with NVIC_ClearPendingIRQ(FPU_IRQn);

Which brings me to my problem. I can't find any definition for FPU_IRQn for the nRF54L15, neither in the Nordic Documentation nor in any of the processor header files.

For other SoCs FPU_IRQn is defined as an enum value in IRQn_Type. For the nRF54L15, in nrf54l15_application.h there is a similar type definition for IRQn_Type, but it does not contain the FPU_IRQn.

Maybe it is just named differently? 

So my question is: how do i clear the pending IRQ for the FPU on the nRF54L15?

Best regards

Frank Viganske

Parents
  • The six FPU events such as EVENTS_FPUIOC are noted as "RW"; maybe try writing a '0' to those registers which read as '1' to see if that clears the event; subsequently writing 0x3F to INTENCLR might also clear any interrupts still enabled, although it is usually an unwanted set Event which causes wakeup problems. I haven't tried this but would like a working option. Another way might be to simply temporarily enable all six interrupts with dummy handlers (if none provided) which might clear the interrupt pending in hardware.

    As an aside, (at least on the nRF52) although Interrupts are level-sensitive and must be cleared each use (otherwise repeated invocation of the enabled interrupt handler occurs), Events are edge sensitive and do not require clearing.

  • Hi,

    I already did a few more experiments with clearing the FPSCR register bits and the Event registers. Here is what i found out:

    1. Clearing the FPSCR bits (__set_FPSCR(original_fpscr & ~0x9Fu);) brings the current consumption back to normal. It seems this works without clearing the pending IRQ on the nRF54L15.

    2. The EVENTS_FPU... regsiters remain set even after the FPSCR bits have been cleared. They have to be written to 0 to reset them, but this does not seem to be necessary for getting the current down.

    So it seems for the moment i have a workaround - whenever i have used floating point operations in my code i need to check for any FPU exception flags ahd clear them.

    Still it would be better, if i could just implement an Interrupt handler that will handle these exceptions automatically. But without knowing the IRQ number I have no idea how to do this. 

  • Hello,

    ''But without knowing the IRQ number I have no idea how to do this.''

    You can try to search nrf54l15_application.h (ncs/version../modules/hal/nordic/nrfx/bsp/stable/mdk/nrfl15_application.h) for the entry containing CPUC in the IRQn_Type enum.

    ''1. Clearing the FPSCR bits (__set_FPSCR(original_fpscr & ~0x9Fu);) brings the current consumption back to normal. It seems this works without clearing the pending IRQ on the nRF54L15.''

    This seems correct approach as when an FPU operation raises an exception flag in the FPSCR, CPUC captures this as an event and if the corresponding interrupt is enabled, it raises the CM33SS_IRQn interrupt. It keeps the CPU from entering sleep mode properly. It means CPU goes to sleep mode but it awakes up immediately. That's why you measure 300uA increase in the current. 

Reply
  • Hello,

    ''But without knowing the IRQ number I have no idea how to do this.''

    You can try to search nrf54l15_application.h (ncs/version../modules/hal/nordic/nrfx/bsp/stable/mdk/nrfl15_application.h) for the entry containing CPUC in the IRQn_Type enum.

    ''1. Clearing the FPSCR bits (__set_FPSCR(original_fpscr & ~0x9Fu);) brings the current consumption back to normal. It seems this works without clearing the pending IRQ on the nRF54L15.''

    This seems correct approach as when an FPU operation raises an exception flag in the FPSCR, CPUC captures this as an event and if the corresponding interrupt is enabled, it raises the CM33SS_IRQn interrupt. It keeps the CPU from entering sleep mode properly. It means CPU goes to sleep mode but it awakes up immediately. That's why you measure 300uA increase in the current. 

Children
  • Hi,

    You can try to search nrf54l15_application.h (ncs/version../modules/hal/nordic/nrfx/bsp/stable/mdk/nrfl15_application.h) for the entry containing CPUC in the IRQn_Type enum.

    The header file included in the current version of the WIrepas SDK is a little bit outdated. It has no CPUC_IRQn defined in the IRQn_Type enum. But there is a CM33SS_IRQn.

    In a more recent version of the header file CPUC_IRQn is defined as an alias for CM33SS_IRQn, so CM33SS_IRQn appears to be the right IRQ number to use.

    I implemented an IRQ handler for this and set the corresponding INTEN bits, but unfortunately the Interrupt handler is not called when there is a floating point exception.

    I have no idea why this does not work. Maybe the WIrepas network firmware handles this IRQ internally  and i can't install my own handler because of that. 

    So I think I'll just have to live with my existing workaround, and check / clear the FPSCR bits after each part of the code where the FPU is used. 

    Thanks for your help.

    Frank

Related