[HAL][I2C] Move polling code of HAL memory interface through interrupt management to prevent timeout issue using HAL MEM interface through FreeRTOS
diff --git a/Inc/stm32f4xx_hal_fmpi2c.h b/Inc/stm32f4xx_hal_fmpi2c.h
index 400b923..90ab2c6 100644
--- a/Inc/stm32f4xx_hal_fmpi2c.h
+++ b/Inc/stm32f4xx_hal_fmpi2c.h
@@ -218,6 +218,10 @@
 
   __IO uint32_t              AddrEventCount; /*!< FMPI2C Address Event counter                 */
 
+  __IO uint32_t              Devaddress;     /*!< FMPI2C Target device address                 */
+
+  __IO uint32_t              Memaddress;     /*!< FMPI2C Target memory address                 */
+
 #if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1)
   void (* MasterTxCpltCallback)(struct __FMPI2C_HandleTypeDef *hfmpi2c);
   /*!< FMPI2C Master Tx Transfer completed callback */
diff --git a/Inc/stm32f4xx_hal_fmpsmbus.h b/Inc/stm32f4xx_hal_fmpsmbus.h
index 6d1ff4b..5086790 100644
--- a/Inc/stm32f4xx_hal_fmpsmbus.h
+++ b/Inc/stm32f4xx_hal_fmpsmbus.h
@@ -512,6 +512,7 @@
   * @param  __HANDLE__ specifies the FMPSMBUS Handle.
   * @param  __FLAG__ specifies the flag to clear.
   *          This parameter can be any combination of the following values:
+  *            @arg @ref FMPSMBUS_FLAG_TXE     Transmit data register empty
   *            @arg @ref FMPSMBUS_FLAG_ADDR    Address matched (slave mode)
   *            @arg @ref FMPSMBUS_FLAG_AF      NACK received flag
   *            @arg @ref FMPSMBUS_FLAG_STOPF   STOP detection flag
@@ -524,7 +525,9 @@
   *
   * @retval None
   */
-#define __HAL_FMPSMBUS_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->ICR = (__FLAG__))
+#define __HAL_FMPSMBUS_CLEAR_FLAG(__HANDLE__, __FLAG__)  (((__FLAG__) == FMPSMBUS_FLAG_TXE) ? \
+                                                       ((__HANDLE__)->Instance->ISR |= (__FLAG__)) : \
+                                                       ((__HANDLE__)->Instance->ICR = (__FLAG__)))
 
 /** @brief  Enable the specified FMPSMBUS peripheral.
   * @param  __HANDLE__ specifies the FMPSMBUS Handle.
diff --git a/Src/stm32f4xx_hal_fmpi2c.c b/Src/stm32f4xx_hal_fmpi2c.c
index 522e529..6f83e87 100644
--- a/Src/stm32f4xx_hal_fmpi2c.c
+++ b/Src/stm32f4xx_hal_fmpi2c.c
@@ -402,6 +402,9 @@
   */
 
 /* Private macro -------------------------------------------------------------*/
+/* Macro to get remaining data to transfer on DMA side */
+#define FMPI2C_GET_DMA_REMAIN_DATA(__HANDLE__)     __HAL_DMA_GET_COUNTER(__HANDLE__)
+
 /* Private variables ---------------------------------------------------------*/
 /* Private function prototypes -----------------------------------------------*/
 
@@ -436,10 +439,14 @@
 /* Private functions for FMPI2C transfer IRQ handler */
 static HAL_StatusTypeDef FMPI2C_Master_ISR_IT(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags,
                                            uint32_t ITSources);
+static HAL_StatusTypeDef FMPI2C_Mem_ISR_IT(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags,
+                                        uint32_t ITSources);
 static HAL_StatusTypeDef FMPI2C_Slave_ISR_IT(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags,
                                           uint32_t ITSources);
 static HAL_StatusTypeDef FMPI2C_Master_ISR_DMA(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags,
                                             uint32_t ITSources);
+static HAL_StatusTypeDef FMPI2C_Mem_ISR_DMA(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags,
+                                         uint32_t ITSources);
 static HAL_StatusTypeDef FMPI2C_Slave_ISR_DMA(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags,
                                            uint32_t ITSources);
 
@@ -1432,22 +1439,27 @@
       hfmpi2c->XferCount--;
     }
 
+    /* Wait until AF flag is set */
+    if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_AF, RESET, Timeout, tickstart) != HAL_OK)
+    {
+      /* Disable Address Acknowledge */
+      hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK;
+      return HAL_ERROR;
+    }
+
+    /* Flush TX register */
+    FMPI2C_Flush_TXDR(hfmpi2c);
+
+    /* Clear AF flag */
+    __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF);
+
     /* Wait until STOP flag is set */
     if (FMPI2C_WaitOnSTOPFlagUntilTimeout(hfmpi2c, Timeout, tickstart) != HAL_OK)
     {
       /* Disable Address Acknowledge */
       hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK;
 
-      if (hfmpi2c->ErrorCode == HAL_FMPI2C_ERROR_AF)
-      {
-        /* Normal use case for Transmitter mode */
-        /* A NACK is generated to confirm the end of transfer */
-        hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE;
-      }
-      else
-      {
-        return HAL_ERROR;
-      }
+      return HAL_ERROR;
     }
 
     /* Clear STOP flag */
@@ -1512,6 +1524,7 @@
     /* Prepare transfer parameters */
     hfmpi2c->pBuffPtr  = pData;
     hfmpi2c->XferCount = Size;
+    hfmpi2c->XferSize = hfmpi2c->XferCount;
     hfmpi2c->XferISR   = NULL;
 
     /* Enable Address Acknowledge */
@@ -1554,6 +1567,7 @@
           hfmpi2c->pBuffPtr++;
 
           hfmpi2c->XferCount--;
+          hfmpi2c->XferSize--;
         }
 
         return HAL_ERROR;
@@ -1566,6 +1580,7 @@
       hfmpi2c->pBuffPtr++;
 
       hfmpi2c->XferCount--;
