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