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

NRF_ERROR_BUSY at nrf_drv_twi_tx on sleep_mode_enter

I am using SDK15.2 and I am using ble_app_hrs example to build a device that has multiple sensors and a display.

I am constantly reading sensors data using blocking TWI and everything works great, but before the system goes to sleep I need to send a TWI commands that will turn off the sensors and the display, this is where I get the NRF_ERROR_BUSY at the nrf_drv_twi_tx call...

If I remove the "APP_ERROR_CHECK(err_code);" lines from my custom sensors and display libraries I dont get the error but the sensors and the display dont receive the command to turn off...

I tired doing a while loop until err_code becomes NRF_SUCCESS and also I tried doing the "do while(0)" loop as provided in the twi_master_with_twis_slave example but it didnt fix my problem.

I think the problem is that the constant reading keeps the TWI busy non stop and once the APP_ADV_DURATION times out and prepares the system to go to sleep (where i also try to send my TWI commands for turning off the sensors and display) is where I get the conflict...

Any suggestion how should i fix this properly?

Thanks in advance.

  • Hi,

    It is not clear to me weather you stop the constant calls to nrf_drv_twi_tx() before you do the final call before going to sleep? With the behavior you are describing I wonder if you are doing the regular polling in continuously thread mode, and then suddenly try to do the last write in an interrupt handler priority? (in a timer event handler or BLE event handler or similar)? You need to let the last "normal" transaction finish, then move on to the last transaction where you send the command to turn off sensors and display.

  • Thanks for your reply.
    Actually after reading everything that I could find about blocking TWI I cant figure out how to stop sending calls before I send the last "turn off" sensors and display command before the system goes to sleep...

    I read the sensors and refresh the display in the main loop (function idle_state_handle) and then in the function sleep_mode_enter() i try to send the commands that turn off the sensors and the display.

    Here is the "idle_state_handle" function:

    static void idle_state_handle(void)
    {
        ret_code_t err_code;
        err_code = nrf_ble_lesc_request_handler();
        APP_ERROR_CHECK(err_code);
    
        readHrSpo();
        OLED_SD1306_Driver_refresh();    
    
    
        if (NRF_LOG_PROCESS() == false)
        {
            nrf_pwr_mgmt_run();
        }
    }


    And here is the "sleep_mode_enter" function:

    static void sleep_mode_enter(void)
    {
        ret_code_t err_code;
        MAX30105_shutDown();
        OLED_SD1306_Driver_off();
        nrf_drv_twi_disable(&m_twi);
    
        err_code = bsp_indication_set(BSP_INDICATE_IDLE);
        APP_ERROR_CHECK(err_code);
    
        // Prepare wakeup buttons.
        err_code = bsp_btn_ble_sleep_mode_prepare();
        APP_ERROR_CHECK(err_code);
    
        // Go to system-off mode (this function will not return; wakeup will cause a reset).
        err_code = sd_power_system_off();
        APP_ERROR_CHECK(err_code);    
    }

    I get the error in the MAX30105_shutDown() function where I send the command for shut down using nrf_drv_twi_tx.

  • Hi,

    I see. Then the error you are seeing is expected and appropriate. You are trying to do two transactions at the same time. The proper way to handle this is to let the current transaction complete, then do the last transaction where you send the command for the sensor to go to sleep.

  • yes, thats what I think too, but where can i find info how to do that? i read everything in the sdk documentation about twi and checked all the twi examples and i cant figure out how to do that waiting for the transaction to complete, also tried to wait in while loop until the nrf_drv_twi_tx response becomes NRF_SUCCESS but then i end up in an endless loop for some reason.

    from what i understand from the documentation about blocking TWI, code continues after nrf_drv_twi_tx only when the transaction completes, but as i said its not the case in my code...

  • I am having some problems making sense of this. Can you upload your code and describe in more detail? As you write, the blocking call will return whenever it is finished. Then you simply just have to not call the function again.

Related