This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
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

No NAK reported with TWI driver?

Using nRF5 SDK v11.0.0, I am working on bringing up new hardware based on the nRF52. I started with code that works on the PCA10040 development board in which we connected an FTDI USB-to-I2C chip. When switching to our new hardware board, we found that the slave chip was NAKing memory reads/writes; however, the TWI driver did not return any error indication. I have verified that the data on the SDA line is such that the slave device is sending a NAK (i.e., leaving A = 1) for the data byte.

So, although we have a problem with our device, I don't understand why the TWI driver is not reporting back an error indication. This is very important since the slave chip often uses NAKs to indicate if any bytes are sitting in its queues waiting to be read by the master.

We are using nrf_drv_twi.c in blocking mode. Below is a block of code -- the last line should have some kind of error indication but it does not.

static uint8_t twi_usb_mtp_read_byte(uint16_t address)
{
    uint32_t err_code;
    uint8_t buffer[2];
    uint8_t byte;

    buffer[0] = TWI_USB_MTP_ADDR_CMD;
    err_code = nrf_drv_twi_tx(&m_twi_handle, TWI_USB_GENERAL_CALL_ADDR, buffer, 1, true);
    APP_ERROR_CHECK(err_code);

    buffer[0] = (uint8_t)((address >> 8) & 0x00FF);
    buffer[1] = (uint8_t)(address & 0x00FF);
    err_code = nrf_drv_twi_tx(&m_twi_handle, TWI_USB_SLAVE_ADDR, buffer, 2, false);
    APP_ERROR_CHECK(err_code);

    buffer[0] = TWI_USB_MTP_READ_CMD;
    err_code = nrf_drv_twi_tx(&m_twi_handle, TWI_USB_GENERAL_CALL_ADDR, buffer, 1, true);
    APP_ERROR_CHECK(err_code);

    /* This call SHOULD return an error based on the physical SDA waveform. */
    err_code = nrf_drv_twi_rx(&m_twi_handle, TWI_USB_SLAVE_ADDR, &byte, 1);
    APP_ERROR_CHECK(err_code);

    return byte;
}

void twi_usb_init(void)
{
    uint32_t err_code;

    const nrf_drv_twi_config_t nrf_drv_twi_config = {
        .scl                = TWI_SCL_PIN,
        .sda                = TWI_SDA_PIN,
        .frequency          = NRF_TWI_FREQ_100K,
        .interrupt_priority = APP_IRQ_PRIORITY_LOW
    };

    err_code = nrf_drv_twi_init(&m_twi_handle, &nrf_drv_twi_config, NULL, NULL);
    APP_ERROR_CHECK(err_code);

    nrf_drv_twi_enable(&m_twi_handle);

    /* Example that should read a byte from the slave. */
    uint8_t dump = twi_usb_mtp_read_byte(0);
}

Is this a known problem in the SDK? Is there a patch or workaround available?

Parents
  • Hi,

    I think you should wait a event is done before reading and writing next command. Setup event as below

    ....
    err_code = nrf_drv_twi_init(&m_twi_handle, &nrf_drv_twi_config, twi_handler, NULL);
    APP_ERROR_CHECK(err_code);
    ....
    

    // handler function

    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)
                {
                    m_tx_done = true;
                }
                else if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_RX)
                {
                    m_rx_done = true;
                }
                else{
                	NRF_LOG_PRINTF(NRF_LOG_COLOR_RED "Don't have event type\n");
                }
                break;
            case NRF_DRV_TWI_EVT_ADDRESS_NACK:
            	NRF_LOG_PRINTF(NRF_LOG_COLOR_RED "TWI NRF_DRV_TWI_EVT_ADDRESS_NACK\n");
            	break;
            case NRF_DRV_TWI_EVT_DATA_NACK:
            	NRF_LOG_PRINTF(NRF_LOG_COLOR_RED "TWI NRF_DRV_TWI_EVT_DATA_NACK\n");
                break;
            default:
                break;
        }
    
    }
    

    Good luck!

Reply
  • Hi,

    I think you should wait a event is done before reading and writing next command. Setup event as below

    ....
    err_code = nrf_drv_twi_init(&m_twi_handle, &nrf_drv_twi_config, twi_handler, NULL);
    APP_ERROR_CHECK(err_code);
    ....
    

    // handler function

    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)
                {
                    m_tx_done = true;
                }
                else if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_RX)
                {
                    m_rx_done = true;
                }
                else{
                	NRF_LOG_PRINTF(NRF_LOG_COLOR_RED "Don't have event type\n");
                }
                break;
            case NRF_DRV_TWI_EVT_ADDRESS_NACK:
            	NRF_LOG_PRINTF(NRF_LOG_COLOR_RED "TWI NRF_DRV_TWI_EVT_ADDRESS_NACK\n");
            	break;
            case NRF_DRV_TWI_EVT_DATA_NACK:
            	NRF_LOG_PRINTF(NRF_LOG_COLOR_RED "TWI NRF_DRV_TWI_EVT_DATA_NACK\n");
                break;
            default:
                break;
        }
    
    }
    

    Good luck!

Children
Related