+      hfmpi2c->XferSize--;
     }
 
     /* Wait until STOP flag is set */
@@ -2637,9 +2652,6 @@
 HAL_StatusTypeDef HAL_FMPI2C_Mem_Write_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint16_t MemAddress,
                                        uint16_t MemAddSize, uint8_t *pData, uint16_t Size)
 {
-  uint32_t tickstart;
-  uint32_t xfermode;
-
   /* Check the parameters */
   assert_param(IS_FMPI2C_MEMADD_SIZE(MemAddSize));
 
@@ -2659,9 +2671,6 @@
     /* Process Locked */
     __HAL_LOCK(hfmpi2c);
 
-    /* Init tickstart for timeout management*/
-    tickstart = HAL_GetTick();
-
     hfmpi2c->State       = HAL_FMPI2C_STATE_BUSY_TX;
     hfmpi2c->Mode        = HAL_FMPI2C_MODE_MEM;
     hfmpi2c->ErrorCode   = HAL_FMPI2C_ERROR_NONE;
@@ -2670,30 +2679,29 @@
     hfmpi2c->pBuffPtr    = pData;
     hfmpi2c->XferCount   = Size;
     hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME;
-    hfmpi2c->XferISR     = FMPI2C_Master_ISR_IT;
+    hfmpi2c->XferISR     = FMPI2C_Mem_ISR_IT;
+    hfmpi2c->Devaddress  = DevAddress;
 
-    if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
+    /* If Memory address size is 8Bit */
+    if (MemAddSize == FMPI2C_MEMADD_SIZE_8BIT)
     {
-      hfmpi2c->XferSize = MAX_NBYTE_SIZE;
-      xfermode = FMPI2C_RELOAD_MODE;
+      /* Prefetch Memory Address */
+      hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_LSB(MemAddress);
+
+      /* Reset Memaddress content */
+      hfmpi2c->Memaddress = 0xFFFFFFFFU;
     }
+    /* If Memory address size is 16Bit */
     else
     {
-      hfmpi2c->XferSize = hfmpi2c->XferCount;
-      xfermode = FMPI2C_AUTOEND_MODE;
-    }
+      /* Prefetch Memory Address (MSB part, LSB will be manage through interrupt) */
+      hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_MSB(MemAddress);
 
+      /* Prepare Memaddress buffer for LSB part */
+      hfmpi2c->Memaddress = FMPI2C_MEM_ADD_LSB(MemAddress);
+    }
     /* Send Slave Address and Memory Address */
-    if (FMPI2C_RequestMemoryWrite(hfmpi2c, DevAddress, MemAddress, MemAddSize, FMPI2C_TIMEOUT_FLAG, tickstart)
-        != HAL_OK)
-    {
-      /* Process Unlocked */
-      __HAL_UNLOCK(hfmpi2c);
-      return HAL_ERROR;
-    }
-
-    /* Set NBYTES to write and reload if hfmpi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
-    FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, xfermode, FMPI2C_NO_STARTSTOP);
+    FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)MemAddSize, FMPI2C_RELOAD_MODE, FMPI2C_GENERATE_START_WRITE);
 
     /* Process Unlocked */
     __HAL_UNLOCK(hfmpi2c);
@@ -2731,9 +2739,6 @@
 HAL_StatusTypeDef HAL_FMPI2C_Mem_Read_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint16_t MemAddress,
                                       uint16_t MemAddSize, uint8_t *pData, uint16_t Size)
 {
-  uint32_t tickstart;
-  uint32_t xfermode;
-
   /* Check the parameters */
   assert_param(IS_FMPI2C_MEMADD_SIZE(MemAddSize));
 
@@ -2753,9 +2758,6 @@
     /* Process Locked */
     __HAL_LOCK(hfmpi2c);
 
-    /* Init tickstart for timeout management*/
-    tickstart = HAL_GetTick();
-
     hfmpi2c->State       = HAL_FMPI2C_STATE_BUSY_RX;
     hfmpi2c->Mode        = HAL_FMPI2C_MODE_MEM;
     hfmpi2c->ErrorCode   = HAL_FMPI2C_ERROR_NONE;
@@ -2764,29 +2766,29 @@
     hfmpi2c->pBuffPtr    = pData;
     hfmpi2c->XferCount   = Size;
     hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME;
-    hfmpi2c->XferISR     = FMPI2C_Master_ISR_IT;
+    hfmpi2c->XferISR     = FMPI2C_Mem_ISR_IT;
+    hfmpi2c->Devaddress  = DevAddress;
 
-    if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
+    /* If Memory address size is 8Bit */
+    if (MemAddSize == FMPI2C_MEMADD_SIZE_8BIT)
     {
-      hfmpi2c->XferSize = MAX_NBYTE_SIZE;
-      xfermode = FMPI2C_RELOAD_MODE;
+      /* Prefetch Memory Address */
+      hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_LSB(MemAddress);
+
+      /* Reset Memaddress content */
+      hfmpi2c->Memaddress = 0xFFFFFFFFU;
     }
+    /* If Memory address size is 16Bit */
     else
     {
-      hfmpi2c->XferSize = hfmpi2c->XferCount;
-      xfermode = FMPI2C_AUTOEND_MODE;
-    }
+      /* Prefetch Memory Address (MSB part, LSB will be manage through interrupt) */
+      hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_MSB(MemAddress);
 
+      /* Prepare Memaddress buffer for LSB part */
+      hfmpi2c->Memaddress = FMPI2C_MEM_ADD_LSB(MemAddress);
+    }
     /* Send Slave Address and Memory Address */
