Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs

Workaround for erratum [220] when using FPU

Hi

We are using the nRF52832 with the SoftDevice S132 V7.2.0.
Recently, we had to enable the FPU whereby we have to re-evaluate the consequences of erratum 220.

According to this description, the SoftDevice V8.x should be used when the FPU is enabled.

But according to this thread, it seems that there would be also a workaround for SoftDevice V7.2.0 when the FPU is enabled by disabling stacking of FPU registers.

Is that correct? Could you please specify how this workaround can be implemented?

Many thanks in advance.

Best regards

Remo

Parents Reply
  • Hi Remo,

    The implementation of sd_app_evt_wait() in the SoftDevice is more complex and differs from how it you would do it in an application. This is because it involves an SVCall and defering of the __WFE() call from the interrupt context.

    Remo said:
    You've written that with option 1, we will also be woken up in case of SoftDevice interrupts (RADIO, TIMER0, RTC0, ...).

    Are you using a supperloop, or are there other reasons for why this is problematic in your application?

    Best regards,

    Vidar

    EDIT: forgot to add that nrf_pwr_mgmt_run() also handles clearing of FPU events with PWR_MGMT_FPU_SLEEP_PREPARE(). 

Children
  • Hi Vidar

    Our application is controlled by commands from the UART interface, e.g. to "sleep" in system ON mode until a rising edge on a certain GPIO occurs. We relied on the behavior that the function sd_app_evt_wait() only returned when an application-based event occurred. Therefore, it would be great to have a workaround that behaves the same way as sd_app_evt_wait() did.

    When I've understood the code in PWR_MGMT_FPU_SLEEP_PREPARE correctly, this is the workaround for erratum 87 and not 220. Or does this also fix erratum 220?

    Best regards

    Remo

  • Hi Remo,

    Can you set a volatile flag in the UART or GPIO ISR to signal the main loop when the interrupt has been triggered?

    do 
    {
        //TODO: use errata 220 WA to enter System ON
    } while(<gpio interrupt triggered == 0>)
    
    

    When I've understood the code in PWR_MGMT_FPU_SLEEP_PREPARE correctly, this is the workaround for erratum 87 and not 220. Or does this also fix erratum 220?

    Correct, and the wait for event loop should include the workaround for both.

    Best regards,

    Vidar

  • Hi Vidar

    Unfortunately, it is not that easy because we have multiple wakeup-sources (rising edge on GPIO was only one example).

    In SDK V17.1.0, the wait for event loop doesn't seem to have a workaround implemented. Or have I missed something?

        {
            // Wait for an event.
            __WFE();
            // Clear the internal event register.
            __SEV();
            __WFE();
        }

    If we implement the loop ourselves, what does our application need to do when a SoftDevice-specific event occurred (e.g. RADIO)? Do we have to clear any pending IRQs/events, or can we simply go to sleep again?

    Best regards

    Remo

  • Hi Remo,

    It's correct that SDK 17.1.0 does not implement the errata 220 workaround. 

    Remo said:
    If we implement the loop ourselves, what does our application need to do when a SoftDevice-specific event occurred (e.g. RADIO)? Do we have to clear any pending IRQs/events, or can we simply go to sleep again?

    The IRQ pending bit will be cleared as soon as the Softdevice has serviced the ISR, the same applies to application interrupts. I quickly tested this here by replacing the sd_app_evt_wait() call in nrf_pwr_mgmt_run() with this app_evt_wait() function I implemented:

    /*
     * Enter system ON idle mode and return only when application level interrupts are triggered.
     * This function requires SEVONPEND to be enabled in the application.
     * (SCB->SCR |= SCB_SCR_SEVONPEND_Msk;)
     */
    static void app_evt_wait(void)
    {
        uint32_t pending_irqs0;
        uint32_t pending_irqs1;
    
        do
        {
            __disable_irq();
            MWU_DISABLE();
            __WFE();
            __NOP();__NOP();__NOP();__NOP();
            pending_irqs0 = NVIC->ISPR[0];
            pending_irqs1 = NVIC->ISPR[1];
            __enable_irq();
            /* Note: mwu is enabled internally in the Softdevice during
             * forwarding of application interrutps
             */
            MWU_ENABLE();
        } while ((pending_irqs0 & __NRF_NVIC_APP_IRQS_0) == 0ul &&
                 (pending_irqs1 & __NRF_NVIC_APP_IRQS_1) == 0ul);
    
    }

    Disclaimer: This function has not been thoroughly tested or reviewed by others.

    Remo said:
    easy because we have multiple wakeup-sources (rising edge on GPIO was only one example).

    Do you use the wait for event function in a superloop in main?

    Best regards,

    Vidar

  • Hi Vidar

    Thank you very much for this function. We will test it on our side.

    Yes, we are using this function in a super loop in main.

    Best regards

    Remo

Related