• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2   ******************************************************************************
3   * @file    stm32mp1xx_hal_i2c.c
4   * @author  MCD Application Team
5   * @brief   I2C HAL module driver.
6   *          This file provides firmware functions to manage the following
7   *          functionalities of the Inter Integrated Circuit (I2C) peripheral:
8   *           + Initialization and de-initialization functions
9   *           + IO operation functions
10   *           + Peripheral State and Errors functions
11   *
12   @verbatim
13   ==============================================================================
14                         ##### How to use this driver #####
15   ==============================================================================
16     [..]
17     The I2C HAL driver can be used as follows:
18 
19     (#) Declare a I2C_HandleTypeDef handle structure, for example:
20         I2C_HandleTypeDef  hi2c;
21 
22     (#)Initialize the I2C low level resources by implementing the @ref HAL_I2C_MspInit() API:
23         (##) Enable the I2Cx interface clock
24         (##) I2C pins configuration
25             (+++) Enable the clock for the I2C GPIOs
26             (+++) Configure I2C pins as alternate function open-drain
27         (##) NVIC configuration if you need to use interrupt process
28             (+++) Configure the I2Cx interrupt priority
29             (+++) Enable the NVIC I2C IRQ Channel
30         (##) DMA Configuration if you need to use DMA process
31             (+++) Declare a DMA_HandleTypeDef handle structure for the transmit or receive stream
32             (+++) Enable the DMAx interface clock using
33             (+++) Configure the DMA handle parameters
34             (+++) Configure the DMA Tx or Rx stream
35             (+++) Associate the initialized DMA handle to the hi2c DMA Tx or Rx handle
36             (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on
37                   the DMA Tx or Rx stream
38 
39     (#) Configure the Communication Clock Timing, Own Address1, Master Addressing mode, Dual Addressing mode,
40         Own Address2, Own Address2 Mask, General call and Nostretch mode in the hi2c Init structure.
41 
42     (#) Initialize the I2C registers by calling the @ref HAL_I2C_Init(), configures also the low level Hardware
43         (GPIO, CLOCK, NVIC...etc) by calling the customized @ref HAL_I2C_MspInit(&hi2c) API.
44 
45     (#) To check if target device is ready for communication, use the function @ref HAL_I2C_IsDeviceReady()
46 
47     (#) For I2C IO and IO MEM operations, three operation modes are available within this driver :
48 
49     *** Polling mode IO operation ***
50     =================================
51     [..]
52       (+) Transmit in master mode an amount of data in blocking mode using @ref HAL_I2C_Master_Transmit()
53       (+) Receive in master mode an amount of data in blocking mode using @ref HAL_I2C_Master_Receive()
54       (+) Transmit in slave mode an amount of data in blocking mode using @ref HAL_I2C_Slave_Transmit()
55       (+) Receive in slave mode an amount of data in blocking mode using @ref HAL_I2C_Slave_Receive()
56 
57     *** Polling mode IO MEM operation ***
58     =====================================
59     [..]
60       (+) Write an amount of data in blocking mode to a specific memory address using @ref HAL_I2C_Mem_Write()
61       (+) Read an amount of data in blocking mode from a specific memory address using @ref HAL_I2C_Mem_Read()
62 
63 
64     *** Interrupt mode IO operation ***
65     ===================================
66     [..]
67       (+) Transmit in master mode an amount of data in non-blocking mode using @ref HAL_I2C_Master_Transmit_IT()
68       (+) At transmission end of transfer, @ref HAL_I2C_MasterTxCpltCallback() is executed and user can
69            add his own code by customization of function pointer @ref HAL_I2C_MasterTxCpltCallback()
70       (+) Receive in master mode an amount of data in non-blocking mode using @ref HAL_I2C_Master_Receive_IT()
71       (+) At reception end of transfer, @ref HAL_I2C_MasterRxCpltCallback() is executed and user can
72            add his own code by customization of function pointer @ref HAL_I2C_MasterRxCpltCallback()
73       (+) Transmit in slave mode an amount of data in non-blocking mode using @ref HAL_I2C_Slave_Transmit_IT()
74       (+) At transmission end of transfer, @ref HAL_I2C_SlaveTxCpltCallback() is executed and user can
75            add his own code by customization of function pointer @ref HAL_I2C_SlaveTxCpltCallback()
76       (+) Receive in slave mode an amount of data in non-blocking mode using @ref HAL_I2C_Slave_Receive_IT()
77       (+) At reception end of transfer, @ref HAL_I2C_SlaveRxCpltCallback() is executed and user can
78            add his own code by customization of function pointer @ref HAL_I2C_SlaveRxCpltCallback()
79       (+) In case of transfer Error, @ref HAL_I2C_ErrorCallback() function is executed and user can
80            add his own code by customization of function pointer @ref HAL_I2C_ErrorCallback()
81       (+) Abort a master I2C process communication with Interrupt using @ref HAL_I2C_Master_Abort_IT()
82       (+) End of abort process, @ref HAL_I2C_AbortCpltCallback() is executed and user can
83            add his own code by customization of function pointer @ref HAL_I2C_AbortCpltCallback()
84       (+) Discard a slave I2C process communication using @ref __HAL_I2C_GENERATE_NACK() macro.
85            This action will inform Master to generate a Stop condition to discard the communication.
86 
87 
88     *** Interrupt mode or DMA mode IO sequential operation ***
89     ==========================================================
90     [..]
91       (@) These interfaces allow to manage a sequential transfer with a repeated start condition
92           when a direction change during transfer
93     [..]
94       (+) A specific option field manage the different steps of a sequential transfer
95       (+) Option field values are defined through @ref I2C_XFEROPTIONS and are listed below:
96       (++) I2C_FIRST_AND_LAST_FRAME: No sequential usage, functionnal is same as associated interfaces in no sequential mode
97       (++) I2C_FIRST_FRAME: Sequential usage, this option allow to manage a sequence with start condition, address
98                             and data to transfer without a final stop condition
99       (++) I2C_FIRST_AND_NEXT_FRAME: Sequential usage (Master only), this option allow to manage a sequence with start condition, address
100                             and data to transfer without a final stop condition, an then permit a call the same master sequential interface
101                             several times (like @ref HAL_I2C_Master_Seq_Transmit_IT() then @ref HAL_I2C_Master_Seq_Transmit_IT()
102                             or @ref HAL_I2C_Master_Seq_Transmit_DMA() then @ref HAL_I2C_Master_Seq_Transmit_DMA())
103       (++) I2C_NEXT_FRAME: Sequential usage, this option allow to manage a sequence with a restart condition, address
104                             and with new data to transfer if the direction change or manage only the new data to transfer
105                             if no direction change and without a final stop condition in both cases
106       (++) I2C_LAST_FRAME: Sequential usage, this option allow to manage a sequance with a restart condition, address
107                             and with new data to transfer if the direction change or manage only the new data to transfer
108                             if no direction change and with a final stop condition in both cases
109       (++) I2C_LAST_FRAME_NO_STOP: Sequential usage (Master only), this option allow to manage a restart condition after several call of the same master sequential
110                             interface several times (link with option I2C_FIRST_AND_NEXT_FRAME).
111                             Usage can, transfer several bytes one by one using HAL_I2C_Master_Seq_Transmit_IT(option I2C_FIRST_AND_NEXT_FRAME then I2C_NEXT_FRAME)
112                               or HAL_I2C_Master_Seq_Receive_IT(option I2C_FIRST_AND_NEXT_FRAME then I2C_NEXT_FRAME)
113                               or HAL_I2C_Master_Seq_Transmit_DMA(option I2C_FIRST_AND_NEXT_FRAME then I2C_NEXT_FRAME)
114                               or HAL_I2C_Master_Seq_Receive_DMA(option I2C_FIRST_AND_NEXT_FRAME then I2C_NEXT_FRAME).
115                             Then usage of this option I2C_LAST_FRAME_NO_STOP at the last Transmit or Receive sequence permit to call the oposite interface Receive or Transmit
116                               without stopping the communication and so generate a restart condition.
117       (++) I2C_OTHER_FRAME: Sequential usage (Master only), this option allow to manage a restart condition after each call of the same master sequential
118                             interface.
119                             Usage can, transfer several bytes one by one with a restart with slave address between each bytes using HAL_I2C_Master_Seq_Transmit_IT(option I2C_FIRST_FRAME then I2C_OTHER_FRAME)
120                               or HAL_I2C_Master_Seq_Receive_IT(option I2C_FIRST_FRAME then I2C_OTHER_FRAME)
121                               or HAL_I2C_Master_Seq_Transmit_DMA(option I2C_FIRST_FRAME then I2C_OTHER_FRAME)
122                               or HAL_I2C_Master_Seq_Receive_DMA(option I2C_FIRST_FRAME then I2C_OTHER_FRAME).
123                             Then usage of this option I2C_OTHER_AND_LAST_FRAME at the last frame to help automatic generation of STOP condition.
124 
125       (+) Differents sequential I2C interfaces are listed below:
126       (++) Sequential transmit in master I2C mode an amount of data in non-blocking mode using @ref HAL_I2C_Master_Seq_Transmit_IT()
127             or using @ref HAL_I2C_Master_Seq_Transmit_DMA()
128       (+++) At transmission end of current frame transfer, @ref HAL_I2C_MasterTxCpltCallback() is executed and user can
129            add his own code by customization of function pointer @ref HAL_I2C_MasterTxCpltCallback()
130       (++) Sequential receive in master I2C mode an amount of data in non-blocking mode using @ref HAL_I2C_Master_Seq_Receive_IT()
131             or using @ref HAL_I2C_Master_Seq_Receive_DMA()
132       (+++) At reception end of current frame transfer, @ref HAL_I2C_MasterRxCpltCallback() is executed and user can
133            add his own code by customization of function pointer @ref HAL_I2C_MasterRxCpltCallback()
134       (++) Abort a master IT or DMA I2C process communication with Interrupt using @ref HAL_I2C_Master_Abort_IT()
135       (+++) End of abort process, @ref HAL_I2C_AbortCpltCallback() is executed and user can
136            add his own code by customization of function pointer @ref HAL_I2C_AbortCpltCallback()
137       (++) Enable/disable the Address listen mode in slave I2C mode using @ref HAL_I2C_EnableListen_IT() @ref HAL_I2C_DisableListen_IT()
138       (+++) When address slave I2C match, @ref HAL_I2C_AddrCallback() is executed and user can
139            add his own code to check the Address Match Code and the transmission direction request by master (Write/Read).
140       (+++) At Listen mode end @ref HAL_I2C_ListenCpltCallback() is executed and user can
141            add his own code by customization of function pointer @ref HAL_I2C_ListenCpltCallback()
142       (++) Sequential transmit in slave I2C mode an amount of data in non-blocking mode using @ref HAL_I2C_Slave_Seq_Transmit_IT()
143             or using @ref HAL_I2C_Slave_Seq_Transmit_DMA()
144       (+++) At transmission end of current frame transfer, @ref HAL_I2C_SlaveTxCpltCallback() is executed and user can
145            add his own code by customization of function pointer @ref HAL_I2C_SlaveTxCpltCallback()
146       (++) Sequential receive in slave I2C mode an amount of data in non-blocking mode using @ref HAL_I2C_Slave_Seq_Receive_IT()
147             or using @ref HAL_I2C_Slave_Seq_Receive_DMA()
148       (+++) At reception end of current frame transfer, @ref HAL_I2C_SlaveRxCpltCallback() is executed and user can
149            add his own code by customization of function pointer @ref HAL_I2C_SlaveRxCpltCallback()
150       (++) In case of transfer Error, @ref HAL_I2C_ErrorCallback() function is executed and user can
151            add his own code by customization of function pointer @ref HAL_I2C_ErrorCallback()
152       (++) Discard a slave I2C process communication using @ref __HAL_I2C_GENERATE_NACK() macro.
153            This action will inform Master to generate a Stop condition to discard the communication.
154 
155     *** Interrupt mode IO MEM operation ***
156     =======================================
157     [..]
158       (+) Write an amount of data in non-blocking mode with Interrupt to a specific memory address using
159           @ref HAL_I2C_Mem_Write_IT()
160       (+) At Memory end of write transfer, @ref HAL_I2C_MemTxCpltCallback() is executed and user can
161            add his own code by customization of function pointer @ref HAL_I2C_MemTxCpltCallback()
162       (+) Read an amount of data in non-blocking mode with Interrupt from a specific memory address using
163           @ref HAL_I2C_Mem_Read_IT()
164       (+) At Memory end of read transfer, @ref HAL_I2C_MemRxCpltCallback() is executed and user can
165            add his own code by customization of function pointer @ref HAL_I2C_MemRxCpltCallback()
166       (+) In case of transfer Error, @ref HAL_I2C_ErrorCallback() function is executed and user can
167            add his own code by customization of function pointer @ref HAL_I2C_ErrorCallback()
168 
169     *** DMA mode IO operation ***
170     ==============================
171     [..]
172       (+) Transmit in master mode an amount of data in non-blocking mode (DMA) using
173           @ref HAL_I2C_Master_Transmit_DMA()
174       (+) At transmission end of transfer, @ref HAL_I2C_MasterTxCpltCallback() is executed and user can
175            add his own code by customization of function pointer @ref HAL_I2C_MasterTxCpltCallback()
176       (+) Receive in master mode an amount of data in non-blocking mode (DMA) using
177           @ref HAL_I2C_Master_Receive_DMA()
178       (+) At reception end of transfer, @ref HAL_I2C_MasterRxCpltCallback() is executed and user can
179            add his own code by customization of function pointer @ref HAL_I2C_MasterRxCpltCallback()
180       (+) Transmit in slave mode an amount of data in non-blocking mode (DMA) using
181           @ref HAL_I2C_Slave_Transmit_DMA()
182       (+) At transmission end of transfer, @ref HAL_I2C_SlaveTxCpltCallback() is executed and user can
183            add his own code by customization of function pointer @ref HAL_I2C_SlaveTxCpltCallback()
184       (+) Receive in slave mode an amount of data in non-blocking mode (DMA) using
185           @ref HAL_I2C_Slave_Receive_DMA()
186       (+) At reception end of transfer, @ref HAL_I2C_SlaveRxCpltCallback() is executed and user can
187            add his own code by customization of function pointer @ref HAL_I2C_SlaveRxCpltCallback()
188       (+) In case of transfer Error, @ref HAL_I2C_ErrorCallback() function is executed and user can
189            add his own code by customization of function pointer @ref HAL_I2C_ErrorCallback()
190       (+) Abort a master I2C process communication with Interrupt using @ref HAL_I2C_Master_Abort_IT()
191       (+) End of abort process, @ref HAL_I2C_AbortCpltCallback() is executed and user can
192            add his own code by customization of function pointer @ref HAL_I2C_AbortCpltCallback()
193       (+) Discard a slave I2C process communication using @ref __HAL_I2C_GENERATE_NACK() macro.
194            This action will inform Master to generate a Stop condition to discard the communication.
195 
196     *** DMA mode IO MEM operation ***
197     =================================
198     [..]
199       (+) Write an amount of data in non-blocking mode with DMA to a specific memory address using
200           @ref HAL_I2C_Mem_Write_DMA()
201       (+) At Memory end of write transfer, @ref HAL_I2C_MemTxCpltCallback() is executed and user can
202            add his own code by customization of function pointer @ref HAL_I2C_MemTxCpltCallback()
203       (+) Read an amount of data in non-blocking mode with DMA from a specific memory address using
204           @ref HAL_I2C_Mem_Read_DMA()
205       (+) At Memory end of read transfer, @ref HAL_I2C_MemRxCpltCallback() is executed and user can
206            add his own code by customization of function pointer @ref HAL_I2C_MemRxCpltCallback()
207       (+) In case of transfer Error, @ref HAL_I2C_ErrorCallback() function is executed and user can
208            add his own code by customization of function pointer @ref HAL_I2C_ErrorCallback()
209 
210 
211      *** I2C HAL driver macros list ***
212      ==================================
213      [..]
214        Below the list of most used macros in I2C HAL driver.
215 
216       (+) @ref __HAL_I2C_ENABLE: Enable the I2C peripheral
217       (+) @ref __HAL_I2C_DISABLE: Disable the I2C peripheral
218       (+) @ref __HAL_I2C_GENERATE_NACK: Generate a Non-Acknowledge I2C peripheral in Slave mode
219       (+) @ref __HAL_I2C_GET_FLAG: Check whether the specified I2C flag is set or not
220       (+) @ref __HAL_I2C_CLEAR_FLAG: Clear the specified I2C pending flag
221       (+) @ref __HAL_I2C_ENABLE_IT: Enable the specified I2C interrupt
222       (+) @ref __HAL_I2C_DISABLE_IT: Disable the specified I2C interrupt
223 
224      *** Callback registration ***
225      =============================================
226     [..]
227      The compilation flag USE_HAL_I2C_REGISTER_CALLBACKS when set to 1
228      allows the user to configure dynamically the driver callbacks.
229      Use Functions @ref HAL_I2C_RegisterCallback() or @ref HAL_I2C_RegisterAddrCallback()
230      to register an interrupt callback.
231     [..]
232      Function @ref HAL_I2C_RegisterCallback() allows to register following callbacks:
233        (+) MasterTxCpltCallback : callback for Master transmission end of transfer.
234        (+) MasterRxCpltCallback : callback for Master reception end of transfer.
235        (+) SlaveTxCpltCallback  : callback for Slave transmission end of transfer.
236        (+) SlaveRxCpltCallback  : callback for Slave reception end of transfer.
237        (+) ListenCpltCallback   : callback for end of listen mode.
238        (+) MemTxCpltCallback    : callback for Memory transmission end of transfer.
239        (+) MemRxCpltCallback    : callback for Memory reception end of transfer.
240        (+) ErrorCallback        : callback for error detection.
241        (+) AbortCpltCallback    : callback for abort completion process.
242        (+) MspInitCallback      : callback for Msp Init.
243        (+) MspDeInitCallback    : callback for Msp DeInit.
244      This function takes as parameters the HAL peripheral handle, the Callback ID
245      and a pointer to the user callback function.
246     [..]
247      For specific callback AddrCallback use dedicated register callbacks : @ref HAL_I2C_RegisterAddrCallback().
248     [..]
249      Use function @ref HAL_I2C_UnRegisterCallback to reset a callback to the default
250      weak function.
251      @ref HAL_I2C_UnRegisterCallback takes as parameters the HAL peripheral handle,
252      and the Callback ID.
253      This function allows to reset following callbacks:
254        (+) MasterTxCpltCallback : callback for Master transmission end of transfer.
255        (+) MasterRxCpltCallback : callback for Master reception end of transfer.
256        (+) SlaveTxCpltCallback  : callback for Slave transmission end of transfer.
257        (+) SlaveRxCpltCallback  : callback for Slave reception end of transfer.
258        (+) ListenCpltCallback   : callback for end of listen mode.
259        (+) MemTxCpltCallback    : callback for Memory transmission end of transfer.
260        (+) MemRxCpltCallback    : callback for Memory reception end of transfer.
261        (+) ErrorCallback        : callback for error detection.
262        (+) AbortCpltCallback    : callback for abort completion process.
263        (+) MspInitCallback      : callback for Msp Init.
264        (+) MspDeInitCallback    : callback for Msp DeInit.
265     [..]
266      For callback AddrCallback use dedicated register callbacks : @ref HAL_I2C_UnRegisterAddrCallback().
267     [..]
268      By default, after the @ref HAL_I2C_Init() and when the state is @ref HAL_I2C_STATE_RESET
269      all callbacks are set to the corresponding weak functions:
270      examples @ref HAL_I2C_MasterTxCpltCallback(), @ref HAL_I2C_MasterRxCpltCallback().
271      Exception done for MspInit and MspDeInit functions that are
272      reset to the legacy weak functions in the @ref HAL_I2C_Init()/ @ref HAL_I2C_DeInit() only when
273      these callbacks are null (not registered beforehand).
274      If MspInit or MspDeInit are not null, the @ref HAL_I2C_Init()/ @ref HAL_I2C_DeInit()
275      keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state.
276     [..]
277      Callbacks can be registered/unregistered in @ref HAL_I2C_STATE_READY state only.
278      Exception done MspInit/MspDeInit functions that can be registered/unregistered
279      in @ref HAL_I2C_STATE_READY or @ref HAL_I2C_STATE_RESET state,
280      thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit.
281      Then, the user first registers the MspInit/MspDeInit user callbacks
282      using @ref HAL_I2C_RegisterCallback() before calling @ref HAL_I2C_DeInit()
283      or @ref HAL_I2C_Init() function.
284     [..]
285      When the compilation flag USE_HAL_I2C_REGISTER_CALLBACKS is set to 0 or
286      not defined, the callback registration feature is not available and all callbacks
287      are set to the corresponding weak functions.
288 
289      [..]
290        (@) You can refer to the I2C HAL driver header file for more useful macros
291 
292   @endverbatim
293   ******************************************************************************
294   * @attention
295   *
296   * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
297   * All rights reserved.</center></h2>
298   *
299   * This software component is licensed by ST under BSD 3-Clause license,
300   * the "License"; You may not use this file except in compliance with the
301   * License. You may obtain a copy of the License at:
302   *                        opensource.org/licenses/BSD-3-Clause
303   *
304   ******************************************************************************
305   */
306 
307 /* Includes ------------------------------------------------------------------*/
308 #include "stm32mp1xx_hal.h"
309 #include "los_sys.h"
310 
311 /* Private typedef -----------------------------------------------------------*/
312 /* Private define ------------------------------------------------------------*/
313 
314 /** @defgroup I2C_Private_Define I2C Private Define
315   * @{
316   */
317 #define TIMING_CLEAR_MASK   (0xF0FFFFFFU)  /*!< I2C TIMING clear register Mask */
318 #define I2C_TIMEOUT_ADDR    (10000U)       /*!< 10 s  */
319 #define I2C_TIMEOUT_BUSY    (25U)          /*!< 25 ms */
320 #define I2C_TIMEOUT_DIR     (25U)          /*!< 25 ms */
321 #define I2C_TIMEOUT_RXNE    (25U)          /*!< 25 ms */
322 #define I2C_TIMEOUT_STOPF   (25U)          /*!< 25 ms */
323 #define I2C_TIMEOUT_TC      (25U)          /*!< 25 ms */
324 #define I2C_TIMEOUT_TCR     (25U)          /*!< 25 ms */
325 #define I2C_TIMEOUT_TXIS    (25U)          /*!< 25 ms */
326 #define I2C_TIMEOUT_FLAG    (25U)          /*!< 25 ms */
327 
328 #define MAX_NBYTE_SIZE      255U
329 #define SlaveAddr_SHIFT     7U
330 #define SlaveAddr_MSK       0x06U
331 
332 /* Private define for @ref PreviousState usage */
333 #define I2C_STATE_MSK             ((uint32_t)((uint32_t)((uint32_t)HAL_I2C_STATE_BUSY_TX | (uint32_t)HAL_I2C_STATE_BUSY_RX) & (uint32_t)(~((uint32_t)HAL_I2C_STATE_READY)))) /*!< Mask State define, keep only RX and TX bits            */
334 #define I2C_STATE_NONE            ((uint32_t)(HAL_I2C_MODE_NONE))                                                        /*!< Default Value                                          */
335 #define I2C_STATE_MASTER_BUSY_TX  ((uint32_t)(((uint32_t)HAL_I2C_STATE_BUSY_TX & I2C_STATE_MSK) | (uint32_t)HAL_I2C_MODE_MASTER))            /*!< Master Busy TX, combinaison of State LSB and Mode enum */
336 #define I2C_STATE_MASTER_BUSY_RX  ((uint32_t)(((uint32_t)HAL_I2C_STATE_BUSY_RX & I2C_STATE_MSK) | (uint32_t)HAL_I2C_MODE_MASTER))            /*!< Master Busy RX, combinaison of State LSB and Mode enum */
337 #define I2C_STATE_SLAVE_BUSY_TX   ((uint32_t)(((uint32_t)HAL_I2C_STATE_BUSY_TX & I2C_STATE_MSK) | (uint32_t)HAL_I2C_MODE_SLAVE))             /*!< Slave Busy TX, combinaison of State LSB and Mode enum  */
338 #define I2C_STATE_SLAVE_BUSY_RX   ((uint32_t)(((uint32_t)HAL_I2C_STATE_BUSY_RX & I2C_STATE_MSK) | (uint32_t)HAL_I2C_MODE_SLAVE))             /*!< Slave Busy RX, combinaison of State LSB and Mode enum  */
339 #define I2C_STATE_MEM_BUSY_TX     ((uint32_t)(((uint32_t)HAL_I2C_STATE_BUSY_TX & I2C_STATE_MSK) | (uint32_t)HAL_I2C_MODE_MEM))               /*!< Memory Busy TX, combinaison of State LSB and Mode enum */
340 #define I2C_STATE_MEM_BUSY_RX     ((uint32_t)(((uint32_t)HAL_I2C_STATE_BUSY_RX & I2C_STATE_MSK) | (uint32_t)HAL_I2C_MODE_MEM))               /*!< Memory Busy RX, combinaison of State LSB and Mode enum */
341 
342 
343 /* Private define to centralize the enable/disable of Interrupts */
344 #define I2C_XFER_TX_IT          (0x00000001U)
345 #define I2C_XFER_RX_IT          (0x00000002U)
346 #define I2C_XFER_LISTEN_IT      (0x00000004U)
347 
348 #define I2C_XFER_ERROR_IT       (0x00000011U)
349 #define I2C_XFER_CPLT_IT        (0x00000012U)
350 #define I2C_XFER_RELOAD_IT      (0x00000012U)
351 
352 /* Private define Sequential Transfer Options default/reset value */
353 #define I2C_NO_OPTION_FRAME     (0xFFFF0000U)
354 /**
355   * @}
356   */
357 /**
358   * @brief  Initializes the I2C according to the specified parameters
359   *         in the I2C_InitTypeDef and initialize the associated handle.
360   * @param  hi2c Pointer to a I2C_HandleTypeDef structure that contains
361   *                the configuration information for the specified I2C.
362   * @retval HAL status
363   */
HAL_I2C_Init(I2C_HandleTypeDef * hi2c)364 HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c)
365 {
366   /* Check the I2C handle allocation */
367   if (hi2c == NULL)
368   {
369     return HAL_ERROR;
370   }
371 
372 
373   if (hi2c->State == HAL_I2C_STATE_RESET)
374   {
375     /* Allocate lock resource and initialize it */
376     hi2c->Lock = HAL_UNLOCKED;
377   }
378 
379   hi2c->State = HAL_I2C_STATE_BUSY;
380 
381   /* Disable the selected I2C peripheral */
382   __HAL_I2C_DISABLE(hi2c);
383 
384   /*---------------------------- I2Cx TIMINGR Configuration ------------------*/
385   /* Configure I2Cx: Frequency range */
386   hi2c->Instance->TIMINGR = hi2c->Init.Timing & TIMING_CLEAR_MASK;
387 
388   /*---------------------------- I2Cx OAR1 Configuration ---------------------*/
389   /* Disable Own Address1 before set the Own Address1 configuration */
390   hi2c->Instance->OAR1 &= ~I2C_OAR1_OA1EN;
391 
392   /* Configure I2Cx: Own Address1 and ack own address1 mode */
393   if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_7BIT)
394   {
395     hi2c->Instance->OAR1 = (I2C_OAR1_OA1EN | hi2c->Init.OwnAddress1);
396   }
397   else /* I2C_ADDRESSINGMODE_10BIT */
398   {
399     hi2c->Instance->OAR1 = (I2C_OAR1_OA1EN | I2C_OAR1_OA1MODE | hi2c->Init.OwnAddress1);
400   }
401 
402   /*---------------------------- I2Cx CR2 Configuration ----------------------*/
403   /* Configure I2Cx: Addressing Master mode */
404   if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_10BIT)
405   {
406     hi2c->Instance->CR2 = (I2C_CR2_ADD10);
407   }
408   /* Enable the AUTOEND by default, and enable NACK (should be disable only during Slave process */
409   hi2c->Instance->CR2 |= (I2C_CR2_AUTOEND | I2C_CR2_NACK);
410 
411   /*---------------------------- I2Cx OAR2 Configuration ---------------------*/
412   /* Disable Own Address2 before set the Own Address2 configuration */
413   hi2c->Instance->OAR2 &= ~I2C_DUALADDRESS_ENABLE;
414 
415   /* Configure I2Cx: Dual mode and Own Address2 */
416   hi2c->Instance->OAR2 = (hi2c->Init.DualAddressMode | hi2c->Init.OwnAddress2 | (hi2c->Init.OwnAddress2Masks << 8));
417 
418   /*---------------------------- I2Cx CR1 Configuration ----------------------*/
419   /* Configure I2Cx: Generalcall and NoStretch mode */
420   hi2c->Instance->CR1 = (hi2c->Init.GeneralCallMode | hi2c->Init.NoStretchMode);
421 
422   /* Enable the selected I2C peripheral */
423   __HAL_I2C_ENABLE(hi2c);
424 
425   hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
426   hi2c->State = HAL_I2C_STATE_READY;
427   hi2c->PreviousState = I2C_STATE_NONE;
428   hi2c->Mode = HAL_I2C_MODE_NONE;
429 
430   return HAL_OK;
431 }
432 
433 /**
434   * @brief  DeInitialize the I2C peripheral.
435   * @param  hi2c Pointer to a I2C_HandleTypeDef structure that contains
436   *                the configuration information for the specified I2C.
437   * @retval HAL status
438   */
HAL_I2C_DeInit(I2C_HandleTypeDef * hi2c)439 HAL_StatusTypeDef HAL_I2C_DeInit(I2C_HandleTypeDef *hi2c)
440 {
441   /* Check the I2C handle allocation */
442   if (hi2c == NULL)
443   {
444     return HAL_ERROR;
445   }
446 
447   hi2c->State = HAL_I2C_STATE_BUSY;
448 
449   /* Disable the I2C Peripheral Clock */
450   __HAL_I2C_DISABLE(hi2c);
451 
452   hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
453   hi2c->State = HAL_I2C_STATE_RESET;
454   hi2c->PreviousState = I2C_STATE_NONE;
455   hi2c->Mode = HAL_I2C_MODE_NONE;
456 
457   /* Release Lock */
458   __HAL_UNLOCK(hi2c);
459 
460   return HAL_OK;
461 }
462 
463 /**
464   * @brief  I2C Tx data register flush process.
465   * @param  hi2c I2C handle.
466   * @retval None
467   */
I2C_Flush_TXDR(I2C_HandleTypeDef * hi2c)468 static void I2C_Flush_TXDR(I2C_HandleTypeDef *hi2c)
469 {
470   /* If a pending TXIS flag is set */
471   /* Write a dummy data in TXDR to clear it */
472   if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXIS) != RESET)
473   {
474     hi2c->Instance->TXDR = 0x00U;
475   }
476 
477   /* Flush TX register if not empty */
478   if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXE) == RESET)
479   {
480     __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_TXE);
481   }
482 }
483 
484 /**
485   * @brief  This function handles Acknowledge failed detection during an I2C Communication.
486   * @param  hi2c Pointer to a I2C_HandleTypeDef structure that contains
487   *                the configuration information for the specified I2C.
488   * @param  Timeout Timeout duration
489   * @param  Tickstart Tick start value
490   * @retval HAL status
491   */
I2C_IsAcknowledgeFailed(I2C_HandleTypeDef * hi2c,uint32_t Timeout,uint32_t Tickstart)492 static HAL_StatusTypeDef I2C_IsAcknowledgeFailed(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart)
493 {
494   if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET)
495   {
496     /* Wait until STOP Flag is reset */
497     /* AutoEnd should be initiate after AF */
498     while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET)
499     {
500       /* Check for the Timeout */
501       if (Timeout != HAL_MAX_DELAY)
502       {
503         if (((LOS_TickCountGet() - Tickstart) > Timeout) || (Timeout == 0U))
504         {
505           hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
506           hi2c->State = HAL_I2C_STATE_READY;
507           hi2c->Mode = HAL_I2C_MODE_NONE;
508 
509           /* Process Unlocked */
510           __HAL_UNLOCK(hi2c);
511 
512           return HAL_ERROR;
513         }
514       }
515     }
516 
517     /* Clear NACKF Flag */
518     __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
519 
520     /* Clear STOP Flag */
521     __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
522 
523     /* Flush TX register */
524     I2C_Flush_TXDR(hi2c);
525 
526     /* Clear Configuration Register 2 */
527     I2C_RESET_CR2(hi2c);
528 
529     hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
530     hi2c->State = HAL_I2C_STATE_READY;
531     hi2c->Mode = HAL_I2C_MODE_NONE;
532 
533     /* Process Unlocked */
534     __HAL_UNLOCK(hi2c);
535 
536     return HAL_ERROR;
537   }
538   return HAL_OK;
539 }
540 
541 /**
542   * @brief  Handles I2Cx communication when starting transfer or during transfer (TC or TCR flag are set).
543   * @param  hi2c I2C handle.
544   * @param  DevAddress Specifies the slave address to be programmed.
545   * @param  Size Specifies the number of bytes to be programmed.
546   *   This parameter must be a value between 0 and 255.
547   * @param  Mode New state of the I2C START condition generation.
548   *   This parameter can be one of the following values:
549   *     @arg @ref I2C_RELOAD_MODE Enable Reload mode .
550   *     @arg @ref I2C_AUTOEND_MODE Enable Automatic end mode.
551   *     @arg @ref I2C_SOFTEND_MODE Enable Software end mode.
552   * @param  Request New state of the I2C START condition generation.
553   *   This parameter can be one of the following values:
554   *     @arg @ref I2C_NO_STARTSTOP Don't Generate stop and start condition.
555   *     @arg @ref I2C_GENERATE_STOP Generate stop condition (Size should be set to 0).
556   *     @arg @ref I2C_GENERATE_START_READ Generate Restart for read request.
557   *     @arg @ref I2C_GENERATE_START_WRITE Generate Restart for write request.
558   * @retval None
559   */
I2C_TransferConfig(I2C_HandleTypeDef * hi2c,uint16_t DevAddress,uint8_t Size,uint32_t Mode,uint32_t Request)560 static void I2C_TransferConfig(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t Size, uint32_t Mode, uint32_t Request)
561 {
562   /* update CR2 register */
563   MODIFY_REG(hi2c->Instance->CR2, ((I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_AUTOEND | (I2C_CR2_RD_WRN & (uint32_t)(Request >> (31U - I2C_CR2_RD_WRN_Pos))) | I2C_CR2_START | I2C_CR2_STOP)), \
564              (uint32_t)(((uint32_t)DevAddress & I2C_CR2_SADD) | (((uint32_t)Size << I2C_CR2_NBYTES_Pos) & I2C_CR2_NBYTES) | (uint32_t)Mode | (uint32_t)Request));
565 }
566 
567 /**
568   * @brief  This function handles I2C Communication Timeout.
569   * @param  hi2c Pointer to a I2C_HandleTypeDef structure that contains
570   *                the configuration information for the specified I2C.
571   * @param  Flag Specifies the I2C flag to check.
572   * @param  Status The new Flag status (SET or RESET).
573   * @param  Timeout Timeout duration
574   * @param  Tickstart Tick start value
575   * @retval HAL status
576   */
I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef * hi2c,uint32_t Flag,FlagStatus Status,uint32_t Timeout,uint32_t Tickstart)577 static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, FlagStatus Status, uint32_t Timeout, uint32_t Tickstart)
578 {
579   while (__HAL_I2C_GET_FLAG(hi2c, Flag) == Status)
580   {
581     /* Check for the Timeout */
582     if (Timeout != HAL_MAX_DELAY)
583     {
584       if (((LOS_TickCountGet() - Tickstart) > Timeout) || (Timeout == 0U))
585       {
586         hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
587         hi2c->State = HAL_I2C_STATE_READY;
588         hi2c->Mode = HAL_I2C_MODE_NONE;
589 
590         /* Process Unlocked */
591         __HAL_UNLOCK(hi2c);
592         return HAL_ERROR;
593       }
594     }
595   }
596   return HAL_OK;
597 }
598 
599 /**
600   * @brief  This function handles I2C Communication Timeout for specific usage of TXIS flag.
601   * @param  hi2c Pointer to a I2C_HandleTypeDef structure that contains
602   *                the configuration information for the specified I2C.
603   * @param  Timeout Timeout duration
604   * @param  Tickstart Tick start value
605   * @retval HAL status
606   */
I2C_WaitOnTXISFlagUntilTimeout(I2C_HandleTypeDef * hi2c,uint32_t Timeout,uint32_t Tickstart)607 static HAL_StatusTypeDef I2C_WaitOnTXISFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart)
608 {
609   while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXIS) == RESET)
610   {
611     /* Check if a NACK is detected */
612     if (I2C_IsAcknowledgeFailed(hi2c, Timeout, Tickstart) != HAL_OK)
613     {
614       return HAL_ERROR;
615     }
616 
617     /* Check for the Timeout */
618     if (Timeout != HAL_MAX_DELAY)
619     {
620       if (((LOS_TickCountGet() - Tickstart) > Timeout) || (Timeout == 0U))
621       {
622         hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
623         hi2c->State = HAL_I2C_STATE_READY;
624         hi2c->Mode = HAL_I2C_MODE_NONE;
625         /* Process Unlocked */
626         __HAL_UNLOCK(hi2c);
627 
628         return HAL_ERROR;
629       }
630     }
631   }
632   return HAL_OK;
633 }
634 
635 /**
636   * @brief  This function handles I2C Communication Timeout for specific usage of STOP flag.
637   * @param  hi2c Pointer to a I2C_HandleTypeDef structure that contains
638   *                the configuration information for the specified I2C.
639   * @param  Timeout Timeout duration
640   * @param  Tickstart Tick start value
641   * @retval HAL status
642   */
I2C_WaitOnSTOPFlagUntilTimeout(I2C_HandleTypeDef * hi2c,uint32_t Timeout,uint32_t Tickstart)643 static HAL_StatusTypeDef I2C_WaitOnSTOPFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart)
644 {
645   while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET)
646   {
647     /* Check if a NACK is detected */
648     if (I2C_IsAcknowledgeFailed(hi2c, Timeout, Tickstart) != HAL_OK)
649     {
650       return HAL_ERROR;
651     }
652 
653     /* Check for the Timeout */
654     if (((LOS_TickCountGet() - Tickstart) > Timeout) || (Timeout == 0U))
655     {
656       hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
657       hi2c->State = HAL_I2C_STATE_READY;
658       hi2c->Mode = HAL_I2C_MODE_NONE;
659 
660       /* Process Unlocked */
661       __HAL_UNLOCK(hi2c);
662 
663       return HAL_ERROR;
664     }
665   }
666   return HAL_OK;
667 }
668 
669 /**
670   * @brief  This function handles I2C Communication Timeout for specific usage of RXNE flag.
671   * @param  hi2c Pointer to a I2C_HandleTypeDef structure that contains
672   *                the configuration information for the specified I2C.
673   * @param  Timeout Timeout duration
674   * @param  Tickstart Tick start value
675   * @retval HAL status
676   */
I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef * hi2c,uint32_t Timeout,uint32_t Tickstart)677 static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart)
678 {
679   while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == RESET)
680   {
681     /* Check if a NACK is detected */
682     if (I2C_IsAcknowledgeFailed(hi2c, Timeout, Tickstart) != HAL_OK)
683     {
684       return HAL_ERROR;
685     }
686 
687     /* Check if a STOPF is detected */
688     if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == SET)
689     {
690       /* Check if an RXNE is pending */
691       /* Store Last receive data if any */
692       if ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET) && (hi2c->XferSize > 0U))
693       {
694         /* Return HAL_OK */
695         /* The Reading of data from RXDR will be done in caller function */
696         return HAL_OK;
697       }
698       else
699       {
700         /* Clear STOP Flag */
701         __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
702 
703         /* Clear Configuration Register 2 */
704         I2C_RESET_CR2(hi2c);
705 
706         hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
707         hi2c->State = HAL_I2C_STATE_READY;
708         hi2c->Mode = HAL_I2C_MODE_NONE;
709 
710         /* Process Unlocked */
711         __HAL_UNLOCK(hi2c);
712 
713         return HAL_ERROR;
714       }
715     }
716 
717     /* Check for the Timeout */
718     if (((LOS_TickCountGet() - Tickstart) > Timeout) || (Timeout == 0U))
719     {
720       hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
721       hi2c->State = HAL_I2C_STATE_READY;
722 
723       /* Process Unlocked */
724       __HAL_UNLOCK(hi2c);
725 
726       return HAL_ERROR;
727     }
728   }
729   return HAL_OK;
730 }
731 
732 /**
733   * @brief  Transmits in master mode an amount of data in blocking mode.
734   * @param  hi2c Pointer to a I2C_HandleTypeDef structure that contains
735   *                the configuration information for the specified I2C.
736   * @param  DevAddress Target device address: The device 7 bits address value
737   *         in datasheet must be shifted to the left before calling the interface
738   * @param  pData Pointer to data buffer
739   * @param  Size Amount of data to be sent
740   * @param  Timeout Timeout duration
741   * @retval HAL status
742   */
HAL_I2C_Master_Transmit(I2C_HandleTypeDef * hi2c,uint16_t DevAddress,uint8_t * pData,uint16_t Size,uint32_t Timeout)743 HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)
744 {
745     uint32_t tickstart;
746 
747     if (hi2c->State == HAL_I2C_STATE_READY)
748     {
749       if(hi2c == NULL)
750       {
751           return -1;
752       }
753       /* Process Locked */
754       __HAL_LOCK(hi2c);
755 
756       /* Init tickstart for timeout management*/
757       tickstart = LOS_TickCountGet();
758 
759       if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY, tickstart) != HAL_OK)
760       {
761         return HAL_ERROR;
762       }
763 
764       hi2c->State     = HAL_I2C_STATE_BUSY_TX;
765       hi2c->Mode      = HAL_I2C_MODE_MASTER;
766       hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
767 
768       /* Prepare transfer parameters */
769       hi2c->pBuffPtr  = pData;
770       hi2c->XferCount = Size;
771       hi2c->XferISR   = NULL;
772 
773       /* Send Slave Address */
774       /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
775       if (hi2c->XferCount > MAX_NBYTE_SIZE)
776       {
777         hi2c->XferSize = MAX_NBYTE_SIZE;
778         I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_RELOAD_MODE, I2C_GENERATE_START_WRITE);
779       }
780       else
781       {
782         hi2c->XferSize = hi2c->XferCount;
783         I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_WRITE);
784       }
785       while (hi2c->XferCount > 0U)
786       {
787           /* Wait until TXIS flag is set */
788           if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
789           {
790               return HAL_ERROR;
791           }
792           /* Write data to TXDR */
793           hi2c->Instance->TXDR = *hi2c->pBuffPtr;
794 
795           /* Increment Buffer pointer */
796           hi2c->pBuffPtr++;
797 
798           hi2c->XferCount--;
799           hi2c->XferSize--;
800 
801           if ((hi2c->XferCount != 0U) && (hi2c->XferSize == 0U))
802           {
803               /* Wait until TCR flag is set */
804               if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK)
805               {
806                   return HAL_ERROR;
807               }
808 
809 
810               if (hi2c->XferCount > MAX_NBYTE_SIZE)
811               {
812                   hi2c->XferSize = MAX_NBYTE_SIZE;
813                   I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
814               }
815               else
816               {
817                   hi2c->XferSize = hi2c->XferCount;
818                   I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
819               }
820           }
821       }
822       /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
823       /* Wait until STOPF flag is set */
824       if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
825       {
826         return HAL_ERROR;
827       }
828 
829       /* Clear STOP Flag */
830       __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
831 
832       /* Clear Configuration Register 2 */
833       I2C_RESET_CR2(hi2c);
834 
835       hi2c->State = HAL_I2C_STATE_READY;
836       hi2c->Mode  = HAL_I2C_MODE_NONE;
837 
838       /* Process Unlocked */
839       __HAL_UNLOCK(hi2c);
840 
841       return HAL_OK;
842   }
843   else
844   {
845     return HAL_BUSY;
846   }
847 }
848 
HAL_I2C_Master_Receive(I2C_HandleTypeDef * hi2c,uint16_t DevAddress,uint8_t * pData,uint16_t Size,uint32_t Timeout)849 HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)
850 {
851   uint32_t tickstart;
852 
853   if (hi2c->State == HAL_I2C_STATE_READY)
854   {
855     /* Process Locked */
856     __HAL_LOCK(hi2c);
857 
858     /* Init tickstart for timeout management*/
859     tickstart = LOS_TickCountGet();
860 
861     if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY, tickstart) != HAL_OK)
862     {
863       return HAL_ERROR;
864     }
865 
866     hi2c->State     = HAL_I2C_STATE_BUSY_RX;
867     hi2c->Mode      = HAL_I2C_MODE_MASTER;
868     hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
869 
870     /* Prepare transfer parameters */
871     hi2c->pBuffPtr  = pData;
872     hi2c->XferCount = Size;
873     hi2c->XferISR   = NULL;
874 
875     /* Send Slave Address */
876     /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
877     if (hi2c->XferCount > MAX_NBYTE_SIZE)
878     {
879       hi2c->XferSize = MAX_NBYTE_SIZE;
880       I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_RELOAD_MODE, I2C_GENERATE_START_READ);
881     }
882     else
883     {
884       hi2c->XferSize = hi2c->XferCount;
885       I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_READ);
886     }
887     while (hi2c->XferCount > 0U)
888     {
889         /* Wait until RXNE flag is set */
890         if (I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
891         {
892             return HAL_ERROR;
893         }
894 
895         /* Read data from RXDR */
896         *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->RXDR;
897 
898         /* Increment Buffer pointer */
899         hi2c->pBuffPtr++;
900 
901         hi2c->XferSize--;
902         hi2c->XferCount--;
903 
904         if ((hi2c->XferCount != 0U) && (hi2c->XferSize == 0U))
905         {
906             /* Wait until TCR flag is set */
907             if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK)
908             {
909                 return HAL_ERROR;
910             }
911 
912             if (hi2c->XferCount > MAX_NBYTE_SIZE)
913             {
914                 hi2c->XferSize = MAX_NBYTE_SIZE;
915                 I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
916             }
917             else
918             {
919                 hi2c->XferSize = hi2c->XferCount;
920                 I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
921             }
922         }
923     }
924 
925     /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
926     /* Wait until STOPF flag is set */
927     if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
928     {
929       return HAL_ERROR;
930     }
931 
932     /* Clear STOP Flag */
933     __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
934 
935     /* Clear Configuration Register 2 */
936     I2C_RESET_CR2(hi2c);
937 
938     hi2c->State = HAL_I2C_STATE_READY;
939     hi2c->Mode  = HAL_I2C_MODE_NONE;
940 
941     /* Process Unlocked */
942     __HAL_UNLOCK(hi2c);
943 
944     return HAL_OK;
945   }
946   else
947   {
948     return HAL_BUSY;
949   }
950 }
951 
952 /**
953   * @}
954   */
955 
956 /**
957   * @}
958   */
959 
960 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
961