Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

TWIM not doing anything although TWIM0 registers look correct

I'm trying to get the TWIM peripheral up and running on a custom board with an NRF52810 running SDK15 and S112.

My board is properly advertising, and publishing our custom service and characteristics.

I have an impossible schedule to meet, and have been bumping my head against the TWIM driver all day.  I suspect that I am doing something totally stupid, but can't figure it out...

The TWIM instance initializes and enables without error.  It will run through the nrfx_twim_xfer function with no error in non-blocking mode, but the handler never gets called, and the TWIM never starts the driver (verified with scope and TWIM0 register settings.  In blocking mode, it just never exits and still nothing comes out the bus.  In any case I never get an I2C error, I just get nothing happening.

If I stop the code execution a little after the twim_xfer call (the transaction should have completed long ago) then I will see the following non-zero values in TWIM0:

EVENTS_TXSTARTED 0x00000001                                          (I assume this means that I requested a transmit event)

SHORTS                        LASTTX_STOP is Enabled (all others disabled)

INTEN                             STOPPED and ERROR are enabled (all other disabled)

ENABLE                          0x6 ENABLED (my understanding is that this means twim is running with easy dma enabled)

PSEL                               SCL 0x5, SDA 0x6 (correct pins selected)

FREQUENCY                  0x01980000  (This should be 100 kHz)

TXD                                 PTR 0x200032D0 (address of my buffer), MAXCNT 0x2 (correct number of bytes that I am trying to send), AMOUNT 0 (this is my problem!)

ADDRESS                      0x78 (correct slave address for the device I am trying to talk to)

Any help would be appreciate.  My schedule for production is impossible and I am already behind.  Relevant TWI code is below(sorry for calling it I2C in it).  The end of i2c_init() is where I am testing the interface.  I tried testing elsewhere as well, but moved it here for brevity and convenience.

Thanks,

-F

#define I2C_INSTANCE_ID               0
                 
static bool volatile i2cXferComplete = false;
static uint8_t       i2cState        = I2C_IDLE;
static uint8_t       i2cPending      = 0x00;

static const nrfx_twim_t i2c = NRFX_TWIM_INSTANCE(I2C_INSTANCE_ID);

void i2c_handler(nrfx_twim_evt_t const *event, void *context)
{
  if(event->type == NRFX_TWIM_EVT_DONE)
  {
    i2cXferComplete = true;
    /* BOGWTF -- ADD PENDING CODE FOR AZOTEQ AND FUEL GAUGE */
  }
}

bool i2c_complete(void)
{
  return i2cXferComplete;
}

void i2c_set_state(uint8_t state)
{
  i2cState = state;
}

uint8_t i2c_get_state(void)
{
  return i2cState;
}

void i2c_init(void)
{
  ret_code_t               error;
  const nrfx_twim_config_t config = 
  {                                              \
    .frequency          = NRF_TWIM_FREQ_100K,    \
    .scl                = I2C_SCL_PIN,           \
    .sda                = I2C_SDA_PIN,           \
    .interrupt_priority = APP_IRQ_PRIORITY_HIGH, \
    .hold_bus_uninit    = false,                 \
  };
  
  uint8_t testData[5]         = { 0x4A, 0x07, 0x00, 0x00, 0x00 };
  uint8_t testLength          = 2;
    
  error = nrfx_twim_init(&i2c, &config, i2c_handler, NULL);
//  error = nrfx_twim_init(&i2c, &config, NULL, NULL);
  APP_ERROR_CHECK(error);
  
  nrfx_twim_enable(&i2c);
  
  const nrfx_twim_xfer_desc_t test = NRFX_TWIM_XFER_DESC_TX(I2C_LED_ADDRESS, testData, testLength);
  error = nrfx_twim_xfer(&i2c, &test, 0);
  APP_ERROR_CHECK(error);
  while(1);
}

Parents
  • Upon further investigation, it appears that the NRF52 is pulling the SDA line high even after I explicitly tell it to go low with an nrf_gpio_pin_clear() prior to its assignment as an I2C pin.  The P0 registers confirm that the SDA line is set to output low, but it is reading high.  I know that it is the NRF52 chip pulling the line high since if I do an erase all and remove the external pull up then the line will fall low--therefore it isn't something else on the line pulling it high.  

    I'm using the template example project that has so far only been modified to add my service, characteristics, and scan response.  Here's my main functions and custom boards file.  I define LEDs as 0 so I don't think it should be trying to flip any...

    int main(void)
    {
        bool erase_bonds;
    
        // Initialize.
        log_init();
        timers_init();
        buttons_leds_init(&erase_bonds);
        power_management_init();
        ble_stack_init();
        gap_params_init();
        gatt_init();
        services_init();
        advertising_init();
        conn_params_init();
        peer_manager_init();
    
        // Start execution.
        NRF_LOG_INFO("Template example started.");
        application_timers_start();
    
        i2c_init();
    //    spi_init();
    
        led_init();
        
        advertising_start(erase_bonds);
    
        // Enter main loop.
        for (;;)
        {
            idle_state_handle();
        }
    }

    #ifndef __SP_2042_H_
    #define __SP_2042_H_
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    #include "nrf_gpio.h"
    
    #define NRF_NUM_GPIO_PINS        32
    
    #define LED_RESET_PIN            0
    #define BUTTON_PIN               1
    #define SPI_SCK_PIN              2
    #define DISPLAY_ERASE_PIN        3
    #define SPI_MOSI_PIN             4
    #define I2C_SCL_PIN              5
    #define I2C_SDA_PIN              6
    #define TOUCH_READY_PIN          7
    #define TOUCH_RESET_PIN          8
    #define TOUCH_WAKE_PIN           9
    #define TOUCH_PGM_PIN            10
    #define DISPLAY_ACTIVE_PIN       11
    #define SPI_MISO_PIN             12
    #define DISPLAY_CS_PIN           13
    #define DISPLAY_BOOT_TX          14
    #define DISPLAY_RESET_PIN        15
    #define DISPLAY_BOOT_RX          16
    #define ENABLE_5V_PIN            17
    #define NFC_CS_PIN               18
    #define NFC_ISTAT_PIN            19
    #define NFC_POWER_DOWN_PIN       20
    #define UNUSED_P21_PIN           21
    #define UNUSED_P22_PIN           22
    #define HWID_BIT0_PIN            23
    #define HWID_BIT1_PIN            24
    #define HWID_BIT2_PIN            25
    #define HWID_BIT3_PIN            26
    #define HWID_BIT4_PIN            27
    #define HWID_BIT5_PIN            28
    #define HWID_BIT6_PIN            29
    #define HWID_BIT7_PIN            30
    #define UNUSED_P31_PIN           31
    
    // Button config
    #define BUTTONS_NUMBER           1
    #define BUTTON_START             BUTTON_PIN
    #define BUTTON_STOP              BUTTON_PIN
    #define BUTTON_PULL              NRF_GPIO_PIN_NOPULL
    #define BUTTONS_ACTIVE_STATE     0
    #define BUTTONS_LIST             { BUTTON_PIN }
    
    #define BSP_BUTTON_0             BUTTON_PIN
    
    #define LEDS_NUMBER              0
    
    // Uart configuration for testing
    #define RX_PIN_NUMBER            UART_PIN_DISCONNECTED
    #define TX_PIN_NUMBER            UART_PIN_DISCONNECTED
    #define CTS_PIN_NUMBER           UART_PIN_DISCONNECTED
    #define RTS_PIN_NUMBER           UART_PIN_DISCONNECTED
    
    #ifdef __cplusplus
    }
    #endif

    Modified i2c_init() functions showing explicit setting of gpio values.  After both nrf_gpio_pin_clear() calls (I put a breakpoint on the call to nrfx_twim_init()), the SDA line is still high...

    void i2c_init(void)
    {
      ret_code_t               error;
      const nrfx_twim_config_t config = 
      {                                              \
        .frequency          = NRF_TWIM_FREQ_100K,    \
        .scl                = I2C_SCL_PIN,           \
        .sda                = I2C_SDA_PIN,           \
        .interrupt_priority = APP_IRQ_PRIORITY_HIGH, \
        .hold_bus_uninit    = false,                 \
      };
      
      uint8_t testData[5]         = { 0x4A, 0x07, 0x00, 0x00, 0x00 };
      uint8_t testLength          = 2;
      
      nrf_gpio_cfg(5,                                                    \
                                             NRF_GPIO_PIN_DIR_OUTPUT,     \
                                             NRF_GPIO_PIN_INPUT_CONNECT, \
                                             NRF_GPIO_PIN_NOPULL,        \
                                             NRF_GPIO_PIN_S0S1,          \
                                             NRF_GPIO_PIN_NOSENSE);
      nrf_gpio_cfg(6,                                                    \
                                             NRF_GPIO_PIN_DIR_OUTPUT,     \
                                             NRF_GPIO_PIN_INPUT_CONNECT, \
                                             NRF_GPIO_PIN_NOPULL,        \
                                             NRF_GPIO_PIN_S0S1,          \
                                             NRF_GPIO_PIN_NOSENSE);
    
      nrf_gpio_pin_set(5);
      nrf_gpio_pin_set(6);
    
      nrf_gpio_pin_clear(5);
      nrf_gpio_pin_clear(6);
      
      error = nrfx_twim_init(&i2c, &config, i2c_handler, NULL);
    //  error = nrfx_twim_init(&i2c, &config, NULL, NULL);
      APP_ERROR_CHECK(error);
      
      nrfx_twim_enable(&i2c);
      
      const nrfx_twim_xfer_desc_t test = NRFX_TWIM_XFER_DESC_TX(I2C_LED_ADDRESS, testData, testLength);
        
      error = nrfx_twim_xfer(&i2c, &test, 0);
      APP_ERROR_CHECK(error);
      while(1);

  • I finally figured out what the problem was.  The NRF_LOG uart (which is enabled by default and whose existence I was unaware of) was overriding my SDA pin setting.  As soon as the "log_init()" function was called my SDA jumped high after I had explicitly set it low.

    After disabling the NRF_LOG functionality my I2C code is now appropriately entering the handler function.  I do not know if my I2C driver will work, but the issue mentioned above is officially rectified.

    Thanks.

Reply
  • I finally figured out what the problem was.  The NRF_LOG uart (which is enabled by default and whose existence I was unaware of) was overriding my SDA pin setting.  As soon as the "log_init()" function was called my SDA jumped high after I had explicitly set it low.

    After disabling the NRF_LOG functionality my I2C code is now appropriately entering the handler function.  I do not know if my I2C driver will work, but the issue mentioned above is officially rectified.

    Thanks.

Children
No Data
Related