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

non blocking TWI from app_timer callback

Hi,

I have blocking TWI operation in app_timer callback to read fifo from accelerometer. It works just fine but I want to make it non-blocking to decrease current consumption. I am not able to do it. Could you please help me?

I tried to change the TWI IRQ priority from 3 to 1 but it had no effect. Variable FIFO_read is still false.

I use nRF51822QFACA, SDK10, Softdevice S110 v.8

volatile bool FIFO_read = false;
void twi_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
{
	if(p_event->type == NRF_DRV_TWI_RX_DONE)
	{
		FIFO_read = true;
	}
				
}

static void accel_timeout_handler(void * p_context)
{
    uint8_t tx_x[] = {0x28};	//X axis out low
	uint8_t tx_fifostatus[] = {0x2F};	//fifo status
	uint8_t rx_x[192];
	uint8_t rx_fifostatus[1];
	uint8_t number_of_registers = 6;
	
	const nrf_drv_twi_t p_twi_instance = NRF_DRV_TWI_INSTANCE(0);
   nrf_drv_twi_config_t p_twi_config;
   p_twi_config.scl = 2;
   p_twi_config.sda = 1;
   p_twi_config.frequency = NRF_TWI_FREQ_400K;
   p_twi_config.interrupt_priority = 1;
  uint32_t err_code = NRF_SUCCESS;
	err_code = nrf_drv_twi_init(&p_twi_instance, &p_twi_config, twi_handler, NULL);
	nrf_drv_twi_enable(&p_twi_instance);
	
	err_code = nrf_drv_twi_tx(&p_twi_instance, 0x19, tx_fifostatus, sizeof(tx_fifostatus), true);
	err_code = nrf_drv_twi_rx(&p_twi_instance, 0x19, rx_fifostatus, sizeof(rx_fifostatus), false);
		
	err_code = nrf_drv_twi_tx(&p_twi_instance, 0x19, tx_x, sizeof(tx_x), true);
	FIFO_read = false;
	err_code = nrf_drv_twi_rx(&p_twi_instance, 0x19, rx_x, (rx_fifostatus[0] & 0x3F) * number_of_registers , false);
	do{
		__WFE();
	}
	while(FIFO_read == false);
}

Thank you.

  • Hi,

    Could you try setting a breakpoint in the event handler and see if it's called?

    regards

    Jared 

  • volatile bool read = false;
    volatile bool write = false;
    void twi_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
    {	
    	if(p_event->type == NRF_DRV_TWI_RX_DONE)
    	{
    		read = true;
    	}
    	if(p_event->type == NRF_DRV_TWI_TX_DONE)
    	{
    	    write = true;
    	}
    }
    
    static void accel_timeout_handler(void * p_context)
    {
    	uint8_t tx_x[] = {0x28};	//X axis out low
    	uint8_t tx_fifostatus[] = {0x2F};	//fifo status
    	uint8_t rx_x[192];
    	uint8_t rx_fifostatus[1];
    	uint8_t number_of_registers = 6;
    	
    		
    	const nrf_drv_twi_t p_twi_instance = NRF_DRV_TWI_INSTANCE(0);
       nrf_drv_twi_config_t p_twi_config;
       p_twi_config.scl = 2;
       p_twi_config.sda = 1;
       p_twi_config.frequency = NRF_TWI_FREQ_400K;
       p_twi_config.interrupt_priority = 1;//priority low
      uint32_t err_code = NRF_SUCCESS;
    	err_code = nrf_drv_twi_init(&p_twi_instance, &p_twi_config, twi_handler, NULL);
    	nrf_drv_twi_enable(&p_twi_instance);
    	
    	write = false;
    	err_code = nrf_drv_twi_tx(&p_twi_instance, 0x19, tx_fifostatus, sizeof(tx_fifostatus), true);
    	do{
    		__WFE();
    	}
    	while(write == false);
    	
    	read = false;
    	err_code = nrf_drv_twi_rx(&p_twi_instance, 0x19, rx_fifostatus, sizeof(rx_fifostatus), false);
    	do{
    		__WFE();
    	}
    	while(read == false);
    		
    	write = false;
    	err_code = nrf_drv_twi_tx(&p_twi_instance, 0x19, tx_x, sizeof(tx_x), true);
    	do{
    		__WFE();
    	}
    	while(write == false);
    	
    	read = false;
    	err_code = nrf_drv_twi_rx(&p_twi_instance, 0x19, rx_x, (rx_fifostatus[0] & 0x3F) * number_of_registers , false);
    	do{
    		__WFE();
    	}
    	while(read == false);
    	...

    Hi Jared,

    thank you for quick response.

    It is getting to handler. I updated the code to wait for DONE event everytime I call function nrf_drv_twi_rx() or nrf_drv_twi_tx(). Code is not stuck now and everything seems to be fine.

    But I am not sure if it is implemented in right way. I expected higher energy savings.

    In connection without TWI reading FIFO(192 bytes) every 2,5s current consumption is 11uA.

    When reading FIFO in blocking mode current consumtion is 37uA.

    When reading FIFO in non-blocking mode current consumption is 35uA.

    Are these results expected? Or do you think there is an issue in non blocking mode implementation?

    What current consumption would you expect if SPI was used instead of TWI for this purpose?

    Thanks,

    Mila

  • Hi,

    Are you using a custom board? What are you doing in main() while you're waiting for the event to be generated?

    regards

    Jared

  • Hi,

    I am using custom board.

    Function power_manage() is called in main.

    I tried to replace __WFE() with power_manage() while waiting for TWI event but the current consumption was the same.

    /**@brief Function for the Power manager.
     */
    static void power_manage(void)
    {
        uint32_t err_code = sd_app_evt_wait();
        APP_ERROR_CHECK(err_code);
    }

  • Hi,

    Are you using the Softdevice? If yes, what connection parameters do you use?

    regards

    Jared

Related