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