1 /**
2   ******************************************************************************
3   * @file    stm32f4xx_hal_fmpi2c.c
4   * @author  MCD Application Team
5   * @brief   FMPI2C HAL module driver.
6   *          This file provides firmware functions to manage the following
7   *          functionalities of the Inter Integrated Circuit (FMPI2C) peripheral:
8   *           + Initialization and de-initialization functions
9   *           + IO operation functions
10   *           + Peripheral State and Errors functions
11   *
12   ******************************************************************************
13   * @attention
14   *
15   * Copyright (c) 2016 STMicroelectronics.
16   * All rights reserved.
17   *
18   * This software is licensed under terms that can be found in the LICENSE file
19   * in the root directory of this software component.
20   * If no LICENSE file comes with this software, it is provided AS-IS.
21   *
22   ******************************************************************************
23   @verbatim
24   ==============================================================================
25                         ##### How to use this driver #####
26   ==============================================================================
27     [..]
28     The FMPI2C HAL driver can be used as follows:
29 
30     (#) Declare a FMPI2C_HandleTypeDef handle structure, for example:
31         FMPI2C_HandleTypeDef  hfmpi2c;
32 
33     (#)Initialize the FMPI2C low level resources by implementing the HAL_FMPI2C_MspInit() API:
34         (##) Enable the FMPI2Cx interface clock
35         (##) FMPI2C pins configuration
36             (+++) Enable the clock for the FMPI2C GPIOs
37             (+++) Configure FMPI2C pins as alternate function open-drain
38         (##) NVIC configuration if you need to use interrupt process
39             (+++) Configure the FMPI2Cx interrupt priority
40             (+++) Enable the NVIC FMPI2C IRQ Channel
41         (##) DMA Configuration if you need to use DMA process
42             (+++) Declare a DMA_HandleTypeDef handle structure for
43                   the transmit or receive stream
44             (+++) Enable the DMAx interface clock using
45             (+++) Configure the DMA handle parameters
46             (+++) Configure the DMA Tx or Rx stream
47             (+++) Associate the initialized DMA handle to the hfmpi2c DMA Tx or Rx handle
48             (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on
49                   the DMA Tx or Rx stream
50 
51     (#) Configure the Communication Clock Timing, Own Address1, Master Addressing mode, Dual Addressing mode,
52         Own Address2, Own Address2 Mask, General call and Nostretch mode in the hfmpi2c Init structure.
53 
54     (#) Initialize the FMPI2C registers by calling the HAL_FMPI2C_Init(), configures also the low level Hardware
55         (GPIO, CLOCK, NVIC...etc) by calling the customized HAL_FMPI2C_MspInit(&hfmpi2c) API.
56 
57     (#) To check if target device is ready for communication, use the function HAL_FMPI2C_IsDeviceReady()
58 
59     (#) For FMPI2C IO and IO MEM operations, three operation modes are available within this driver :
60 
61     *** Polling mode IO operation ***
62     =================================
63     [..]
64       (+) Transmit in master mode an amount of data in blocking mode using HAL_FMPI2C_Master_Transmit()
65       (+) Receive in master mode an amount of data in blocking mode using HAL_FMPI2C_Master_Receive()
66       (+) Transmit in slave mode an amount of data in blocking mode using HAL_FMPI2C_Slave_Transmit()
67       (+) Receive in slave mode an amount of data in blocking mode using HAL_FMPI2C_Slave_Receive()
68 
69     *** Polling mode IO MEM operation ***
70     =====================================
71     [..]
72       (+) Write an amount of data in blocking mode to a specific memory address using HAL_FMPI2C_Mem_Write()
73       (+) Read an amount of data in blocking mode from a specific memory address using HAL_FMPI2C_Mem_Read()
74 
75 
76     *** Interrupt mode IO operation ***
77     ===================================
78     [..]
79       (+) Transmit in master mode an amount of data in non-blocking mode using HAL_FMPI2C_Master_Transmit_IT()
80       (+) At transmission end of transfer, HAL_FMPI2C_MasterTxCpltCallback() is executed and users can
81            add their own code by customization of function pointer HAL_FMPI2C_MasterTxCpltCallback()
82       (+) Receive in master mode an amount of data in non-blocking mode using HAL_FMPI2C_Master_Receive_IT()
83       (+) At reception end of transfer, HAL_FMPI2C_MasterRxCpltCallback() is executed and users can
84            add their own code by customization of function pointer HAL_FMPI2C_MasterRxCpltCallback()
85       (+) Transmit in slave mode an amount of data in non-blocking mode using HAL_FMPI2C_Slave_Transmit_IT()
86       (+) At transmission end of transfer, HAL_FMPI2C_SlaveTxCpltCallback() is executed and users can
87            add their own code by customization of function pointer HAL_FMPI2C_SlaveTxCpltCallback()
88       (+) Receive in slave mode an amount of data in non-blocking mode using HAL_FMPI2C_Slave_Receive_IT()
89       (+) At reception end of transfer, HAL_FMPI2C_SlaveRxCpltCallback() is executed and users can
90            add their own code by customization of function pointer HAL_FMPI2C_SlaveRxCpltCallback()
91       (+) In case of transfer Error, HAL_FMPI2C_ErrorCallback() function is executed and users can
92            add their own code by customization of function pointer HAL_FMPI2C_ErrorCallback()
93       (+) Abort a master FMPI2C process communication with Interrupt using HAL_FMPI2C_Master_Abort_IT()
94       (+) End of abort process, HAL_FMPI2C_AbortCpltCallback() is executed and users can
95            add their own code by customization of function pointer HAL_FMPI2C_AbortCpltCallback()
96       (+) Discard a slave FMPI2C process communication using __HAL_FMPI2C_GENERATE_NACK() macro.
97            This action will inform Master to generate a Stop condition to discard the communication.
98 
99 
100     *** Interrupt mode or DMA mode IO sequential operation ***
101     ==========================================================
102     [..]
103       (@) These interfaces allow to manage a sequential transfer with a repeated start condition
104           when a direction change during transfer
105     [..]
106       (+) A specific option field manage the different steps of a sequential transfer
107       (+) Option field values are defined through FMPI2C_XFEROPTIONS and are listed below:
108       (++) FMPI2C_FIRST_AND_LAST_FRAME: No sequential usage, functional is same as associated interfaces in
109            no sequential mode
110       (++) FMPI2C_FIRST_FRAME: Sequential usage, this option allow to manage a sequence with start condition, address
111                             and data to transfer without a final stop condition
112       (++) FMPI2C_FIRST_AND_NEXT_FRAME: Sequential usage (Master only), this option allow to manage a sequence with
113                             start condition, address and data to transfer without a final stop condition,
114                             an then permit a call the same master sequential interface several times
115                             (like HAL_FMPI2C_Master_Seq_Transmit_IT() then HAL_FMPI2C_Master_Seq_Transmit_IT()
116                             or HAL_FMPI2C_Master_Seq_Transmit_DMA() then HAL_FMPI2C_Master_Seq_Transmit_DMA())
117       (++) FMPI2C_NEXT_FRAME: Sequential usage, this option allow to manage a sequence with a restart condition, address
118                             and with new data to transfer if the direction change or manage only the new data to
119                             transfer
120                             if no direction change and without a final stop condition in both cases
121       (++) FMPI2C_LAST_FRAME: Sequential usage, this option allow to manage a sequance with a restart condition, address
122                             and with new data to transfer if the direction change or manage only the new data to
123                             transfer
124                             if no direction change and with a final stop condition in both cases
125       (++) FMPI2C_LAST_FRAME_NO_STOP: Sequential usage (Master only), this option allow to manage a restart condition
126                             after several call of the same master sequential interface several times
127                             (link with option FMPI2C_FIRST_AND_NEXT_FRAME).
128                             Usage can, transfer several bytes one by one using
129                               HAL_FMPI2C_Master_Seq_Transmit_IT
130                               or HAL_FMPI2C_Master_Seq_Receive_IT
131                               or HAL_FMPI2C_Master_Seq_Transmit_DMA
132                               or HAL_FMPI2C_Master_Seq_Receive_DMA
133                               with option FMPI2C_FIRST_AND_NEXT_FRAME then FMPI2C_NEXT_FRAME.
134                              Then usage of this option FMPI2C_LAST_FRAME_NO_STOP at the last Transmit or
135                               Receive sequence permit to call the opposite interface Receive or Transmit
136                               without stopping the communication and so generate a restart condition.
137       (++) FMPI2C_OTHER_FRAME: Sequential usage (Master only), this option allow to manage a restart condition after
138                             each call of the same master sequential
139                             interface.
140                             Usage can, transfer several bytes one by one with a restart with slave address between
141                             each bytes using
142                               HAL_FMPI2C_Master_Seq_Transmit_IT
143                               or HAL_FMPI2C_Master_Seq_Receive_IT
144                               or HAL_FMPI2C_Master_Seq_Transmit_DMA
145                               or HAL_FMPI2C_Master_Seq_Receive_DMA
146                               with option FMPI2C_FIRST_FRAME then FMPI2C_OTHER_FRAME.
147                             Then usage of this option FMPI2C_OTHER_AND_LAST_FRAME at the last frame to help automatic
148                             generation of STOP condition.
149 
150       (+) Different sequential FMPI2C interfaces are listed below:
151       (++) Sequential transmit in master FMPI2C mode an amount of data in non-blocking mode using
152             HAL_FMPI2C_Master_Seq_Transmit_IT() or using HAL_FMPI2C_Master_Seq_Transmit_DMA()
153       (+++) At transmission end of current frame transfer, HAL_FMPI2C_MasterTxCpltCallback() is executed and
154             users can add their own code by customization of function pointer HAL_FMPI2C_MasterTxCpltCallback()
155       (++) Sequential receive in master FMPI2C mode an amount of data in non-blocking mode using
156             HAL_FMPI2C_Master_Seq_Receive_IT() or using HAL_FMPI2C_Master_Seq_Receive_DMA()
157       (+++) At reception end of current frame transfer, HAL_FMPI2C_MasterRxCpltCallback() is executed and users can
158            add their own code by customization of function pointer HAL_FMPI2C_MasterRxCpltCallback()
159       (++) Abort a master IT or DMA FMPI2C process communication with Interrupt using HAL_FMPI2C_Master_Abort_IT()
160       (+++) End of abort process, HAL_FMPI2C_AbortCpltCallback() is executed and users can
161            add their own code by customization of function pointer HAL_FMPI2C_AbortCpltCallback()
162       (++) Enable/disable the Address listen mode in slave FMPI2C mode using HAL_FMPI2C_EnableListen_IT()
163             HAL_FMPI2C_DisableListen_IT()
164       (+++) When address slave FMPI2C match, HAL_FMPI2C_AddrCallback() is executed and users can
165            add their own code to check the Address Match Code and the transmission direction request by master
166            (Write/Read).
167       (+++) At Listen mode end HAL_FMPI2C_ListenCpltCallback() is executed and users can
168           add their own code by customization of function pointer HAL_FMPI2C_ListenCpltCallback()
169       (++) Sequential transmit in slave FMPI2C mode an amount of data in non-blocking mode using
170             HAL_FMPI2C_Slave_Seq_Transmit_IT() or using HAL_FMPI2C_Slave_Seq_Transmit_DMA()
171       (+++) At transmission end of current frame transfer, HAL_FMPI2C_SlaveTxCpltCallback() is executed and
172             users can add their own code by customization of function pointer HAL_FMPI2C_SlaveTxCpltCallback()
173       (++) Sequential receive in slave FMPI2C mode an amount of data in non-blocking mode using
174             HAL_FMPI2C_Slave_Seq_Receive_IT() or using HAL_FMPI2C_Slave_Seq_Receive_DMA()
175       (+++) At reception end of current frame transfer, HAL_FMPI2C_SlaveRxCpltCallback() is executed and users can
176            add their own code by customization of function pointer HAL_FMPI2C_SlaveRxCpltCallback()
177       (++) In case of transfer Error, HAL_FMPI2C_ErrorCallback() function is executed and users can
178            add their own code by customization of function pointer HAL_FMPI2C_ErrorCallback()
179       (++) Discard a slave FMPI2C process communication using __HAL_FMPI2C_GENERATE_NACK() macro.
180            This action will inform Master to generate a Stop condition to discard the communication.
181 
182     *** Interrupt mode IO MEM operation ***
183     =======================================
184     [..]
185       (+) Write an amount of data in non-blocking mode with Interrupt to a specific memory address using
186           HAL_FMPI2C_Mem_Write_IT()
187       (+) At Memory end of write transfer, HAL_FMPI2C_MemTxCpltCallback() is executed and users can
188            add their own code by customization of function pointer HAL_FMPI2C_MemTxCpltCallback()
189       (+) Read an amount of data in non-blocking mode with Interrupt from a specific memory address using
190           HAL_FMPI2C_Mem_Read_IT()
191       (+) At Memory end of read transfer, HAL_FMPI2C_MemRxCpltCallback() is executed and users can
192            add their own code by customization of function pointer HAL_FMPI2C_MemRxCpltCallback()
193       (+) In case of transfer Error, HAL_FMPI2C_ErrorCallback() function is executed and users can
194            add their own code by customization of function pointer HAL_FMPI2C_ErrorCallback()
195 
196     *** DMA mode IO operation ***
197     ==============================
198     [..]
199       (+) Transmit in master mode an amount of data in non-blocking mode (DMA) using
200           HAL_FMPI2C_Master_Transmit_DMA()
201       (+) At transmission end of transfer, HAL_FMPI2C_MasterTxCpltCallback() is executed and users can
202            add their own code by customization of function pointer HAL_FMPI2C_MasterTxCpltCallback()
203       (+) Receive in master mode an amount of data in non-blocking mode (DMA) using
204           HAL_FMPI2C_Master_Receive_DMA()
205       (+) At reception end of transfer, HAL_FMPI2C_MasterRxCpltCallback() is executed and users can
206            add their own code by customization of function pointer HAL_FMPI2C_MasterRxCpltCallback()
207       (+) Transmit in slave mode an amount of data in non-blocking mode (DMA) using
208           HAL_FMPI2C_Slave_Transmit_DMA()
209       (+) At transmission end of transfer, HAL_FMPI2C_SlaveTxCpltCallback() is executed and users can
210            add their own code by customization of function pointer HAL_FMPI2C_SlaveTxCpltCallback()
211       (+) Receive in slave mode an amount of data in non-blocking mode (DMA) using
212           HAL_FMPI2C_Slave_Receive_DMA()
213       (+) At reception end of transfer, HAL_FMPI2C_SlaveRxCpltCallback() is executed and users can
214            add their own code by customization of function pointer HAL_FMPI2C_SlaveRxCpltCallback()
215       (+) In case of transfer Error, HAL_FMPI2C_ErrorCallback() function is executed and users can
216            add their own code by customization of function pointer HAL_FMPI2C_ErrorCallback()
217       (+) Abort a master FMPI2C process communication with Interrupt using HAL_FMPI2C_Master_Abort_IT()
218       (+) End of abort process, HAL_FMPI2C_AbortCpltCallback() is executed and users can
219            add their own code by customization of function pointer HAL_FMPI2C_AbortCpltCallback()
220       (+) Discard a slave FMPI2C process communication using __HAL_FMPI2C_GENERATE_NACK() macro.
221            This action will inform Master to generate a Stop condition to discard the communication.
222 
223     *** DMA mode IO MEM operation ***
224     =================================
225     [..]
226       (+) Write an amount of data in non-blocking mode with DMA to a specific memory address using
227           HAL_FMPI2C_Mem_Write_DMA()
228       (+) At Memory end of write transfer, HAL_FMPI2C_MemTxCpltCallback() is executed and users can
229            add their own code by customization of function pointer HAL_FMPI2C_MemTxCpltCallback()
230       (+) Read an amount of data in non-blocking mode with DMA from a specific memory address using
231           HAL_FMPI2C_Mem_Read_DMA()
232       (+) At Memory end of read transfer, HAL_FMPI2C_MemRxCpltCallback() is executed and users can
233            add their own code by customization of function pointer HAL_FMPI2C_MemRxCpltCallback()
234       (+) In case of transfer Error, HAL_FMPI2C_ErrorCallback() function is executed and users can
235            add their own code by customization of function pointer HAL_FMPI2C_ErrorCallback()
236 
237 
238      *** FMPI2C HAL driver macros list ***
239      ==================================
240      [..]
241        Below the list of most used macros in FMPI2C HAL driver.
242 
243       (+) __HAL_FMPI2C_ENABLE: Enable the FMPI2C peripheral
244       (+) __HAL_FMPI2C_DISABLE: Disable the FMPI2C peripheral
245       (+) __HAL_FMPI2C_GENERATE_NACK: Generate a Non-Acknowledge FMPI2C peripheral in Slave mode
246       (+) __HAL_FMPI2C_GET_FLAG: Check whether the specified FMPI2C flag is set or not
247       (+) __HAL_FMPI2C_CLEAR_FLAG: Clear the specified FMPI2C pending flag
248       (+) __HAL_FMPI2C_ENABLE_IT: Enable the specified FMPI2C interrupt
249       (+) __HAL_FMPI2C_DISABLE_IT: Disable the specified FMPI2C interrupt
250 
251      *** Callback registration ***
252      =============================================
253     [..]
254      The compilation flag USE_HAL_FMPI2C_REGISTER_CALLBACKS when set to 1
255      allows the user to configure dynamically the driver callbacks.
256      Use Functions HAL_FMPI2C_RegisterCallback() or HAL_FMPI2C_RegisterAddrCallback()
257      to register an interrupt callback.
258     [..]
259      Function HAL_FMPI2C_RegisterCallback() allows to register following callbacks:
260        (+) MasterTxCpltCallback : callback for Master transmission end of transfer.
261        (+) MasterRxCpltCallback : callback for Master reception end of transfer.
262        (+) SlaveTxCpltCallback  : callback for Slave transmission end of transfer.
263        (+) SlaveRxCpltCallback  : callback for Slave reception end of transfer.
264        (+) ListenCpltCallback   : callback for end of listen mode.
265        (+) MemTxCpltCallback    : callback for Memory transmission end of transfer.
266        (+) MemRxCpltCallback    : callback for Memory reception end of transfer.
267        (+) ErrorCallback        : callback for error detection.
268        (+) AbortCpltCallback    : callback for abort completion process.
269        (+) MspInitCallback      : callback for Msp Init.
270        (+) MspDeInitCallback    : callback for Msp DeInit.
271      This function takes as parameters the HAL peripheral handle, the Callback ID
272      and a pointer to the user callback function.
273     [..]
274      For specific callback AddrCallback use dedicated register callbacks : HAL_FMPI2C_RegisterAddrCallback().
275     [..]
276      Use function HAL_FMPI2C_UnRegisterCallback to reset a callback to the default
277      weak function.
278      HAL_FMPI2C_UnRegisterCallback takes as parameters the HAL peripheral handle,
279      and the Callback ID.
280      This function allows to reset following callbacks:
281        (+) MasterTxCpltCallback : callback for Master transmission end of transfer.
282        (+) MasterRxCpltCallback : callback for Master reception end of transfer.
283        (+) SlaveTxCpltCallback  : callback for Slave transmission end of transfer.
284        (+) SlaveRxCpltCallback  : callback for Slave reception end of transfer.
285        (+) ListenCpltCallback   : callback for end of listen mode.
286        (+) MemTxCpltCallback    : callback for Memory transmission end of transfer.
287        (+) MemRxCpltCallback    : callback for Memory reception end of transfer.
288        (+) ErrorCallback        : callback for error detection.
289        (+) AbortCpltCallback    : callback for abort completion process.
290        (+) MspInitCallback      : callback for Msp Init.
291        (+) MspDeInitCallback    : callback for Msp DeInit.
292     [..]
293      For callback AddrCallback use dedicated register callbacks : HAL_FMPI2C_UnRegisterAddrCallback().
294     [..]
295      By default, after the HAL_FMPI2C_Init() and when the state is HAL_FMPI2C_STATE_RESET
296      all callbacks are set to the corresponding weak functions:
297      examples HAL_FMPI2C_MasterTxCpltCallback(), HAL_FMPI2C_MasterRxCpltCallback().
298      Exception done for MspInit and MspDeInit functions that are
299      reset to the legacy weak functions in the HAL_FMPI2C_Init()/ HAL_FMPI2C_DeInit() only when
300      these callbacks are null (not registered beforehand).
301      If MspInit or MspDeInit are not null, the HAL_FMPI2C_Init()/ HAL_FMPI2C_DeInit()
302      keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state.
303     [..]
304      Callbacks can be registered/unregistered in HAL_FMPI2C_STATE_READY state only.
305      Exception done MspInit/MspDeInit functions that can be registered/unregistered
306      in HAL_FMPI2C_STATE_READY or HAL_FMPI2C_STATE_RESET state,
307      thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit.
308      Then, the user first registers the MspInit/MspDeInit user callbacks
309      using HAL_FMPI2C_RegisterCallback() before calling HAL_FMPI2C_DeInit()
310      or HAL_FMPI2C_Init() function.
311     [..]
312      When the compilation flag USE_HAL_FMPI2C_REGISTER_CALLBACKS is set to 0 or
313      not defined, the callback registration feature is not available and all callbacks
314      are set to the corresponding weak functions.
315 
316      [..]
317        (@) You can refer to the FMPI2C HAL driver header file for more useful macros
318 
319   @endverbatim
320   */
321 
322 /* Includes ------------------------------------------------------------------*/
323 #include "stm32f4xx_hal.h"
324 
325 /** @addtogroup STM32F4xx_HAL_Driver
326   * @{
327   */
328 
329 /** @defgroup FMPI2C FMPI2C
330   * @brief FMPI2C HAL module driver
331   * @{
332   */
333 
334 #ifdef HAL_FMPI2C_MODULE_ENABLED
335 #if defined(FMPI2C_CR1_PE)
336 
337 /* Private typedef -----------------------------------------------------------*/
338 /* Private define ------------------------------------------------------------*/
339 
340 /** @defgroup FMPI2C_Private_Define FMPI2C Private Define
341   * @{
342   */
343 #define TIMING_CLEAR_MASK   (0xF0FFFFFFU)  /*!< FMPI2C TIMING clear register Mask */
344 #define FMPI2C_TIMEOUT_ADDR    (10000U)       /*!< 10 s  */
345 #define FMPI2C_TIMEOUT_BUSY    (25U)          /*!< 25 ms */
346 #define FMPI2C_TIMEOUT_DIR     (25U)          /*!< 25 ms */
347 #define FMPI2C_TIMEOUT_RXNE    (25U)          /*!< 25 ms */
348 #define FMPI2C_TIMEOUT_STOPF   (25U)          /*!< 25 ms */
349 #define FMPI2C_TIMEOUT_TC      (25U)          /*!< 25 ms */
350 #define FMPI2C_TIMEOUT_TCR     (25U)          /*!< 25 ms */
351 #define FMPI2C_TIMEOUT_TXIS    (25U)          /*!< 25 ms */
352 #define FMPI2C_TIMEOUT_FLAG    (25U)          /*!< 25 ms */
353 
354 #define MAX_NBYTE_SIZE      255U
355 #define SLAVE_ADDR_SHIFT     7U
356 #define SLAVE_ADDR_MSK       0x06U
357 
358 /* Private define for @ref PreviousState usage */
359 #define FMPI2C_STATE_MSK             ((uint32_t)((uint32_t)((uint32_t)HAL_FMPI2C_STATE_BUSY_TX | \
360                                                             (uint32_t)HAL_FMPI2C_STATE_BUSY_RX) & \
361                                                  (uint32_t)(~((uint32_t)HAL_FMPI2C_STATE_READY))))
362 /*!< Mask State define, keep only RX and TX bits */
363 #define FMPI2C_STATE_NONE            ((uint32_t)(HAL_FMPI2C_MODE_NONE))
364 /*!< Default Value */
365 #define FMPI2C_STATE_MASTER_BUSY_TX  ((uint32_t)(((uint32_t)HAL_FMPI2C_STATE_BUSY_TX & FMPI2C_STATE_MSK) | \
366                                                  (uint32_t)HAL_FMPI2C_MODE_MASTER))
367 /*!< Master Busy TX, combinaison of State LSB and Mode enum */
368 #define FMPI2C_STATE_MASTER_BUSY_RX  ((uint32_t)(((uint32_t)HAL_FMPI2C_STATE_BUSY_RX & FMPI2C_STATE_MSK) | \
369                                                  (uint32_t)HAL_FMPI2C_MODE_MASTER))
370 /*!< Master Busy RX, combinaison of State LSB and Mode enum */
371 #define FMPI2C_STATE_SLAVE_BUSY_TX   ((uint32_t)(((uint32_t)HAL_FMPI2C_STATE_BUSY_TX & FMPI2C_STATE_MSK) | \
372                                                  (uint32_t)HAL_FMPI2C_MODE_SLAVE))
373 /*!< Slave Busy TX, combinaison of State LSB and Mode enum */
374 #define FMPI2C_STATE_SLAVE_BUSY_RX   ((uint32_t)(((uint32_t)HAL_FMPI2C_STATE_BUSY_RX & FMPI2C_STATE_MSK) | \
375                                                  (uint32_t)HAL_FMPI2C_MODE_SLAVE))
376 /*!< Slave Busy RX, combinaison of State LSB and Mode enum  */
377 #define FMPI2C_STATE_MEM_BUSY_TX     ((uint32_t)(((uint32_t)HAL_FMPI2C_STATE_BUSY_TX & FMPI2C_STATE_MSK) | \
378                                                  (uint32_t)HAL_FMPI2C_MODE_MEM))
379 /*!< Memory Busy TX, combinaison of State LSB and Mode enum */
380 #define FMPI2C_STATE_MEM_BUSY_RX     ((uint32_t)(((uint32_t)HAL_FMPI2C_STATE_BUSY_RX & FMPI2C_STATE_MSK) | \
381                                                  (uint32_t)HAL_FMPI2C_MODE_MEM))
382 /*!< Memory Busy RX, combinaison of State LSB and Mode enum */
383 
384 
385 /* Private define to centralize the enable/disable of Interrupts */
386 #define FMPI2C_XFER_TX_IT          (uint16_t)(0x0001U)   /*!< Bit field can be combinated with
387                                                          @ref FMPI2C_XFER_LISTEN_IT */
388 #define FMPI2C_XFER_RX_IT          (uint16_t)(0x0002U)   /*!< Bit field can be combinated with
389                                                          @ref FMPI2C_XFER_LISTEN_IT */
390 #define FMPI2C_XFER_LISTEN_IT      (uint16_t)(0x8000U)   /*!< Bit field can be combinated with @ref FMPI2C_XFER_TX_IT
391                                                          and @ref FMPI2C_XFER_RX_IT */
392 
393 #define FMPI2C_XFER_ERROR_IT       (uint16_t)(0x0010U)   /*!< Bit definition to manage addition of global Error
394                                                          and NACK treatment */
395 #define FMPI2C_XFER_CPLT_IT        (uint16_t)(0x0020U)   /*!< Bit definition to manage only STOP evenement */
396 #define FMPI2C_XFER_RELOAD_IT      (uint16_t)(0x0040U)   /*!< Bit definition to manage only Reload of NBYTE */
397 
398 /* Private define Sequential Transfer Options default/reset value */
399 #define FMPI2C_NO_OPTION_FRAME     (0xFFFF0000U)
400 /**
401   * @}
402   */
403 
404 /* Private macros ------------------------------------------------------------*/
405 /** @addtogroup FMPI2C_Private_Macro
406   * @{
407   */
408 /* Macro to get remaining data to transfer on DMA side */
409 #define FMPI2C_GET_DMA_REMAIN_DATA(__HANDLE__)     __HAL_DMA_GET_COUNTER(__HANDLE__)
410 /**
411   * @}
412   */
413 
414 /* Private variables ---------------------------------------------------------*/
415 /* Private function prototypes -----------------------------------------------*/
416 
417 /** @defgroup FMPI2C_Private_Functions FMPI2C Private Functions
418   * @{
419   */
420 /* Private functions to handle DMA transfer */
421 static void FMPI2C_DMAMasterTransmitCplt(DMA_HandleTypeDef *hdma);
422 static void FMPI2C_DMAMasterReceiveCplt(DMA_HandleTypeDef *hdma);
423 static void FMPI2C_DMASlaveTransmitCplt(DMA_HandleTypeDef *hdma);
424 static void FMPI2C_DMASlaveReceiveCplt(DMA_HandleTypeDef *hdma);
425 static void FMPI2C_DMAError(DMA_HandleTypeDef *hdma);
426 static void FMPI2C_DMAAbort(DMA_HandleTypeDef *hdma);
427 
428 
429 /* Private functions to handle IT transfer */
430 static void FMPI2C_ITAddrCplt(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags);
431 static void FMPI2C_ITMasterSeqCplt(FMPI2C_HandleTypeDef *hfmpi2c);
432 static void FMPI2C_ITSlaveSeqCplt(FMPI2C_HandleTypeDef *hfmpi2c);
433 static void FMPI2C_ITMasterCplt(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags);
434 static void FMPI2C_ITSlaveCplt(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags);
435 static void FMPI2C_ITListenCplt(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags);
436 static void FMPI2C_ITError(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ErrorCode);
437 
438 /* Private functions to handle IT transfer */
439 static HAL_StatusTypeDef FMPI2C_RequestMemoryWrite(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress,
440                                                    uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout,
441                                                    uint32_t Tickstart);
442 static HAL_StatusTypeDef FMPI2C_RequestMemoryRead(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress,
443                                                   uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout,
444                                                   uint32_t Tickstart);
445 
446 /* Private functions for FMPI2C transfer IRQ handler */
447 static HAL_StatusTypeDef FMPI2C_Master_ISR_IT(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags,
448                                               uint32_t ITSources);
449 static HAL_StatusTypeDef FMPI2C_Mem_ISR_IT(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags,
450                                            uint32_t ITSources);
451 static HAL_StatusTypeDef FMPI2C_Slave_ISR_IT(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags,
452                                              uint32_t ITSources);
453 static HAL_StatusTypeDef FMPI2C_Master_ISR_DMA(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags,
454                                                uint32_t ITSources);
455 static HAL_StatusTypeDef FMPI2C_Mem_ISR_DMA(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags,
456                                             uint32_t ITSources);
457 static HAL_StatusTypeDef FMPI2C_Slave_ISR_DMA(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags,
458                                               uint32_t ITSources);
459 
460 /* Private functions to handle flags during polling transfer */
461 static HAL_StatusTypeDef FMPI2C_WaitOnFlagUntilTimeout(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t Flag, FlagStatus Status,
462                                                        uint32_t Timeout, uint32_t Tickstart);
463 static HAL_StatusTypeDef FMPI2C_WaitOnTXISFlagUntilTimeout(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t Timeout,
464                                                            uint32_t Tickstart);
465 static HAL_StatusTypeDef FMPI2C_WaitOnRXNEFlagUntilTimeout(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t Timeout,
466                                                            uint32_t Tickstart);
467 static HAL_StatusTypeDef FMPI2C_WaitOnSTOPFlagUntilTimeout(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t Timeout,
468                                                            uint32_t Tickstart);
469 static HAL_StatusTypeDef FMPI2C_IsErrorOccurred(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t Timeout,
470                                                 uint32_t Tickstart);
471 
472 /* Private functions to centralize the enable/disable of Interrupts */
473 static void FMPI2C_Enable_IRQ(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t InterruptRequest);
474 static void FMPI2C_Disable_IRQ(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t InterruptRequest);
475 
476 /* Private function to treat different error callback */
477 static void FMPI2C_TreatErrorCallback(FMPI2C_HandleTypeDef *hfmpi2c);
478 
479 /* Private function to flush TXDR register */
480 static void FMPI2C_Flush_TXDR(FMPI2C_HandleTypeDef *hfmpi2c);
481 
482 /* Private function to handle  start, restart or stop a transfer */
483 static void FMPI2C_TransferConfig(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t Size, uint32_t Mode,
484                                   uint32_t Request);
485 
486 /* Private function to Convert Specific options */
487 static void FMPI2C_ConvertOtherXferOptions(FMPI2C_HandleTypeDef *hfmpi2c);
488 /**
489   * @}
490   */
491 
492 /* Exported functions --------------------------------------------------------*/
493 
494 /** @defgroup FMPI2C_Exported_Functions FMPI2C Exported Functions
495   * @{
496   */
497 
498 /** @defgroup FMPI2C_Exported_Functions_Group1 Initialization and de-initialization functions
499   *  @brief    Initialization and Configuration functions
500   *
501 @verbatim
502  ===============================================================================
503               ##### Initialization and de-initialization functions #####
504  ===============================================================================
505     [..]  This subsection provides a set of functions allowing to initialize and
506           deinitialize the FMPI2Cx peripheral:
507 
508       (+) User must Implement HAL_FMPI2C_MspInit() function in which he configures
509           all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
510 
511       (+) Call the function HAL_FMPI2C_Init() to configure the selected device with
512           the selected configuration:
513         (++) Clock Timing
514         (++) Own Address 1
515         (++) Addressing mode (Master, Slave)
516         (++) Dual Addressing mode
517         (++) Own Address 2
518         (++) Own Address 2 Mask
519         (++) General call mode
520         (++) Nostretch mode
521 
522       (+) Call the function HAL_FMPI2C_DeInit() to restore the default configuration
523           of the selected FMPI2Cx peripheral.
524 
525 @endverbatim
526   * @{
527   */
528 
529 /**
530   * @brief  Initializes the FMPI2C according to the specified parameters
531   *         in the FMPI2C_InitTypeDef and initialize the associated handle.
532   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
533   *                the configuration information for the specified FMPI2C.
534   * @retval HAL status
535   */
HAL_FMPI2C_Init(FMPI2C_HandleTypeDef * hfmpi2c)536 HAL_StatusTypeDef HAL_FMPI2C_Init(FMPI2C_HandleTypeDef *hfmpi2c)
537 {
538   /* Check the FMPI2C handle allocation */
539   if (hfmpi2c == NULL)
540   {
541     return HAL_ERROR;
542   }
543 
544   /* Check the parameters */
545   assert_param(IS_FMPI2C_ALL_INSTANCE(hfmpi2c->Instance));
546   assert_param(IS_FMPI2C_OWN_ADDRESS1(hfmpi2c->Init.OwnAddress1));
547   assert_param(IS_FMPI2C_ADDRESSING_MODE(hfmpi2c->Init.AddressingMode));
548   assert_param(IS_FMPI2C_DUAL_ADDRESS(hfmpi2c->Init.DualAddressMode));
549   assert_param(IS_FMPI2C_OWN_ADDRESS2(hfmpi2c->Init.OwnAddress2));
550   assert_param(IS_FMPI2C_OWN_ADDRESS2_MASK(hfmpi2c->Init.OwnAddress2Masks));
551   assert_param(IS_FMPI2C_GENERAL_CALL(hfmpi2c->Init.GeneralCallMode));
552   assert_param(IS_FMPI2C_NO_STRETCH(hfmpi2c->Init.NoStretchMode));
553 
554   if (hfmpi2c->State == HAL_FMPI2C_STATE_RESET)
555   {
556     /* Allocate lock resource and initialize it */
557     hfmpi2c->Lock = HAL_UNLOCKED;
558 
559 #if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1)
560     /* Init the FMPI2C Callback settings */
561     hfmpi2c->MasterTxCpltCallback = HAL_FMPI2C_MasterTxCpltCallback; /* Legacy weak MasterTxCpltCallback */
562     hfmpi2c->MasterRxCpltCallback = HAL_FMPI2C_MasterRxCpltCallback; /* Legacy weak MasterRxCpltCallback */
563     hfmpi2c->SlaveTxCpltCallback  = HAL_FMPI2C_SlaveTxCpltCallback;  /* Legacy weak SlaveTxCpltCallback  */
564     hfmpi2c->SlaveRxCpltCallback  = HAL_FMPI2C_SlaveRxCpltCallback;  /* Legacy weak SlaveRxCpltCallback  */
565     hfmpi2c->ListenCpltCallback   = HAL_FMPI2C_ListenCpltCallback;   /* Legacy weak ListenCpltCallback   */
566     hfmpi2c->MemTxCpltCallback    = HAL_FMPI2C_MemTxCpltCallback;    /* Legacy weak MemTxCpltCallback    */
567     hfmpi2c->MemRxCpltCallback    = HAL_FMPI2C_MemRxCpltCallback;    /* Legacy weak MemRxCpltCallback    */
568     hfmpi2c->ErrorCallback        = HAL_FMPI2C_ErrorCallback;        /* Legacy weak ErrorCallback        */
569     hfmpi2c->AbortCpltCallback    = HAL_FMPI2C_AbortCpltCallback;    /* Legacy weak AbortCpltCallback    */
570     hfmpi2c->AddrCallback         = HAL_FMPI2C_AddrCallback;         /* Legacy weak AddrCallback         */
571 
572     if (hfmpi2c->MspInitCallback == NULL)
573     {
574       hfmpi2c->MspInitCallback = HAL_FMPI2C_MspInit; /* Legacy weak MspInit  */
575     }
576 
577     /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */
578     hfmpi2c->MspInitCallback(hfmpi2c);
579 #else
580     /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */
581     HAL_FMPI2C_MspInit(hfmpi2c);
582 #endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */
583   }
584 
585   hfmpi2c->State = HAL_FMPI2C_STATE_BUSY;
586 
587   /* Disable the selected FMPI2C peripheral */
588   __HAL_FMPI2C_DISABLE(hfmpi2c);
589 
590   /*---------------------------- FMPI2Cx TIMINGR Configuration ------------------*/
591   /* Configure FMPI2Cx: Frequency range */
592   hfmpi2c->Instance->TIMINGR = hfmpi2c->Init.Timing & TIMING_CLEAR_MASK;
593 
594   /*---------------------------- FMPI2Cx OAR1 Configuration ---------------------*/
595   /* Disable Own Address1 before set the Own Address1 configuration */
596   hfmpi2c->Instance->OAR1 &= ~FMPI2C_OAR1_OA1EN;
597 
598   /* Configure FMPI2Cx: Own Address1 and ack own address1 mode */
599   if (hfmpi2c->Init.AddressingMode == FMPI2C_ADDRESSINGMODE_7BIT)
600   {
601     hfmpi2c->Instance->OAR1 = (FMPI2C_OAR1_OA1EN | hfmpi2c->Init.OwnAddress1);
602   }
603   else /* FMPI2C_ADDRESSINGMODE_10BIT */
604   {
605     hfmpi2c->Instance->OAR1 = (FMPI2C_OAR1_OA1EN | FMPI2C_OAR1_OA1MODE | hfmpi2c->Init.OwnAddress1);
606   }
607 
608   /*---------------------------- FMPI2Cx CR2 Configuration ----------------------*/
609   /* Configure FMPI2Cx: Addressing Master mode */
610   if (hfmpi2c->Init.AddressingMode == FMPI2C_ADDRESSINGMODE_10BIT)
611   {
612     SET_BIT(hfmpi2c->Instance->CR2, FMPI2C_CR2_ADD10);
613   }
614   else
615   {
616     /* Clear the FMPI2C ADD10 bit */
617     CLEAR_BIT(hfmpi2c->Instance->CR2, FMPI2C_CR2_ADD10);
618   }
619   /* Enable the AUTOEND by default, and enable NACK (should be disable only during Slave process */
620   hfmpi2c->Instance->CR2 |= (FMPI2C_CR2_AUTOEND | FMPI2C_CR2_NACK);
621 
622   /*---------------------------- FMPI2Cx OAR2 Configuration ---------------------*/
623   /* Disable Own Address2 before set the Own Address2 configuration */
624   hfmpi2c->Instance->OAR2 &= ~FMPI2C_DUALADDRESS_ENABLE;
625 
626   /* Configure FMPI2Cx: Dual mode and Own Address2 */
627   hfmpi2c->Instance->OAR2 = (hfmpi2c->Init.DualAddressMode | hfmpi2c->Init.OwnAddress2 | \
628                              (hfmpi2c->Init.OwnAddress2Masks << 8));
629 
630   /*---------------------------- FMPI2Cx CR1 Configuration ----------------------*/
631   /* Configure FMPI2Cx: Generalcall and NoStretch mode */
632   hfmpi2c->Instance->CR1 = (hfmpi2c->Init.GeneralCallMode | hfmpi2c->Init.NoStretchMode);
633 
634   /* Enable the selected FMPI2C peripheral */
635   __HAL_FMPI2C_ENABLE(hfmpi2c);
636 
637   hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE;
638   hfmpi2c->State = HAL_FMPI2C_STATE_READY;
639   hfmpi2c->PreviousState = FMPI2C_STATE_NONE;
640   hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE;
641 
642   return HAL_OK;
643 }
644 
645 /**
646   * @brief  DeInitialize the FMPI2C peripheral.
647   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
648   *                the configuration information for the specified FMPI2C.
649   * @retval HAL status
650   */
HAL_FMPI2C_DeInit(FMPI2C_HandleTypeDef * hfmpi2c)651 HAL_StatusTypeDef HAL_FMPI2C_DeInit(FMPI2C_HandleTypeDef *hfmpi2c)
652 {
653   /* Check the FMPI2C handle allocation */
654   if (hfmpi2c == NULL)
655   {
656     return HAL_ERROR;
657   }
658 
659   /* Check the parameters */
660   assert_param(IS_FMPI2C_ALL_INSTANCE(hfmpi2c->Instance));
661 
662   hfmpi2c->State = HAL_FMPI2C_STATE_BUSY;
663 
664   /* Disable the FMPI2C Peripheral Clock */
665   __HAL_FMPI2C_DISABLE(hfmpi2c);
666 
667 #if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1)
668   if (hfmpi2c->MspDeInitCallback == NULL)
669   {
670     hfmpi2c->MspDeInitCallback = HAL_FMPI2C_MspDeInit; /* Legacy weak MspDeInit  */
671   }
672 
673   /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
674   hfmpi2c->MspDeInitCallback(hfmpi2c);
675 #else
676   /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
677   HAL_FMPI2C_MspDeInit(hfmpi2c);
678 #endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */
679 
680   hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE;
681   hfmpi2c->State = HAL_FMPI2C_STATE_RESET;
682   hfmpi2c->PreviousState = FMPI2C_STATE_NONE;
683   hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE;
684 
685   /* Release Lock */
686   __HAL_UNLOCK(hfmpi2c);
687 
688   return HAL_OK;
689 }
690 
691 /**
692   * @brief Initialize the FMPI2C MSP.
693   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
694   *                the configuration information for the specified FMPI2C.
695   * @retval None
696   */
HAL_FMPI2C_MspInit(FMPI2C_HandleTypeDef * hfmpi2c)697 __weak void HAL_FMPI2C_MspInit(FMPI2C_HandleTypeDef *hfmpi2c)
698 {
699   /* Prevent unused argument(s) compilation warning */
700   UNUSED(hfmpi2c);
701 
702   /* NOTE : This function should not be modified, when the callback is needed,
703             the HAL_FMPI2C_MspInit could be implemented in the user file
704    */
705 }
706 
707 /**
708   * @brief DeInitialize the FMPI2C MSP.
709   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
710   *                the configuration information for the specified FMPI2C.
711   * @retval None
712   */
HAL_FMPI2C_MspDeInit(FMPI2C_HandleTypeDef * hfmpi2c)713 __weak void HAL_FMPI2C_MspDeInit(FMPI2C_HandleTypeDef *hfmpi2c)
714 {
715   /* Prevent unused argument(s) compilation warning */
716   UNUSED(hfmpi2c);
717 
718   /* NOTE : This function should not be modified, when the callback is needed,
719             the HAL_FMPI2C_MspDeInit could be implemented in the user file
720    */
721 }
722 
723 #if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1)
724 /**
725   * @brief  Register a User FMPI2C Callback
726   *         To be used instead of the weak predefined callback
727   * @note   The HAL_FMPI2C_RegisterCallback() may be called before HAL_FMPI2C_Init() in HAL_FMPI2C_STATE_RESET
728   *         to register callbacks for HAL_FMPI2C_MSPINIT_CB_ID and HAL_FMPI2C_MSPDEINIT_CB_ID.
729   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
730   *                the configuration information for the specified FMPI2C.
731   * @param  CallbackID ID of the callback to be registered
732   *         This parameter can be one of the following values:
733   *          @arg @ref HAL_FMPI2C_MASTER_TX_COMPLETE_CB_ID Master Tx Transfer completed callback ID
734   *          @arg @ref HAL_FMPI2C_MASTER_RX_COMPLETE_CB_ID Master Rx Transfer completed callback ID
735   *          @arg @ref HAL_FMPI2C_SLAVE_TX_COMPLETE_CB_ID Slave Tx Transfer completed callback ID
736   *          @arg @ref HAL_FMPI2C_SLAVE_RX_COMPLETE_CB_ID Slave Rx Transfer completed callback ID
737   *          @arg @ref HAL_FMPI2C_LISTEN_COMPLETE_CB_ID Listen Complete callback ID
738   *          @arg @ref HAL_FMPI2C_MEM_TX_COMPLETE_CB_ID Memory Tx Transfer callback ID
739   *          @arg @ref HAL_FMPI2C_MEM_RX_COMPLETE_CB_ID Memory Rx Transfer completed callback ID
740   *          @arg @ref HAL_FMPI2C_ERROR_CB_ID Error callback ID
741   *          @arg @ref HAL_FMPI2C_ABORT_CB_ID Abort callback ID
742   *          @arg @ref HAL_FMPI2C_MSPINIT_CB_ID MspInit callback ID
743   *          @arg @ref HAL_FMPI2C_MSPDEINIT_CB_ID MspDeInit callback ID
744   * @param  pCallback pointer to the Callback function
745   * @retval HAL status
746   */
HAL_FMPI2C_RegisterCallback(FMPI2C_HandleTypeDef * hfmpi2c,HAL_FMPI2C_CallbackIDTypeDef CallbackID,pFMPI2C_CallbackTypeDef pCallback)747 HAL_StatusTypeDef HAL_FMPI2C_RegisterCallback(FMPI2C_HandleTypeDef *hfmpi2c, HAL_FMPI2C_CallbackIDTypeDef CallbackID,
748                                               pFMPI2C_CallbackTypeDef pCallback)
749 {
750   HAL_StatusTypeDef status = HAL_OK;
751 
752   if (pCallback == NULL)
753   {
754     /* Update the error code */
755     hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_INVALID_CALLBACK;
756 
757     return HAL_ERROR;
758   }
759 
760   if (HAL_FMPI2C_STATE_READY == hfmpi2c->State)
761   {
762     switch (CallbackID)
763     {
764       case HAL_FMPI2C_MASTER_TX_COMPLETE_CB_ID :
765         hfmpi2c->MasterTxCpltCallback = pCallback;
766         break;
767 
768       case HAL_FMPI2C_MASTER_RX_COMPLETE_CB_ID :
769         hfmpi2c->MasterRxCpltCallback = pCallback;
770         break;
771 
772       case HAL_FMPI2C_SLAVE_TX_COMPLETE_CB_ID :
773         hfmpi2c->SlaveTxCpltCallback = pCallback;
774         break;
775 
776       case HAL_FMPI2C_SLAVE_RX_COMPLETE_CB_ID :
777         hfmpi2c->SlaveRxCpltCallback = pCallback;
778         break;
779 
780       case HAL_FMPI2C_LISTEN_COMPLETE_CB_ID :
781         hfmpi2c->ListenCpltCallback = pCallback;
782         break;
783 
784       case HAL_FMPI2C_MEM_TX_COMPLETE_CB_ID :
785         hfmpi2c->MemTxCpltCallback = pCallback;
786         break;
787 
788       case HAL_FMPI2C_MEM_RX_COMPLETE_CB_ID :
789         hfmpi2c->MemRxCpltCallback = pCallback;
790         break;
791 
792       case HAL_FMPI2C_ERROR_CB_ID :
793         hfmpi2c->ErrorCallback = pCallback;
794         break;
795 
796       case HAL_FMPI2C_ABORT_CB_ID :
797         hfmpi2c->AbortCpltCallback = pCallback;
798         break;
799 
800       case HAL_FMPI2C_MSPINIT_CB_ID :
801         hfmpi2c->MspInitCallback = pCallback;
802         break;
803 
804       case HAL_FMPI2C_MSPDEINIT_CB_ID :
805         hfmpi2c->MspDeInitCallback = pCallback;
806         break;
807 
808       default :
809         /* Update the error code */
810         hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_INVALID_CALLBACK;
811 
812         /* Return error status */
813         status =  HAL_ERROR;
814         break;
815     }
816   }
817   else if (HAL_FMPI2C_STATE_RESET == hfmpi2c->State)
818   {
819     switch (CallbackID)
820     {
821       case HAL_FMPI2C_MSPINIT_CB_ID :
822         hfmpi2c->MspInitCallback = pCallback;
823         break;
824 
825       case HAL_FMPI2C_MSPDEINIT_CB_ID :
826         hfmpi2c->MspDeInitCallback = pCallback;
827         break;
828 
829       default :
830         /* Update the error code */
831         hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_INVALID_CALLBACK;
832 
833         /* Return error status */
834         status =  HAL_ERROR;
835         break;
836     }
837   }
838   else
839   {
840     /* Update the error code */
841     hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_INVALID_CALLBACK;
842 
843     /* Return error status */
844     status =  HAL_ERROR;
845   }
846 
847   return status;
848 }
849 
850 /**
851   * @brief  Unregister an FMPI2C Callback
852   *         FMPI2C callback is redirected to the weak predefined callback
853   * @note   The HAL_FMPI2C_UnRegisterCallback() may be called before HAL_FMPI2C_Init() in HAL_FMPI2C_STATE_RESET
854   *         to un-register callbacks for HAL_FMPI2C_MSPINIT_CB_ID and HAL_FMPI2C_MSPDEINIT_CB_ID.
855   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
856   *                the configuration information for the specified FMPI2C.
857   * @param  CallbackID ID of the callback to be unregistered
858   *         This parameter can be one of the following values:
859   *         This parameter can be one of the following values:
860   *          @arg @ref HAL_FMPI2C_MASTER_TX_COMPLETE_CB_ID Master Tx Transfer completed callback ID
861   *          @arg @ref HAL_FMPI2C_MASTER_RX_COMPLETE_CB_ID Master Rx Transfer completed callback ID
862   *          @arg @ref HAL_FMPI2C_SLAVE_TX_COMPLETE_CB_ID Slave Tx Transfer completed callback ID
863   *          @arg @ref HAL_FMPI2C_SLAVE_RX_COMPLETE_CB_ID Slave Rx Transfer completed callback ID
864   *          @arg @ref HAL_FMPI2C_LISTEN_COMPLETE_CB_ID Listen Complete callback ID
865   *          @arg @ref HAL_FMPI2C_MEM_TX_COMPLETE_CB_ID Memory Tx Transfer callback ID
866   *          @arg @ref HAL_FMPI2C_MEM_RX_COMPLETE_CB_ID Memory Rx Transfer completed callback ID
867   *          @arg @ref HAL_FMPI2C_ERROR_CB_ID Error callback ID
868   *          @arg @ref HAL_FMPI2C_ABORT_CB_ID Abort callback ID
869   *          @arg @ref HAL_FMPI2C_MSPINIT_CB_ID MspInit callback ID
870   *          @arg @ref HAL_FMPI2C_MSPDEINIT_CB_ID MspDeInit callback ID
871   * @retval HAL status
872   */
HAL_FMPI2C_UnRegisterCallback(FMPI2C_HandleTypeDef * hfmpi2c,HAL_FMPI2C_CallbackIDTypeDef CallbackID)873 HAL_StatusTypeDef HAL_FMPI2C_UnRegisterCallback(FMPI2C_HandleTypeDef *hfmpi2c, HAL_FMPI2C_CallbackIDTypeDef CallbackID)
874 {
875   HAL_StatusTypeDef status = HAL_OK;
876 
877   if (HAL_FMPI2C_STATE_READY == hfmpi2c->State)
878   {
879     switch (CallbackID)
880     {
881       case HAL_FMPI2C_MASTER_TX_COMPLETE_CB_ID :
882         hfmpi2c->MasterTxCpltCallback = HAL_FMPI2C_MasterTxCpltCallback; /* Legacy weak MasterTxCpltCallback */
883         break;
884 
885       case HAL_FMPI2C_MASTER_RX_COMPLETE_CB_ID :
886         hfmpi2c->MasterRxCpltCallback = HAL_FMPI2C_MasterRxCpltCallback; /* Legacy weak MasterRxCpltCallback */
887         break;
888 
889       case HAL_FMPI2C_SLAVE_TX_COMPLETE_CB_ID :
890         hfmpi2c->SlaveTxCpltCallback = HAL_FMPI2C_SlaveTxCpltCallback;   /* Legacy weak SlaveTxCpltCallback  */
891         break;
892 
893       case HAL_FMPI2C_SLAVE_RX_COMPLETE_CB_ID :
894         hfmpi2c->SlaveRxCpltCallback = HAL_FMPI2C_SlaveRxCpltCallback;   /* Legacy weak SlaveRxCpltCallback  */
895         break;
896 
897       case HAL_FMPI2C_LISTEN_COMPLETE_CB_ID :
898         hfmpi2c->ListenCpltCallback = HAL_FMPI2C_ListenCpltCallback;     /* Legacy weak ListenCpltCallback   */
899         break;
900 
901       case HAL_FMPI2C_MEM_TX_COMPLETE_CB_ID :
902         hfmpi2c->MemTxCpltCallback = HAL_FMPI2C_MemTxCpltCallback;       /* Legacy weak MemTxCpltCallback    */
903         break;
904 
905       case HAL_FMPI2C_MEM_RX_COMPLETE_CB_ID :
906         hfmpi2c->MemRxCpltCallback = HAL_FMPI2C_MemRxCpltCallback;       /* Legacy weak MemRxCpltCallback    */
907         break;
908 
909       case HAL_FMPI2C_ERROR_CB_ID :
910         hfmpi2c->ErrorCallback = HAL_FMPI2C_ErrorCallback;               /* Legacy weak ErrorCallback        */
911         break;
912 
913       case HAL_FMPI2C_ABORT_CB_ID :
914         hfmpi2c->AbortCpltCallback = HAL_FMPI2C_AbortCpltCallback;       /* Legacy weak AbortCpltCallback    */
915         break;
916 
917       case HAL_FMPI2C_MSPINIT_CB_ID :
918         hfmpi2c->MspInitCallback = HAL_FMPI2C_MspInit;                   /* Legacy weak MspInit              */
919         break;
920 
921       case HAL_FMPI2C_MSPDEINIT_CB_ID :
922         hfmpi2c->MspDeInitCallback = HAL_FMPI2C_MspDeInit;               /* Legacy weak MspDeInit            */
923         break;
924 
925       default :
926         /* Update the error code */
927         hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_INVALID_CALLBACK;
928 
929         /* Return error status */
930         status =  HAL_ERROR;
931         break;
932     }
933   }
934   else if (HAL_FMPI2C_STATE_RESET == hfmpi2c->State)
935   {
936     switch (CallbackID)
937     {
938       case HAL_FMPI2C_MSPINIT_CB_ID :
939         hfmpi2c->MspInitCallback = HAL_FMPI2C_MspInit;                   /* Legacy weak MspInit              */
940         break;
941 
942       case HAL_FMPI2C_MSPDEINIT_CB_ID :
943         hfmpi2c->MspDeInitCallback = HAL_FMPI2C_MspDeInit;               /* Legacy weak MspDeInit            */
944         break;
945 
946       default :
947         /* Update the error code */
948         hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_INVALID_CALLBACK;
949 
950         /* Return error status */
951         status =  HAL_ERROR;
952         break;
953     }
954   }
955   else
956   {
957     /* Update the error code */
958     hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_INVALID_CALLBACK;
959 
960     /* Return error status */
961     status =  HAL_ERROR;
962   }
963 
964   return status;
965 }
966 
967 /**
968   * @brief  Register the Slave Address Match FMPI2C Callback
969   *         To be used instead of the weak HAL_FMPI2C_AddrCallback() predefined callback
970   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
971   *                the configuration information for the specified FMPI2C.
972   * @param  pCallback pointer to the Address Match Callback function
973   * @retval HAL status
974   */
HAL_FMPI2C_RegisterAddrCallback(FMPI2C_HandleTypeDef * hfmpi2c,pFMPI2C_AddrCallbackTypeDef pCallback)975 HAL_StatusTypeDef HAL_FMPI2C_RegisterAddrCallback(FMPI2C_HandleTypeDef *hfmpi2c, pFMPI2C_AddrCallbackTypeDef pCallback)
976 {
977   HAL_StatusTypeDef status = HAL_OK;
978 
979   if (pCallback == NULL)
980   {
981     /* Update the error code */
982     hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_INVALID_CALLBACK;
983 
984     return HAL_ERROR;
985   }
986 
987   if (HAL_FMPI2C_STATE_READY == hfmpi2c->State)
988   {
989     hfmpi2c->AddrCallback = pCallback;
990   }
991   else
992   {
993     /* Update the error code */
994     hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_INVALID_CALLBACK;
995 
996     /* Return error status */
997     status =  HAL_ERROR;
998   }
999 
1000   return status;
1001 }
1002 
1003 /**
1004   * @brief  UnRegister the Slave Address Match FMPI2C Callback
1005   *         Info Ready FMPI2C Callback is redirected to the weak HAL_FMPI2C_AddrCallback() predefined callback
1006   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
1007   *                the configuration information for the specified FMPI2C.
1008   * @retval HAL status
1009   */
HAL_FMPI2C_UnRegisterAddrCallback(FMPI2C_HandleTypeDef * hfmpi2c)1010 HAL_StatusTypeDef HAL_FMPI2C_UnRegisterAddrCallback(FMPI2C_HandleTypeDef *hfmpi2c)
1011 {
1012   HAL_StatusTypeDef status = HAL_OK;
1013 
1014   if (HAL_FMPI2C_STATE_READY == hfmpi2c->State)
1015   {
1016     hfmpi2c->AddrCallback = HAL_FMPI2C_AddrCallback; /* Legacy weak AddrCallback  */
1017   }
1018   else
1019   {
1020     /* Update the error code */
1021     hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_INVALID_CALLBACK;
1022 
1023     /* Return error status */
1024     status =  HAL_ERROR;
1025   }
1026 
1027   return status;
1028 }
1029 
1030 #endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */
1031 
1032 /**
1033   * @}
1034   */
1035 
1036 /** @defgroup FMPI2C_Exported_Functions_Group2 Input and Output operation functions
1037   *  @brief   Data transfers functions
1038   *
1039 @verbatim
1040  ===============================================================================
1041                       ##### IO operation functions #####
1042  ===============================================================================
1043     [..]
1044     This subsection provides a set of functions allowing to manage the FMPI2C data
1045     transfers.
1046 
1047     (#) There are two modes of transfer:
1048        (++) Blocking mode : The communication is performed in the polling mode.
1049             The status of all data processing is returned by the same function
1050             after finishing transfer.
1051        (++) No-Blocking mode : The communication is performed using Interrupts
1052             or DMA. These functions return the status of the transfer startup.
1053             The end of the data processing will be indicated through the
1054             dedicated FMPI2C IRQ when using Interrupt mode or the DMA IRQ when
1055             using DMA mode.
1056 
1057     (#) Blocking mode functions are :
1058         (++) HAL_FMPI2C_Master_Transmit()
1059         (++) HAL_FMPI2C_Master_Receive()
1060         (++) HAL_FMPI2C_Slave_Transmit()
1061         (++) HAL_FMPI2C_Slave_Receive()
1062         (++) HAL_FMPI2C_Mem_Write()
1063         (++) HAL_FMPI2C_Mem_Read()
1064         (++) HAL_FMPI2C_IsDeviceReady()
1065 
1066     (#) No-Blocking mode functions with Interrupt are :
1067         (++) HAL_FMPI2C_Master_Transmit_IT()
1068         (++) HAL_FMPI2C_Master_Receive_IT()
1069         (++) HAL_FMPI2C_Slave_Transmit_IT()
1070         (++) HAL_FMPI2C_Slave_Receive_IT()
1071         (++) HAL_FMPI2C_Mem_Write_IT()
1072         (++) HAL_FMPI2C_Mem_Read_IT()
1073         (++) HAL_FMPI2C_Master_Seq_Transmit_IT()
1074         (++) HAL_FMPI2C_Master_Seq_Receive_IT()
1075         (++) HAL_FMPI2C_Slave_Seq_Transmit_IT()
1076         (++) HAL_FMPI2C_Slave_Seq_Receive_IT()
1077         (++) HAL_FMPI2C_EnableListen_IT()
1078         (++) HAL_FMPI2C_DisableListen_IT()
1079         (++) HAL_FMPI2C_Master_Abort_IT()
1080 
1081     (#) No-Blocking mode functions with DMA are :
1082         (++) HAL_FMPI2C_Master_Transmit_DMA()
1083         (++) HAL_FMPI2C_Master_Receive_DMA()
1084         (++) HAL_FMPI2C_Slave_Transmit_DMA()
1085         (++) HAL_FMPI2C_Slave_Receive_DMA()
1086         (++) HAL_FMPI2C_Mem_Write_DMA()
1087         (++) HAL_FMPI2C_Mem_Read_DMA()
1088         (++) HAL_FMPI2C_Master_Seq_Transmit_DMA()
1089         (++) HAL_FMPI2C_Master_Seq_Receive_DMA()
1090         (++) HAL_FMPI2C_Slave_Seq_Transmit_DMA()
1091         (++) HAL_FMPI2C_Slave_Seq_Receive_DMA()
1092 
1093     (#) A set of Transfer Complete Callbacks are provided in non Blocking mode:
1094         (++) HAL_FMPI2C_MasterTxCpltCallback()
1095         (++) HAL_FMPI2C_MasterRxCpltCallback()
1096         (++) HAL_FMPI2C_SlaveTxCpltCallback()
1097         (++) HAL_FMPI2C_SlaveRxCpltCallback()
1098         (++) HAL_FMPI2C_MemTxCpltCallback()
1099         (++) HAL_FMPI2C_MemRxCpltCallback()
1100         (++) HAL_FMPI2C_AddrCallback()
1101         (++) HAL_FMPI2C_ListenCpltCallback()
1102         (++) HAL_FMPI2C_ErrorCallback()
1103         (++) HAL_FMPI2C_AbortCpltCallback()
1104 
1105 @endverbatim
1106   * @{
1107   */
1108 
1109 /**
1110   * @brief  Transmits in master mode an amount of data in blocking mode.
1111   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
1112   *                the configuration information for the specified FMPI2C.
1113   * @param  DevAddress Target device address: The device 7 bits address value
1114   *         in datasheet must be shifted to the left before calling the interface
1115   * @param  pData Pointer to data buffer
1116   * @param  Size Amount of data to be sent
1117   * @param  Timeout Timeout duration
1118   * @retval HAL status
1119   */
HAL_FMPI2C_Master_Transmit(FMPI2C_HandleTypeDef * hfmpi2c,uint16_t DevAddress,uint8_t * pData,uint16_t Size,uint32_t Timeout)1120 HAL_StatusTypeDef HAL_FMPI2C_Master_Transmit(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t *pData,
1121                                              uint16_t Size, uint32_t Timeout)
1122 {
1123   uint32_t tickstart;
1124   uint32_t xfermode;
1125 
1126   if (hfmpi2c->State == HAL_FMPI2C_STATE_READY)
1127   {
1128     /* Process Locked */
1129     __HAL_LOCK(hfmpi2c);
1130 
1131     /* Init tickstart for timeout management*/
1132     tickstart = HAL_GetTick();
1133 
1134     if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_BUSY, SET, FMPI2C_TIMEOUT_BUSY, tickstart) != HAL_OK)
1135     {
1136       return HAL_ERROR;
1137     }
1138 
1139     hfmpi2c->State     = HAL_FMPI2C_STATE_BUSY_TX;
1140     hfmpi2c->Mode      = HAL_FMPI2C_MODE_MASTER;
1141     hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE;
1142 
1143     /* Prepare transfer parameters */
1144     hfmpi2c->pBuffPtr  = pData;
1145     hfmpi2c->XferCount = Size;
1146     hfmpi2c->XferISR   = NULL;
1147 
1148     if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
1149     {
1150       hfmpi2c->XferSize = MAX_NBYTE_SIZE;
1151       xfermode = FMPI2C_RELOAD_MODE;
1152     }
1153     else
1154     {
1155       hfmpi2c->XferSize = hfmpi2c->XferCount;
1156       xfermode = FMPI2C_AUTOEND_MODE;
1157     }
1158 
1159     if (hfmpi2c->XferSize > 0U)
1160     {
1161       /* Preload TX register */
1162       /* Write data to TXDR */
1163       hfmpi2c->Instance->TXDR = *hfmpi2c->pBuffPtr;
1164 
1165       /* Increment Buffer pointer */
1166       hfmpi2c->pBuffPtr++;
1167 
1168       hfmpi2c->XferCount--;
1169       hfmpi2c->XferSize--;
1170 
1171       /* Send Slave Address */
1172       /* Set NBYTES to write and reload if hfmpi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
1173       FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)(hfmpi2c->XferSize + 1U), xfermode,
1174                             FMPI2C_GENERATE_START_WRITE);
1175     }
1176     else
1177     {
1178       /* Send Slave Address */
1179       /* Set NBYTES to write and reload if hfmpi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
1180       FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, xfermode,
1181                             FMPI2C_GENERATE_START_WRITE);
1182     }
1183 
1184     while (hfmpi2c->XferCount > 0U)
1185     {
1186       /* Wait until TXIS flag is set */
1187       if (FMPI2C_WaitOnTXISFlagUntilTimeout(hfmpi2c, Timeout, tickstart) != HAL_OK)
1188       {
1189         return HAL_ERROR;
1190       }
1191       /* Write data to TXDR */
1192       hfmpi2c->Instance->TXDR = *hfmpi2c->pBuffPtr;
1193 
1194       /* Increment Buffer pointer */
1195       hfmpi2c->pBuffPtr++;
1196 
1197       hfmpi2c->XferCount--;
1198       hfmpi2c->XferSize--;
1199 
1200       if ((hfmpi2c->XferCount != 0U) && (hfmpi2c->XferSize == 0U))
1201       {
1202         /* Wait until TCR flag is set */
1203         if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK)
1204         {
1205           return HAL_ERROR;
1206         }
1207 
1208         if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
1209         {
1210           hfmpi2c->XferSize = MAX_NBYTE_SIZE;
1211           FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_RELOAD_MODE,
1212                                 FMPI2C_NO_STARTSTOP);
1213         }
1214         else
1215         {
1216           hfmpi2c->XferSize = hfmpi2c->XferCount;
1217           FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_AUTOEND_MODE,
1218                                 FMPI2C_NO_STARTSTOP);
1219         }
1220       }
1221     }
1222 
1223     /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
1224     /* Wait until STOPF flag is set */
1225     if (FMPI2C_WaitOnSTOPFlagUntilTimeout(hfmpi2c, Timeout, tickstart) != HAL_OK)
1226     {
1227       return HAL_ERROR;
1228     }
1229 
1230     /* Clear STOP Flag */
1231     __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF);
1232 
1233     /* Clear Configuration Register 2 */
1234     FMPI2C_RESET_CR2(hfmpi2c);
1235 
1236     hfmpi2c->State = HAL_FMPI2C_STATE_READY;
1237     hfmpi2c->Mode  = HAL_FMPI2C_MODE_NONE;
1238 
1239     /* Process Unlocked */
1240     __HAL_UNLOCK(hfmpi2c);
1241 
1242     return HAL_OK;
1243   }
1244   else
1245   {
1246     return HAL_BUSY;
1247   }
1248 }
1249 
1250 /**
1251   * @brief  Receives in master mode an amount of data in blocking mode.
1252   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
1253   *                the configuration information for the specified FMPI2C.
1254   * @param  DevAddress Target device address: The device 7 bits address value
1255   *         in datasheet must be shifted to the left before calling the interface
1256   * @param  pData Pointer to data buffer
1257   * @param  Size Amount of data to be sent
1258   * @param  Timeout Timeout duration
1259   * @retval HAL status
1260   */
HAL_FMPI2C_Master_Receive(FMPI2C_HandleTypeDef * hfmpi2c,uint16_t DevAddress,uint8_t * pData,uint16_t Size,uint32_t Timeout)1261 HAL_StatusTypeDef HAL_FMPI2C_Master_Receive(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t *pData,
1262                                             uint16_t Size, uint32_t Timeout)
1263 {
1264   uint32_t tickstart;
1265 
1266   if (hfmpi2c->State == HAL_FMPI2C_STATE_READY)
1267   {
1268     /* Process Locked */
1269     __HAL_LOCK(hfmpi2c);
1270 
1271     /* Init tickstart for timeout management*/
1272     tickstart = HAL_GetTick();
1273 
1274     if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_BUSY, SET, FMPI2C_TIMEOUT_BUSY, tickstart) != HAL_OK)
1275     {
1276       return HAL_ERROR;
1277     }
1278 
1279     hfmpi2c->State     = HAL_FMPI2C_STATE_BUSY_RX;
1280     hfmpi2c->Mode      = HAL_FMPI2C_MODE_MASTER;
1281     hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE;
1282 
1283     /* Prepare transfer parameters */
1284     hfmpi2c->pBuffPtr  = pData;
1285     hfmpi2c->XferCount = Size;
1286     hfmpi2c->XferISR   = NULL;
1287 
1288     /* Send Slave Address */
1289     /* Set NBYTES to write and reload if hfmpi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
1290     if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
1291     {
1292       hfmpi2c->XferSize = 1U;
1293       FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_RELOAD_MODE,
1294                             FMPI2C_GENERATE_START_READ);
1295     }
1296     else
1297     {
1298       hfmpi2c->XferSize = hfmpi2c->XferCount;
1299       FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_AUTOEND_MODE,
1300                             FMPI2C_GENERATE_START_READ);
1301     }
1302 
1303     while (hfmpi2c->XferCount > 0U)
1304     {
1305       /* Wait until RXNE flag is set */
1306       if (FMPI2C_WaitOnRXNEFlagUntilTimeout(hfmpi2c, Timeout, tickstart) != HAL_OK)
1307       {
1308         return HAL_ERROR;
1309       }
1310 
1311       /* Read data from RXDR */
1312       *hfmpi2c->pBuffPtr = (uint8_t)hfmpi2c->Instance->RXDR;
1313 
1314       /* Increment Buffer pointer */
1315       hfmpi2c->pBuffPtr++;
1316 
1317       hfmpi2c->XferSize--;
1318       hfmpi2c->XferCount--;
1319 
1320       if ((hfmpi2c->XferCount != 0U) && (hfmpi2c->XferSize == 0U))
1321       {
1322         /* Wait until TCR flag is set */
1323         if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK)
1324         {
1325           return HAL_ERROR;
1326         }
1327 
1328         if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
1329         {
1330           hfmpi2c->XferSize = MAX_NBYTE_SIZE;
1331           FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_RELOAD_MODE,
1332                                 FMPI2C_NO_STARTSTOP);
1333         }
1334         else
1335         {
1336           hfmpi2c->XferSize = hfmpi2c->XferCount;
1337           FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_AUTOEND_MODE,
1338                                 FMPI2C_NO_STARTSTOP);
1339         }
1340       }
1341     }
1342 
1343     /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
1344     /* Wait until STOPF flag is set */
1345     if (FMPI2C_WaitOnSTOPFlagUntilTimeout(hfmpi2c, Timeout, tickstart) != HAL_OK)
1346     {
1347       return HAL_ERROR;
1348     }
1349 
1350     /* Clear STOP Flag */
1351     __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF);
1352 
1353     /* Clear Configuration Register 2 */
1354     FMPI2C_RESET_CR2(hfmpi2c);
1355 
1356     hfmpi2c->State = HAL_FMPI2C_STATE_READY;
1357     hfmpi2c->Mode  = HAL_FMPI2C_MODE_NONE;
1358 
1359     /* Process Unlocked */
1360     __HAL_UNLOCK(hfmpi2c);
1361 
1362     return HAL_OK;
1363   }
1364   else
1365   {
1366     return HAL_BUSY;
1367   }
1368 }
1369 
1370 /**
1371   * @brief  Transmits in slave mode an amount of data in blocking mode.
1372   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
1373   *                the configuration information for the specified FMPI2C.
1374   * @param  pData Pointer to data buffer
1375   * @param  Size Amount of data to be sent
1376   * @param  Timeout Timeout duration
1377   * @retval HAL status
1378   */
HAL_FMPI2C_Slave_Transmit(FMPI2C_HandleTypeDef * hfmpi2c,uint8_t * pData,uint16_t Size,uint32_t Timeout)1379 HAL_StatusTypeDef HAL_FMPI2C_Slave_Transmit(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t *pData, uint16_t Size,
1380                                             uint32_t Timeout)
1381 {
1382   uint32_t tickstart;
1383   uint16_t tmpXferCount;
1384   HAL_StatusTypeDef error;
1385 
1386   if (hfmpi2c->State == HAL_FMPI2C_STATE_READY)
1387   {
1388     if ((pData == NULL) || (Size == 0U))
1389     {
1390       hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_INVALID_PARAM;
1391       return  HAL_ERROR;
1392     }
1393     /* Process Locked */
1394     __HAL_LOCK(hfmpi2c);
1395 
1396     /* Init tickstart for timeout management*/
1397     tickstart = HAL_GetTick();
1398 
1399     hfmpi2c->State     = HAL_FMPI2C_STATE_BUSY_TX;
1400     hfmpi2c->Mode      = HAL_FMPI2C_MODE_SLAVE;
1401     hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE;
1402 
1403     /* Prepare transfer parameters */
1404     hfmpi2c->pBuffPtr  = pData;
1405     hfmpi2c->XferCount = Size;
1406     hfmpi2c->XferISR   = NULL;
1407 
1408     /* Enable Address Acknowledge */
1409     hfmpi2c->Instance->CR2 &= ~FMPI2C_CR2_NACK;
1410 
1411     /* Wait until ADDR flag is set */
1412     if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK)
1413     {
1414       /* Disable Address Acknowledge */
1415       hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK;
1416       return HAL_ERROR;
1417     }
1418 
1419     /* Preload TX data if no stretch enable */
1420     if (hfmpi2c->Init.NoStretchMode == FMPI2C_NOSTRETCH_ENABLE)
1421     {
1422       /* Preload TX register */
1423       /* Write data to TXDR */
1424       hfmpi2c->Instance->TXDR = *hfmpi2c->pBuffPtr;
1425 
1426       /* Increment Buffer pointer */
1427       hfmpi2c->pBuffPtr++;
1428 
1429       hfmpi2c->XferCount--;
1430     }
1431 
1432     /* Clear ADDR flag */
1433     __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_ADDR);
1434 
1435     /* If 10bit addressing mode is selected */
1436     if (hfmpi2c->Init.AddressingMode == FMPI2C_ADDRESSINGMODE_10BIT)
1437     {
1438       /* Wait until ADDR flag is set */
1439       if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK)
1440       {
1441         /* Disable Address Acknowledge */
1442         hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK;
1443         return HAL_ERROR;
1444       }
1445 
1446       /* Clear ADDR flag */
1447       __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_ADDR);
1448     }
1449 
1450     /* Wait until DIR flag is set Transmitter mode */
1451     if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_DIR, RESET, Timeout, tickstart) != HAL_OK)
1452     {
1453       /* Disable Address Acknowledge */
1454       hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK;
1455       return HAL_ERROR;
1456     }
1457 
1458     while (hfmpi2c->XferCount > 0U)
1459     {
1460       /* Wait until TXIS flag is set */
1461       if (FMPI2C_WaitOnTXISFlagUntilTimeout(hfmpi2c, Timeout, tickstart) != HAL_OK)
1462       {
1463         /* Disable Address Acknowledge */
1464         hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK;
1465         return HAL_ERROR;
1466       }
1467 
1468       /* Write data to TXDR */
1469       hfmpi2c->Instance->TXDR = *hfmpi2c->pBuffPtr;
1470 
1471       /* Increment Buffer pointer */
1472       hfmpi2c->pBuffPtr++;
1473 
1474       hfmpi2c->XferCount--;
1475     }
1476 
1477     /* Wait until AF flag is set */
1478     error = FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_AF, RESET, Timeout, tickstart);
1479 
1480     if (error != HAL_OK)
1481     {
1482       /* Check that FMPI2C transfer finished */
1483       /* if yes, normal use case, a NACK is sent by the MASTER when Transfer is finished */
1484       /* Mean XferCount == 0 */
1485 
1486       tmpXferCount = hfmpi2c->XferCount;
1487       if ((hfmpi2c->ErrorCode == HAL_FMPI2C_ERROR_AF) && (tmpXferCount == 0U))
1488       {
1489         /* Reset ErrorCode to NONE */
1490         hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE;
1491       }
1492       else
1493       {
1494         /* Disable Address Acknowledge */
1495         hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK;
1496         return HAL_ERROR;
1497       }
1498     }
1499     else
1500     {
1501       /* Flush TX register */
1502       FMPI2C_Flush_TXDR(hfmpi2c);
1503 
1504       /* Clear AF flag */
1505       __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF);
1506 
1507       /* Wait until STOP flag is set */
1508       if (FMPI2C_WaitOnSTOPFlagUntilTimeout(hfmpi2c, Timeout, tickstart) != HAL_OK)
1509       {
1510         /* Disable Address Acknowledge */
1511         hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK;
1512 
1513         return HAL_ERROR;
1514       }
1515 
1516       /* Clear STOP flag */
1517       __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF);
1518     }
1519 
1520     /* Wait until BUSY flag is reset */
1521     if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_BUSY, SET, Timeout, tickstart) != HAL_OK)
1522     {
1523       /* Disable Address Acknowledge */
1524       hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK;
1525       return HAL_ERROR;
1526     }
1527 
1528     /* Disable Address Acknowledge */
1529     hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK;
1530 
1531     hfmpi2c->State = HAL_FMPI2C_STATE_READY;
1532     hfmpi2c->Mode  = HAL_FMPI2C_MODE_NONE;
1533 
1534     /* Process Unlocked */
1535     __HAL_UNLOCK(hfmpi2c);
1536 
1537     return HAL_OK;
1538   }
1539   else
1540   {
1541     return HAL_BUSY;
1542   }
1543 }
1544 
1545 /**
1546   * @brief  Receive in slave mode an amount of data in blocking mode
1547   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
1548   *                the configuration information for the specified FMPI2C.
1549   * @param  pData Pointer to data buffer
1550   * @param  Size Amount of data to be sent
1551   * @param  Timeout Timeout duration
1552   * @retval HAL status
1553   */
HAL_FMPI2C_Slave_Receive(FMPI2C_HandleTypeDef * hfmpi2c,uint8_t * pData,uint16_t Size,uint32_t Timeout)1554 HAL_StatusTypeDef HAL_FMPI2C_Slave_Receive(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t *pData, uint16_t Size,
1555                                            uint32_t Timeout)
1556 {
1557   uint32_t tickstart;
1558 
1559   if (hfmpi2c->State == HAL_FMPI2C_STATE_READY)
1560   {
1561     if ((pData == NULL) || (Size == 0U))
1562     {
1563       hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_INVALID_PARAM;
1564       return  HAL_ERROR;
1565     }
1566     /* Process Locked */
1567     __HAL_LOCK(hfmpi2c);
1568 
1569     /* Init tickstart for timeout management*/
1570     tickstart = HAL_GetTick();
1571 
1572     hfmpi2c->State     = HAL_FMPI2C_STATE_BUSY_RX;
1573     hfmpi2c->Mode      = HAL_FMPI2C_MODE_SLAVE;
1574     hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE;
1575 
1576     /* Prepare transfer parameters */
1577     hfmpi2c->pBuffPtr  = pData;
1578     hfmpi2c->XferCount = Size;
1579     hfmpi2c->XferSize = hfmpi2c->XferCount;
1580     hfmpi2c->XferISR   = NULL;
1581 
1582     /* Enable Address Acknowledge */
1583     hfmpi2c->Instance->CR2 &= ~FMPI2C_CR2_NACK;
1584 
1585     /* Wait until ADDR flag is set */
1586     if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK)
1587     {
1588       /* Disable Address Acknowledge */
1589       hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK;
1590       return HAL_ERROR;
1591     }
1592 
1593     /* Clear ADDR flag */
1594     __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_ADDR);
1595 
1596     /* Wait until DIR flag is reset Receiver mode */
1597     if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_DIR, SET, Timeout, tickstart) != HAL_OK)
1598     {
1599       /* Disable Address Acknowledge */
1600       hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK;
1601       return HAL_ERROR;
1602     }
1603 
1604     while (hfmpi2c->XferCount > 0U)
1605     {
1606       /* Wait until RXNE flag is set */
1607       if (FMPI2C_WaitOnRXNEFlagUntilTimeout(hfmpi2c, Timeout, tickstart) != HAL_OK)
1608       {
1609         /* Disable Address Acknowledge */
1610         hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK;
1611 
1612         /* Store Last receive data if any */
1613         if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_RXNE) == SET)
1614         {
1615           /* Read data from RXDR */
1616           *hfmpi2c->pBuffPtr = (uint8_t)hfmpi2c->Instance->RXDR;
1617 
1618           /* Increment Buffer pointer */
1619           hfmpi2c->pBuffPtr++;
1620 
1621           hfmpi2c->XferCount--;
1622           hfmpi2c->XferSize--;
1623         }
1624 
1625         return HAL_ERROR;
1626       }
1627 
1628       /* Read data from RXDR */
1629       *hfmpi2c->pBuffPtr = (uint8_t)hfmpi2c->Instance->RXDR;
1630 
1631       /* Increment Buffer pointer */
1632       hfmpi2c->pBuffPtr++;
1633 
1634       hfmpi2c->XferCount--;
1635       hfmpi2c->XferSize--;
1636     }
1637 
1638     /* Wait until STOP flag is set */
1639     if (FMPI2C_WaitOnSTOPFlagUntilTimeout(hfmpi2c, Timeout, tickstart) != HAL_OK)
1640     {
1641       /* Disable Address Acknowledge */
1642       hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK;
1643       return HAL_ERROR;
1644     }
1645 
1646     /* Clear STOP flag */
1647     __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF);
1648 
1649     /* Wait until BUSY flag is reset */
1650     if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_BUSY, SET, Timeout, tickstart) != HAL_OK)
1651     {
1652       /* Disable Address Acknowledge */
1653       hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK;
1654       return HAL_ERROR;
1655     }
1656 
1657     /* Disable Address Acknowledge */
1658     hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK;
1659 
1660     hfmpi2c->State = HAL_FMPI2C_STATE_READY;
1661     hfmpi2c->Mode  = HAL_FMPI2C_MODE_NONE;
1662 
1663     /* Process Unlocked */
1664     __HAL_UNLOCK(hfmpi2c);
1665 
1666     return HAL_OK;
1667   }
1668   else
1669   {
1670     return HAL_BUSY;
1671   }
1672 }
1673 
1674 /**
1675   * @brief  Transmit in master mode an amount of data in non-blocking mode with Interrupt
1676   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
1677   *                the configuration information for the specified FMPI2C.
1678   * @param  DevAddress Target device address: The device 7 bits address value
1679   *         in datasheet must be shifted to the left before calling the interface
1680   * @param  pData Pointer to data buffer
1681   * @param  Size Amount of data to be sent
1682   * @retval HAL status
1683   */
HAL_FMPI2C_Master_Transmit_IT(FMPI2C_HandleTypeDef * hfmpi2c,uint16_t DevAddress,uint8_t * pData,uint16_t Size)1684 HAL_StatusTypeDef HAL_FMPI2C_Master_Transmit_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t *pData,
1685                                                 uint16_t Size)
1686 {
1687   uint32_t xfermode;
1688 
1689   if (hfmpi2c->State == HAL_FMPI2C_STATE_READY)
1690   {
1691     if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_BUSY) == SET)
1692     {
1693       return HAL_BUSY;
1694     }
1695 
1696     /* Process Locked */
1697     __HAL_LOCK(hfmpi2c);
1698 
1699     hfmpi2c->State       = HAL_FMPI2C_STATE_BUSY_TX;
1700     hfmpi2c->Mode        = HAL_FMPI2C_MODE_MASTER;
1701     hfmpi2c->ErrorCode   = HAL_FMPI2C_ERROR_NONE;
1702 
1703     /* Prepare transfer parameters */
1704     hfmpi2c->pBuffPtr    = pData;
1705     hfmpi2c->XferCount   = Size;
1706     hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME;
1707     hfmpi2c->XferISR     = FMPI2C_Master_ISR_IT;
1708 
1709     if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
1710     {
1711       hfmpi2c->XferSize = MAX_NBYTE_SIZE;
1712       xfermode = FMPI2C_RELOAD_MODE;
1713     }
1714     else
1715     {
1716       hfmpi2c->XferSize = hfmpi2c->XferCount;
1717       xfermode = FMPI2C_AUTOEND_MODE;
1718     }
1719 
1720     /* Send Slave Address */
1721     /* Set NBYTES to write and reload if hfmpi2c->XferCount > MAX_NBYTE_SIZE */
1722     if (hfmpi2c->XferSize > 0U)
1723     {
1724       /* Preload TX register */
1725       /* Write data to TXDR */
1726       hfmpi2c->Instance->TXDR = *hfmpi2c->pBuffPtr;
1727 
1728       /* Increment Buffer pointer */
1729       hfmpi2c->pBuffPtr++;
1730 
1731       hfmpi2c->XferCount--;
1732       hfmpi2c->XferSize--;
1733 
1734       FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)(hfmpi2c->XferSize + 1U), xfermode,
1735                             FMPI2C_GENERATE_START_WRITE);
1736     }
1737     else
1738     {
1739       FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, xfermode,
1740                             FMPI2C_GENERATE_START_WRITE);
1741     }
1742 
1743     /* Process Unlocked */
1744     __HAL_UNLOCK(hfmpi2c);
1745 
1746     /* Note : The FMPI2C interrupts must be enabled after unlocking current process
1747               to avoid the risk of FMPI2C interrupt handle execution before current
1748               process unlock */
1749 
1750     /* Enable ERR, TC, STOP, NACK, TXI interrupt */
1751     /* possible to enable all of these */
1752     /* FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI |
1753       FMPI2C_IT_ADDRI | FMPI2C_IT_RXI | FMPI2C_IT_TXI */
1754     FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT);
1755 
1756     return HAL_OK;
1757   }
1758   else
1759   {
1760     return HAL_BUSY;
1761   }
1762 }
1763 
1764 /**
1765   * @brief  Receive in master mode an amount of data in non-blocking mode with Interrupt
1766   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
1767   *                the configuration information for the specified FMPI2C.
1768   * @param  DevAddress Target device address: The device 7 bits address value
1769   *         in datasheet must be shifted to the left before calling the interface
1770   * @param  pData Pointer to data buffer
1771   * @param  Size Amount of data to be sent
1772   * @retval HAL status
1773   */
HAL_FMPI2C_Master_Receive_IT(FMPI2C_HandleTypeDef * hfmpi2c,uint16_t DevAddress,uint8_t * pData,uint16_t Size)1774 HAL_StatusTypeDef HAL_FMPI2C_Master_Receive_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t *pData,
1775                                                uint16_t Size)
1776 {
1777   uint32_t xfermode;
1778 
1779   if (hfmpi2c->State == HAL_FMPI2C_STATE_READY)
1780   {
1781     if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_BUSY) == SET)
1782     {
1783       return HAL_BUSY;
1784     }
1785 
1786     /* Process Locked */
1787     __HAL_LOCK(hfmpi2c);
1788 
1789     hfmpi2c->State       = HAL_FMPI2C_STATE_BUSY_RX;
1790     hfmpi2c->Mode        = HAL_FMPI2C_MODE_MASTER;
1791     hfmpi2c->ErrorCode   = HAL_FMPI2C_ERROR_NONE;
1792 
1793     /* Prepare transfer parameters */
1794     hfmpi2c->pBuffPtr    = pData;
1795     hfmpi2c->XferCount   = Size;
1796     hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME;
1797     hfmpi2c->XferISR     = FMPI2C_Master_ISR_IT;
1798 
1799     if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
1800     {
1801       hfmpi2c->XferSize = 1U;
1802       xfermode = FMPI2C_RELOAD_MODE;
1803     }
1804     else
1805     {
1806       hfmpi2c->XferSize = hfmpi2c->XferCount;
1807       xfermode = FMPI2C_AUTOEND_MODE;
1808     }
1809 
1810     /* Send Slave Address */
1811     /* Set NBYTES to write and reload if hfmpi2c->XferCount > MAX_NBYTE_SIZE */
1812     FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, xfermode, FMPI2C_GENERATE_START_READ);
1813 
1814     /* Process Unlocked */
1815     __HAL_UNLOCK(hfmpi2c);
1816 
1817     /* Note : The FMPI2C interrupts must be enabled after unlocking current process
1818               to avoid the risk of FMPI2C interrupt handle execution before current
1819               process unlock */
1820 
1821     /* Enable ERR, TC, STOP, NACK, RXI interrupt */
1822     /* possible to enable all of these */
1823     /* FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI |
1824       FMPI2C_IT_ADDRI | FMPI2C_IT_RXI | FMPI2C_IT_TXI */
1825     FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_RX_IT);
1826 
1827     return HAL_OK;
1828   }
1829   else
1830   {
1831     return HAL_BUSY;
1832   }
1833 }
1834 
1835 /**
1836   * @brief  Transmit in slave mode an amount of data in non-blocking mode with Interrupt
1837   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
1838   *                the configuration information for the specified FMPI2C.
1839   * @param  pData Pointer to data buffer
1840   * @param  Size Amount of data to be sent
1841   * @retval HAL status
1842   */
HAL_FMPI2C_Slave_Transmit_IT(FMPI2C_HandleTypeDef * hfmpi2c,uint8_t * pData,uint16_t Size)1843 HAL_StatusTypeDef HAL_FMPI2C_Slave_Transmit_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t *pData, uint16_t Size)
1844 {
1845   if (hfmpi2c->State == HAL_FMPI2C_STATE_READY)
1846   {
1847     /* Process Locked */
1848     __HAL_LOCK(hfmpi2c);
1849 
1850     hfmpi2c->State       = HAL_FMPI2C_STATE_BUSY_TX;
1851     hfmpi2c->Mode        = HAL_FMPI2C_MODE_SLAVE;
1852     hfmpi2c->ErrorCode   = HAL_FMPI2C_ERROR_NONE;
1853 
1854     /* Enable Address Acknowledge */
1855     hfmpi2c->Instance->CR2 &= ~FMPI2C_CR2_NACK;
1856 
1857     /* Prepare transfer parameters */
1858     hfmpi2c->pBuffPtr    = pData;
1859     hfmpi2c->XferCount   = Size;
1860     hfmpi2c->XferSize    = hfmpi2c->XferCount;
1861     hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME;
1862     hfmpi2c->XferISR     = FMPI2C_Slave_ISR_IT;
1863 
1864     /* Preload TX data if no stretch enable */
1865     if (hfmpi2c->Init.NoStretchMode == FMPI2C_NOSTRETCH_ENABLE)
1866     {
1867       /* Preload TX register */
1868       /* Write data to TXDR */
1869       hfmpi2c->Instance->TXDR = *hfmpi2c->pBuffPtr;
1870 
1871       /* Increment Buffer pointer */
1872       hfmpi2c->pBuffPtr++;
1873 
1874       hfmpi2c->XferCount--;
1875       hfmpi2c->XferSize--;
1876     }
1877 
1878     /* Process Unlocked */
1879     __HAL_UNLOCK(hfmpi2c);
1880 
1881     /* Note : The FMPI2C interrupts must be enabled after unlocking current process
1882               to avoid the risk of FMPI2C interrupt handle execution before current
1883               process unlock */
1884 
1885     /* Enable ERR, TC, STOP, NACK, TXI interrupt */
1886     /* possible to enable all of these */
1887     /* FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI |
1888       FMPI2C_IT_ADDRI | FMPI2C_IT_RXI | FMPI2C_IT_TXI */
1889     FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT | FMPI2C_XFER_LISTEN_IT);
1890 
1891     return HAL_OK;
1892   }
1893   else
1894   {
1895     return HAL_BUSY;
1896   }
1897 }
1898 
1899 /**
1900   * @brief  Receive in slave mode an amount of data in non-blocking mode with Interrupt
1901   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
1902   *                the configuration information for the specified FMPI2C.
1903   * @param  pData Pointer to data buffer
1904   * @param  Size Amount of data to be sent
1905   * @retval HAL status
1906   */
HAL_FMPI2C_Slave_Receive_IT(FMPI2C_HandleTypeDef * hfmpi2c,uint8_t * pData,uint16_t Size)1907 HAL_StatusTypeDef HAL_FMPI2C_Slave_Receive_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t *pData, uint16_t Size)
1908 {
1909   if (hfmpi2c->State == HAL_FMPI2C_STATE_READY)
1910   {
1911     /* Process Locked */
1912     __HAL_LOCK(hfmpi2c);
1913 
1914     hfmpi2c->State       = HAL_FMPI2C_STATE_BUSY_RX;
1915     hfmpi2c->Mode        = HAL_FMPI2C_MODE_SLAVE;
1916     hfmpi2c->ErrorCode   = HAL_FMPI2C_ERROR_NONE;
1917 
1918     /* Enable Address Acknowledge */
1919     hfmpi2c->Instance->CR2 &= ~FMPI2C_CR2_NACK;
1920 
1921     /* Prepare transfer parameters */
1922     hfmpi2c->pBuffPtr    = pData;
1923     hfmpi2c->XferCount   = Size;
1924     hfmpi2c->XferSize    = hfmpi2c->XferCount;
1925     hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME;
1926     hfmpi2c->XferISR     = FMPI2C_Slave_ISR_IT;
1927 
1928     /* Process Unlocked */
1929     __HAL_UNLOCK(hfmpi2c);
1930 
1931     /* Note : The FMPI2C interrupts must be enabled after unlocking current process
1932               to avoid the risk of FMPI2C interrupt handle execution before current
1933               process unlock */
1934 
1935     /* Enable ERR, TC, STOP, NACK, RXI interrupt */
1936     /* possible to enable all of these */
1937     /* FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI |
1938       FMPI2C_IT_ADDRI | FMPI2C_IT_RXI | FMPI2C_IT_TXI */
1939     FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_RX_IT | FMPI2C_XFER_LISTEN_IT);
1940 
1941     return HAL_OK;
1942   }
1943   else
1944   {
1945     return HAL_BUSY;
1946   }
1947 }
1948 
1949 /**
1950   * @brief  Transmit in master mode an amount of data in non-blocking mode with DMA
1951   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
1952   *                the configuration information for the specified FMPI2C.
1953   * @param  DevAddress Target device address: The device 7 bits address value
1954   *         in datasheet must be shifted to the left before calling the interface
1955   * @param  pData Pointer to data buffer
1956   * @param  Size Amount of data to be sent
1957   * @retval HAL status
1958   */
HAL_FMPI2C_Master_Transmit_DMA(FMPI2C_HandleTypeDef * hfmpi2c,uint16_t DevAddress,uint8_t * pData,uint16_t Size)1959 HAL_StatusTypeDef HAL_FMPI2C_Master_Transmit_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t *pData,
1960                                                  uint16_t Size)
1961 {
1962   uint32_t xfermode;
1963   HAL_StatusTypeDef dmaxferstatus;
1964   uint32_t sizetoxfer = 0U;
1965 
1966   if (hfmpi2c->State == HAL_FMPI2C_STATE_READY)
1967   {
1968     if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_BUSY) == SET)
1969     {
1970       return HAL_BUSY;
1971     }
1972 
1973     /* Process Locked */
1974     __HAL_LOCK(hfmpi2c);
1975 
1976     hfmpi2c->State       = HAL_FMPI2C_STATE_BUSY_TX;
1977     hfmpi2c->Mode        = HAL_FMPI2C_MODE_MASTER;
1978     hfmpi2c->ErrorCode   = HAL_FMPI2C_ERROR_NONE;
1979 
1980     /* Prepare transfer parameters */
1981     hfmpi2c->pBuffPtr    = pData;
1982     hfmpi2c->XferCount   = Size;
1983     hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME;
1984     hfmpi2c->XferISR     = FMPI2C_Master_ISR_DMA;
1985 
1986     if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
1987     {
1988       hfmpi2c->XferSize = MAX_NBYTE_SIZE;
1989       xfermode = FMPI2C_RELOAD_MODE;
1990     }
1991     else
1992     {
1993       hfmpi2c->XferSize = hfmpi2c->XferCount;
1994       xfermode = FMPI2C_AUTOEND_MODE;
1995     }
1996 
1997     if (hfmpi2c->XferSize > 0U)
1998     {
1999       /* Preload TX register */
2000       /* Write data to TXDR */
2001       hfmpi2c->Instance->TXDR = *hfmpi2c->pBuffPtr;
2002 
2003       /* Increment Buffer pointer */
2004       hfmpi2c->pBuffPtr++;
2005 
2006       sizetoxfer = hfmpi2c->XferSize;
2007       hfmpi2c->XferCount--;
2008       hfmpi2c->XferSize--;
2009     }
2010 
2011     if (hfmpi2c->XferSize > 0U)
2012     {
2013       if (hfmpi2c->hdmatx != NULL)
2014       {
2015         /* Set the FMPI2C DMA transfer complete callback */
2016         hfmpi2c->hdmatx->XferCpltCallback = FMPI2C_DMAMasterTransmitCplt;
2017 
2018         /* Set the DMA error callback */
2019         hfmpi2c->hdmatx->XferErrorCallback = FMPI2C_DMAError;
2020 
2021         /* Set the unused DMA callbacks to NULL */
2022         hfmpi2c->hdmatx->XferHalfCpltCallback = NULL;
2023         hfmpi2c->hdmatx->XferAbortCallback = NULL;
2024 
2025         /* Enable the DMA stream */
2026         dmaxferstatus = HAL_DMA_Start_IT(hfmpi2c->hdmatx, (uint32_t)hfmpi2c->pBuffPtr,
2027                                          (uint32_t)&hfmpi2c->Instance->TXDR, hfmpi2c->XferSize);
2028       }
2029       else
2030       {
2031         /* Update FMPI2C state */
2032         hfmpi2c->State     = HAL_FMPI2C_STATE_READY;
2033         hfmpi2c->Mode      = HAL_FMPI2C_MODE_NONE;
2034 
2035         /* Update FMPI2C error code */
2036         hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA_PARAM;
2037 
2038         /* Process Unlocked */
2039         __HAL_UNLOCK(hfmpi2c);
2040 
2041         return HAL_ERROR;
2042       }
2043 
2044       if (dmaxferstatus == HAL_OK)
2045       {
2046         /* Send Slave Address */
2047         /* Set NBYTES to write and reload if hfmpi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
2048         FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)(hfmpi2c->XferSize + 1U),
2049                               xfermode, FMPI2C_GENERATE_START_WRITE);
2050 
2051         /* Update XferCount value */
2052         hfmpi2c->XferCount -= hfmpi2c->XferSize;
2053 
2054         /* Process Unlocked */
2055         __HAL_UNLOCK(hfmpi2c);
2056 
2057         /* Note : The FMPI2C interrupts must be enabled after unlocking current process
2058                   to avoid the risk of FMPI2C interrupt handle execution before current
2059                   process unlock */
2060         /* Enable ERR and NACK interrupts */
2061         FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_ERROR_IT);
2062 
2063         /* Enable DMA Request */
2064         hfmpi2c->Instance->CR1 |= FMPI2C_CR1_TXDMAEN;
2065       }
2066       else
2067       {
2068         /* Update FMPI2C state */
2069         hfmpi2c->State     = HAL_FMPI2C_STATE_READY;
2070         hfmpi2c->Mode      = HAL_FMPI2C_MODE_NONE;
2071 
2072         /* Update FMPI2C error code */
2073         hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA;
2074 
2075         /* Process Unlocked */
2076         __HAL_UNLOCK(hfmpi2c);
2077 
2078         return HAL_ERROR;
2079       }
2080     }
2081     else
2082     {
2083       /* Update Transfer ISR function pointer */
2084       hfmpi2c->XferISR = FMPI2C_Master_ISR_IT;
2085 
2086       /* Send Slave Address */
2087       /* Set NBYTES to write and generate START condition */
2088       FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)sizetoxfer, FMPI2C_AUTOEND_MODE,
2089                             FMPI2C_GENERATE_START_WRITE);
2090 
2091       /* Process Unlocked */
2092       __HAL_UNLOCK(hfmpi2c);
2093 
2094       /* Note : The FMPI2C interrupts must be enabled after unlocking current process
2095                 to avoid the risk of FMPI2C interrupt handle execution before current
2096                 process unlock */
2097       /* Enable ERR, TC, STOP, NACK, TXI interrupt */
2098       /* possible to enable all of these */
2099       /* FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI |
2100         FMPI2C_IT_ADDRI | FMPI2C_IT_RXI | FMPI2C_IT_TXI */
2101       FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT);
2102     }
2103 
2104     return HAL_OK;
2105   }
2106   else
2107   {
2108     return HAL_BUSY;
2109   }
2110 }
2111 
2112 /**
2113   * @brief  Receive in master mode an amount of data in non-blocking mode with DMA
2114   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
2115   *                the configuration information for the specified FMPI2C.
2116   * @param  DevAddress Target device address: The device 7 bits address value
2117   *         in datasheet must be shifted to the left before calling the interface
2118   * @param  pData Pointer to data buffer
2119   * @param  Size Amount of data to be sent
2120   * @retval HAL status
2121   */
HAL_FMPI2C_Master_Receive_DMA(FMPI2C_HandleTypeDef * hfmpi2c,uint16_t DevAddress,uint8_t * pData,uint16_t Size)2122 HAL_StatusTypeDef HAL_FMPI2C_Master_Receive_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t *pData,
2123                                                 uint16_t Size)
2124 {
2125   uint32_t xfermode;
2126   HAL_StatusTypeDef dmaxferstatus;
2127 
2128   if (hfmpi2c->State == HAL_FMPI2C_STATE_READY)
2129   {
2130     if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_BUSY) == SET)
2131     {
2132       return HAL_BUSY;
2133     }
2134 
2135     /* Process Locked */
2136     __HAL_LOCK(hfmpi2c);
2137 
2138     hfmpi2c->State       = HAL_FMPI2C_STATE_BUSY_RX;
2139     hfmpi2c->Mode        = HAL_FMPI2C_MODE_MASTER;
2140     hfmpi2c->ErrorCode   = HAL_FMPI2C_ERROR_NONE;
2141 
2142     /* Prepare transfer parameters */
2143     hfmpi2c->pBuffPtr    = pData;
2144     hfmpi2c->XferCount   = Size;
2145     hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME;
2146     hfmpi2c->XferISR     = FMPI2C_Master_ISR_DMA;
2147 
2148     if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
2149     {
2150       hfmpi2c->XferSize = 1U;
2151       xfermode = FMPI2C_RELOAD_MODE;
2152     }
2153     else
2154     {
2155       hfmpi2c->XferSize = hfmpi2c->XferCount;
2156       xfermode = FMPI2C_AUTOEND_MODE;
2157     }
2158 
2159     if (hfmpi2c->XferSize > 0U)
2160     {
2161       if (hfmpi2c->hdmarx != NULL)
2162       {
2163         /* Set the FMPI2C DMA transfer complete callback */
2164         hfmpi2c->hdmarx->XferCpltCallback = FMPI2C_DMAMasterReceiveCplt;
2165 
2166         /* Set the DMA error callback */
2167         hfmpi2c->hdmarx->XferErrorCallback = FMPI2C_DMAError;
2168 
2169         /* Set the unused DMA callbacks to NULL */
2170         hfmpi2c->hdmarx->XferHalfCpltCallback = NULL;
2171         hfmpi2c->hdmarx->XferAbortCallback = NULL;
2172 
2173         /* Enable the DMA stream */
2174         dmaxferstatus = HAL_DMA_Start_IT(hfmpi2c->hdmarx, (uint32_t)&hfmpi2c->Instance->RXDR, (uint32_t)pData,
2175                                          hfmpi2c->XferSize);
2176       }
2177       else
2178       {
2179         /* Update FMPI2C state */
2180         hfmpi2c->State     = HAL_FMPI2C_STATE_READY;
2181         hfmpi2c->Mode      = HAL_FMPI2C_MODE_NONE;
2182 
2183         /* Update FMPI2C error code */
2184         hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA_PARAM;
2185 
2186         /* Process Unlocked */
2187         __HAL_UNLOCK(hfmpi2c);
2188 
2189         return HAL_ERROR;
2190       }
2191 
2192       if (dmaxferstatus == HAL_OK)
2193       {
2194         /* Send Slave Address */
2195         /* Set NBYTES to read and reload if hfmpi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
2196         FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, xfermode, FMPI2C_GENERATE_START_READ);
2197 
2198         /* Update XferCount value */
2199         hfmpi2c->XferCount -= hfmpi2c->XferSize;
2200 
2201         /* Process Unlocked */
2202         __HAL_UNLOCK(hfmpi2c);
2203 
2204         /* Note : The FMPI2C interrupts must be enabled after unlocking current process
2205                   to avoid the risk of FMPI2C interrupt handle execution before current
2206                   process unlock */
2207         /* Enable ERR and NACK interrupts */
2208         FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_ERROR_IT);
2209 
2210         /* Enable DMA Request */
2211         hfmpi2c->Instance->CR1 |= FMPI2C_CR1_RXDMAEN;
2212       }
2213       else
2214       {
2215         /* Update FMPI2C state */
2216         hfmpi2c->State     = HAL_FMPI2C_STATE_READY;
2217         hfmpi2c->Mode      = HAL_FMPI2C_MODE_NONE;
2218 
2219         /* Update FMPI2C error code */
2220         hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA;
2221 
2222         /* Process Unlocked */
2223         __HAL_UNLOCK(hfmpi2c);
2224 
2225         return HAL_ERROR;
2226       }
2227     }
2228     else
2229     {
2230       /* Update Transfer ISR function pointer */
2231       hfmpi2c->XferISR = FMPI2C_Master_ISR_IT;
2232 
2233       /* Send Slave Address */
2234       /* Set NBYTES to read and generate START condition */
2235       FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_AUTOEND_MODE,
2236                             FMPI2C_GENERATE_START_READ);
2237 
2238       /* Process Unlocked */
2239       __HAL_UNLOCK(hfmpi2c);
2240 
2241       /* Note : The FMPI2C interrupts must be enabled after unlocking current process
2242                 to avoid the risk of FMPI2C interrupt handle execution before current
2243                 process unlock */
2244       /* Enable ERR, TC, STOP, NACK, RXI interrupt */
2245       /* possible to enable all of these */
2246       /* FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI |
2247         FMPI2C_IT_ADDRI | FMPI2C_IT_RXI | FMPI2C_IT_TXI */
2248       FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_RX_IT);
2249     }
2250 
2251     return HAL_OK;
2252   }
2253   else
2254   {
2255     return HAL_BUSY;
2256   }
2257 }
2258 
2259 /**
2260   * @brief  Transmit in slave mode an amount of data in non-blocking mode with DMA
2261   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
2262   *                the configuration information for the specified FMPI2C.
2263   * @param  pData Pointer to data buffer
2264   * @param  Size Amount of data to be sent
2265   * @retval HAL status
2266   */
HAL_FMPI2C_Slave_Transmit_DMA(FMPI2C_HandleTypeDef * hfmpi2c,uint8_t * pData,uint16_t Size)2267 HAL_StatusTypeDef HAL_FMPI2C_Slave_Transmit_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t *pData, uint16_t Size)
2268 {
2269   HAL_StatusTypeDef dmaxferstatus;
2270 
2271   if (hfmpi2c->State == HAL_FMPI2C_STATE_READY)
2272   {
2273     if ((pData == NULL) || (Size == 0U))
2274     {
2275       hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_INVALID_PARAM;
2276       return  HAL_ERROR;
2277     }
2278     /* Process Locked */
2279     __HAL_LOCK(hfmpi2c);
2280 
2281     hfmpi2c->State       = HAL_FMPI2C_STATE_BUSY_TX;
2282     hfmpi2c->Mode        = HAL_FMPI2C_MODE_SLAVE;
2283     hfmpi2c->ErrorCode   = HAL_FMPI2C_ERROR_NONE;
2284 
2285     /* Prepare transfer parameters */
2286     hfmpi2c->pBuffPtr    = pData;
2287     hfmpi2c->XferCount   = Size;
2288     hfmpi2c->XferSize    = hfmpi2c->XferCount;
2289     hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME;
2290     hfmpi2c->XferISR     = FMPI2C_Slave_ISR_DMA;
2291 
2292     /* Preload TX data if no stretch enable */
2293     if (hfmpi2c->Init.NoStretchMode == FMPI2C_NOSTRETCH_ENABLE)
2294     {
2295       /* Preload TX register */
2296       /* Write data to TXDR */
2297       hfmpi2c->Instance->TXDR = *hfmpi2c->pBuffPtr;
2298 
2299       /* Increment Buffer pointer */
2300       hfmpi2c->pBuffPtr++;
2301 
2302       hfmpi2c->XferCount--;
2303       hfmpi2c->XferSize--;
2304     }
2305 
2306     if (hfmpi2c->XferCount != 0U)
2307     {
2308       if (hfmpi2c->hdmatx != NULL)
2309       {
2310         /* Set the FMPI2C DMA transfer complete callback */
2311         hfmpi2c->hdmatx->XferCpltCallback = FMPI2C_DMASlaveTransmitCplt;
2312 
2313         /* Set the DMA error callback */
2314         hfmpi2c->hdmatx->XferErrorCallback = FMPI2C_DMAError;
2315 
2316         /* Set the unused DMA callbacks to NULL */
2317         hfmpi2c->hdmatx->XferHalfCpltCallback = NULL;
2318         hfmpi2c->hdmatx->XferAbortCallback = NULL;
2319 
2320         /* Enable the DMA stream */
2321         dmaxferstatus = HAL_DMA_Start_IT(hfmpi2c->hdmatx,
2322                                          (uint32_t)hfmpi2c->pBuffPtr, (uint32_t)&hfmpi2c->Instance->TXDR,
2323                                          hfmpi2c->XferSize);
2324       }
2325       else
2326       {
2327         /* Update FMPI2C state */
2328         hfmpi2c->State     = HAL_FMPI2C_STATE_LISTEN;
2329         hfmpi2c->Mode      = HAL_FMPI2C_MODE_NONE;
2330 
2331         /* Update FMPI2C error code */
2332         hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA_PARAM;
2333 
2334         /* Process Unlocked */
2335         __HAL_UNLOCK(hfmpi2c);
2336 
2337         return HAL_ERROR;
2338       }
2339 
2340       if (dmaxferstatus == HAL_OK)
2341       {
2342         /* Enable Address Acknowledge */
2343         hfmpi2c->Instance->CR2 &= ~FMPI2C_CR2_NACK;
2344 
2345         /* Process Unlocked */
2346         __HAL_UNLOCK(hfmpi2c);
2347 
2348         /* Note : The FMPI2C interrupts must be enabled after unlocking current process
2349                   to avoid the risk of FMPI2C interrupt handle execution before current
2350                   process unlock */
2351         /* Enable ERR, STOP, NACK, ADDR interrupts */
2352         FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT);
2353 
2354         /* Enable DMA Request */
2355         hfmpi2c->Instance->CR1 |= FMPI2C_CR1_TXDMAEN;
2356       }
2357       else
2358       {
2359         /* Update FMPI2C state */
2360         hfmpi2c->State     = HAL_FMPI2C_STATE_LISTEN;
2361         hfmpi2c->Mode      = HAL_FMPI2C_MODE_NONE;
2362 
2363         /* Update FMPI2C error code */
2364         hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA;
2365 
2366         /* Process Unlocked */
2367         __HAL_UNLOCK(hfmpi2c);
2368 
2369         return HAL_ERROR;
2370       }
2371     }
2372     else
2373     {
2374       /* Enable Address Acknowledge */
2375       hfmpi2c->Instance->CR2 &= ~FMPI2C_CR2_NACK;
2376 
2377       /* Process Unlocked */
2378       __HAL_UNLOCK(hfmpi2c);
2379 
2380       /* Note : The FMPI2C interrupts must be enabled after unlocking current process
2381       to avoid the risk of FMPI2C interrupt handle execution before current
2382       process unlock */
2383       /* Enable ERR, STOP, NACK, ADDR interrupts */
2384       FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT);
2385     }
2386 
2387     return HAL_OK;
2388   }
2389   else
2390   {
2391     return HAL_BUSY;
2392   }
2393 }
2394 
2395 /**
2396   * @brief  Receive in slave mode an amount of data in non-blocking mode with DMA
2397   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
2398   *                the configuration information for the specified FMPI2C.
2399   * @param  pData Pointer to data buffer
2400   * @param  Size Amount of data to be sent
2401   * @retval HAL status
2402   */
HAL_FMPI2C_Slave_Receive_DMA(FMPI2C_HandleTypeDef * hfmpi2c,uint8_t * pData,uint16_t Size)2403 HAL_StatusTypeDef HAL_FMPI2C_Slave_Receive_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t *pData, uint16_t Size)
2404 {
2405   HAL_StatusTypeDef dmaxferstatus;
2406 
2407   if (hfmpi2c->State == HAL_FMPI2C_STATE_READY)
2408   {
2409     if ((pData == NULL) || (Size == 0U))
2410     {
2411       hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_INVALID_PARAM;
2412       return  HAL_ERROR;
2413     }
2414     /* Process Locked */
2415     __HAL_LOCK(hfmpi2c);
2416 
2417     hfmpi2c->State       = HAL_FMPI2C_STATE_BUSY_RX;
2418     hfmpi2c->Mode        = HAL_FMPI2C_MODE_SLAVE;
2419     hfmpi2c->ErrorCode   = HAL_FMPI2C_ERROR_NONE;
2420 
2421     /* Prepare transfer parameters */
2422     hfmpi2c->pBuffPtr    = pData;
2423     hfmpi2c->XferCount   = Size;
2424     hfmpi2c->XferSize    = hfmpi2c->XferCount;
2425     hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME;
2426     hfmpi2c->XferISR     = FMPI2C_Slave_ISR_DMA;
2427 
2428     if (hfmpi2c->hdmarx != NULL)
2429     {
2430       /* Set the FMPI2C DMA transfer complete callback */
2431       hfmpi2c->hdmarx->XferCpltCallback = FMPI2C_DMASlaveReceiveCplt;
2432 
2433       /* Set the DMA error callback */
2434       hfmpi2c->hdmarx->XferErrorCallback = FMPI2C_DMAError;
2435 
2436       /* Set the unused DMA callbacks to NULL */
2437       hfmpi2c->hdmarx->XferHalfCpltCallback = NULL;
2438       hfmpi2c->hdmarx->XferAbortCallback = NULL;
2439 
2440       /* Enable the DMA stream */
2441       dmaxferstatus = HAL_DMA_Start_IT(hfmpi2c->hdmarx, (uint32_t)&hfmpi2c->Instance->RXDR, (uint32_t)pData,
2442                                        hfmpi2c->XferSize);
2443     }
2444     else
2445     {
2446       /* Update FMPI2C state */
2447       hfmpi2c->State     = HAL_FMPI2C_STATE_LISTEN;
2448       hfmpi2c->Mode      = HAL_FMPI2C_MODE_NONE;
2449 
2450       /* Update FMPI2C error code */
2451       hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA_PARAM;
2452 
2453       /* Process Unlocked */
2454       __HAL_UNLOCK(hfmpi2c);
2455 
2456       return HAL_ERROR;
2457     }
2458 
2459     if (dmaxferstatus == HAL_OK)
2460     {
2461       /* Enable Address Acknowledge */
2462       hfmpi2c->Instance->CR2 &= ~FMPI2C_CR2_NACK;
2463 
2464       /* Process Unlocked */
2465       __HAL_UNLOCK(hfmpi2c);
2466 
2467       /* Note : The FMPI2C interrupts must be enabled after unlocking current process
2468                 to avoid the risk of FMPI2C interrupt handle execution before current
2469                 process unlock */
2470       /* Enable ERR, STOP, NACK, ADDR interrupts */
2471       FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT);
2472 
2473       /* Enable DMA Request */
2474       hfmpi2c->Instance->CR1 |= FMPI2C_CR1_RXDMAEN;
2475     }
2476     else
2477     {
2478       /* Update FMPI2C state */
2479       hfmpi2c->State     = HAL_FMPI2C_STATE_LISTEN;
2480       hfmpi2c->Mode      = HAL_FMPI2C_MODE_NONE;
2481 
2482       /* Update FMPI2C error code */
2483       hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA;
2484 
2485       /* Process Unlocked */
2486       __HAL_UNLOCK(hfmpi2c);
2487 
2488       return HAL_ERROR;
2489     }
2490 
2491     return HAL_OK;
2492   }
2493   else
2494   {
2495     return HAL_BUSY;
2496   }
2497 }
2498 
2499 /**
2500   * @brief  Write an amount of data in blocking mode to a specific memory address
2501   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
2502   *                the configuration information for the specified FMPI2C.
2503   * @param  DevAddress Target device address: The device 7 bits address value
2504   *         in datasheet must be shifted to the left before calling the interface
2505   * @param  MemAddress Internal memory address
2506   * @param  MemAddSize Size of internal memory address
2507   * @param  pData Pointer to data buffer
2508   * @param  Size Amount of data to be sent
2509   * @param  Timeout Timeout duration
2510   * @retval HAL status
2511   */
HAL_FMPI2C_Mem_Write(FMPI2C_HandleTypeDef * hfmpi2c,uint16_t DevAddress,uint16_t MemAddress,uint16_t MemAddSize,uint8_t * pData,uint16_t Size,uint32_t Timeout)2512 HAL_StatusTypeDef HAL_FMPI2C_Mem_Write(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint16_t MemAddress,
2513                                        uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
2514 {
2515   uint32_t tickstart;
2516 
2517   /* Check the parameters */
2518   assert_param(IS_FMPI2C_MEMADD_SIZE(MemAddSize));
2519 
2520   if (hfmpi2c->State == HAL_FMPI2C_STATE_READY)
2521   {
2522     if ((pData == NULL) || (Size == 0U))
2523     {
2524       hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_INVALID_PARAM;
2525       return  HAL_ERROR;
2526     }
2527 
2528     /* Process Locked */
2529     __HAL_LOCK(hfmpi2c);
2530 
2531     /* Init tickstart for timeout management*/
2532     tickstart = HAL_GetTick();
2533 
2534     if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_BUSY, SET, FMPI2C_TIMEOUT_BUSY, tickstart) != HAL_OK)
2535     {
2536       return HAL_ERROR;
2537     }
2538 
2539     hfmpi2c->State     = HAL_FMPI2C_STATE_BUSY_TX;
2540     hfmpi2c->Mode      = HAL_FMPI2C_MODE_MEM;
2541     hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE;
2542 
2543     /* Prepare transfer parameters */
2544     hfmpi2c->pBuffPtr  = pData;
2545     hfmpi2c->XferCount = Size;
2546     hfmpi2c->XferISR   = NULL;
2547 
2548     /* Send Slave Address and Memory Address */
2549     if (FMPI2C_RequestMemoryWrite(hfmpi2c, DevAddress, MemAddress, MemAddSize, Timeout, tickstart) != HAL_OK)
2550     {
2551       /* Process Unlocked */
2552       __HAL_UNLOCK(hfmpi2c);
2553       return HAL_ERROR;
2554     }
2555 
2556     /* Set NBYTES to write and reload if hfmpi2c->XferCount > MAX_NBYTE_SIZE */
2557     if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
2558     {
2559       hfmpi2c->XferSize = MAX_NBYTE_SIZE;
2560       FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_RELOAD_MODE, FMPI2C_NO_STARTSTOP);
2561     }
2562     else
2563     {
2564       hfmpi2c->XferSize = hfmpi2c->XferCount;
2565       FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_AUTOEND_MODE, FMPI2C_NO_STARTSTOP);
2566     }
2567 
2568     do
2569     {
2570       /* Wait until TXIS flag is set */
2571       if (FMPI2C_WaitOnTXISFlagUntilTimeout(hfmpi2c, Timeout, tickstart) != HAL_OK)
2572       {
2573         return HAL_ERROR;
2574       }
2575 
2576       /* Write data to TXDR */
2577       hfmpi2c->Instance->TXDR = *hfmpi2c->pBuffPtr;
2578 
2579       /* Increment Buffer pointer */
2580       hfmpi2c->pBuffPtr++;
2581 
2582       hfmpi2c->XferCount--;
2583       hfmpi2c->XferSize--;
2584 
2585       if ((hfmpi2c->XferCount != 0U) && (hfmpi2c->XferSize == 0U))
2586       {
2587         /* Wait until TCR flag is set */
2588         if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK)
2589         {
2590           return HAL_ERROR;
2591         }
2592 
2593         if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
2594         {
2595           hfmpi2c->XferSize = MAX_NBYTE_SIZE;
2596           FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_RELOAD_MODE,
2597                                 FMPI2C_NO_STARTSTOP);
2598         }
2599         else
2600         {
2601           hfmpi2c->XferSize = hfmpi2c->XferCount;
2602           FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_AUTOEND_MODE,
2603                                 FMPI2C_NO_STARTSTOP);
2604         }
2605       }
2606 
2607     } while (hfmpi2c->XferCount > 0U);
2608 
2609     /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
2610     /* Wait until STOPF flag is reset */
2611     if (FMPI2C_WaitOnSTOPFlagUntilTimeout(hfmpi2c, Timeout, tickstart) != HAL_OK)
2612     {
2613       return HAL_ERROR;
2614     }
2615 
2616     /* Clear STOP Flag */
2617     __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF);
2618 
2619     /* Clear Configuration Register 2 */
2620     FMPI2C_RESET_CR2(hfmpi2c);
2621 
2622     hfmpi2c->State = HAL_FMPI2C_STATE_READY;
2623     hfmpi2c->Mode  = HAL_FMPI2C_MODE_NONE;
2624 
2625     /* Process Unlocked */
2626     __HAL_UNLOCK(hfmpi2c);
2627 
2628     return HAL_OK;
2629   }
2630   else
2631   {
2632     return HAL_BUSY;
2633   }
2634 }
2635 
2636 /**
2637   * @brief  Read an amount of data in blocking mode from a specific memory address
2638   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
2639   *                the configuration information for the specified FMPI2C.
2640   * @param  DevAddress Target device address: The device 7 bits address value
2641   *         in datasheet must be shifted to the left before calling the interface
2642   * @param  MemAddress Internal memory address
2643   * @param  MemAddSize Size of internal memory address
2644   * @param  pData Pointer to data buffer
2645   * @param  Size Amount of data to be sent
2646   * @param  Timeout Timeout duration
2647   * @retval HAL status
2648   */
HAL_FMPI2C_Mem_Read(FMPI2C_HandleTypeDef * hfmpi2c,uint16_t DevAddress,uint16_t MemAddress,uint16_t MemAddSize,uint8_t * pData,uint16_t Size,uint32_t Timeout)2649 HAL_StatusTypeDef HAL_FMPI2C_Mem_Read(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint16_t MemAddress,
2650                                       uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
2651 {
2652   uint32_t tickstart;
2653 
2654   /* Check the parameters */
2655   assert_param(IS_FMPI2C_MEMADD_SIZE(MemAddSize));
2656 
2657   if (hfmpi2c->State == HAL_FMPI2C_STATE_READY)
2658   {
2659     if ((pData == NULL) || (Size == 0U))
2660     {
2661       hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_INVALID_PARAM;
2662       return  HAL_ERROR;
2663     }
2664 
2665     /* Process Locked */
2666     __HAL_LOCK(hfmpi2c);
2667 
2668     /* Init tickstart for timeout management*/
2669     tickstart = HAL_GetTick();
2670 
2671     if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_BUSY, SET, FMPI2C_TIMEOUT_BUSY, tickstart) != HAL_OK)
2672     {
2673       return HAL_ERROR;
2674     }
2675 
2676     hfmpi2c->State     = HAL_FMPI2C_STATE_BUSY_RX;
2677     hfmpi2c->Mode      = HAL_FMPI2C_MODE_MEM;
2678     hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE;
2679 
2680     /* Prepare transfer parameters */
2681     hfmpi2c->pBuffPtr  = pData;
2682     hfmpi2c->XferCount = Size;
2683     hfmpi2c->XferISR   = NULL;
2684 
2685     /* Send Slave Address and Memory Address */
2686     if (FMPI2C_RequestMemoryRead(hfmpi2c, DevAddress, MemAddress, MemAddSize, Timeout, tickstart) != HAL_OK)
2687     {
2688       /* Process Unlocked */
2689       __HAL_UNLOCK(hfmpi2c);
2690       return HAL_ERROR;
2691     }
2692 
2693     /* Send Slave Address */
2694     /* Set NBYTES to write and reload if hfmpi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
2695     if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
2696     {
2697       hfmpi2c->XferSize = 1U;
2698       FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_RELOAD_MODE,
2699                             FMPI2C_GENERATE_START_READ);
2700     }
2701     else
2702     {
2703       hfmpi2c->XferSize = hfmpi2c->XferCount;
2704       FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_AUTOEND_MODE,
2705                             FMPI2C_GENERATE_START_READ);
2706     }
2707 
2708     do
2709     {
2710       /* Wait until RXNE flag is set */
2711       if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_RXNE, RESET, Timeout, tickstart) != HAL_OK)
2712       {
2713         return HAL_ERROR;
2714       }
2715 
2716       /* Read data from RXDR */
2717       *hfmpi2c->pBuffPtr = (uint8_t)hfmpi2c->Instance->RXDR;
2718 
2719       /* Increment Buffer pointer */
2720       hfmpi2c->pBuffPtr++;
2721 
2722       hfmpi2c->XferSize--;
2723       hfmpi2c->XferCount--;
2724 
2725       if ((hfmpi2c->XferCount != 0U) && (hfmpi2c->XferSize == 0U))
2726       {
2727         /* Wait until TCR flag is set */
2728         if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK)
2729         {
2730           return HAL_ERROR;
2731         }
2732 
2733         if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
2734         {
2735           hfmpi2c->XferSize = 1U;
2736           FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t) hfmpi2c->XferSize, FMPI2C_RELOAD_MODE,
2737                                 FMPI2C_NO_STARTSTOP);
2738         }
2739         else
2740         {
2741           hfmpi2c->XferSize = hfmpi2c->XferCount;
2742           FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_AUTOEND_MODE,
2743                                 FMPI2C_NO_STARTSTOP);
2744         }
2745       }
2746     } while (hfmpi2c->XferCount > 0U);
2747 
2748     /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
2749     /* Wait until STOPF flag is reset */
2750     if (FMPI2C_WaitOnSTOPFlagUntilTimeout(hfmpi2c, Timeout, tickstart) != HAL_OK)
2751     {
2752       return HAL_ERROR;
2753     }
2754 
2755     /* Clear STOP Flag */
2756     __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF);
2757 
2758     /* Clear Configuration Register 2 */
2759     FMPI2C_RESET_CR2(hfmpi2c);
2760 
2761     hfmpi2c->State = HAL_FMPI2C_STATE_READY;
2762     hfmpi2c->Mode  = HAL_FMPI2C_MODE_NONE;
2763 
2764     /* Process Unlocked */
2765     __HAL_UNLOCK(hfmpi2c);
2766 
2767     return HAL_OK;
2768   }
2769   else
2770   {
2771     return HAL_BUSY;
2772   }
2773 }
2774 /**
2775   * @brief  Write an amount of data in non-blocking mode with Interrupt to a specific memory address
2776   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
2777   *                the configuration information for the specified FMPI2C.
2778   * @param  DevAddress Target device address: The device 7 bits address value
2779   *         in datasheet must be shifted to the left before calling the interface
2780   * @param  MemAddress Internal memory address
2781   * @param  MemAddSize Size of internal memory address
2782   * @param  pData Pointer to data buffer
2783   * @param  Size Amount of data to be sent
2784   * @retval HAL status
2785   */
HAL_FMPI2C_Mem_Write_IT(FMPI2C_HandleTypeDef * hfmpi2c,uint16_t DevAddress,uint16_t MemAddress,uint16_t MemAddSize,uint8_t * pData,uint16_t Size)2786 HAL_StatusTypeDef HAL_FMPI2C_Mem_Write_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint16_t MemAddress,
2787                                           uint16_t MemAddSize, uint8_t *pData, uint16_t Size)
2788 {
2789   /* Check the parameters */
2790   assert_param(IS_FMPI2C_MEMADD_SIZE(MemAddSize));
2791 
2792   if (hfmpi2c->State == HAL_FMPI2C_STATE_READY)
2793   {
2794     if ((pData == NULL) || (Size == 0U))
2795     {
2796       hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_INVALID_PARAM;
2797       return  HAL_ERROR;
2798     }
2799 
2800     if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_BUSY) == SET)
2801     {
2802       return HAL_BUSY;
2803     }
2804 
2805     /* Process Locked */
2806     __HAL_LOCK(hfmpi2c);
2807 
2808     hfmpi2c->State       = HAL_FMPI2C_STATE_BUSY_TX;
2809     hfmpi2c->Mode        = HAL_FMPI2C_MODE_MEM;
2810     hfmpi2c->ErrorCode   = HAL_FMPI2C_ERROR_NONE;
2811 
2812     /* Prepare transfer parameters */
2813     hfmpi2c->XferSize    = 0U;
2814     hfmpi2c->pBuffPtr    = pData;
2815     hfmpi2c->XferCount   = Size;
2816     hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME;
2817     hfmpi2c->XferISR     = FMPI2C_Mem_ISR_IT;
2818     hfmpi2c->Devaddress  = DevAddress;
2819 
2820     /* If Memory address size is 8Bit */
2821     if (MemAddSize == FMPI2C_MEMADD_SIZE_8BIT)
2822     {
2823       /* Prefetch Memory Address */
2824       hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_LSB(MemAddress);
2825 
2826       /* Reset Memaddress content */
2827       hfmpi2c->Memaddress = 0xFFFFFFFFU;
2828     }
2829     /* If Memory address size is 16Bit */
2830     else
2831     {
2832       /* Prefetch Memory Address (MSB part, LSB will be manage through interrupt) */
2833       hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_MSB(MemAddress);
2834 
2835       /* Prepare Memaddress buffer for LSB part */
2836       hfmpi2c->Memaddress = FMPI2C_MEM_ADD_LSB(MemAddress);
2837     }
2838     /* Send Slave Address and Memory Address */
2839     FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)MemAddSize, FMPI2C_RELOAD_MODE, FMPI2C_GENERATE_START_WRITE);
2840 
2841     /* Process Unlocked */
2842     __HAL_UNLOCK(hfmpi2c);
2843 
2844     /* Note : The FMPI2C interrupts must be enabled after unlocking current process
2845               to avoid the risk of FMPI2C interrupt handle execution before current
2846               process unlock */
2847 
2848     /* Enable ERR, TC, STOP, NACK, TXI interrupt */
2849     /* possible to enable all of these */
2850     /* FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI |
2851       FMPI2C_IT_ADDRI | FMPI2C_IT_RXI | FMPI2C_IT_TXI */
2852     FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT);
2853 
2854     return HAL_OK;
2855   }
2856   else
2857   {
2858     return HAL_BUSY;
2859   }
2860 }
2861 
2862 /**
2863   * @brief  Read an amount of data in non-blocking mode with Interrupt from a specific memory address
2864   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
2865   *                the configuration information for the specified FMPI2C.
2866   * @param  DevAddress Target device address: The device 7 bits address value
2867   *         in datasheet must be shifted to the left before calling the interface
2868   * @param  MemAddress Internal memory address
2869   * @param  MemAddSize Size of internal memory address
2870   * @param  pData Pointer to data buffer
2871   * @param  Size Amount of data to be sent
2872   * @retval HAL status
2873   */
HAL_FMPI2C_Mem_Read_IT(FMPI2C_HandleTypeDef * hfmpi2c,uint16_t DevAddress,uint16_t MemAddress,uint16_t MemAddSize,uint8_t * pData,uint16_t Size)2874 HAL_StatusTypeDef HAL_FMPI2C_Mem_Read_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint16_t MemAddress,
2875                                          uint16_t MemAddSize, uint8_t *pData, uint16_t Size)
2876 {
2877   /* Check the parameters */
2878   assert_param(IS_FMPI2C_MEMADD_SIZE(MemAddSize));
2879 
2880   if (hfmpi2c->State == HAL_FMPI2C_STATE_READY)
2881   {
2882     if ((pData == NULL) || (Size == 0U))
2883     {
2884       hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_INVALID_PARAM;
2885       return  HAL_ERROR;
2886     }
2887 
2888     if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_BUSY) == SET)
2889     {
2890       return HAL_BUSY;
2891     }
2892 
2893     /* Process Locked */
2894     __HAL_LOCK(hfmpi2c);
2895 
2896     hfmpi2c->State       = HAL_FMPI2C_STATE_BUSY_RX;
2897     hfmpi2c->Mode        = HAL_FMPI2C_MODE_MEM;
2898     hfmpi2c->ErrorCode   = HAL_FMPI2C_ERROR_NONE;
2899 
2900     /* Prepare transfer parameters */
2901     hfmpi2c->pBuffPtr    = pData;
2902     hfmpi2c->XferCount   = Size;
2903     hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME;
2904     hfmpi2c->XferISR     = FMPI2C_Mem_ISR_IT;
2905     hfmpi2c->Devaddress  = DevAddress;
2906 
2907     /* If Memory address size is 8Bit */
2908     if (MemAddSize == FMPI2C_MEMADD_SIZE_8BIT)
2909     {
2910       /* Prefetch Memory Address */
2911       hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_LSB(MemAddress);
2912 
2913       /* Reset Memaddress content */
2914       hfmpi2c->Memaddress = 0xFFFFFFFFU;
2915     }
2916     /* If Memory address size is 16Bit */
2917     else
2918     {
2919       /* Prefetch Memory Address (MSB part, LSB will be manage through interrupt) */
2920       hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_MSB(MemAddress);
2921 
2922       /* Prepare Memaddress buffer for LSB part */
2923       hfmpi2c->Memaddress = FMPI2C_MEM_ADD_LSB(MemAddress);
2924     }
2925     /* Send Slave Address and Memory Address */
2926     FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)MemAddSize, FMPI2C_SOFTEND_MODE, FMPI2C_GENERATE_START_WRITE);
2927 
2928     /* Process Unlocked */
2929     __HAL_UNLOCK(hfmpi2c);
2930 
2931     /* Note : The FMPI2C interrupts must be enabled after unlocking current process
2932               to avoid the risk of FMPI2C interrupt handle execution before current
2933               process unlock */
2934 
2935     /* Enable ERR, TC, STOP, NACK, TXI interrupt */
2936     /* possible to enable all of these */
2937     /* FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI |
2938       FMPI2C_IT_ADDRI | FMPI2C_IT_RXI | FMPI2C_IT_TXI */
2939     FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT);
2940 
2941     return HAL_OK;
2942   }
2943   else
2944   {
2945     return HAL_BUSY;
2946   }
2947 }
2948 
2949 /**
2950   * @brief  Write an amount of data in non-blocking mode with DMA to a specific memory address
2951   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
2952   *                the configuration information for the specified FMPI2C.
2953   * @param  DevAddress Target device address: The device 7 bits address value
2954   *         in datasheet must be shifted to the left before calling the interface
2955   * @param  MemAddress Internal memory address
2956   * @param  MemAddSize Size of internal memory address
2957   * @param  pData Pointer to data buffer
2958   * @param  Size Amount of data to be sent
2959   * @retval HAL status
2960   */
HAL_FMPI2C_Mem_Write_DMA(FMPI2C_HandleTypeDef * hfmpi2c,uint16_t DevAddress,uint16_t MemAddress,uint16_t MemAddSize,uint8_t * pData,uint16_t Size)2961 HAL_StatusTypeDef HAL_FMPI2C_Mem_Write_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint16_t MemAddress,
2962                                            uint16_t MemAddSize, uint8_t *pData, uint16_t Size)
2963 {
2964   HAL_StatusTypeDef dmaxferstatus;
2965 
2966   /* Check the parameters */
2967   assert_param(IS_FMPI2C_MEMADD_SIZE(MemAddSize));
2968 
2969   if (hfmpi2c->State == HAL_FMPI2C_STATE_READY)
2970   {
2971     if ((pData == NULL) || (Size == 0U))
2972     {
2973       hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_INVALID_PARAM;
2974       return  HAL_ERROR;
2975     }
2976 
2977     if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_BUSY) == SET)
2978     {
2979       return HAL_BUSY;
2980     }
2981 
2982     /* Process Locked */
2983     __HAL_LOCK(hfmpi2c);
2984 
2985     hfmpi2c->State       = HAL_FMPI2C_STATE_BUSY_TX;
2986     hfmpi2c->Mode        = HAL_FMPI2C_MODE_MEM;
2987     hfmpi2c->ErrorCode   = HAL_FMPI2C_ERROR_NONE;
2988 
2989     /* Prepare transfer parameters */
2990     hfmpi2c->pBuffPtr    = pData;
2991     hfmpi2c->XferCount   = Size;
2992     hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME;
2993     hfmpi2c->XferISR     = FMPI2C_Mem_ISR_DMA;
2994     hfmpi2c->Devaddress  = DevAddress;
2995 
2996     if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
2997     {
2998       hfmpi2c->XferSize = MAX_NBYTE_SIZE;
2999     }
3000     else
3001     {
3002       hfmpi2c->XferSize = hfmpi2c->XferCount;
3003     }
3004 
3005     /* If Memory address size is 8Bit */
3006     if (MemAddSize == FMPI2C_MEMADD_SIZE_8BIT)
3007     {
3008       /* Prefetch Memory Address */
3009       hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_LSB(MemAddress);
3010 
3011       /* Reset Memaddress content */
3012       hfmpi2c->Memaddress = 0xFFFFFFFFU;
3013     }
3014     /* If Memory address size is 16Bit */
3015     else
3016     {
3017       /* Prefetch Memory Address (MSB part, LSB will be manage through interrupt) */
3018       hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_MSB(MemAddress);
3019 
3020       /* Prepare Memaddress buffer for LSB part */
3021       hfmpi2c->Memaddress = FMPI2C_MEM_ADD_LSB(MemAddress);
3022     }
3023 
3024     if (hfmpi2c->hdmatx != NULL)
3025     {
3026       /* Set the FMPI2C DMA transfer complete callback */
3027       hfmpi2c->hdmatx->XferCpltCallback = FMPI2C_DMAMasterTransmitCplt;
3028 
3029       /* Set the DMA error callback */
3030       hfmpi2c->hdmatx->XferErrorCallback = FMPI2C_DMAError;
3031 
3032       /* Set the unused DMA callbacks to NULL */
3033       hfmpi2c->hdmatx->XferHalfCpltCallback = NULL;
3034       hfmpi2c->hdmatx->XferAbortCallback = NULL;
3035 
3036       /* Enable the DMA stream */
3037       dmaxferstatus = HAL_DMA_Start_IT(hfmpi2c->hdmatx, (uint32_t)pData, (uint32_t)&hfmpi2c->Instance->TXDR,
3038                                        hfmpi2c->XferSize);
3039     }
3040     else
3041     {
3042       /* Update FMPI2C state */
3043       hfmpi2c->State     = HAL_FMPI2C_STATE_READY;
3044       hfmpi2c->Mode      = HAL_FMPI2C_MODE_NONE;
3045 
3046       /* Update FMPI2C error code */
3047       hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA_PARAM;
3048 
3049       /* Process Unlocked */
3050       __HAL_UNLOCK(hfmpi2c);
3051 
3052       return HAL_ERROR;
3053     }
3054 
3055     if (dmaxferstatus == HAL_OK)
3056     {
3057       /* Send Slave Address and Memory Address */
3058       FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)MemAddSize, FMPI2C_RELOAD_MODE, FMPI2C_GENERATE_START_WRITE);
3059 
3060       /* Process Unlocked */
3061       __HAL_UNLOCK(hfmpi2c);
3062 
3063       /* Note : The FMPI2C interrupts must be enabled after unlocking current process
3064                 to avoid the risk of FMPI2C interrupt handle execution before current
3065                 process unlock */
3066       /* Enable ERR, TC, STOP, NACK, TXI interrupt */
3067       /* possible to enable all of these */
3068       /* FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI |
3069         FMPI2C_IT_ADDRI | FMPI2C_IT_RXI | FMPI2C_IT_TXI */
3070       FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT);
3071     }
3072     else
3073     {
3074       /* Update FMPI2C state */
3075       hfmpi2c->State     = HAL_FMPI2C_STATE_READY;
3076       hfmpi2c->Mode      = HAL_FMPI2C_MODE_NONE;
3077 
3078       /* Update FMPI2C error code */
3079       hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA;
3080 
3081       /* Process Unlocked */
3082       __HAL_UNLOCK(hfmpi2c);
3083 
3084       return HAL_ERROR;
3085     }
3086 
3087     return HAL_OK;
3088   }
3089   else
3090   {
3091     return HAL_BUSY;
3092   }
3093 }
3094 
3095 /**
3096   * @brief  Reads an amount of data in non-blocking mode with DMA from a specific memory address.
3097   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
3098   *                the configuration information for the specified FMPI2C.
3099   * @param  DevAddress Target device address: The device 7 bits address value
3100   *         in datasheet must be shifted to the left before calling the interface
3101   * @param  MemAddress Internal memory address
3102   * @param  MemAddSize Size of internal memory address
3103   * @param  pData Pointer to data buffer
3104   * @param  Size Amount of data to be read
3105   * @retval HAL status
3106   */
HAL_FMPI2C_Mem_Read_DMA(FMPI2C_HandleTypeDef * hfmpi2c,uint16_t DevAddress,uint16_t MemAddress,uint16_t MemAddSize,uint8_t * pData,uint16_t Size)3107 HAL_StatusTypeDef HAL_FMPI2C_Mem_Read_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint16_t MemAddress,
3108                                           uint16_t MemAddSize, uint8_t *pData, uint16_t Size)
3109 {
3110   HAL_StatusTypeDef dmaxferstatus;
3111 
3112   /* Check the parameters */
3113   assert_param(IS_FMPI2C_MEMADD_SIZE(MemAddSize));
3114 
3115   if (hfmpi2c->State == HAL_FMPI2C_STATE_READY)
3116   {
3117     if ((pData == NULL) || (Size == 0U))
3118     {
3119       hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_INVALID_PARAM;
3120       return  HAL_ERROR;
3121     }
3122 
3123     if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_BUSY) == SET)
3124     {
3125       return HAL_BUSY;
3126     }
3127 
3128     /* Process Locked */
3129     __HAL_LOCK(hfmpi2c);
3130 
3131     hfmpi2c->State       = HAL_FMPI2C_STATE_BUSY_RX;
3132     hfmpi2c->Mode        = HAL_FMPI2C_MODE_MEM;
3133     hfmpi2c->ErrorCode   = HAL_FMPI2C_ERROR_NONE;
3134 
3135     /* Prepare transfer parameters */
3136     hfmpi2c->pBuffPtr    = pData;
3137     hfmpi2c->XferCount   = Size;
3138     hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME;
3139     hfmpi2c->XferISR     = FMPI2C_Mem_ISR_DMA;
3140     hfmpi2c->Devaddress  = DevAddress;
3141 
3142     if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
3143     {
3144       hfmpi2c->XferSize = MAX_NBYTE_SIZE;
3145     }
3146     else
3147     {
3148       hfmpi2c->XferSize = hfmpi2c->XferCount;
3149     }
3150 
3151     /* If Memory address size is 8Bit */
3152     if (MemAddSize == FMPI2C_MEMADD_SIZE_8BIT)
3153     {
3154       /* Prefetch Memory Address */
3155       hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_LSB(MemAddress);
3156 
3157       /* Reset Memaddress content */
3158       hfmpi2c->Memaddress = 0xFFFFFFFFU;
3159     }
3160     /* If Memory address size is 16Bit */
3161     else
3162     {
3163       /* Prefetch Memory Address (MSB part, LSB will be manage through interrupt) */
3164       hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_MSB(MemAddress);
3165 
3166       /* Prepare Memaddress buffer for LSB part */
3167       hfmpi2c->Memaddress = FMPI2C_MEM_ADD_LSB(MemAddress);
3168     }
3169 
3170     if (hfmpi2c->hdmarx != NULL)
3171     {
3172       /* Set the FMPI2C DMA transfer complete callback */
3173       hfmpi2c->hdmarx->XferCpltCallback = FMPI2C_DMAMasterReceiveCplt;
3174 
3175       /* Set the DMA error callback */
3176       hfmpi2c->hdmarx->XferErrorCallback = FMPI2C_DMAError;
3177 
3178       /* Set the unused DMA callbacks to NULL */
3179       hfmpi2c->hdmarx->XferHalfCpltCallback = NULL;
3180       hfmpi2c->hdmarx->XferAbortCallback = NULL;
3181 
3182       /* Enable the DMA stream */
3183       dmaxferstatus = HAL_DMA_Start_IT(hfmpi2c->hdmarx, (uint32_t)&hfmpi2c->Instance->RXDR, (uint32_t)pData,
3184                                        hfmpi2c->XferSize);
3185     }
3186     else
3187     {
3188       /* Update FMPI2C state */
3189       hfmpi2c->State     = HAL_FMPI2C_STATE_READY;
3190       hfmpi2c->Mode      = HAL_FMPI2C_MODE_NONE;
3191 
3192       /* Update FMPI2C error code */
3193       hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA_PARAM;
3194 
3195       /* Process Unlocked */
3196       __HAL_UNLOCK(hfmpi2c);
3197 
3198       return HAL_ERROR;
3199     }
3200 
3201     if (dmaxferstatus == HAL_OK)
3202     {
3203       /* Send Slave Address and Memory Address */
3204       FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)MemAddSize, FMPI2C_SOFTEND_MODE, FMPI2C_GENERATE_START_WRITE);
3205 
3206       /* Process Unlocked */
3207       __HAL_UNLOCK(hfmpi2c);
3208 
3209       /* Note : The FMPI2C interrupts must be enabled after unlocking current process
3210                 to avoid the risk of FMPI2C interrupt handle execution before current
3211                 process unlock */
3212       /* Enable ERR, TC, STOP, NACK, TXI interrupt */
3213       /* possible to enable all of these */
3214       /* FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI |
3215         FMPI2C_IT_ADDRI | FMPI2C_IT_RXI | FMPI2C_IT_TXI */
3216       FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT);
3217     }
3218     else
3219     {
3220       /* Update FMPI2C state */
3221       hfmpi2c->State     = HAL_FMPI2C_STATE_READY;
3222       hfmpi2c->Mode      = HAL_FMPI2C_MODE_NONE;
3223 
3224       /* Update FMPI2C error code */
3225       hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA;
3226 
3227       /* Process Unlocked */
3228       __HAL_UNLOCK(hfmpi2c);
3229 
3230       return HAL_ERROR;
3231     }
3232 
3233     return HAL_OK;
3234   }
3235   else
3236   {
3237     return HAL_BUSY;
3238   }
3239 }
3240 
3241 /**
3242   * @brief  Checks if target device is ready for communication.
3243   * @note   This function is used with Memory devices
3244   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
3245   *                the configuration information for the specified FMPI2C.
3246   * @param  DevAddress Target device address: The device 7 bits address value
3247   *         in datasheet must be shifted to the left before calling the interface
3248   * @param  Trials Number of trials
3249   * @param  Timeout Timeout duration
3250   * @retval HAL status
3251   */
HAL_FMPI2C_IsDeviceReady(FMPI2C_HandleTypeDef * hfmpi2c,uint16_t DevAddress,uint32_t Trials,uint32_t Timeout)3252 HAL_StatusTypeDef HAL_FMPI2C_IsDeviceReady(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint32_t Trials,
3253                                            uint32_t Timeout)
3254 {
3255   uint32_t tickstart;
3256 
3257   __IO uint32_t FMPI2C_Trials = 0UL;
3258 
3259   FlagStatus tmp1;
3260   FlagStatus tmp2;
3261 
3262   if (hfmpi2c->State == HAL_FMPI2C_STATE_READY)
3263   {
3264     if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_BUSY) == SET)
3265     {
3266       return HAL_BUSY;
3267     }
3268 
3269     /* Process Locked */
3270     __HAL_LOCK(hfmpi2c);
3271 
3272     hfmpi2c->State = HAL_FMPI2C_STATE_BUSY;
3273     hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE;
3274 
3275     do
3276     {
3277       /* Generate Start */
3278       hfmpi2c->Instance->CR2 = FMPI2C_GENERATE_START(hfmpi2c->Init.AddressingMode, DevAddress);
3279 
3280       /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
3281       /* Wait until STOPF flag is set or a NACK flag is set*/
3282       tickstart = HAL_GetTick();
3283 
3284       tmp1 = __HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF);
3285       tmp2 = __HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_AF);
3286 
3287       while ((tmp1 == RESET) && (tmp2 == RESET))
3288       {
3289         if (Timeout != HAL_MAX_DELAY)
3290         {
3291           if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
3292           {
3293             /* Update FMPI2C state */
3294             hfmpi2c->State = HAL_FMPI2C_STATE_READY;
3295 
3296             /* Update FMPI2C error code */
3297             hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_TIMEOUT;
3298 
3299             /* Process Unlocked */
3300             __HAL_UNLOCK(hfmpi2c);
3301 
3302             return HAL_ERROR;
3303           }
3304         }
3305 
3306         tmp1 = __HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF);
3307         tmp2 = __HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_AF);
3308       }
3309 
3310       /* Check if the NACKF flag has not been set */
3311       if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_AF) == RESET)
3312       {
3313         /* Wait until STOPF flag is reset */
3314         if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_STOPF, RESET, Timeout, tickstart) != HAL_OK)
3315         {
3316           return HAL_ERROR;
3317         }
3318 
3319         /* Clear STOP Flag */
3320         __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF);
3321 
3322         /* Device is ready */
3323         hfmpi2c->State = HAL_FMPI2C_STATE_READY;
3324 
3325         /* Process Unlocked */
3326         __HAL_UNLOCK(hfmpi2c);
3327 
3328         return HAL_OK;
3329       }
3330       else
3331       {
3332         /* Wait until STOPF flag is reset */
3333         if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_STOPF, RESET, Timeout, tickstart) != HAL_OK)
3334         {
3335           return HAL_ERROR;
3336         }
3337 
3338         /* Clear NACK Flag */
3339         __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF);
3340 
3341         /* Clear STOP Flag, auto generated with autoend*/
3342         __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF);
3343       }
3344 
3345       /* Increment Trials */
3346       FMPI2C_Trials++;
3347     } while (FMPI2C_Trials < Trials);
3348 
3349     /* Update FMPI2C state */
3350     hfmpi2c->State = HAL_FMPI2C_STATE_READY;
3351 
3352     /* Update FMPI2C error code */
3353     hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_TIMEOUT;
3354 
3355     /* Process Unlocked */
3356     __HAL_UNLOCK(hfmpi2c);
3357 
3358     return HAL_ERROR;
3359   }
3360   else
3361   {
3362     return HAL_BUSY;
3363   }
3364 }
3365 
3366 /**
3367   * @brief  Sequential transmit in master FMPI2C mode an amount of data in non-blocking mode with Interrupt.
3368   * @note   This interface allow to manage repeated start condition when a direction change during transfer
3369   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
3370   *                the configuration information for the specified FMPI2C.
3371   * @param  DevAddress Target device address: The device 7 bits address value
3372   *         in datasheet must be shifted to the left before calling the interface
3373   * @param  pData Pointer to data buffer
3374   * @param  Size Amount of data to be sent
3375   * @param  XferOptions Options of Transfer, value of @ref FMPI2C_XFEROPTIONS
3376   * @retval HAL status
3377   */
HAL_FMPI2C_Master_Seq_Transmit_IT(FMPI2C_HandleTypeDef * hfmpi2c,uint16_t DevAddress,uint8_t * pData,uint16_t Size,uint32_t XferOptions)3378 HAL_StatusTypeDef HAL_FMPI2C_Master_Seq_Transmit_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t *pData,
3379                                                     uint16_t Size, uint32_t XferOptions)
3380 {
3381   uint32_t xfermode;
3382   uint32_t xferrequest = FMPI2C_GENERATE_START_WRITE;
3383   uint32_t sizetoxfer = 0U;
3384 
3385   /* Check the parameters */
3386   assert_param(IS_FMPI2C_TRANSFER_OPTIONS_REQUEST(XferOptions));
3387 
3388   if (hfmpi2c->State == HAL_FMPI2C_STATE_READY)
3389   {
3390     /* Process Locked */
3391     __HAL_LOCK(hfmpi2c);
3392 
3393     hfmpi2c->State     = HAL_FMPI2C_STATE_BUSY_TX;
3394     hfmpi2c->Mode      = HAL_FMPI2C_MODE_MASTER;
3395     hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE;
3396 
3397     /* Prepare transfer parameters */
3398     hfmpi2c->pBuffPtr    = pData;
3399     hfmpi2c->XferCount   = Size;
3400     hfmpi2c->XferOptions = XferOptions;
3401     hfmpi2c->XferISR     = FMPI2C_Master_ISR_IT;
3402 
3403     /* If hfmpi2c->XferCount > MAX_NBYTE_SIZE, use reload mode */
3404     if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
3405     {
3406       hfmpi2c->XferSize = MAX_NBYTE_SIZE;
3407       xfermode = FMPI2C_RELOAD_MODE;
3408     }
3409     else
3410     {
3411       hfmpi2c->XferSize = hfmpi2c->XferCount;
3412       xfermode = hfmpi2c->XferOptions;
3413     }
3414 
3415     if ((hfmpi2c->XferSize > 0U) && ((XferOptions == FMPI2C_FIRST_FRAME) || \
3416                                      (XferOptions == FMPI2C_FIRST_AND_LAST_FRAME)))
3417     {
3418       /* Preload TX register */
3419       /* Write data to TXDR */
3420       hfmpi2c->Instance->TXDR = *hfmpi2c->pBuffPtr;
3421 
3422       /* Increment Buffer pointer */
3423       hfmpi2c->pBuffPtr++;
3424 
3425       sizetoxfer = hfmpi2c->XferSize;
3426       hfmpi2c->XferCount--;
3427       hfmpi2c->XferSize--;
3428     }
3429 
3430     /* If transfer direction not change and there is no request to start another frame,
3431        do not generate Restart Condition */
3432     /* Mean Previous state is same as current state */
3433     if ((hfmpi2c->PreviousState == FMPI2C_STATE_MASTER_BUSY_TX) && \
3434         (IS_FMPI2C_TRANSFER_OTHER_OPTIONS_REQUEST(XferOptions) == 0))
3435     {
3436       xferrequest = FMPI2C_NO_STARTSTOP;
3437     }
3438     else
3439     {
3440       /* Convert OTHER_xxx XferOptions if any */
3441       FMPI2C_ConvertOtherXferOptions(hfmpi2c);
3442 
3443       /* Update xfermode accordingly if no reload is necessary */
3444       if (hfmpi2c->XferCount <= MAX_NBYTE_SIZE)
3445       {
3446         xfermode = hfmpi2c->XferOptions;
3447       }
3448     }
3449 
3450     /* Send Slave Address and set NBYTES to write */
3451     if ((XferOptions == FMPI2C_FIRST_FRAME) || (XferOptions == FMPI2C_FIRST_AND_LAST_FRAME))
3452     {
3453       FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)sizetoxfer, xfermode, xferrequest);
3454     }
3455     else
3456     {
3457       FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, xfermode, xferrequest);
3458     }
3459 
3460     /* Process Unlocked */
3461     __HAL_UNLOCK(hfmpi2c);
3462 
3463     /* Note : The FMPI2C interrupts must be enabled after unlocking current process
3464               to avoid the risk of FMPI2C interrupt handle execution before current
3465               process unlock */
3466     /* Enable ERR, TC, STOP, NACK, TXI interrupt */
3467     /* possible to enable all of these */
3468     /* FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI |
3469        FMPI2C_IT_ADDRI | FMPI2C_IT_RXI | FMPI2C_IT_TXI */
3470     FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT);
3471 
3472     return HAL_OK;
3473   }
3474   else
3475   {
3476     return HAL_BUSY;
3477   }
3478 }
3479 
3480 /**
3481   * @brief  Sequential transmit in master FMPI2C mode an amount of data in non-blocking mode with DMA.
3482   * @note   This interface allow to manage repeated start condition when a direction change during transfer
3483   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
3484   *                the configuration information for the specified FMPI2C.
3485   * @param  DevAddress Target device address: The device 7 bits address value
3486   *         in datasheet must be shifted to the left before calling the interface
3487   * @param  pData Pointer to data buffer
3488   * @param  Size Amount of data to be sent
3489   * @param  XferOptions Options of Transfer, value of @ref FMPI2C_XFEROPTIONS
3490   * @retval HAL status
3491   */
HAL_FMPI2C_Master_Seq_Transmit_DMA(FMPI2C_HandleTypeDef * hfmpi2c,uint16_t DevAddress,uint8_t * pData,uint16_t Size,uint32_t XferOptions)3492 HAL_StatusTypeDef HAL_FMPI2C_Master_Seq_Transmit_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t *pData,
3493                                                      uint16_t Size, uint32_t XferOptions)
3494 {
3495   uint32_t xfermode;
3496   uint32_t xferrequest = FMPI2C_GENERATE_START_WRITE;
3497   HAL_StatusTypeDef dmaxferstatus;
3498   uint32_t sizetoxfer = 0U;
3499 
3500   /* Check the parameters */
3501   assert_param(IS_FMPI2C_TRANSFER_OPTIONS_REQUEST(XferOptions));
3502 
3503   if (hfmpi2c->State == HAL_FMPI2C_STATE_READY)
3504   {
3505     /* Process Locked */
3506     __HAL_LOCK(hfmpi2c);
3507 
3508     hfmpi2c->State     = HAL_FMPI2C_STATE_BUSY_TX;
3509     hfmpi2c->Mode      = HAL_FMPI2C_MODE_MASTER;
3510     hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE;
3511 
3512     /* Prepare transfer parameters */
3513     hfmpi2c->pBuffPtr    = pData;
3514     hfmpi2c->XferCount   = Size;
3515     hfmpi2c->XferOptions = XferOptions;
3516     hfmpi2c->XferISR     = FMPI2C_Master_ISR_DMA;
3517 
3518     /* If hfmpi2c->XferCount > MAX_NBYTE_SIZE, use reload mode */
3519     if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
3520     {
3521       hfmpi2c->XferSize = MAX_NBYTE_SIZE;
3522       xfermode = FMPI2C_RELOAD_MODE;
3523     }
3524     else
3525     {
3526       hfmpi2c->XferSize = hfmpi2c->XferCount;
3527       xfermode = hfmpi2c->XferOptions;
3528     }
3529 
3530     if ((hfmpi2c->XferSize > 0U) && ((XferOptions == FMPI2C_FIRST_FRAME) || \
3531                                      (XferOptions == FMPI2C_FIRST_AND_LAST_FRAME)))
3532     {
3533       /* Preload TX register */
3534       /* Write data to TXDR */
3535       hfmpi2c->Instance->TXDR = *hfmpi2c->pBuffPtr;
3536 
3537       /* Increment Buffer pointer */
3538       hfmpi2c->pBuffPtr++;
3539 
3540       sizetoxfer = hfmpi2c->XferSize;
3541       hfmpi2c->XferCount--;
3542       hfmpi2c->XferSize--;
3543     }
3544 
3545     /* If transfer direction not change and there is no request to start another frame,
3546        do not generate Restart Condition */
3547     /* Mean Previous state is same as current state */
3548     if ((hfmpi2c->PreviousState == FMPI2C_STATE_MASTER_BUSY_TX) && \
3549         (IS_FMPI2C_TRANSFER_OTHER_OPTIONS_REQUEST(XferOptions) == 0))
3550     {
3551       xferrequest = FMPI2C_NO_STARTSTOP;
3552     }
3553     else
3554     {
3555       /* Convert OTHER_xxx XferOptions if any */
3556       FMPI2C_ConvertOtherXferOptions(hfmpi2c);
3557 
3558       /* Update xfermode accordingly if no reload is necessary */
3559       if (hfmpi2c->XferCount <= MAX_NBYTE_SIZE)
3560       {
3561         xfermode = hfmpi2c->XferOptions;
3562       }
3563     }
3564 
3565     if (hfmpi2c->XferSize > 0U)
3566     {
3567       if (hfmpi2c->hdmatx != NULL)
3568       {
3569         /* Set the FMPI2C DMA transfer complete callback */
3570         hfmpi2c->hdmatx->XferCpltCallback = FMPI2C_DMAMasterTransmitCplt;
3571 
3572         /* Set the DMA error callback */
3573         hfmpi2c->hdmatx->XferErrorCallback = FMPI2C_DMAError;
3574 
3575         /* Set the unused DMA callbacks to NULL */
3576         hfmpi2c->hdmatx->XferHalfCpltCallback = NULL;
3577         hfmpi2c->hdmatx->XferAbortCallback = NULL;
3578 
3579         /* Enable the DMA stream */
3580         dmaxferstatus = HAL_DMA_Start_IT(hfmpi2c->hdmatx, (uint32_t)hfmpi2c->pBuffPtr,
3581                                          (uint32_t)&hfmpi2c->Instance->TXDR, hfmpi2c->XferSize);
3582       }
3583       else
3584       {
3585         /* Update FMPI2C state */
3586         hfmpi2c->State     = HAL_FMPI2C_STATE_READY;
3587         hfmpi2c->Mode      = HAL_FMPI2C_MODE_NONE;
3588 
3589         /* Update FMPI2C error code */
3590         hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA_PARAM;
3591 
3592         /* Process Unlocked */
3593         __HAL_UNLOCK(hfmpi2c);
3594 
3595         return HAL_ERROR;
3596       }
3597 
3598       if (dmaxferstatus == HAL_OK)
3599       {
3600         /* Send Slave Address and set NBYTES to write */
3601         if ((XferOptions == FMPI2C_FIRST_FRAME) || (XferOptions == FMPI2C_FIRST_AND_LAST_FRAME))
3602         {
3603           FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)sizetoxfer, xfermode, xferrequest);
3604         }
3605         else
3606         {
3607           FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, xfermode, xferrequest);
3608         }
3609 
3610         /* Update XferCount value */
3611         hfmpi2c->XferCount -= hfmpi2c->XferSize;
3612 
3613         /* Process Unlocked */
3614         __HAL_UNLOCK(hfmpi2c);
3615 
3616         /* Note : The FMPI2C interrupts must be enabled after unlocking current process
3617                   to avoid the risk of FMPI2C interrupt handle execution before current
3618                   process unlock */
3619         /* Enable ERR and NACK interrupts */
3620         FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_ERROR_IT);
3621 
3622         /* Enable DMA Request */
3623         hfmpi2c->Instance->CR1 |= FMPI2C_CR1_TXDMAEN;
3624       }
3625       else
3626       {
3627         /* Update FMPI2C state */
3628         hfmpi2c->State     = HAL_FMPI2C_STATE_READY;
3629         hfmpi2c->Mode      = HAL_FMPI2C_MODE_NONE;
3630 
3631         /* Update FMPI2C error code */
3632         hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA;
3633 
3634         /* Process Unlocked */
3635         __HAL_UNLOCK(hfmpi2c);
3636 
3637         return HAL_ERROR;
3638       }
3639     }
3640     else
3641     {
3642       /* Update Transfer ISR function pointer */
3643       hfmpi2c->XferISR = FMPI2C_Master_ISR_IT;
3644 
3645       /* Send Slave Address */
3646       /* Set NBYTES to write and generate START condition */
3647       if ((XferOptions == FMPI2C_FIRST_FRAME) || (XferOptions == FMPI2C_FIRST_AND_LAST_FRAME))
3648       {
3649         FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)sizetoxfer, xfermode, xferrequest);
3650       }
3651       else
3652       {
3653         FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, xfermode, xferrequest);
3654       }
3655 
3656       /* Process Unlocked */
3657       __HAL_UNLOCK(hfmpi2c);
3658 
3659       /* Note : The FMPI2C interrupts must be enabled after unlocking current process
3660                 to avoid the risk of FMPI2C interrupt handle execution before current
3661                 process unlock */
3662       /* Enable ERR, TC, STOP, NACK, TXI interrupt */
3663       /* possible to enable all of these */
3664       /* FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI |
3665         FMPI2C_IT_ADDRI | FMPI2C_IT_RXI | FMPI2C_IT_TXI */
3666       FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT);
3667     }
3668 
3669     return HAL_OK;
3670   }
3671   else
3672   {
3673     return HAL_BUSY;
3674   }
3675 }
3676 
3677 /**
3678   * @brief  Sequential receive in master FMPI2C mode an amount of data in non-blocking mode with Interrupt
3679   * @note   This interface allow to manage repeated start condition when a direction change during transfer
3680   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
3681   *                the configuration information for the specified FMPI2C.
3682   * @param  DevAddress Target device address: The device 7 bits address value
3683   *         in datasheet must be shifted to the left before calling the interface
3684   * @param  pData Pointer to data buffer
3685   * @param  Size Amount of data to be sent
3686   * @param  XferOptions Options of Transfer, value of @ref FMPI2C_XFEROPTIONS
3687   * @retval HAL status
3688   */
HAL_FMPI2C_Master_Seq_Receive_IT(FMPI2C_HandleTypeDef * hfmpi2c,uint16_t DevAddress,uint8_t * pData,uint16_t Size,uint32_t XferOptions)3689 HAL_StatusTypeDef HAL_FMPI2C_Master_Seq_Receive_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t *pData,
3690                                                    uint16_t Size, uint32_t XferOptions)
3691 {
3692   uint32_t xfermode;
3693   uint32_t xferrequest = FMPI2C_GENERATE_START_READ;
3694 
3695   /* Check the parameters */
3696   assert_param(IS_FMPI2C_TRANSFER_OPTIONS_REQUEST(XferOptions));
3697 
3698   if (hfmpi2c->State == HAL_FMPI2C_STATE_READY)
3699   {
3700     /* Process Locked */
3701     __HAL_LOCK(hfmpi2c);
3702 
3703     hfmpi2c->State     = HAL_FMPI2C_STATE_BUSY_RX;
3704     hfmpi2c->Mode      = HAL_FMPI2C_MODE_MASTER;
3705     hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE;
3706 
3707     /* Prepare transfer parameters */
3708     hfmpi2c->pBuffPtr    = pData;
3709     hfmpi2c->XferCount   = Size;
3710     hfmpi2c->XferOptions = XferOptions;
3711     hfmpi2c->XferISR     = FMPI2C_Master_ISR_IT;
3712 
3713     /* If hfmpi2c->XferCount > MAX_NBYTE_SIZE, use reload mode */
3714     if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
3715     {
3716       hfmpi2c->XferSize = MAX_NBYTE_SIZE;
3717       xfermode = FMPI2C_RELOAD_MODE;
3718     }
3719     else
3720     {
3721       hfmpi2c->XferSize = hfmpi2c->XferCount;
3722       xfermode = hfmpi2c->XferOptions;
3723     }
3724 
3725     /* If transfer direction not change and there is no request to start another frame,
3726        do not generate Restart Condition */
3727     /* Mean Previous state is same as current state */
3728     if ((hfmpi2c->PreviousState == FMPI2C_STATE_MASTER_BUSY_RX) && \
3729         (IS_FMPI2C_TRANSFER_OTHER_OPTIONS_REQUEST(XferOptions) == 0))
3730     {
3731       xferrequest = FMPI2C_NO_STARTSTOP;
3732     }
3733     else
3734     {
3735       /* Convert OTHER_xxx XferOptions if any */
3736       FMPI2C_ConvertOtherXferOptions(hfmpi2c);
3737 
3738       /* Update xfermode accordingly if no reload is necessary */
3739       if (hfmpi2c->XferCount <= MAX_NBYTE_SIZE)
3740       {
3741         xfermode = hfmpi2c->XferOptions;
3742       }
3743     }
3744 
3745     /* Send Slave Address and set NBYTES to read */
3746     FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, xfermode, xferrequest);
3747 
3748     /* Process Unlocked */
3749     __HAL_UNLOCK(hfmpi2c);
3750 
3751     /* Note : The FMPI2C interrupts must be enabled after unlocking current process
3752               to avoid the risk of FMPI2C interrupt handle execution before current
3753               process unlock */
3754     FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_RX_IT);
3755 
3756     return HAL_OK;
3757   }
3758   else
3759   {
3760     return HAL_BUSY;
3761   }
3762 }
3763 
3764 /**
3765   * @brief  Sequential receive in master FMPI2C mode an amount of data in non-blocking mode with DMA
3766   * @note   This interface allow to manage repeated start condition when a direction change during transfer
3767   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
3768   *                the configuration information for the specified FMPI2C.
3769   * @param  DevAddress Target device address: The device 7 bits address value
3770   *         in datasheet must be shifted to the left before calling the interface
3771   * @param  pData Pointer to data buffer
3772   * @param  Size Amount of data to be sent
3773   * @param  XferOptions Options of Transfer, value of @ref FMPI2C_XFEROPTIONS
3774   * @retval HAL status
3775   */
HAL_FMPI2C_Master_Seq_Receive_DMA(FMPI2C_HandleTypeDef * hfmpi2c,uint16_t DevAddress,uint8_t * pData,uint16_t Size,uint32_t XferOptions)3776 HAL_StatusTypeDef HAL_FMPI2C_Master_Seq_Receive_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t *pData,
3777                                                     uint16_t Size, uint32_t XferOptions)
3778 {
3779   uint32_t xfermode;
3780   uint32_t xferrequest = FMPI2C_GENERATE_START_READ;
3781   HAL_StatusTypeDef dmaxferstatus;
3782 
3783   /* Check the parameters */
3784   assert_param(IS_FMPI2C_TRANSFER_OPTIONS_REQUEST(XferOptions));
3785 
3786   if (hfmpi2c->State == HAL_FMPI2C_STATE_READY)
3787   {
3788     /* Process Locked */
3789     __HAL_LOCK(hfmpi2c);
3790 
3791     hfmpi2c->State     = HAL_FMPI2C_STATE_BUSY_RX;
3792     hfmpi2c->Mode      = HAL_FMPI2C_MODE_MASTER;
3793     hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE;
3794 
3795     /* Prepare transfer parameters */
3796     hfmpi2c->pBuffPtr    = pData;
3797     hfmpi2c->XferCount   = Size;
3798     hfmpi2c->XferOptions = XferOptions;
3799     hfmpi2c->XferISR     = FMPI2C_Master_ISR_DMA;
3800 
3801     /* If hfmpi2c->XferCount > MAX_NBYTE_SIZE, use reload mode */
3802     if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
3803     {
3804       hfmpi2c->XferSize = MAX_NBYTE_SIZE;
3805       xfermode = FMPI2C_RELOAD_MODE;
3806     }
3807     else
3808     {
3809       hfmpi2c->XferSize = hfmpi2c->XferCount;
3810       xfermode = hfmpi2c->XferOptions;
3811     }
3812 
3813     /* If transfer direction not change and there is no request to start another frame,
3814        do not generate Restart Condition */
3815     /* Mean Previous state is same as current state */
3816     if ((hfmpi2c->PreviousState == FMPI2C_STATE_MASTER_BUSY_RX) && \
3817         (IS_FMPI2C_TRANSFER_OTHER_OPTIONS_REQUEST(XferOptions) == 0))
3818     {
3819       xferrequest = FMPI2C_NO_STARTSTOP;
3820     }
3821     else
3822     {
3823       /* Convert OTHER_xxx XferOptions if any */
3824       FMPI2C_ConvertOtherXferOptions(hfmpi2c);
3825 
3826       /* Update xfermode accordingly if no reload is necessary */
3827       if (hfmpi2c->XferCount <= MAX_NBYTE_SIZE)
3828       {
3829         xfermode = hfmpi2c->XferOptions;
3830       }
3831     }
3832 
3833     if (hfmpi2c->XferSize > 0U)
3834     {
3835       if (hfmpi2c->hdmarx != NULL)
3836       {
3837         /* Set the FMPI2C DMA transfer complete callback */
3838         hfmpi2c->hdmarx->XferCpltCallback = FMPI2C_DMAMasterReceiveCplt;
3839 
3840         /* Set the DMA error callback */
3841         hfmpi2c->hdmarx->XferErrorCallback = FMPI2C_DMAError;
3842 
3843         /* Set the unused DMA callbacks to NULL */
3844         hfmpi2c->hdmarx->XferHalfCpltCallback = NULL;
3845         hfmpi2c->hdmarx->XferAbortCallback = NULL;
3846 
3847         /* Enable the DMA stream */
3848         dmaxferstatus = HAL_DMA_Start_IT(hfmpi2c->hdmarx, (uint32_t)&hfmpi2c->Instance->RXDR, (uint32_t)pData,
3849                                          hfmpi2c->XferSize);
3850       }
3851       else
3852       {
3853         /* Update FMPI2C state */
3854         hfmpi2c->State     = HAL_FMPI2C_STATE_READY;
3855         hfmpi2c->Mode      = HAL_FMPI2C_MODE_NONE;
3856 
3857         /* Update FMPI2C error code */
3858         hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA_PARAM;
3859 
3860         /* Process Unlocked */
3861         __HAL_UNLOCK(hfmpi2c);
3862 
3863         return HAL_ERROR;
3864       }
3865 
3866       if (dmaxferstatus == HAL_OK)
3867       {
3868         /* Send Slave Address and set NBYTES to read */
3869         FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, xfermode, xferrequest);
3870 
3871         /* Update XferCount value */
3872         hfmpi2c->XferCount -= hfmpi2c->XferSize;
3873 
3874         /* Process Unlocked */
3875         __HAL_UNLOCK(hfmpi2c);
3876 
3877         /* Note : The FMPI2C interrupts must be enabled after unlocking current process
3878                   to avoid the risk of FMPI2C interrupt handle execution before current
3879                   process unlock */
3880         /* Enable ERR and NACK interrupts */
3881         FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_ERROR_IT);
3882 
3883         /* Enable DMA Request */
3884         hfmpi2c->Instance->CR1 |= FMPI2C_CR1_RXDMAEN;
3885       }
3886       else
3887       {
3888         /* Update FMPI2C state */
3889         hfmpi2c->State     = HAL_FMPI2C_STATE_READY;
3890         hfmpi2c->Mode      = HAL_FMPI2C_MODE_NONE;
3891 
3892         /* Update FMPI2C error code */
3893         hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA;
3894 
3895         /* Process Unlocked */
3896         __HAL_UNLOCK(hfmpi2c);
3897 
3898         return HAL_ERROR;
3899       }
3900     }
3901     else
3902     {
3903       /* Update Transfer ISR function pointer */
3904       hfmpi2c->XferISR = FMPI2C_Master_ISR_IT;
3905 
3906       /* Send Slave Address */
3907       /* Set NBYTES to read and generate START condition */
3908       FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_AUTOEND_MODE,
3909                             FMPI2C_GENERATE_START_READ);
3910 
3911       /* Process Unlocked */
3912       __HAL_UNLOCK(hfmpi2c);
3913 
3914       /* Note : The FMPI2C interrupts must be enabled after unlocking current process
3915                 to avoid the risk of FMPI2C interrupt handle execution before current
3916                 process unlock */
3917       /* Enable ERR, TC, STOP, NACK, RXI interrupt */
3918       /* possible to enable all of these */
3919       /* FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI |
3920         FMPI2C_IT_ADDRI | FMPI2C_IT_RXI | FMPI2C_IT_TXI */
3921       FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_RX_IT);
3922     }
3923 
3924     return HAL_OK;
3925   }
3926   else
3927   {
3928     return HAL_BUSY;
3929   }
3930 }
3931 
3932 /**
3933   * @brief  Sequential transmit in slave/device FMPI2C mode an amount of data in non-blocking mode with Interrupt
3934   * @note   This interface allow to manage repeated start condition when a direction change during transfer
3935   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
3936   *                the configuration information for the specified FMPI2C.
3937   * @param  pData Pointer to data buffer
3938   * @param  Size Amount of data to be sent
3939   * @param  XferOptions Options of Transfer, value of @ref FMPI2C_XFEROPTIONS
3940   * @retval HAL status
3941   */
HAL_FMPI2C_Slave_Seq_Transmit_IT(FMPI2C_HandleTypeDef * hfmpi2c,uint8_t * pData,uint16_t Size,uint32_t XferOptions)3942 HAL_StatusTypeDef HAL_FMPI2C_Slave_Seq_Transmit_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t *pData, uint16_t Size,
3943                                                    uint32_t XferOptions)
3944 {
3945   /* Declaration of tmp to prevent undefined behavior of volatile usage */
3946   FlagStatus tmp;
3947 
3948   /* Check the parameters */
3949   assert_param(IS_FMPI2C_TRANSFER_OPTIONS_REQUEST(XferOptions));
3950 
3951   if (((uint32_t)hfmpi2c->State & (uint32_t)HAL_FMPI2C_STATE_LISTEN) == (uint32_t)HAL_FMPI2C_STATE_LISTEN)
3952   {
3953     if ((pData == NULL) || (Size == 0U))
3954     {
3955       hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_INVALID_PARAM;
3956       return  HAL_ERROR;
3957     }
3958 
3959     /* Disable Interrupts, to prevent preemption during treatment in case of multicall */
3960     FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT | FMPI2C_XFER_TX_IT);
3961 
3962     /* Process Locked */
3963     __HAL_LOCK(hfmpi2c);
3964 
3965     /* FMPI2C cannot manage full duplex exchange so disable previous IT enabled if any */
3966     /* and then toggle the HAL slave RX state to TX state */
3967     if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX_LISTEN)
3968     {
3969       /* Disable associated Interrupts */
3970       FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_RX_IT);
3971 
3972       /* Abort DMA Xfer if any */
3973       if ((hfmpi2c->Instance->CR1 & FMPI2C_CR1_RXDMAEN) == FMPI2C_CR1_RXDMAEN)
3974       {
3975         hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_RXDMAEN;
3976 
3977         if (hfmpi2c->hdmarx != NULL)
3978         {
3979           /* Set the FMPI2C DMA Abort callback :
3980            will lead to call HAL_FMPI2C_ErrorCallback() at end of DMA abort procedure */
3981           hfmpi2c->hdmarx->XferAbortCallback = FMPI2C_DMAAbort;
3982 
3983           /* Abort DMA RX */
3984           if (HAL_DMA_Abort_IT(hfmpi2c->hdmarx) != HAL_OK)
3985           {
3986             /* Call Directly XferAbortCallback function in case of error */
3987             hfmpi2c->hdmarx->XferAbortCallback(hfmpi2c->hdmarx);
3988           }
3989         }
3990       }
3991     }
3992 
3993     hfmpi2c->State     = HAL_FMPI2C_STATE_BUSY_TX_LISTEN;
3994     hfmpi2c->Mode      = HAL_FMPI2C_MODE_SLAVE;
3995     hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE;
3996 
3997     /* Enable Address Acknowledge */
3998     hfmpi2c->Instance->CR2 &= ~FMPI2C_CR2_NACK;
3999 
4000     /* Prepare transfer parameters */
4001     hfmpi2c->pBuffPtr    = pData;
4002     hfmpi2c->XferCount   = Size;
4003     hfmpi2c->XferSize    = hfmpi2c->XferCount;
4004     hfmpi2c->XferOptions = XferOptions;
4005     hfmpi2c->XferISR     = FMPI2C_Slave_ISR_IT;
4006 
4007     tmp = __HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_ADDR);
4008     if ((FMPI2C_GET_DIR(hfmpi2c) == FMPI2C_DIRECTION_RECEIVE) && (tmp != RESET))
4009     {
4010       /* Clear ADDR flag after prepare the transfer parameters */
4011       /* This action will generate an acknowledge to the Master */
4012       __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_ADDR);
4013     }
4014 
4015     /* Process Unlocked */
4016     __HAL_UNLOCK(hfmpi2c);
4017 
4018     /* Note : The FMPI2C interrupts must be enabled after unlocking current process
4019     to avoid the risk of FMPI2C interrupt handle execution before current
4020     process unlock */
4021     /* REnable ADDR interrupt */
4022     FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT | FMPI2C_XFER_LISTEN_IT);
4023 
4024     return HAL_OK;
4025   }
4026   else
4027   {
4028     return HAL_ERROR;
4029   }
4030 }
4031 
4032 /**
4033   * @brief  Sequential transmit in slave/device FMPI2C mode an amount of data in non-blocking mode with DMA
4034   * @note   This interface allow to manage repeated start condition when a direction change during transfer
4035   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
4036   *                the configuration information for the specified FMPI2C.
4037   * @param  pData Pointer to data buffer
4038   * @param  Size Amount of data to be sent
4039   * @param  XferOptions Options of Transfer, value of @ref FMPI2C_XFEROPTIONS
4040   * @retval HAL status
4041   */
HAL_FMPI2C_Slave_Seq_Transmit_DMA(FMPI2C_HandleTypeDef * hfmpi2c,uint8_t * pData,uint16_t Size,uint32_t XferOptions)4042 HAL_StatusTypeDef HAL_FMPI2C_Slave_Seq_Transmit_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t *pData, uint16_t Size,
4043                                                     uint32_t XferOptions)
4044 {
4045   /* Declaration of tmp to prevent undefined behavior of volatile usage */
4046   FlagStatus tmp;
4047   HAL_StatusTypeDef dmaxferstatus;
4048 
4049   /* Check the parameters */
4050   assert_param(IS_FMPI2C_TRANSFER_OPTIONS_REQUEST(XferOptions));
4051 
4052   if (((uint32_t)hfmpi2c->State & (uint32_t)HAL_FMPI2C_STATE_LISTEN) == (uint32_t)HAL_FMPI2C_STATE_LISTEN)
4053   {
4054     if ((pData == NULL) || (Size == 0U))
4055     {
4056       hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_INVALID_PARAM;
4057       return  HAL_ERROR;
4058     }
4059 
4060     /* Process Locked */
4061     __HAL_LOCK(hfmpi2c);
4062 
4063     /* Disable Interrupts, to prevent preemption during treatment in case of multicall */
4064     FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT | FMPI2C_XFER_TX_IT);
4065 
4066     /* FMPI2C cannot manage full duplex exchange so disable previous IT enabled if any */
4067     /* and then toggle the HAL slave RX state to TX state */
4068     if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX_LISTEN)
4069     {
4070       /* Disable associated Interrupts */
4071       FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_RX_IT);
4072 
4073       if ((hfmpi2c->Instance->CR1 & FMPI2C_CR1_RXDMAEN) == FMPI2C_CR1_RXDMAEN)
4074       {
4075         /* Abort DMA Xfer if any */
4076         if (hfmpi2c->hdmarx != NULL)
4077         {
4078           hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_RXDMAEN;
4079 
4080           /* Set the FMPI2C DMA Abort callback :
4081           will lead to call HAL_FMPI2C_ErrorCallback() at end of DMA abort procedure */
4082           hfmpi2c->hdmarx->XferAbortCallback = FMPI2C_DMAAbort;
4083 
4084           /* Abort DMA RX */
4085           if (HAL_DMA_Abort_IT(hfmpi2c->hdmarx) != HAL_OK)
4086           {
4087             /* Call Directly XferAbortCallback function in case of error */
4088             hfmpi2c->hdmarx->XferAbortCallback(hfmpi2c->hdmarx);
4089           }
4090         }
4091       }
4092     }
4093     else if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_TX_LISTEN)
4094     {
4095       if ((hfmpi2c->Instance->CR1 & FMPI2C_CR1_TXDMAEN) == FMPI2C_CR1_TXDMAEN)
4096       {
4097         hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_TXDMAEN;
4098 
4099         /* Abort DMA Xfer if any */
4100         if (hfmpi2c->hdmatx != NULL)
4101         {
4102           /* Set the FMPI2C DMA Abort callback :
4103           will lead to call HAL_FMPI2C_ErrorCallback() at end of DMA abort procedure */
4104           hfmpi2c->hdmatx->XferAbortCallback = FMPI2C_DMAAbort;
4105 
4106           /* Abort DMA TX */
4107           if (HAL_DMA_Abort_IT(hfmpi2c->hdmatx) != HAL_OK)
4108           {
4109             /* Call Directly XferAbortCallback function in case of error */
4110             hfmpi2c->hdmatx->XferAbortCallback(hfmpi2c->hdmatx);
4111           }
4112         }
4113       }
4114     }
4115     else
4116     {
4117       /* Nothing to do */
4118     }
4119 
4120     hfmpi2c->State     = HAL_FMPI2C_STATE_BUSY_TX_LISTEN;
4121     hfmpi2c->Mode      = HAL_FMPI2C_MODE_SLAVE;
4122     hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE;
4123 
4124     /* Enable Address Acknowledge */
4125     hfmpi2c->Instance->CR2 &= ~FMPI2C_CR2_NACK;
4126 
4127     /* Prepare transfer parameters */
4128     hfmpi2c->pBuffPtr    = pData;
4129     hfmpi2c->XferCount   = Size;
4130     hfmpi2c->XferSize    = hfmpi2c->XferCount;
4131     hfmpi2c->XferOptions = XferOptions;
4132     hfmpi2c->XferISR     = FMPI2C_Slave_ISR_DMA;
4133 
4134     if (hfmpi2c->hdmatx != NULL)
4135     {
4136       /* Set the FMPI2C DMA transfer complete callback */
4137       hfmpi2c->hdmatx->XferCpltCallback = FMPI2C_DMASlaveTransmitCplt;
4138 
4139       /* Set the DMA error callback */
4140       hfmpi2c->hdmatx->XferErrorCallback = FMPI2C_DMAError;
4141 
4142       /* Set the unused DMA callbacks to NULL */
4143       hfmpi2c->hdmatx->XferHalfCpltCallback = NULL;
4144       hfmpi2c->hdmatx->XferAbortCallback = NULL;
4145 
4146       /* Enable the DMA stream */
4147       dmaxferstatus = HAL_DMA_Start_IT(hfmpi2c->hdmatx, (uint32_t)pData, (uint32_t)&hfmpi2c->Instance->TXDR,
4148                                        hfmpi2c->XferSize);
4149     }
4150     else
4151     {
4152       /* Update FMPI2C state */
4153       hfmpi2c->State     = HAL_FMPI2C_STATE_LISTEN;
4154       hfmpi2c->Mode      = HAL_FMPI2C_MODE_NONE;
4155 
4156       /* Update FMPI2C error code */
4157       hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA_PARAM;
4158 
4159       /* Process Unlocked */
4160       __HAL_UNLOCK(hfmpi2c);
4161 
4162       return HAL_ERROR;
4163     }
4164 
4165     if (dmaxferstatus == HAL_OK)
4166     {
4167       /* Update XferCount value */
4168       hfmpi2c->XferCount -= hfmpi2c->XferSize;
4169 
4170       /* Reset XferSize */
4171       hfmpi2c->XferSize = 0;
4172     }
4173     else
4174     {
4175       /* Update FMPI2C state */
4176       hfmpi2c->State     = HAL_FMPI2C_STATE_LISTEN;
4177       hfmpi2c->Mode      = HAL_FMPI2C_MODE_NONE;
4178 
4179       /* Update FMPI2C error code */
4180       hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA;
4181 
4182       /* Process Unlocked */
4183       __HAL_UNLOCK(hfmpi2c);
4184 
4185       return HAL_ERROR;
4186     }
4187 
4188     tmp = __HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_ADDR);
4189     if ((FMPI2C_GET_DIR(hfmpi2c) == FMPI2C_DIRECTION_RECEIVE) && (tmp != RESET))
4190     {
4191       /* Clear ADDR flag after prepare the transfer parameters */
4192       /* This action will generate an acknowledge to the Master */
4193       __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_ADDR);
4194     }
4195 
4196     /* Process Unlocked */
4197     __HAL_UNLOCK(hfmpi2c);
4198 
4199     /* Enable DMA Request */
4200     hfmpi2c->Instance->CR1 |= FMPI2C_CR1_TXDMAEN;
4201 
4202     /* Note : The FMPI2C interrupts must be enabled after unlocking current process
4203     to avoid the risk of FMPI2C interrupt handle execution before current
4204     process unlock */
4205     /* Enable ERR, STOP, NACK, ADDR interrupts */
4206     FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT);
4207 
4208     return HAL_OK;
4209   }
4210   else
4211   {
4212     return HAL_ERROR;
4213   }
4214 }
4215 
4216 /**
4217   * @brief  Sequential receive in slave/device FMPI2C mode an amount of data in non-blocking mode with Interrupt
4218   * @note   This interface allow to manage repeated start condition when a direction change during transfer
4219   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
4220   *                the configuration information for the specified FMPI2C.
4221   * @param  pData Pointer to data buffer
4222   * @param  Size Amount of data to be sent
4223   * @param  XferOptions Options of Transfer, value of @ref FMPI2C_XFEROPTIONS
4224   * @retval HAL status
4225   */
HAL_FMPI2C_Slave_Seq_Receive_IT(FMPI2C_HandleTypeDef * hfmpi2c,uint8_t * pData,uint16_t Size,uint32_t XferOptions)4226 HAL_StatusTypeDef HAL_FMPI2C_Slave_Seq_Receive_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t *pData, uint16_t Size,
4227                                                   uint32_t XferOptions)
4228 {
4229   /* Declaration of tmp to prevent undefined behavior of volatile usage */
4230   FlagStatus tmp;
4231 
4232   /* Check the parameters */
4233   assert_param(IS_FMPI2C_TRANSFER_OPTIONS_REQUEST(XferOptions));
4234 
4235   if (((uint32_t)hfmpi2c->State & (uint32_t)HAL_FMPI2C_STATE_LISTEN) == (uint32_t)HAL_FMPI2C_STATE_LISTEN)
4236   {
4237     if ((pData == NULL) || (Size == 0U))
4238     {
4239       hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_INVALID_PARAM;
4240       return  HAL_ERROR;
4241     }
4242 
4243     /* Disable Interrupts, to prevent preemption during treatment in case of multicall */
4244     FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT | FMPI2C_XFER_RX_IT);
4245 
4246     /* Process Locked */
4247     __HAL_LOCK(hfmpi2c);
4248 
4249     /* FMPI2C cannot manage full duplex exchange so disable previous IT enabled if any */
4250     /* and then toggle the HAL slave TX state to RX state */
4251     if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_TX_LISTEN)
4252     {
4253       /* Disable associated Interrupts */
4254       FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT);
4255 
4256       if ((hfmpi2c->Instance->CR1 & FMPI2C_CR1_TXDMAEN) == FMPI2C_CR1_TXDMAEN)
4257       {
4258         hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_TXDMAEN;
4259 
4260         /* Abort DMA Xfer if any */
4261         if (hfmpi2c->hdmatx != NULL)
4262         {
4263           /* Set the FMPI2C DMA Abort callback :
4264            will lead to call HAL_FMPI2C_ErrorCallback() at end of DMA abort procedure */
4265           hfmpi2c->hdmatx->XferAbortCallback = FMPI2C_DMAAbort;
4266 
4267           /* Abort DMA TX */
4268           if (HAL_DMA_Abort_IT(hfmpi2c->hdmatx) != HAL_OK)
4269           {
4270             /* Call Directly XferAbortCallback function in case of error */
4271             hfmpi2c->hdmatx->XferAbortCallback(hfmpi2c->hdmatx);
4272           }
4273         }
4274       }
4275     }
4276 
4277     hfmpi2c->State     = HAL_FMPI2C_STATE_BUSY_RX_LISTEN;
4278     hfmpi2c->Mode      = HAL_FMPI2C_MODE_SLAVE;
4279     hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE;
4280 
4281     /* Enable Address Acknowledge */
4282     hfmpi2c->Instance->CR2 &= ~FMPI2C_CR2_NACK;
4283 
4284     /* Prepare transfer parameters */
4285     hfmpi2c->pBuffPtr    = pData;
4286     hfmpi2c->XferCount   = Size;
4287     hfmpi2c->XferSize    = hfmpi2c->XferCount;
4288     hfmpi2c->XferOptions = XferOptions;
4289     hfmpi2c->XferISR     = FMPI2C_Slave_ISR_IT;
4290 
4291     tmp = __HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_ADDR);
4292     if ((FMPI2C_GET_DIR(hfmpi2c) == FMPI2C_DIRECTION_TRANSMIT) && (tmp != RESET))
4293     {
4294       /* Clear ADDR flag after prepare the transfer parameters */
4295       /* This action will generate an acknowledge to the Master */
4296       __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_ADDR);
4297     }
4298 
4299     /* Process Unlocked */
4300     __HAL_UNLOCK(hfmpi2c);
4301 
4302     /* Note : The FMPI2C interrupts must be enabled after unlocking current process
4303     to avoid the risk of FMPI2C interrupt handle execution before current
4304     process unlock */
4305     /* REnable ADDR interrupt */
4306     FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_RX_IT | FMPI2C_XFER_LISTEN_IT);
4307 
4308     return HAL_OK;
4309   }
4310   else
4311   {
4312     return HAL_ERROR;
4313   }
4314 }
4315 
4316 /**
4317   * @brief  Sequential receive in slave/device FMPI2C mode an amount of data in non-blocking mode with DMA
4318   * @note   This interface allow to manage repeated start condition when a direction change during transfer
4319   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
4320   *                the configuration information for the specified FMPI2C.
4321   * @param  pData Pointer to data buffer
4322   * @param  Size Amount of data to be sent
4323   * @param  XferOptions Options of Transfer, value of @ref FMPI2C_XFEROPTIONS
4324   * @retval HAL status
4325   */
HAL_FMPI2C_Slave_Seq_Receive_DMA(FMPI2C_HandleTypeDef * hfmpi2c,uint8_t * pData,uint16_t Size,uint32_t XferOptions)4326 HAL_StatusTypeDef HAL_FMPI2C_Slave_Seq_Receive_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t *pData, uint16_t Size,
4327                                                    uint32_t XferOptions)
4328 {
4329   /* Declaration of tmp to prevent undefined behavior of volatile usage */
4330   FlagStatus tmp;
4331   HAL_StatusTypeDef dmaxferstatus;
4332 
4333   /* Check the parameters */
4334   assert_param(IS_FMPI2C_TRANSFER_OPTIONS_REQUEST(XferOptions));
4335 
4336   if (((uint32_t)hfmpi2c->State & (uint32_t)HAL_FMPI2C_STATE_LISTEN) == (uint32_t)HAL_FMPI2C_STATE_LISTEN)
4337   {
4338     if ((pData == NULL) || (Size == 0U))
4339     {
4340       hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_INVALID_PARAM;
4341       return  HAL_ERROR;
4342     }
4343 
4344     /* Disable Interrupts, to prevent preemption during treatment in case of multicall */
4345     FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT | FMPI2C_XFER_RX_IT);
4346 
4347     /* Process Locked */
4348     __HAL_LOCK(hfmpi2c);
4349 
4350     /* FMPI2C cannot manage full duplex exchange so disable previous IT enabled if any */
4351     /* and then toggle the HAL slave TX state to RX state */
4352     if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_TX_LISTEN)
4353     {
4354       /* Disable associated Interrupts */
4355       FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT);
4356 
4357       if ((hfmpi2c->Instance->CR1 & FMPI2C_CR1_TXDMAEN) == FMPI2C_CR1_TXDMAEN)
4358       {
4359         /* Abort DMA Xfer if any */
4360         if (hfmpi2c->hdmatx != NULL)
4361         {
4362           hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_TXDMAEN;
4363 
4364           /* Set the FMPI2C DMA Abort callback :
4365            will lead to call HAL_FMPI2C_ErrorCallback() at end of DMA abort procedure */
4366           hfmpi2c->hdmatx->XferAbortCallback = FMPI2C_DMAAbort;
4367 
4368           /* Abort DMA TX */
4369           if (HAL_DMA_Abort_IT(hfmpi2c->hdmatx) != HAL_OK)
4370           {
4371             /* Call Directly XferAbortCallback function in case of error */
4372             hfmpi2c->hdmatx->XferAbortCallback(hfmpi2c->hdmatx);
4373           }
4374         }
4375       }
4376     }
4377     else if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX_LISTEN)
4378     {
4379       if ((hfmpi2c->Instance->CR1 & FMPI2C_CR1_RXDMAEN) == FMPI2C_CR1_RXDMAEN)
4380       {
4381         hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_RXDMAEN;
4382 
4383         /* Abort DMA Xfer if any */
4384         if (hfmpi2c->hdmarx != NULL)
4385         {
4386           /* Set the FMPI2C DMA Abort callback :
4387            will lead to call HAL_FMPI2C_ErrorCallback() at end of DMA abort procedure */
4388           hfmpi2c->hdmarx->XferAbortCallback = FMPI2C_DMAAbort;
4389 
4390           /* Abort DMA RX */
4391           if (HAL_DMA_Abort_IT(hfmpi2c->hdmarx) != HAL_OK)
4392           {
4393             /* Call Directly XferAbortCallback function in case of error */
4394             hfmpi2c->hdmarx->XferAbortCallback(hfmpi2c->hdmarx);
4395           }
4396         }
4397       }
4398     }
4399     else
4400     {
4401       /* Nothing to do */
4402     }
4403 
4404     hfmpi2c->State     = HAL_FMPI2C_STATE_BUSY_RX_LISTEN;
4405     hfmpi2c->Mode      = HAL_FMPI2C_MODE_SLAVE;
4406     hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE;
4407 
4408     /* Enable Address Acknowledge */
4409     hfmpi2c->Instance->CR2 &= ~FMPI2C_CR2_NACK;
4410 
4411     /* Prepare transfer parameters */
4412     hfmpi2c->pBuffPtr    = pData;
4413     hfmpi2c->XferCount   = Size;
4414     hfmpi2c->XferSize    = hfmpi2c->XferCount;
4415     hfmpi2c->XferOptions = XferOptions;
4416     hfmpi2c->XferISR     = FMPI2C_Slave_ISR_DMA;
4417 
4418     if (hfmpi2c->hdmarx != NULL)
4419     {
4420       /* Set the FMPI2C DMA transfer complete callback */
4421       hfmpi2c->hdmarx->XferCpltCallback = FMPI2C_DMASlaveReceiveCplt;
4422 
4423       /* Set the DMA error callback */
4424       hfmpi2c->hdmarx->XferErrorCallback = FMPI2C_DMAError;
4425 
4426       /* Set the unused DMA callbacks to NULL */
4427       hfmpi2c->hdmarx->XferHalfCpltCallback = NULL;
4428       hfmpi2c->hdmarx->XferAbortCallback = NULL;
4429 
4430       /* Enable the DMA stream */
4431       dmaxferstatus = HAL_DMA_Start_IT(hfmpi2c->hdmarx, (uint32_t)&hfmpi2c->Instance->RXDR,
4432                                        (uint32_t)pData, hfmpi2c->XferSize);
4433     }
4434     else
4435     {
4436       /* Update FMPI2C state */
4437       hfmpi2c->State     = HAL_FMPI2C_STATE_LISTEN;
4438       hfmpi2c->Mode      = HAL_FMPI2C_MODE_NONE;
4439 
4440       /* Update FMPI2C error code */
4441       hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA_PARAM;
4442 
4443       /* Process Unlocked */
4444       __HAL_UNLOCK(hfmpi2c);
4445 
4446       return HAL_ERROR;
4447     }
4448 
4449     if (dmaxferstatus == HAL_OK)
4450     {
4451       /* Update XferCount value */
4452       hfmpi2c->XferCount -= hfmpi2c->XferSize;
4453 
4454       /* Reset XferSize */
4455       hfmpi2c->XferSize = 0;
4456     }
4457     else
4458     {
4459       /* Update FMPI2C state */
4460       hfmpi2c->State     = HAL_FMPI2C_STATE_LISTEN;
4461       hfmpi2c->Mode      = HAL_FMPI2C_MODE_NONE;
4462 
4463       /* Update FMPI2C error code */
4464       hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA;
4465 
4466       /* Process Unlocked */
4467       __HAL_UNLOCK(hfmpi2c);
4468 
4469       return HAL_ERROR;
4470     }
4471 
4472     tmp = __HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_ADDR);
4473     if ((FMPI2C_GET_DIR(hfmpi2c) == FMPI2C_DIRECTION_TRANSMIT) && (tmp != RESET))
4474     {
4475       /* Clear ADDR flag after prepare the transfer parameters */
4476       /* This action will generate an acknowledge to the Master */
4477       __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_ADDR);
4478     }
4479 
4480     /* Process Unlocked */
4481     __HAL_UNLOCK(hfmpi2c);
4482 
4483     /* Enable DMA Request */
4484     hfmpi2c->Instance->CR1 |= FMPI2C_CR1_RXDMAEN;
4485 
4486     /* Note : The FMPI2C interrupts must be enabled after unlocking current process
4487     to avoid the risk of FMPI2C interrupt handle execution before current
4488     process unlock */
4489     /* REnable ADDR interrupt */
4490     FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_RX_IT | FMPI2C_XFER_LISTEN_IT);
4491 
4492     return HAL_OK;
4493   }
4494   else
4495   {
4496     return HAL_ERROR;
4497   }
4498 }
4499 
4500 /**
4501   * @brief  Enable the Address listen mode with Interrupt.
4502   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
4503   *                the configuration information for the specified FMPI2C.
4504   * @retval HAL status
4505   */
HAL_FMPI2C_EnableListen_IT(FMPI2C_HandleTypeDef * hfmpi2c)4506 HAL_StatusTypeDef HAL_FMPI2C_EnableListen_IT(FMPI2C_HandleTypeDef *hfmpi2c)
4507 {
4508   if (hfmpi2c->State == HAL_FMPI2C_STATE_READY)
4509   {
4510     hfmpi2c->State = HAL_FMPI2C_STATE_LISTEN;
4511     hfmpi2c->XferISR = FMPI2C_Slave_ISR_IT;
4512 
4513     /* Enable the Address Match interrupt */
4514     FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT);
4515 
4516     return HAL_OK;
4517   }
4518   else
4519   {
4520     return HAL_BUSY;
4521   }
4522 }
4523 
4524 /**
4525   * @brief  Disable the Address listen mode with Interrupt.
4526   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
4527   *                the configuration information for the specified FMPI2C
4528   * @retval HAL status
4529   */
HAL_FMPI2C_DisableListen_IT(FMPI2C_HandleTypeDef * hfmpi2c)4530 HAL_StatusTypeDef HAL_FMPI2C_DisableListen_IT(FMPI2C_HandleTypeDef *hfmpi2c)
4531 {
4532   /* Declaration of tmp to prevent undefined behavior of volatile usage */
4533   uint32_t tmp;
4534 
4535   /* Disable Address listen mode only if a transfer is not ongoing */
4536   if (hfmpi2c->State == HAL_FMPI2C_STATE_LISTEN)
4537   {
4538     tmp = (uint32_t)(hfmpi2c->State) & FMPI2C_STATE_MSK;
4539     hfmpi2c->PreviousState = tmp | (uint32_t)(hfmpi2c->Mode);
4540     hfmpi2c->State = HAL_FMPI2C_STATE_READY;
4541     hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE;
4542     hfmpi2c->XferISR = NULL;
4543 
4544     /* Disable the Address Match interrupt */
4545     FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT);
4546 
4547     return HAL_OK;
4548   }
4549   else
4550   {
4551     return HAL_BUSY;
4552   }
4553 }
4554 
4555 /**
4556   * @brief  Abort a master FMPI2C IT or DMA process communication with Interrupt.
4557   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
4558   *                the configuration information for the specified FMPI2C.
4559   * @param  DevAddress Target device address: The device 7 bits address value
4560   *         in datasheet must be shifted to the left before calling the interface
4561   * @retval HAL status
4562   */
HAL_FMPI2C_Master_Abort_IT(FMPI2C_HandleTypeDef * hfmpi2c,uint16_t DevAddress)4563 HAL_StatusTypeDef HAL_FMPI2C_Master_Abort_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress)
4564 {
4565   if (hfmpi2c->Mode == HAL_FMPI2C_MODE_MASTER)
4566   {
4567     /* Process Locked */
4568     __HAL_LOCK(hfmpi2c);
4569 
4570     /* Disable Interrupts and Store Previous state */
4571     if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_TX)
4572     {
4573       FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT);
4574       hfmpi2c->PreviousState = FMPI2C_STATE_MASTER_BUSY_TX;
4575     }
4576     else if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX)
4577     {
4578       FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_RX_IT);
4579       hfmpi2c->PreviousState = FMPI2C_STATE_MASTER_BUSY_RX;
4580     }
4581     else
4582     {
4583       /* Do nothing */
4584     }
4585 
4586     /* Set State at HAL_FMPI2C_STATE_ABORT */
4587     hfmpi2c->State = HAL_FMPI2C_STATE_ABORT;
4588 
4589     /* Set NBYTES to 1 to generate a dummy read on FMPI2C peripheral */
4590     /* Set AUTOEND mode, this will generate a NACK then STOP condition to abort the current transfer */
4591     FMPI2C_TransferConfig(hfmpi2c, DevAddress, 1, FMPI2C_AUTOEND_MODE, FMPI2C_GENERATE_STOP);
4592 
4593     /* Process Unlocked */
4594     __HAL_UNLOCK(hfmpi2c);
4595 
4596     /* Note : The FMPI2C interrupts must be enabled after unlocking current process
4597               to avoid the risk of FMPI2C interrupt handle execution before current
4598               process unlock */
4599     FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_CPLT_IT);
4600 
4601     return HAL_OK;
4602   }
4603   else
4604   {
4605     /* Wrong usage of abort function */
4606     /* This function should be used only in case of abort monitored by master device */
4607     return HAL_ERROR;
4608   }
4609 }
4610 
4611 /**
4612   * @}
4613   */
4614 
4615 /** @defgroup FMPI2C_IRQ_Handler_and_Callbacks IRQ Handler and Callbacks
4616   * @{
4617   */
4618 
4619 /**
4620   * @brief  This function handles FMPI2C event interrupt request.
4621   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
4622   *                the configuration information for the specified FMPI2C.
4623   * @retval None
4624   */
HAL_FMPI2C_EV_IRQHandler(FMPI2C_HandleTypeDef * hfmpi2c)4625 void HAL_FMPI2C_EV_IRQHandler(FMPI2C_HandleTypeDef *hfmpi2c) /* Derogation MISRAC2012-Rule-8.13 */
4626 {
4627   /* Get current IT Flags and IT sources value */
4628   uint32_t itflags   = READ_REG(hfmpi2c->Instance->ISR);
4629   uint32_t itsources = READ_REG(hfmpi2c->Instance->CR1);
4630 
4631   /* FMPI2C events treatment -------------------------------------*/
4632   if (hfmpi2c->XferISR != NULL)
4633   {
4634     hfmpi2c->XferISR(hfmpi2c, itflags, itsources);
4635   }
4636 }
4637 
4638 /**
4639   * @brief  This function handles FMPI2C error interrupt request.
4640   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
4641   *                the configuration information for the specified FMPI2C.
4642   * @retval None
4643   */
HAL_FMPI2C_ER_IRQHandler(FMPI2C_HandleTypeDef * hfmpi2c)4644 void HAL_FMPI2C_ER_IRQHandler(FMPI2C_HandleTypeDef *hfmpi2c)
4645 {
4646   uint32_t itflags   = READ_REG(hfmpi2c->Instance->ISR);
4647   uint32_t itsources = READ_REG(hfmpi2c->Instance->CR1);
4648   uint32_t tmperror;
4649 
4650   /* FMPI2C Bus error interrupt occurred ------------------------------------*/
4651   if ((FMPI2C_CHECK_FLAG(itflags, FMPI2C_FLAG_BERR) != RESET) && \
4652       (FMPI2C_CHECK_IT_SOURCE(itsources, FMPI2C_IT_ERRI) != RESET))
4653   {
4654     hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_BERR;
4655 
4656     /* Clear BERR flag */
4657     __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_BERR);
4658   }
4659 
4660   /* FMPI2C Over-Run/Under-Run interrupt occurred ----------------------------------------*/
4661   if ((FMPI2C_CHECK_FLAG(itflags, FMPI2C_FLAG_OVR) != RESET) && \
4662       (FMPI2C_CHECK_IT_SOURCE(itsources, FMPI2C_IT_ERRI) != RESET))
4663   {
4664     hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_OVR;
4665 
4666     /* Clear OVR flag */
4667     __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_OVR);
4668   }
4669 
4670   /* FMPI2C Arbitration Loss error interrupt occurred -------------------------------------*/
4671   if ((FMPI2C_CHECK_FLAG(itflags, FMPI2C_FLAG_ARLO) != RESET) && \
4672       (FMPI2C_CHECK_IT_SOURCE(itsources, FMPI2C_IT_ERRI) != RESET))
4673   {
4674     hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_ARLO;
4675 
4676     /* Clear ARLO flag */
4677     __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_ARLO);
4678   }
4679 
4680   /* Store current volatile hfmpi2c->ErrorCode, misra rule */
4681   tmperror = hfmpi2c->ErrorCode;
4682 
4683   /* Call the Error Callback in case of Error detected */
4684   if ((tmperror & (HAL_FMPI2C_ERROR_BERR | HAL_FMPI2C_ERROR_OVR | HAL_FMPI2C_ERROR_ARLO)) !=  HAL_FMPI2C_ERROR_NONE)
4685   {
4686     FMPI2C_ITError(hfmpi2c, tmperror);
4687   }
4688 }
4689 
4690 /**
4691   * @brief  Master Tx Transfer completed callback.
4692   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
4693   *                the configuration information for the specified FMPI2C.
4694   * @retval None
4695   */
HAL_FMPI2C_MasterTxCpltCallback(FMPI2C_HandleTypeDef * hfmpi2c)4696 __weak void HAL_FMPI2C_MasterTxCpltCallback(FMPI2C_HandleTypeDef *hfmpi2c)
4697 {
4698   /* Prevent unused argument(s) compilation warning */
4699   UNUSED(hfmpi2c);
4700 
4701   /* NOTE : This function should not be modified, when the callback is needed,
4702             the HAL_FMPI2C_MasterTxCpltCallback could be implemented in the user file
4703    */
4704 }
4705 
4706 /**
4707   * @brief  Master Rx Transfer completed callback.
4708   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
4709   *                the configuration information for the specified FMPI2C.
4710   * @retval None
4711   */
HAL_FMPI2C_MasterRxCpltCallback(FMPI2C_HandleTypeDef * hfmpi2c)4712 __weak void HAL_FMPI2C_MasterRxCpltCallback(FMPI2C_HandleTypeDef *hfmpi2c)
4713 {
4714   /* Prevent unused argument(s) compilation warning */
4715   UNUSED(hfmpi2c);
4716 
4717   /* NOTE : This function should not be modified, when the callback is needed,
4718             the HAL_FMPI2C_MasterRxCpltCallback could be implemented in the user file
4719    */
4720 }
4721 
4722 /** @brief  Slave Tx Transfer completed callback.
4723   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
4724   *                the configuration information for the specified FMPI2C.
4725   * @retval None
4726   */
HAL_FMPI2C_SlaveTxCpltCallback(FMPI2C_HandleTypeDef * hfmpi2c)4727 __weak void HAL_FMPI2C_SlaveTxCpltCallback(FMPI2C_HandleTypeDef *hfmpi2c)
4728 {
4729   /* Prevent unused argument(s) compilation warning */
4730   UNUSED(hfmpi2c);
4731 
4732   /* NOTE : This function should not be modified, when the callback is needed,
4733             the HAL_FMPI2C_SlaveTxCpltCallback could be implemented in the user file
4734    */
4735 }
4736 
4737 /**
4738   * @brief  Slave Rx Transfer completed callback.
4739   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
4740   *                the configuration information for the specified FMPI2C.
4741   * @retval None
4742   */
HAL_FMPI2C_SlaveRxCpltCallback(FMPI2C_HandleTypeDef * hfmpi2c)4743 __weak void HAL_FMPI2C_SlaveRxCpltCallback(FMPI2C_HandleTypeDef *hfmpi2c)
4744 {
4745   /* Prevent unused argument(s) compilation warning */
4746   UNUSED(hfmpi2c);
4747 
4748   /* NOTE : This function should not be modified, when the callback is needed,
4749             the HAL_FMPI2C_SlaveRxCpltCallback could be implemented in the user file
4750    */
4751 }
4752 
4753 /**
4754   * @brief  Slave Address Match callback.
4755   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
4756   *                the configuration information for the specified FMPI2C.
4757   * @param  TransferDirection Master request Transfer Direction (Write/Read), value of @ref FMPI2C_XFERDIRECTION
4758   * @param  AddrMatchCode Address Match Code
4759   * @retval None
4760   */
HAL_FMPI2C_AddrCallback(FMPI2C_HandleTypeDef * hfmpi2c,uint8_t TransferDirection,uint16_t AddrMatchCode)4761 __weak void HAL_FMPI2C_AddrCallback(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t TransferDirection, uint16_t AddrMatchCode)
4762 {
4763   /* Prevent unused argument(s) compilation warning */
4764   UNUSED(hfmpi2c);
4765   UNUSED(TransferDirection);
4766   UNUSED(AddrMatchCode);
4767 
4768   /* NOTE : This function should not be modified, when the callback is needed,
4769             the HAL_FMPI2C_AddrCallback() could be implemented in the user file
4770    */
4771 }
4772 
4773 /**
4774   * @brief  Listen Complete callback.
4775   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
4776   *                the configuration information for the specified FMPI2C.
4777   * @retval None
4778   */
HAL_FMPI2C_ListenCpltCallback(FMPI2C_HandleTypeDef * hfmpi2c)4779 __weak void HAL_FMPI2C_ListenCpltCallback(FMPI2C_HandleTypeDef *hfmpi2c)
4780 {
4781   /* Prevent unused argument(s) compilation warning */
4782   UNUSED(hfmpi2c);
4783 
4784   /* NOTE : This function should not be modified, when the callback is needed,
4785             the HAL_FMPI2C_ListenCpltCallback() could be implemented in the user file
4786    */
4787 }
4788 
4789 /**
4790   * @brief  Memory Tx Transfer completed callback.
4791   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
4792   *                the configuration information for the specified FMPI2C.
4793   * @retval None
4794   */
HAL_FMPI2C_MemTxCpltCallback(FMPI2C_HandleTypeDef * hfmpi2c)4795 __weak void HAL_FMPI2C_MemTxCpltCallback(FMPI2C_HandleTypeDef *hfmpi2c)
4796 {
4797   /* Prevent unused argument(s) compilation warning */
4798   UNUSED(hfmpi2c);
4799 
4800   /* NOTE : This function should not be modified, when the callback is needed,
4801             the HAL_FMPI2C_MemTxCpltCallback could be implemented in the user file
4802    */
4803 }
4804 
4805 /**
4806   * @brief  Memory Rx Transfer completed callback.
4807   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
4808   *                the configuration information for the specified FMPI2C.
4809   * @retval None
4810   */
HAL_FMPI2C_MemRxCpltCallback(FMPI2C_HandleTypeDef * hfmpi2c)4811 __weak void HAL_FMPI2C_MemRxCpltCallback(FMPI2C_HandleTypeDef *hfmpi2c)
4812 {
4813   /* Prevent unused argument(s) compilation warning */
4814   UNUSED(hfmpi2c);
4815 
4816   /* NOTE : This function should not be modified, when the callback is needed,
4817             the HAL_FMPI2C_MemRxCpltCallback could be implemented in the user file
4818    */
4819 }
4820 
4821 /**
4822   * @brief  FMPI2C error callback.
4823   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
4824   *                the configuration information for the specified FMPI2C.
4825   * @retval None
4826   */
HAL_FMPI2C_ErrorCallback(FMPI2C_HandleTypeDef * hfmpi2c)4827 __weak void HAL_FMPI2C_ErrorCallback(FMPI2C_HandleTypeDef *hfmpi2c)
4828 {
4829   /* Prevent unused argument(s) compilation warning */
4830   UNUSED(hfmpi2c);
4831 
4832   /* NOTE : This function should not be modified, when the callback is needed,
4833             the HAL_FMPI2C_ErrorCallback could be implemented in the user file
4834    */
4835 }
4836 
4837 /**
4838   * @brief  FMPI2C abort callback.
4839   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
4840   *                the configuration information for the specified FMPI2C.
4841   * @retval None
4842   */
HAL_FMPI2C_AbortCpltCallback(FMPI2C_HandleTypeDef * hfmpi2c)4843 __weak void HAL_FMPI2C_AbortCpltCallback(FMPI2C_HandleTypeDef *hfmpi2c)
4844 {
4845   /* Prevent unused argument(s) compilation warning */
4846   UNUSED(hfmpi2c);
4847 
4848   /* NOTE : This function should not be modified, when the callback is needed,
4849             the HAL_FMPI2C_AbortCpltCallback could be implemented in the user file
4850    */
4851 }
4852 
4853 /**
4854   * @}
4855   */
4856 
4857 /** @defgroup FMPI2C_Exported_Functions_Group3 Peripheral State, Mode and Error functions
4858   *  @brief   Peripheral State, Mode and Error functions
4859   *
4860 @verbatim
4861  ===============================================================================
4862             ##### Peripheral State, Mode and Error functions #####
4863  ===============================================================================
4864     [..]
4865     This subsection permit to get in run-time the status of the peripheral
4866     and the data flow.
4867 
4868 @endverbatim
4869   * @{
4870   */
4871 
4872 /**
4873   * @brief  Return the FMPI2C handle state.
4874   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
4875   *                the configuration information for the specified FMPI2C.
4876   * @retval HAL state
4877   */
HAL_FMPI2C_GetState(const FMPI2C_HandleTypeDef * hfmpi2c)4878 HAL_FMPI2C_StateTypeDef HAL_FMPI2C_GetState(const FMPI2C_HandleTypeDef *hfmpi2c)
4879 {
4880   /* Return FMPI2C handle state */
4881   return hfmpi2c->State;
4882 }
4883 
4884 /**
4885   * @brief  Returns the FMPI2C Master, Slave, Memory or no mode.
4886   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
4887   *         the configuration information for FMPI2C module
4888   * @retval HAL mode
4889   */
HAL_FMPI2C_GetMode(const FMPI2C_HandleTypeDef * hfmpi2c)4890 HAL_FMPI2C_ModeTypeDef HAL_FMPI2C_GetMode(const FMPI2C_HandleTypeDef *hfmpi2c)
4891 {
4892   return hfmpi2c->Mode;
4893 }
4894 
4895 /**
4896   * @brief  Return the FMPI2C error code.
4897   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
4898   *              the configuration information for the specified FMPI2C.
4899   * @retval FMPI2C Error Code
4900   */
HAL_FMPI2C_GetError(const FMPI2C_HandleTypeDef * hfmpi2c)4901 uint32_t HAL_FMPI2C_GetError(const FMPI2C_HandleTypeDef *hfmpi2c)
4902 {
4903   return hfmpi2c->ErrorCode;
4904 }
4905 
4906 /**
4907   * @}
4908   */
4909 
4910 /**
4911   * @}
4912   */
4913 
4914 /** @addtogroup FMPI2C_Private_Functions
4915   * @{
4916   */
4917 
4918 /**
4919   * @brief  Interrupt Sub-Routine which handle the Interrupt Flags Master Mode with Interrupt.
4920   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
4921   *                the configuration information for the specified FMPI2C.
4922   * @param  ITFlags Interrupt flags to handle.
4923   * @param  ITSources Interrupt sources enabled.
4924   * @retval HAL status
4925   */
FMPI2C_Master_ISR_IT(struct __FMPI2C_HandleTypeDef * hfmpi2c,uint32_t ITFlags,uint32_t ITSources)4926 static HAL_StatusTypeDef FMPI2C_Master_ISR_IT(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags,
4927                                               uint32_t ITSources)
4928 {
4929   uint16_t devaddress;
4930   uint32_t tmpITFlags = ITFlags;
4931 
4932   /* Process Locked */
4933   __HAL_LOCK(hfmpi2c);
4934 
4935   if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_AF) != RESET) && \
4936       (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_NACKI) != RESET))
4937   {
4938     /* Clear NACK Flag */
4939     __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF);
4940 
4941     /* Set corresponding Error Code */
4942     /* No need to generate STOP, it is automatically done */
4943     /* Error callback will be send during stop flag treatment */
4944     hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_AF;
4945 
4946     /* Flush TX register */
4947     FMPI2C_Flush_TXDR(hfmpi2c);
4948   }
4949   else if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_RXNE) != RESET) && \
4950            (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_RXI) != RESET))
4951   {
4952     /* Remove RXNE flag on temporary variable as read done */
4953     tmpITFlags &= ~FMPI2C_FLAG_RXNE;
4954 
4955     /* Read data from RXDR */
4956     *hfmpi2c->pBuffPtr = (uint8_t)hfmpi2c->Instance->RXDR;
4957 
4958     /* Increment Buffer pointer */
4959     hfmpi2c->pBuffPtr++;
4960 
4961     hfmpi2c->XferSize--;
4962     hfmpi2c->XferCount--;
4963   }
4964   else if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_TC) == RESET) && \
4965            ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_TXIS) != RESET) && \
4966             (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_TXI) != RESET)))
4967   {
4968     /* Write data to TXDR */
4969     if (hfmpi2c->XferCount != 0U)
4970     {
4971       /* Write data to TXDR */
4972       hfmpi2c->Instance->TXDR = *hfmpi2c->pBuffPtr;
4973 
4974       /* Increment Buffer pointer */
4975       hfmpi2c->pBuffPtr++;
4976 
4977       hfmpi2c->XferSize--;
4978       hfmpi2c->XferCount--;
4979     }
4980   }
4981   else if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_TCR) != RESET) && \
4982            (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_TCI) != RESET))
4983   {
4984     if ((hfmpi2c->XferCount != 0U) && (hfmpi2c->XferSize == 0U))
4985     {
4986       devaddress = (uint16_t)(hfmpi2c->Instance->CR2 & FMPI2C_CR2_SADD);
4987 
4988       if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
4989       {
4990         /* Errata workaround 170323 */
4991         if (FMPI2C_GET_DIR(hfmpi2c) == FMPI2C_DIRECTION_RECEIVE)
4992         {
4993           hfmpi2c->XferSize = 1U;
4994         }
4995         else
4996         {
4997           hfmpi2c->XferSize = MAX_NBYTE_SIZE;
4998         }
4999         FMPI2C_TransferConfig(hfmpi2c, devaddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_RELOAD_MODE, FMPI2C_NO_STARTSTOP);
5000       }
5001       else
5002       {
5003         hfmpi2c->XferSize = hfmpi2c->XferCount;
5004         if (hfmpi2c->XferOptions != FMPI2C_NO_OPTION_FRAME)
5005         {
5006           FMPI2C_TransferConfig(hfmpi2c, devaddress, (uint8_t)hfmpi2c->XferSize,
5007                                 hfmpi2c->XferOptions, FMPI2C_NO_STARTSTOP);
5008         }
5009         else
5010         {
5011           FMPI2C_TransferConfig(hfmpi2c, devaddress, (uint8_t)hfmpi2c->XferSize,
5012                                 FMPI2C_AUTOEND_MODE, FMPI2C_NO_STARTSTOP);
5013         }
5014       }
5015     }
5016     else
5017     {
5018       /* Call TxCpltCallback() if no stop mode is set */
5019       if (FMPI2C_GET_STOP_MODE(hfmpi2c) != FMPI2C_AUTOEND_MODE)
5020       {
5021         /* Call FMPI2C Master Sequential complete process */
5022         FMPI2C_ITMasterSeqCplt(hfmpi2c);
5023       }
5024       else
5025       {
5026         /* Wrong size Status regarding TCR flag event */
5027         /* Call the corresponding callback to inform upper layer of End of Transfer */
5028         FMPI2C_ITError(hfmpi2c, HAL_FMPI2C_ERROR_SIZE);
5029       }
5030     }
5031   }
5032   else if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_TC) != RESET) && \
5033            (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_TCI) != RESET))
5034   {
5035     if (hfmpi2c->XferCount == 0U)
5036     {
5037       if (FMPI2C_GET_STOP_MODE(hfmpi2c) != FMPI2C_AUTOEND_MODE)
5038       {
5039         /* Generate a stop condition in case of no transfer option */
5040         if (hfmpi2c->XferOptions == FMPI2C_NO_OPTION_FRAME)
5041         {
5042           /* Generate Stop */
5043           hfmpi2c->Instance->CR2 |= FMPI2C_CR2_STOP;
5044         }
5045         else
5046         {
5047           /* Call FMPI2C Master Sequential complete process */
5048           FMPI2C_ITMasterSeqCplt(hfmpi2c);
5049         }
5050       }
5051     }
5052     else
5053     {
5054       /* Wrong size Status regarding TC flag event */
5055       /* Call the corresponding callback to inform upper layer of End of Transfer */
5056       FMPI2C_ITError(hfmpi2c, HAL_FMPI2C_ERROR_SIZE);
5057     }
5058   }
5059   else
5060   {
5061     /* Nothing to do */
5062   }
5063 
5064   if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_STOPF) != RESET) && \
5065       (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_STOPI) != RESET))
5066   {
5067     /* Call FMPI2C Master complete process */
5068     FMPI2C_ITMasterCplt(hfmpi2c, tmpITFlags);
5069   }
5070 
5071   /* Process Unlocked */
5072   __HAL_UNLOCK(hfmpi2c);
5073 
5074   return HAL_OK;
5075 }
5076 
5077 /**
5078   * @brief  Interrupt Sub-Routine which handle the Interrupt Flags Memory Mode with Interrupt.
5079   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
5080   *                the configuration information for the specified FMPI2C.
5081   * @param  ITFlags Interrupt flags to handle.
5082   * @param  ITSources Interrupt sources enabled.
5083   * @retval HAL status
5084   */
FMPI2C_Mem_ISR_IT(struct __FMPI2C_HandleTypeDef * hfmpi2c,uint32_t ITFlags,uint32_t ITSources)5085 static HAL_StatusTypeDef FMPI2C_Mem_ISR_IT(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags,
5086                                            uint32_t ITSources)
5087 {
5088   uint32_t direction = FMPI2C_GENERATE_START_WRITE;
5089   uint32_t tmpITFlags = ITFlags;
5090 
5091   /* Process Locked */
5092   __HAL_LOCK(hfmpi2c);
5093 
5094   if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_AF) != RESET) && \
5095       (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_NACKI) != RESET))
5096   {
5097     /* Clear NACK Flag */
5098     __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF);
5099 
5100     /* Set corresponding Error Code */
5101     /* No need to generate STOP, it is automatically done */
5102     /* Error callback will be send during stop flag treatment */
5103     hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_AF;
5104 
5105     /* Flush TX register */
5106     FMPI2C_Flush_TXDR(hfmpi2c);
5107   }
5108   else if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_RXNE) != RESET) && \
5109            (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_RXI) != RESET))
5110   {
5111     /* Remove RXNE flag on temporary variable as read done */
5112     tmpITFlags &= ~FMPI2C_FLAG_RXNE;
5113 
5114     /* Read data from RXDR */
5115     *hfmpi2c->pBuffPtr = (uint8_t)hfmpi2c->Instance->RXDR;
5116 
5117     /* Increment Buffer pointer */
5118     hfmpi2c->pBuffPtr++;
5119 
5120     hfmpi2c->XferSize--;
5121     hfmpi2c->XferCount--;
5122   }
5123   else if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_TXIS) != RESET) && \
5124            (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_TXI) != RESET))
5125   {
5126     if (hfmpi2c->Memaddress == 0xFFFFFFFFU)
5127     {
5128       /* Write data to TXDR */
5129       hfmpi2c->Instance->TXDR = *hfmpi2c->pBuffPtr;
5130 
5131       /* Increment Buffer pointer */
5132       hfmpi2c->pBuffPtr++;
5133 
5134       hfmpi2c->XferSize--;
5135       hfmpi2c->XferCount--;
5136     }
5137     else
5138     {
5139       /* Write LSB part of Memory Address */
5140       hfmpi2c->Instance->TXDR = hfmpi2c->Memaddress;
5141 
5142       /* Reset Memaddress content */
5143       hfmpi2c->Memaddress = 0xFFFFFFFFU;
5144     }
5145   }
5146   else if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_TCR) != RESET) && \
5147            (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_TCI) != RESET))
5148   {
5149     if ((hfmpi2c->XferCount != 0U) && (hfmpi2c->XferSize == 0U))
5150     {
5151       if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
5152       {
5153         /* Errata workaround 170323 */
5154         if (FMPI2C_GET_DIR(hfmpi2c) == FMPI2C_DIRECTION_RECEIVE)
5155         {
5156           hfmpi2c->XferSize = 1U;
5157         }
5158         else
5159         {
5160           hfmpi2c->XferSize = MAX_NBYTE_SIZE;
5161         }
5162         FMPI2C_TransferConfig(hfmpi2c, (uint16_t)hfmpi2c->Devaddress, (uint8_t)hfmpi2c->XferSize,
5163                               FMPI2C_RELOAD_MODE, FMPI2C_NO_STARTSTOP);
5164       }
5165       else
5166       {
5167         hfmpi2c->XferSize = hfmpi2c->XferCount;
5168         FMPI2C_TransferConfig(hfmpi2c, (uint16_t)hfmpi2c->Devaddress, (uint8_t)hfmpi2c->XferSize,
5169                               FMPI2C_AUTOEND_MODE, FMPI2C_NO_STARTSTOP);
5170       }
5171     }
5172     else
5173     {
5174       /* Wrong size Status regarding TCR flag event */
5175       /* Call the corresponding callback to inform upper layer of End of Transfer */
5176       FMPI2C_ITError(hfmpi2c, HAL_FMPI2C_ERROR_SIZE);
5177     }
5178   }
5179   else if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_TC) != RESET) && \
5180            (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_TCI) != RESET))
5181   {
5182     /* Disable Interrupt related to address step */
5183     FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT);
5184 
5185     /* Enable ERR, TC, STOP, NACK and RXI interrupts */
5186     FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_RX_IT);
5187 
5188     if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX)
5189     {
5190       direction = FMPI2C_GENERATE_START_READ;
5191     }
5192 
5193     if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
5194     {
5195       /* Errata workaround 170323 */
5196       if (FMPI2C_GET_DIR(hfmpi2c) == FMPI2C_DIRECTION_RECEIVE)
5197       {
5198         hfmpi2c->XferSize = 1U;
5199       }
5200       else
5201       {
5202         hfmpi2c->XferSize = MAX_NBYTE_SIZE;
5203       }
5204 
5205       /* Set NBYTES to write and reload if hfmpi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
5206       FMPI2C_TransferConfig(hfmpi2c, (uint16_t)hfmpi2c->Devaddress, (uint8_t)hfmpi2c->XferSize,
5207                             FMPI2C_RELOAD_MODE, direction);
5208     }
5209     else
5210     {
5211       hfmpi2c->XferSize = hfmpi2c->XferCount;
5212 
5213       /* Set NBYTES to write and generate RESTART */
5214       FMPI2C_TransferConfig(hfmpi2c, (uint16_t)hfmpi2c->Devaddress, (uint8_t)hfmpi2c->XferSize,
5215                             FMPI2C_AUTOEND_MODE, direction);
5216     }
5217   }
5218   else
5219   {
5220     /* Nothing to do */
5221   }
5222 
5223   if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_STOPF) != RESET) && \
5224       (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_STOPI) != RESET))
5225   {
5226     /* Call FMPI2C Master complete process */
5227     FMPI2C_ITMasterCplt(hfmpi2c, tmpITFlags);
5228   }
5229 
5230   /* Process Unlocked */
5231   __HAL_UNLOCK(hfmpi2c);
5232 
5233   return HAL_OK;
5234 }
5235 
5236 /**
5237   * @brief  Interrupt Sub-Routine which handle the Interrupt Flags Slave Mode with Interrupt.
5238   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
5239   *                the configuration information for the specified FMPI2C.
5240   * @param  ITFlags Interrupt flags to handle.
5241   * @param  ITSources Interrupt sources enabled.
5242   * @retval HAL status
5243   */
FMPI2C_Slave_ISR_IT(struct __FMPI2C_HandleTypeDef * hfmpi2c,uint32_t ITFlags,uint32_t ITSources)5244 static HAL_StatusTypeDef FMPI2C_Slave_ISR_IT(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags,
5245                                              uint32_t ITSources)
5246 {
5247   uint32_t tmpoptions = hfmpi2c->XferOptions;
5248   uint32_t tmpITFlags = ITFlags;
5249 
5250   /* Process locked */
5251   __HAL_LOCK(hfmpi2c);
5252 
5253   /* Check if STOPF is set */
5254   if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_STOPF) != RESET) && \
5255       (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_STOPI) != RESET))
5256   {
5257     /* Call FMPI2C Slave complete process */
5258     FMPI2C_ITSlaveCplt(hfmpi2c, tmpITFlags);
5259   }
5260   else if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_AF) != RESET) && \
5261            (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_NACKI) != RESET))
5262   {
5263     /* Check that FMPI2C transfer finished */
5264     /* if yes, normal use case, a NACK is sent by the MASTER when Transfer is finished */
5265     /* Mean XferCount == 0*/
5266     /* So clear Flag NACKF only */
5267     if (hfmpi2c->XferCount == 0U)
5268     {
5269       if ((hfmpi2c->State == HAL_FMPI2C_STATE_LISTEN) && (tmpoptions == FMPI2C_FIRST_AND_LAST_FRAME))
5270         /* Same action must be done for (tmpoptions == FMPI2C_LAST_FRAME) which removed for
5271            Warning[Pa134]: left and right operands are identical */
5272       {
5273         /* Call FMPI2C Listen complete process */
5274         FMPI2C_ITListenCplt(hfmpi2c, tmpITFlags);
5275       }
5276       else if ((hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_TX_LISTEN) && (tmpoptions != FMPI2C_NO_OPTION_FRAME))
5277       {
5278         /* Clear NACK Flag */
5279         __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF);
5280 
5281         /* Flush TX register */
5282         FMPI2C_Flush_TXDR(hfmpi2c);
5283 
5284         /* Last Byte is Transmitted */
5285         /* Call FMPI2C Slave Sequential complete process */
5286         FMPI2C_ITSlaveSeqCplt(hfmpi2c);
5287       }
5288       else
5289       {
5290         /* Clear NACK Flag */
5291         __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF);
5292       }
5293     }
5294     else
5295     {
5296       /* if no, error use case, a Non-Acknowledge of last Data is generated by the MASTER*/
5297       /* Clear NACK Flag */
5298       __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF);
5299 
5300       /* Set ErrorCode corresponding to a Non-Acknowledge */
5301       hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_AF;
5302 
5303       if ((tmpoptions == FMPI2C_FIRST_FRAME) || (tmpoptions == FMPI2C_NEXT_FRAME))
5304       {
5305         /* Call the corresponding callback to inform upper layer of End of Transfer */
5306         FMPI2C_ITError(hfmpi2c, hfmpi2c->ErrorCode);
5307       }
5308     }
5309   }
5310   else if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_RXNE) != RESET) && \
5311            (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_RXI) != RESET))
5312   {
5313     if (hfmpi2c->XferCount > 0U)
5314     {
5315       /* Read data from RXDR */
5316       *hfmpi2c->pBuffPtr = (uint8_t)hfmpi2c->Instance->RXDR;
5317 
5318       /* Increment Buffer pointer */
5319       hfmpi2c->pBuffPtr++;
5320 
5321       hfmpi2c->XferSize--;
5322       hfmpi2c->XferCount--;
5323     }
5324 
5325     if ((hfmpi2c->XferCount == 0U) && \
5326         (tmpoptions != FMPI2C_NO_OPTION_FRAME))
5327     {
5328       /* Call FMPI2C Slave Sequential complete process */
5329       FMPI2C_ITSlaveSeqCplt(hfmpi2c);
5330     }
5331   }
5332   else if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_ADDR) != RESET) && \
5333            (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_ADDRI) != RESET))
5334   {
5335     FMPI2C_ITAddrCplt(hfmpi2c, tmpITFlags);
5336   }
5337   else if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_TXIS) != RESET) && \
5338            (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_TXI) != RESET))
5339   {
5340     /* Write data to TXDR only if XferCount not reach "0" */
5341     /* A TXIS flag can be set, during STOP treatment      */
5342     /* Check if all Data have already been sent */
5343     /* If it is the case, this last write in TXDR is not sent, correspond to a dummy TXIS event */
5344     if (hfmpi2c->XferCount > 0U)
5345     {
5346       /* Write data to TXDR */
5347       hfmpi2c->Instance->TXDR = *hfmpi2c->pBuffPtr;
5348 
5349       /* Increment Buffer pointer */
5350       hfmpi2c->pBuffPtr++;
5351 
5352       hfmpi2c->XferCount--;
5353       hfmpi2c->XferSize--;
5354     }
5355     else
5356     {
5357       if ((tmpoptions == FMPI2C_NEXT_FRAME) || (tmpoptions == FMPI2C_FIRST_FRAME))
5358       {
5359         /* Last Byte is Transmitted */
5360         /* Call FMPI2C Slave Sequential complete process */
5361         FMPI2C_ITSlaveSeqCplt(hfmpi2c);
5362       }
5363     }
5364   }
5365   else
5366   {
5367     /* Nothing to do */
5368   }
5369 
5370   /* Process Unlocked */
5371   __HAL_UNLOCK(hfmpi2c);
5372 
5373   return HAL_OK;
5374 }
5375 
5376 /**
5377   * @brief  Interrupt Sub-Routine which handle the Interrupt Flags Master Mode with DMA.
5378   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
5379   *                the configuration information for the specified FMPI2C.
5380   * @param  ITFlags Interrupt flags to handle.
5381   * @param  ITSources Interrupt sources enabled.
5382   * @retval HAL status
5383   */
FMPI2C_Master_ISR_DMA(struct __FMPI2C_HandleTypeDef * hfmpi2c,uint32_t ITFlags,uint32_t ITSources)5384 static HAL_StatusTypeDef FMPI2C_Master_ISR_DMA(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags,
5385                                                uint32_t ITSources)
5386 {
5387   uint16_t devaddress;
5388   uint32_t xfermode;
5389 
5390   /* Process Locked */
5391   __HAL_LOCK(hfmpi2c);
5392 
5393   if ((FMPI2C_CHECK_FLAG(ITFlags, FMPI2C_FLAG_AF) != RESET) && \
5394       (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_NACKI) != RESET))
5395   {
5396     /* Clear NACK Flag */
5397     __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF);
5398 
5399     /* Set corresponding Error Code */
5400     hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_AF;
5401 
5402     /* No need to generate STOP, it is automatically done */
5403     /* But enable STOP interrupt, to treat it */
5404     /* Error callback will be send during stop flag treatment */
5405     FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_CPLT_IT);
5406 
5407     /* Flush TX register */
5408     FMPI2C_Flush_TXDR(hfmpi2c);
5409   }
5410   else if ((FMPI2C_CHECK_FLAG(ITFlags, FMPI2C_FLAG_TCR) != RESET) && \
5411            (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_TCI) != RESET))
5412   {
5413     /* Disable TC interrupt */
5414     __HAL_FMPI2C_DISABLE_IT(hfmpi2c, FMPI2C_IT_TCI);
5415 
5416     if (hfmpi2c->XferCount != 0U)
5417     {
5418       /* Recover Slave address */
5419       devaddress = (uint16_t)(hfmpi2c->Instance->CR2 & FMPI2C_CR2_SADD);
5420 
5421       /* Prepare the new XferSize to transfer */
5422       if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
5423       {
5424         /* Errata workaround 170323 */
5425         if (FMPI2C_GET_DIR(hfmpi2c) == FMPI2C_DIRECTION_RECEIVE)
5426         {
5427           hfmpi2c->XferSize = 1U;
5428         }
5429         else
5430         {
5431           hfmpi2c->XferSize = MAX_NBYTE_SIZE;
5432         }
5433         xfermode = FMPI2C_RELOAD_MODE;
5434       }
5435       else
5436       {
5437         hfmpi2c->XferSize = hfmpi2c->XferCount;
5438         if (hfmpi2c->XferOptions != FMPI2C_NO_OPTION_FRAME)
5439         {
5440           xfermode = hfmpi2c->XferOptions;
5441         }
5442         else
5443         {
5444           xfermode = FMPI2C_AUTOEND_MODE;
5445         }
5446       }
5447 
5448       /* Set the new XferSize in Nbytes register */
5449       FMPI2C_TransferConfig(hfmpi2c, devaddress, (uint8_t)hfmpi2c->XferSize, xfermode, FMPI2C_NO_STARTSTOP);
5450 
5451       /* Update XferCount value */
5452       hfmpi2c->XferCount -= hfmpi2c->XferSize;
5453 
5454       /* Enable DMA Request */
5455       if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX)
5456       {
5457         hfmpi2c->Instance->CR1 |= FMPI2C_CR1_RXDMAEN;
5458       }
5459       else
5460       {
5461         hfmpi2c->Instance->CR1 |= FMPI2C_CR1_TXDMAEN;
5462       }
5463     }
5464     else
5465     {
5466       /* Call TxCpltCallback() if no stop mode is set */
5467       if (FMPI2C_GET_STOP_MODE(hfmpi2c) != FMPI2C_AUTOEND_MODE)
5468       {
5469         /* Call FMPI2C Master Sequential complete process */
5470         FMPI2C_ITMasterSeqCplt(hfmpi2c);
5471       }
5472       else
5473       {
5474         /* Wrong size Status regarding TCR flag event */
5475         /* Call the corresponding callback to inform upper layer of End of Transfer */
5476         FMPI2C_ITError(hfmpi2c, HAL_FMPI2C_ERROR_SIZE);
5477       }
5478     }
5479   }
5480   else if ((FMPI2C_CHECK_FLAG(ITFlags, FMPI2C_FLAG_TC) != RESET) && \
5481            (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_TCI) != RESET))
5482   {
5483     if (hfmpi2c->XferCount == 0U)
5484     {
5485       if (FMPI2C_GET_STOP_MODE(hfmpi2c) != FMPI2C_AUTOEND_MODE)
5486       {
5487         /* Generate a stop condition in case of no transfer option */
5488         if (hfmpi2c->XferOptions == FMPI2C_NO_OPTION_FRAME)
5489         {
5490           /* Generate Stop */
5491           hfmpi2c->Instance->CR2 |= FMPI2C_CR2_STOP;
5492         }
5493         else
5494         {
5495           /* Call FMPI2C Master Sequential complete process */
5496           FMPI2C_ITMasterSeqCplt(hfmpi2c);
5497         }
5498       }
5499     }
5500     else
5501     {
5502       /* Wrong size Status regarding TC flag event */
5503       /* Call the corresponding callback to inform upper layer of End of Transfer */
5504       FMPI2C_ITError(hfmpi2c, HAL_FMPI2C_ERROR_SIZE);
5505     }
5506   }
5507   else if ((FMPI2C_CHECK_FLAG(ITFlags, FMPI2C_FLAG_STOPF) != RESET) && \
5508            (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_STOPI) != RESET))
5509   {
5510     /* Call FMPI2C Master complete process */
5511     FMPI2C_ITMasterCplt(hfmpi2c, ITFlags);
5512   }
5513   else
5514   {
5515     /* Nothing to do */
5516   }
5517 
5518   /* Process Unlocked */
5519   __HAL_UNLOCK(hfmpi2c);
5520 
5521   return HAL_OK;
5522 }
5523 
5524 /**
5525   * @brief  Interrupt Sub-Routine which handle the Interrupt Flags Memory Mode with DMA.
5526   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
5527   *                the configuration information for the specified FMPI2C.
5528   * @param  ITFlags Interrupt flags to handle.
5529   * @param  ITSources Interrupt sources enabled.
5530   * @retval HAL status
5531   */
FMPI2C_Mem_ISR_DMA(struct __FMPI2C_HandleTypeDef * hfmpi2c,uint32_t ITFlags,uint32_t ITSources)5532 static HAL_StatusTypeDef FMPI2C_Mem_ISR_DMA(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags,
5533                                             uint32_t ITSources)
5534 {
5535   uint32_t direction = FMPI2C_GENERATE_START_WRITE;
5536 
5537   /* Process Locked */
5538   __HAL_LOCK(hfmpi2c);
5539 
5540   if ((FMPI2C_CHECK_FLAG(ITFlags, FMPI2C_FLAG_AF) != RESET) && \
5541       (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_NACKI) != RESET))
5542   {
5543     /* Clear NACK Flag */
5544     __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF);
5545 
5546     /* Set corresponding Error Code */
5547     hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_AF;
5548 
5549     /* No need to generate STOP, it is automatically done */
5550     /* But enable STOP interrupt, to treat it */
5551     /* Error callback will be send during stop flag treatment */
5552     FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_CPLT_IT);
5553 
5554     /* Flush TX register */
5555     FMPI2C_Flush_TXDR(hfmpi2c);
5556   }
5557   else if ((FMPI2C_CHECK_FLAG(ITFlags, FMPI2C_FLAG_TXIS) != RESET) && \
5558            (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_TXI) != RESET))
5559   {
5560     /* Write LSB part of Memory Address */
5561     hfmpi2c->Instance->TXDR = hfmpi2c->Memaddress;
5562 
5563     /* Reset Memaddress content */
5564     hfmpi2c->Memaddress = 0xFFFFFFFFU;
5565   }
5566   else if ((FMPI2C_CHECK_FLAG(ITFlags, FMPI2C_FLAG_TCR) != RESET) && \
5567            (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_TCI) != RESET))
5568   {
5569     /* Disable Interrupt related to address step */
5570     FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT);
5571 
5572     /* Enable only Error interrupt */
5573     FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_ERROR_IT);
5574 
5575     if (hfmpi2c->XferCount != 0U)
5576     {
5577       /* Prepare the new XferSize to transfer */
5578       if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
5579       {
5580         /* Errata workaround 170323 */
5581         if (FMPI2C_GET_DIR(hfmpi2c) == FMPI2C_DIRECTION_RECEIVE)
5582         {
5583           hfmpi2c->XferSize = 1U;
5584         }
5585         else
5586         {
5587           hfmpi2c->XferSize = MAX_NBYTE_SIZE;
5588         }
5589         FMPI2C_TransferConfig(hfmpi2c, (uint16_t)hfmpi2c->Devaddress, (uint8_t)hfmpi2c->XferSize,
5590                               FMPI2C_RELOAD_MODE, FMPI2C_NO_STARTSTOP);
5591       }
5592       else
5593       {
5594         hfmpi2c->XferSize = hfmpi2c->XferCount;
5595         FMPI2C_TransferConfig(hfmpi2c, (uint16_t)hfmpi2c->Devaddress, (uint8_t)hfmpi2c->XferSize,
5596                               FMPI2C_AUTOEND_MODE, FMPI2C_NO_STARTSTOP);
5597       }
5598 
5599       /* Update XferCount value */
5600       hfmpi2c->XferCount -= hfmpi2c->XferSize;
5601 
5602       /* Enable DMA Request */
5603       if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX)
5604       {
5605         hfmpi2c->Instance->CR1 |= FMPI2C_CR1_RXDMAEN;
5606       }
5607       else
5608       {
5609         hfmpi2c->Instance->CR1 |= FMPI2C_CR1_TXDMAEN;
5610       }
5611     }
5612     else
5613     {
5614       /* Wrong size Status regarding TCR flag event */
5615       /* Call the corresponding callback to inform upper layer of End of Transfer */
5616       FMPI2C_ITError(hfmpi2c, HAL_FMPI2C_ERROR_SIZE);
5617     }
5618   }
5619   else if ((FMPI2C_CHECK_FLAG(ITFlags, FMPI2C_FLAG_TC) != RESET) && \
5620            (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_TCI) != RESET))
5621   {
5622     /* Disable Interrupt related to address step */
5623     FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT);
5624 
5625     /* Enable only Error and NACK interrupt for data transfer */
5626     FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_ERROR_IT);
5627 
5628     if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX)
5629     {
5630       direction = FMPI2C_GENERATE_START_READ;
5631     }
5632 
5633     if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
5634     {
5635       /* Errata workaround 170323 */
5636       if (FMPI2C_GET_DIR(hfmpi2c) == FMPI2C_DIRECTION_RECEIVE)
5637       {
5638         hfmpi2c->XferSize = 1U;
5639       }
5640       else
5641       {
5642         hfmpi2c->XferSize = MAX_NBYTE_SIZE;
5643       }
5644 
5645       /* Set NBYTES to write and reload if hfmpi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
5646       FMPI2C_TransferConfig(hfmpi2c, (uint16_t)hfmpi2c->Devaddress, (uint8_t)hfmpi2c->XferSize,
5647                             FMPI2C_RELOAD_MODE, direction);
5648     }
5649     else
5650     {
5651       hfmpi2c->XferSize = hfmpi2c->XferCount;
5652 
5653       /* Set NBYTES to write and generate RESTART */
5654       FMPI2C_TransferConfig(hfmpi2c, (uint16_t)hfmpi2c->Devaddress, (uint8_t)hfmpi2c->XferSize,
5655                             FMPI2C_AUTOEND_MODE, direction);
5656     }
5657 
5658     /* Update XferCount value */
5659     hfmpi2c->XferCount -= hfmpi2c->XferSize;
5660 
5661     /* Enable DMA Request */
5662     if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX)
5663     {
5664       hfmpi2c->Instance->CR1 |= FMPI2C_CR1_RXDMAEN;
5665     }
5666     else
5667     {
5668       hfmpi2c->Instance->CR1 |= FMPI2C_CR1_TXDMAEN;
5669     }
5670   }
5671   else if ((FMPI2C_CHECK_FLAG(ITFlags, FMPI2C_FLAG_STOPF) != RESET) && \
5672            (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_STOPI) != RESET))
5673   {
5674     /* Call FMPI2C Master complete process */
5675     FMPI2C_ITMasterCplt(hfmpi2c, ITFlags);
5676   }
5677   else
5678   {
5679     /* Nothing to do */
5680   }
5681 
5682   /* Process Unlocked */
5683   __HAL_UNLOCK(hfmpi2c);
5684 
5685   return HAL_OK;
5686 }
5687 
5688 /**
5689   * @brief  Interrupt Sub-Routine which handle the Interrupt Flags Slave Mode with DMA.
5690   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
5691   *                the configuration information for the specified FMPI2C.
5692   * @param  ITFlags Interrupt flags to handle.
5693   * @param  ITSources Interrupt sources enabled.
5694   * @retval HAL status
5695   */
FMPI2C_Slave_ISR_DMA(struct __FMPI2C_HandleTypeDef * hfmpi2c,uint32_t ITFlags,uint32_t ITSources)5696 static HAL_StatusTypeDef FMPI2C_Slave_ISR_DMA(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags,
5697                                               uint32_t ITSources)
5698 {
5699   uint32_t tmpoptions = hfmpi2c->XferOptions;
5700   uint32_t treatdmanack = 0U;
5701   HAL_FMPI2C_StateTypeDef tmpstate;
5702 
5703   /* Process locked */
5704   __HAL_LOCK(hfmpi2c);
5705 
5706   /* Check if STOPF is set */
5707   if ((FMPI2C_CHECK_FLAG(ITFlags, FMPI2C_FLAG_STOPF) != RESET) && \
5708       (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_STOPI) != RESET))
5709   {
5710     /* Call FMPI2C Slave complete process */
5711     FMPI2C_ITSlaveCplt(hfmpi2c, ITFlags);
5712   }
5713   else if ((FMPI2C_CHECK_FLAG(ITFlags, FMPI2C_FLAG_AF) != RESET) && \
5714            (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_NACKI) != RESET))
5715   {
5716     /* Check that FMPI2C transfer finished */
5717     /* if yes, normal use case, a NACK is sent by the MASTER when Transfer is finished */
5718     /* Mean XferCount == 0 */
5719     /* So clear Flag NACKF only */
5720     if ((FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_CR1_TXDMAEN) != RESET) ||
5721         (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_CR1_RXDMAEN) != RESET))
5722     {
5723       /* Split check of hdmarx, for MISRA compliance */
5724       if (hfmpi2c->hdmarx != NULL)
5725       {
5726         if (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_CR1_RXDMAEN) != RESET)
5727         {
5728           if (FMPI2C_GET_DMA_REMAIN_DATA(hfmpi2c->hdmarx) == 0U)
5729           {
5730             treatdmanack = 1U;
5731           }
5732         }
5733       }
5734 
5735       /* Split check of hdmatx, for MISRA compliance  */
5736       if (hfmpi2c->hdmatx != NULL)
5737       {
5738         if (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_CR1_TXDMAEN) != RESET)
5739         {
5740           if (FMPI2C_GET_DMA_REMAIN_DATA(hfmpi2c->hdmatx) == 0U)
5741           {
5742             treatdmanack = 1U;
5743           }
5744         }
5745       }
5746 
5747       if (treatdmanack == 1U)
5748       {
5749         if ((hfmpi2c->State == HAL_FMPI2C_STATE_LISTEN) && (tmpoptions == FMPI2C_FIRST_AND_LAST_FRAME))
5750           /* Same action must be done for (tmpoptions == FMPI2C_LAST_FRAME) which removed for
5751              Warning[Pa134]: left and right operands are identical */
5752         {
5753           /* Call FMPI2C Listen complete process */
5754           FMPI2C_ITListenCplt(hfmpi2c, ITFlags);
5755         }
5756         else if ((hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_TX_LISTEN) && (tmpoptions != FMPI2C_NO_OPTION_FRAME))
5757         {
5758           /* Clear NACK Flag */
5759           __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF);
5760 
5761           /* Flush TX register */
5762           FMPI2C_Flush_TXDR(hfmpi2c);
5763 
5764           /* Last Byte is Transmitted */
5765           /* Call FMPI2C Slave Sequential complete process */
5766           FMPI2C_ITSlaveSeqCplt(hfmpi2c);
5767         }
5768         else
5769         {
5770           /* Clear NACK Flag */
5771           __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF);
5772         }
5773       }
5774       else
5775       {
5776         /* if no, error use case, a Non-Acknowledge of last Data is generated by the MASTER*/
5777         /* Clear NACK Flag */
5778         __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF);
5779 
5780         /* Set ErrorCode corresponding to a Non-Acknowledge */
5781         hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_AF;
5782 
5783         /* Store current hfmpi2c->State, solve MISRA2012-Rule-13.5 */
5784         tmpstate = hfmpi2c->State;
5785 
5786         if ((tmpoptions == FMPI2C_FIRST_FRAME) || (tmpoptions == FMPI2C_NEXT_FRAME))
5787         {
5788           if ((tmpstate == HAL_FMPI2C_STATE_BUSY_TX) || (tmpstate == HAL_FMPI2C_STATE_BUSY_TX_LISTEN))
5789           {
5790             hfmpi2c->PreviousState = FMPI2C_STATE_SLAVE_BUSY_TX;
5791           }
5792           else if ((tmpstate == HAL_FMPI2C_STATE_BUSY_RX) || (tmpstate == HAL_FMPI2C_STATE_BUSY_RX_LISTEN))
5793           {
5794             hfmpi2c->PreviousState = FMPI2C_STATE_SLAVE_BUSY_RX;
5795           }
5796           else
5797           {
5798             /* Do nothing */
5799           }
5800 
5801           /* Call the corresponding callback to inform upper layer of End of Transfer */
5802           FMPI2C_ITError(hfmpi2c, hfmpi2c->ErrorCode);
5803         }
5804       }
5805     }
5806     else
5807     {
5808       /* Only Clear NACK Flag, no DMA treatment is pending */
5809       __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF);
5810     }
5811   }
5812   else if ((FMPI2C_CHECK_FLAG(ITFlags, FMPI2C_FLAG_ADDR) != RESET) && \
5813            (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_ADDRI) != RESET))
5814   {
5815     FMPI2C_ITAddrCplt(hfmpi2c, ITFlags);
5816   }
5817   else
5818   {
5819     /* Nothing to do */
5820   }
5821 
5822   /* Process Unlocked */
5823   __HAL_UNLOCK(hfmpi2c);
5824 
5825   return HAL_OK;
5826 }
5827 
5828 /**
5829   * @brief  Master sends target device address followed by internal memory address for write request.
5830   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
5831   *                the configuration information for the specified FMPI2C.
5832   * @param  DevAddress Target device address: The device 7 bits address value
5833   *         in datasheet must be shifted to the left before calling the interface
5834   * @param  MemAddress Internal memory address
5835   * @param  MemAddSize Size of internal memory address
5836   * @param  Timeout Timeout duration
5837   * @param  Tickstart Tick start value
5838   * @retval HAL status
5839   */
FMPI2C_RequestMemoryWrite(FMPI2C_HandleTypeDef * hfmpi2c,uint16_t DevAddress,uint16_t MemAddress,uint16_t MemAddSize,uint32_t Timeout,uint32_t Tickstart)5840 static HAL_StatusTypeDef FMPI2C_RequestMemoryWrite(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress,
5841                                                    uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout,
5842                                                    uint32_t Tickstart)
5843 {
5844   FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)MemAddSize, FMPI2C_RELOAD_MODE, FMPI2C_GENERATE_START_WRITE);
5845 
5846   /* Wait until TXIS flag is set */
5847   if (FMPI2C_WaitOnTXISFlagUntilTimeout(hfmpi2c, Timeout, Tickstart) != HAL_OK)
5848   {
5849     return HAL_ERROR;
5850   }
5851 
5852   /* If Memory address size is 8Bit */
5853   if (MemAddSize == FMPI2C_MEMADD_SIZE_8BIT)
5854   {
5855     /* Send Memory Address */
5856     hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_LSB(MemAddress);
5857   }
5858   /* If Memory address size is 16Bit */
5859   else
5860   {
5861     /* Send MSB of Memory Address */
5862     hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_MSB(MemAddress);
5863 
5864     /* Wait until TXIS flag is set */
5865     if (FMPI2C_WaitOnTXISFlagUntilTimeout(hfmpi2c, Timeout, Tickstart) != HAL_OK)
5866     {
5867       return HAL_ERROR;
5868     }
5869 
5870     /* Send LSB of Memory Address */
5871     hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_LSB(MemAddress);
5872   }
5873 
5874   /* Wait until TCR flag is set */
5875   if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_TCR, RESET, Timeout, Tickstart) != HAL_OK)
5876   {
5877     return HAL_ERROR;
5878   }
5879 
5880   return HAL_OK;
5881 }
5882 
5883 /**
5884   * @brief  Master sends target device address followed by internal memory address for read request.
5885   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
5886   *                the configuration information for the specified FMPI2C.
5887   * @param  DevAddress Target device address: The device 7 bits address value
5888   *         in datasheet must be shifted to the left before calling the interface
5889   * @param  MemAddress Internal memory address
5890   * @param  MemAddSize Size of internal memory address
5891   * @param  Timeout Timeout duration
5892   * @param  Tickstart Tick start value
5893   * @retval HAL status
5894   */
FMPI2C_RequestMemoryRead(FMPI2C_HandleTypeDef * hfmpi2c,uint16_t DevAddress,uint16_t MemAddress,uint16_t MemAddSize,uint32_t Timeout,uint32_t Tickstart)5895 static HAL_StatusTypeDef FMPI2C_RequestMemoryRead(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress,
5896                                                   uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout,
5897                                                   uint32_t Tickstart)
5898 {
5899   FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)MemAddSize, FMPI2C_SOFTEND_MODE, FMPI2C_GENERATE_START_WRITE);
5900 
5901   /* Wait until TXIS flag is set */
5902   if (FMPI2C_WaitOnTXISFlagUntilTimeout(hfmpi2c, Timeout, Tickstart) != HAL_OK)
5903   {
5904     return HAL_ERROR;
5905   }
5906 
5907   /* If Memory address size is 8Bit */
5908   if (MemAddSize == FMPI2C_MEMADD_SIZE_8BIT)
5909   {
5910     /* Send Memory Address */
5911     hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_LSB(MemAddress);
5912   }
5913   /* If Memory address size is 16Bit */
5914   else
5915   {
5916     /* Send MSB of Memory Address */
5917     hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_MSB(MemAddress);
5918 
5919     /* Wait until TXIS flag is set */
5920     if (FMPI2C_WaitOnTXISFlagUntilTimeout(hfmpi2c, Timeout, Tickstart) != HAL_OK)
5921     {
5922       return HAL_ERROR;
5923     }
5924 
5925     /* Send LSB of Memory Address */
5926     hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_LSB(MemAddress);
5927   }
5928 
5929   /* Wait until TC flag is set */
5930   if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_TC, RESET, Timeout, Tickstart) != HAL_OK)
5931   {
5932     return HAL_ERROR;
5933   }
5934 
5935   return HAL_OK;
5936 }
5937 
5938 /**
5939   * @brief  FMPI2C Address complete process callback.
5940   * @param  hfmpi2c FMPI2C handle.
5941   * @param  ITFlags Interrupt flags to handle.
5942   * @retval None
5943   */
FMPI2C_ITAddrCplt(FMPI2C_HandleTypeDef * hfmpi2c,uint32_t ITFlags)5944 static void FMPI2C_ITAddrCplt(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags)
5945 {
5946   uint8_t transferdirection;
5947   uint16_t slaveaddrcode;
5948   uint16_t ownadd1code;
5949   uint16_t ownadd2code;
5950 
5951   /* Prevent unused argument(s) compilation warning */
5952   UNUSED(ITFlags);
5953 
5954   /* In case of Listen state, need to inform upper layer of address match code event */
5955   if (((uint32_t)hfmpi2c->State & (uint32_t)HAL_FMPI2C_STATE_LISTEN) == (uint32_t)HAL_FMPI2C_STATE_LISTEN)
5956   {
5957     transferdirection = FMPI2C_GET_DIR(hfmpi2c);
5958     slaveaddrcode     = FMPI2C_GET_ADDR_MATCH(hfmpi2c);
5959     ownadd1code       = FMPI2C_GET_OWN_ADDRESS1(hfmpi2c);
5960     ownadd2code       = FMPI2C_GET_OWN_ADDRESS2(hfmpi2c);
5961 
5962     /* If 10bits addressing mode is selected */
5963     if (hfmpi2c->Init.AddressingMode == FMPI2C_ADDRESSINGMODE_10BIT)
5964     {
5965       if ((slaveaddrcode & SLAVE_ADDR_MSK) == ((ownadd1code >> SLAVE_ADDR_SHIFT) & SLAVE_ADDR_MSK))
5966       {
5967         slaveaddrcode = ownadd1code;
5968         hfmpi2c->AddrEventCount++;
5969         if (hfmpi2c->AddrEventCount == 2U)
5970         {
5971           /* Reset Address Event counter */
5972           hfmpi2c->AddrEventCount = 0U;
5973 
5974           /* Clear ADDR flag */
5975           __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_ADDR);
5976 
5977           /* Process Unlocked */
5978           __HAL_UNLOCK(hfmpi2c);
5979 
5980           /* Call Slave Addr callback */
5981 #if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1)
5982           hfmpi2c->AddrCallback(hfmpi2c, transferdirection, slaveaddrcode);
5983 #else
5984           HAL_FMPI2C_AddrCallback(hfmpi2c, transferdirection, slaveaddrcode);
5985 #endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */
5986         }
5987       }
5988       else
5989       {
5990         slaveaddrcode = ownadd2code;
5991 
5992         /* Disable ADDR Interrupts */
5993         FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT);
5994 
5995         /* Process Unlocked */
5996         __HAL_UNLOCK(hfmpi2c);
5997 
5998         /* Call Slave Addr callback */
5999 #if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1)
6000         hfmpi2c->AddrCallback(hfmpi2c, transferdirection, slaveaddrcode);
6001 #else
6002         HAL_FMPI2C_AddrCallback(hfmpi2c, transferdirection, slaveaddrcode);
6003 #endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */
6004       }
6005     }
6006     /* else 7 bits addressing mode is selected */
6007     else
6008     {
6009       /* Disable ADDR Interrupts */
6010       FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT);
6011 
6012       /* Process Unlocked */
6013       __HAL_UNLOCK(hfmpi2c);
6014 
6015       /* Call Slave Addr callback */
6016 #if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1)
6017       hfmpi2c->AddrCallback(hfmpi2c, transferdirection, slaveaddrcode);
6018 #else
6019       HAL_FMPI2C_AddrCallback(hfmpi2c, transferdirection, slaveaddrcode);
6020 #endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */
6021     }
6022   }
6023   /* Else clear address flag only */
6024   else
6025   {
6026     /* Clear ADDR flag */
6027     __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_ADDR);
6028 
6029     /* Process Unlocked */
6030     __HAL_UNLOCK(hfmpi2c);
6031   }
6032 }
6033 
6034 /**
6035   * @brief  FMPI2C Master sequential complete process.
6036   * @param  hfmpi2c FMPI2C handle.
6037   * @retval None
6038   */
FMPI2C_ITMasterSeqCplt(FMPI2C_HandleTypeDef * hfmpi2c)6039 static void FMPI2C_ITMasterSeqCplt(FMPI2C_HandleTypeDef *hfmpi2c)
6040 {
6041   /* Reset FMPI2C handle mode */
6042   hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE;
6043 
6044   /* No Generate Stop, to permit restart mode */
6045   /* The stop will be done at the end of transfer, when FMPI2C_AUTOEND_MODE enable */
6046   if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_TX)
6047   {
6048     hfmpi2c->State         = HAL_FMPI2C_STATE_READY;
6049     hfmpi2c->PreviousState = FMPI2C_STATE_MASTER_BUSY_TX;
6050     hfmpi2c->XferISR       = NULL;
6051 
6052     /* Disable Interrupts */
6053     FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT);
6054 
6055     /* Process Unlocked */
6056     __HAL_UNLOCK(hfmpi2c);
6057 
6058     /* Call the corresponding callback to inform upper layer of End of Transfer */
6059 #if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1)
6060     hfmpi2c->MasterTxCpltCallback(hfmpi2c);
6061 #else
6062     HAL_FMPI2C_MasterTxCpltCallback(hfmpi2c);
6063 #endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */
6064   }
6065   /* hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX */
6066   else
6067   {
6068     hfmpi2c->State         = HAL_FMPI2C_STATE_READY;
6069     hfmpi2c->PreviousState = FMPI2C_STATE_MASTER_BUSY_RX;
6070     hfmpi2c->XferISR       = NULL;
6071 
6072     /* Disable Interrupts */
6073     FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_RX_IT);
6074 
6075     /* Process Unlocked */
6076     __HAL_UNLOCK(hfmpi2c);
6077 
6078     /* Call the corresponding callback to inform upper layer of End of Transfer */
6079 #if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1)
6080     hfmpi2c->MasterRxCpltCallback(hfmpi2c);
6081 #else
6082     HAL_FMPI2C_MasterRxCpltCallback(hfmpi2c);
6083 #endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */
6084   }
6085 }
6086 
6087 /**
6088   * @brief  FMPI2C Slave sequential complete process.
6089   * @param  hfmpi2c FMPI2C handle.
6090   * @retval None
6091   */
FMPI2C_ITSlaveSeqCplt(FMPI2C_HandleTypeDef * hfmpi2c)6092 static void FMPI2C_ITSlaveSeqCplt(FMPI2C_HandleTypeDef *hfmpi2c)
6093 {
6094   uint32_t tmpcr1value = READ_REG(hfmpi2c->Instance->CR1);
6095 
6096   /* Reset FMPI2C handle mode */
6097   hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE;
6098 
6099   /* If a DMA is ongoing, Update handle size context */
6100   if (FMPI2C_CHECK_IT_SOURCE(tmpcr1value, FMPI2C_CR1_TXDMAEN) != RESET)
6101   {
6102     /* Disable DMA Request */
6103     hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_TXDMAEN;
6104   }
6105   else if (FMPI2C_CHECK_IT_SOURCE(tmpcr1value, FMPI2C_CR1_RXDMAEN) != RESET)
6106   {
6107     /* Disable DMA Request */
6108     hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_RXDMAEN;
6109   }
6110   else
6111   {
6112     /* Do nothing */
6113   }
6114 
6115   if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_TX_LISTEN)
6116   {
6117     /* Remove HAL_FMPI2C_STATE_SLAVE_BUSY_TX, keep only HAL_FMPI2C_STATE_LISTEN */
6118     hfmpi2c->State         = HAL_FMPI2C_STATE_LISTEN;
6119     hfmpi2c->PreviousState = FMPI2C_STATE_SLAVE_BUSY_TX;
6120 
6121     /* Disable Interrupts */
6122     FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT);
6123 
6124     /* Process Unlocked */
6125     __HAL_UNLOCK(hfmpi2c);
6126 
6127     /* Call the corresponding callback to inform upper layer of End of Transfer */
6128 #if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1)
6129     hfmpi2c->SlaveTxCpltCallback(hfmpi2c);
6130 #else
6131     HAL_FMPI2C_SlaveTxCpltCallback(hfmpi2c);
6132 #endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */
6133   }
6134 
6135   else if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX_LISTEN)
6136   {
6137     /* Remove HAL_FMPI2C_STATE_SLAVE_BUSY_RX, keep only HAL_FMPI2C_STATE_LISTEN */
6138     hfmpi2c->State         = HAL_FMPI2C_STATE_LISTEN;
6139     hfmpi2c->PreviousState = FMPI2C_STATE_SLAVE_BUSY_RX;
6140 
6141     /* Disable Interrupts */
6142     FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_RX_IT);
6143 
6144     /* Process Unlocked */
6145     __HAL_UNLOCK(hfmpi2c);
6146 
6147     /* Call the corresponding callback to inform upper layer of End of Transfer */
6148 #if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1)
6149     hfmpi2c->SlaveRxCpltCallback(hfmpi2c);
6150 #else
6151     HAL_FMPI2C_SlaveRxCpltCallback(hfmpi2c);
6152 #endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */
6153   }
6154   else
6155   {
6156     /* Nothing to do */
6157   }
6158 }
6159 
6160 /**
6161   * @brief  FMPI2C Master complete process.
6162   * @param  hfmpi2c FMPI2C handle.
6163   * @param  ITFlags Interrupt flags to handle.
6164   * @retval None
6165   */
FMPI2C_ITMasterCplt(FMPI2C_HandleTypeDef * hfmpi2c,uint32_t ITFlags)6166 static void FMPI2C_ITMasterCplt(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags)
6167 {
6168   uint32_t tmperror;
6169   uint32_t tmpITFlags = ITFlags;
6170   __IO uint32_t tmpreg;
6171 
6172   /* Clear STOP Flag */
6173   __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF);
6174 
6175   /* Disable Interrupts and Store Previous state */
6176   if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_TX)
6177   {
6178     FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT);
6179     hfmpi2c->PreviousState = FMPI2C_STATE_MASTER_BUSY_TX;
6180   }
6181   else if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX)
6182   {
6183     FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_RX_IT);
6184     hfmpi2c->PreviousState = FMPI2C_STATE_MASTER_BUSY_RX;
6185   }
6186   else
6187   {
6188     /* Do nothing */
6189   }
6190 
6191   /* Clear Configuration Register 2 */
6192   FMPI2C_RESET_CR2(hfmpi2c);
6193 
6194   /* Reset handle parameters */
6195   hfmpi2c->XferISR       = NULL;
6196   hfmpi2c->XferOptions   = FMPI2C_NO_OPTION_FRAME;
6197 
6198   if (FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_AF) != RESET)
6199   {
6200     /* Clear NACK Flag */
6201     __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF);
6202 
6203     /* Set acknowledge error code */
6204     hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_AF;
6205   }
6206 
6207   /* Fetch Last receive data if any */
6208   if ((hfmpi2c->State == HAL_FMPI2C_STATE_ABORT) && (FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_RXNE) != RESET))
6209   {
6210     /* Read data from RXDR */
6211     tmpreg = (uint8_t)hfmpi2c->Instance->RXDR;
6212     UNUSED(tmpreg);
6213   }
6214 
6215   /* Flush TX register */
6216   FMPI2C_Flush_TXDR(hfmpi2c);
6217 
6218   /* Store current volatile hfmpi2c->ErrorCode, misra rule */
6219   tmperror = hfmpi2c->ErrorCode;
6220 
6221   /* Call the corresponding callback to inform upper layer of End of Transfer */
6222   if ((hfmpi2c->State == HAL_FMPI2C_STATE_ABORT) || (tmperror != HAL_FMPI2C_ERROR_NONE))
6223   {
6224     /* Call the corresponding callback to inform upper layer of End of Transfer */
6225     FMPI2C_ITError(hfmpi2c, hfmpi2c->ErrorCode);
6226   }
6227   /* hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_TX */
6228   else if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_TX)
6229   {
6230     hfmpi2c->State = HAL_FMPI2C_STATE_READY;
6231     hfmpi2c->PreviousState = FMPI2C_STATE_NONE;
6232 
6233     if (hfmpi2c->Mode == HAL_FMPI2C_MODE_MEM)
6234     {
6235       hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE;
6236 
6237       /* Process Unlocked */
6238       __HAL_UNLOCK(hfmpi2c);
6239 
6240       /* Call the corresponding callback to inform upper layer of End of Transfer */
6241 #if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1)
6242       hfmpi2c->MemTxCpltCallback(hfmpi2c);
6243 #else
6244       HAL_FMPI2C_MemTxCpltCallback(hfmpi2c);
6245 #endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */
6246     }
6247     else
6248     {
6249       hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE;
6250 
6251       /* Process Unlocked */
6252       __HAL_UNLOCK(hfmpi2c);
6253 
6254       /* Call the corresponding callback to inform upper layer of End of Transfer */
6255 #if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1)
6256       hfmpi2c->MasterTxCpltCallback(hfmpi2c);
6257 #else
6258       HAL_FMPI2C_MasterTxCpltCallback(hfmpi2c);
6259 #endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */
6260     }
6261   }
6262   /* hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX */
6263   else if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX)
6264   {
6265     hfmpi2c->State = HAL_FMPI2C_STATE_READY;
6266     hfmpi2c->PreviousState = FMPI2C_STATE_NONE;
6267 
6268     if (hfmpi2c->Mode == HAL_FMPI2C_MODE_MEM)
6269     {
6270       hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE;
6271 
6272       /* Process Unlocked */
6273       __HAL_UNLOCK(hfmpi2c);
6274 
6275       /* Call the corresponding callback to inform upper layer of End of Transfer */
6276 #if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1)
6277       hfmpi2c->MemRxCpltCallback(hfmpi2c);
6278 #else
6279       HAL_FMPI2C_MemRxCpltCallback(hfmpi2c);
6280 #endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */
6281     }
6282     else
6283     {
6284       hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE;
6285 
6286       /* Process Unlocked */
6287       __HAL_UNLOCK(hfmpi2c);
6288 
6289       /* Call the corresponding callback to inform upper layer of End of Transfer */
6290 #if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1)
6291       hfmpi2c->MasterRxCpltCallback(hfmpi2c);
6292 #else
6293       HAL_FMPI2C_MasterRxCpltCallback(hfmpi2c);
6294 #endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */
6295     }
6296   }
6297   else
6298   {
6299     /* Nothing to do */
6300   }
6301 }
6302 
6303 /**
6304   * @brief  FMPI2C Slave complete process.
6305   * @param  hfmpi2c FMPI2C handle.
6306   * @param  ITFlags Interrupt flags to handle.
6307   * @retval None
6308   */
FMPI2C_ITSlaveCplt(FMPI2C_HandleTypeDef * hfmpi2c,uint32_t ITFlags)6309 static void FMPI2C_ITSlaveCplt(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags)
6310 {
6311   uint32_t tmpcr1value = READ_REG(hfmpi2c->Instance->CR1);
6312   uint32_t tmpITFlags = ITFlags;
6313   uint32_t tmpoptions = hfmpi2c->XferOptions;
6314   HAL_FMPI2C_StateTypeDef tmpstate = hfmpi2c->State;
6315 
6316   /* Clear STOP Flag */
6317   __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF);
6318 
6319   /* Disable Interrupts and Store Previous state */
6320   if ((tmpstate == HAL_FMPI2C_STATE_BUSY_TX) || (tmpstate == HAL_FMPI2C_STATE_BUSY_TX_LISTEN))
6321   {
6322     FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT | FMPI2C_XFER_TX_IT);
6323     hfmpi2c->PreviousState = FMPI2C_STATE_SLAVE_BUSY_TX;
6324   }
6325   else if ((tmpstate == HAL_FMPI2C_STATE_BUSY_RX) || (tmpstate == HAL_FMPI2C_STATE_BUSY_RX_LISTEN))
6326   {
6327     FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT | FMPI2C_XFER_RX_IT);
6328     hfmpi2c->PreviousState = FMPI2C_STATE_SLAVE_BUSY_RX;
6329   }
6330   else if (tmpstate == HAL_FMPI2C_STATE_LISTEN)
6331   {
6332     FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT | FMPI2C_XFER_TX_IT | FMPI2C_XFER_RX_IT);
6333     hfmpi2c->PreviousState = FMPI2C_STATE_NONE;
6334   }
6335   else
6336   {
6337     /* Do nothing */
6338   }
6339 
6340   /* Disable Address Acknowledge */
6341   hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK;
6342 
6343   /* Clear Configuration Register 2 */
6344   FMPI2C_RESET_CR2(hfmpi2c);
6345 
6346   /* Flush TX register */
6347   FMPI2C_Flush_TXDR(hfmpi2c);
6348 
6349   /* If a DMA is ongoing, Update handle size context */
6350   if (FMPI2C_CHECK_IT_SOURCE(tmpcr1value, FMPI2C_CR1_TXDMAEN) != RESET)
6351   {
6352     /* Disable DMA Request */
6353     hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_TXDMAEN;
6354 
6355     if (hfmpi2c->hdmatx != NULL)
6356     {
6357       hfmpi2c->XferCount = (uint16_t)FMPI2C_GET_DMA_REMAIN_DATA(hfmpi2c->hdmatx);
6358     }
6359   }
6360   else if (FMPI2C_CHECK_IT_SOURCE(tmpcr1value, FMPI2C_CR1_RXDMAEN) != RESET)
6361   {
6362     /* Disable DMA Request */
6363     hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_RXDMAEN;
6364 
6365     if (hfmpi2c->hdmarx != NULL)
6366     {
6367       hfmpi2c->XferCount = (uint16_t)FMPI2C_GET_DMA_REMAIN_DATA(hfmpi2c->hdmarx);
6368     }
6369   }
6370   else
6371   {
6372     /* Do nothing */
6373   }
6374 
6375   /* Store Last receive data if any */
6376   if (FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_RXNE) != RESET)
6377   {
6378     /* Remove RXNE flag on temporary variable as read done */
6379     tmpITFlags &= ~FMPI2C_FLAG_RXNE;
6380 
6381     /* Read data from RXDR */
6382     *hfmpi2c->pBuffPtr = (uint8_t)hfmpi2c->Instance->RXDR;
6383 
6384     /* Increment Buffer pointer */
6385     hfmpi2c->pBuffPtr++;
6386 
6387     if ((hfmpi2c->XferSize > 0U))
6388     {
6389       hfmpi2c->XferSize--;
6390       hfmpi2c->XferCount--;
6391     }
6392   }
6393 
6394   /* All data are not transferred, so set error code accordingly */
6395   if (hfmpi2c->XferCount != 0U)
6396   {
6397     /* Set ErrorCode corresponding to a Non-Acknowledge */
6398     hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_AF;
6399   }
6400 
6401   if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_AF) != RESET) && \
6402       (FMPI2C_CHECK_IT_SOURCE(tmpcr1value, FMPI2C_IT_NACKI) != RESET))
6403   {
6404     /* Check that FMPI2C transfer finished */
6405     /* if yes, normal use case, a NACK is sent by the MASTER when Transfer is finished */
6406     /* Mean XferCount == 0*/
6407     /* So clear Flag NACKF only */
6408     if (hfmpi2c->XferCount == 0U)
6409     {
6410       if ((hfmpi2c->State == HAL_FMPI2C_STATE_LISTEN) && (tmpoptions == FMPI2C_FIRST_AND_LAST_FRAME))
6411         /* Same action must be done for (tmpoptions == FMPI2C_LAST_FRAME) which removed for
6412            Warning[Pa134]: left and right operands are identical */
6413       {
6414         /* Call FMPI2C Listen complete process */
6415         FMPI2C_ITListenCplt(hfmpi2c, tmpITFlags);
6416       }
6417       else if ((hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_TX_LISTEN) && (tmpoptions != FMPI2C_NO_OPTION_FRAME))
6418       {
6419         /* Clear NACK Flag */
6420         __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF);
6421 
6422         /* Flush TX register */
6423         FMPI2C_Flush_TXDR(hfmpi2c);
6424 
6425         /* Last Byte is Transmitted */
6426         /* Call FMPI2C Slave Sequential complete process */
6427         FMPI2C_ITSlaveSeqCplt(hfmpi2c);
6428       }
6429       else
6430       {
6431         /* Clear NACK Flag */
6432         __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF);
6433       }
6434     }
6435     else
6436     {
6437       /* if no, error use case, a Non-Acknowledge of last Data is generated by the MASTER*/
6438       /* Clear NACK Flag */
6439       __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF);
6440 
6441       /* Set ErrorCode corresponding to a Non-Acknowledge */
6442       hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_AF;
6443 
6444       if ((tmpoptions == FMPI2C_FIRST_FRAME) || (tmpoptions == FMPI2C_NEXT_FRAME))
6445       {
6446         /* Call the corresponding callback to inform upper layer of End of Transfer */
6447         FMPI2C_ITError(hfmpi2c, hfmpi2c->ErrorCode);
6448       }
6449     }
6450   }
6451 
6452   hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE;
6453   hfmpi2c->XferISR = NULL;
6454 
6455   if (hfmpi2c->ErrorCode != HAL_FMPI2C_ERROR_NONE)
6456   {
6457     /* Call the corresponding callback to inform upper layer of End of Transfer */
6458     FMPI2C_ITError(hfmpi2c, hfmpi2c->ErrorCode);
6459 
6460     /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */
6461     if (hfmpi2c->State == HAL_FMPI2C_STATE_LISTEN)
6462     {
6463       /* Call FMPI2C Listen complete process */
6464       FMPI2C_ITListenCplt(hfmpi2c, tmpITFlags);
6465     }
6466   }
6467   else if (hfmpi2c->XferOptions != FMPI2C_NO_OPTION_FRAME)
6468   {
6469     /* Call the Sequential Complete callback, to inform upper layer of the end of Transfer */
6470     FMPI2C_ITSlaveSeqCplt(hfmpi2c);
6471 
6472     hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME;
6473     hfmpi2c->State = HAL_FMPI2C_STATE_READY;
6474     hfmpi2c->PreviousState = FMPI2C_STATE_NONE;
6475 
6476     /* Process Unlocked */
6477     __HAL_UNLOCK(hfmpi2c);
6478 
6479     /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */
6480 #if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1)
6481     hfmpi2c->ListenCpltCallback(hfmpi2c);
6482 #else
6483     HAL_FMPI2C_ListenCpltCallback(hfmpi2c);
6484 #endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */
6485   }
6486   /* Call the corresponding callback to inform upper layer of End of Transfer */
6487   else if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX)
6488   {
6489     hfmpi2c->State = HAL_FMPI2C_STATE_READY;
6490     hfmpi2c->PreviousState = FMPI2C_STATE_NONE;
6491 
6492     /* Process Unlocked */
6493     __HAL_UNLOCK(hfmpi2c);
6494 
6495     /* Call the corresponding callback to inform upper layer of End of Transfer */
6496 #if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1)
6497     hfmpi2c->SlaveRxCpltCallback(hfmpi2c);
6498 #else
6499     HAL_FMPI2C_SlaveRxCpltCallback(hfmpi2c);
6500 #endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */
6501   }
6502   else
6503   {
6504     hfmpi2c->State = HAL_FMPI2C_STATE_READY;
6505     hfmpi2c->PreviousState = FMPI2C_STATE_NONE;
6506 
6507     /* Process Unlocked */
6508     __HAL_UNLOCK(hfmpi2c);
6509 
6510     /* Call the corresponding callback to inform upper layer of End of Transfer */
6511 #if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1)
6512     hfmpi2c->SlaveTxCpltCallback(hfmpi2c);
6513 #else
6514     HAL_FMPI2C_SlaveTxCpltCallback(hfmpi2c);
6515 #endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */
6516   }
6517 }
6518 
6519 /**
6520   * @brief  FMPI2C Listen complete process.
6521   * @param  hfmpi2c FMPI2C handle.
6522   * @param  ITFlags Interrupt flags to handle.
6523   * @retval None
6524   */
FMPI2C_ITListenCplt(FMPI2C_HandleTypeDef * hfmpi2c,uint32_t ITFlags)6525 static void FMPI2C_ITListenCplt(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags)
6526 {
6527   /* Reset handle parameters */
6528   hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME;
6529   hfmpi2c->PreviousState = FMPI2C_STATE_NONE;
6530   hfmpi2c->State = HAL_FMPI2C_STATE_READY;
6531   hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE;
6532   hfmpi2c->XferISR = NULL;
6533 
6534   /* Store Last receive data if any */
6535   if (FMPI2C_CHECK_FLAG(ITFlags, FMPI2C_FLAG_RXNE) != RESET)
6536   {
6537     /* Read data from RXDR */
6538     *hfmpi2c->pBuffPtr = (uint8_t)hfmpi2c->Instance->RXDR;
6539 
6540     /* Increment Buffer pointer */
6541     hfmpi2c->pBuffPtr++;
6542 
6543     if ((hfmpi2c->XferSize > 0U))
6544     {
6545       hfmpi2c->XferSize--;
6546       hfmpi2c->XferCount--;
6547 
6548       /* Set ErrorCode corresponding to a Non-Acknowledge */
6549       hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_AF;
6550     }
6551   }
6552 
6553   /* Disable all Interrupts*/
6554   FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT | FMPI2C_XFER_RX_IT | FMPI2C_XFER_TX_IT);
6555 
6556   /* Clear NACK Flag */
6557   __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF);
6558 
6559   /* Process Unlocked */
6560   __HAL_UNLOCK(hfmpi2c);
6561 
6562   /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */
6563 #if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1)
6564   hfmpi2c->ListenCpltCallback(hfmpi2c);
6565 #else
6566   HAL_FMPI2C_ListenCpltCallback(hfmpi2c);
6567 #endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */
6568 }
6569 
6570 /**
6571   * @brief  FMPI2C interrupts error process.
6572   * @param  hfmpi2c FMPI2C handle.
6573   * @param  ErrorCode Error code to handle.
6574   * @retval None
6575   */
FMPI2C_ITError(FMPI2C_HandleTypeDef * hfmpi2c,uint32_t ErrorCode)6576 static void FMPI2C_ITError(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ErrorCode)
6577 {
6578   HAL_FMPI2C_StateTypeDef tmpstate = hfmpi2c->State;
6579 
6580   uint32_t tmppreviousstate;
6581 
6582   /* Reset handle parameters */
6583   hfmpi2c->Mode          = HAL_FMPI2C_MODE_NONE;
6584   hfmpi2c->XferOptions   = FMPI2C_NO_OPTION_FRAME;
6585   hfmpi2c->XferCount     = 0U;
6586 
6587   /* Set new error code */
6588   hfmpi2c->ErrorCode |= ErrorCode;
6589 
6590   /* Disable Interrupts */
6591   if ((tmpstate == HAL_FMPI2C_STATE_LISTEN)         ||
6592       (tmpstate == HAL_FMPI2C_STATE_BUSY_TX_LISTEN) ||
6593       (tmpstate == HAL_FMPI2C_STATE_BUSY_RX_LISTEN))
6594   {
6595     /* Disable all interrupts, except interrupts related to LISTEN state */
6596     FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_RX_IT | FMPI2C_XFER_TX_IT);
6597 
6598     /* keep HAL_FMPI2C_STATE_LISTEN if set */
6599     hfmpi2c->State         = HAL_FMPI2C_STATE_LISTEN;
6600     hfmpi2c->XferISR       = FMPI2C_Slave_ISR_IT;
6601   }
6602   else
6603   {
6604     /* Disable all interrupts */
6605     FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT | FMPI2C_XFER_RX_IT | FMPI2C_XFER_TX_IT);
6606 
6607     /* Flush TX register */
6608     FMPI2C_Flush_TXDR(hfmpi2c);
6609 
6610     /* If state is an abort treatment on going, don't change state */
6611     /* This change will be do later */
6612     if (hfmpi2c->State != HAL_FMPI2C_STATE_ABORT)
6613     {
6614       /* Set HAL_FMPI2C_STATE_READY */
6615       hfmpi2c->State         = HAL_FMPI2C_STATE_READY;
6616 
6617       /* Check if a STOPF is detected */
6618       if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF) == SET)
6619       {
6620         if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_AF) == SET)
6621         {
6622           __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF);
6623           hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_AF;
6624         }
6625 
6626         /* Clear STOP Flag */
6627         __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF);
6628       }
6629 
6630     }
6631     hfmpi2c->XferISR       = NULL;
6632   }
6633 
6634   /* Abort DMA TX transfer if any */
6635   tmppreviousstate = hfmpi2c->PreviousState;
6636 
6637   if ((hfmpi2c->hdmatx != NULL) && ((tmppreviousstate == FMPI2C_STATE_MASTER_BUSY_TX) || \
6638                                     (tmppreviousstate == FMPI2C_STATE_SLAVE_BUSY_TX)))
6639   {
6640     if ((hfmpi2c->Instance->CR1 & FMPI2C_CR1_TXDMAEN) == FMPI2C_CR1_TXDMAEN)
6641     {
6642       hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_TXDMAEN;
6643     }
6644 
6645     if (HAL_DMA_GetState(hfmpi2c->hdmatx) != HAL_DMA_STATE_READY)
6646     {
6647       /* Set the FMPI2C DMA Abort callback :
6648        will lead to call HAL_FMPI2C_ErrorCallback() at end of DMA abort procedure */
6649       hfmpi2c->hdmatx->XferAbortCallback = FMPI2C_DMAAbort;
6650 
6651       /* Process Unlocked */
6652       __HAL_UNLOCK(hfmpi2c);
6653 
6654       /* Abort DMA TX */
6655       if (HAL_DMA_Abort_IT(hfmpi2c->hdmatx) != HAL_OK)
6656       {
6657         /* Call Directly XferAbortCallback function in case of error */
6658         hfmpi2c->hdmatx->XferAbortCallback(hfmpi2c->hdmatx);
6659       }
6660     }
6661     else
6662     {
6663       FMPI2C_TreatErrorCallback(hfmpi2c);
6664     }
6665   }
6666   /* Abort DMA RX transfer if any */
6667   else if ((hfmpi2c->hdmarx != NULL) && ((tmppreviousstate == FMPI2C_STATE_MASTER_BUSY_RX) || \
6668                                          (tmppreviousstate == FMPI2C_STATE_SLAVE_BUSY_RX)))
6669   {
6670     if ((hfmpi2c->Instance->CR1 & FMPI2C_CR1_RXDMAEN) == FMPI2C_CR1_RXDMAEN)
6671     {
6672       hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_RXDMAEN;
6673     }
6674 
6675     if (HAL_DMA_GetState(hfmpi2c->hdmarx) != HAL_DMA_STATE_READY)
6676     {
6677       /* Set the FMPI2C DMA Abort callback :
6678         will lead to call HAL_FMPI2C_ErrorCallback() at end of DMA abort procedure */
6679       hfmpi2c->hdmarx->XferAbortCallback = FMPI2C_DMAAbort;
6680 
6681       /* Process Unlocked */
6682       __HAL_UNLOCK(hfmpi2c);
6683 
6684       /* Abort DMA RX */
6685       if (HAL_DMA_Abort_IT(hfmpi2c->hdmarx) != HAL_OK)
6686       {
6687         /* Call Directly hfmpi2c->hdmarx->XferAbortCallback function in case of error */
6688         hfmpi2c->hdmarx->XferAbortCallback(hfmpi2c->hdmarx);
6689       }
6690     }
6691     else
6692     {
6693       FMPI2C_TreatErrorCallback(hfmpi2c);
6694     }
6695   }
6696   else
6697   {
6698     FMPI2C_TreatErrorCallback(hfmpi2c);
6699   }
6700 }
6701 
6702 /**
6703   * @brief  FMPI2C Error callback treatment.
6704   * @param  hfmpi2c FMPI2C handle.
6705   * @retval None
6706   */
FMPI2C_TreatErrorCallback(FMPI2C_HandleTypeDef * hfmpi2c)6707 static void FMPI2C_TreatErrorCallback(FMPI2C_HandleTypeDef *hfmpi2c)
6708 {
6709   if (hfmpi2c->State == HAL_FMPI2C_STATE_ABORT)
6710   {
6711     hfmpi2c->State = HAL_FMPI2C_STATE_READY;
6712     hfmpi2c->PreviousState = FMPI2C_STATE_NONE;
6713 
6714     /* Process Unlocked */
6715     __HAL_UNLOCK(hfmpi2c);
6716 
6717     /* Call the corresponding callback to inform upper layer of End of Transfer */
6718 #if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1)
6719     hfmpi2c->AbortCpltCallback(hfmpi2c);
6720 #else
6721     HAL_FMPI2C_AbortCpltCallback(hfmpi2c);
6722 #endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */
6723   }
6724   else
6725   {
6726     hfmpi2c->PreviousState = FMPI2C_STATE_NONE;
6727 
6728     /* Process Unlocked */
6729     __HAL_UNLOCK(hfmpi2c);
6730 
6731     /* Call the corresponding callback to inform upper layer of End of Transfer */
6732 #if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1)
6733     hfmpi2c->ErrorCallback(hfmpi2c);
6734 #else
6735     HAL_FMPI2C_ErrorCallback(hfmpi2c);
6736 #endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */
6737   }
6738 }
6739 
6740 /**
6741   * @brief  FMPI2C Tx data register flush process.
6742   * @param  hfmpi2c FMPI2C handle.
6743   * @retval None
6744   */
FMPI2C_Flush_TXDR(FMPI2C_HandleTypeDef * hfmpi2c)6745 static void FMPI2C_Flush_TXDR(FMPI2C_HandleTypeDef *hfmpi2c)
6746 {
6747   /* If a pending TXIS flag is set */
6748   /* Write a dummy data in TXDR to clear it */
6749   if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_TXIS) != RESET)
6750   {
6751     hfmpi2c->Instance->TXDR = 0x00U;
6752   }
6753 
6754   /* Flush TX register if not empty */
6755   if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_TXE) == RESET)
6756   {
6757     __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_TXE);
6758   }
6759 }
6760 
6761 /**
6762   * @brief  DMA FMPI2C master transmit process complete callback.
6763   * @param  hdma DMA handle
6764   * @retval None
6765   */
FMPI2C_DMAMasterTransmitCplt(DMA_HandleTypeDef * hdma)6766 static void FMPI2C_DMAMasterTransmitCplt(DMA_HandleTypeDef *hdma)
6767 {
6768   /* Derogation MISRAC2012-Rule-11.5 */
6769   FMPI2C_HandleTypeDef *hfmpi2c = (FMPI2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
6770 
6771   /* Disable DMA Request */
6772   hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_TXDMAEN;
6773 
6774   /* If last transfer, enable STOP interrupt */
6775   if (hfmpi2c->XferCount == 0U)
6776   {
6777     /* Enable STOP interrupt */
6778     FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_CPLT_IT);
6779   }
6780   /* else prepare a new DMA transfer and enable TCReload interrupt */
6781   else
6782   {
6783     /* Update Buffer pointer */
6784     hfmpi2c->pBuffPtr += hfmpi2c->XferSize;
6785 
6786     /* Set the XferSize to transfer */
6787     if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
6788     {
6789       hfmpi2c->XferSize = MAX_NBYTE_SIZE;
6790     }
6791     else
6792     {
6793       hfmpi2c->XferSize = hfmpi2c->XferCount;
6794     }
6795 
6796     /* Enable the DMA stream */
6797     if (HAL_DMA_Start_IT(hfmpi2c->hdmatx, (uint32_t)hfmpi2c->pBuffPtr, (uint32_t)&hfmpi2c->Instance->TXDR,
6798                          hfmpi2c->XferSize) != HAL_OK)
6799     {
6800       /* Call the corresponding callback to inform upper layer of End of Transfer */
6801       FMPI2C_ITError(hfmpi2c, HAL_FMPI2C_ERROR_DMA);
6802     }
6803     else
6804     {
6805       /* Enable TC interrupts */
6806       FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_RELOAD_IT);
6807     }
6808   }
6809 }
6810 
6811 
6812 /**
6813   * @brief  DMA FMPI2C slave transmit process complete callback.
6814   * @param  hdma DMA handle
6815   * @retval None
6816   */
FMPI2C_DMASlaveTransmitCplt(DMA_HandleTypeDef * hdma)6817 static void FMPI2C_DMASlaveTransmitCplt(DMA_HandleTypeDef *hdma)
6818 {
6819   /* Derogation MISRAC2012-Rule-11.5 */
6820   FMPI2C_HandleTypeDef *hfmpi2c = (FMPI2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
6821   uint32_t tmpoptions = hfmpi2c->XferOptions;
6822 
6823   if ((tmpoptions == FMPI2C_NEXT_FRAME) || (tmpoptions == FMPI2C_FIRST_FRAME))
6824   {
6825     /* Disable DMA Request */
6826     hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_TXDMAEN;
6827 
6828     /* Last Byte is Transmitted */
6829     /* Call FMPI2C Slave Sequential complete process */
6830     FMPI2C_ITSlaveSeqCplt(hfmpi2c);
6831   }
6832   else
6833   {
6834     /* No specific action, Master fully manage the generation of STOP condition */
6835     /* Mean that this generation can arrive at any time, at the end or during DMA process */
6836     /* So STOP condition should be manage through Interrupt treatment */
6837   }
6838 }
6839 
6840 
6841 /**
6842   * @brief DMA FMPI2C master receive process complete callback.
6843   * @param  hdma DMA handle
6844   * @retval None
6845   */
FMPI2C_DMAMasterReceiveCplt(DMA_HandleTypeDef * hdma)6846 static void FMPI2C_DMAMasterReceiveCplt(DMA_HandleTypeDef *hdma)
6847 {
6848   /* Derogation MISRAC2012-Rule-11.5 */
6849   FMPI2C_HandleTypeDef *hfmpi2c = (FMPI2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
6850 
6851   /* Disable DMA Request */
6852   hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_RXDMAEN;
6853 
6854   /* If last transfer, enable STOP interrupt */
6855   if (hfmpi2c->XferCount == 0U)
6856   {
6857     /* Enable STOP interrupt */
6858     FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_CPLT_IT);
6859   }
6860   /* else prepare a new DMA transfer and enable TCReload interrupt */
6861   else
6862   {
6863     /* Update Buffer pointer */
6864     hfmpi2c->pBuffPtr += hfmpi2c->XferSize;
6865 
6866     /* Set the XferSize to transfer */
6867     if (hfmpi2c->XferCount > MAX_NBYTE_SIZE)
6868     {
6869       /* Errata workaround 170323 */
6870       if (FMPI2C_GET_DIR(hfmpi2c) == FMPI2C_DIRECTION_RECEIVE)
6871       {
6872         hfmpi2c->XferSize = 1U;
6873       }
6874       else
6875       {
6876         hfmpi2c->XferSize = MAX_NBYTE_SIZE;
6877       }
6878     }
6879     else
6880     {
6881       hfmpi2c->XferSize = hfmpi2c->XferCount;
6882     }
6883 
6884     /* Enable the DMA stream */
6885     if (HAL_DMA_Start_IT(hfmpi2c->hdmarx, (uint32_t)&hfmpi2c->Instance->RXDR, (uint32_t)hfmpi2c->pBuffPtr,
6886                          hfmpi2c->XferSize) != HAL_OK)
6887     {
6888       /* Call the corresponding callback to inform upper layer of End of Transfer */
6889       FMPI2C_ITError(hfmpi2c, HAL_FMPI2C_ERROR_DMA);
6890     }
6891     else
6892     {
6893       /* Enable TC interrupts */
6894       FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_RELOAD_IT);
6895     }
6896   }
6897 }
6898 
6899 
6900 /**
6901   * @brief  DMA FMPI2C slave receive process complete callback.
6902   * @param  hdma DMA handle
6903   * @retval None
6904   */
FMPI2C_DMASlaveReceiveCplt(DMA_HandleTypeDef * hdma)6905 static void FMPI2C_DMASlaveReceiveCplt(DMA_HandleTypeDef *hdma)
6906 {
6907   /* Derogation MISRAC2012-Rule-11.5 */
6908   FMPI2C_HandleTypeDef *hfmpi2c = (FMPI2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
6909   uint32_t tmpoptions = hfmpi2c->XferOptions;
6910 
6911   if ((FMPI2C_GET_DMA_REMAIN_DATA(hfmpi2c->hdmarx) == 0U) && \
6912       (tmpoptions != FMPI2C_NO_OPTION_FRAME))
6913   {
6914     /* Disable DMA Request */
6915     hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_RXDMAEN;
6916 
6917     /* Call FMPI2C Slave Sequential complete process */
6918     FMPI2C_ITSlaveSeqCplt(hfmpi2c);
6919   }
6920   else
6921   {
6922     /* No specific action, Master fully manage the generation of STOP condition */
6923     /* Mean that this generation can arrive at any time, at the end or during DMA process */
6924     /* So STOP condition should be manage through Interrupt treatment */
6925   }
6926 }
6927 
6928 
6929 /**
6930   * @brief  DMA FMPI2C communication error callback.
6931   * @param hdma DMA handle
6932   * @retval None
6933   */
FMPI2C_DMAError(DMA_HandleTypeDef * hdma)6934 static void FMPI2C_DMAError(DMA_HandleTypeDef *hdma)
6935 {
6936   uint32_t treatdmaerror = 0U;
6937   /* Derogation MISRAC2012-Rule-11.5 */
6938   FMPI2C_HandleTypeDef *hfmpi2c = (FMPI2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
6939 
6940   if (hfmpi2c->hdmatx != NULL)
6941   {
6942     if (FMPI2C_GET_DMA_REMAIN_DATA(hfmpi2c->hdmatx) == 0U)
6943     {
6944       treatdmaerror = 1U;
6945     }
6946   }
6947 
6948   if (hfmpi2c->hdmarx != NULL)
6949   {
6950     if (FMPI2C_GET_DMA_REMAIN_DATA(hfmpi2c->hdmarx) == 0U)
6951     {
6952       treatdmaerror = 1U;
6953     }
6954   }
6955 
6956   /* Check if a FIFO error is detected, if true normal use case, so no specific action to perform */
6957   if (!((HAL_DMA_GetError(hdma) == HAL_DMA_ERROR_FE)) && (treatdmaerror != 0U))
6958   {
6959     /* Disable Acknowledge */
6960     hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK;
6961 
6962     /* Call the corresponding callback to inform upper layer of End of Transfer */
6963     FMPI2C_ITError(hfmpi2c, HAL_FMPI2C_ERROR_DMA);
6964   }
6965 }
6966 
6967 
6968 /**
6969   * @brief DMA FMPI2C communication abort callback
6970   *        (To be called at end of DMA Abort procedure).
6971   * @param hdma DMA handle.
6972   * @retval None
6973   */
FMPI2C_DMAAbort(DMA_HandleTypeDef * hdma)6974 static void FMPI2C_DMAAbort(DMA_HandleTypeDef *hdma)
6975 {
6976   /* Derogation MISRAC2012-Rule-11.5 */
6977   FMPI2C_HandleTypeDef *hfmpi2c = (FMPI2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
6978 
6979   /* Reset AbortCpltCallback */
6980   if (hfmpi2c->hdmatx != NULL)
6981   {
6982     hfmpi2c->hdmatx->XferAbortCallback = NULL;
6983   }
6984   if (hfmpi2c->hdmarx != NULL)
6985   {
6986     hfmpi2c->hdmarx->XferAbortCallback = NULL;
6987   }
6988 
6989   FMPI2C_TreatErrorCallback(hfmpi2c);
6990 }
6991 
6992 
6993 /**
6994   * @brief  This function handles FMPI2C Communication Timeout. It waits
6995   *                until a flag is no longer in the specified status.
6996   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
6997   *                the configuration information for the specified FMPI2C.
6998   * @param  Flag Specifies the FMPI2C flag to check.
6999   * @param  Status The actual Flag status (SET or RESET).
7000   * @param  Timeout Timeout duration
7001   * @param  Tickstart Tick start value
7002   * @retval HAL status
7003   */
FMPI2C_WaitOnFlagUntilTimeout(FMPI2C_HandleTypeDef * hfmpi2c,uint32_t Flag,FlagStatus Status,uint32_t Timeout,uint32_t Tickstart)7004 static HAL_StatusTypeDef FMPI2C_WaitOnFlagUntilTimeout(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t Flag, FlagStatus Status,
7005                                                        uint32_t Timeout, uint32_t Tickstart)
7006 {
7007   while (__HAL_FMPI2C_GET_FLAG(hfmpi2c, Flag) == Status)
7008   {
7009     /* Check if an error is detected */
7010     if (FMPI2C_IsErrorOccurred(hfmpi2c, Timeout, Tickstart) != HAL_OK)
7011     {
7012       return HAL_ERROR;
7013     }
7014 
7015     /* Check for the Timeout */
7016     if (Timeout != HAL_MAX_DELAY)
7017     {
7018       if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U))
7019       {
7020         if ((__HAL_FMPI2C_GET_FLAG(hfmpi2c, Flag) == Status))
7021         {
7022           hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_TIMEOUT;
7023           hfmpi2c->State = HAL_FMPI2C_STATE_READY;
7024           hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE;
7025 
7026           /* Process Unlocked */
7027           __HAL_UNLOCK(hfmpi2c);
7028           return HAL_ERROR;
7029         }
7030       }
7031     }
7032   }
7033   return HAL_OK;
7034 }
7035 
7036 /**
7037   * @brief  This function handles FMPI2C Communication Timeout for specific usage of TXIS flag.
7038   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
7039   *                the configuration information for the specified FMPI2C.
7040   * @param  Timeout Timeout duration
7041   * @param  Tickstart Tick start value
7042   * @retval HAL status
7043   */
FMPI2C_WaitOnTXISFlagUntilTimeout(FMPI2C_HandleTypeDef * hfmpi2c,uint32_t Timeout,uint32_t Tickstart)7044 static HAL_StatusTypeDef FMPI2C_WaitOnTXISFlagUntilTimeout(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t Timeout,
7045                                                            uint32_t Tickstart)
7046 {
7047   while (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_TXIS) == RESET)
7048   {
7049     /* Check if an error is detected */
7050     if (FMPI2C_IsErrorOccurred(hfmpi2c, Timeout, Tickstart) != HAL_OK)
7051     {
7052       return HAL_ERROR;
7053     }
7054 
7055     /* Check for the Timeout */
7056     if (Timeout != HAL_MAX_DELAY)
7057     {
7058       if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U))
7059       {
7060         if ((__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_TXIS) == RESET))
7061         {
7062           hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_TIMEOUT;
7063           hfmpi2c->State = HAL_FMPI2C_STATE_READY;
7064           hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE;
7065 
7066           /* Process Unlocked */
7067           __HAL_UNLOCK(hfmpi2c);
7068 
7069           return HAL_ERROR;
7070         }
7071       }
7072     }
7073   }
7074   return HAL_OK;
7075 }
7076 
7077 /**
7078   * @brief  This function handles FMPI2C Communication Timeout for specific usage of STOP flag.
7079   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
7080   *                the configuration information for the specified FMPI2C.
7081   * @param  Timeout Timeout duration
7082   * @param  Tickstart Tick start value
7083   * @retval HAL status
7084   */
FMPI2C_WaitOnSTOPFlagUntilTimeout(FMPI2C_HandleTypeDef * hfmpi2c,uint32_t Timeout,uint32_t Tickstart)7085 static HAL_StatusTypeDef FMPI2C_WaitOnSTOPFlagUntilTimeout(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t Timeout,
7086                                                            uint32_t Tickstart)
7087 {
7088   while (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF) == RESET)
7089   {
7090     /* Check if an error is detected */
7091     if (FMPI2C_IsErrorOccurred(hfmpi2c, Timeout, Tickstart) != HAL_OK)
7092     {
7093       return HAL_ERROR;
7094     }
7095 
7096     /* Check for the Timeout */
7097     if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U))
7098     {
7099       if ((__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF) == RESET))
7100       {
7101         hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_TIMEOUT;
7102         hfmpi2c->State = HAL_FMPI2C_STATE_READY;
7103         hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE;
7104 
7105         /* Process Unlocked */
7106         __HAL_UNLOCK(hfmpi2c);
7107 
7108         return HAL_ERROR;
7109       }
7110     }
7111   }
7112   return HAL_OK;
7113 }
7114 
7115 /**
7116   * @brief  This function handles FMPI2C Communication Timeout for specific usage of RXNE flag.
7117   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
7118   *                the configuration information for the specified FMPI2C.
7119   * @param  Timeout Timeout duration
7120   * @param  Tickstart Tick start value
7121   * @retval HAL status
7122   */
FMPI2C_WaitOnRXNEFlagUntilTimeout(FMPI2C_HandleTypeDef * hfmpi2c,uint32_t Timeout,uint32_t Tickstart)7123 static HAL_StatusTypeDef FMPI2C_WaitOnRXNEFlagUntilTimeout(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t Timeout,
7124                                                            uint32_t Tickstart)
7125 {
7126   HAL_StatusTypeDef status = HAL_OK;
7127 
7128   while ((__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_RXNE) == RESET) && (status == HAL_OK))
7129   {
7130     /* Check if an error is detected */
7131     if (FMPI2C_IsErrorOccurred(hfmpi2c, Timeout, Tickstart) != HAL_OK)
7132     {
7133       status = HAL_ERROR;
7134     }
7135 
7136     /* Check if a STOPF is detected */
7137     if ((__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF) == SET) && (status == HAL_OK))
7138     {
7139       /* Check if an RXNE is pending */
7140       /* Store Last receive data if any */
7141       if ((__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_RXNE) == SET) && (hfmpi2c->XferSize > 0U))
7142       {
7143         /* Return HAL_OK */
7144         /* The Reading of data from RXDR will be done in caller function */
7145         status = HAL_OK;
7146       }
7147 
7148       /* Check a no-acknowledge have been detected */
7149       if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_AF) == SET)
7150       {
7151         __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF);
7152         hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_AF;
7153 
7154         /* Clear STOP Flag */
7155         __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF);
7156 
7157         /* Clear Configuration Register 2 */
7158         FMPI2C_RESET_CR2(hfmpi2c);
7159 
7160         hfmpi2c->State = HAL_FMPI2C_STATE_READY;
7161         hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE;
7162 
7163         /* Process Unlocked */
7164         __HAL_UNLOCK(hfmpi2c);
7165 
7166         status = HAL_ERROR;
7167       }
7168       else
7169       {
7170         hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE;
7171       }
7172     }
7173 
7174     /* Check for the Timeout */
7175     if ((((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U)) && (status == HAL_OK))
7176     {
7177       if ((__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_RXNE) == RESET))
7178       {
7179         hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_TIMEOUT;
7180         hfmpi2c->State = HAL_FMPI2C_STATE_READY;
7181 
7182         /* Process Unlocked */
7183         __HAL_UNLOCK(hfmpi2c);
7184 
7185         status = HAL_ERROR;
7186       }
7187     }
7188   }
7189   return status;
7190 }
7191 
7192 /**
7193   * @brief  This function handles errors detection during an FMPI2C Communication.
7194   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
7195   *                the configuration information for the specified FMPI2C.
7196   * @param  Timeout Timeout duration
7197   * @param  Tickstart Tick start value
7198   * @retval HAL status
7199   */
FMPI2C_IsErrorOccurred(FMPI2C_HandleTypeDef * hfmpi2c,uint32_t Timeout,uint32_t Tickstart)7200 static HAL_StatusTypeDef FMPI2C_IsErrorOccurred(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t Timeout, uint32_t Tickstart)
7201 {
7202   HAL_StatusTypeDef status = HAL_OK;
7203   uint32_t itflag   = hfmpi2c->Instance->ISR;
7204   uint32_t error_code = 0;
7205   uint32_t tickstart = Tickstart;
7206   uint32_t tmp1;
7207   HAL_FMPI2C_ModeTypeDef tmp2;
7208 
7209   if (HAL_IS_BIT_SET(itflag, FMPI2C_FLAG_AF))
7210   {
7211     /* Clear NACKF Flag */
7212     __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF);
7213 
7214     /* Wait until STOP Flag is set or timeout occurred */
7215     /* AutoEnd should be initiate after AF */
7216     while ((__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF) == RESET) && (status == HAL_OK))
7217     {
7218       /* Check for the Timeout */
7219       if (Timeout != HAL_MAX_DELAY)
7220       {
7221         if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
7222         {
7223           tmp1 = (uint32_t)(hfmpi2c->Instance->CR2 & FMPI2C_CR2_STOP);
7224           tmp2 = hfmpi2c->Mode;
7225 
7226           /* In case of FMPI2C still busy, try to regenerate a STOP manually */
7227           if ((__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_BUSY) != RESET) && \
7228               (tmp1 != FMPI2C_CR2_STOP) && \
7229               (tmp2 != HAL_FMPI2C_MODE_SLAVE))
7230           {
7231             /* Generate Stop */
7232             hfmpi2c->Instance->CR2 |= FMPI2C_CR2_STOP;
7233 
7234             /* Update Tick with new reference */
7235             tickstart = HAL_GetTick();
7236           }
7237 
7238           while (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF) == RESET)
7239           {
7240             /* Check for the Timeout */
7241             if ((HAL_GetTick() - tickstart) > FMPI2C_TIMEOUT_STOPF)
7242             {
7243               error_code |= HAL_FMPI2C_ERROR_TIMEOUT;
7244 
7245               status = HAL_ERROR;
7246 
7247               break;
7248             }
7249           }
7250         }
7251       }
7252     }
7253 
7254     /* In case STOP Flag is detected, clear it */
7255     if (status == HAL_OK)
7256     {
7257       /* Clear STOP Flag */
7258       __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF);
7259     }
7260 
7261     error_code |= HAL_FMPI2C_ERROR_AF;
7262 
7263     status = HAL_ERROR;
7264   }
7265 
7266   /* Refresh Content of Status register */
7267   itflag = hfmpi2c->Instance->ISR;
7268 
7269   /* Then verify if an additional errors occurs */
7270   /* Check if a Bus error occurred */
7271   if (HAL_IS_BIT_SET(itflag, FMPI2C_FLAG_BERR))
7272   {
7273     error_code |= HAL_FMPI2C_ERROR_BERR;
7274 
7275     /* Clear BERR flag */
7276     __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_BERR);
7277 
7278     status = HAL_ERROR;
7279   }
7280 
7281   /* Check if an Over-Run/Under-Run error occurred */
7282   if (HAL_IS_BIT_SET(itflag, FMPI2C_FLAG_OVR))
7283   {
7284     error_code |= HAL_FMPI2C_ERROR_OVR;
7285 
7286     /* Clear OVR flag */
7287     __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_OVR);
7288 
7289     status = HAL_ERROR;
7290   }
7291 
7292   /* Check if an Arbitration Loss error occurred */
7293   if (HAL_IS_BIT_SET(itflag, FMPI2C_FLAG_ARLO))
7294   {
7295     error_code |= HAL_FMPI2C_ERROR_ARLO;
7296 
7297     /* Clear ARLO flag */
7298     __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_ARLO);
7299 
7300     status = HAL_ERROR;
7301   }
7302 
7303   if (status != HAL_OK)
7304   {
7305     /* Flush TX register */
7306     FMPI2C_Flush_TXDR(hfmpi2c);
7307 
7308     /* Clear Configuration Register 2 */
7309     FMPI2C_RESET_CR2(hfmpi2c);
7310 
7311     hfmpi2c->ErrorCode |= error_code;
7312     hfmpi2c->State = HAL_FMPI2C_STATE_READY;
7313     hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE;
7314 
7315     /* Process Unlocked */
7316     __HAL_UNLOCK(hfmpi2c);
7317   }
7318 
7319   return status;
7320 }
7321 
7322 /**
7323   * @brief  Handles FMPI2Cx communication when starting transfer or during transfer (TC or TCR flag are set).
7324   * @param  hfmpi2c FMPI2C handle.
7325   * @param  DevAddress Specifies the slave address to be programmed.
7326   * @param  Size Specifies the number of bytes to be programmed.
7327   *   This parameter must be a value between 0 and 255.
7328   * @param  Mode New state of the FMPI2C START condition generation.
7329   *   This parameter can be one of the following values:
7330   *     @arg @ref FMPI2C_RELOAD_MODE Enable Reload mode .
7331   *     @arg @ref FMPI2C_AUTOEND_MODE Enable Automatic end mode.
7332   *     @arg @ref FMPI2C_SOFTEND_MODE Enable Software end mode.
7333   * @param  Request New state of the FMPI2C START condition generation.
7334   *   This parameter can be one of the following values:
7335   *     @arg @ref FMPI2C_NO_STARTSTOP Don't Generate stop and start condition.
7336   *     @arg @ref FMPI2C_GENERATE_STOP Generate stop condition (Size should be set to 0).
7337   *     @arg @ref FMPI2C_GENERATE_START_READ Generate Restart for read request.
7338   *     @arg @ref FMPI2C_GENERATE_START_WRITE Generate Restart for write request.
7339   * @retval None
7340   */
FMPI2C_TransferConfig(FMPI2C_HandleTypeDef * hfmpi2c,uint16_t DevAddress,uint8_t Size,uint32_t Mode,uint32_t Request)7341 static void FMPI2C_TransferConfig(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t Size, uint32_t Mode,
7342                                   uint32_t Request)
7343 {
7344   /* Check the parameters */
7345   assert_param(IS_FMPI2C_ALL_INSTANCE(hfmpi2c->Instance));
7346   assert_param(IS_TRANSFER_MODE(Mode));
7347   assert_param(IS_TRANSFER_REQUEST(Request));
7348 
7349   /* Declaration of tmp to prevent undefined behavior of volatile usage */
7350   uint32_t tmp = ((uint32_t)(((uint32_t)DevAddress & FMPI2C_CR2_SADD) | \
7351                              (((uint32_t)Size << FMPI2C_CR2_NBYTES_Pos) & FMPI2C_CR2_NBYTES) | \
7352                              (uint32_t)Mode | (uint32_t)Request) & (~0x80000000U));
7353 
7354   /* update CR2 register */
7355   MODIFY_REG(hfmpi2c->Instance->CR2, \
7356              ((FMPI2C_CR2_SADD | FMPI2C_CR2_NBYTES | FMPI2C_CR2_RELOAD | FMPI2C_CR2_AUTOEND | \
7357                (FMPI2C_CR2_RD_WRN & (uint32_t)(Request >> (31U - FMPI2C_CR2_RD_WRN_Pos))) | \
7358                FMPI2C_CR2_START | FMPI2C_CR2_STOP)), tmp);
7359 }
7360 
7361 /**
7362   * @brief  Manage the enabling of Interrupts.
7363   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
7364   *                the configuration information for the specified FMPI2C.
7365   * @param  InterruptRequest Value of @ref FMPI2C_Interrupt_configuration_definition.
7366   * @retval None
7367   */
FMPI2C_Enable_IRQ(FMPI2C_HandleTypeDef * hfmpi2c,uint16_t InterruptRequest)7368 static void FMPI2C_Enable_IRQ(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t InterruptRequest)
7369 {
7370   uint32_t tmpisr = 0U;
7371 
7372   if ((hfmpi2c->XferISR != FMPI2C_Master_ISR_DMA) && \
7373       (hfmpi2c->XferISR != FMPI2C_Slave_ISR_DMA) && \
7374       (hfmpi2c->XferISR != FMPI2C_Mem_ISR_DMA))
7375   {
7376     if ((InterruptRequest & FMPI2C_XFER_LISTEN_IT) == FMPI2C_XFER_LISTEN_IT)
7377     {
7378       /* Enable ERR, STOP, NACK and ADDR interrupts */
7379       tmpisr |= FMPI2C_IT_ADDRI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI | FMPI2C_IT_ERRI;
7380     }
7381 
7382     if ((InterruptRequest & FMPI2C_XFER_TX_IT) == FMPI2C_XFER_TX_IT)
7383     {
7384       /* Enable ERR, TC, STOP, NACK and TXI interrupts */
7385       tmpisr |= FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI | FMPI2C_IT_TXI;
7386     }
7387 
7388     if ((InterruptRequest & FMPI2C_XFER_RX_IT) == FMPI2C_XFER_RX_IT)
7389     {
7390       /* Enable ERR, TC, STOP, NACK and RXI interrupts */
7391       tmpisr |= FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI | FMPI2C_IT_RXI;
7392     }
7393 
7394     if (InterruptRequest == FMPI2C_XFER_ERROR_IT)
7395     {
7396       /* Enable ERR and NACK interrupts */
7397       tmpisr |= FMPI2C_IT_ERRI | FMPI2C_IT_NACKI;
7398     }
7399 
7400     if (InterruptRequest == FMPI2C_XFER_CPLT_IT)
7401     {
7402       /* Enable STOP interrupts */
7403       tmpisr |= FMPI2C_IT_STOPI;
7404     }
7405   }
7406 
7407   else
7408   {
7409     if ((InterruptRequest & FMPI2C_XFER_LISTEN_IT) == FMPI2C_XFER_LISTEN_IT)
7410     {
7411       /* Enable ERR, STOP, NACK and ADDR interrupts */
7412       tmpisr |= FMPI2C_IT_ADDRI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI | FMPI2C_IT_ERRI;
7413     }
7414 
7415     if ((InterruptRequest & FMPI2C_XFER_TX_IT) == FMPI2C_XFER_TX_IT)
7416     {
7417       /* Enable ERR, TC, STOP, NACK and TXI interrupts */
7418       tmpisr |= FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI | FMPI2C_IT_TXI;
7419     }
7420 
7421     if ((InterruptRequest & FMPI2C_XFER_RX_IT) == FMPI2C_XFER_RX_IT)
7422     {
7423       /* Enable ERR, TC, STOP, NACK and RXI interrupts */
7424       tmpisr |= FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI | FMPI2C_IT_RXI;
7425     }
7426 
7427     if (InterruptRequest == FMPI2C_XFER_ERROR_IT)
7428     {
7429       /* Enable ERR and NACK interrupts */
7430       tmpisr |= FMPI2C_IT_ERRI | FMPI2C_IT_NACKI;
7431     }
7432 
7433     if (InterruptRequest == FMPI2C_XFER_CPLT_IT)
7434     {
7435       /* Enable STOP interrupts */
7436       tmpisr |= (FMPI2C_IT_STOPI | FMPI2C_IT_TCI);
7437     }
7438 
7439     if (InterruptRequest == FMPI2C_XFER_RELOAD_IT)
7440     {
7441       /* Enable TC interrupts */
7442       tmpisr |= FMPI2C_IT_TCI;
7443     }
7444   }
7445 
7446   /* Enable interrupts only at the end */
7447   /* to avoid the risk of FMPI2C interrupt handle execution before */
7448   /* all interrupts requested done */
7449   __HAL_FMPI2C_ENABLE_IT(hfmpi2c, tmpisr);
7450 }
7451 
7452 /**
7453   * @brief  Manage the disabling of Interrupts.
7454   * @param  hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains
7455   *                the configuration information for the specified FMPI2C.
7456   * @param  InterruptRequest Value of @ref FMPI2C_Interrupt_configuration_definition.
7457   * @retval None
7458   */
FMPI2C_Disable_IRQ(FMPI2C_HandleTypeDef * hfmpi2c,uint16_t InterruptRequest)7459 static void FMPI2C_Disable_IRQ(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t InterruptRequest)
7460 {
7461   uint32_t tmpisr = 0U;
7462 
7463   if ((InterruptRequest & FMPI2C_XFER_TX_IT) == FMPI2C_XFER_TX_IT)
7464   {
7465     /* Disable TC and TXI interrupts */
7466     tmpisr |= FMPI2C_IT_TCI | FMPI2C_IT_TXI;
7467 
7468     if (((uint32_t)hfmpi2c->State & (uint32_t)HAL_FMPI2C_STATE_LISTEN) != (uint32_t)HAL_FMPI2C_STATE_LISTEN)
7469     {
7470       /* Disable NACK and STOP interrupts */
7471       tmpisr |= FMPI2C_IT_STOPI | FMPI2C_IT_NACKI | FMPI2C_IT_ERRI;
7472     }
7473   }
7474 
7475   if ((InterruptRequest & FMPI2C_XFER_RX_IT) == FMPI2C_XFER_RX_IT)
7476   {
7477     /* Disable TC and RXI interrupts */
7478     tmpisr |= FMPI2C_IT_TCI | FMPI2C_IT_RXI;
7479 
7480     if (((uint32_t)hfmpi2c->State & (uint32_t)HAL_FMPI2C_STATE_LISTEN) != (uint32_t)HAL_FMPI2C_STATE_LISTEN)
7481     {
7482       /* Disable NACK and STOP interrupts */
7483       tmpisr |= FMPI2C_IT_STOPI | FMPI2C_IT_NACKI | FMPI2C_IT_ERRI;
7484     }
7485   }
7486 
7487   if ((InterruptRequest & FMPI2C_XFER_LISTEN_IT) == FMPI2C_XFER_LISTEN_IT)
7488   {
7489     /* Disable ADDR, NACK and STOP interrupts */
7490     tmpisr |= FMPI2C_IT_ADDRI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI | FMPI2C_IT_ERRI;
7491   }
7492 
7493   if (InterruptRequest == FMPI2C_XFER_ERROR_IT)
7494   {
7495     /* Enable ERR and NACK interrupts */
7496     tmpisr |= FMPI2C_IT_ERRI | FMPI2C_IT_NACKI;
7497   }
7498 
7499   if (InterruptRequest == FMPI2C_XFER_CPLT_IT)
7500   {
7501     /* Enable STOP interrupts */
7502     tmpisr |= FMPI2C_IT_STOPI;
7503   }
7504 
7505   if (InterruptRequest == FMPI2C_XFER_RELOAD_IT)
7506   {
7507     /* Enable TC interrupts */
7508     tmpisr |= FMPI2C_IT_TCI;
7509   }
7510 
7511   /* Disable interrupts only at the end */
7512   /* to avoid a breaking situation like at "t" time */
7513   /* all disable interrupts request are not done */
7514   __HAL_FMPI2C_DISABLE_IT(hfmpi2c, tmpisr);
7515 }
7516 
7517 /**
7518   * @brief  Convert FMPI2Cx OTHER_xxx XferOptions to functional XferOptions.
7519   * @param  hfmpi2c FMPI2C handle.
7520   * @retval None
7521   */
FMPI2C_ConvertOtherXferOptions(FMPI2C_HandleTypeDef * hfmpi2c)7522 static void FMPI2C_ConvertOtherXferOptions(FMPI2C_HandleTypeDef *hfmpi2c)
7523 {
7524   /* if user set XferOptions to FMPI2C_OTHER_FRAME            */
7525   /* it request implicitly to generate a restart condition */
7526   /* set XferOptions to FMPI2C_FIRST_FRAME                    */
7527   if (hfmpi2c->XferOptions == FMPI2C_OTHER_FRAME)
7528   {
7529     hfmpi2c->XferOptions = FMPI2C_FIRST_FRAME;
7530   }
7531   /* else if user set XferOptions to FMPI2C_OTHER_AND_LAST_FRAME */
7532   /* it request implicitly to generate a restart condition    */
7533   /* then generate a stop condition at the end of transfer    */
7534   /* set XferOptions to FMPI2C_FIRST_AND_LAST_FRAME              */
7535   else if (hfmpi2c->XferOptions == FMPI2C_OTHER_AND_LAST_FRAME)
7536   {
7537     hfmpi2c->XferOptions = FMPI2C_FIRST_AND_LAST_FRAME;
7538   }
7539   else
7540   {
7541     /* Nothing to do */
7542   }
7543 }
7544 
7545 /**
7546   * @}
7547   */
7548 
7549 #endif /* FMPI2C_CR1_PE */
7550 #endif /* HAL_FMPI2C_MODULE_ENABLED */
7551 /**
7552   * @}
7553   */
7554 
7555 /**
7556   * @}
7557   */
7558