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

twi_master_clear_bus fails

Calling twi_master_clear_bus() always returns bus_clear = FALSE. The IF statement is always FALSE even though both SDA and SCL measure high. All 18 SCL's occur in the ELSE but it fails, also. This has worked in the past but recently began failing every time. I tried other previously working firmware versions and they all fail, also. No known events have occurred to cause a hardware failure.

static bool twi_master_clear_bus(void)

{ uint32_t twi_state; bool bus_clear; uint32_t clk_pin_config; uint32_t data_pin_config;

// Save and disable TWI hardware so software can take control over the pins.
twi_state        = NRF_TWI1->ENABLE;
NRF_TWI1->ENABLE = TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos;

clk_pin_config =
    NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER];
NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER] =
    (GPIO_PIN_CNF_SENSE_Disabled  << GPIO_PIN_CNF_SENSE_Pos)
  | (GPIO_PIN_CNF_DRIVE_S0D1    << GPIO_PIN_CNF_DRIVE_Pos)    // STD0, DISC1
  | (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos)
  | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
  | (GPIO_PIN_CNF_DIR_Output    << GPIO_PIN_CNF_DIR_Pos);

data_pin_config =
    NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_DATA_PIN_NUMBER];
NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_DATA_PIN_NUMBER] =
    (GPIO_PIN_CNF_SENSE_Disabled  << GPIO_PIN_CNF_SENSE_Pos)
  | (GPIO_PIN_CNF_DRIVE_S0D1    << GPIO_PIN_CNF_DRIVE_Pos)    // STD0, DISC1
  | (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos)
  | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
  | (GPIO_PIN_CNF_DIR_Output    << GPIO_PIN_CNF_DIR_Pos);

TWI_SDA_HIGH();
TWI_SCL_HIGH();
TWI_DELAY();

if ((TWI_SDA_READ() == 1) && (TWI_SCL_READ() == 1))
{
    bus_clear = true;
}
else
{
    uint_fast8_t i;
    bus_clear = false;

    // Clock max 18 pulses worst case scenario(9 for master to send the rest of command and 9
    // for slave to respond) to SCL line and wait for SDA come high.
    for (i=18; i--;)
    {
        TWI_SCL_LOW();
        TWI_DELAY();
        TWI_SCL_HIGH();
        TWI_DELAY();

        if (TWI_SDA_READ() == 1)
        {
            bus_clear = true;
            break;
        }
    }
}

NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER] = clk_pin_config;
NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_DATA_PIN_NUMBER]  = data_pin_config;

NRF_TWI1->ENABLE = twi_state;

return bus_clear;

}

  • Hi Tomg,

    As I understand, when the function clock out 18 clocks to clear SDA, TWI_SDA_READ() return 0 ? And SDA only change to high after that ?

    It would be interesting the logic analyzer trace to see why it changes from 0 to 1 only after the function returns.

  • Hung Bui,

    Not exactly. After the 18 clocks TWI_SDA_READ() always returns 0 so bus_clear is 0 and the initialization fails. I just found that if TWI_SDA_HIGH() is called before twi_master_init() the initialization passes. But the peripheral (accelerometer) returns bad data (x always 0x10, y always 0x30, z always 0x50). Maybe this means the accelerometer is not responding properly and has failed? Past experience shows that the hardware is seldom the problem - the firmware usually the culprit.

  • You meant that " both SDA and SCL measure high" ? But TWI_SDA_READ() returns 0 ? I don't know about your accelerometer sensor, just want to clarify twi_master_clear_bus() should work as it should. (You can try to test with open pins)

  • When I said "both SDA and SCL measure high" I meant that when breaking in debug mode just before the if statement both SDA and SCL are high when viewed with a scope. Executing the if statement always skips to the else. I just found that if TWI_SDA_HIGH() and TWI_SCL_HIGH are called in main() both SDA and SCL measure high (scope) just before the if statement. But if these commands are removed the TWI_SDA_HIGH() and TWI_SCL_HIGH() in twi_master_ Does "should work as it should" mean that twi_master_clear_bus() should work without any peripherals tied to SDA and SCL? If this is true does this imply the nrF51822 is bad or might the accelerometer be pulling the bus? The PCB is very small so disconnecting SDA and SCL between the accelerometer and nrF51822 is very difficult.

  • I added TWI_SDA_READ() and TWI_SCL_READ() just before the if statement for testing. Found that if TWI_SDA_HIGH() and TWI_SCL_HIGH() are called in main() both SDA and SCL are read as high. But if these commands are removed from main() both SDA and SCL are read as low even though TWI_SDA_HIGH() and TWI_SCL_HIGH() are in twi_master_clear_bus just before the if statement.

    main()
    
          TWI_SDA_HIGH();						//+++ REQUIRED SO TWI_MASTER_INIT() PASSES
          TWI_SCL_HIGH();						//+++ REQUIRED SO TWI_MASTER_INIT() PASSES
    
          if (!twi_master_init())           // configure SCK, SDA pins
              while(1);                       // stay here if initialization fails
    
    twi_master_clear_bus()
    
        TWI_SDA_HIGH();
        TWI_SCL_HIGH();
        TWI_DELAY();
    
        sda = TWI_SDA_READ();
        scl = TWI_SCL_READ();
        if ((TWI_SDA_READ() == 1) && (TWI_SCL_READ() == 1))
        {
            bus_clear = true;
        }
        else
    
Related