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

TWI error when SDA on Port 1

Hi everyone,

I'm using a Si7051 I²C temperature sensor connected to a nRF52840 and I found some very weird behavior of the TWIM module. Firmware-wise I'm using the mbed framework with the blocking I²C functions.

Writing data to the slave works fine, but reading data from a slave results in the nRF's SDA pin trying to output a low-impedance high level and therefore blocking further I²C communications (6mA measured between slave and nRF). Bluetooth seems unaffected by this short and continues to operate (meaning the softdevice is active, I've read some reports that some I²C functions depend on the SD)

What's strange is that this only ever happens with the SDA pin on Port 1.

SDA and SCL both on Port0: works
SDA on Port0 and SCL on Port1: works
SDA on Port1, SCL on either: fault

I didn't find any info relating to the TWIM in the errata. If possible, I'd like to avoid ordering a new run of prototype PCBs.

Cheers,
Martin

Parents Reply Children
  • Hi Edvin,

    yes, I'm referring to P0.xx and P1.xx. Further testing showed that this only occurs with mbed, other frameworks seem to work fine with the same hardware. I'll take this to their issue tracker.

    Best,

    Martin

  • Hi Edvin,

    I've switched from mbed back to the plain nRF framework and I'm getting the same error again (Adafruit's Arduino implementation worked).

    relevant code:

    void si705_request()
    {
    	uint8_t reg[1] = {SI_CMD_SINGLE};
    
    	ret_code_t err_code = nrf_drv_twi_tx(&m_twi, SI_ADDR, &reg, sizeof(reg), false);
    	APP_ERROR_CHECK(err_code);
    }
    
    void si705_read()
    {
    	ret_code_t err_code = nrf_drv_twi_rx(&m_twi, SI_ADDR, m_twi_data, sizeof(m_twi_data));
    	APP_ERROR_CHECK(err_code);
    }
    
    void si705x_init()
    {
    	ret_code_t err_code;
    
    	const nrf_drv_twi_config_t twi_lm75b_config = {
    		.scl = 32 + 15,
    		.sda = 32 + 13,
    		.frequency = NRF_DRV_TWI_FREQ_100K,
    		.interrupt_priority = APP_IRQ_PRIORITY_HIGH,
    		.clear_bus_init = false,
    		.hold_bus_uninit = false
    		};
    
    	err_code = nrf_drv_twi_init(&m_twi, &twi_lm75b_config, twi_handler, NULL);
    	APP_ERROR_CHECK(err_code);
    
    	nrf_drv_twi_enable(&m_twi);
    }

    scope 'screenshot':

    you can see that SDA (blue) is held at VCC/2 during the ACK bit because both the NRF and the sensor are trying to drive the pin high/low, resulting in a short.

  • In case anyone runs into the same issue: I 'solved' it by initializing the pins myself

    	NRF_GPIO_Type *p_gpio = ((NRF_GPIO_Type*)0x50000300);
    	p_gpio->PIN_CNF[13] = ((uint32_t)GPIO_PIN_CNF_DIR_Input        << GPIO_PIN_CNF_DIR_Pos)
    						| ((uint32_t)GPIO_PIN_CNF_INPUT_Connect    << GPIO_PIN_CNF_INPUT_Pos)
    						| ((uint32_t)GPIO_PIN_CNF_PULL_Pullup      << GPIO_PIN_CNF_PULL_Pos)
    						| ((uint32_t)GPIO_PIN_CNF_DRIVE_S0D1       << GPIO_PIN_CNF_DRIVE_Pos)
    						| ((uint32_t)GPIO_PIN_CNF_SENSE_Disabled   << GPIO_PIN_CNF_SENSE_Pos);
    
    	p_gpio->PIN_CNF[15] = ((uint32_t)GPIO_PIN_CNF_DIR_Input        << GPIO_PIN_CNF_DIR_Pos)
    						| ((uint32_t)GPIO_PIN_CNF_INPUT_Connect    << GPIO_PIN_CNF_INPUT_Pos)
    						| ((uint32_t)GPIO_PIN_CNF_PULL_Pullup      << GPIO_PIN_CNF_PULL_Pos)
    						| ((uint32_t)GPIO_PIN_CNF_DRIVE_S0D1       << GPIO_PIN_CNF_DRIVE_Pos)
    						| ((uint32_t)GPIO_PIN_CNF_SENSE_Disabled   << GPIO_PIN_CNF_SENSE_Pos);
    There must be some issue with the SDK, as nrf_drv_twi_init should take care of this already.

    I'll mark this as solved as soon as the SDK is fixed.

Related