cancel
Showing results for 
Search instead for 
Did you mean: 

STM32G4 I2C Slave AF Error on Normal Transaction Completion

JohnFrancis
Associate III

Hardware: STM32G473QETX
HAL Version: STM32G4 HAL
I2C Mode: Slave mode using HAL_I2C_Slave_Seq_Receive_IT()
Application: DS1307 RTC emulation

Issue Description
When implementing an I2C slave device (DS1307 RTC emulation), we observe that HAL_I2C_ErrorCallback() is consistently called with error code HAL_I2C_ERROR_AF (0x00000004 - Acknowledge Failure) at the end of successful write transactions from the I2C master

Transaction Flow
Master sends START + Address (0x68) + WRITE
Slave ACKs (address match detected)
Master sends data bytes (8 bytes total)
Slave receives all bytes correctly via HAL_I2C_SlaveRxCpltCallback()
Master sends NACK (to signal end of write)
Master sends STOP
HAL_I2C_ErrorCallback() is called with HAL_I2C_ERROR_AF
HAL_I2C_ListenCpltCallback() is also called

Expected Behavior
According to I2C protocol, the master sending NACK at the end of a write transaction is normal behavior to signal "I don't want to send more data." This should not be reported as an error.

Actual Behavior
The STM32 HAL reports this as HAL_I2C_ERROR_AF and calls HAL_I2C_ErrorCallback(), even though:

All data was received correctly
The transaction completed successfully
The master's behavior is per I2C specification

Questions
Is this the expected behavior of the STM32 HAL I2C slave implementation?
Is there a way to configure the HAL to not report AF errors for normal NACK conditions?
Should we rely on HAL_I2C_ListenCpltCallback() for transaction completion instead of treating AF errors as failures?
Additional Information
Both HAL_I2C_ErrorCallback() and HAL_I2C_ListenCpltCallback() are called for each transaction
The error callback is called first, then the listen complete callback
Data processing works correctly when done in HAL_I2C_ListenCpltCallback()
This behavior is consistent across all I2C write transactions

1 ACCEPTED SOLUTION

Accepted Solutions

> The AF error is a HAL implementation characteristic, not a real protocol error?

Right.

> Is there any way to prevent this AF error, or is the only solution to implement custom logic in HAL_I2C_ErrorCallback() to silently ignore the AF flag during normal transaction completion?

You can either modify HAL or implementing this logic inside your error handler.

> Is this the recommended approach for STM32 HAL I2C slave mode?

I would add a flag which ignores AF only when the condition happens--all 9 bytes have been sent. Unless you don't care if fewer bytes are sent.

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

View solution in original post

5 REPLIES 5
bmckenney
Senior

In a Master-Transmitter transaction it's the Slave side that issues ACKs/NACKs. In this case, the Slave is permitted to NACK, but my experience is that this is rare -- rather the Slave is typically designed to deal gracefully with any extra bytes.

In a Master-Receiver transaction it is indeed the Master that issues ACKs/NACKs, and the Master must indicate the end of the transaction with a NACK, in order to wrest control of SDA so that it can issue a STOP.

Are you actually describing a Master-Receiver transaction rather than Master-Transmitter? Or is there some case where your Slave will issue a NACK?

TDK
Super User

Your observations are perfectly valid here.

That is how it's always been handled in HAL.

The hardware does raise an AF flag in this case. Which is perfectly valid because an AF appears in the transaction.

 

I suggest implementing your own logic in the error handler to silently ignore the AF flag during this scenario when the transaction completes. Expecting a breaking change to HAL seems unlikely.

 

There are more than a few other threads on this if you do enough digging.

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

when Master-Transmitter (AF error happens here)

Thank you for the clarification.

In my I2C slave implementation, the master sends 9 bytes of data. After receiving each byte, including the 9th byte, the HAL_I2C_SlaveRxCpltCallback() is called, and I prepare for the next byte by calling:

HAL_I2C_Slave_Seq_Receive_IT(hi2c, &s_rx_byte, 1, I2C_NEXT_FRAME);

Since I2C slave mode doesn't know in advance how many bytes will come (it receives byte-by-byte until the master sends STOP), the HAL prepares for a 10th byte. However, the master sends STOP after the 9th byte, causing the HAL to report an AF error even though all 9 bytes were successfully transmitted and received.

My understanding:

The I2C transaction completes successfully (all bytes ACKed, STOP received)
The AF error is a HAL implementation characteristic, not a real protocol error?
The HAL was "optimistically" waiting for another byte when STOP arrived

My question: Is there any way to prevent this AF error, or is the only solution to implement custom logic in HAL_I2C_ErrorCallback() to silently ignore the AF flag during normal transaction completion?

Currently, I filter AF errors in my error handler like this:

void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)
{
  uint32_t error_code = HAL_I2C_GetError(hi2c);

  /* Only count non-AF errors (AF is expected at end of transaction) */
  if ((error_code & HAL_I2C_ERROR_AF) == 0U)
  {
    ++s_error_count;
  }

  /* Let HAL_I2C_ListenCpltCallback handle transaction cleanup */
}


Is this the recommended approach for STM32 HAL I2C slave mode?


Edited to apply source code formatting - please see How to insert source code for future reference.

> The AF error is a HAL implementation characteristic, not a real protocol error?

Right.

> Is there any way to prevent this AF error, or is the only solution to implement custom logic in HAL_I2C_ErrorCallback() to silently ignore the AF flag during normal transaction completion?

You can either modify HAL or implementing this logic inside your error handler.

> Is this the recommended approach for STM32 HAL I2C slave mode?

I would add a flag which ignores AF only when the condition happens--all 9 bytes have been sent. Unless you don't care if fewer bytes are sent.

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