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

Is there any setting for using WFE();?

Hi,

In my proejct, I am using WFE(); in some while loops because of core low power mode.

For example, waiting for time_out flags like codes below.

I am wondering if it is helpful to use WFE(); in terms of power consumption and if the example usage is proper.

Also, the other question is do I need to set up anything (interrupt pin or timer) to wake device up from the WFE low power mode state? or just call WFE(); anywhere if I use while loop?

int i2c_read(i2c_s *objuint8_t devAddruint8_t *datauint8_t length)
{
    i2c_xfer_done[obj->instance] = false;
    int retry = I2C_RETRY_NUM;

    ret_code_t err_code = nrf_drv_twi_rx(obj->i2c_dev, devAddr, data, length);
    if (err_code != NRFX_SUCCESS)
    {
        debug_verbose(NON_CRITICAL_ERROR, SENSOR_CONTROL_CATEGORY, "i2c_read: nrf_drv_twi_init error\r\n");
    }
    while (i2c_xfer_done[obj->instance] == false && retry--)
    {
#ifdef SOFTDEVICE_PRESENT
        if(nrf_sdh_is_enabled())
        {
            sd_app_evt_wait();
        }
        else
#endif // SOFTDEVICE_PRESENT
        {
            __WFE();
        }
    }
    if (retry < 0)
    {
        err_code = NRFX_ERROR_TIMEOUT;
    }
    return err_code;
}
    while(get_interruptPin_level_C() == 0 && !timed_out) // TODO: app timer expired immediately
    // while(get_interruptPin_level_C() == 0 && (timeOutTicks > os_getTime() - startTick))
    {
#ifdef SOFTDEVICE_PRESENT
        if(nrf_sdh_is_enabled())
        {
            sd_app_evt_wait();
        }
        else
#endif // SOFTDEVICE_PRESENT
        {
            __WFE();
        }
    }
Thanks!
  • One more thing, Can use  nrf_pwr_mgmt_run() instead of __WFE() in those situation like waiting for timeout. 

    There is already device sleep mode code with nrf_pwr_mgmt_run().

  • Hi

    I would suggest checking out our examples in the SDK which has the nrf_pwr_mgmt_run() function set at the bottom of the main loop (for example the ble_app_uart, or pwr_mgmt examples), triggering whenever nothing else is going on in the application. This should be a cleaner solution than adding __WFE(); multiple places in your application. nrf_pwr_mgmt_run() will also take care of any necessary preparation tasks. For details on what needs to be prepared when going to sleep, you can check out the nrf_pwr_mgmt_run() function in nrf_pwr_mgmt.c in the SDK.

    Best regards,

    Simon

  • Hi Simon,

    Thank you for your answer.

    I have another question.

    One thing I found that i2c read while loop is stuck before other interrupt happen like uart reading when I change __WFE to nrf_pwr_mgmt_run() If the sensor is not connected. In that case, using just some delay instead nrf_pwr_mgmt_run() should be better, right? Also SPI read /write should be the same?

    Thank you.

  • Hi

    How exactly does the application get stuck? It's entirely up to you if you'd like to use the nrf_pwr_mgmt_run() function or not, but if you just call __WFE, keep in mind that you won't prepare the device for sleep like the nrf_pwr_mgmt_run() function does (See below for the full function):

    void nrf_pwr_mgmt_run(void)
    {
        PWR_MGMT_FPU_SLEEP_PREPARE();
        PWR_MGMT_SLEEP_LOCK_ACQUIRE();
        PWR_MGMT_CPU_USAGE_MONITOR_SECTION_ENTER();
        PWR_MGMT_DEBUG_PIN_SET();
    
        // Wait for an event.
    #ifdef SOFTDEVICE_PRESENT
        if (nrf_sdh_is_enabled())
        {
            ret_code_t ret_code = sd_app_evt_wait();
            ASSERT((ret_code == NRF_SUCCESS) || (ret_code == NRF_ERROR_SOFTDEVICE_NOT_ENABLED));
            UNUSED_VARIABLE(ret_code);
        }
        else
    #endif // SOFTDEVICE_PRESENT
        {
            // Wait for an event.
            __WFE();
            // Clear the internal event register.
            __SEV();
            __WFE();
        }
    
        PWR_MGMT_DEBUG_PIN_CLEAR();
        PWR_MGMT_CPU_USAGE_MONITOR_SECTION_EXIT();
        PWR_MGMT_SLEEP_LOCK_RELEASE();
    }
    

    Best regards,

    Simon

  • Sorry I'll try to give more details for you to understand my question.

    I am using a kind of loop concept to queue jobs and execute them and if there is no job to do then go to sleep.

    Of course, when the device goes to sleep, nrf_pwr_mgmt_run() will be called and it works fine.

    However, my question is about i2c read/write's while loop to wait for i2c_xfer_done.

    When I use nrf_pwr_mgmt_run() like below and i2c sensor is disconnected, it seems it can't wake up from nrf_pwr_mgmt_run().

    And when I send data through UART then it restarts progressing. So I guess i2c_xfer_done can't be done because h/w is disconnected and no more event to wake up the device so it is stuck there and UART event triggers the device to wake up from nrf_pwr_mgmt_run(). So in this case I think it's better to use just some delay vs nrf_pwr_mgmt_run() for the while loop.

    I just want to make sure if what I am thinking is correct.

    int i2c_read(i2c_s *objuint8_t devAddruint8_t *datauint8_t length)
    {
        i2c_xfer_done[obj->instance] = false;
        int retry = I2C_RETRY_NUM;

     

        ret_code_t err_code = nrf_drv_twi_rx(obj->i2c_dev, devAddr, data, length);
        if (err_code != NRFX_SUCCESS)
        {
            debug_verbose(NON_CRITICAL_ERROR, SENSOR_CONTROL_CATEGORY, "i2c_read: nrf_drv_twi_init error\r\n");
        }
        while (i2c_xfer_done[obj->instance] == false && retry--)
        {
             nrf_pwr_mgmt_run()
        }
        if (retry < 0)
        {
            err_code = NRFX_ERROR_TIMEOUT;
        }
        return err_code;
    }
    Thanks!
Related