-    if (FMPI2C_RequestMemoryRead(hfmpi2c, DevAddress, MemAddress, MemAddSize, FMPI2C_TIMEOUT_FLAG, tickstart) != HAL_OK)
-    {
-      /* Process Unlocked */
-      __HAL_UNLOCK(hfmpi2c);
-      return HAL_ERROR;
-    }
-
-    /* Set NBYTES to write and reload if hfmpi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
-    FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, xfermode, FMPI2C_GENERATE_START_READ);
+    FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)MemAddSize, FMPI2C_SOFTEND_MODE, FMPI2C_GENERATE_START_WRITE);
 
     /* Process Unlocked */
     __HAL_UNLOCK(hfmpi2c);
@@ -2799,7 +2801,7 @@
     /* possible to enable all of these */
     /* FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI |
       FMPI2C_IT_ADDRI | FMPI2C_IT_RXI | FMPI2C_IT_TXI */
-    FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_RX_IT);
+    FMPI2C_Enable_IRQ(hfmpi2c, (FMPI2C_XFER_TX_IT | FMPI2C_XFER_RX_IT));
 
     return HAL_OK;
   }
@@ -2823,8 +2825,6 @@
 HAL_StatusTypeDef HAL_FMPI2C_Mem_Write_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint16_t MemAddress,
                                         uint16_t MemAddSize, uint8_t *pData, uint16_t Size)
 {
-  uint32_t tickstart;
-  uint32_t xfermode;
   HAL_StatusTypeDef dmaxferstatus;
 
   /* Check the parameters */
@@ -2846,9 +2846,6 @@
     /* Process Locked */
     __HAL_LOCK(hfmpi2c);
 
-    /* Init tickstart for timeout management*/
-    tickstart = HAL_GetTick();
-
     hfmpi2c->State       = HAL_FMPI2C_STATE_BUSY_TX;
     hfmpi2c->Mode        = HAL_FMPI2C_MODE_MEM;
     hfmpi2c->ErrorCode   = HAL_FMPI2C_ERROR_NONE;
@@ -2857,28 +2854,36 @@
     hfmpi2c->pBuffPtr    = pData;
     hfmpi2c->XferCount   = Size;
     hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME;
-    hfmpi2c->XferISR     = FMPI2C_Master_ISR_DMA;
+    hfmpi2c->XferISR     = FMPI2C_Mem_ISR_DMA;
+    hfmpi2c->Devaddress  = DevAddress;
 
     if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
     {
       hfmpi2c->XferSize = MAX_NBYTE_SIZE;
-      xfermode = FMPI2C_RELOAD_MODE;
     }
     else
     {
       hfmpi2c->XferSize = hfmpi2c->XferCount;
-      xfermode = FMPI2C_AUTOEND_MODE;
     }
 
-    /* Send Slave Address and Memory Address */
-    if (FMPI2C_RequestMemoryWrite(hfmpi2c, DevAddress, MemAddress, MemAddSize, FMPI2C_TIMEOUT_FLAG, tickstart)
-        != HAL_OK)
+    /* If Memory address size is 8Bit */
+    if (MemAddSize == FMPI2C_MEMADD_SIZE_8BIT)
     {
-      /* Process Unlocked */
-      __HAL_UNLOCK(hfmpi2c);
-      return HAL_ERROR;
-    }
+      /* Prefetch Memory Address */
+      hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_LSB(MemAddress);
 
+      /* Reset Memaddress content */
+      hfmpi2c->Memaddress = 0xFFFFFFFFU;
+    }
+    /* If Memory address size is 16Bit */
+    else
+    {
+      /* Prefetch Memory Address (MSB part, LSB will be manage through interrupt) */
+      hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_MSB(MemAddress);
+
+      /* Prepare Memaddress buffer for LSB part */
+      hfmpi2c->Memaddress = FMPI2C_MEM_ADD_LSB(MemAddress);
+    }
 
     if (hfmpi2c->hdmatx != NULL)
     {
@@ -2913,12 +2918,8 @@
 
     if (dmaxferstatus == HAL_OK)
     {
-      /* Send Slave Address */
-      /* Set NBYTES to write and reload if hfmpi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
-      FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, xfermode, FMPI2C_NO_STARTSTOP);
-
-      /* Update XferCount value */
-      hfmpi2c->XferCount -= hfmpi2c->XferSize;
+      /* Send Slave Address and Memory Address */
+      FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)MemAddSize, FMPI2C_RELOAD_MODE, FMPI2C_GENERATE_START_WRITE);
 
       /* Process Unlocked */
       __HAL_UNLOCK(hfmpi2c);
@@ -2926,11 +2927,11 @@
       /* Note : The FMPI2C interrupts must be enabled after unlocking current process
                 to avoid the risk of FMPI2C interrupt handle execution before current
                 process unlock */
