Hello,
I'm having an issue with a hard fault when trying to write a specific value to a peripheral chip (TDC7201) register after multiple successful writes to the same register(s). I'm using a custom board with BL652 (nRF52832), SDK 16.0 and S132. The peripheral chip has two SPI channels, controlling to each via a different spi_config with the nRF SPI Manager.
SPI Config(s):
static nrf_drv_spi_config_t m_spi_tdc1_config =
{
.sck_pin = SPI_SCK_PIN,
.mosi_pin = SPI_MOSI_PIN,
.miso_pin = SPI_MISO_PIN,
.ss_pin = SPI_CS1_PIN,
.irq_priority = SPI_DEFAULT_CONFIG_IRQ_PRIORITY, //6
.orc = 0xFF,
.frequency = NRF_DRV_SPI_FREQ_8M,
.mode = NRF_DRV_SPI_MODE_0,
.bit_order = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST
};
static nrf_drv_spi_config_t m_spi_tdc2_config =
{
.sck_pin = SPI_SCK_PIN,
.mosi_pin = SPI_MOSI_PIN,
.miso_pin = SPI_MISO_PIN,
.ss_pin = SPI_CS2_PIN,
.irq_priority = SPI_DEFAULT_CONFIG_IRQ_PRIORITY, //6
.orc = 0xFF,
.frequency = NRF_DRV_SPI_FREQ_8M,
.mode = NRF_DRV_SPI_MODE_0,
.bit_order = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST
};
SPI Write:
ret_code_t tdc7201_write_regs(uint8_t reg_addr, const uint8_t reg_data, uint8_t len, const struct tdc7201_dev *dev)
{
int8_t rslt;
uint8_t temp_buff[2]; /* Typically not to write more than 4 registers */
uint8_t temp_len;
uint8_t reg_addr_cnt;
ret_code_t ret_val;
struct tdc_callback_data tdc_data;
rslt = null_ptr_check(dev);
if ((rslt == TDC7201_OK) && (tdc_data.rx_buf != NULL))
{
/* Converting all the reg address into proper SPI write address*/
reg_addr = reg_addr | TDC720x_WRITE_BIT;
temp_buff[1] = reg_data;
temp_buff[0] = reg_addr;
nrf_spi_mngr_transfer_t const transfers[] =
{
//Write data to designated register from both TDCs
NRF_SPI_MNGR_TRANSFER(&temp_buff, sizeof(temp_buff), tdc_data.rx_buf, tdc_data.length)
};
nrf_spi_mngr_transaction_t const transaction_tdc1 =
{
.begin_callback = NULL,
.end_callback = NULL,
.p_user_data = NULL,
.p_transfers = transfers,
.number_of_transfers = sizeof(transfers) / sizeof(transfers[0]),
.p_required_spi_cfg = &m_spi_tdc1_config //NULL
};
nrf_spi_mngr_transaction_t const transaction_tdc2 =
{
.begin_callback = NULL,
.end_callback = NULL,
.p_user_data = NULL,
.p_transfers = transfers,
.number_of_transfers = sizeof(transfers) / sizeof(transfers[0]),
.p_required_spi_cfg = &m_spi_tdc2_config
};
/* Schedule SPI read transmissions */
while(!nrf_spi_mngr_is_idle(&m_nrf_spi_mngr));
ret_val = nrf_spi_mngr_schedule(&m_nrf_spi_mngr, &transaction_tdc1); //non-blocking
//ret_val = nrf_spi_mngr_perform(&m_nrf_spi_mngr, &m_spi_tdc1_config, transfers, 1, NULL); //blocking
dev->delay_ms(10); //necessary delay since TDC7201 cannot handle consecutive read / write commands
if (ret_val == NRF_SUCCESS)
{
ret_val = nrf_spi_mngr_schedule(&m_nrf_spi_mngr, &transaction_tdc2); //blocking
//ret_val = nrf_spi_mngr_perform(&m_nrf_spi_mngr, &m_spi_tdc2_config, transfers, 1, NULL); //blocking
dev->delay_ms(10); //necessary delay since TDC7201 cannot handle consecutive read / write commands
}
/* Check for communication error and mask with an internal error code */
if (rslt != TDC7201_OK)
{
rslt = TDC7201_E_COMM_FAIL;
}
}
else
{
rslt = TDC7201_E_NULL_PTR;
}
return ret_val;
}
I'm just looping and trying to read the registers in the main.c but the hard fault occurs when tdc7201_new_meas(&dev.conf, &dev); is called. Driving into that, the hard fault occurs when jumping out of the tdc7201_write_regs().
while (1)
{
nrf_delay_ms(1000);
uint8_t rx_buf[4] = {0, 0, 0, 0};
if(!measurement_done)
{
tdc7201_start_measurement(&dev.conf, &dev);
nrf_delay_ms(1000);
tdc7201_read_regs(TI_TDC720x_CONFIG1_REG, rx_buf, 2, &dev);
tdc7201_read_regs(TI_TDC720x_CONFIG2_REG, rx_buf, 2, &dev);
nrf_delay_ms(100);
measurement_done = true;
}
else if(measurement_done)
{
//nrf_delay_ms(500);
tdc7201_read_regs(TI_TDC720x_TIME1_REG, rx_buf, 4, &dev);
tdc7201_read_regs(TI_TDC720x_CALIBRATION1_REG, rx_buf, 4, &dev);
tdc7201_read_regs(TI_TDC720x_CALIBRATION2_REG, rx_buf, 4, &dev);
tdc7201_compute_tof(&dev);
tdc7201_new_meas(&dev.conf, &dev); //fails if this line is uncommented
measurement_done = false;
}
}
My original though was that it had something to do with the non-blocking vs. blocking modes of the SPI Manager, but I don't think that's the case since implementing both variants doesn't change the result. Any other thoughts on the possible reason?
Thanks!