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

TWI sends only the first read access

I have been debugging the TWI master of nRF52832 for a few days now and I have one more problem, which is very weird. For some reason, the master sends only the first read access. It seems that the TWI master is in a certain state where it cannot send any subsequent read accesses.

I am using nRF52 DK + nRF5 (16.0.0) + SES. I am using the TWI master at the register level without any high level libraries. I have created a simple test case to recreate the issue:

#include <stdint.h>
#include <string.h>

#include "nrf_delay.h"
#include "nrf.h"
#include "nrf_gpio.h"

#define I2C_SCL_PIN 11
#define I2C_SDA_PIN 12

void i2c_init (void)
{
    nrf_gpio_cfg_input(I2C_SCL_PIN,NRF_GPIO_PIN_PULLUP); 
    nrf_gpio_cfg_input(I2C_SDA_PIN,NRF_GPIO_PIN_PULLUP); 

    NRF_TWI1->FREQUENCY = 0x01980000; 

    NRF_TWI1->PSELSCL   = I2C_SCL_PIN;
    NRF_TWI1->PSELSDA   = I2C_SDA_PIN;
    
    NRF_TWI1->ADDRESS   = 0x48;       

    NRF_TWI1->ENABLE    = 0x00000005; 
}

void i2c_start_tx (void)
{
    NRF_TWI1->TASKS_STARTTX = 1;
}

void i2c_start_rx (void)
{
    NRF_TWI1->TASKS_STARTRX = 1;
}

void i2c_stop (void)
{
    NRF_TWI1->TASKS_STOP = 1;
}

// ----------------------------------------------------------------------------------------------------
// I2C Write
// ----------------------------------------------------------------------------------------------------
void i2c_write (uint8_t data)
{
    NRF_TWI1->TXD = data;

    while (NRF_TWI1->EVENTS_TXDSENT == 0)  { }

    NRF_TWI1->EVENTS_TXDSENT = 0;
}

// ----------------------------------------------------------------------------------------------------
// I2C Read
// ----------------------------------------------------------------------------------------------------
uint8_t i2c_read (uint8_t ack)
{
    uint8_t data;

    if (ack == 0) {
        NRF_TWI1->TASKS_STOP = 1;
    }
    
    while (NRF_TWI1->EVENTS_RXDREADY == 0) { }

    data = NRF_TWI1->RXD;

    return data;
}

// ----------------------------------------------------------------------------------------------------
// Read device id
// ----------------------------------------------------------------------------------------------------
void read_device_id (void)
{
    uint8_t data;

    i2c_start_tx();
    i2c_write(0x0F); 

    i2c_start_rx();
    data = i2c_read(1);
    data = i2c_read(0);
}

int main (void)
{
    i2c_init();

    while (1) {
        nrf_delay_ms(1000);

        read_device_id();
    }

    return 0;
}

When I debug the issue with a logic analyzer, the first read access works perfectly:

However, the subsequent read accesses are totally ignored:

As you can see, the write accesses are always sent and even the stop condition is also sent. However, the read access is totally ignored. It is very unlikely that this might be related to the sensor, because the first read access works perfectly and the sensor responds to all accesses normally.

I assume that there is somewhere a register that I must clear or I must wait for something. However, I am not sure what that might be. I have checked the register map of the TWI very carefully and I cannot find anything that might explain the issue.

Parents Reply Children
No Data
Related