-      /* Enable ERR and NACK interrupts */
-      FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_ERROR_IT);
-
-      /* Enable DMA Request */
-      hfmpi2c->Instance->CR1 |= FMPI2C_CR1_TXDMAEN;
+      /* Enable ERR, TC, STOP, NACK, TXI interrupt */
+      /* possible to enable all of these */
+      /* FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI |
+        FMPI2C_IT_ADDRI | FMPI2C_IT_RXI | FMPI2C_IT_TXI */
+      FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT);
     }
     else
     {
@@ -2970,8 +2971,6 @@
 HAL_StatusTypeDef HAL_FMPI2C_Mem_Read_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint16_t MemAddress,
                                        uint16_t MemAddSize, uint8_t *pData, uint16_t Size)
 {
-  uint32_t tickstart;
-  uint32_t xfermode;
   HAL_StatusTypeDef dmaxferstatus;
 
   /* Check the parameters */
@@ -2993,9 +2992,6 @@
     /* Process Locked */
     __HAL_LOCK(hfmpi2c);
 
-    /* Init tickstart for timeout management*/
-    tickstart = HAL_GetTick();
-
     hfmpi2c->State       = HAL_FMPI2C_STATE_BUSY_RX;
     hfmpi2c->Mode        = HAL_FMPI2C_MODE_MEM;
     hfmpi2c->ErrorCode   = HAL_FMPI2C_ERROR_NONE;
@@ -3004,25 +3000,35 @@
     hfmpi2c->pBuffPtr    = pData;
     hfmpi2c->XferCount   = Size;
     hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME;
-    hfmpi2c->XferISR     = FMPI2C_Master_ISR_DMA;
+    hfmpi2c->XferISR     = FMPI2C_Mem_ISR_DMA;
+    hfmpi2c->Devaddress  = DevAddress;
 
     if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
     {
       hfmpi2c->XferSize = MAX_NBYTE_SIZE;
-      xfermode = FMPI2C_RELOAD_MODE;
     }
     else
     {
       hfmpi2c->XferSize = hfmpi2c->XferCount;
-      xfermode = FMPI2C_AUTOEND_MODE;
     }
 
-    /* Send Slave Address and Memory Address */
-    if (FMPI2C_RequestMemoryRead(hfmpi2c, DevAddress, MemAddress, MemAddSize, FMPI2C_TIMEOUT_FLAG, tickstart) != HAL_OK)
+    /* If Memory address size is 8Bit */
+    if (MemAddSize == FMPI2C_MEMADD_SIZE_8BIT)
     {
-      /* Process Unlocked */
-      __HAL_UNLOCK(hfmpi2c);
-      return HAL_ERROR;
+      /* Prefetch Memory Address */
+      hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_LSB(MemAddress);
+
+      /* Reset Memaddress content */
+      hfmpi2c->Memaddress = 0xFFFFFFFFU;
+    }
+    /* If Memory address size is 16Bit */
+    else
+    {
+      /* Prefetch Memory Address (MSB part, LSB will be manage through interrupt) */
+      hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_MSB(MemAddress);
+
+      /* Prepare Memaddress buffer for LSB part */
+      hfmpi2c->Memaddress = FMPI2C_MEM_ADD_LSB(MemAddress);
     }
 
     if (hfmpi2c->hdmarx != NULL)
@@ -3058,11 +3064,8 @@
 
     if (dmaxferstatus == HAL_OK)
     {
-      /* Set NBYTES to write and reload if hfmpi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
-      FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, xfermode, FMPI2C_GENERATE_START_READ);
-
-      /* Update XferCount value */
-      hfmpi2c->XferCount -= hfmpi2c->XferSize;
+      /* Send Slave Address and Memory Address */
+      FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)MemAddSize, FMPI2C_SOFTEND_MODE, FMPI2C_GENERATE_START_WRITE);
 
       /* Process Unlocked */
       __HAL_UNLOCK(hfmpi2c);
@@ -3070,11 +3073,11 @@
       /* Note : The FMPI2C interrupts must be enabled after unlocking current process
                 to avoid the risk of FMPI2C interrupt handle execution before current
                 process unlock */
-      /* Enable ERR and NACK interrupts */
-      FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_ERROR_IT);
-
-      /* Enable DMA Request */
-      hfmpi2c->Instance->CR1 |= FMPI2C_CR1_RXDMAEN;
+      /* Enable ERR, TC, STOP, NACK, TXI interrupt */
+      /* possible to enable all of these */
+      /* FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI |
+        FMPI2C_IT_ADDRI | FMPI2C_IT_RXI | FMPI2C_IT_TXI */
+      FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT);
     }
     else
     {
@@ -3317,6 +3320,10 @@
     /* Note : The FMPI2C interrupts must be enabled after unlocking current process
               to avoid the risk of FMPI2C interrupt handle execution before current
               process unlock */
+    /* Enable ERR, TC, STOP, NACK, TXI interrupt */
+    /* possible to enable all of these */
+    /* FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI |
+       FMPI2C_IT_ADDRI | FMPI2C_IT_RXI | FMPI2C_IT_TXI */
     FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT);
 
     return HAL_OK;
@@ -4017,15 +4024,15 @@
     /* Process Unlocked */
     __HAL_UNLOCK(hfmpi2c);
 
+    /* Enable DMA Request */
+    hfmpi2c->Instance->CR1 |= FMPI2C_CR1_TXDMAEN;
+
     /* Note : The FMPI2C interrupts must be enabled after unlocking current process
     to avoid the risk of FMPI2C interrupt handle execution before current
     process unlock */
     /* Enable ERR, STOP, NACK, ADDR interrupts */
     FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT);
 
-    /* Enable DMA Request */
-    hfmpi2c->Instance->CR1 |= FMPI2C_CR1_TXDMAEN;
-
     return HAL_OK;
   }
   else
@@ -4301,15 +4308,15 @@
     /* Process Unlocked */
     __HAL_UNLOCK(hfmpi2c);
 
+    /* Enable DMA Request */
+    hfmpi2c->Instance->CR1 |= FMPI2C_CR1_RXDMAEN;
+
     /* Note : The FMPI2C interrupts must be enabled after unlocking current process
     to avoid the risk of FMPI2C interrupt handle execution before current
     process unlock */
     /* REnable ADDR interrupt */
     FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_RX_IT | FMPI2C_XFER_LISTEN_IT);
 
-    /* Enable DMA Request */
-    hfmpi2c->Instance->CR1 |= FMPI2C_CR1_RXDMAEN;
-
     return HAL_OK;
   }
   else
