Seeed XIAO BLE Sense direct TWI register access doesn't generate I2C clock

I was using Seeed Xiao BLE Sense as the I2C master and Arduino’s Wire library. The basic I2C communication was working but it could not be stopped for switching the pins for other purpose. So I turned to direct TWI register access hoping I could resolve that problem. But the basic I2C communication could not start with this method. The SCL clock wasn’t toggling after setting TASKS_STARTTX to 1. Here is my code:

#define SCL_PIN 5
#define SDA_PIN 4

void I2C_init(void)
{ 
    NRF_TWI1->ENABLE = 0x00000000;

    NRF_GPIO->PIN_CNF[SCL_PIN] = 
        (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
      | (GPIO_PIN_CNF_DRIVE_S0D1     << GPIO_PIN_CNF_DRIVE_Pos)
      | (GPIO_PIN_CNF_PULL_Pullup    << GPIO_PIN_CNF_PULL_Pos)
      | (GPIO_PIN_CNF_INPUT_Connect  << GPIO_PIN_CNF_INPUT_Pos)
      | (GPIO_PIN_CNF_DIR_Input      << GPIO_PIN_CNF_DIR_Pos);    

    NRF_GPIO->PIN_CNF[SDA_PIN] = 
        (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
      | (GPIO_PIN_CNF_DRIVE_S0D1     << GPIO_PIN_CNF_DRIVE_Pos)
      | (GPIO_PIN_CNF_PULL_Pullup    << GPIO_PIN_CNF_PULL_Pos)
      | (GPIO_PIN_CNF_INPUT_Connect  << GPIO_PIN_CNF_INPUT_Pos)
      | (GPIO_PIN_CNF_DIR_Input      << GPIO_PIN_CNF_DIR_Pos); 	

    NRF_TWI1->PSELSCL=SCL_PIN;
    NRF_TWI1->PSELSDA=SDA_PIN;

    NRF_TWI1->FREQUENCY = 0x01980000;   //100 KHz /
    //NRF_TWI1->FREQUENCY = 0x04000000;     //250 Khz
    //NRF_TWI1->FREQUENCY = 0x06680000;     //400 Khz

    NRF_TWI1->ENABLE = 0x00000005;
}

void I2C_disable(void)
{
    NRF_TWI1->ENABLE = 0x00000000;
}


void I2C_startTX(unsigned char addr) 
{ 
    cprintf("I2C_startTX addr: 0x%x 0x%x\n", &(NRF_TWI1->ADDRESS), addr);
    NRF_TWI1->ADDRESS=addr;
    NRF_TWI1->TASKS_STARTTX=1; 
}

I tried both TWI0 and TWI1, all 3 different clock speeds. From a logic analyzer, the SDA start signal (high->low) was there, but SCL was not there.

To be clear, the above experiments were performed with Arduino. Any help will be highly appreciated.

Hi there,
Why is this?
is that the Clock pin?
GL :slight_smile: PJ

I found these GPIO settings from another post and hoping it could fix the problem. With or without these settings, my I2C behaved the same.

Yikes,
hMMM, smh…
Can you post the code and the compiler output?
Direct writing, almost never works AFAIK, unless it’s for a temp gauge or something with no data or need of High speed(SPI is better). What is the slave device?
Clock only stops or stretches if the Slave is having an issue.
That wire lib is suspicious IMO.
GL :slight_smile: PJ

Even if there is no I2C slave but only a logic analyzer hooked on I2C, no I2C clock was generated. So I don’t think the I2C slave matters at this point.

OK, well I’m confused , I thought the 9th Clock pulse that turns the conversation around comes from the slave clocking in the previous 8.
I don’t think the process is correct…
Your close , I’m sure you’ll get it.
HTH
GL :slight_smile: PJ

My memory say’s this: YMMV
A short recap from what I remember:
The master always controls the clock line, but the data direction can vary.
Master first sends and 8-bit byte, which has 7 address bits and a read / write bit.
The ninth bit is an "acknowledge bit, which is sent by the slave, on a clock pulse generated by the master.
After that the data direction depends, on whether the master wants to send or receive data.
Each byte is followed up by an acknowledge bit, that goes in the other direction.
Except for the last byte. That byte is not acknowledged, which indicates the end of a data transfer.

I2C clock is generated by the master. No matter the slave exists or not, the master should generate the clock. I didn’t see it in my case.

1 Like