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