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
  • Hello Remo,

    It is possible to implement the workaround in the application code, please see this thread:  RE: Random bad instruction faults at 0x16274 with softdevice s132 version 7.0.1. SDK 16.0.0 . Have you experienced the errata in your current application?  

    Best regards,

    Vidar

  • Hi Vidar

    Thank you very much for the really fast answer! ;-)

    No, we have not yet experienced this erratum. We just went through the errata-sheet and wanted to ensure that we will not run into this issue in the future.

    Have I understood this correctly, that it is sufficient to disable the FPU context saving procedure by setting ASPEN=0 before calling sd_app_evt_wait()?

    Best regards

    Remo

  • Hi Vidar

    Thank you. You are right, option 1 sounds more reliable.

    You've written that with option 1, we will also be woken up in case of SoftDevice interrupts (RADIO, TIMER0, RTC0, ...). Do you have a proposal how this function shall look like so that it behaves as sd_app_evt_wait()? Or would it be possible that you can share the code of sd_app_evt_wait() how it is implemented in SoftDevice V8.x.

    Best regards

    Remo

  • 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(). 

  • 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

Reply
  • 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

Children
  • 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

  • Hi Vidar

    I tested your function, and it seemed to worked with one exception: the function is not left when the SD_EVT_IRQn occurs. I mean the SD_EVT_IRQHandler is called, but the function app_evt_wait() is not left (assumingly because the SD_EVT_IRQn is automatically cleared). Do you have an idea how to solve this? How is this handled in sd_app_evt_wait()?

    Best regards

    Remo

  • Hi Remo,

    Detecting the SD_EVT_IRQn is more tricky as it is a SW interrupt that is set pending within the Softdevice ISRs to notify the app of a SD event. I suggest adding a volatile flag in the app to cover this.

    Best regards,

    Vidar

  • Hi Vidar

    Ok, solving this with a flag worked.

    Thanks again for all the help. It was very appreciated.

    Best regards

    Remo

Related