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

Hard Fault on return of SPI Manager Write after multiple successful SPI Writes

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!

Related