Our system has SPI and I2C. Each of these communications works in isolation, as implemented in our program, for multiple transactions. When we try to include both we noted that any SPI transactions that occurs after the 1st I2C transaction will hang in the nrf_spi_event_check() function called from spi_xfer() in nrfx_spi.c.
So in isolation our I2C transactions work fine, and our SPI transactions work fine, but as soon as we try to perform an I2C transaction followed by a SPI transaction the program hangs.
Through debugging we cannot see any notable change in behavior of the SPI transaction before or after the I2C transaction other than it hanging. We have no interrupts in our system and we are only sending data over SPI (we pass a dummy rx buffer to the transfer function). I pasted some code snippets below to show our implementation of SPI and I2C. We are seeking any advice in how to get our program to exit the nrf_spi_event_check() loop when it is stuck.
SPI
Init:
...
instance_(NRFX_SPI_INSTANCE(0)),
handle_(
{
.sck_pin = 14,
.mosi_pin = 13,
.miso_pin = 15,
.ss_pin = NRFX_SPI_PIN_NOT_USED,
.irq_priority = 7,
.orc = 0xFF,
.frequency = NRF_SPI_FREQ_4M,
.mode = NRF_SPI_MODE_0,
.bit_order = NRF_SPI_BIT_ORDER_MSB_FIRST
}
),
...
Init code, NOTE: no handler function, we are polling not using an interrupt:
nrfx_spi_init(&instance_, &handle_, nullptr, NULL);
SPI transfer function. Only interested in the write:
...
nrfx_spi_xfer_desc_t xfer_desc = NRFX_SPI_XFER_TRX(&packet, static_cast<size_t>(i), &dummy_rx_byte, 1);
nrfx_spi_xfer(&instance_, &xfer_desc, 0);
...
Where it gets stuck after an I2C Write:
...
else
{
do {
while (!nrf_spi_event_check(p_spi, NRF_SPI_EVENT_READY)) {} // <-- gets stuck here
nrf_spi_event_clear(p_spi, NRF_SPI_EVENT_READY);
NRFX_LOG_DEBUG("SPI: Event: NRF_SPI_EVENT_READY.");
} while (transfer_byte(p_spi, p_cb));
if (p_cb->ss_pin != NRFX_SPI_PIN_NOT_USED)
{
nrf_gpio_pin_set(p_cb->ss_pin);
}
}
...
nrfx_spi.c, line 332
Relevant I2C code:
Init:
...
instance_(NRFX_TWI_INSTANCE(0)),
handle_(
{
.scl = scl_pin_number,
.sda = sda_pin_number,
.frequency = NRF_TWI_FREQ_100K,
.interrupt_priority = NRFX_TWI_DEFAULT_CONFIG_IRQ_PRIORITY,
.hold_bus_uninit = NRFX_TWI_DEFAULT_CONFIG_HOLD_BUS_UNINIT
}
)
nrfx_twi_init(&instance_, &handle_, nullptr, NULL);
nrfx_twi_enable(&instance_);
Write:
...
nrfx_twi_xfer_desc_t tx_transfer = {
.type = NRFX_TWI_XFER_TX,
.address = device_address,
.primary_length = size,
.secondary_length = 0,
.p_primary_buf = buffer,
.p_secondary_buf = NULL
};
auto error = nrfx_twi_xfer(&instance_, &tx_transfer, 0);
...