This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

TWI I2C communication with sensor leads to fatal error and system reset.

Hello,

I am using an nrf52832-based ble chip and try to communicate with cap1293 touch sensor. I'm using SDK 15.3 and started off from the twi_sensor peripheral example. 

Running this code, which tries to write a register and then read another one, leads to a fatal error and system reset, but when I tried debugging the code and run it step by step, the code worked. After some experimentation with delays I managed to make it work by inserting a delay (line 28) in nrfx_twim_xfer() function located in nrfx_twim.c. Do you have any idea what kind of problem could cause this issue?

int main(void)
{
    APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
    NRF_LOG_DEFAULT_BACKENDS_INIT();
    NRF_LOG_INFO("\r\nTWI sensor example started.");
	
	nrf_gpio_cfg_output(18);
    //NRF_LOG_FLUSH();
    twi_init();
	nrf_delay_ms(100);;
	NRF_LOG_INFO("TWI Initialized");
	
	uint8_t data[1] = {0x02};
	NRF_LOG_INFO("device address is %x", CAP1293);
	twi_write(CAP1293, 0x1F, data, 1);  // write a value to a register
	twi_read(CAP1293, MANUFACTURE_ID, data, 1); // read manufacturer id which is '5D'
	NRF_LOG_INFO("Manufacturer ID is %x",data[0]);
}

void twi_init (void)
{
    ret_code_t err_code;

    const nrf_drv_twi_config_t twi_cap1293_config = {
       .scl                = SCL_PIN,
       .sda                = SDA_PIN,
       .frequency          = NRF_DRV_TWI_FREQ_100K,
       .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
       .clear_bus_init     = false
    };

    err_code = nrf_drv_twi_init(&m_twi, &twi_cap1293_config, twi_handler, NULL);
    APP_ERROR_CHECK(err_code);
		
    nrf_drv_twi_enable(&m_twi);
}

void twi_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
{
    switch (p_event->type)
    {
        case NRF_DRV_TWI_EVT_DONE:
            if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_TX){
							NRF_LOG_INFO("TWI TX DONE");
						}
						else if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_RX){
							NRF_LOG_INFO("TWI RX DONE");
						}
						else if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_TXRX){
							NRF_LOG_INFO("TWI TXRX DONE");
						}
						else if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_TXTX){
							NRF_LOG_INFO("TWI TXTX DONE");
						}
						m_xfer_done = true;
				case NRFX_TWIM_EVT_ADDRESS_NACK:
            NRF_LOG_INFO("Received NACK after sending address!");
						break;
				case NRFX_TWIM_EVT_DATA_NACK:
            NRF_LOG_INFO("Received NACK after sending data.");
						break;
            
        default:
            break;
    }
}


int8_t twi_write(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint16_t length){
	
		uint32_t err_code;
		
		uint8_t buffer[2] = {0};
		buffer[0] = reg_addr;
		memcpy(&buffer[1], data, length);
		m_xfer_done = false;
		NRF_LOG_INFO("buffer and size of buffer %x, %d", &buffer, sizeof(buffer));
		err_code = nrf_drv_twi_tx(&m_twi, dev_addr, buffer, sizeof(buffer), false);

		APP_ERROR_CHECK(err_code);
		while(m_xfer_done == false);
		
		return err_code;
}

int8_t twi_read(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint16_t length)
{
    uint32_t err_code;
    m_xfer_done = false;
    err_code = nrf_drv_twi_tx(&m_twi, dev_addr, &reg_addr, sizeof(reg_addr), true);
    APP_ERROR_CHECK(err_code);
    while (m_xfer_done == false);

    m_xfer_done = false;
    err_code = nrf_drv_twi_rx(&m_twi, dev_addr, data, length);
    APP_ERROR_CHECK(err_code);
    while (m_xfer_done == false);

    return err_code;
}

nrfx_err_t nrfx_twim_xfer(nrfx_twim_t           const * p_instance,
                          nrfx_twim_xfer_desc_t const * p_xfer_desc,
                          uint32_t                      flags)
{
    NRFX_ASSERT(TWIM_LENGTH_VALIDATE(p_instance->drv_inst_idx,
                                     p_xfer_desc->primary_length,
                                     p_xfer_desc->secondary_length));

    nrfx_err_t err_code = NRFX_SUCCESS;
    twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];

    // TXRX and TXTX transfers are supported only in non-blocking mode.
    NRFX_ASSERT( !((p_cb->handler == NULL) && (p_xfer_desc->type == NRFX_TWIM_XFER_TXRX)));
    NRFX_ASSERT( !((p_cb->handler == NULL) && (p_xfer_desc->type == NRFX_TWIM_XFER_TXTX)));

    NRFX_LOG_INFO("Transfer type: %s.", TRANSFER_TO_STR(p_xfer_desc->type));
    NRFX_LOG_INFO("Transfer buffers length: primary: %d, secondary: %d.",
                  p_xfer_desc->primary_length,
                  p_xfer_desc->secondary_length);
    NRFX_LOG_DEBUG("Primary buffer data:");
    NRFX_LOG_HEXDUMP_DEBUG(p_xfer_desc->p_primary_buf,
                           p_xfer_desc->primary_length * sizeof(p_xfer_desc->p_primary_buf[0]));
    NRFX_LOG_DEBUG("Secondary buffer data:");
    NRFX_LOG_HEXDUMP_DEBUG(p_xfer_desc->p_secondary_buf,
                           p_xfer_desc->secondary_length * sizeof(p_xfer_desc->p_secondary_buf[0]));

    err_code = twim_xfer(p_cb, (NRF_TWIM_Type *)p_instance->p_twim, p_xfer_desc, flags);
	nrf_delay_ms(100); // edited by me!! solves fatal error issue.
    NRFX_LOG_WARNING("Function: %s, error code: %s.",
                     __func__,
                     NRFX_LOG_ERROR_STRING_GET(err_code));
    return err_code;
}

  • Hi,

    do you have constant power applied, or do you power-up the device when testing?

    You need to wait after VDD has reached 2.85V for 15ms until communication is ready:

    Time to communication ready max 15ms

    according to the datasheet. So you should wait 15ms before calling twi_init() to be safe.

    APP_ERROR_CHECK leads to a system reset when it fails.

    BR

    Olaf

Related