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