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