@@ -4883,6 +4890,143 @@
 }
 
 /**
+  * @brief  Interrupt Sub-Routine which handle the Interrupt Flags Memory Mode with Interrupt.
+  * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
+  *                the configuration information for the specified FMPI2C.
+  * @param  ITFlags Interrupt flags to handle.
+  * @param  ITSources Interrupt sources enabled.
+  * @retval HAL status
+  */
+static HAL_StatusTypeDef FMPI2C_Mem_ISR_IT(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags,
+                                           uint32_t ITSources)
+{
+  uint32_t direction = FMPI2C_GENERATE_START_WRITE;
+  uint32_t tmpITFlags = ITFlags;
+
+  /* Process Locked */
+  __HAL_LOCK(hfmpi2c);
+
+  if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_AF) != RESET) && \
+      (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_NACKI) != RESET))
+  {
+    /* Clear NACK Flag */
+    __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF);
+
+    /* Set corresponding Error Code */
+    /* No need to generate STOP, it is automatically done */
+    /* Error callback will be send during stop flag treatment */
+    hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_AF;
+
+    /* Flush TX register */
+    FMPI2C_Flush_TXDR(hfmpi2c);
+  }
+  else if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_RXNE) != RESET) && \
+           (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_RXI) != RESET))
+  {
+    /* Remove RXNE flag on temporary variable as read done */
+    tmpITFlags &= ~FMPI2C_FLAG_RXNE;
+
+    /* Read data from RXDR */
+    *hfmpi2c->pBuffPtr = (uint8_t)hfmpi2c->Instance->RXDR;
+
+    /* Increment Buffer pointer */
+    hfmpi2c->pBuffPtr++;
+
+    hfmpi2c->XferSize--;
+    hfmpi2c->XferCount--;
+  }
+  else if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_TXIS) != RESET) && \
+           (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_TXI) != RESET))
+  {
+    if (hfmpi2c->Memaddress == 0xFFFFFFFFU)
+    {
+      /* Write data to TXDR */
+      hfmpi2c->Instance->TXDR = *hfmpi2c->pBuffPtr;
+
+      /* Increment Buffer pointer */
+      hfmpi2c->pBuffPtr++;
+
+      hfmpi2c->XferSize--;
+      hfmpi2c->XferCount--;
+    }
+    else
+    {
+      /* Write LSB part of Memory Address */
+      hfmpi2c->Instance->TXDR = hfmpi2c->Memaddress;
+
+      /* Reset Memaddress content */
+      hfmpi2c->Memaddress = 0xFFFFFFFFU;
+    }
+  }
+  else if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_TCR) != RESET) && \
+           (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_TCI) != RESET))
+  {
+    if ((hfmpi2c->XferCount != 0U) && (hfmpi2c->XferSize == 0U))
+    {
+      if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
+      {
+        hfmpi2c->XferSize = MAX_NBYTE_SIZE;
+        FMPI2C_TransferConfig(hfmpi2c, (uint16_t)hfmpi2c->Devaddress, (uint8_t)hfmpi2c->XferSize,
+                           FMPI2C_RELOAD_MODE, FMPI2C_NO_STARTSTOP);
+      }
+      else
+      {
+        hfmpi2c->XferSize = hfmpi2c->XferCount;
+        FMPI2C_TransferConfig(hfmpi2c, (uint16_t)hfmpi2c->Devaddress, (uint8_t)hfmpi2c->XferSize,
+                           FMPI2C_AUTOEND_MODE, FMPI2C_NO_STARTSTOP);
+      }
+    }
+    else
+    {
+      /* Wrong size Status regarding TCR flag event */
+      /* Call the corresponding callback to inform upper layer of End of Transfer */
+      FMPI2C_ITError(hfmpi2c, HAL_FMPI2C_ERROR_SIZE);
+    }
+  }
+  else if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_TC) != RESET) && \
+           (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_TCI) != RESET))
+  {
+    if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX)
+    {
+      direction = FMPI2C_GENERATE_START_READ;
+    }
+
+    if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
+    {
+      hfmpi2c->XferSize = MAX_NBYTE_SIZE;
+
+      /* Set NBYTES to write and reload if hfmpi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
+      FMPI2C_TransferConfig(hfmpi2c, (uint16_t)hfmpi2c->Devaddress, (uint8_t)hfmpi2c->XferSize,
+                         FMPI2C_RELOAD_MODE, direction);
+    }
+    else
+    {
+      hfmpi2c->XferSize = hfmpi2c->XferCount;
+
+      /* Set NBYTES to write and generate RESTART */
+      FMPI2C_TransferConfig(hfmpi2c, (uint16_t)hfmpi2c->Devaddress, (uint8_t)hfmpi2c->XferSize,
+                         FMPI2C_AUTOEND_MODE, direction);
+    }
+  }
+  else
+  {
+    /* Nothing to do */
+  }
+
+  if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_STOPF) != RESET) && \
+      (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_STOPI) != RESET))
+  {
+    /* Call FMPI2C Master complete process */
+    FMPI2C_ITMasterCplt(hfmpi2c, tmpITFlags);
+  }
+
+  /* Process Unlocked */
+  __HAL_UNLOCK(hfmpi2c);
+
+  return HAL_OK;
+}
+
+/**
   * @brief  Interrupt Sub-Routine which handle the Interrupt Flags Slave Mode with Interrupt.
   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
   *                the configuration information for the specified FMPI2C.
@@ -5164,6 +5308,145 @@
 }
 
 /**
+  * @brief  Interrupt Sub-Routine which handle the Interrupt Flags Memory Mode with DMA.
+  * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
+  *                the configuration information for the specified FMPI2C.
+  * @param  ITFlags Interrupt flags to handle.
+  * @param  ITSources Interrupt sources enabled.
+  * @retval HAL status
+  */
+static HAL_StatusTypeDef FMPI2C_Mem_ISR_DMA(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags,
+                                            uint32_t ITSources)
+{
+  uint32_t direction = FMPI2C_GENERATE_START_WRITE;
+
+  /* Process Locked */
+  __HAL_LOCK(hfmpi2c);
+
+  if ((FMPI2C_CHECK_FLAG(ITFlags, FMPI2C_FLAG_AF) != RESET) && \
+      (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_NACKI) != RESET))
+  {
+    /* Clear NACK Flag */
+    __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF);
+
+    /* Set corresponding Error Code */
+    hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_AF;
+
+    /* No need to generate STOP, it is automatically done */
+    /* But enable STOP interrupt, to treat it */
+    /* Error callback will be send during stop flag treatment */
+    FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_CPLT_IT);
+
+    /* Flush TX register */
+    FMPI2C_Flush_TXDR(hfmpi2c);
+  }
+  else if ((FMPI2C_CHECK_FLAG(ITFlags, FMPI2C_FLAG_TXIS) != RESET) && \
+           (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_TXI) != RESET))
+  {
+    /* Write LSB part of Memory Address */
+    hfmpi2c->Instance->TXDR = hfmpi2c->Memaddress;
+
+    /* Reset Memaddress content */
+    hfmpi2c->Memaddress = 0xFFFFFFFFU;
+  }
+  else if ((FMPI2C_CHECK_FLAG(ITFlags, FMPI2C_FLAG_TCR) != RESET) && \
+           (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_TCI) != RESET))
+  {
+    /* Enable only Error interrupt */
+    FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_ERROR_IT);
+
+    if (hfmpi2c->XferCount != 0U)
+    {
+      /* Prepare the new XferSize to transfer */
+      if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
+      {
+        hfmpi2c->XferSize = MAX_NBYTE_SIZE;
+        FMPI2C_TransferConfig(hfmpi2c, (uint16_t)hfmpi2c->Devaddress, (uint8_t)hfmpi2c->XferSize,
+                           FMPI2C_RELOAD_MODE, FMPI2C_NO_STARTSTOP);
+      }
+      else
+      {
+        hfmpi2c->XferSize = hfmpi2c->XferCount;
+        FMPI2C_TransferConfig(hfmpi2c, (uint16_t)hfmpi2c->Devaddress, (uint8_t)hfmpi2c->XferSize,
+                           FMPI2C_AUTOEND_MODE, FMPI2C_NO_STARTSTOP);
+      }
+
+      /* Update XferCount value */
+      hfmpi2c->XferCount -= hfmpi2c->XferSize;
+
+      /* Enable DMA Request */
+      if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX)
+      {
+        hfmpi2c->Instance->CR1 |= FMPI2C_CR1_RXDMAEN;
+      }
+      else
+      {
+        hfmpi2c->Instance->CR1 |= FMPI2C_CR1_TXDMAEN;
+      }
+    }
+    else
+    {
+      /* Wrong size Status regarding TCR flag event */
+      /* Call the corresponding callback to inform upper layer of End of Transfer */
+      FMPI2C_ITError(hfmpi2c, HAL_FMPI2C_ERROR_SIZE);
+    }
+  }
+  else if ((FMPI2C_CHECK_FLAG(ITFlags, FMPI2C_FLAG_TC) != RESET) && \
+           (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_TCI) != RESET))
+  {
+    if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX)
+    {
+      direction = FMPI2C_GENERATE_START_READ;
+    }
+
+    if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
+    {
+      hfmpi2c->XferSize = MAX_NBYTE_SIZE;
+
+      /* Set NBYTES to write and reload if hfmpi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
+      FMPI2C_TransferConfig(hfmpi2c, (uint16_t)hfmpi2c->Devaddress, (uint8_t)hfmpi2c->XferSize,
+                         FMPI2C_RELOAD_MODE, direction);
+    }
+    else
+    {
+      hfmpi2c->XferSize = hfmpi2c->XferCount;
+
+      /* Set NBYTES to write and generate RESTART */
+      FMPI2C_TransferConfig(hfmpi2c, (uint16_t)hfmpi2c->Devaddress, (uint8_t)hfmpi2c->XferSize,
+                         FMPI2C_AUTOEND_MODE, direction);
+    }
+
+    /* Update XferCount value */
+    hfmpi2c->XferCount -= hfmpi2c->XferSize;
+
+    /* Enable DMA Request */
+    if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX)
+    {
+      hfmpi2c->Instance->CR1 |= FMPI2C_CR1_RXDMAEN;
+    }
+    else
+    {
+      hfmpi2c->Instance->CR1 |= FMPI2C_CR1_TXDMAEN;
+    }
+  }
+  else if ((FMPI2C_CHECK_FLAG(ITFlags, FMPI2C_FLAG_STOPF) != RESET) && \
+           (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_STOPI) != RESET))
+  {
+    /* Call FMPI2C Master complete process */
+    FMPI2C_ITMasterCplt(hfmpi2c, ITFlags);
+  }
+  else
+  {
+    /* Nothing to do */
+  }
+
+  /* Process Unlocked */
+  __HAL_UNLOCK(hfmpi2c);
+
+  return HAL_OK;
+}
+
+/**
   * @brief  Interrupt Sub-Routine which handle the Interrupt Flags Slave Mode with DMA.
   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
   *                the configuration information for the specified FMPI2C.
@@ -5204,7 +5487,7 @@
       {
         if (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_CR1_RXDMAEN) != RESET)
         {
-          if (__HAL_DMA_GET_COUNTER(hfmpi2c->hdmarx) == 0U)
+          if (FMPI2C_GET_DMA_REMAIN_DATA(hfmpi2c->hdmarx) == 0U)
           {
             treatdmanack = 1U;
           }
@@ -5216,7 +5499,7 @@
       {
         if (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_CR1_TXDMAEN) != RESET)
         {
-          if (__HAL_DMA_GET_COUNTER(hfmpi2c->hdmatx) == 0U)
+          if (FMPI2C_GET_DMA_REMAIN_DATA(hfmpi2c->hdmatx) == 0U)
           {
             treatdmanack = 1U;
           }
@@ -5827,7 +6110,7 @@
 
     if (hfmpi2c->hdmatx != NULL)
     {
-      hfmpi2c->XferCount = (uint16_t)__HAL_DMA_GET_COUNTER(hfmpi2c->hdmatx);
+      hfmpi2c->XferCount = (uint16_t)FMPI2C_GET_DMA_REMAIN_DATA(hfmpi2c->hdmatx);
     }
   }
   else if (FMPI2C_CHECK_IT_SOURCE(tmpcr1value, FMPI2C_CR1_RXDMAEN) != RESET)
@@ -5837,7 +6120,7 @@
 
     if (hfmpi2c->hdmarx != NULL)
     {
-      hfmpi2c->XferCount = (uint16_t)__HAL_DMA_GET_COUNTER(hfmpi2c->hdmarx);
+      hfmpi2c->XferCount = (uint16_t)FMPI2C_GET_DMA_REMAIN_DATA(hfmpi2c->hdmarx);
     }
   }
   else
@@ -6300,7 +6583,7 @@
   FMPI2C_HandleTypeDef *hfmpi2c = (FMPI2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
   uint32_t tmpoptions = hfmpi2c->XferOptions;
 
-  if ((__HAL_DMA_GET_COUNTER(hfmpi2c->hdmarx) == 0U) && \
+  if ((FMPI2C_GET_DMA_REMAIN_DATA(hfmpi2c->hdmarx) == 0U) && \
       (tmpoptions != FMPI2C_NO_OPTION_FRAME))
   {
     /* Disable DMA Request */
