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

Is MWU in Softdevice?

Hi,

I am using nRF52832 along with Softdevice 6.0.0, SDK 15.0.0, Chip Revision 2 (QFAA-EX0).

I understand that softdevice uses MWU from this document

As per the Errata 75 there is increased current consumption when MWU is used.

We are not using MWU in our application code, so how to apply the workaround for this errata in our code? Will the softdevice take care of this errata internally or the application has to take care of it. In application we do use __WFE.

Regards,

Justin

  • If you use sd_app_evt_wait to sleep, then the workaround is applied inside this sleep function. But if you use __WFE instead of sd_app_evt_wait, then when you go to sleep then MWU remains enabled by the softdevice and the ERRATA issue exists keeping higher power consumption in the sleep.

    Is there any specific reason you do not use sd_app_evt_wait() to go to sleep?

  • Hi Susheel,

    In this ticket you asked us to use __WFE instead of sd_app_evt as a workaround for Errata 220.

    Please suggest what needs to be done in this case? 

  • Sorry for the delayed reply, I think we need to do, I am asking the experts to confirm this.

  • I am sorry Justin,

    It is my fault that I did not think about Errata 75 when suggesting you to apply the workaround for Errata 220.

    You are right, we need to apply the workaround of Errata 75 too into the workaround of Errata-220.

    So the required and combined workaround for 220 and 75 becomes like below

    SCB->SCR |= SCB_SCR_SEVONPEND_Msk;
    __disable_irq();
    
    /* MWU Disable */
    NRF_MWU->REGIONENCLR
        = ((MWU_REGIONENCLR_RGN0WA_Clear << MWU_REGIONENCLR_RGN0WA_Pos) 
         | (MWU_REGIONENCLR_PRGN0WA_Clear << MWU_REGIONENCLR_PRGN0WA_Pos));
    
    __WFE()
    __nop();__nop();__nop();__nop();
    
    /* MWU Enable */
    NRF_MWU->REGIONENSET
        = ((MWU_REGIONENSET_RGN0WA_Set << MWU_REGIONENSET_RGN0WA_Pos) 
         | (MWU_REGIONENSET_PRGN0WA_Set << MWU_REGIONENSET_PRGN0WA_Pos));
    
    __enable_irq();

  • For a more general case where the Softdevice is/isn't installed and user code does/doesn't use the MWU I am using the following:

    // Errata 75: MWU: Increased current consumption
    //  This has to be handled by turning off MWU region 0 which is used in SoftDevice
    //  see https://infocenter.nordicsemi.com/index.jsp?topic=%2Ferrata_nRF52832_EngB%2FERR%2FnRF52832%2FEngineeringB%2Flatest%2Fanomaly_832_75.html
    #define MWU_ACCESS_WATCH_MASK (0x0F0000FF)

    The code replacing the WFE() is as follows:

      // Errata 220: CPU: RAM is not ready when written - Disable IRQ while using WFE
      // Enable SEVONPEND to disable interrupts so the internal events that generate the interrupt cause wakeuup in __WFE context and not in interrupt context
      // Before: ENABLE_WAKEUP_SOURCE -> __WFE -> WAKEUP_SOURCE_ISR -> CONTINUE_FROM_ISR  next line of __WFE
      // After:  ENABLE_WAKEUP_SOURCE -> SEVONPEND -> DISABLE_INTERRUPTS -> __WFE -> WAKEUP inside __WFE -> ENABLE_interrupts -> WAKEUP_SOURCE_ISR
      //
      // Errata 75: MWU: Increased current consumption
      // This has to be handled by turning off MWU but it is used in SoftDevice
      // see https://infocenter.nordicsemi.com/index.jsp?topic=%2Ferrata_nRF52832_EngB%2FERR%2FnRF52832%2FEngineeringB%2Flatest%2Fanomaly_832_75.html
      //
      // Errata 220: Enable SEVONPEND
      SCB->SCR |= SCB_SCR_SEVONPEND_Msk;
      __disable_irq();
      // Errata 75: MWU Disable
      uint32_t MWU_AccessWatchMask = NRF_MWU->REGIONEN & MWU_ACCESS_WATCH_MASK;
      // Handle MNU if any areas are enabled
      if (MWU_AccessWatchMask)
      {
         NRF_MWU->REGIONENCLR = MWU_AccessWatchMask; // Disable write access watch in region[0] and PREGION[0]
         __WFE();
         __NOP(); __NOP(); __NOP(); __NOP();
         // Errata 75: MWU Enable
         NRF_MWU->REGIONENSET = MWU_AccessWatchMask;
      }
      else
      {
         __WFE();
         __NOP(); __NOP(); __NOP(); __NOP();
      }
      __enable_irq();

    This code is required in nrf_pwr_mgmt.c, main.c and nrf_soc.c to cover our use cases with both BLE SoftDevice and without. Feel free to provide constructive feedback .. this is very hard to test!

Related