This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

FPU divide by 0 and High Current Consumption

I was trying to track down high, approx. 6mA, processor current consumption and I have found high current consumption if the FPU executes a divide by 0. If I comment out the line the current consumption goes down to tens of micro amps. If the line is executed then the current is high since the processor is constantly coming out of sleep.

How does the the SDK deal with a divide by 0 with the FPU? I thought this was a hard fault?

Thanks

  • Learning is good.

    Learning now is understanding the link between WFE on events, and how pending levels in the NVIC relate to events that cause wakeup. I clearly see the condition occur, the FPU flag is set, and the exception condition in the NVIC is raised (NVIC_IPR1, bit 6) and never cleared. When I run the code without clearing, the sd_app_evt_wait() call never stalls, returns immediately. As Darren said, if I comment out the math instruction, the NVIC pending is not set, and then the instrumented idle wait performs a very nice 1ms sleep wait, as I expect.

    When I leave the math instruction, and add the code that Ole suggested, I have partial success. The sd_nvic_ClearPendingIRQ() works, and I get expected results. If I leave the __set_FPSCR() and __DMB(); __DSB(); _ISB(); calls in, then ANY subsequent sd function calls hardfault.

    Still some testing to finish.

  • And what if you don't use sd_app_evt_wait() but just __wfe(), since you're testing it it would be handy to know if the pending, disabled interrupt does keep the processor from sleeping at all, ie WFE continues to return instantly, in which case I get to read the manual again to work out why, or it's something that sd_app_evt_wait() does. I stopped using the latter a while ago because I never quite got comfortable that I knew exactly what it did.

  • You made me actually test it! It appears to be an effect of sd_app_evt_wait(). It's quite hard to get it to do it all just using __wfe() directly if the FPU exception is disabled (which it is). You need SEVONPEND set to make the exception raise cause an event, else the pending exception is ignored, then you need to arrange for the exception to re-trigger in order to cause another event, just ignoring it entirely and leaving it pending doesn't raise another event and __wfe() doesn't return again. So for instance clearing the exception but leaving the FPU flags will re-raise it and then you'll get another event, but that's what it takes.

    Replacing __wfe() with sd_app_event_wait() makes the code busy loop constantly if the FPU exception is pending, even with SEVONPEND cleared and even if it were only raised the one time. sd_app_evt_wait() is clearly more conservative than __wfe().

  • Ole,

    Can you show how to apply you code with Tickless sleep? Right now the only way I can get the power down is to use a combination of tickless sleep and the idle task which is clearing the FPU interrupt.

  • why don't you just enable the FPU interrupt and clear the divide by zero condition when it fires.

    .. or stop dividing things by zero

Related