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

nrf52832 __WFI instruct can not been executed correct?

This is my code,the problem is when cpu executed the __WFI() instruct it should be paused ,this means that NRF_LOG_INFO("wake up\r\n") should not been executed only after rtc interrupt wake up cpu. But the result of my code is that cpu not paused ,the printed result is: enter sleep wake up; COMPARE_EVENT_OUTPUT; not enter sleep; COMPARE_EVENT_OUTPUT ; wake up; development environment : sdk12.2 nrf52832

#define RTC_FREQUENCY  (8UL)    /*!< required RTC working clock RTC_FREQUENCY Hertz. Changable */

#define COMPARE_COUNTERTIME (30UL) /*!< Get Compare event COMPARE_TIME seconds after the counter starts from 0 */

    const nrf_drv_rtc_t rtc = NRF_DRV_RTC_INSTANCE(0); /**< Declaring an instance of nrf_drv_rtc for RTC0. */
    
    /** @brief Function starting the internal LFCLK XTAL oscillator.
     */
    static void lfclk_config(void)
    {
        ret_code_t err_code = nrf_drv_clock_init();
        APP_ERROR_CHECK(err_code);
        nrf_drv_clock_lfclk_request(NULL);
    }
    
    /** @brief: Function for handling the RTC0 interrupts.
     * Triggered on TICK and COMPARE0 match.
     */
    static void rtc_handler(nrf_drv_rtc_int_type_t int_type)
    {
        if (int_type == NRF_DRV_RTC_INT_COMPARE0)
        {
    	NRF_LOG_INFO("COMPARE_EVENT_OUTPUT\r\n");
    	//Enable tick event & interrupt
    	nrf_drv_rtc_disable(&rtc);
    	uint32_t mask = NRF_RTC_INT_COMPARE0_MASK;
    	nrf_drv_rtc_int_disable(&rtc,&mask);
    	nrf_drv_rtc_uninit(&rtc);
        }
    }
    
    /** @brief Function initialization and configuration of RTC driver instance.
     */
    static void rtc_config(void)
    {
        uint32_t err_code;
        
        nrf_drv_common_irq_disable(SysTick_IRQn);
        //Initialize RTC instance
        nrf_drv_rtc_config_t config = NRF_DRV_RTC_DEFAULT_CONFIG;
        config.prescaler = 4095;
        err_code = nrf_drv_rtc_init(&rtc, &config, rtc_handler);
        APP_ERROR_CHECK(err_code);
    
        //Enable interrupt
        nrf_drv_rtc_int_enable(&rtc,NRF_RTC_INT_COMPARE0_MASK);
    
        //Set compare channel to trigger interrupt after COMPARE_COUNTERTIME seconds
        err_code = nrf_drv_rtc_cc_set(&rtc,0,COMPARE_COUNTERTIME * RTC_FREQUENCY,true);
        APP_ERROR_CHECK(err_code);
    
        //Power on RTC instance
        nrf_drv_rtc_enable(&rtc);
    }
    
    void pre_init()
    {
        lfclk_config();
        rtc_config();
        NRF_LOG_INFO("enter sleep\r\n");
        __WFI();
        NRF_LOG_INFO("wake up\r\n");
    }
    
    /**@brief Function for application main entry.
     */
    int main(void)
    {
        uint32_t err_code;
    
        // Initialize.
        err_code = NRF_LOG_INIT(NULL);
        APP_ERROR_CHECK(err_code);
        pre_init();
    	
        while(1)
       {
         nrf_delay_ms(100);
       }
    }
  • Not a full answer, just some ideas: a device (e.g. the RTC) sets a flag bit, which triggers the interrupt. Disabling/enabling an interrupt from the device does not clear the flag bit. If the flag bit is set when you WFI, it will not wait. Your code does not ensure that the flag bit is not set before your WFI. I could be wrong, I am not that familiar with the nrf_drv_rtc_.... code, but you could read that code to make sure that the nrf_drv_rtc calls you are making are clearing the flag bit. Or look at other working examples.

  • thank you ,i checked the source code found the internal of lfclk_config() function used the interrupt , so i changed the lfclk_config() to this

    static void lfclk_config(void)
        {
            NRF_CLOCK->LFCLKSRC            = (CLOCK_LFCLKSRC_SRC_RC << CLOCK_LFCLKSRC_SRC_Pos);
            NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
            NRF_CLOCK->TASKS_LFCLKSTART    = 1;
        
            NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
        }
        the problem resloved!
    
Related