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

app_twi_schedule with Soft Device returning error

I'm hoping this is just something silly that I've overlooked, but I'm running into an issue: Whenever I try to prompt the scheduling of a TWI transaction an error occurs

What I'm trying to do is initialise the transaction when a certain value is sent to the characteristic. What I'm seeing in the debugger though is an NRF_ERROR_BUSY being generated when doing the app_twi_schedule in the function below (called when the write is made), located within my service file:

void rh_read(void)
{
	//printf("rh read...  ");
	
	static app_twi_transfer_t transfers[] = 
	{
		SHT21_RH_READ(&m_sht21_buffer[0])
	};
	static app_twi_transaction_t const transaction =
	{
	.callback            = rh_read_callback,
	.p_user_data         = NULL,
	.p_transfers         = transfers,
	.number_of_transfers = sizeof(transfers) / sizeof(transfers[0])
	};
	
	APP_ERROR_CHECK(app_twi_schedule(&m_app_twi, &transaction));

}

The documentation says that this error is thrown when the queue is full, but no other twi transactions would have been scheduled at this point. When the slave device is set up it's set up with app_twi_perform, and I see them complete on with my scope.

Here's my TWI setup function:

static void twi_init(void)
{
	ret_code_t err_code;
	
	nrf_drv_twi_config_t const config = {
		.scl						= I2C_SCL,
		.sda						= I2C_SDA,
		.frequency					= NRF_TWI_FREQ_100K,
		.interrupt_priority			= APP_IRQ_PRIORITY_HIGH
	};
	
	APP_TWI_INIT(&m_app_twi, &config, MAX_PENDING_TRANSACTIONS, err_code);
	APP_ERROR_CHECK(err_code);
}

Any idea what's happening here?

  • Hi. So sorry for the delayed response on this. I have been trying to reproduce this, but without any luck. Can you provide some more context? I see from your tags that you use S110. How much other stuff do you have going on when you start your transfers? Would you mind posting your complete code? Or something that can reproduce the issue? And I'll have to ask the obvious question; is MAX_PENDING_TRANSACTIONS defined according to how many transactions you plan to do?

  • Basically I based it on two examples. The BLE side being based on the tutorial for custom services and characteristics, the second being an app_twi example.

    MAX_PENDING_TRANSACTIONS is set to 100, but prior to this transaction that is causing the error, there would have been <10 TWI communications, but all done by app_twi_perform(), so just polled not scheduled.

    The only other things I have going on when I start the twi comms, is some timers (with callbacks) and the soft device running.

  • I am not able to access your link. Can you upload it here on devzone? You can edit your question and upload it there.

  • Thanks. I tried your example now. I don't have access to a SHT21 sensor so I just made some minor changes to make the example work with an MPU I have instead. Otherwise the flow in the example is pretty much unaltered. Anyway, I saw the same behaviour as you. So I consulted with the creator of the library and he pointed out a mistake in your code:

    You are declaring

    static app_twi_t m_app_twi = APP_TWI_INSTANCE(0);
    

    in hardware.h and then you are including this file in both hardware.c and our_service.c. This will in effect cause two instances of m_app_twi to be created in static memory. One instance is used by hardware.c and the other by our_serivce.c. Then you initialize m_app_twi with APP_TWI_INIT() in hardware.c and hence, hardware.c is working perfectly since it is using a properly declared and initialized m_app_twi, but our_service.c is using a completely different, uninitialized m_app_twi. To solve it you have two options:

    1. Declare m_app_twi in e.g. main.c and pass a pointer to this instance to every function that would need it.

    2. An easier way would be to us the extern keyword and declare:

      app_twi_t m_app_twi = APP_TWI_INSTANCE(0);

    in hardware.c and:

    extern app_twi_t m_app_twi;
    

    in hardware.h. This way you won't need to rewrite all your functions relying on m_app_twi. I tried it and it seemed to work.

Related