Skip to main content
Johannes
Senior
September 15, 2023
Question

HAL_I2C_MEM_READ_IT fails if a NAK occurs on the memory address

  • September 15, 2023
  • 1 reply
  • 3263 views

Hi Everyone
I use STM32G474RE with CubeIDE 1.13.1 and MCU Package G4 V1.5.1

I have a problem, when an I2C_MEM_READ_IT encounters a NAK on the memory address. 

A typical I2C mem read is: 
Start DevAdr(W) (Ack) MemoryAdr (Ack) RepeatedStart DevAdr(R) data(A), data(A)... data(N) Stop

If during this transaction, the first DevAdr(W) is Acknowledged, but the Memoryaddress is NACK, the transaction should stop there and does not need to continue trying repeated start etc. 

This is done here:

static HAL_StatusTypeDef I2C_RequestMemoryRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress,
uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart)
{
I2C_TransferConfig(hi2c, DevAddress, (uint8_t)MemAddSize, I2C_SOFTEND_MODE, I2C_GENERATE_START_WRITE);

/* Wait until TXIS flag is set */
if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK) {
return HAL_ERROR;
}
/* If Memory address size is 8Bit */
if (MemAddSize == I2C_MEMADD_SIZE_8BIT)
{
/* Send Memory Address */
hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress);
}
/* If Memory address size is 16Bit */
else
{
/* Send MSB of Memory Address */
hi2c->Instance->TXDR = I2C_MEM_ADD_MSB(MemAddress);
/* Wait until TXIS flag is set */
if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK)
{
return HAL_ERROR;
}
/* Send LSB of Memory Address */
hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress);
}
/* Wait until TC flag is set */
if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TC, RESET, Timeout, Tickstart) != HAL_OK){
return HAL_ERROR;
}
return HAL_OK;
}

The memory address is sent out (8bit memory address) and the code is waiting for the TC flag being set (Transmit complete)

 

If there is a NAK, TC never gets set, instead NAKF is set. But this code does not check for the NAK flag.

There is is a timeout, which triggers, but the I2c_Mem_Read is exited with the hardware in a bad state.

 

When a next I2C_MEM_read is started, it failes here:
 

static HAL_StatusTypeDef I2C_RequestMemoryRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress,
uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout,
uint32_t Tickstart)
{
I2C_TransferConfig(hi2c, DevAddress, (uint8_t)MemAddSize, I2C_SOFTEND_MODE, I2C_GENERATE_START_WRITE);
/* Wait until TXIS flag is set */
if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK)
{

return HAL_ERROR;
}


The TXIS flag stays zero. The transaction stops immediately after transmitting the device address.

The bus is blocked, clock stays low and the bus is stuck.

 

Does anyone experience the same thing?

Johannes

 

 

 

 

    This topic has been closed for replies.

    1 reply

    Foued_KH
    ST Employee
    September 15, 2023

    Hello @Johannes , 

    Could you please share you code ?

    Foued

    To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
    Johannes
    JohannesAuthor
    Senior
    September 18, 2023

    Hello Foued
    Thank you for helping me. 
    I attached the code. It is a very basic CubeIDE project which uses I2C3. It has a very simple loop in main.c which tries to do a mem read on 0x14 adr 0x12 every 500ms 
    The i2c blocks after two attempts. 
    First read attempt: Deviceaddress is ACKed, Sub-address is "NAKed" 
    I try to talk to a LTC1760 which rejects a subaddress, if it is not available. 

    Johannes_0-1695021375604.png

    This transaciton ends "normal".
    Now, If I try to repeat that, the result is:

    Johannes_1-1695021504785.png

    Not the bus is stuck. Clock is stuck low (STM32 holds it low) the I2c Hardware shows the "busy flag". 
    See attached project (STM32G474RET6)

    The Bus can be reset by clearing the PE bit in CR1, waiting a few cycles and setting it again

    Johannes

     

    Foued_KH
    ST Employee
    September 18, 2023

    Hello @Johannes , 

    Please make sure that you are using the correct sub-address 

    Foued

    To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.