I2C_RTOS_Transfer does not send Stop if dataSize is 0

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

I2C_RTOS_Transfer does not send Stop if dataSize is 0

Jump to solution
742 Views
beng_
Contributor III

I've found that I2C_RTOS_Transfer does not send a Stop if dataSize is 0.

Am I doing something wrong or is there a bug is the API?

I'm using a Sensirion SHT 21 (datasheet).

One of the command available is to send a soft reset (easily explained via screen shot from the data sheet).

pastedImage_3.png

My I2C is configured as follows:

status_t status;
i2c_master_config_t i2c_master_config;
uint32_t i2c_source_clock_hz;

I2C_MasterGetDefaultConfig(&i2c_master_config);
i2c_master_config.baudRate_Bps = 10000;
i2c_master_config.enableMaster = false;

i2c_source_clock_hz = CLOCK_GetFreq(kCLOCK_CoreSysClk);

CLOCK_EnableClock(kCLOCK_I2c0);
status = I2C_RTOS_Init(&i2c_rtos_handle, I2C0, &i2c_master_config,
                       i2c_source_clock_hz);

/* Disable I2C module and gate its clock */

I'm sending a soft reset in the following manner:

static void soft_reset_sht(void)
{
  i2c_master_transfer_t i2c_soft_reset;

  i2c_soft_reset.slaveAddress = SENSIRION_I2C_ADDRESS;
  i2c_soft_reset.direction = kI2C_Write;
  i2c_soft_reset.subaddress = SHT_SOFT_RESET;
  i2c_soft_reset.subaddressSize = 1;
  i2c_soft_reset.data = NULL;
  i2c_soft_reset.dataSize = 0;
  i2c_soft_reset.flags = kI2C_TransferDefaultFlag;


  I2C_Enable(I2C0, true);

  I2C_RTOS_Transfer(&i2c_rtos_handle, &i2c_soft_reset, CEIL_US_TO_TICKS(MS_TO_US(100)) );

  // Disable I2C hardware
  I2C_Enable(I2C0, false);

  return;
}

This doesn't' send a stop command and leaves SCL low:

pastedImage_12.png

If I add in some dummy data and send a send it (i.e. i2c_soft_reset.dataSize is not set to zero) the an I2C stop is correctly sent.

static void soft_reset_sht(void)
{
  i2c_master_transfer_t i2c_soft_reset;
  uint8_t local_u8_buffer[1];

  i2c_soft_reset.slaveAddress = SENSIRION_I2C_ADDRESS;
  i2c_soft_reset.direction = kI2C_Write;
  i2c_soft_reset.subaddress = SHT_SOFT_RESET;
  i2c_soft_reset.subaddressSize = 1;
  i2c_soft_reset.data = local_u8_buffer;
  i2c_soft_reset.dataSize = 1;
  i2c_soft_reset.flags = kI2C_TransferDefaultFlag;


  I2C_Enable(I2C0, true);

  I2C_RTOS_Transfer(&i2c_rtos_handle, &i2c_soft_reset, CEIL_US_TO_TICKS(MS_TO_US(100)) );


  I2C_Enable(I2C0, false);

  return;
}

This gives

pastedImage_9.png

Labels (1)
Tags (2)
0 Kudos
1 Solution
511 Views
visakhanc
Contributor III

Hi Ben,

For the I2C driver to work properly (ie, send stop to complete transfer), at least 1 data byte need to be there, when using a subaddress. So, for transmitting only 1 data byte (as in your case), use data to send the byte and give no subaddress. Like this:

  i2c_soft_reset.slaveAddress = SENSIRION_I2C_ADDRESS;
  i2c_soft_reset.direction = kI2C_Write;
  i2c_soft_reset.subaddress = 0;
  i2c_soft_reset.subaddressSize = 0;
  i2c_soft_reset.data = SHT_SOFT_RESET;
  i2c_soft_reset.dataSize = 1;
  i2c_soft_reset.flags = kI2C_TransferDefaultFlag;

 

Regards,

Visakhan

View solution in original post

0 Kudos
1 Reply
512 Views
visakhanc
Contributor III

Hi Ben,

For the I2C driver to work properly (ie, send stop to complete transfer), at least 1 data byte need to be there, when using a subaddress. So, for transmitting only 1 data byte (as in your case), use data to send the byte and give no subaddress. Like this:

  i2c_soft_reset.slaveAddress = SENSIRION_I2C_ADDRESS;
  i2c_soft_reset.direction = kI2C_Write;
  i2c_soft_reset.subaddress = 0;
  i2c_soft_reset.subaddressSize = 0;
  i2c_soft_reset.data = SHT_SOFT_RESET;
  i2c_soft_reset.dataSize = 1;
  i2c_soft_reset.flags = kI2C_TransferDefaultFlag;

 

Regards,

Visakhan

0 Kudos