Skip to main content
Visitor II
February 4, 2025
Solved

STM3G0B1 as I2C SLAVE with NoStretchMode. How to handle HAL_I2C_Slave_Seq_Transmit_IT?

  • February 4, 2025
  • 3 replies
  • 956 views

I'm using STM3G0B1 as I2C SLAVE device with NVIC+NoStretchMode since I2C Master device doesn't support the clock stretching.

When HAL_I2C_AddrCallback is called (Read request from Master device), HAL_I2C_Slave_Seq_Transmit_IT seems not working because 0xFF is transmitted, not the expected value held by I2C_REGISTERS.
I guess 0xFF is the default value with NoStretchMode to respond immediately to the request.
How to resolve this issue? Is there a way to transmit the correct data with NoStretchMode for Read request?

 

 

hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_ENABLE;

...

void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode) {
 if (TransferDirection == I2C_DIRECTION_TRANSMIT) { 
 if (HAL_I2C_Slave_Seq_Receive_IT(hi2c, &regAddr, 1, I2C_FIRST_FRAME) != HAL_OK) {
 DBG_LOG("%s(%d): Error Receive Data", __func__, __LINE__);
 return;
 }
 } else {
 if (HAL_I2C_Slave_Seq_Transmit_IT(hi2c, I2C_REGISTERS + regAddr, 1, I2C_FIRST_FRAME) != HAL_OK) {
 DBG_LOG("%s(%d): Error Transmit Data", __func__, __LINE__);
 return;
 }
 }
}

 

 

 

    This topic has been closed for replies.
    Best answer by ShoH

    I was able to resolve this by presetting the value to TXDR in HAL_I2C_SlaveRxCpltCallback.

    void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c) {
     hi2c->Instance->TXDR = regAddr; 
    }

     

    3 replies

    Technical Moderator
    February 4, 2025

    Hello @ShoH 

    You are setting a receive process when "TransferDirection == I2C_DIRECTION_TRANSMIT".

    Please try with the snippet code below:

    hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_ENABLE;
    
    ...
    
    void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode) {
     if (TransferDirection != I2C_DIRECTION_TRANSMIT) { 
     if (HAL_I2C_Slave_Seq_Receive_IT(hi2c, &regAddr, 1, I2C_FIRST_FRAME) != HAL_OK) {
     DBG_LOG("%s(%d): Error Receive Data", __func__, __LINE__);
     return;
     }
     } else {
     if (HAL_I2C_Slave_Seq_Transmit_IT(hi2c, I2C_REGISTERS + regAddr, 1, I2C_FIRST_FRAME) != HAL_OK) {
     DBG_LOG("%s(%d): Error Transmit Data", __func__, __LINE__);
     return;
     }
     }
    }

     

     

    ShoHAuthor
    Visitor II
    February 5, 2025

    Hi @Saket_Om, thank you for your reply.

    The condition for direction seems to be correct as “TransferDirection == I2C_DIRECTION_TRANSMIT”.
    (I tried “TransferDirection != I2C_DIRECTION_TRANSMIT”, the I2C transaction was corrupted and MCU rebooted.)

    When tramsmitting Write Request (Data=Register Address) then Read Request from Master device, HAL_I2C_Slave_Seq_Receive_IT is called correctly to receive Register Address, and then HAL_I2C_Slave_Seq_Transmit_IT is called. However, because Clock Stretching is disabled, it seems that 0xFF is transmitted immediately before that and HAL_I2C_Slave_Seq_Transmit_IT is ignored.

    If I preset "hi2c->Instance->TXDR = 0x5a" after HAL_I2C_Slave_Seq_Receive_IT as follows, 0x5a is transmitted in response to Read Request instead of 0xFF.

    hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_ENABLE;
    
    ...
    
    void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode) {
     if (TransferDirection == I2C_DIRECTION_TRANSMIT) { 
     if (HAL_I2C_Slave_Seq_Receive_IT(hi2c, &regAddr, 1, I2C_FIRST_FRAME) != HAL_OK) {
     DBG_LOG("%s(%d): Error Receive Data", __func__, __LINE__);
     return;
     }
     hi2c->Instance->TXDR = 0x5a;
     } else {
     if (HAL_I2C_Slave_Seq_Transmit_IT(hi2c, I2C_REGISTERS + regAddr, 1, I2C_FIRST_FRAME) != HAL_OK) {
     DBG_LOG("%s(%d): Error Transmit Data", __func__, __LINE__);
     return;
     }
     }
    }

    I have attached the relevant source codes. It would be helpful if you give an additional advice.

    ShoHAuthorAnswer
    Visitor II
    February 14, 2025

    I was able to resolve this by presetting the value to TXDR in HAL_I2C_SlaveRxCpltCallback.

    void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c) {
     hi2c->Instance->TXDR = regAddr; 
    }