@@ -6330,7 +6613,7 @@
 
   if (hfmpi2c->hdmatx != NULL)
   {
-    if (__HAL_DMA_GET_COUNTER(hfmpi2c->hdmatx) == 0U)
+    if (FMPI2C_GET_DMA_REMAIN_DATA(hfmpi2c->hdmatx) == 0U)
     {
       treatdmaerror = 1U;
     }
@@ -6338,7 +6621,7 @@
 
   if (hfmpi2c->hdmarx != NULL)
   {
-    if (__HAL_DMA_GET_COUNTER(hfmpi2c->hdmarx) == 0U)
+    if (FMPI2C_GET_DMA_REMAIN_DATA(hfmpi2c->hdmarx) == 0U)
     {
       treatdmaerror = 1U;
     }
@@ -6518,13 +6801,22 @@
       }
       else
       {
+        if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_AF) == SET)
+        {
+          __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF);
+          hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_AF;
+        }
+        else
+        {
+          hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE;
+        }
+
         /* Clear STOP Flag */
         __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF);
 
         /* Clear Configuration Register 2 */
         FMPI2C_RESET_CR2(hfmpi2c);
 
-        hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE;
         hfmpi2c->State = HAL_FMPI2C_STATE_READY;
         hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE;
 
@@ -6563,15 +6855,14 @@
   HAL_StatusTypeDef status = HAL_OK;
   uint32_t itflag   = hfmpi2c->Instance->ISR;
   uint32_t error_code = 0;
