cancel
Showing results for 
Search instead for 
Did you mean: 

I2C Slave Wrong Read Count (NUCLEO-U5A5ZJ-Q)

WhoIsJohnGalt
Associate II

Hey there :)

I am having trouble running the nucleo (NUCLEO-U5A5ZJ-Q) as an I2C slave where read/write sizes are unknown (only known by master)

For the configuration I am using CubeMX and most of the time the slave is working quite fine. However sometimes (1 in 100), the slave transmit count (how many bytes have been read by the master) is not correct (one off - although the master reads the correct amount of data (see analyzer picture)) 

My code structure:

// First run the cubeMX init code and enable listening
MX_I2C2_Init();
HAL_I2C_EnableListen_IT(hi2c);

// When the slave address maches, the write or read HAL function is called
void HAL_I2C_AddrCallback(I2C_HandleTypeDef* hi2c, uint8_t TransferDirection, uint16_t /*AddrMatchCode*/) {
  if (TransferDirection == I2C_DIRECTION_TRANSMIT) {
    slave_match_master_write = true;
    HAL_I2C_Slave_Seq_Receive_IT(hi2c, buffer_, sizeof(buffer_), I2C_FIRST_FRAME);
  } else {
    slave_match_master_write = false;
    HAL_I2C_Slave_Seq_Transmit_IT(hi2c, buffer_, sizeof(buffer), I2C_LAST_FRAME);
  }
}

void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef* hi2c) {
  if (slave_match_master_write == true) {
     int32_t slave_rx_cnt = sizeof(buffer_) - hi2c->XferSize; // Value always correct
  } else {
     int32_t slave_tx_cnt = sizeof(buffer_) - hi2c->XferSize - 1; // Why -1?
  }
  HAL_I2C_EnableListen_IT(hi2c);
}

// This function gets called once every 100 frames (strange)
void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef* /*hi2c*/) {
  // empty
}

// This function gets never called (why? - not that i need it)
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef* /*hi2c*/) {
  // empty
}

// The error callback gets called each time as expechted (master NAK)
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef* hi2c) {
  uint32_t error = HAL_I2C_GetError(hi2c);
}

 

In line 20 I added the -1 because otherwise the slave_tx_cnt would be one to much (except for the one in 100 time when its one too small). So it seems to me that there is somehing off.

Does aynone has an idea what I am doing wrong?
Thanks for any hint.

Regards,
Alexander

 

Side note: Before that i tried it with DMA (same issue with the read size), but lets now focus on Interrupt Mode.
I have not tried it jet in blocking mode...

 

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
WhoIsJohnGalt
Associate II

I have located the problem and found a solution.

As already said in the post occasionally the callback HAL_I2C_SlaveTxCpltCallback(...)
function gets called. Obviously this is the case when the master reads sizeof(buffer_)
bytes (Which is the max size specified in the slave). Then somehow the computation is off by one. 

int32_t slave_tx_cnt = sizeof(buffer_) - hi2c->XferSize - 1; // Why -1?

 

Solution:

Making the slave buffer bigger such that the master will never read  the slaves max size. So the HAL_I2C_SlaveTxCpltCallback will never be called because the master NAKs always before the max tx size specified by the slave is reached.


Why I need the -1 is still unclear to me (does the restart byte for the read also count? that would not make sense to me...).

Thank you

View solution in original post

3 REPLIES 3
TDK
Guru

When the slave is sending data, the master is the receiver and the master is the one ACKing or NACKing data to indicate the end of the transfer.

In your plot, I see a write of 4 bytes, then a write of 2 bytes with a repeated start and a read of 2 bytes (with a clock stretch duration), the last of which is NACKd. I'm not sure what this is supposed to show or what is wrong/unexpected about it. Should the master have received more than 2 bytes? or does the slave think it send more/less?

If you feel a post has answered your question, please click "Accept as Solution".

Thanks for your reply.

The picture shows that on the scope everything looks fine (also for the master). In the second frame the master reads 2 bytes from the slave but the slave_tx_cnt variable indicates that only one byte has been read, which is wrong.
But this only happens 1 in 100 times that the slave_tx_cnt is off by one (too small).
Is the way how the slave_tx_cnt is calculated correct (line 20)? Why do I need the -1? (I put it there otherwise the slave_tx_cnt will bee too big 99 times out of 100)

WhoIsJohnGalt
Associate II

I have located the problem and found a solution.

As already said in the post occasionally the callback HAL_I2C_SlaveTxCpltCallback(...)
function gets called. Obviously this is the case when the master reads sizeof(buffer_)
bytes (Which is the max size specified in the slave). Then somehow the computation is off by one. 

int32_t slave_tx_cnt = sizeof(buffer_) - hi2c->XferSize - 1; // Why -1?

 

Solution:

Making the slave buffer bigger such that the master will never read  the slaves max size. So the HAL_I2C_SlaveTxCpltCallback will never be called because the master NAKs always before the max tx size specified by the slave is reached.


Why I need the -1 is still unclear to me (does the restart byte for the read also count? that would not make sense to me...).

Thank you