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
  • Hello Martin,

    Does this only happen in the embOS examples? Have you tested on a Nordic SDK example as well?

    when you say Port0 and Port1, are you referring to the P0.xx and P1.xx on the nRF52840 DK?

    Best regards,

    Edvin

  • 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.

Reply
  • 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.

Children
  • 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