+  uint32_t tickstart = Tickstart;
+  uint32_t tmp1;
+  HAL_FMPI2C_ModeTypeDef tmp2;
 
   if (HAL_IS_BIT_SET(itflag, FMPI2C_FLAG_AF))
   {
-    /* In case of Soft End condition, generate the STOP condition */
-    if (FMPI2C_GET_STOP_MODE(hfmpi2c) != FMPI2C_AUTOEND_MODE)
-    {
-      /* Generate Stop */
-      hfmpi2c->Instance->CR2 |= FMPI2C_CR2_STOP;
-    }
+    /* Clear NACKF Flag */
+    __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF);
 
     /* Wait until STOP Flag is set or timeout occurred */
     /* AutoEnd should be initiate after AF */
@@ -6580,11 +6871,38 @@
       /* Check for the Timeout */
       if (Timeout != HAL_MAX_DELAY)
       {
-        if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U))
+        if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
         {
-          error_code |= HAL_FMPI2C_ERROR_TIMEOUT;
+          tmp1 = (uint32_t)(hfmpi2c->Instance->CR2 & FMPI2C_CR2_STOP);
+          tmp2 = hfmpi2c->Mode;
 
-          status = HAL_ERROR;
+          /* In case of FMPI2C still busy, try to regenerate a STOP manually */
+          if ((__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_BUSY) != RESET) && \
+              (tmp1 != FMPI2C_CR2_STOP) && \
+              (tmp2 != HAL_FMPI2C_MODE_SLAVE))
+          {
+            /* Generate Stop */
+            hfmpi2c->Instance->CR2 |= FMPI2C_CR2_STOP;
+
+            /* Update Tick with new reference */
+            tickstart = HAL_GetTick();
+          }
+
+          while (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF) == RESET)
+          {
+            /* Check for the Timeout */
+            if ((HAL_GetTick() - tickstart) > FMPI2C_TIMEOUT_STOPF)
+            {
+              hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_TIMEOUT;
+              hfmpi2c->State = HAL_FMPI2C_STATE_READY;
+              hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE;
+
+              /* Process Unlocked */
+              __HAL_UNLOCK(hfmpi2c);
+
+              status = HAL_ERROR;
+            }
+          }
         }
       }
     }
@@ -6596,9 +6914,6 @@
       __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF);
     }
 
-    /* Clear NACKF Flag */
-    __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF);
-
     error_code |= HAL_FMPI2C_ERROR_AF;
 
     status = HAL_ERROR;
