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