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