1 /**
2   ******************************************************************************
3   * @file    stm32h5xx_hal_smbus.c
4   * @author  MCD Application Team
5   * @brief   SMBUS HAL module driver.
6   *          This file provides firmware functions to manage the following
7   *          functionalities of the System Management Bus (SMBus) peripheral,
8   *          based on I2C principles of operation :
9   *           + Initialization and de-initialization functions
10   *           + IO operation functions
11   *           + Peripheral State and Errors functions
12   *
13   ******************************************************************************
14   * @attention
15   *
16   * Copyright (c) 2022 STMicroelectronics.
17   * All rights reserved.
18   *
19   * This software is licensed under terms that can be found in the LICENSE file
20   * in the root directory of this software component.
21   * If no LICENSE file comes with this software, it is provided AS-IS.
22   *
23   ******************************************************************************
24   @verbatim
25   ==============================================================================
26                         ##### How to use this driver #####
27   ==============================================================================
28     [..]
29     The SMBUS HAL driver can be used as follows:
30 
31     (#) Declare a SMBUS_HandleTypeDef handle structure, for example:
32         SMBUS_HandleTypeDef  hsmbus;
33 
34     (#)Initialize the SMBUS low level resources by implementing the HAL_SMBUS_MspInit() API:
35         (##) Enable the SMBUSx interface clock
36         (##) SMBUS pins configuration
37             (+++) Enable the clock for the SMBUS GPIOs
38             (+++) Configure SMBUS pins as alternate function open-drain
39         (##) NVIC configuration if you need to use interrupt process
40             (+++) Configure the SMBUSx interrupt priority
41             (+++) Enable the NVIC SMBUS IRQ Channel
42 
43     (#) Configure the Communication Clock Timing, Bus Timeout, Own Address1, Master Addressing mode,
44         Dual Addressing mode, Own Address2, Own Address2 Mask, General call, Nostretch mode,
45         Peripheral mode and Packet Error Check mode in the hsmbus Init structure.
46 
47     (#) Initialize the SMBUS registers by calling the HAL_SMBUS_Init() API:
48         (++) These API's configures also the low level Hardware GPIO, CLOCK, CORTEX...etc)
49              by calling the customized HAL_SMBUS_MspInit(&hsmbus) API.
50 
51     (#) To check if target device is ready for communication, use the function HAL_SMBUS_IsDeviceReady()
52 
53     (#) For SMBUS IO operations, only one mode of operations is available within this driver
54 
55     *** Interrupt mode IO operation ***
56     ===================================
57     [..]
58       (+) Transmit in master/host SMBUS mode an amount of data in non-blocking mode
59           using HAL_SMBUS_Master_Transmit_IT()
60       (++) At transmission end of transfer HAL_SMBUS_MasterTxCpltCallback() is executed and users can
61            add their own code by customization of function pointer HAL_SMBUS_MasterTxCpltCallback()
62       (+) Receive in master/host SMBUS mode an amount of data in non-blocking mode
63           using HAL_SMBUS_Master_Receive_IT()
64       (++) At reception end of transfer HAL_SMBUS_MasterRxCpltCallback() is executed and users can
65            add their own code by customization of function pointer HAL_SMBUS_MasterRxCpltCallback()
66       (+) Abort a master/host SMBUS process communication with Interrupt using HAL_SMBUS_Master_Abort_IT()
67       (++) The associated previous transfer callback is called at the end of abort process
68       (++) mean HAL_SMBUS_MasterTxCpltCallback() in case of previous state was master transmit
69       (++) mean HAL_SMBUS_MasterRxCpltCallback() in case of previous state was master receive
70       (+) Enable/disable the Address listen mode in slave/device or host/slave SMBUS mode
71            using HAL_SMBUS_EnableListen_IT() HAL_SMBUS_DisableListen_IT()
72       (++) When address slave/device SMBUS match, HAL_SMBUS_AddrCallback() is executed and users can
73            add their own code to check the Address Match Code and the transmission direction
74            request by master/host (Write/Read).
75       (++) At Listen mode end HAL_SMBUS_ListenCpltCallback() is executed and users can
76            add their own code by customization of function pointer HAL_SMBUS_ListenCpltCallback()
77       (+) Transmit in slave/device SMBUS mode an amount of data in non-blocking mode
78           using HAL_SMBUS_Slave_Transmit_IT()
79       (++) At transmission end of transfer HAL_SMBUS_SlaveTxCpltCallback() is executed and users can
80            add their own code by customization of function pointer HAL_SMBUS_SlaveTxCpltCallback()
81       (+) Receive in slave/device SMBUS mode an amount of data in non-blocking mode
82           using HAL_SMBUS_Slave_Receive_IT()
83       (++) At reception end of transfer HAL_SMBUS_SlaveRxCpltCallback() is executed and users can
84            add their own code by customization of function pointer HAL_SMBUS_SlaveRxCpltCallback()
85       (+) Enable/Disable the SMBUS alert mode using
86           HAL_SMBUS_EnableAlert_IT() or HAL_SMBUS_DisableAlert_IT()
87       (++) When SMBUS Alert is generated HAL_SMBUS_ErrorCallback() is executed and users can
88            add their own code by customization of function pointer HAL_SMBUS_ErrorCallback()
89            to check the Alert Error Code using function HAL_SMBUS_GetError()
90       (+) Get HAL state machine or error values using HAL_SMBUS_GetState() or HAL_SMBUS_GetError()
91       (+) In case of transfer Error, HAL_SMBUS_ErrorCallback() function is executed and users can
92            add their own code by customization of function pointer HAL_SMBUS_ErrorCallback()
93            to check the Error Code using function HAL_SMBUS_GetError()
94 
95      *** SMBUS HAL driver macros list ***
96      ==================================
97      [..]
98        Below the list of most used macros in SMBUS HAL driver.
99 
100       (+) __HAL_SMBUS_ENABLE:      Enable the SMBUS peripheral
101       (+) __HAL_SMBUS_DISABLE:     Disable the SMBUS peripheral
102       (+) __HAL_SMBUS_GET_FLAG:    Check whether the specified SMBUS flag is set or not
103       (+) __HAL_SMBUS_CLEAR_FLAG:  Clear the specified SMBUS pending flag
104       (+) __HAL_SMBUS_ENABLE_IT:   Enable the specified SMBUS interrupt
105       (+) __HAL_SMBUS_DISABLE_IT:  Disable the specified SMBUS interrupt
106 
107      *** Callback registration ***
108      =============================================
109     [..]
110      The compilation flag USE_HAL_SMBUS_REGISTER_CALLBACKS when set to 1
111      allows the user to configure dynamically the driver callbacks.
112      Use Functions HAL_SMBUS_RegisterCallback() or HAL_SMBUS_RegisterAddrCallback()
113      to register an interrupt callback.
114     [..]
115      Function HAL_SMBUS_RegisterCallback() allows to register following callbacks:
116        (+) MasterTxCpltCallback : callback for Master transmission end of transfer.
117        (+) MasterRxCpltCallback : callback for Master reception end of transfer.
118        (+) SlaveTxCpltCallback  : callback for Slave transmission end of transfer.
119        (+) SlaveRxCpltCallback  : callback for Slave reception end of transfer.
120        (+) ListenCpltCallback   : callback for end of listen mode.
121        (+) ErrorCallback        : callback for error detection.
122        (+) MspInitCallback      : callback for Msp Init.
123        (+) MspDeInitCallback    : callback for Msp DeInit.
124      This function takes as parameters the HAL peripheral handle, the Callback ID
125      and a pointer to the user callback function.
126     [..]
127      For specific callback AddrCallback use dedicated register callbacks : HAL_SMBUS_RegisterAddrCallback.
128     [..]
129      Use function HAL_SMBUS_UnRegisterCallback to reset a callback to the default
130      weak function.
131      HAL_SMBUS_UnRegisterCallback takes as parameters the HAL peripheral handle,
132      and the Callback ID.
133      This function allows to reset following callbacks:
134        (+) MasterTxCpltCallback : callback for Master transmission end of transfer.
135        (+) MasterRxCpltCallback : callback for Master reception end of transfer.
136        (+) SlaveTxCpltCallback  : callback for Slave transmission end of transfer.
137        (+) SlaveRxCpltCallback  : callback for Slave reception end of transfer.
138        (+) ListenCpltCallback   : callback for end of listen mode.
139        (+) ErrorCallback        : callback for error detection.
140        (+) MspInitCallback      : callback for Msp Init.
141        (+) MspDeInitCallback    : callback for Msp DeInit.
142     [..]
143      For callback AddrCallback use dedicated register callbacks : HAL_SMBUS_UnRegisterAddrCallback.
144     [..]
145      By default, after the HAL_SMBUS_Init() and when the state is HAL_I2C_STATE_RESET
146      all callbacks are set to the corresponding weak functions:
147      examples HAL_SMBUS_MasterTxCpltCallback(), HAL_SMBUS_MasterRxCpltCallback().
148      Exception done for MspInit and MspDeInit functions that are
149      reset to the legacy weak functions in the HAL_SMBUS_Init()/ HAL_SMBUS_DeInit() only when
150      these callbacks are null (not registered beforehand).
151      If MspInit or MspDeInit are not null, the HAL_SMBUS_Init()/ HAL_SMBUS_DeInit()
152      keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state.
153     [..]
154      Callbacks can be registered/unregistered in HAL_I2C_STATE_READY state only.
155      Exception done MspInit/MspDeInit functions that can be registered/unregistered
156      in HAL_I2C_STATE_READY or HAL_I2C_STATE_RESET state,
157      thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit.
158      Then, the user first registers the MspInit/MspDeInit user callbacks
159      using HAL_SMBUS_RegisterCallback() before calling HAL_SMBUS_DeInit()
160      or HAL_SMBUS_Init() function.
161     [..]
162      When the compilation flag USE_HAL_SMBUS_REGISTER_CALLBACKS is set to 0 or
163      not defined, the callback registration feature is not available and all callbacks
164      are set to the corresponding weak functions.
165 
166      [..]
167        (@) You can refer to the SMBUS HAL driver header file for more useful macros
168 
169   @endverbatim
170   */
171 
172 /* Includes ------------------------------------------------------------------*/
173 #include "stm32h5xx_hal.h"
174 
175 /** @addtogroup STM32H5xx_HAL_Driver
176   * @{
177   */
178 
179 /** @defgroup SMBUS SMBUS
180   * @brief SMBUS HAL module driver
181   * @{
182   */
183 
184 #ifdef HAL_SMBUS_MODULE_ENABLED
185 
186 /* Private typedef -----------------------------------------------------------*/
187 /* Private constants ---------------------------------------------------------*/
188 /** @defgroup SMBUS_Private_Define SMBUS Private Constants
189   * @{
190   */
191 #define TIMING_CLEAR_MASK   (0xF0FFFFFFUL)     /*!< SMBUS TIMING clear register Mask */
192 #define HAL_TIMEOUT_ADDR    (10000U)           /*!< 10 s  */
193 #define HAL_TIMEOUT_BUSY    (25U)              /*!< 25 ms */
194 #define HAL_TIMEOUT_DIR     (25U)              /*!< 25 ms */
195 #define HAL_TIMEOUT_RXNE    (25U)              /*!< 25 ms */
196 #define HAL_TIMEOUT_STOPF   (25U)              /*!< 25 ms */
197 #define HAL_TIMEOUT_TC      (25U)              /*!< 25 ms */
198 #define HAL_TIMEOUT_TCR     (25U)              /*!< 25 ms */
199 #define HAL_TIMEOUT_TXIS    (25U)              /*!< 25 ms */
200 #define MAX_NBYTE_SIZE      255U
201 /**
202   * @}
203   */
204 
205 /* Private macro -------------------------------------------------------------*/
206 /* Private variables ---------------------------------------------------------*/
207 /* Private function prototypes -----------------------------------------------*/
208 /** @addtogroup SMBUS_Private_Functions SMBUS Private Functions
209   * @{
210   */
211 /* Private functions to handle flags during polling transfer */
212 static HAL_StatusTypeDef SMBUS_WaitOnFlagUntilTimeout(SMBUS_HandleTypeDef *hsmbus, uint32_t Flag,
213                                                       FlagStatus Status, uint32_t Timeout);
214 
215 /* Private functions for SMBUS transfer IRQ handler */
216 static HAL_StatusTypeDef SMBUS_Master_ISR(SMBUS_HandleTypeDef *hsmbus, uint32_t StatusFlags);
217 static HAL_StatusTypeDef SMBUS_Slave_ISR(SMBUS_HandleTypeDef *hsmbus, uint32_t StatusFlags);
218 static void SMBUS_ITErrorHandler(SMBUS_HandleTypeDef *hsmbus);
219 
220 /* Private functions to centralize the enable/disable of Interrupts */
221 static void SMBUS_Enable_IRQ(SMBUS_HandleTypeDef *hsmbus, uint32_t InterruptRequest);
222 static void SMBUS_Disable_IRQ(SMBUS_HandleTypeDef *hsmbus, uint32_t InterruptRequest);
223 
224 /* Private function to flush TXDR register */
225 static void SMBUS_Flush_TXDR(SMBUS_HandleTypeDef *hsmbus);
226 
227 /* Private function to handle start, restart or stop a transfer */
228 static void SMBUS_TransferConfig(SMBUS_HandleTypeDef *hsmbus,  uint16_t DevAddress, uint8_t Size,
229                                  uint32_t Mode, uint32_t Request);
230 
231 /* Private function to Convert Specific options */
232 static void SMBUS_ConvertOtherXferOptions(SMBUS_HandleTypeDef *hsmbus);
233 /**
234   * @}
235   */
236 
237 /* Exported functions --------------------------------------------------------*/
238 
239 /** @defgroup SMBUS_Exported_Functions SMBUS Exported Functions
240   * @{
241   */
242 
243 /** @defgroup SMBUS_Exported_Functions_Group1 Initialization and de-initialization functions
244   *  @brief    Initialization and Configuration functions
245   *
246 @verbatim
247  ===============================================================================
248               ##### Initialization and de-initialization functions #####
249  ===============================================================================
250     [..]  This subsection provides a set of functions allowing to initialize and
251           deinitialize the SMBUSx peripheral:
252 
253       (+) User must Implement HAL_SMBUS_MspInit() function in which he configures
254           all related peripherals resources (CLOCK, GPIO, IT and NVIC ).
255 
256       (+) Call the function HAL_SMBUS_Init() to configure the selected device with
257           the selected configuration:
258         (++) Clock Timing
259         (++) Bus Timeout
260         (++) Analog Filer mode
261         (++) Own Address 1
262         (++) Addressing mode (Master, Slave)
263         (++) Dual Addressing mode
264         (++) Own Address 2
265         (++) Own Address 2 Mask
266         (++) General call mode
267         (++) Nostretch mode
268         (++) Packet Error Check mode
269         (++) Peripheral mode
270 
271 
272       (+) Call the function HAL_SMBUS_DeInit() to restore the default configuration
273           of the selected SMBUSx peripheral.
274 
275       (+) Enable/Disable Analog/Digital filters with HAL_SMBUS_ConfigAnalogFilter() and
276           HAL_SMBUS_ConfigDigitalFilter().
277 
278 @endverbatim
279   * @{
280   */
281 
282 /**
283   * @brief  Initialize the SMBUS according to the specified parameters
284   *         in the SMBUS_InitTypeDef and initialize the associated handle.
285   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
286   *                the configuration information for the specified SMBUS.
287   * @retval HAL status
288   */
HAL_SMBUS_Init(SMBUS_HandleTypeDef * hsmbus)289 HAL_StatusTypeDef HAL_SMBUS_Init(SMBUS_HandleTypeDef *hsmbus)
290 {
291   /* Check the SMBUS handle allocation */
292   if (hsmbus == NULL)
293   {
294     return HAL_ERROR;
295   }
296 
297   /* Check the parameters */
298   assert_param(IS_SMBUS_ALL_INSTANCE(hsmbus->Instance));
299   assert_param(IS_SMBUS_ANALOG_FILTER(hsmbus->Init.AnalogFilter));
300   assert_param(IS_SMBUS_OWN_ADDRESS1(hsmbus->Init.OwnAddress1));
301   assert_param(IS_SMBUS_ADDRESSING_MODE(hsmbus->Init.AddressingMode));
302   assert_param(IS_SMBUS_DUAL_ADDRESS(hsmbus->Init.DualAddressMode));
303   assert_param(IS_SMBUS_OWN_ADDRESS2(hsmbus->Init.OwnAddress2));
304   assert_param(IS_SMBUS_OWN_ADDRESS2_MASK(hsmbus->Init.OwnAddress2Masks));
305   assert_param(IS_SMBUS_GENERAL_CALL(hsmbus->Init.GeneralCallMode));
306   assert_param(IS_SMBUS_NO_STRETCH(hsmbus->Init.NoStretchMode));
307   assert_param(IS_SMBUS_PEC(hsmbus->Init.PacketErrorCheckMode));
308   assert_param(IS_SMBUS_PERIPHERAL_MODE(hsmbus->Init.PeripheralMode));
309 
310   if (hsmbus->State == HAL_SMBUS_STATE_RESET)
311   {
312     /* Allocate lock resource and initialize it */
313     hsmbus->Lock = HAL_UNLOCKED;
314 
315 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
316     hsmbus->MasterTxCpltCallback = HAL_SMBUS_MasterTxCpltCallback; /* Legacy weak MasterTxCpltCallback */
317     hsmbus->MasterRxCpltCallback = HAL_SMBUS_MasterRxCpltCallback; /* Legacy weak MasterRxCpltCallback */
318     hsmbus->SlaveTxCpltCallback  = HAL_SMBUS_SlaveTxCpltCallback;  /* Legacy weak SlaveTxCpltCallback  */
319     hsmbus->SlaveRxCpltCallback  = HAL_SMBUS_SlaveRxCpltCallback;  /* Legacy weak SlaveRxCpltCallback  */
320     hsmbus->ListenCpltCallback   = HAL_SMBUS_ListenCpltCallback;   /* Legacy weak ListenCpltCallback   */
321     hsmbus->ErrorCallback        = HAL_SMBUS_ErrorCallback;        /* Legacy weak ErrorCallback        */
322     hsmbus->AddrCallback         = HAL_SMBUS_AddrCallback;         /* Legacy weak AddrCallback         */
323 
324     if (hsmbus->MspInitCallback == NULL)
325     {
326       hsmbus->MspInitCallback = HAL_SMBUS_MspInit; /* Legacy weak MspInit  */
327     }
328 
329     /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */
330     hsmbus->MspInitCallback(hsmbus);
331 #else
332     /* Init the low level hardware : GPIO, CLOCK, NVIC */
333     HAL_SMBUS_MspInit(hsmbus);
334 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
335   }
336 
337   hsmbus->State = HAL_SMBUS_STATE_BUSY;
338 
339   /* Disable the selected SMBUS peripheral */
340   __HAL_SMBUS_DISABLE(hsmbus);
341 
342   /*---------------------------- SMBUSx TIMINGR Configuration ------------------------*/
343   /* Configure SMBUSx: Frequency range */
344   hsmbus->Instance->TIMINGR = hsmbus->Init.Timing & TIMING_CLEAR_MASK;
345 
346   /*---------------------------- SMBUSx TIMEOUTR Configuration ------------------------*/
347   /* Configure SMBUSx: Bus Timeout  */
348   hsmbus->Instance->TIMEOUTR &= ~I2C_TIMEOUTR_TIMOUTEN;
349   hsmbus->Instance->TIMEOUTR &= ~I2C_TIMEOUTR_TEXTEN;
350   hsmbus->Instance->TIMEOUTR = hsmbus->Init.SMBusTimeout;
351 
352   /*---------------------------- SMBUSx OAR1 Configuration -----------------------*/
353   /* Configure SMBUSx: Own Address1 and ack own address1 mode */
354   hsmbus->Instance->OAR1 &= ~I2C_OAR1_OA1EN;
355 
356   if (hsmbus->Init.OwnAddress1 != 0UL)
357   {
358     if (hsmbus->Init.AddressingMode == SMBUS_ADDRESSINGMODE_7BIT)
359     {
360       hsmbus->Instance->OAR1 = (I2C_OAR1_OA1EN | hsmbus->Init.OwnAddress1);
361     }
362   }
363 
364   /*---------------------------- SMBUSx CR2 Configuration ------------------------*/
365   /* Enable the AUTOEND by default, and enable NACK (should be disable only during Slave process) */
366   /* AUTOEND and NACK bit will be manage during Transfer process */
367   hsmbus->Instance->CR2 |= (I2C_CR2_AUTOEND | I2C_CR2_NACK);
368 
369   /*---------------------------- SMBUSx OAR2 Configuration -----------------------*/
370   /* Configure SMBUSx: Dual mode and Own Address2 */
371   hsmbus->Instance->OAR2 = (hsmbus->Init.DualAddressMode | hsmbus->Init.OwnAddress2 | \
372                             (hsmbus->Init.OwnAddress2Masks << 8U));
373 
374   /*---------------------------- SMBUSx CR1 Configuration ------------------------*/
375   /* Configure SMBUSx: Generalcall and NoStretch mode */
376   hsmbus->Instance->CR1 = (hsmbus->Init.GeneralCallMode | hsmbus->Init.NoStretchMode | \
377                            hsmbus->Init.PacketErrorCheckMode | hsmbus->Init.PeripheralMode | \
378                            hsmbus->Init.AnalogFilter);
379 
380   /* Enable Slave Byte Control only in case of Packet Error Check is enabled
381      and SMBUS Peripheral is set in Slave mode */
382   if ((hsmbus->Init.PacketErrorCheckMode == SMBUS_PEC_ENABLE) && \
383       ((hsmbus->Init.PeripheralMode == SMBUS_PERIPHERAL_MODE_SMBUS_SLAVE) || \
384        (hsmbus->Init.PeripheralMode == SMBUS_PERIPHERAL_MODE_SMBUS_SLAVE_ARP)))
385   {
386     hsmbus->Instance->CR1 |= I2C_CR1_SBC;
387   }
388 
389   /* Enable the selected SMBUS peripheral */
390   __HAL_SMBUS_ENABLE(hsmbus);
391 
392   hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE;
393   hsmbus->PreviousState = HAL_SMBUS_STATE_READY;
394   hsmbus->State = HAL_SMBUS_STATE_READY;
395 
396   return HAL_OK;
397 }
398 
399 /**
400   * @brief  DeInitialize the SMBUS peripheral.
401   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
402   *                the configuration information for the specified SMBUS.
403   * @retval HAL status
404   */
HAL_SMBUS_DeInit(SMBUS_HandleTypeDef * hsmbus)405 HAL_StatusTypeDef HAL_SMBUS_DeInit(SMBUS_HandleTypeDef *hsmbus)
406 {
407   /* Check the SMBUS handle allocation */
408   if (hsmbus == NULL)
409   {
410     return HAL_ERROR;
411   }
412 
413   /* Check the parameters */
414   assert_param(IS_SMBUS_ALL_INSTANCE(hsmbus->Instance));
415 
416   hsmbus->State = HAL_SMBUS_STATE_BUSY;
417 
418   /* Disable the SMBUS Peripheral Clock */
419   __HAL_SMBUS_DISABLE(hsmbus);
420 
421 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
422   if (hsmbus->MspDeInitCallback == NULL)
423   {
424     hsmbus->MspDeInitCallback = HAL_SMBUS_MspDeInit; /* Legacy weak MspDeInit  */
425   }
426 
427   /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
428   hsmbus->MspDeInitCallback(hsmbus);
429 #else
430   /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
431   HAL_SMBUS_MspDeInit(hsmbus);
432 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
433 
434   hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE;
435   hsmbus->PreviousState =  HAL_SMBUS_STATE_RESET;
436   hsmbus->State = HAL_SMBUS_STATE_RESET;
437 
438   /* Release Lock */
439   __HAL_UNLOCK(hsmbus);
440 
441   return HAL_OK;
442 }
443 
444 /**
445   * @brief Initialize the SMBUS MSP.
446   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
447   *                the configuration information for the specified SMBUS.
448   * @retval None
449   */
HAL_SMBUS_MspInit(SMBUS_HandleTypeDef * hsmbus)450 __weak void HAL_SMBUS_MspInit(SMBUS_HandleTypeDef *hsmbus)
451 {
452   /* Prevent unused argument(s) compilation warning */
453   UNUSED(hsmbus);
454 
455   /* NOTE : This function should not be modified, when the callback is needed,
456             the HAL_SMBUS_MspInit could be implemented in the user file
457    */
458 }
459 
460 /**
461   * @brief DeInitialize the SMBUS MSP.
462   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
463   *                the configuration information for the specified SMBUS.
464   * @retval None
465   */
HAL_SMBUS_MspDeInit(SMBUS_HandleTypeDef * hsmbus)466 __weak void HAL_SMBUS_MspDeInit(SMBUS_HandleTypeDef *hsmbus)
467 {
468   /* Prevent unused argument(s) compilation warning */
469   UNUSED(hsmbus);
470 
471   /* NOTE : This function should not be modified, when the callback is needed,
472             the HAL_SMBUS_MspDeInit could be implemented in the user file
473    */
474 }
475 
476 /**
477   * @brief  Configure Analog noise filter.
478   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
479   *                the configuration information for the specified SMBUS.
480   * @param  AnalogFilter This parameter can be one of the following values:
481   *         @arg @ref SMBUS_ANALOGFILTER_ENABLE
482   *         @arg @ref SMBUS_ANALOGFILTER_DISABLE
483   * @retval HAL status
484   */
HAL_SMBUS_ConfigAnalogFilter(SMBUS_HandleTypeDef * hsmbus,uint32_t AnalogFilter)485 HAL_StatusTypeDef HAL_SMBUS_ConfigAnalogFilter(SMBUS_HandleTypeDef *hsmbus, uint32_t AnalogFilter)
486 {
487   /* Check the parameters */
488   assert_param(IS_SMBUS_ALL_INSTANCE(hsmbus->Instance));
489   assert_param(IS_SMBUS_ANALOG_FILTER(AnalogFilter));
490 
491   if (hsmbus->State == HAL_SMBUS_STATE_READY)
492   {
493     /* Process Locked */
494     __HAL_LOCK(hsmbus);
495 
496     hsmbus->State = HAL_SMBUS_STATE_BUSY;
497 
498     /* Disable the selected SMBUS peripheral */
499     __HAL_SMBUS_DISABLE(hsmbus);
500 
501     /* Reset ANOFF bit */
502     hsmbus->Instance->CR1 &= ~(I2C_CR1_ANFOFF);
503 
504     /* Set analog filter bit*/
505     hsmbus->Instance->CR1 |= AnalogFilter;
506 
507     __HAL_SMBUS_ENABLE(hsmbus);
508 
509     hsmbus->State = HAL_SMBUS_STATE_READY;
510 
511     /* Process Unlocked */
512     __HAL_UNLOCK(hsmbus);
513 
514     return HAL_OK;
515   }
516   else
517   {
518     return HAL_BUSY;
519   }
520 }
521 
522 /**
523   * @brief  Configure Digital noise filter.
524   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
525   *                the configuration information for the specified SMBUS.
526   * @param  DigitalFilter Coefficient of digital noise filter between Min_Data=0x00 and Max_Data=0x0F.
527   * @retval HAL status
528   */
HAL_SMBUS_ConfigDigitalFilter(SMBUS_HandleTypeDef * hsmbus,uint32_t DigitalFilter)529 HAL_StatusTypeDef HAL_SMBUS_ConfigDigitalFilter(SMBUS_HandleTypeDef *hsmbus, uint32_t DigitalFilter)
530 {
531   uint32_t tmpreg;
532 
533   /* Check the parameters */
534   assert_param(IS_SMBUS_ALL_INSTANCE(hsmbus->Instance));
535   assert_param(IS_SMBUS_DIGITAL_FILTER(DigitalFilter));
536 
537   if (hsmbus->State == HAL_SMBUS_STATE_READY)
538   {
539     /* Process Locked */
540     __HAL_LOCK(hsmbus);
541 
542     hsmbus->State = HAL_SMBUS_STATE_BUSY;
543 
544     /* Disable the selected SMBUS peripheral */
545     __HAL_SMBUS_DISABLE(hsmbus);
546 
547     /* Get the old register value */
548     tmpreg = hsmbus->Instance->CR1;
549 
550     /* Reset I2C DNF bits [11:8] */
551     tmpreg &= ~(I2C_CR1_DNF);
552 
553     /* Set I2Cx DNF coefficient */
554     tmpreg |= DigitalFilter << I2C_CR1_DNF_Pos;
555 
556     /* Store the new register value */
557     hsmbus->Instance->CR1 = tmpreg;
558 
559     __HAL_SMBUS_ENABLE(hsmbus);
560 
561     hsmbus->State = HAL_SMBUS_STATE_READY;
562 
563     /* Process Unlocked */
564     __HAL_UNLOCK(hsmbus);
565 
566     return HAL_OK;
567   }
568   else
569   {
570     return HAL_BUSY;
571   }
572 }
573 
574 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
575 /**
576   * @brief  Register a User SMBUS Callback
577   *         To be used instead of the weak predefined callback
578   * @note   The HAL_SMBUS_RegisterCallback() may be called before HAL_SMBUS_Init() in
579   *         HAL_SMBUS_STATE_RESET to register callbacks for HAL_SMBUS_MSPINIT_CB_ID and
580   *         HAL_SMBUS_MSPDEINIT_CB_ID.
581   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
582   *                the configuration information for the specified SMBUS.
583   * @param  CallbackID ID of the callback to be registered
584   *         This parameter can be one of the following values:
585   *          @arg @ref HAL_SMBUS_MASTER_TX_COMPLETE_CB_ID Master Tx Transfer completed callback ID
586   *          @arg @ref HAL_SMBUS_MASTER_RX_COMPLETE_CB_ID Master Rx Transfer completed callback ID
587   *          @arg @ref HAL_SMBUS_SLAVE_TX_COMPLETE_CB_ID Slave Tx Transfer completed callback ID
588   *          @arg @ref HAL_SMBUS_SLAVE_RX_COMPLETE_CB_ID Slave Rx Transfer completed callback ID
589   *          @arg @ref HAL_SMBUS_LISTEN_COMPLETE_CB_ID Listen Complete callback ID
590   *          @arg @ref HAL_SMBUS_ERROR_CB_ID Error callback ID
591   *          @arg @ref HAL_SMBUS_MSPINIT_CB_ID MspInit callback ID
592   *          @arg @ref HAL_SMBUS_MSPDEINIT_CB_ID MspDeInit callback ID
593   * @param  pCallback pointer to the Callback function
594   * @retval HAL status
595   */
HAL_SMBUS_RegisterCallback(SMBUS_HandleTypeDef * hsmbus,HAL_SMBUS_CallbackIDTypeDef CallbackID,pSMBUS_CallbackTypeDef pCallback)596 HAL_StatusTypeDef HAL_SMBUS_RegisterCallback(SMBUS_HandleTypeDef *hsmbus,
597                                              HAL_SMBUS_CallbackIDTypeDef CallbackID,
598                                              pSMBUS_CallbackTypeDef pCallback)
599 {
600   HAL_StatusTypeDef status = HAL_OK;
601 
602   if (pCallback == NULL)
603   {
604     /* Update the error code */
605     hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK;
606 
607     return HAL_ERROR;
608   }
609 
610   if (HAL_SMBUS_STATE_READY == hsmbus->State)
611   {
612     switch (CallbackID)
613     {
614       case HAL_SMBUS_MASTER_TX_COMPLETE_CB_ID :
615         hsmbus->MasterTxCpltCallback = pCallback;
616         break;
617 
618       case HAL_SMBUS_MASTER_RX_COMPLETE_CB_ID :
619         hsmbus->MasterRxCpltCallback = pCallback;
620         break;
621 
622       case HAL_SMBUS_SLAVE_TX_COMPLETE_CB_ID :
623         hsmbus->SlaveTxCpltCallback = pCallback;
624         break;
625 
626       case HAL_SMBUS_SLAVE_RX_COMPLETE_CB_ID :
627         hsmbus->SlaveRxCpltCallback = pCallback;
628         break;
629 
630       case HAL_SMBUS_LISTEN_COMPLETE_CB_ID :
631         hsmbus->ListenCpltCallback = pCallback;
632         break;
633 
634       case HAL_SMBUS_ERROR_CB_ID :
635         hsmbus->ErrorCallback = pCallback;
636         break;
637 
638       case HAL_SMBUS_MSPINIT_CB_ID :
639         hsmbus->MspInitCallback = pCallback;
640         break;
641 
642       case HAL_SMBUS_MSPDEINIT_CB_ID :
643         hsmbus->MspDeInitCallback = pCallback;
644         break;
645 
646       default :
647         /* Update the error code */
648         hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK;
649 
650         /* Return error status */
651         status =  HAL_ERROR;
652         break;
653     }
654   }
655   else if (HAL_SMBUS_STATE_RESET == hsmbus->State)
656   {
657     switch (CallbackID)
658     {
659       case HAL_SMBUS_MSPINIT_CB_ID :
660         hsmbus->MspInitCallback = pCallback;
661         break;
662 
663       case HAL_SMBUS_MSPDEINIT_CB_ID :
664         hsmbus->MspDeInitCallback = pCallback;
665         break;
666 
667       default :
668         /* Update the error code */
669         hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK;
670 
671         /* Return error status */
672         status =  HAL_ERROR;
673         break;
674     }
675   }
676   else
677   {
678     /* Update the error code */
679     hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK;
680 
681     /* Return error status */
682     status =  HAL_ERROR;
683   }
684 
685   return status;
686 }
687 
688 /**
689   * @brief  Unregister an SMBUS Callback
690   *         SMBUS callback is redirected to the weak predefined callback
691   * @note   The HAL_SMBUS_UnRegisterCallback() may be called before HAL_SMBUS_Init() in
692   *         HAL_SMBUS_STATE_RESET to un-register callbacks for HAL_SMBUS_MSPINIT_CB_ID and
693   *         HAL_SMBUS_MSPDEINIT_CB_ID
694   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
695   *                the configuration information for the specified SMBUS.
696   * @param  CallbackID ID of the callback to be unregistered
697   *         This parameter can be one of the following values:
698   *         This parameter can be one of the following values:
699   *          @arg @ref HAL_SMBUS_MASTER_TX_COMPLETE_CB_ID Master Tx Transfer completed callback ID
700   *          @arg @ref HAL_SMBUS_MASTER_RX_COMPLETE_CB_ID Master Rx Transfer completed callback ID
701   *          @arg @ref HAL_SMBUS_SLAVE_TX_COMPLETE_CB_ID Slave Tx Transfer completed callback ID
702   *          @arg @ref HAL_SMBUS_SLAVE_RX_COMPLETE_CB_ID Slave Rx Transfer completed callback ID
703   *          @arg @ref HAL_SMBUS_LISTEN_COMPLETE_CB_ID Listen Complete callback ID
704   *          @arg @ref HAL_SMBUS_ERROR_CB_ID Error callback ID
705   *          @arg @ref HAL_SMBUS_MSPINIT_CB_ID MspInit callback ID
706   *          @arg @ref HAL_SMBUS_MSPDEINIT_CB_ID MspDeInit callback ID
707   * @retval HAL status
708   */
HAL_SMBUS_UnRegisterCallback(SMBUS_HandleTypeDef * hsmbus,HAL_SMBUS_CallbackIDTypeDef CallbackID)709 HAL_StatusTypeDef HAL_SMBUS_UnRegisterCallback(SMBUS_HandleTypeDef *hsmbus,
710                                                HAL_SMBUS_CallbackIDTypeDef CallbackID)
711 {
712   HAL_StatusTypeDef status = HAL_OK;
713 
714   if (HAL_SMBUS_STATE_READY == hsmbus->State)
715   {
716     switch (CallbackID)
717     {
718       case HAL_SMBUS_MASTER_TX_COMPLETE_CB_ID :
719         hsmbus->MasterTxCpltCallback = HAL_SMBUS_MasterTxCpltCallback; /* Legacy weak MasterTxCpltCallback */
720         break;
721 
722       case HAL_SMBUS_MASTER_RX_COMPLETE_CB_ID :
723         hsmbus->MasterRxCpltCallback = HAL_SMBUS_MasterRxCpltCallback; /* Legacy weak MasterRxCpltCallback */
724         break;
725 
726       case HAL_SMBUS_SLAVE_TX_COMPLETE_CB_ID :
727         hsmbus->SlaveTxCpltCallback = HAL_SMBUS_SlaveTxCpltCallback;   /* Legacy weak SlaveTxCpltCallback  */
728         break;
729 
730       case HAL_SMBUS_SLAVE_RX_COMPLETE_CB_ID :
731         hsmbus->SlaveRxCpltCallback = HAL_SMBUS_SlaveRxCpltCallback;   /* Legacy weak SlaveRxCpltCallback  */
732         break;
733 
734       case HAL_SMBUS_LISTEN_COMPLETE_CB_ID :
735         hsmbus->ListenCpltCallback = HAL_SMBUS_ListenCpltCallback;     /* Legacy weak ListenCpltCallback   */
736         break;
737 
738       case HAL_SMBUS_ERROR_CB_ID :
739         hsmbus->ErrorCallback = HAL_SMBUS_ErrorCallback;               /* Legacy weak ErrorCallback        */
740         break;
741 
742       case HAL_SMBUS_MSPINIT_CB_ID :
743         hsmbus->MspInitCallback = HAL_SMBUS_MspInit;                   /* Legacy weak MspInit              */
744         break;
745 
746       case HAL_SMBUS_MSPDEINIT_CB_ID :
747         hsmbus->MspDeInitCallback = HAL_SMBUS_MspDeInit;               /* Legacy weak MspDeInit            */
748         break;
749 
750       default :
751         /* Update the error code */
752         hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK;
753 
754         /* Return error status */
755         status =  HAL_ERROR;
756         break;
757     }
758   }
759   else if (HAL_SMBUS_STATE_RESET == hsmbus->State)
760   {
761     switch (CallbackID)
762     {
763       case HAL_SMBUS_MSPINIT_CB_ID :
764         hsmbus->MspInitCallback = HAL_SMBUS_MspInit;                   /* Legacy weak MspInit              */
765         break;
766 
767       case HAL_SMBUS_MSPDEINIT_CB_ID :
768         hsmbus->MspDeInitCallback = HAL_SMBUS_MspDeInit;               /* Legacy weak MspDeInit            */
769         break;
770 
771       default :
772         /* Update the error code */
773         hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK;
774 
775         /* Return error status */
776         status =  HAL_ERROR;
777         break;
778     }
779   }
780   else
781   {
782     /* Update the error code */
783     hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK;
784 
785     /* Return error status */
786     status =  HAL_ERROR;
787   }
788 
789   return status;
790 }
791 
792 /**
793   * @brief  Register the Slave Address Match SMBUS Callback
794   *         To be used instead of the weak HAL_SMBUS_AddrCallback() predefined callback
795   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
796   *                the configuration information for the specified SMBUS.
797   * @param  pCallback pointer to the Address Match Callback function
798   * @retval HAL status
799   */
HAL_SMBUS_RegisterAddrCallback(SMBUS_HandleTypeDef * hsmbus,pSMBUS_AddrCallbackTypeDef pCallback)800 HAL_StatusTypeDef HAL_SMBUS_RegisterAddrCallback(SMBUS_HandleTypeDef *hsmbus,
801                                                  pSMBUS_AddrCallbackTypeDef pCallback)
802 {
803   HAL_StatusTypeDef status = HAL_OK;
804 
805   if (pCallback == NULL)
806   {
807     /* Update the error code */
808     hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK;
809 
810     return HAL_ERROR;
811   }
812 
813   if (HAL_SMBUS_STATE_READY == hsmbus->State)
814   {
815     hsmbus->AddrCallback = pCallback;
816   }
817   else
818   {
819     /* Update the error code */
820     hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK;
821 
822     /* Return error status */
823     status =  HAL_ERROR;
824   }
825 
826   return status;
827 }
828 
829 /**
830   * @brief  UnRegister the Slave Address Match SMBUS Callback
831   *         Info Ready SMBUS Callback is redirected to the weak HAL_SMBUS_AddrCallback() predefined callback
832   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
833   *                the configuration information for the specified SMBUS.
834   * @retval HAL status
835   */
HAL_SMBUS_UnRegisterAddrCallback(SMBUS_HandleTypeDef * hsmbus)836 HAL_StatusTypeDef HAL_SMBUS_UnRegisterAddrCallback(SMBUS_HandleTypeDef *hsmbus)
837 {
838   HAL_StatusTypeDef status = HAL_OK;
839 
840   if (HAL_SMBUS_STATE_READY == hsmbus->State)
841   {
842     hsmbus->AddrCallback = HAL_SMBUS_AddrCallback; /* Legacy weak AddrCallback  */
843   }
844   else
845   {
846     /* Update the error code */
847     hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK;
848 
849     /* Return error status */
850     status =  HAL_ERROR;
851   }
852 
853   return status;
854 }
855 
856 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
857 
858 /**
859   * @}
860   */
861 
862 /** @defgroup SMBUS_Exported_Functions_Group2 Input and Output operation functions
863   *  @brief   Data transfers functions
864   *
865 @verbatim
866  ===============================================================================
867                       ##### IO operation functions #####
868  ===============================================================================
869     [..]
870     This subsection provides a set of functions allowing to manage the SMBUS data
871     transfers.
872 
873     (#) Blocking mode function to check if device is ready for usage is :
874         (++) HAL_SMBUS_IsDeviceReady()
875 
876     (#) There is only one mode of transfer:
877        (++) Non-Blocking mode : The communication is performed using Interrupts.
878             These functions return the status of the transfer startup.
879             The end of the data processing will be indicated through the
880             dedicated SMBUS IRQ when using Interrupt mode.
881 
882     (#) Non-Blocking mode functions with Interrupt are :
883         (++) HAL_SMBUS_Master_Transmit_IT()
884         (++) HAL_SMBUS_Master_Receive_IT()
885         (++) HAL_SMBUS_Slave_Transmit_IT()
886         (++) HAL_SMBUS_Slave_Receive_IT()
887         (++) HAL_SMBUS_EnableListen_IT() or alias HAL_SMBUS_EnableListen_IT()
888         (++) HAL_SMBUS_DisableListen_IT()
889         (++) HAL_SMBUS_EnableAlert_IT()
890         (++) HAL_SMBUS_DisableAlert_IT()
891 
892     (#) A set of Transfer Complete Callbacks are provided in non-Blocking mode:
893         (++) HAL_SMBUS_MasterTxCpltCallback()
894         (++) HAL_SMBUS_MasterRxCpltCallback()
895         (++) HAL_SMBUS_SlaveTxCpltCallback()
896         (++) HAL_SMBUS_SlaveRxCpltCallback()
897         (++) HAL_SMBUS_AddrCallback()
898         (++) HAL_SMBUS_ListenCpltCallback()
899         (++) HAL_SMBUS_ErrorCallback()
900 
901 @endverbatim
902   * @{
903   */
904 
905 /**
906   * @brief  Transmit in master/host SMBUS mode an amount of data in non-blocking mode with Interrupt.
907   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
908   *                the configuration information for the specified SMBUS.
909   * @param  DevAddress Target device address: The device 7 bits address value
910   *         in datasheet must be shifted to the left before calling the interface
911   * @param  pData Pointer to data buffer
912   * @param  Size Amount of data to be sent
913   * @param  XferOptions Options of Transfer, value of @ref SMBUS_XferOptions_definition
914   * @retval HAL status
915   */
HAL_SMBUS_Master_Transmit_IT(SMBUS_HandleTypeDef * hsmbus,uint16_t DevAddress,uint8_t * pData,uint16_t Size,uint32_t XferOptions)916 HAL_StatusTypeDef HAL_SMBUS_Master_Transmit_IT(SMBUS_HandleTypeDef *hsmbus, uint16_t DevAddress,
917                                                uint8_t *pData, uint16_t Size, uint32_t XferOptions)
918 {
919   uint32_t tmp;
920 
921   /* Check the parameters */
922   assert_param(IS_SMBUS_TRANSFER_OPTIONS_REQUEST(XferOptions));
923 
924   if (hsmbus->State == HAL_SMBUS_STATE_READY)
925   {
926     /* Process Locked */
927     __HAL_LOCK(hsmbus);
928 
929     hsmbus->State = HAL_SMBUS_STATE_MASTER_BUSY_TX;
930     hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE;
931     /* Prepare transfer parameters */
932     hsmbus->pBuffPtr = pData;
933     hsmbus->XferCount = Size;
934     hsmbus->XferOptions = XferOptions;
935 
936     /* In case of Quick command, remove autoend mode */
937     /* Manage the stop generation by software */
938     if (hsmbus->pBuffPtr == NULL)
939     {
940       hsmbus->XferOptions &= ~SMBUS_AUTOEND_MODE;
941     }
942 
943     if (Size > MAX_NBYTE_SIZE)
944     {
945       hsmbus->XferSize = MAX_NBYTE_SIZE;
946     }
947     else
948     {
949       hsmbus->XferSize = Size;
950     }
951 
952     /* Send Slave Address */
953     /* Set NBYTES to write and reload if size > MAX_NBYTE_SIZE and generate RESTART */
954     if ((hsmbus->XferSize < hsmbus->XferCount) && (hsmbus->XferSize == MAX_NBYTE_SIZE))
955     {
956       SMBUS_TransferConfig(hsmbus, DevAddress, (uint8_t)hsmbus->XferSize,
957                            SMBUS_RELOAD_MODE | (hsmbus->XferOptions & SMBUS_SENDPEC_MODE),
958                            SMBUS_GENERATE_START_WRITE);
959     }
960     else
961     {
962       /* If transfer direction not change, do not generate Restart Condition */
963       /* Mean Previous state is same as current state */
964 
965       /* Store current volatile XferOptions, misra rule */
966       tmp = hsmbus->XferOptions;
967 
968       if ((hsmbus->PreviousState == HAL_SMBUS_STATE_MASTER_BUSY_TX) && \
969           (IS_SMBUS_TRANSFER_OTHER_OPTIONS_REQUEST(tmp) == 0))
970       {
971         SMBUS_TransferConfig(hsmbus, DevAddress, (uint8_t)hsmbus->XferSize, hsmbus->XferOptions,
972                              SMBUS_NO_STARTSTOP);
973       }
974       /* Else transfer direction change, so generate Restart with new transfer direction */
975       else
976       {
977         /* Convert OTHER_xxx XferOptions if any */
978         SMBUS_ConvertOtherXferOptions(hsmbus);
979 
980         /* Handle Transfer */
981         SMBUS_TransferConfig(hsmbus, DevAddress, (uint8_t)hsmbus->XferSize,
982                              hsmbus->XferOptions,
983                              SMBUS_GENERATE_START_WRITE);
984       }
985 
986       /* If PEC mode is enable, size to transmit manage by SW part should be Size-1 byte, corresponding to PEC byte */
987       /* PEC byte is automatically sent by HW block, no need to manage it in Transmit process */
988       if (SMBUS_GET_PEC_MODE(hsmbus) != 0UL)
989       {
990         if (hsmbus->XferSize > 0U)
991         {
992           hsmbus->XferSize--;
993           hsmbus->XferCount--;
994         }
995         else
996         {
997           return HAL_ERROR;
998         }
999       }
1000     }
1001 
1002     /* Process Unlocked */
1003     __HAL_UNLOCK(hsmbus);
1004 
1005     /* Note : The SMBUS interrupts must be enabled after unlocking current process
1006               to avoid the risk of SMBUS interrupt handle execution before current
1007               process unlock */
1008     SMBUS_Enable_IRQ(hsmbus, SMBUS_IT_TX);
1009 
1010     return HAL_OK;
1011   }
1012   else
1013   {
1014     return HAL_BUSY;
1015   }
1016 }
1017 
1018 /**
1019   * @brief  Receive in master/host SMBUS mode an amount of data in non-blocking mode with Interrupt.
1020   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
1021   *                the configuration information for the specified SMBUS.
1022   * @param  DevAddress Target device address: The device 7 bits address value
1023   *         in datasheet must be shifted to the left before calling the interface
1024   * @param  pData Pointer to data buffer
1025   * @param  Size Amount of data to be sent
1026   * @param  XferOptions Options of Transfer, value of @ref SMBUS_XferOptions_definition
1027   * @retval HAL status
1028   */
HAL_SMBUS_Master_Receive_IT(SMBUS_HandleTypeDef * hsmbus,uint16_t DevAddress,uint8_t * pData,uint16_t Size,uint32_t XferOptions)1029 HAL_StatusTypeDef HAL_SMBUS_Master_Receive_IT(SMBUS_HandleTypeDef *hsmbus, uint16_t DevAddress, uint8_t *pData,
1030                                               uint16_t Size, uint32_t XferOptions)
1031 {
1032   uint32_t tmp;
1033 
1034   /* Check the parameters */
1035   assert_param(IS_SMBUS_TRANSFER_OPTIONS_REQUEST(XferOptions));
1036 
1037   if (hsmbus->State == HAL_SMBUS_STATE_READY)
1038   {
1039     /* Process Locked */
1040     __HAL_LOCK(hsmbus);
1041 
1042     hsmbus->State = HAL_SMBUS_STATE_MASTER_BUSY_RX;
1043     hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE;
1044 
1045     /* Prepare transfer parameters */
1046     hsmbus->pBuffPtr = pData;
1047     hsmbus->XferCount = Size;
1048     hsmbus->XferOptions = XferOptions;
1049 
1050     /* In case of Quick command, remove autoend mode */
1051     /* Manage the stop generation by software */
1052     if (hsmbus->pBuffPtr == NULL)
1053     {
1054       hsmbus->XferOptions &= ~SMBUS_AUTOEND_MODE;
1055     }
1056 
1057     if (Size > MAX_NBYTE_SIZE)
1058     {
1059       hsmbus->XferSize = MAX_NBYTE_SIZE;
1060     }
1061     else
1062     {
1063       hsmbus->XferSize = Size;
1064     }
1065 
1066     /* Send Slave Address */
1067     /* Set NBYTES to write and reload if size > MAX_NBYTE_SIZE and generate RESTART */
1068     if ((hsmbus->XferSize < hsmbus->XferCount) && (hsmbus->XferSize == MAX_NBYTE_SIZE))
1069     {
1070       SMBUS_TransferConfig(hsmbus, DevAddress, (uint8_t)hsmbus->XferSize,
1071                            SMBUS_RELOAD_MODE  | (hsmbus->XferOptions & SMBUS_SENDPEC_MODE),
1072                            SMBUS_GENERATE_START_READ);
1073     }
1074     else
1075     {
1076       /* If transfer direction not change, do not generate Restart Condition */
1077       /* Mean Previous state is same as current state */
1078 
1079       /* Store current volatile XferOptions, Misra rule */
1080       tmp = hsmbus->XferOptions;
1081 
1082       if ((hsmbus->PreviousState == HAL_SMBUS_STATE_MASTER_BUSY_RX) && \
1083           (IS_SMBUS_TRANSFER_OTHER_OPTIONS_REQUEST(tmp) == 0))
1084       {
1085         SMBUS_TransferConfig(hsmbus, DevAddress, (uint8_t)hsmbus->XferSize, hsmbus->XferOptions,
1086                              SMBUS_NO_STARTSTOP);
1087       }
1088       /* Else transfer direction change, so generate Restart with new transfer direction */
1089       else
1090       {
1091         /* Convert OTHER_xxx XferOptions if any */
1092         SMBUS_ConvertOtherXferOptions(hsmbus);
1093 
1094         /* Handle Transfer */
1095         SMBUS_TransferConfig(hsmbus, DevAddress, (uint8_t)hsmbus->XferSize,
1096                              hsmbus->XferOptions,
1097                              SMBUS_GENERATE_START_READ);
1098       }
1099     }
1100 
1101     /* Process Unlocked */
1102     __HAL_UNLOCK(hsmbus);
1103 
1104     /* Note : The SMBUS interrupts must be enabled after unlocking current process
1105               to avoid the risk of SMBUS interrupt handle execution before current
1106               process unlock */
1107     SMBUS_Enable_IRQ(hsmbus, SMBUS_IT_RX);
1108 
1109     return HAL_OK;
1110   }
1111   else
1112   {
1113     return HAL_BUSY;
1114   }
1115 }
1116 
1117 /**
1118   * @brief  Abort a master/host SMBUS process communication with Interrupt.
1119   * @note   This abort can be called only if state is ready
1120   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
1121   *                the configuration information for the specified SMBUS.
1122   * @param  DevAddress Target device address: The device 7 bits address value
1123   *         in datasheet must be shifted to the left before calling the interface
1124   * @retval HAL status
1125   */
HAL_SMBUS_Master_Abort_IT(SMBUS_HandleTypeDef * hsmbus,uint16_t DevAddress)1126 HAL_StatusTypeDef HAL_SMBUS_Master_Abort_IT(SMBUS_HandleTypeDef *hsmbus, uint16_t DevAddress)
1127 {
1128   if (hsmbus->State == HAL_SMBUS_STATE_READY)
1129   {
1130     /* Process Locked */
1131     __HAL_LOCK(hsmbus);
1132 
1133     /* Keep the same state as previous */
1134     /* to perform as well the call of the corresponding end of transfer callback */
1135     if (hsmbus->PreviousState == HAL_SMBUS_STATE_MASTER_BUSY_TX)
1136     {
1137       hsmbus->State = HAL_SMBUS_STATE_MASTER_BUSY_TX;
1138     }
1139     else if (hsmbus->PreviousState == HAL_SMBUS_STATE_MASTER_BUSY_RX)
1140     {
1141       hsmbus->State = HAL_SMBUS_STATE_MASTER_BUSY_RX;
1142     }
1143     else
1144     {
1145       /* Wrong usage of abort function */
1146       /* This function should be used only in case of abort monitored by master device */
1147       return HAL_ERROR;
1148     }
1149     hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE;
1150 
1151     /* Set NBYTES to 1 to generate a dummy read on SMBUS peripheral */
1152     /* Set AUTOEND mode, this will generate a NACK then STOP condition to abort the current transfer */
1153     SMBUS_TransferConfig(hsmbus, DevAddress, 1, SMBUS_AUTOEND_MODE, SMBUS_NO_STARTSTOP);
1154 
1155     /* Process Unlocked */
1156     __HAL_UNLOCK(hsmbus);
1157 
1158     /* Note : The SMBUS interrupts must be enabled after unlocking current process
1159               to avoid the risk of SMBUS interrupt handle execution before current
1160               process unlock */
1161     if (hsmbus->State == HAL_SMBUS_STATE_MASTER_BUSY_TX)
1162     {
1163       SMBUS_Enable_IRQ(hsmbus, SMBUS_IT_TX);
1164     }
1165     else if (hsmbus->State == HAL_SMBUS_STATE_MASTER_BUSY_RX)
1166     {
1167       SMBUS_Enable_IRQ(hsmbus, SMBUS_IT_RX);
1168     }
1169     else
1170     {
1171       /* Nothing to do */
1172     }
1173 
1174     return HAL_OK;
1175   }
1176   else
1177   {
1178     return HAL_BUSY;
1179   }
1180 }
1181 
1182 /**
1183   * @brief  Transmit in slave/device SMBUS mode an amount of data in non-blocking mode with Interrupt.
1184   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
1185   *                the configuration information for the specified SMBUS.
1186   * @param  pData Pointer to data buffer
1187   * @param  Size Amount of data to be sent
1188   * @param  XferOptions Options of Transfer, value of @ref SMBUS_XferOptions_definition
1189   * @retval HAL status
1190   */
HAL_SMBUS_Slave_Transmit_IT(SMBUS_HandleTypeDef * hsmbus,uint8_t * pData,uint16_t Size,uint32_t XferOptions)1191 HAL_StatusTypeDef HAL_SMBUS_Slave_Transmit_IT(SMBUS_HandleTypeDef *hsmbus, uint8_t *pData, uint16_t Size,
1192                                               uint32_t XferOptions)
1193 {
1194   /* Check the parameters */
1195   assert_param(IS_SMBUS_TRANSFER_OPTIONS_REQUEST(XferOptions));
1196 
1197   if ((hsmbus->State & HAL_SMBUS_STATE_LISTEN) == HAL_SMBUS_STATE_LISTEN)
1198   {
1199     if ((pData == NULL) || (Size == 0UL))
1200     {
1201       hsmbus->ErrorCode = HAL_SMBUS_ERROR_INVALID_PARAM;
1202       return HAL_ERROR;
1203     }
1204 
1205     /* Disable Interrupts, to prevent preemption during treatment in case of multicall */
1206     SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_ADDR | SMBUS_IT_TX);
1207 
1208     /* Process Locked */
1209     __HAL_LOCK(hsmbus);
1210 
1211     hsmbus->State = (HAL_SMBUS_STATE_SLAVE_BUSY_TX | HAL_SMBUS_STATE_LISTEN);
1212     hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE;
1213 
1214     /* Set SBC bit to manage Acknowledge at each bit */
1215     hsmbus->Instance->CR1 |= I2C_CR1_SBC;
1216 
1217     /* Enable Address Acknowledge */
1218     hsmbus->Instance->CR2 &= ~I2C_CR2_NACK;
1219 
1220     /* Prepare transfer parameters */
1221     hsmbus->pBuffPtr = pData;
1222     hsmbus->XferCount = Size;
1223     hsmbus->XferOptions = XferOptions;
1224 
1225     /* Convert OTHER_xxx XferOptions if any */
1226     SMBUS_ConvertOtherXferOptions(hsmbus);
1227 
1228     if (Size > MAX_NBYTE_SIZE)
1229     {
1230       hsmbus->XferSize = MAX_NBYTE_SIZE;
1231     }
1232     else
1233     {
1234       hsmbus->XferSize = Size;
1235     }
1236 
1237     /* Set NBYTES to write and reload if size > MAX_NBYTE_SIZE and generate RESTART */
1238     if ((hsmbus->XferSize < hsmbus->XferCount) && (hsmbus->XferSize == MAX_NBYTE_SIZE))
1239     {
1240       SMBUS_TransferConfig(hsmbus, 0, (uint8_t)hsmbus->XferSize,
1241                            SMBUS_RELOAD_MODE | (hsmbus->XferOptions & SMBUS_SENDPEC_MODE),
1242                            SMBUS_NO_STARTSTOP);
1243     }
1244     else
1245     {
1246       /* Set NBYTE to transmit */
1247       SMBUS_TransferConfig(hsmbus, 0, (uint8_t)hsmbus->XferSize, hsmbus->XferOptions,
1248                            SMBUS_NO_STARTSTOP);
1249 
1250       /* If PEC mode is enable, size to transmit should be Size-1 byte, corresponding to PEC byte */
1251       /* PEC byte is automatically sent by HW block, no need to manage it in Transmit process */
1252       if (SMBUS_GET_PEC_MODE(hsmbus) != 0UL)
1253       {
1254         hsmbus->XferSize--;
1255         hsmbus->XferCount--;
1256       }
1257     }
1258 
1259     /* Clear ADDR flag after prepare the transfer parameters */
1260     /* This action will generate an acknowledge to the HOST */
1261     __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_ADDR);
1262 
1263     /* Process Unlocked */
1264     __HAL_UNLOCK(hsmbus);
1265 
1266     /* Note : The SMBUS interrupts must be enabled after unlocking current process
1267               to avoid the risk of SMBUS interrupt handle execution before current
1268               process unlock */
1269     /* REnable ADDR interrupt */
1270     SMBUS_Enable_IRQ(hsmbus, SMBUS_IT_TX | SMBUS_IT_ADDR);
1271 
1272     return HAL_OK;
1273   }
1274   else
1275   {
1276     return HAL_BUSY;
1277   }
1278 }
1279 
1280 /**
1281   * @brief  Receive in slave/device SMBUS mode an amount of data in non-blocking mode with Interrupt.
1282   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
1283   *                the configuration information for the specified SMBUS.
1284   * @param  pData Pointer to data buffer
1285   * @param  Size Amount of data to be sent
1286   * @param  XferOptions Options of Transfer, value of @ref SMBUS_XferOptions_definition
1287   * @retval HAL status
1288   */
HAL_SMBUS_Slave_Receive_IT(SMBUS_HandleTypeDef * hsmbus,uint8_t * pData,uint16_t Size,uint32_t XferOptions)1289 HAL_StatusTypeDef HAL_SMBUS_Slave_Receive_IT(SMBUS_HandleTypeDef *hsmbus, uint8_t *pData, uint16_t Size,
1290                                              uint32_t XferOptions)
1291 {
1292   /* Check the parameters */
1293   assert_param(IS_SMBUS_TRANSFER_OPTIONS_REQUEST(XferOptions));
1294 
1295   if ((hsmbus->State & HAL_SMBUS_STATE_LISTEN) == HAL_SMBUS_STATE_LISTEN)
1296   {
1297     if ((pData == NULL) || (Size == 0UL))
1298     {
1299       hsmbus->ErrorCode = HAL_SMBUS_ERROR_INVALID_PARAM;
1300       return HAL_ERROR;
1301     }
1302 
1303     /* Disable Interrupts, to prevent preemption during treatment in case of multicall */
1304     SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_ADDR | SMBUS_IT_RX);
1305 
1306     /* Process Locked */
1307     __HAL_LOCK(hsmbus);
1308 
1309     hsmbus->State = (HAL_SMBUS_STATE_SLAVE_BUSY_RX | HAL_SMBUS_STATE_LISTEN);
1310     hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE;
1311 
1312     /* Set SBC bit to manage Acknowledge at each bit */
1313     hsmbus->Instance->CR1 |= I2C_CR1_SBC;
1314 
1315     /* Enable Address Acknowledge */
1316     hsmbus->Instance->CR2 &= ~I2C_CR2_NACK;
1317 
1318     /* Prepare transfer parameters */
1319     hsmbus->pBuffPtr = pData;
1320     hsmbus->XferSize = Size;
1321     hsmbus->XferCount = Size;
1322     hsmbus->XferOptions = XferOptions;
1323 
1324     /* Convert OTHER_xxx XferOptions if any */
1325     SMBUS_ConvertOtherXferOptions(hsmbus);
1326 
1327     /* Set NBYTE to receive */
1328     /* If XferSize equal "1", or XferSize equal "2" with PEC requested (mean 1 data byte + 1 PEC byte */
1329     /* no need to set RELOAD bit mode, a ACK will be automatically generated in that case */
1330     /* else need to set RELOAD bit mode to generate an automatic ACK at each byte Received */
1331     /* This RELOAD bit will be reset for last BYTE to be receive in SMBUS_Slave_ISR */
1332     if (((SMBUS_GET_PEC_MODE(hsmbus) != 0UL) && (hsmbus->XferSize == 2U)) || (hsmbus->XferSize == 1U))
1333     {
1334       SMBUS_TransferConfig(hsmbus, 0, (uint8_t)hsmbus->XferSize, hsmbus->XferOptions,
1335                            SMBUS_NO_STARTSTOP);
1336     }
1337     else
1338     {
1339       SMBUS_TransferConfig(hsmbus, 0, 1, hsmbus->XferOptions | SMBUS_RELOAD_MODE, SMBUS_NO_STARTSTOP);
1340     }
1341 
1342     /* Clear ADDR flag after prepare the transfer parameters */
1343     /* This action will generate an acknowledge to the HOST */
1344     __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_ADDR);
1345 
1346     /* Process Unlocked */
1347     __HAL_UNLOCK(hsmbus);
1348 
1349     /* Note : The SMBUS interrupts must be enabled after unlocking current process
1350               to avoid the risk of SMBUS interrupt handle execution before current
1351               process unlock */
1352     /* REnable ADDR interrupt */
1353     SMBUS_Enable_IRQ(hsmbus, SMBUS_IT_RX | SMBUS_IT_ADDR);
1354 
1355     return HAL_OK;
1356   }
1357   else
1358   {
1359     return HAL_BUSY;
1360   }
1361 }
1362 
1363 /**
1364   * @brief  Enable the Address listen mode with Interrupt.
1365   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
1366   *                the configuration information for the specified SMBUS.
1367   * @retval HAL status
1368   */
HAL_SMBUS_EnableListen_IT(SMBUS_HandleTypeDef * hsmbus)1369 HAL_StatusTypeDef HAL_SMBUS_EnableListen_IT(SMBUS_HandleTypeDef *hsmbus)
1370 {
1371   hsmbus->State = HAL_SMBUS_STATE_LISTEN;
1372 
1373   /* Enable the Address Match interrupt */
1374   SMBUS_Enable_IRQ(hsmbus, SMBUS_IT_ADDR);
1375 
1376   return HAL_OK;
1377 }
1378 
1379 /**
1380   * @brief  Disable the Address listen mode with Interrupt.
1381   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
1382   *                the configuration information for the specified SMBUS.
1383   * @retval HAL status
1384   */
HAL_SMBUS_DisableListen_IT(SMBUS_HandleTypeDef * hsmbus)1385 HAL_StatusTypeDef HAL_SMBUS_DisableListen_IT(SMBUS_HandleTypeDef *hsmbus)
1386 {
1387   /* Disable Address listen mode only if a transfer is not ongoing */
1388   if (hsmbus->State == HAL_SMBUS_STATE_LISTEN)
1389   {
1390     hsmbus->State = HAL_SMBUS_STATE_READY;
1391 
1392     /* Disable the Address Match interrupt */
1393     SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_ADDR);
1394 
1395     return HAL_OK;
1396   }
1397   else
1398   {
1399     return HAL_BUSY;
1400   }
1401 }
1402 
1403 /**
1404   * @brief  Enable the SMBUS alert mode with Interrupt.
1405   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
1406   *                the configuration information for the specified SMBUSx peripheral.
1407   * @retval HAL status
1408   */
HAL_SMBUS_EnableAlert_IT(SMBUS_HandleTypeDef * hsmbus)1409 HAL_StatusTypeDef HAL_SMBUS_EnableAlert_IT(SMBUS_HandleTypeDef *hsmbus)
1410 {
1411   /* Enable SMBus alert */
1412   hsmbus->Instance->CR1 |= I2C_CR1_ALERTEN;
1413 
1414   /* Clear ALERT flag */
1415   __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_ALERT);
1416 
1417   /* Enable Alert Interrupt */
1418   SMBUS_Enable_IRQ(hsmbus, SMBUS_IT_ALERT);
1419 
1420   return HAL_OK;
1421 }
1422 /**
1423   * @brief  Disable the SMBUS alert mode with Interrupt.
1424   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
1425   *                the configuration information for the specified SMBUSx peripheral.
1426   * @retval HAL status
1427   */
HAL_SMBUS_DisableAlert_IT(SMBUS_HandleTypeDef * hsmbus)1428 HAL_StatusTypeDef HAL_SMBUS_DisableAlert_IT(SMBUS_HandleTypeDef *hsmbus)
1429 {
1430   /* Enable SMBus alert */
1431   hsmbus->Instance->CR1 &= ~I2C_CR1_ALERTEN;
1432 
1433   /* Disable Alert Interrupt */
1434   SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_ALERT);
1435 
1436   return HAL_OK;
1437 }
1438 
1439 /**
1440   * @brief  Check if target device is ready for communication.
1441   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
1442   *                the configuration information for the specified SMBUS.
1443   * @param  DevAddress Target device address: The device 7 bits address value
1444   *         in datasheet must be shifted to the left before calling the interface
1445   * @param  Trials Number of trials
1446   * @param  Timeout Timeout duration
1447   * @retval HAL status
1448   */
HAL_SMBUS_IsDeviceReady(SMBUS_HandleTypeDef * hsmbus,uint16_t DevAddress,uint32_t Trials,uint32_t Timeout)1449 HAL_StatusTypeDef HAL_SMBUS_IsDeviceReady(SMBUS_HandleTypeDef *hsmbus, uint16_t DevAddress, uint32_t Trials,
1450                                           uint32_t Timeout)
1451 {
1452   uint32_t tickstart;
1453 
1454   __IO uint32_t SMBUS_Trials = 0UL;
1455 
1456   FlagStatus tmp1;
1457   FlagStatus tmp2;
1458 
1459   if (hsmbus->State == HAL_SMBUS_STATE_READY)
1460   {
1461     if (__HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_BUSY) != RESET)
1462     {
1463       return HAL_BUSY;
1464     }
1465 
1466     /* Process Locked */
1467     __HAL_LOCK(hsmbus);
1468 
1469     hsmbus->State = HAL_SMBUS_STATE_BUSY;
1470     hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE;
1471 
1472     do
1473     {
1474       /* Generate Start */
1475       hsmbus->Instance->CR2 = SMBUS_GENERATE_START(hsmbus->Init.AddressingMode, DevAddress);
1476 
1477       /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
1478       /* Wait until STOPF flag is set or a NACK flag is set*/
1479       tickstart = HAL_GetTick();
1480 
1481       tmp1 = __HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_STOPF);
1482       tmp2 = __HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_AF);
1483 
1484       while ((tmp1 == RESET) && (tmp2 == RESET))
1485       {
1486         if (Timeout != HAL_MAX_DELAY)
1487         {
1488           if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0UL))
1489           {
1490             /* Device is ready */
1491             hsmbus->State = HAL_SMBUS_STATE_READY;
1492 
1493             /* Update SMBUS error code */
1494             hsmbus->ErrorCode |= HAL_SMBUS_ERROR_HALTIMEOUT;
1495 
1496             /* Process Unlocked */
1497             __HAL_UNLOCK(hsmbus);
1498             return HAL_ERROR;
1499           }
1500         }
1501 
1502         tmp1 = __HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_STOPF);
1503         tmp2 = __HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_AF);
1504       }
1505 
1506       /* Check if the NACKF flag has not been set */
1507       if (__HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_AF) == RESET)
1508       {
1509         /* Wait until STOPF flag is reset */
1510         if (SMBUS_WaitOnFlagUntilTimeout(hsmbus, SMBUS_FLAG_STOPF, RESET, Timeout) != HAL_OK)
1511         {
1512           return HAL_ERROR;
1513         }
1514 
1515         /* Clear STOP Flag */
1516         __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_STOPF);
1517 
1518         /* Device is ready */
1519         hsmbus->State = HAL_SMBUS_STATE_READY;
1520 
1521         /* Process Unlocked */
1522         __HAL_UNLOCK(hsmbus);
1523 
1524         return HAL_OK;
1525       }
1526       else
1527       {
1528         /* Wait until STOPF flag is reset */
1529         if (SMBUS_WaitOnFlagUntilTimeout(hsmbus, SMBUS_FLAG_STOPF, RESET, Timeout) != HAL_OK)
1530         {
1531           return HAL_ERROR;
1532         }
1533 
1534         /* Clear NACK Flag */
1535         __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_AF);
1536 
1537         /* Clear STOP Flag, auto generated with autoend*/
1538         __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_STOPF);
1539       }
1540 
1541       /* Check if the maximum allowed number of trials has been reached */
1542       if (SMBUS_Trials == Trials)
1543       {
1544         /* Generate Stop */
1545         hsmbus->Instance->CR2 |= I2C_CR2_STOP;
1546 
1547         /* Wait until STOPF flag is reset */
1548         if (SMBUS_WaitOnFlagUntilTimeout(hsmbus, SMBUS_FLAG_STOPF, RESET, Timeout) != HAL_OK)
1549         {
1550           return HAL_ERROR;
1551         }
1552 
1553         /* Clear STOP Flag */
1554         __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_STOPF);
1555       }
1556 
1557       /* Increment Trials */
1558       SMBUS_Trials++;
1559     } while (SMBUS_Trials < Trials);
1560 
1561     hsmbus->State = HAL_SMBUS_STATE_READY;
1562 
1563     /* Update SMBUS error code */
1564     hsmbus->ErrorCode |= HAL_SMBUS_ERROR_HALTIMEOUT;
1565 
1566     /* Process Unlocked */
1567     __HAL_UNLOCK(hsmbus);
1568 
1569     return HAL_ERROR;
1570   }
1571   else
1572   {
1573     return HAL_BUSY;
1574   }
1575 }
1576 /**
1577   * @}
1578   */
1579 
1580 /** @defgroup SMBUS_IRQ_Handler_and_Callbacks IRQ Handler and Callbacks
1581   * @{
1582   */
1583 
1584 /**
1585   * @brief  Handle SMBUS event interrupt request.
1586   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
1587   *                the configuration information for the specified SMBUS.
1588   * @retval None
1589   */
HAL_SMBUS_EV_IRQHandler(SMBUS_HandleTypeDef * hsmbus)1590 void HAL_SMBUS_EV_IRQHandler(SMBUS_HandleTypeDef *hsmbus)
1591 {
1592   /* Use a local variable to store the current ISR flags */
1593   /* This action will avoid a wrong treatment due to ISR flags change during interrupt handler */
1594   uint32_t tmpisrvalue = READ_REG(hsmbus->Instance->ISR);
1595   uint32_t tmpcr1value = READ_REG(hsmbus->Instance->CR1);
1596 
1597   /* SMBUS in mode Transmitter ---------------------------------------------------*/
1598   if ((SMBUS_CHECK_IT_SOURCE(tmpcr1value, (SMBUS_IT_TCI | SMBUS_IT_STOPI |
1599                                            SMBUS_IT_NACKI | SMBUS_IT_TXI)) != RESET) &&
1600       ((SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_TXIS) != RESET) ||
1601        (SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_TCR) != RESET) ||
1602        (SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_TC) != RESET) ||
1603        (SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_STOPF) != RESET) ||
1604        (SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_AF) != RESET)))
1605   {
1606     /* Slave mode selected */
1607     if ((hsmbus->State & HAL_SMBUS_STATE_SLAVE_BUSY_TX) == HAL_SMBUS_STATE_SLAVE_BUSY_TX)
1608     {
1609       (void)SMBUS_Slave_ISR(hsmbus, tmpisrvalue);
1610     }
1611     /* Master mode selected */
1612     else if ((hsmbus->State & HAL_SMBUS_STATE_MASTER_BUSY_TX) == HAL_SMBUS_STATE_MASTER_BUSY_TX)
1613     {
1614       (void)SMBUS_Master_ISR(hsmbus, tmpisrvalue);
1615     }
1616     else
1617     {
1618       /* Nothing to do */
1619     }
1620   }
1621 
1622   /* SMBUS in mode Receiver ----------------------------------------------------*/
1623   if ((SMBUS_CHECK_IT_SOURCE(tmpcr1value, (SMBUS_IT_TCI | SMBUS_IT_STOPI |
1624                                            SMBUS_IT_NACKI | SMBUS_IT_RXI)) != RESET) &&
1625       ((SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_RXNE) != RESET) ||
1626        (SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_TCR) != RESET) ||
1627        (SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_TC) != RESET) ||
1628        (SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_STOPF) != RESET) ||
1629        (SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_AF) != RESET)))
1630   {
1631     /* Slave mode selected */
1632     if ((hsmbus->State & HAL_SMBUS_STATE_SLAVE_BUSY_RX) == HAL_SMBUS_STATE_SLAVE_BUSY_RX)
1633     {
1634       (void)SMBUS_Slave_ISR(hsmbus, tmpisrvalue);
1635     }
1636     /* Master mode selected */
1637     else if ((hsmbus->State & HAL_SMBUS_STATE_MASTER_BUSY_RX) == HAL_SMBUS_STATE_MASTER_BUSY_RX)
1638     {
1639       (void)SMBUS_Master_ISR(hsmbus, tmpisrvalue);
1640     }
1641     else
1642     {
1643       /* Nothing to do */
1644     }
1645   }
1646 
1647   /* SMBUS in mode Listener Only --------------------------------------------------*/
1648   if (((SMBUS_CHECK_IT_SOURCE(tmpcr1value, SMBUS_IT_ADDRI) != RESET) ||
1649        (SMBUS_CHECK_IT_SOURCE(tmpcr1value, SMBUS_IT_STOPI) != RESET) ||
1650        (SMBUS_CHECK_IT_SOURCE(tmpcr1value, SMBUS_IT_NACKI) != RESET)) &&
1651       ((SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_ADDR) != RESET) ||
1652        (SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_STOPF) != RESET) ||
1653        (SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_AF) != RESET)))
1654   {
1655     if ((hsmbus->State & HAL_SMBUS_STATE_LISTEN) == HAL_SMBUS_STATE_LISTEN)
1656     {
1657       (void)SMBUS_Slave_ISR(hsmbus, tmpisrvalue);
1658     }
1659   }
1660 }
1661 
1662 /**
1663   * @brief  Handle SMBUS error interrupt request.
1664   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
1665   *                the configuration information for the specified SMBUS.
1666   * @retval None
1667   */
HAL_SMBUS_ER_IRQHandler(SMBUS_HandleTypeDef * hsmbus)1668 void HAL_SMBUS_ER_IRQHandler(SMBUS_HandleTypeDef *hsmbus)
1669 {
1670   SMBUS_ITErrorHandler(hsmbus);
1671 }
1672 
1673 /**
1674   * @brief  Master Tx Transfer completed callback.
1675   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
1676   *                the configuration information for the specified SMBUS.
1677   * @retval None
1678   */
HAL_SMBUS_MasterTxCpltCallback(SMBUS_HandleTypeDef * hsmbus)1679 __weak void HAL_SMBUS_MasterTxCpltCallback(SMBUS_HandleTypeDef *hsmbus)
1680 {
1681   /* Prevent unused argument(s) compilation warning */
1682   UNUSED(hsmbus);
1683 
1684   /* NOTE : This function should not be modified, when the callback is needed,
1685             the HAL_SMBUS_MasterTxCpltCallback() could be implemented in the user file
1686    */
1687 }
1688 
1689 /**
1690   * @brief  Master Rx Transfer completed callback.
1691   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
1692   *                the configuration information for the specified SMBUS.
1693   * @retval None
1694   */
HAL_SMBUS_MasterRxCpltCallback(SMBUS_HandleTypeDef * hsmbus)1695 __weak void HAL_SMBUS_MasterRxCpltCallback(SMBUS_HandleTypeDef *hsmbus)
1696 {
1697   /* Prevent unused argument(s) compilation warning */
1698   UNUSED(hsmbus);
1699 
1700   /* NOTE : This function should not be modified, when the callback is needed,
1701             the HAL_SMBUS_MasterRxCpltCallback() could be implemented in the user file
1702    */
1703 }
1704 
1705 /** @brief  Slave Tx Transfer completed callback.
1706   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
1707   *                the configuration information for the specified SMBUS.
1708   * @retval None
1709   */
HAL_SMBUS_SlaveTxCpltCallback(SMBUS_HandleTypeDef * hsmbus)1710 __weak void HAL_SMBUS_SlaveTxCpltCallback(SMBUS_HandleTypeDef *hsmbus)
1711 {
1712   /* Prevent unused argument(s) compilation warning */
1713   UNUSED(hsmbus);
1714 
1715   /* NOTE : This function should not be modified, when the callback is needed,
1716             the HAL_SMBUS_SlaveTxCpltCallback() could be implemented in the user file
1717    */
1718 }
1719 
1720 /**
1721   * @brief  Slave Rx Transfer completed callback.
1722   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
1723   *                the configuration information for the specified SMBUS.
1724   * @retval None
1725   */
HAL_SMBUS_SlaveRxCpltCallback(SMBUS_HandleTypeDef * hsmbus)1726 __weak void HAL_SMBUS_SlaveRxCpltCallback(SMBUS_HandleTypeDef *hsmbus)
1727 {
1728   /* Prevent unused argument(s) compilation warning */
1729   UNUSED(hsmbus);
1730 
1731   /* NOTE : This function should not be modified, when the callback is needed,
1732             the HAL_SMBUS_SlaveRxCpltCallback() could be implemented in the user file
1733    */
1734 }
1735 
1736 /**
1737   * @brief  Slave Address Match callback.
1738   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
1739   *                the configuration information for the specified SMBUS.
1740   * @param  TransferDirection Master request Transfer Direction (Write/Read)
1741   * @param  AddrMatchCode Address Match Code
1742   * @retval None
1743   */
HAL_SMBUS_AddrCallback(SMBUS_HandleTypeDef * hsmbus,uint8_t TransferDirection,uint16_t AddrMatchCode)1744 __weak void HAL_SMBUS_AddrCallback(SMBUS_HandleTypeDef *hsmbus, uint8_t TransferDirection,
1745                                    uint16_t AddrMatchCode)
1746 {
1747   /* Prevent unused argument(s) compilation warning */
1748   UNUSED(hsmbus);
1749   UNUSED(TransferDirection);
1750   UNUSED(AddrMatchCode);
1751 
1752   /* NOTE : This function should not be modified, when the callback is needed,
1753             the HAL_SMBUS_AddrCallback() could be implemented in the user file
1754    */
1755 }
1756 
1757 /**
1758   * @brief  Listen Complete callback.
1759   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
1760   *                the configuration information for the specified SMBUS.
1761   * @retval None
1762   */
HAL_SMBUS_ListenCpltCallback(SMBUS_HandleTypeDef * hsmbus)1763 __weak void HAL_SMBUS_ListenCpltCallback(SMBUS_HandleTypeDef *hsmbus)
1764 {
1765   /* Prevent unused argument(s) compilation warning */
1766   UNUSED(hsmbus);
1767 
1768   /* NOTE : This function should not be modified, when the callback is needed,
1769             the HAL_SMBUS_ListenCpltCallback() could be implemented in the user file
1770    */
1771 }
1772 
1773 /**
1774   * @brief  SMBUS error callback.
1775   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
1776   *                the configuration information for the specified SMBUS.
1777   * @retval None
1778   */
HAL_SMBUS_ErrorCallback(SMBUS_HandleTypeDef * hsmbus)1779 __weak void HAL_SMBUS_ErrorCallback(SMBUS_HandleTypeDef *hsmbus)
1780 {
1781   /* Prevent unused argument(s) compilation warning */
1782   UNUSED(hsmbus);
1783 
1784   /* NOTE : This function should not be modified, when the callback is needed,
1785             the HAL_SMBUS_ErrorCallback() could be implemented in the user file
1786    */
1787 }
1788 
1789 /**
1790   * @}
1791   */
1792 
1793 /** @defgroup SMBUS_Exported_Functions_Group3 Peripheral State and Errors functions
1794   *  @brief   Peripheral State and Errors functions
1795   *
1796 @verbatim
1797  ===============================================================================
1798             ##### Peripheral State and Errors functions #####
1799  ===============================================================================
1800     [..]
1801     This subsection permits to get in run-time the status of the peripheral
1802     and the data flow.
1803 
1804 @endverbatim
1805   * @{
1806   */
1807 
1808 /**
1809   * @brief  Return the SMBUS handle state.
1810   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
1811   *                the configuration information for the specified SMBUS.
1812   * @retval HAL state
1813   */
HAL_SMBUS_GetState(SMBUS_HandleTypeDef * hsmbus)1814 uint32_t HAL_SMBUS_GetState(SMBUS_HandleTypeDef *hsmbus)
1815 {
1816   /* Return SMBUS handle state */
1817   return hsmbus->State;
1818 }
1819 
1820 /**
1821   * @brief  Return the SMBUS error code.
1822   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
1823   *              the configuration information for the specified SMBUS.
1824   * @retval SMBUS Error Code
1825   */
HAL_SMBUS_GetError(SMBUS_HandleTypeDef * hsmbus)1826 uint32_t HAL_SMBUS_GetError(SMBUS_HandleTypeDef *hsmbus)
1827 {
1828   return hsmbus->ErrorCode;
1829 }
1830 
1831 /**
1832   * @}
1833   */
1834 
1835 /**
1836   * @}
1837   */
1838 
1839 /** @addtogroup SMBUS_Private_Functions SMBUS Private Functions
1840   *  @brief   Data transfers Private functions
1841   * @{
1842   */
1843 
1844 /**
1845   * @brief  Interrupt Sub-Routine which handle the Interrupt Flags Master Mode.
1846   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
1847   *                the configuration information for the specified SMBUS.
1848   * @param  StatusFlags Value of Interrupt Flags.
1849   * @retval HAL status
1850   */
SMBUS_Master_ISR(SMBUS_HandleTypeDef * hsmbus,uint32_t StatusFlags)1851 static HAL_StatusTypeDef SMBUS_Master_ISR(SMBUS_HandleTypeDef *hsmbus, uint32_t StatusFlags)
1852 {
1853   uint16_t DevAddress;
1854 
1855   /* Process Locked */
1856   __HAL_LOCK(hsmbus);
1857 
1858   if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_AF) != RESET)
1859   {
1860     /* Clear NACK Flag */
1861     __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_AF);
1862 
1863     /* Set corresponding Error Code */
1864     /* No need to generate STOP, it is automatically done */
1865     hsmbus->ErrorCode |= HAL_SMBUS_ERROR_ACKF;
1866 
1867     /* Flush TX register */
1868     SMBUS_Flush_TXDR(hsmbus);
1869 
1870     /* Process Unlocked */
1871     __HAL_UNLOCK(hsmbus);
1872 
1873     /* Call the Error callback to inform upper layer */
1874 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
1875     hsmbus->ErrorCallback(hsmbus);
1876 #else
1877     HAL_SMBUS_ErrorCallback(hsmbus);
1878 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
1879   }
1880   else if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_STOPF) != RESET)
1881   {
1882     /* Check and treat errors if errors occurs during STOP process */
1883     SMBUS_ITErrorHandler(hsmbus);
1884 
1885     /* Call the corresponding callback to inform upper layer of End of Transfer */
1886     if (hsmbus->State == HAL_SMBUS_STATE_MASTER_BUSY_TX)
1887     {
1888       /* Disable Interrupt */
1889       SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_TX);
1890 
1891       /* Clear STOP Flag */
1892       __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_STOPF);
1893 
1894       /* Clear Configuration Register 2 */
1895       SMBUS_RESET_CR2(hsmbus);
1896 
1897       /* Flush remaining data in Fifo register in case of error occurs before TXEmpty */
1898       /* Disable the selected SMBUS peripheral */
1899       __HAL_SMBUS_DISABLE(hsmbus);
1900 
1901       hsmbus->PreviousState = HAL_SMBUS_STATE_READY;
1902       hsmbus->State = HAL_SMBUS_STATE_READY;
1903 
1904       /* Process Unlocked */
1905       __HAL_UNLOCK(hsmbus);
1906 
1907       /* Re-enable the selected SMBUS peripheral */
1908       __HAL_SMBUS_ENABLE(hsmbus);
1909 
1910       /* Call the corresponding callback to inform upper layer of End of Transfer */
1911 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
1912       hsmbus->MasterTxCpltCallback(hsmbus);
1913 #else
1914       HAL_SMBUS_MasterTxCpltCallback(hsmbus);
1915 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
1916     }
1917     else if (hsmbus->State == HAL_SMBUS_STATE_MASTER_BUSY_RX)
1918     {
1919       /* Store Last receive data if any */
1920       if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_RXNE) != RESET)
1921       {
1922         /* Read data from RXDR */
1923         *hsmbus->pBuffPtr = (uint8_t)(hsmbus->Instance->RXDR);
1924 
1925         /* Increment Buffer pointer */
1926         hsmbus->pBuffPtr++;
1927 
1928         if ((hsmbus->XferSize > 0U))
1929         {
1930           hsmbus->XferSize--;
1931           hsmbus->XferCount--;
1932         }
1933       }
1934 
1935       /* Disable Interrupt */
1936       SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_RX);
1937 
1938       /* Clear STOP Flag */
1939       __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_STOPF);
1940 
1941       /* Clear Configuration Register 2 */
1942       SMBUS_RESET_CR2(hsmbus);
1943 
1944       hsmbus->PreviousState = HAL_SMBUS_STATE_READY;
1945       hsmbus->State = HAL_SMBUS_STATE_READY;
1946 
1947       /* Process Unlocked */
1948       __HAL_UNLOCK(hsmbus);
1949 
1950       /* Call the corresponding callback to inform upper layer of End of Transfer */
1951 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
1952       hsmbus->MasterRxCpltCallback(hsmbus);
1953 #else
1954       HAL_SMBUS_MasterRxCpltCallback(hsmbus);
1955 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
1956     }
1957     else
1958     {
1959       /* Nothing to do */
1960     }
1961   }
1962   else if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_RXNE) != RESET)
1963   {
1964     /* Read data from RXDR */
1965     *hsmbus->pBuffPtr = (uint8_t)(hsmbus->Instance->RXDR);
1966 
1967     /* Increment Buffer pointer */
1968     hsmbus->pBuffPtr++;
1969 
1970     /* Increment Size counter */
1971     hsmbus->XferSize--;
1972     hsmbus->XferCount--;
1973   }
1974   else if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_TXIS) != RESET)
1975   {
1976     /* Write data to TXDR */
1977     hsmbus->Instance->TXDR = *hsmbus->pBuffPtr;
1978 
1979     /* Increment Buffer pointer */
1980     hsmbus->pBuffPtr++;
1981 
1982     /* Increment Size counter */
1983     hsmbus->XferSize--;
1984     hsmbus->XferCount--;
1985   }
1986   else if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_TCR) != RESET)
1987   {
1988     if ((hsmbus->XferCount != 0U) && (hsmbus->XferSize == 0U))
1989     {
1990       DevAddress = (uint16_t)(hsmbus->Instance->CR2 & I2C_CR2_SADD);
1991 
1992       if (hsmbus->XferCount > MAX_NBYTE_SIZE)
1993       {
1994         SMBUS_TransferConfig(hsmbus, DevAddress, MAX_NBYTE_SIZE,
1995                              (SMBUS_RELOAD_MODE | (hsmbus->XferOptions & SMBUS_SENDPEC_MODE)),
1996                              SMBUS_NO_STARTSTOP);
1997         hsmbus->XferSize = MAX_NBYTE_SIZE;
1998       }
1999       else
2000       {
2001         hsmbus->XferSize = hsmbus->XferCount;
2002         SMBUS_TransferConfig(hsmbus, DevAddress, (uint8_t)hsmbus->XferSize, hsmbus->XferOptions,
2003                              SMBUS_NO_STARTSTOP);
2004         /* If PEC mode is enable, size to transmit should be Size-1 byte, corresponding to PEC byte */
2005         /* PEC byte is automatically sent by HW block, no need to manage it in Transmit process */
2006         if (SMBUS_GET_PEC_MODE(hsmbus) != 0UL)
2007         {
2008           hsmbus->XferSize--;
2009           hsmbus->XferCount--;
2010         }
2011       }
2012     }
2013     else if ((hsmbus->XferCount == 0U) && (hsmbus->XferSize == 0U))
2014     {
2015       /* Call TxCpltCallback() if no stop mode is set */
2016       if (SMBUS_GET_STOP_MODE(hsmbus) != SMBUS_AUTOEND_MODE)
2017       {
2018         /* Call the corresponding callback to inform upper layer of End of Transfer */
2019         if (hsmbus->State == HAL_SMBUS_STATE_MASTER_BUSY_TX)
2020         {
2021           /* Disable Interrupt */
2022           SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_TX);
2023           hsmbus->PreviousState = hsmbus->State;
2024           hsmbus->State = HAL_SMBUS_STATE_READY;
2025 
2026           /* Process Unlocked */
2027           __HAL_UNLOCK(hsmbus);
2028 
2029           /* Call the corresponding callback to inform upper layer of End of Transfer */
2030 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
2031           hsmbus->MasterTxCpltCallback(hsmbus);
2032 #else
2033           HAL_SMBUS_MasterTxCpltCallback(hsmbus);
2034 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
2035         }
2036         else if (hsmbus->State == HAL_SMBUS_STATE_MASTER_BUSY_RX)
2037         {
2038           SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_RX);
2039           hsmbus->PreviousState = hsmbus->State;
2040           hsmbus->State = HAL_SMBUS_STATE_READY;
2041 
2042           /* Process Unlocked */
2043           __HAL_UNLOCK(hsmbus);
2044 
2045           /* Call the corresponding callback to inform upper layer of End of Transfer */
2046 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
2047           hsmbus->MasterRxCpltCallback(hsmbus);
2048 #else
2049           HAL_SMBUS_MasterRxCpltCallback(hsmbus);
2050 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
2051         }
2052         else
2053         {
2054           /* Nothing to do */
2055         }
2056       }
2057     }
2058     else
2059     {
2060       /* Nothing to do */
2061     }
2062   }
2063   else if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_TC) != RESET)
2064   {
2065     if (hsmbus->XferCount == 0U)
2066     {
2067       /* Specific use case for Quick command */
2068       if (hsmbus->pBuffPtr == NULL)
2069       {
2070         /* Generate a Stop command */
2071         hsmbus->Instance->CR2 |= I2C_CR2_STOP;
2072       }
2073       /* Call TxCpltCallback() if no stop mode is set */
2074       else if (SMBUS_GET_STOP_MODE(hsmbus) != SMBUS_AUTOEND_MODE)
2075       {
2076         /* No Generate Stop, to permit restart mode */
2077         /* The stop will be done at the end of transfer, when SMBUS_AUTOEND_MODE enable */
2078 
2079         /* Call the corresponding callback to inform upper layer of End of Transfer */
2080         if (hsmbus->State == HAL_SMBUS_STATE_MASTER_BUSY_TX)
2081         {
2082           /* Disable Interrupt */
2083           SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_TX);
2084           hsmbus->PreviousState = hsmbus->State;
2085           hsmbus->State = HAL_SMBUS_STATE_READY;
2086 
2087           /* Process Unlocked */
2088           __HAL_UNLOCK(hsmbus);
2089 
2090           /* Call the corresponding callback to inform upper layer of End of Transfer */
2091 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
2092           hsmbus->MasterTxCpltCallback(hsmbus);
2093 #else
2094           HAL_SMBUS_MasterTxCpltCallback(hsmbus);
2095 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
2096         }
2097         else if (hsmbus->State == HAL_SMBUS_STATE_MASTER_BUSY_RX)
2098         {
2099           SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_RX);
2100           hsmbus->PreviousState = hsmbus->State;
2101           hsmbus->State = HAL_SMBUS_STATE_READY;
2102 
2103           /* Process Unlocked */
2104           __HAL_UNLOCK(hsmbus);
2105 
2106           /* Call the corresponding callback to inform upper layer of End of Transfer */
2107 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
2108           hsmbus->MasterRxCpltCallback(hsmbus);
2109 #else
2110           HAL_SMBUS_MasterRxCpltCallback(hsmbus);
2111 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
2112         }
2113         else
2114         {
2115           /* Nothing to do */
2116         }
2117       }
2118       else
2119       {
2120         /* Nothing to do */
2121       }
2122     }
2123   }
2124   else
2125   {
2126     /* Nothing to do */
2127   }
2128 
2129   /* Process Unlocked */
2130   __HAL_UNLOCK(hsmbus);
2131 
2132   return HAL_OK;
2133 }
2134 /**
2135   * @brief  Interrupt Sub-Routine which handle the Interrupt Flags Slave Mode.
2136   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
2137   *                the configuration information for the specified SMBUS.
2138   * @param  StatusFlags Value of Interrupt Flags.
2139   * @retval HAL status
2140   */
SMBUS_Slave_ISR(SMBUS_HandleTypeDef * hsmbus,uint32_t StatusFlags)2141 static HAL_StatusTypeDef SMBUS_Slave_ISR(SMBUS_HandleTypeDef *hsmbus, uint32_t StatusFlags)
2142 {
2143   uint8_t TransferDirection;
2144   uint16_t SlaveAddrCode;
2145 
2146   /* Process Locked */
2147   __HAL_LOCK(hsmbus);
2148 
2149   if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_AF) != RESET)
2150   {
2151     /* Check that SMBUS transfer finished */
2152     /* if yes, normal usecase, a NACK is sent by the HOST when Transfer is finished */
2153     /* Mean XferCount == 0*/
2154     /* So clear Flag NACKF only */
2155     if (hsmbus->XferCount == 0U)
2156     {
2157       /* Clear NACK Flag */
2158       __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_AF);
2159 
2160       /* Flush TX register */
2161       SMBUS_Flush_TXDR(hsmbus);
2162 
2163       /* Process Unlocked */
2164       __HAL_UNLOCK(hsmbus);
2165     }
2166     else
2167     {
2168       /* if no, error usecase, a Non-Acknowledge of last Data is generated by the HOST*/
2169       /* Clear NACK Flag */
2170       __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_AF);
2171 
2172       /* Set HAL State to "Idle" State, mean to LISTEN state */
2173       /* So reset Slave Busy state */
2174       hsmbus->PreviousState = hsmbus->State;
2175       hsmbus->State &= ~((uint32_t)HAL_SMBUS_STATE_SLAVE_BUSY_TX);
2176       hsmbus->State &= ~((uint32_t)HAL_SMBUS_STATE_SLAVE_BUSY_RX);
2177 
2178       /* Disable RX/TX Interrupts, keep only ADDR Interrupt */
2179       SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_RX | SMBUS_IT_TX);
2180 
2181       /* Set ErrorCode corresponding to a Non-Acknowledge */
2182       hsmbus->ErrorCode |= HAL_SMBUS_ERROR_ACKF;
2183 
2184       /* Flush TX register */
2185       SMBUS_Flush_TXDR(hsmbus);
2186 
2187       /* Process Unlocked */
2188       __HAL_UNLOCK(hsmbus);
2189 
2190       /* Call the Error callback to inform upper layer */
2191 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
2192       hsmbus->ErrorCallback(hsmbus);
2193 #else
2194       HAL_SMBUS_ErrorCallback(hsmbus);
2195 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
2196     }
2197   }
2198   else if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_ADDR) != RESET)
2199   {
2200     TransferDirection = (uint8_t)(SMBUS_GET_DIR(hsmbus));
2201     SlaveAddrCode = (uint16_t)(SMBUS_GET_ADDR_MATCH(hsmbus));
2202 
2203     /* Disable ADDR interrupt to prevent multiple ADDRInterrupt*/
2204     /* Other ADDRInterrupt will be treat in next Listen usecase */
2205     __HAL_SMBUS_DISABLE_IT(hsmbus, SMBUS_IT_ADDRI);
2206 
2207     /* Process Unlocked */
2208     __HAL_UNLOCK(hsmbus);
2209 
2210     /* Call Slave Addr callback */
2211 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
2212     hsmbus->AddrCallback(hsmbus, TransferDirection, SlaveAddrCode);
2213 #else
2214     HAL_SMBUS_AddrCallback(hsmbus, TransferDirection, SlaveAddrCode);
2215 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
2216   }
2217   else if ((SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_RXNE) != RESET) ||
2218            (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_TCR) != RESET))
2219   {
2220     if ((hsmbus->State & HAL_SMBUS_STATE_SLAVE_BUSY_RX) == HAL_SMBUS_STATE_SLAVE_BUSY_RX)
2221     {
2222       /* Read data from RXDR */
2223       *hsmbus->pBuffPtr = (uint8_t)(hsmbus->Instance->RXDR);
2224 
2225       /* Increment Buffer pointer */
2226       hsmbus->pBuffPtr++;
2227 
2228       hsmbus->XferSize--;
2229       hsmbus->XferCount--;
2230 
2231       if (hsmbus->XferCount == 1U)
2232       {
2233         /* Receive last Byte, can be PEC byte in case of PEC BYTE enabled */
2234         /* or only the last Byte of Transfer */
2235         /* So reset the RELOAD bit mode */
2236         hsmbus->XferOptions &= ~SMBUS_RELOAD_MODE;
2237         SMBUS_TransferConfig(hsmbus, 0, 1, hsmbus->XferOptions, SMBUS_NO_STARTSTOP);
2238       }
2239       else if (hsmbus->XferCount == 0U)
2240       {
2241         /* Last Byte is received, disable Interrupt */
2242         SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_RX);
2243 
2244         /* Remove HAL_SMBUS_STATE_SLAVE_BUSY_RX, keep only HAL_SMBUS_STATE_LISTEN */
2245         hsmbus->PreviousState = hsmbus->State;
2246         hsmbus->State &= ~((uint32_t)HAL_SMBUS_STATE_SLAVE_BUSY_RX);
2247 
2248         /* Process Unlocked */
2249         __HAL_UNLOCK(hsmbus);
2250 
2251         /* Call the corresponding callback to inform upper layer of End of Transfer */
2252 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
2253         hsmbus->SlaveRxCpltCallback(hsmbus);
2254 #else
2255         HAL_SMBUS_SlaveRxCpltCallback(hsmbus);
2256 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
2257       }
2258       else
2259       {
2260         /* Set Reload for next Bytes */
2261         SMBUS_TransferConfig(hsmbus, 0, 1,
2262                              SMBUS_RELOAD_MODE  | (hsmbus->XferOptions & SMBUS_SENDPEC_MODE),
2263                              SMBUS_NO_STARTSTOP);
2264 
2265         /* Ack last Byte Read */
2266         hsmbus->Instance->CR2 &= ~I2C_CR2_NACK;
2267       }
2268     }
2269     else if ((hsmbus->State & HAL_SMBUS_STATE_SLAVE_BUSY_TX) == HAL_SMBUS_STATE_SLAVE_BUSY_TX)
2270     {
2271       if ((hsmbus->XferCount != 0U) && (hsmbus->XferSize == 0U))
2272       {
2273         if (hsmbus->XferCount > MAX_NBYTE_SIZE)
2274         {
2275           SMBUS_TransferConfig(hsmbus, 0, MAX_NBYTE_SIZE,
2276                                (SMBUS_RELOAD_MODE | (hsmbus->XferOptions & SMBUS_SENDPEC_MODE)),
2277                                SMBUS_NO_STARTSTOP);
2278           hsmbus->XferSize = MAX_NBYTE_SIZE;
2279         }
2280         else
2281         {
2282           hsmbus->XferSize = hsmbus->XferCount;
2283           SMBUS_TransferConfig(hsmbus, 0, (uint8_t)hsmbus->XferSize, hsmbus->XferOptions,
2284                                SMBUS_NO_STARTSTOP);
2285           /* If PEC mode is enable, size to transmit should be Size-1 byte, corresponding to PEC byte */
2286           /* PEC byte is automatically sent by HW block, no need to manage it in Transmit process */
2287           if (SMBUS_GET_PEC_MODE(hsmbus) != 0UL)
2288           {
2289             hsmbus->XferSize--;
2290             hsmbus->XferCount--;
2291           }
2292         }
2293       }
2294     }
2295     else
2296     {
2297       /* Nothing to do */
2298     }
2299   }
2300   else if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_TXIS) != RESET)
2301   {
2302     /* Write data to TXDR only if XferCount not reach "0" */
2303     /* A TXIS flag can be set, during STOP treatment      */
2304     /* Check if all Data have already been sent */
2305     /* If it is the case, this last write in TXDR is not sent, correspond to a dummy TXIS event */
2306     if (hsmbus->XferCount > 0U)
2307     {
2308       /* Write data to TXDR */
2309       hsmbus->Instance->TXDR = *hsmbus->pBuffPtr;
2310 
2311       /* Increment Buffer pointer */
2312       hsmbus->pBuffPtr++;
2313 
2314       hsmbus->XferCount--;
2315       hsmbus->XferSize--;
2316     }
2317 
2318     if (hsmbus->XferCount == 0U)
2319     {
2320       /* Last Byte is Transmitted */
2321       /* Remove HAL_SMBUS_STATE_SLAVE_BUSY_TX, keep only HAL_SMBUS_STATE_LISTEN */
2322       SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_TX);
2323       hsmbus->PreviousState = hsmbus->State;
2324       hsmbus->State &= ~((uint32_t)HAL_SMBUS_STATE_SLAVE_BUSY_TX);
2325 
2326       /* Process Unlocked */
2327       __HAL_UNLOCK(hsmbus);
2328 
2329       /* Call the corresponding callback to inform upper layer of End of Transfer */
2330 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
2331       hsmbus->SlaveTxCpltCallback(hsmbus);
2332 #else
2333       HAL_SMBUS_SlaveTxCpltCallback(hsmbus);
2334 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
2335     }
2336   }
2337   else
2338   {
2339     /* Nothing to do */
2340   }
2341 
2342   /* Check if STOPF is set */
2343   if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_STOPF) != RESET)
2344   {
2345     if ((hsmbus->State & HAL_SMBUS_STATE_LISTEN) == HAL_SMBUS_STATE_LISTEN)
2346     {
2347       /* Store Last receive data if any */
2348       if (__HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_RXNE) != RESET)
2349       {
2350         /* Read data from RXDR */
2351         *hsmbus->pBuffPtr = (uint8_t)(hsmbus->Instance->RXDR);
2352 
2353         /* Increment Buffer pointer */
2354         hsmbus->pBuffPtr++;
2355 
2356         if ((hsmbus->XferSize > 0U))
2357         {
2358           hsmbus->XferSize--;
2359           hsmbus->XferCount--;
2360         }
2361       }
2362 
2363       /* Disable RX and TX Interrupts */
2364       SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_RX | SMBUS_IT_TX);
2365 
2366       /* Disable ADDR Interrupt */
2367       SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_ADDR);
2368 
2369       /* Disable Address Acknowledge */
2370       hsmbus->Instance->CR2 |= I2C_CR2_NACK;
2371 
2372       /* Clear Configuration Register 2 */
2373       SMBUS_RESET_CR2(hsmbus);
2374 
2375       /* Clear STOP Flag */
2376       __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_STOPF);
2377 
2378       /* Clear ADDR flag */
2379       __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_ADDR);
2380 
2381       hsmbus->XferOptions = 0;
2382       hsmbus->PreviousState = hsmbus->State;
2383       hsmbus->State = HAL_SMBUS_STATE_READY;
2384 
2385       /* Process Unlocked */
2386       __HAL_UNLOCK(hsmbus);
2387 
2388       /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */
2389 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
2390       hsmbus->ListenCpltCallback(hsmbus);
2391 #else
2392       HAL_SMBUS_ListenCpltCallback(hsmbus);
2393 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
2394     }
2395   }
2396 
2397   /* Process Unlocked */
2398   __HAL_UNLOCK(hsmbus);
2399 
2400   return HAL_OK;
2401 }
2402 /**
2403   * @brief  Manage the enabling of Interrupts.
2404   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
2405   *                the configuration information for the specified SMBUS.
2406   * @param  InterruptRequest Value of @ref SMBUS_Interrupt_configuration_definition.
2407   * @retval HAL status
2408   */
SMBUS_Enable_IRQ(SMBUS_HandleTypeDef * hsmbus,uint32_t InterruptRequest)2409 static void SMBUS_Enable_IRQ(SMBUS_HandleTypeDef *hsmbus, uint32_t InterruptRequest)
2410 {
2411   uint32_t tmpisr = 0UL;
2412 
2413   if ((InterruptRequest & SMBUS_IT_ALERT) == SMBUS_IT_ALERT)
2414   {
2415     /* Enable ERR interrupt */
2416     tmpisr |= SMBUS_IT_ERRI;
2417   }
2418 
2419   if ((InterruptRequest & SMBUS_IT_ADDR) == SMBUS_IT_ADDR)
2420   {
2421     /* Enable ADDR, STOP interrupt */
2422     tmpisr |= SMBUS_IT_ADDRI | SMBUS_IT_STOPI | SMBUS_IT_NACKI | SMBUS_IT_ERRI;
2423   }
2424 
2425   if ((InterruptRequest & SMBUS_IT_TX) == SMBUS_IT_TX)
2426   {
2427     /* Enable ERR, TC, STOP, NACK, RXI interrupt */
2428     tmpisr |= SMBUS_IT_ERRI | SMBUS_IT_TCI | SMBUS_IT_STOPI | SMBUS_IT_NACKI | SMBUS_IT_TXI;
2429   }
2430 
2431   if ((InterruptRequest & SMBUS_IT_RX) == SMBUS_IT_RX)
2432   {
2433     /* Enable ERR, TC, STOP, NACK, TXI interrupt */
2434     tmpisr |= SMBUS_IT_ERRI | SMBUS_IT_TCI | SMBUS_IT_STOPI | SMBUS_IT_NACKI | SMBUS_IT_RXI;
2435   }
2436 
2437   /* Enable interrupts only at the end */
2438   /* to avoid the risk of SMBUS interrupt handle execution before */
2439   /* all interrupts requested done */
2440   __HAL_SMBUS_ENABLE_IT(hsmbus, tmpisr);
2441 }
2442 /**
2443   * @brief  Manage the disabling of Interrupts.
2444   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
2445   *                the configuration information for the specified SMBUS.
2446   * @param  InterruptRequest Value of @ref SMBUS_Interrupt_configuration_definition.
2447   * @retval HAL status
2448   */
SMBUS_Disable_IRQ(SMBUS_HandleTypeDef * hsmbus,uint32_t InterruptRequest)2449 static void SMBUS_Disable_IRQ(SMBUS_HandleTypeDef *hsmbus, uint32_t InterruptRequest)
2450 {
2451   uint32_t tmpisr = 0UL;
2452   uint32_t tmpstate = hsmbus->State;
2453 
2454   if ((tmpstate == HAL_SMBUS_STATE_READY) && ((InterruptRequest & SMBUS_IT_ALERT) == SMBUS_IT_ALERT))
2455   {
2456     /* Disable ERR interrupt */
2457     tmpisr |= SMBUS_IT_ERRI;
2458   }
2459 
2460   if ((InterruptRequest & SMBUS_IT_TX) == SMBUS_IT_TX)
2461   {
2462     /* Disable TC, STOP, NACK and TXI interrupt */
2463     tmpisr |= SMBUS_IT_TCI | SMBUS_IT_TXI;
2464 
2465     if ((SMBUS_GET_ALERT_ENABLED(hsmbus) == 0UL)
2466         && ((tmpstate & HAL_SMBUS_STATE_LISTEN) != HAL_SMBUS_STATE_LISTEN))
2467     {
2468       /* Disable ERR interrupt */
2469       tmpisr |= SMBUS_IT_ERRI;
2470     }
2471 
2472     if ((tmpstate & HAL_SMBUS_STATE_LISTEN) != HAL_SMBUS_STATE_LISTEN)
2473     {
2474       /* Disable STOP and NACK interrupt */
2475       tmpisr |= SMBUS_IT_STOPI | SMBUS_IT_NACKI;
2476     }
2477   }
2478 
2479   if ((InterruptRequest & SMBUS_IT_RX) == SMBUS_IT_RX)
2480   {
2481     /* Disable TC, STOP, NACK and RXI interrupt */
2482     tmpisr |= SMBUS_IT_TCI | SMBUS_IT_RXI;
2483 
2484     if ((SMBUS_GET_ALERT_ENABLED(hsmbus) == 0UL)
2485         && ((tmpstate & HAL_SMBUS_STATE_LISTEN) != HAL_SMBUS_STATE_LISTEN))
2486     {
2487       /* Disable ERR interrupt */
2488       tmpisr |= SMBUS_IT_ERRI;
2489     }
2490 
2491     if ((tmpstate & HAL_SMBUS_STATE_LISTEN) != HAL_SMBUS_STATE_LISTEN)
2492     {
2493       /* Disable STOP and NACK interrupt */
2494       tmpisr |= SMBUS_IT_STOPI | SMBUS_IT_NACKI;
2495     }
2496   }
2497 
2498   if ((InterruptRequest & SMBUS_IT_ADDR) == SMBUS_IT_ADDR)
2499   {
2500     /* Disable ADDR, STOP and NACK interrupt */
2501     tmpisr |= SMBUS_IT_ADDRI | SMBUS_IT_STOPI | SMBUS_IT_NACKI;
2502 
2503     if (SMBUS_GET_ALERT_ENABLED(hsmbus) == 0UL)
2504     {
2505       /* Disable ERR interrupt */
2506       tmpisr |= SMBUS_IT_ERRI;
2507     }
2508   }
2509 
2510   /* Disable interrupts only at the end */
2511   /* to avoid a breaking situation like at "t" time */
2512   /* all disable interrupts request are not done */
2513   __HAL_SMBUS_DISABLE_IT(hsmbus, tmpisr);
2514 }
2515 
2516 /**
2517   * @brief  SMBUS interrupts error handler.
2518   * @param  hsmbus SMBUS handle.
2519   * @retval None
2520   */
SMBUS_ITErrorHandler(SMBUS_HandleTypeDef * hsmbus)2521 static void SMBUS_ITErrorHandler(SMBUS_HandleTypeDef *hsmbus)
2522 {
2523   uint32_t itflags   = READ_REG(hsmbus->Instance->ISR);
2524   uint32_t itsources = READ_REG(hsmbus->Instance->CR1);
2525   uint32_t tmpstate;
2526   uint32_t tmperror;
2527 
2528   /* SMBUS Bus error interrupt occurred ------------------------------------*/
2529   if (((itflags & SMBUS_FLAG_BERR) == SMBUS_FLAG_BERR) && \
2530       ((itsources & SMBUS_IT_ERRI) == SMBUS_IT_ERRI))
2531   {
2532     hsmbus->ErrorCode |= HAL_SMBUS_ERROR_BERR;
2533 
2534     /* Clear BERR flag */
2535     __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_BERR);
2536   }
2537 
2538   /* SMBUS Over-Run/Under-Run interrupt occurred ----------------------------------------*/
2539   if (((itflags & SMBUS_FLAG_OVR) == SMBUS_FLAG_OVR) && \
2540       ((itsources & SMBUS_IT_ERRI) == SMBUS_IT_ERRI))
2541   {
2542     hsmbus->ErrorCode |= HAL_SMBUS_ERROR_OVR;
2543 
2544     /* Clear OVR flag */
2545     __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_OVR);
2546   }
2547 
2548   /* SMBUS Arbitration Loss error interrupt occurred ------------------------------------*/
2549   if (((itflags & SMBUS_FLAG_ARLO) == SMBUS_FLAG_ARLO) && \
2550       ((itsources & SMBUS_IT_ERRI) == SMBUS_IT_ERRI))
2551   {
2552     hsmbus->ErrorCode |= HAL_SMBUS_ERROR_ARLO;
2553 
2554     /* Clear ARLO flag */
2555     __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_ARLO);
2556   }
2557 
2558   /* SMBUS Timeout error interrupt occurred ---------------------------------------------*/
2559   if (((itflags & SMBUS_FLAG_TIMEOUT) == SMBUS_FLAG_TIMEOUT) && \
2560       ((itsources & SMBUS_IT_ERRI) == SMBUS_IT_ERRI))
2561   {
2562     hsmbus->ErrorCode |= HAL_SMBUS_ERROR_BUSTIMEOUT;
2563 
2564     /* Clear TIMEOUT flag */
2565     __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_TIMEOUT);
2566   }
2567 
2568   /* SMBUS Alert error interrupt occurred -----------------------------------------------*/
2569   if (((itflags & SMBUS_FLAG_ALERT) == SMBUS_FLAG_ALERT) && \
2570       ((itsources & SMBUS_IT_ERRI) == SMBUS_IT_ERRI))
2571   {
2572     hsmbus->ErrorCode |= HAL_SMBUS_ERROR_ALERT;
2573 
2574     /* Clear ALERT flag */
2575     __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_ALERT);
2576   }
2577 
2578   /* SMBUS Packet Error Check error interrupt occurred ----------------------------------*/
2579   if (((itflags & SMBUS_FLAG_PECERR) == SMBUS_FLAG_PECERR) && \
2580       ((itsources & SMBUS_IT_ERRI) == SMBUS_IT_ERRI))
2581   {
2582     hsmbus->ErrorCode |= HAL_SMBUS_ERROR_PECERR;
2583 
2584     /* Clear PEC error flag */
2585     __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_PECERR);
2586   }
2587 
2588   /* Flush TX register */
2589   SMBUS_Flush_TXDR(hsmbus);
2590 
2591   /* Store current volatile hsmbus->ErrorCode, misra rule */
2592   tmperror = hsmbus->ErrorCode;
2593 
2594   /* Call the Error Callback in case of Error detected */
2595   if ((tmperror != HAL_SMBUS_ERROR_NONE) && (tmperror != HAL_SMBUS_ERROR_ACKF))
2596   {
2597     /* Do not Reset the HAL state in case of ALERT error */
2598     if ((tmperror & HAL_SMBUS_ERROR_ALERT) != HAL_SMBUS_ERROR_ALERT)
2599     {
2600       /* Store current volatile hsmbus->State, misra rule */
2601       tmpstate = hsmbus->State;
2602 
2603       if (((tmpstate & HAL_SMBUS_STATE_SLAVE_BUSY_TX) == HAL_SMBUS_STATE_SLAVE_BUSY_TX)
2604           || ((tmpstate & HAL_SMBUS_STATE_SLAVE_BUSY_RX) == HAL_SMBUS_STATE_SLAVE_BUSY_RX))
2605       {
2606         /* Reset only HAL_SMBUS_STATE_SLAVE_BUSY_XX */
2607         /* keep HAL_SMBUS_STATE_LISTEN if set */
2608         hsmbus->PreviousState = HAL_SMBUS_STATE_READY;
2609         hsmbus->State = HAL_SMBUS_STATE_LISTEN;
2610       }
2611     }
2612 
2613     /* Call the Error callback to inform upper layer */
2614 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
2615     hsmbus->ErrorCallback(hsmbus);
2616 #else
2617     HAL_SMBUS_ErrorCallback(hsmbus);
2618 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
2619   }
2620 }
2621 
2622 /**
2623   * @brief  Handle SMBUS Communication Timeout.
2624   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
2625   *                the configuration information for the specified SMBUS.
2626   * @param  Flag Specifies the SMBUS flag to check.
2627   * @param  Status The new Flag status (SET or RESET).
2628   * @param  Timeout Timeout duration
2629   * @retval HAL status
2630   */
SMBUS_WaitOnFlagUntilTimeout(SMBUS_HandleTypeDef * hsmbus,uint32_t Flag,FlagStatus Status,uint32_t Timeout)2631 static HAL_StatusTypeDef SMBUS_WaitOnFlagUntilTimeout(SMBUS_HandleTypeDef *hsmbus, uint32_t Flag,
2632                                                       FlagStatus Status, uint32_t Timeout)
2633 {
2634   uint32_t tickstart = HAL_GetTick();
2635 
2636   /* Wait until flag is set */
2637   while ((FlagStatus)(__HAL_SMBUS_GET_FLAG(hsmbus, Flag)) == Status)
2638   {
2639     /* Check for the Timeout */
2640     if (Timeout != HAL_MAX_DELAY)
2641     {
2642       if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0UL))
2643       {
2644         hsmbus->PreviousState = hsmbus->State;
2645         hsmbus->State = HAL_SMBUS_STATE_READY;
2646 
2647         /* Update SMBUS error code */
2648         hsmbus->ErrorCode |= HAL_SMBUS_ERROR_HALTIMEOUT;
2649 
2650         /* Process Unlocked */
2651         __HAL_UNLOCK(hsmbus);
2652 
2653         return HAL_ERROR;
2654       }
2655     }
2656   }
2657 
2658   return HAL_OK;
2659 }
2660 
2661 /**
2662   * @brief  SMBUS Tx data register flush process.
2663   * @param  hsmbus SMBUS handle.
2664   * @retval None
2665   */
SMBUS_Flush_TXDR(SMBUS_HandleTypeDef * hsmbus)2666 static void SMBUS_Flush_TXDR(SMBUS_HandleTypeDef *hsmbus)
2667 {
2668   /* If a pending TXIS flag is set */
2669   /* Write a dummy data in TXDR to clear it */
2670   if (__HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_TXIS) != RESET)
2671   {
2672     hsmbus->Instance->TXDR = 0x00U;
2673   }
2674 
2675   /* Flush TX register if not empty */
2676   if (__HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_TXE) == RESET)
2677   {
2678     __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_TXE);
2679   }
2680 }
2681 
2682 /**
2683   * @brief  Handle SMBUSx communication when starting transfer or during transfer (TC or TCR flag are set).
2684   * @param  hsmbus SMBUS handle.
2685   * @param  DevAddress specifies the slave address to be programmed.
2686   * @param  Size specifies the number of bytes to be programmed.
2687   *   This parameter must be a value between 0 and 255.
2688   * @param  Mode New state of the SMBUS START condition generation.
2689   *   This parameter can be one or a combination  of the following values:
2690   *     @arg @ref SMBUS_RELOAD_MODE Enable Reload mode.
2691   *     @arg @ref SMBUS_AUTOEND_MODE Enable Automatic end mode.
2692   *     @arg @ref SMBUS_SOFTEND_MODE Enable Software end mode and Reload mode.
2693   *     @arg @ref SMBUS_SENDPEC_MODE Enable Packet Error Calculation mode.
2694   * @param  Request New state of the SMBUS START condition generation.
2695   *   This parameter can be one of the following values:
2696   *     @arg @ref SMBUS_NO_STARTSTOP Don't Generate stop and start condition.
2697   *     @arg @ref SMBUS_GENERATE_STOP Generate stop condition (Size should be set to 0).
2698   *     @arg @ref SMBUS_GENERATE_START_READ Generate Restart for read request.
2699   *     @arg @ref SMBUS_GENERATE_START_WRITE Generate Restart for write request.
2700   * @retval None
2701   */
SMBUS_TransferConfig(SMBUS_HandleTypeDef * hsmbus,uint16_t DevAddress,uint8_t Size,uint32_t Mode,uint32_t Request)2702 static void SMBUS_TransferConfig(SMBUS_HandleTypeDef *hsmbus,  uint16_t DevAddress, uint8_t Size,
2703                                  uint32_t Mode, uint32_t Request)
2704 {
2705   /* Check the parameters */
2706   assert_param(IS_SMBUS_ALL_INSTANCE(hsmbus->Instance));
2707   assert_param(IS_SMBUS_TRANSFER_MODE(Mode));
2708   assert_param(IS_SMBUS_TRANSFER_REQUEST(Request));
2709 
2710   /* update CR2 register */
2711   MODIFY_REG(hsmbus->Instance->CR2,
2712              ((I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_AUTOEND | \
2713                (I2C_CR2_RD_WRN & (uint32_t)(Request >> (31UL - I2C_CR2_RD_WRN_Pos))) | \
2714                I2C_CR2_START | I2C_CR2_STOP | I2C_CR2_PECBYTE)), \
2715              (uint32_t)(((uint32_t)DevAddress & I2C_CR2_SADD) | \
2716                         (((uint32_t)Size << I2C_CR2_NBYTES_Pos) & I2C_CR2_NBYTES) | \
2717                         (uint32_t)Mode | (uint32_t)Request));
2718 }
2719 
2720 /**
2721   * @brief  Convert SMBUSx OTHER_xxx XferOptions to functional XferOptions.
2722   * @param  hsmbus SMBUS handle.
2723   * @retval None
2724   */
SMBUS_ConvertOtherXferOptions(SMBUS_HandleTypeDef * hsmbus)2725 static void SMBUS_ConvertOtherXferOptions(SMBUS_HandleTypeDef *hsmbus)
2726 {
2727   /* if user set XferOptions to SMBUS_OTHER_FRAME_NO_PEC   */
2728   /* it request implicitly to generate a restart condition */
2729   /* set XferOptions to SMBUS_FIRST_FRAME                  */
2730   if (hsmbus->XferOptions == SMBUS_OTHER_FRAME_NO_PEC)
2731   {
2732     hsmbus->XferOptions = SMBUS_FIRST_FRAME;
2733   }
2734   /* else if user set XferOptions to SMBUS_OTHER_FRAME_WITH_PEC */
2735   /* it request implicitly to generate a restart condition      */
2736   /* set XferOptions to SMBUS_FIRST_FRAME | SMBUS_SENDPEC_MODE  */
2737   else if (hsmbus->XferOptions == SMBUS_OTHER_FRAME_WITH_PEC)
2738   {
2739     hsmbus->XferOptions = SMBUS_FIRST_FRAME | SMBUS_SENDPEC_MODE;
2740   }
2741   /* else if user set XferOptions to SMBUS_OTHER_AND_LAST_FRAME_NO_PEC */
2742   /* it request implicitly to generate a restart condition             */
2743   /* then generate a stop condition at the end of transfer             */
2744   /* set XferOptions to SMBUS_FIRST_AND_LAST_FRAME_NO_PEC              */
2745   else if (hsmbus->XferOptions == SMBUS_OTHER_AND_LAST_FRAME_NO_PEC)
2746   {
2747     hsmbus->XferOptions = SMBUS_FIRST_AND_LAST_FRAME_NO_PEC;
2748   }
2749   /* else if user set XferOptions to SMBUS_OTHER_AND_LAST_FRAME_WITH_PEC */
2750   /* it request implicitly to generate a restart condition               */
2751   /* then generate a stop condition at the end of transfer               */
2752   /* set XferOptions to SMBUS_FIRST_AND_LAST_FRAME_WITH_PEC              */
2753   else if (hsmbus->XferOptions == SMBUS_OTHER_AND_LAST_FRAME_WITH_PEC)
2754   {
2755     hsmbus->XferOptions = SMBUS_FIRST_AND_LAST_FRAME_WITH_PEC;
2756   }
2757   else
2758   {
2759     /* Nothing to do */
2760   }
2761 }
2762 /**
2763   * @}
2764   */
2765 
2766 #endif /* HAL_SMBUS_MODULE_ENABLED */
2767 /**
2768   * @}
2769   */
2770 
2771 /**
2772   * @}
2773   */
2774