Hello,
Today I stumbled upon very strange nRF52832 behaviour which I cannot explain. I am using two TWIM instances (0 and 1) and one SPIM instance (2).
First strange behaviour was that the TWIM instance 1 is working OK and TWIM instance 0 is always failing, even if I swap the configuration between them. I traced the error and discovered that TWIM0 is returning NRF_ERROR_BUSY error code, even that I use blocking mode. Moreover, TWIM1 is working fine with exactly the same code. I traced the error even further and discovered that the handler of the TWIM0 is not NULL, despite the fact that it is NULL after initialization.
I added this piece of code to the TWI driver to locate the error:
components\drivers_nrf\twi_master\nrf_drv_twi.h
/*
* @return Handler passed to the nrf_drv_twi_init function as a event_handler parameter.
*/
nrf_drv_twi_evt_handler_t nrf_drv_get_handler(nrf_drv_twi_t const * p_instance);
components\drivers_nrf\twi_master\nrf_drv_twi.c
nrf_drv_twi_evt_handler_t nrf_drv_get_handler(nrf_drv_twi_t const * p_instance)
{
twi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
return p_cb->handler;
}
Here the magic happens - my (stripped) initialization code:
nrf_drv_twi_t twi0 = NRF_DRV_TWI_INSTANCE(0);
nrf_drv_twi_t twi1 = NRF_DRV_TWI_INSTANCE(1);
nrf_drv_timer_t timer0 = NRF_DRV_TIMER_INSTANCE(1); // Instance 0 makes sd_softdevice_enable returning NRF_ERROR_SDM_INCORRECT_INTERRUPT_CONFIGURATION.
void timer0_event_handler(nrf_timer_event_t event_type, void *p_context)
{
}
void init_peripherals(void)
{
ret_code_t ret;
ret = nrf_drv_ppi_init();
APP_ERROR_CHECK(ret);
ret = nrf_drv_gpiote_init();
APP_ERROR_CHECK(ret);
nrf_drv_twi_config_t twi_config = {
//.scl =
TWI0_SCL,
//.sda =
TWI0_SDA,
//.frequency =
NRF_TWI_FREQ_400K,
//.interrupt_priority =
7,
// Clear bus during init?
//.clear_bus_init =
false,
// Hold pull up state on gpio pins after uninit?
//.hold_bus_uninit =
false
};
ret = nrf_drv_twi_init(&twi0, &twi_config, NULL, NULL);
APP_ERROR_CHECK(ret);
nrf_drv_twi_enable(&twi0);
twi_config.scl = TWI1_SCL;
twi_config.sda = TWI1_SDA;
ret = nrf_drv_twi_init(&twi1, &twi_config, NULL, NULL);
APP_ERROR_CHECK(ret);
nrf_drv_twi_enable(&twi1);
NRF_LOG_WARNING("TWI %u handler A = %x", twi0.drv_inst_idx, nrf_drv_get_handler(&twi0));
// Configure timer, but do not enable it yet.
nrf_drv_timer_config_t timer_config = {
//.frequency =
NRF_TIMER_FREQ_8MHz,
//.mode =
NRF_TIMER_MODE_TIMER,
//.bit_width =
NRF_TIMER_BIT_WIDTH_16,
//.interrupt_priority =
7,
//.p_context =
NULL
};
ret = nrf_drv_timer_init(&timer0, &timer_config, timer0_event_handler);
APP_ERROR_CHECK(ret);
// Timer compare interrupt frequency = (timer_frequency / 2) / cc_value
nrf_drv_timer_extended_compare(&timer0, NRF_TIMER_CC_CHANNEL0, 1, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, false);
NRF_LOG_WARNING("TWI %u handler B = %x", twi0.drv_inst_idx, nrf_drv_get_handler(&twi0));
}
This is the RTT console output:
<info> twi: Function: nrf_drv_twi_init, error code: NRF_SUCCESS.
<info> twi: Instance enabled: 0.
<info> twi: Function: nrf_drv_twi_init, error code: NRF_SUCCESS.
<info> twi: Instance enabled: 1.
<warning> app: TWI 0 handler A = 0
<warning> app: TWI 0 handler B = 23579
<info> app: Initialization done.
Does anyone have any idea how could this happen? TWIM instance 1 is always fine (even if I assign it to the twi0 variable).
Thank you.