@@ -6689,14 +7004,14 @@
 
   /* Declaration of tmp to prevent undefined behavior of volatile usage */
   uint32_t tmp = ((uint32_t)(((uint32_t)DevAddress & FMPI2C_CR2_SADD) | \
-                            (((uint32_t)Size << FMPI2C_CR2_NBYTES_Pos) & FMPI2C_CR2_NBYTES) | \
-                              (uint32_t)Mode | (uint32_t)Request) & (~0x80000000U));
+                             (((uint32_t)Size << FMPI2C_CR2_NBYTES_Pos) & FMPI2C_CR2_NBYTES) | \
+                             (uint32_t)Mode | (uint32_t)Request) & (~0x80000000U));
 
   /* update CR2 register */
   MODIFY_REG(hfmpi2c->Instance->CR2, \
              ((FMPI2C_CR2_SADD | FMPI2C_CR2_NBYTES | FMPI2C_CR2_RELOAD | FMPI2C_CR2_AUTOEND | \
                (FMPI2C_CR2_RD_WRN & (uint32_t)(Request >> (31U - FMPI2C_CR2_RD_WRN_Pos))) | \
-                FMPI2C_CR2_START | FMPI2C_CR2_STOP)), tmp);
+               FMPI2C_CR2_START | FMPI2C_CR2_STOP)), tmp);
 }
 
 /**
@@ -6757,6 +7072,12 @@
       tmpisr |= FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI | FMPI2C_IT_RXI;
     }
 
+    if (InterruptRequest == FMPI2C_XFER_ERROR_IT)
+    {
+      /* Enable ERR and NACK interrupts */
+      tmpisr |= FMPI2C_IT_ERRI | FMPI2C_IT_NACKI;
+    }
+
     if (InterruptRequest == FMPI2C_XFER_CPLT_IT)
     {
       /* Enable STOP interrupts */
diff --git a/Src/stm32f4xx_hal_fmpsmbus.c b/Src/stm32f4xx_hal_fmpsmbus.c
index 700f25a..6a41c03 100644
--- a/Src/stm32f4xx_hal_fmpsmbus.c
+++ b/Src/stm32f4xx_hal_fmpsmbus.c
@@ -209,20 +209,28 @@
 /** @addtogroup FMPSMBUS_Private_Functions FMPSMBUS Private Functions
   * @{
   */
+/* Private functions to handle flags during polling transfer */
 static HAL_StatusTypeDef FMPSMBUS_WaitOnFlagUntilTimeout(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint32_t Flag,
                                                       FlagStatus Status, uint32_t Timeout);
 
-static void FMPSMBUS_Enable_IRQ(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint32_t InterruptRequest);
-static void FMPSMBUS_Disable_IRQ(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint32_t InterruptRequest);
+/* Private functions for FMPSMBUS transfer IRQ handler */
 static HAL_StatusTypeDef FMPSMBUS_Master_ISR(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint32_t StatusFlags);
 static HAL_StatusTypeDef FMPSMBUS_Slave_ISR(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint32_t StatusFlags);
-
-static void FMPSMBUS_ConvertOtherXferOptions(FMPSMBUS_HandleTypeDef *hfmpsmbus);
-
 static void FMPSMBUS_ITErrorHandler(FMPSMBUS_HandleTypeDef *hfmpsmbus);
 
+/* Private functions to centralize the enable/disable of Interrupts */
+static void FMPSMBUS_Enable_IRQ(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint32_t InterruptRequest);
+static void FMPSMBUS_Disable_IRQ(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint32_t InterruptRequest);
+
+/* Private function to flush TXDR register */
+static void FMPSMBUS_Flush_TXDR(FMPSMBUS_HandleTypeDef *hfmpsmbus);
+
+/* Private function to handle start, restart or stop a transfer */
 static void FMPSMBUS_TransferConfig(FMPSMBUS_HandleTypeDef *hfmpsmbus,  uint16_t DevAddress, uint8_t Size,
                                  uint32_t Mode, uint32_t Request);
+
+/* Private function to Convert Specific options */
+static void FMPSMBUS_ConvertOtherXferOptions(FMPSMBUS_HandleTypeDef *hfmpsmbus);
 /**
   * @}
   */
@@ -1872,6 +1880,9 @@
     /* No need to generate STOP, it is automatically done */
     hfmpsmbus->ErrorCode |= HAL_FMPSMBUS_ERROR_ACKF;
 
+    /* Flush TX register */
+    FMPSMBUS_Flush_TXDR(hfmpsmbus);
+
     /* Process Unlocked */
     __HAL_UNLOCK(hfmpsmbus);
 
@@ -2162,6 +2173,9 @@
       /* Clear NACK Flag */
       __HAL_FMPSMBUS_CLEAR_FLAG(hfmpsmbus, FMPSMBUS_FLAG_AF);
 
+      /* Flush TX register */
+      FMPSMBUS_Flush_TXDR(hfmpsmbus);
+
       /* Process Unlocked */
       __HAL_UNLOCK(hfmpsmbus);
     }
@@ -2183,6 +2197,9 @@
       /* Set ErrorCode corresponding to a Non-Acknowledge */
       hfmpsmbus->ErrorCode |= HAL_FMPSMBUS_ERROR_ACKF;
 
+      /* Flush TX register */
+      FMPSMBUS_Flush_TXDR(hfmpsmbus);
+
       /* Process Unlocked */
       __HAL_UNLOCK(hfmpsmbus);
 
@@ -2584,7 +2601,10 @@
     __HAL_FMPSMBUS_CLEAR_FLAG(hfmpsmbus, FMPSMBUS_FLAG_PECERR);
   }
 
-  /* Store current volatile hfmpsmbus->State, misra rule */
+  /* Flush TX register */
+  FMPSMBUS_Flush_TXDR(hfmpsmbus);
+
+  /* Store current volatile hfmpsmbus->ErrorCode, misra rule */
   tmperror = hfmpsmbus->ErrorCode;
 
   /* Call the Error Callback in case of Error detected */
@@ -2655,6 +2675,27 @@
 }
 
 /**
+  * @brief  FMPSMBUS Tx data register flush process.
+  * @param  hfmpsmbus FMPSMBUS handle.
+  * @retval None
+  */
+static void FMPSMBUS_Flush_TXDR(FMPSMBUS_HandleTypeDef *hfmpsmbus)
+{
+  /* If a pending TXIS flag is set */
+  /* Write a dummy data in TXDR to clear it */
+  if (__HAL_FMPSMBUS_GET_FLAG(hfmpsmbus, FMPSMBUS_FLAG_TXIS) != RESET)
+  {
+    hfmpsmbus->Instance->TXDR = 0x00U;
+  }
+
+  /* Flush TX register if not empty */
+  if (__HAL_FMPSMBUS_GET_FLAG(hfmpsmbus, FMPSMBUS_FLAG_TXE) == RESET)
+  {
+    __HAL_FMPSMBUS_CLEAR_FLAG(hfmpsmbus, FMPSMBUS_FLAG_TXE);
+  }
+}
+
+/**
   * @brief  Handle FMPSMBUSx communication when starting transfer or during transfer (TC or TCR flag are set).
   * @param  hfmpsmbus FMPSMBUS handle.
   * @param  DevAddress specifies the slave address to be programmed.