STM32H735xx HAL User Manual
stm32h7xx_hal_smbus.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32h7xx_hal_smbus.c
00004   * @author  MCD Application Team
00005   * @brief   SMBUS HAL module driver.
00006   *          This file provides firmware functions to manage the following
00007   *          functionalities of the System Management Bus (SMBus) peripheral,
00008   *          based on I2C principles of operation :
00009   *           + Initialization and de-initialization functions
00010   *           + IO operation functions
00011   *           + Peripheral State and Errors functions
00012   *
00013   ******************************************************************************
00014   * @attention
00015   *
00016   * Copyright (c) 2017 STMicroelectronics.
00017   * All rights reserved.
00018   *
00019   * This software is licensed under terms that can be found in the LICENSE file
00020   * in the root directory of this software component.
00021   * If no LICENSE file comes with this software, it is provided AS-IS.
00022   *
00023   ******************************************************************************
00024   @verbatim
00025   ==============================================================================
00026                         ##### How to use this driver #####
00027   ==============================================================================
00028     [..]
00029     The SMBUS HAL driver can be used as follows:
00030 
00031     (#) Declare a SMBUS_HandleTypeDef handle structure, for example:
00032         SMBUS_HandleTypeDef  hsmbus;
00033 
00034     (#)Initialize the SMBUS low level resources by implementing the HAL_SMBUS_MspInit() API:
00035         (##) Enable the SMBUSx interface clock
00036         (##) SMBUS pins configuration
00037             (+++) Enable the clock for the SMBUS GPIOs
00038             (+++) Configure SMBUS pins as alternate function open-drain
00039         (##) NVIC configuration if you need to use interrupt process
00040             (+++) Configure the SMBUSx interrupt priority
00041             (+++) Enable the NVIC SMBUS IRQ Channel
00042 
00043     (#) Configure the Communication Clock Timing, Bus Timeout, Own Address1, Master Addressing mode,
00044         Dual Addressing mode, Own Address2, Own Address2 Mask, General call, Nostretch mode,
00045         Peripheral mode and Packet Error Check mode in the hsmbus Init structure.
00046 
00047     (#) Initialize the SMBUS registers by calling the HAL_SMBUS_Init() API:
00048         (++) These API's configures also the low level Hardware GPIO, CLOCK, CORTEX...etc)
00049              by calling the customized HAL_SMBUS_MspInit(&hsmbus) API.
00050 
00051     (#) To check if target device is ready for communication, use the function HAL_SMBUS_IsDeviceReady()
00052 
00053     (#) For SMBUS IO operations, only one mode of operations is available within this driver
00054 
00055     *** Interrupt mode IO operation ***
00056     ===================================
00057     [..]
00058       (+) Transmit in master/host SMBUS mode an amount of data in non-blocking mode
00059           using HAL_SMBUS_Master_Transmit_IT()
00060       (++) At transmission end of transfer HAL_SMBUS_MasterTxCpltCallback() is executed and users can
00061            add their own code by customization of function pointer HAL_SMBUS_MasterTxCpltCallback()
00062       (+) Receive in master/host SMBUS mode an amount of data in non-blocking mode
00063           using HAL_SMBUS_Master_Receive_IT()
00064       (++) At reception end of transfer HAL_SMBUS_MasterRxCpltCallback() is executed and users can
00065            add their own code by customization of function pointer HAL_SMBUS_MasterRxCpltCallback()
00066       (+) Abort a master/host SMBUS process communication with Interrupt using HAL_SMBUS_Master_Abort_IT()
00067       (++) The associated previous transfer callback is called at the end of abort process
00068       (++) mean HAL_SMBUS_MasterTxCpltCallback() in case of previous state was master transmit
00069       (++) mean HAL_SMBUS_MasterRxCpltCallback() in case of previous state was master receive
00070       (+) Enable/disable the Address listen mode in slave/device or host/slave SMBUS mode
00071            using HAL_SMBUS_EnableListen_IT() HAL_SMBUS_DisableListen_IT()
00072       (++) When address slave/device SMBUS match, HAL_SMBUS_AddrCallback() is executed and users can
00073            add their own code to check the Address Match Code and the transmission direction
00074            request by master/host (Write/Read).
00075       (++) At Listen mode end HAL_SMBUS_ListenCpltCallback() is executed and users can
00076            add their own code by customization of function pointer HAL_SMBUS_ListenCpltCallback()
00077       (+) Transmit in slave/device SMBUS mode an amount of data in non-blocking mode
00078           using HAL_SMBUS_Slave_Transmit_IT()
00079       (++) At transmission end of transfer HAL_SMBUS_SlaveTxCpltCallback() is executed and users can
00080            add their own code by customization of function pointer HAL_SMBUS_SlaveTxCpltCallback()
00081       (+) Receive in slave/device SMBUS mode an amount of data in non-blocking mode
00082           using HAL_SMBUS_Slave_Receive_IT()
00083       (++) At reception end of transfer HAL_SMBUS_SlaveRxCpltCallback() is executed and users can
00084            add their own code by customization of function pointer HAL_SMBUS_SlaveRxCpltCallback()
00085       (+) Enable/Disable the SMBUS alert mode using
00086           HAL_SMBUS_EnableAlert_IT() or HAL_SMBUS_DisableAlert_IT()
00087       (++) When SMBUS Alert is generated HAL_SMBUS_ErrorCallback() is executed and users can
00088            add their own code by customization of function pointer HAL_SMBUS_ErrorCallback()
00089            to check the Alert Error Code using function HAL_SMBUS_GetError()
00090       (+) Get HAL state machine or error values using HAL_SMBUS_GetState() or HAL_SMBUS_GetError()
00091       (+) In case of transfer Error, HAL_SMBUS_ErrorCallback() function is executed and users can
00092            add their own code by customization of function pointer HAL_SMBUS_ErrorCallback()
00093            to check the Error Code using function HAL_SMBUS_GetError()
00094 
00095      *** SMBUS HAL driver macros list ***
00096      ==================================
00097      [..]
00098        Below the list of most used macros in SMBUS HAL driver.
00099 
00100       (+) __HAL_SMBUS_ENABLE:      Enable the SMBUS peripheral
00101       (+) __HAL_SMBUS_DISABLE:     Disable the SMBUS peripheral
00102       (+) __HAL_SMBUS_GET_FLAG:    Check whether the specified SMBUS flag is set or not
00103       (+) __HAL_SMBUS_CLEAR_FLAG:  Clear the specified SMBUS pending flag
00104       (+) __HAL_SMBUS_ENABLE_IT:   Enable the specified SMBUS interrupt
00105       (+) __HAL_SMBUS_DISABLE_IT:  Disable the specified SMBUS interrupt
00106 
00107      *** Callback registration ***
00108      =============================================
00109     [..]
00110      The compilation flag USE_HAL_SMBUS_REGISTER_CALLBACKS when set to 1
00111      allows the user to configure dynamically the driver callbacks.
00112      Use Functions HAL_SMBUS_RegisterCallback() or HAL_SMBUS_RegisterAddrCallback()
00113      to register an interrupt callback.
00114     [..]
00115      Function HAL_SMBUS_RegisterCallback() allows to register following callbacks:
00116        (+) MasterTxCpltCallback : callback for Master transmission end of transfer.
00117        (+) MasterRxCpltCallback : callback for Master reception end of transfer.
00118        (+) SlaveTxCpltCallback  : callback for Slave transmission end of transfer.
00119        (+) SlaveRxCpltCallback  : callback for Slave reception end of transfer.
00120        (+) ListenCpltCallback   : callback for end of listen mode.
00121        (+) ErrorCallback        : callback for error detection.
00122        (+) MspInitCallback      : callback for Msp Init.
00123        (+) MspDeInitCallback    : callback for Msp DeInit.
00124      This function takes as parameters the HAL peripheral handle, the Callback ID
00125      and a pointer to the user callback function.
00126     [..]
00127      For specific callback AddrCallback use dedicated register callbacks : HAL_SMBUS_RegisterAddrCallback.
00128     [..]
00129      Use function HAL_SMBUS_UnRegisterCallback to reset a callback to the default
00130      weak function.
00131      HAL_SMBUS_UnRegisterCallback takes as parameters the HAL peripheral handle,
00132      and the Callback ID.
00133      This function allows to reset following callbacks:
00134        (+) MasterTxCpltCallback : callback for Master transmission end of transfer.
00135        (+) MasterRxCpltCallback : callback for Master reception end of transfer.
00136        (+) SlaveTxCpltCallback  : callback for Slave transmission end of transfer.
00137        (+) SlaveRxCpltCallback  : callback for Slave reception end of transfer.
00138        (+) ListenCpltCallback   : callback for end of listen mode.
00139        (+) ErrorCallback        : callback for error detection.
00140        (+) MspInitCallback      : callback for Msp Init.
00141        (+) MspDeInitCallback    : callback for Msp DeInit.
00142     [..]
00143      For callback AddrCallback use dedicated register callbacks : HAL_SMBUS_UnRegisterAddrCallback.
00144     [..]
00145      By default, after the HAL_SMBUS_Init() and when the state is HAL_I2C_STATE_RESET
00146      all callbacks are set to the corresponding weak functions:
00147      examples HAL_SMBUS_MasterTxCpltCallback(), HAL_SMBUS_MasterRxCpltCallback().
00148      Exception done for MspInit and MspDeInit functions that are
00149      reset to the legacy weak functions in the HAL_SMBUS_Init()/ HAL_SMBUS_DeInit() only when
00150      these callbacks are null (not registered beforehand).
00151      If MspInit or MspDeInit are not null, the HAL_SMBUS_Init()/ HAL_SMBUS_DeInit()
00152      keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state.
00153     [..]
00154      Callbacks can be registered/unregistered in HAL_I2C_STATE_READY state only.
00155      Exception done MspInit/MspDeInit functions that can be registered/unregistered
00156      in HAL_I2C_STATE_READY or HAL_I2C_STATE_RESET state,
00157      thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit.
00158      Then, the user first registers the MspInit/MspDeInit user callbacks
00159      using HAL_SMBUS_RegisterCallback() before calling HAL_SMBUS_DeInit()
00160      or HAL_SMBUS_Init() function.
00161     [..]
00162      When the compilation flag USE_HAL_SMBUS_REGISTER_CALLBACKS is set to 0 or
00163      not defined, the callback registration feature is not available and all callbacks
00164      are set to the corresponding weak functions.
00165 
00166      [..]
00167        (@) You can refer to the SMBUS HAL driver header file for more useful macros
00168 
00169   @endverbatim
00170   */
00171 
00172 /* Includes ------------------------------------------------------------------*/
00173 #include "stm32h7xx_hal.h"
00174 
00175 /** @addtogroup STM32H7xx_HAL_Driver
00176   * @{
00177   */
00178 
00179 /** @defgroup SMBUS SMBUS
00180   * @brief SMBUS HAL module driver
00181   * @{
00182   */
00183 
00184 #ifdef HAL_SMBUS_MODULE_ENABLED
00185 
00186 /* Private typedef -----------------------------------------------------------*/
00187 /* Private constants ---------------------------------------------------------*/
00188 /** @defgroup SMBUS_Private_Define SMBUS Private Constants
00189   * @{
00190   */
00191 #define TIMING_CLEAR_MASK   (0xF0FFFFFFUL)     /*!< SMBUS TIMING clear register Mask */
00192 #define HAL_TIMEOUT_ADDR    (10000U)           /*!< 10 s  */
00193 #define HAL_TIMEOUT_BUSY    (25U)              /*!< 25 ms */
00194 #define HAL_TIMEOUT_DIR     (25U)              /*!< 25 ms */
00195 #define HAL_TIMEOUT_RXNE    (25U)              /*!< 25 ms */
00196 #define HAL_TIMEOUT_STOPF   (25U)              /*!< 25 ms */
00197 #define HAL_TIMEOUT_TC      (25U)              /*!< 25 ms */
00198 #define HAL_TIMEOUT_TCR     (25U)              /*!< 25 ms */
00199 #define HAL_TIMEOUT_TXIS    (25U)              /*!< 25 ms */
00200 #define MAX_NBYTE_SIZE      255U
00201 /**
00202   * @}
00203   */
00204 
00205 /* Private macro -------------------------------------------------------------*/
00206 /* Private variables ---------------------------------------------------------*/
00207 /* Private function prototypes -----------------------------------------------*/
00208 /** @addtogroup SMBUS_Private_Functions SMBUS Private Functions
00209   * @{
00210   */
00211 /* Private functions to handle flags during polling transfer */
00212 static HAL_StatusTypeDef SMBUS_WaitOnFlagUntilTimeout(SMBUS_HandleTypeDef *hsmbus, uint32_t Flag,
00213                                                       FlagStatus Status, uint32_t Timeout);
00214 
00215 /* Private functions for SMBUS transfer IRQ handler */
00216 static HAL_StatusTypeDef SMBUS_Master_ISR(SMBUS_HandleTypeDef *hsmbus, uint32_t StatusFlags);
00217 static HAL_StatusTypeDef SMBUS_Slave_ISR(SMBUS_HandleTypeDef *hsmbus, uint32_t StatusFlags);
00218 static void SMBUS_ITErrorHandler(SMBUS_HandleTypeDef *hsmbus);
00219 
00220 /* Private functions to centralize the enable/disable of Interrupts */
00221 static void SMBUS_Enable_IRQ(SMBUS_HandleTypeDef *hsmbus, uint32_t InterruptRequest);
00222 static void SMBUS_Disable_IRQ(SMBUS_HandleTypeDef *hsmbus, uint32_t InterruptRequest);
00223 
00224 /* Private function to flush TXDR register */
00225 static void SMBUS_Flush_TXDR(SMBUS_HandleTypeDef *hsmbus);
00226 
00227 /* Private function to handle start, restart or stop a transfer */
00228 static void SMBUS_TransferConfig(SMBUS_HandleTypeDef *hsmbus,  uint16_t DevAddress, uint8_t Size,
00229                                  uint32_t Mode, uint32_t Request);
00230 
00231 /* Private function to Convert Specific options */
00232 static void SMBUS_ConvertOtherXferOptions(SMBUS_HandleTypeDef *hsmbus);
00233 /**
00234   * @}
00235   */
00236 
00237 /* Exported functions --------------------------------------------------------*/
00238 
00239 /** @defgroup SMBUS_Exported_Functions SMBUS Exported Functions
00240   * @{
00241   */
00242 
00243 /** @defgroup SMBUS_Exported_Functions_Group1 Initialization and de-initialization functions
00244   *  @brief    Initialization and Configuration functions
00245   *
00246 @verbatim
00247  ===============================================================================
00248               ##### Initialization and de-initialization functions #####
00249  ===============================================================================
00250     [..]  This subsection provides a set of functions allowing to initialize and
00251           deinitialize the SMBUSx peripheral:
00252 
00253       (+) User must Implement HAL_SMBUS_MspInit() function in which he configures
00254           all related peripherals resources (CLOCK, GPIO, IT and NVIC ).
00255 
00256       (+) Call the function HAL_SMBUS_Init() to configure the selected device with
00257           the selected configuration:
00258         (++) Clock Timing
00259         (++) Bus Timeout
00260         (++) Analog Filer mode
00261         (++) Own Address 1
00262         (++) Addressing mode (Master, Slave)
00263         (++) Dual Addressing mode
00264         (++) Own Address 2
00265         (++) Own Address 2 Mask
00266         (++) General call mode
00267         (++) Nostretch mode
00268         (++) Packet Error Check mode
00269         (++) Peripheral mode
00270 
00271 
00272       (+) Call the function HAL_SMBUS_DeInit() to restore the default configuration
00273           of the selected SMBUSx peripheral.
00274 
00275       (+) Enable/Disable Analog/Digital filters with HAL_SMBUS_ConfigAnalogFilter() and
00276           HAL_SMBUS_ConfigDigitalFilter().
00277 
00278 @endverbatim
00279   * @{
00280   */
00281 
00282 /**
00283   * @brief  Initialize the SMBUS according to the specified parameters
00284   *         in the SMBUS_InitTypeDef and initialize the associated handle.
00285   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
00286   *                the configuration information for the specified SMBUS.
00287   * @retval HAL status
00288   */
00289 HAL_StatusTypeDef HAL_SMBUS_Init(SMBUS_HandleTypeDef *hsmbus)
00290 {
00291   /* Check the SMBUS handle allocation */
00292   if (hsmbus == NULL)
00293   {
00294     return HAL_ERROR;
00295   }
00296 
00297   /* Check the parameters */
00298   assert_param(IS_SMBUS_ALL_INSTANCE(hsmbus->Instance));
00299   assert_param(IS_SMBUS_ANALOG_FILTER(hsmbus->Init.AnalogFilter));
00300   assert_param(IS_SMBUS_OWN_ADDRESS1(hsmbus->Init.OwnAddress1));
00301   assert_param(IS_SMBUS_ADDRESSING_MODE(hsmbus->Init.AddressingMode));
00302   assert_param(IS_SMBUS_DUAL_ADDRESS(hsmbus->Init.DualAddressMode));
00303   assert_param(IS_SMBUS_OWN_ADDRESS2(hsmbus->Init.OwnAddress2));
00304   assert_param(IS_SMBUS_OWN_ADDRESS2_MASK(hsmbus->Init.OwnAddress2Masks));
00305   assert_param(IS_SMBUS_GENERAL_CALL(hsmbus->Init.GeneralCallMode));
00306   assert_param(IS_SMBUS_NO_STRETCH(hsmbus->Init.NoStretchMode));
00307   assert_param(IS_SMBUS_PEC(hsmbus->Init.PacketErrorCheckMode));
00308   assert_param(IS_SMBUS_PERIPHERAL_MODE(hsmbus->Init.PeripheralMode));
00309 
00310   if (hsmbus->State == HAL_SMBUS_STATE_RESET)
00311   {
00312     /* Allocate lock resource and initialize it */
00313     hsmbus->Lock = HAL_UNLOCKED;
00314 
00315 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
00316     hsmbus->MasterTxCpltCallback = HAL_SMBUS_MasterTxCpltCallback; /* Legacy weak MasterTxCpltCallback */
00317     hsmbus->MasterRxCpltCallback = HAL_SMBUS_MasterRxCpltCallback; /* Legacy weak MasterRxCpltCallback */
00318     hsmbus->SlaveTxCpltCallback  = HAL_SMBUS_SlaveTxCpltCallback;  /* Legacy weak SlaveTxCpltCallback  */
00319     hsmbus->SlaveRxCpltCallback  = HAL_SMBUS_SlaveRxCpltCallback;  /* Legacy weak SlaveRxCpltCallback  */
00320     hsmbus->ListenCpltCallback   = HAL_SMBUS_ListenCpltCallback;   /* Legacy weak ListenCpltCallback   */
00321     hsmbus->ErrorCallback        = HAL_SMBUS_ErrorCallback;        /* Legacy weak ErrorCallback        */
00322     hsmbus->AddrCallback         = HAL_SMBUS_AddrCallback;         /* Legacy weak AddrCallback         */
00323 
00324     if (hsmbus->MspInitCallback == NULL)
00325     {
00326       hsmbus->MspInitCallback = HAL_SMBUS_MspInit; /* Legacy weak MspInit  */
00327     }
00328 
00329     /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */
00330     hsmbus->MspInitCallback(hsmbus);
00331 #else
00332     /* Init the low level hardware : GPIO, CLOCK, NVIC */
00333     HAL_SMBUS_MspInit(hsmbus);
00334 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
00335   }
00336 
00337   hsmbus->State = HAL_SMBUS_STATE_BUSY;
00338 
00339   /* Disable the selected SMBUS peripheral */
00340   __HAL_SMBUS_DISABLE(hsmbus);
00341 
00342   /*---------------------------- SMBUSx TIMINGR Configuration ------------------------*/
00343   /* Configure SMBUSx: Frequency range */
00344   hsmbus->Instance->TIMINGR = hsmbus->Init.Timing & TIMING_CLEAR_MASK;
00345 
00346   /*---------------------------- SMBUSx TIMEOUTR Configuration ------------------------*/
00347   /* Configure SMBUSx: Bus Timeout  */
00348   hsmbus->Instance->TIMEOUTR &= ~I2C_TIMEOUTR_TIMOUTEN;
00349   hsmbus->Instance->TIMEOUTR &= ~I2C_TIMEOUTR_TEXTEN;
00350   hsmbus->Instance->TIMEOUTR = hsmbus->Init.SMBusTimeout;
00351 
00352   /*---------------------------- SMBUSx OAR1 Configuration -----------------------*/
00353   /* Configure SMBUSx: Own Address1 and ack own address1 mode */
00354   hsmbus->Instance->OAR1 &= ~I2C_OAR1_OA1EN;
00355 
00356   if (hsmbus->Init.OwnAddress1 != 0UL)
00357   {
00358     if (hsmbus->Init.AddressingMode == SMBUS_ADDRESSINGMODE_7BIT)
00359     {
00360       hsmbus->Instance->OAR1 = (I2C_OAR1_OA1EN | hsmbus->Init.OwnAddress1);
00361     }
00362     else /* SMBUS_ADDRESSINGMODE_10BIT */
00363     {
00364       hsmbus->Instance->OAR1 = (I2C_OAR1_OA1EN | I2C_OAR1_OA1MODE | hsmbus->Init.OwnAddress1);
00365     }
00366   }
00367 
00368   /*---------------------------- SMBUSx CR2 Configuration ------------------------*/
00369   /* Configure SMBUSx: Addressing Master mode */
00370   if (hsmbus->Init.AddressingMode == SMBUS_ADDRESSINGMODE_10BIT)
00371   {
00372     hsmbus->Instance->CR2 = (I2C_CR2_ADD10);
00373   }
00374   /* Enable the AUTOEND by default, and enable NACK (should be disable only during Slave process) */
00375   /* AUTOEND and NACK bit will be manage during Transfer process */
00376   hsmbus->Instance->CR2 |= (I2C_CR2_AUTOEND | I2C_CR2_NACK);
00377 
00378   /*---------------------------- SMBUSx OAR2 Configuration -----------------------*/
00379   /* Configure SMBUSx: Dual mode and Own Address2 */
00380   hsmbus->Instance->OAR2 = (hsmbus->Init.DualAddressMode | hsmbus->Init.OwnAddress2 | \
00381                             (hsmbus->Init.OwnAddress2Masks << 8U));
00382 
00383   /*---------------------------- SMBUSx CR1 Configuration ------------------------*/
00384   /* Configure SMBUSx: Generalcall and NoStretch mode */
00385   hsmbus->Instance->CR1 = (hsmbus->Init.GeneralCallMode | hsmbus->Init.NoStretchMode | \
00386                            hsmbus->Init.PacketErrorCheckMode | hsmbus->Init.PeripheralMode | \
00387                            hsmbus->Init.AnalogFilter);
00388 
00389   /* Enable Slave Byte Control only in case of Packet Error Check is enabled
00390      and SMBUS Peripheral is set in Slave mode */
00391   if ((hsmbus->Init.PacketErrorCheckMode == SMBUS_PEC_ENABLE) && \
00392       ((hsmbus->Init.PeripheralMode == SMBUS_PERIPHERAL_MODE_SMBUS_SLAVE) || \
00393        (hsmbus->Init.PeripheralMode == SMBUS_PERIPHERAL_MODE_SMBUS_SLAVE_ARP)))
00394   {
00395     hsmbus->Instance->CR1 |= I2C_CR1_SBC;
00396   }
00397 
00398   /* Enable the selected SMBUS peripheral */
00399   __HAL_SMBUS_ENABLE(hsmbus);
00400 
00401   hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE;
00402   hsmbus->PreviousState = HAL_SMBUS_STATE_READY;
00403   hsmbus->State = HAL_SMBUS_STATE_READY;
00404 
00405   return HAL_OK;
00406 }
00407 
00408 /**
00409   * @brief  DeInitialize the SMBUS peripheral.
00410   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
00411   *                the configuration information for the specified SMBUS.
00412   * @retval HAL status
00413   */
00414 HAL_StatusTypeDef HAL_SMBUS_DeInit(SMBUS_HandleTypeDef *hsmbus)
00415 {
00416   /* Check the SMBUS handle allocation */
00417   if (hsmbus == NULL)
00418   {
00419     return HAL_ERROR;
00420   }
00421 
00422   /* Check the parameters */
00423   assert_param(IS_SMBUS_ALL_INSTANCE(hsmbus->Instance));
00424 
00425   hsmbus->State = HAL_SMBUS_STATE_BUSY;
00426 
00427   /* Disable the SMBUS Peripheral Clock */
00428   __HAL_SMBUS_DISABLE(hsmbus);
00429 
00430 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
00431   if (hsmbus->MspDeInitCallback == NULL)
00432   {
00433     hsmbus->MspDeInitCallback = HAL_SMBUS_MspDeInit; /* Legacy weak MspDeInit  */
00434   }
00435 
00436   /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
00437   hsmbus->MspDeInitCallback(hsmbus);
00438 #else
00439   /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
00440   HAL_SMBUS_MspDeInit(hsmbus);
00441 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
00442 
00443   hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE;
00444   hsmbus->PreviousState =  HAL_SMBUS_STATE_RESET;
00445   hsmbus->State = HAL_SMBUS_STATE_RESET;
00446 
00447   /* Release Lock */
00448   __HAL_UNLOCK(hsmbus);
00449 
00450   return HAL_OK;
00451 }
00452 
00453 /**
00454   * @brief Initialize the SMBUS MSP.
00455   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
00456   *                the configuration information for the specified SMBUS.
00457   * @retval None
00458   */
00459 __weak void HAL_SMBUS_MspInit(SMBUS_HandleTypeDef *hsmbus)
00460 {
00461   /* Prevent unused argument(s) compilation warning */
00462   UNUSED(hsmbus);
00463 
00464   /* NOTE : This function should not be modified, when the callback is needed,
00465             the HAL_SMBUS_MspInit could be implemented in the user file
00466    */
00467 }
00468 
00469 /**
00470   * @brief DeInitialize the SMBUS MSP.
00471   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
00472   *                the configuration information for the specified SMBUS.
00473   * @retval None
00474   */
00475 __weak void HAL_SMBUS_MspDeInit(SMBUS_HandleTypeDef *hsmbus)
00476 {
00477   /* Prevent unused argument(s) compilation warning */
00478   UNUSED(hsmbus);
00479 
00480   /* NOTE : This function should not be modified, when the callback is needed,
00481             the HAL_SMBUS_MspDeInit could be implemented in the user file
00482    */
00483 }
00484 
00485 /**
00486   * @brief  Configure Analog noise filter.
00487   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
00488   *                the configuration information for the specified SMBUS.
00489   * @param  AnalogFilter This parameter can be one of the following values:
00490   *         @arg @ref SMBUS_ANALOGFILTER_ENABLE
00491   *         @arg @ref SMBUS_ANALOGFILTER_DISABLE
00492   * @retval HAL status
00493   */
00494 HAL_StatusTypeDef HAL_SMBUS_ConfigAnalogFilter(SMBUS_HandleTypeDef *hsmbus, uint32_t AnalogFilter)
00495 {
00496   /* Check the parameters */
00497   assert_param(IS_SMBUS_ALL_INSTANCE(hsmbus->Instance));
00498   assert_param(IS_SMBUS_ANALOG_FILTER(AnalogFilter));
00499 
00500   if (hsmbus->State == HAL_SMBUS_STATE_READY)
00501   {
00502     /* Process Locked */
00503     __HAL_LOCK(hsmbus);
00504 
00505     hsmbus->State = HAL_SMBUS_STATE_BUSY;
00506 
00507     /* Disable the selected SMBUS peripheral */
00508     __HAL_SMBUS_DISABLE(hsmbus);
00509 
00510     /* Reset ANOFF bit */
00511     hsmbus->Instance->CR1 &= ~(I2C_CR1_ANFOFF);
00512 
00513     /* Set analog filter bit*/
00514     hsmbus->Instance->CR1 |= AnalogFilter;
00515 
00516     __HAL_SMBUS_ENABLE(hsmbus);
00517 
00518     hsmbus->State = HAL_SMBUS_STATE_READY;
00519 
00520     /* Process Unlocked */
00521     __HAL_UNLOCK(hsmbus);
00522 
00523     return HAL_OK;
00524   }
00525   else
00526   {
00527     return HAL_BUSY;
00528   }
00529 }
00530 
00531 /**
00532   * @brief  Configure Digital noise filter.
00533   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
00534   *                the configuration information for the specified SMBUS.
00535   * @param  DigitalFilter Coefficient of digital noise filter between Min_Data=0x00 and Max_Data=0x0F.
00536   * @retval HAL status
00537   */
00538 HAL_StatusTypeDef HAL_SMBUS_ConfigDigitalFilter(SMBUS_HandleTypeDef *hsmbus, uint32_t DigitalFilter)
00539 {
00540   uint32_t tmpreg;
00541 
00542   /* Check the parameters */
00543   assert_param(IS_SMBUS_ALL_INSTANCE(hsmbus->Instance));
00544   assert_param(IS_SMBUS_DIGITAL_FILTER(DigitalFilter));
00545 
00546   if (hsmbus->State == HAL_SMBUS_STATE_READY)
00547   {
00548     /* Process Locked */
00549     __HAL_LOCK(hsmbus);
00550 
00551     hsmbus->State = HAL_SMBUS_STATE_BUSY;
00552 
00553     /* Disable the selected SMBUS peripheral */
00554     __HAL_SMBUS_DISABLE(hsmbus);
00555 
00556     /* Get the old register value */
00557     tmpreg = hsmbus->Instance->CR1;
00558 
00559     /* Reset I2C DNF bits [11:8] */
00560     tmpreg &= ~(I2C_CR1_DNF);
00561 
00562     /* Set I2Cx DNF coefficient */
00563     tmpreg |= DigitalFilter << I2C_CR1_DNF_Pos;
00564 
00565     /* Store the new register value */
00566     hsmbus->Instance->CR1 = tmpreg;
00567 
00568     __HAL_SMBUS_ENABLE(hsmbus);
00569 
00570     hsmbus->State = HAL_SMBUS_STATE_READY;
00571 
00572     /* Process Unlocked */
00573     __HAL_UNLOCK(hsmbus);
00574 
00575     return HAL_OK;
00576   }
00577   else
00578   {
00579     return HAL_BUSY;
00580   }
00581 }
00582 
00583 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
00584 /**
00585   * @brief  Register a User SMBUS Callback
00586   *         To be used instead of the weak predefined callback
00587   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
00588   *                the configuration information for the specified SMBUS.
00589   * @param  CallbackID ID of the callback to be registered
00590   *         This parameter can be one of the following values:
00591   *          @arg @ref HAL_SMBUS_MASTER_TX_COMPLETE_CB_ID Master Tx Transfer completed callback ID
00592   *          @arg @ref HAL_SMBUS_MASTER_RX_COMPLETE_CB_ID Master Rx Transfer completed callback ID
00593   *          @arg @ref HAL_SMBUS_SLAVE_TX_COMPLETE_CB_ID Slave Tx Transfer completed callback ID
00594   *          @arg @ref HAL_SMBUS_SLAVE_RX_COMPLETE_CB_ID Slave Rx Transfer completed callback ID
00595   *          @arg @ref HAL_SMBUS_LISTEN_COMPLETE_CB_ID Listen Complete callback ID
00596   *          @arg @ref HAL_SMBUS_ERROR_CB_ID Error callback ID
00597   *          @arg @ref HAL_SMBUS_MSPINIT_CB_ID MspInit callback ID
00598   *          @arg @ref HAL_SMBUS_MSPDEINIT_CB_ID MspDeInit callback ID
00599   * @param  pCallback pointer to the Callback function
00600   * @retval HAL status
00601   */
00602 HAL_StatusTypeDef HAL_SMBUS_RegisterCallback(SMBUS_HandleTypeDef *hsmbus,
00603                                              HAL_SMBUS_CallbackIDTypeDef CallbackID,
00604                                              pSMBUS_CallbackTypeDef pCallback)
00605 {
00606   HAL_StatusTypeDef status = HAL_OK;
00607 
00608   if (pCallback == NULL)
00609   {
00610     /* Update the error code */
00611     hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK;
00612 
00613     return HAL_ERROR;
00614   }
00615 
00616   /* Process locked */
00617   __HAL_LOCK(hsmbus);
00618 
00619   if (HAL_SMBUS_STATE_READY == hsmbus->State)
00620   {
00621     switch (CallbackID)
00622     {
00623       case HAL_SMBUS_MASTER_TX_COMPLETE_CB_ID :
00624         hsmbus->MasterTxCpltCallback = pCallback;
00625         break;
00626 
00627       case HAL_SMBUS_MASTER_RX_COMPLETE_CB_ID :
00628         hsmbus->MasterRxCpltCallback = pCallback;
00629         break;
00630 
00631       case HAL_SMBUS_SLAVE_TX_COMPLETE_CB_ID :
00632         hsmbus->SlaveTxCpltCallback = pCallback;
00633         break;
00634 
00635       case HAL_SMBUS_SLAVE_RX_COMPLETE_CB_ID :
00636         hsmbus->SlaveRxCpltCallback = pCallback;
00637         break;
00638 
00639       case HAL_SMBUS_LISTEN_COMPLETE_CB_ID :
00640         hsmbus->ListenCpltCallback = pCallback;
00641         break;
00642 
00643       case HAL_SMBUS_ERROR_CB_ID :
00644         hsmbus->ErrorCallback = pCallback;
00645         break;
00646 
00647       case HAL_SMBUS_MSPINIT_CB_ID :
00648         hsmbus->MspInitCallback = pCallback;
00649         break;
00650 
00651       case HAL_SMBUS_MSPDEINIT_CB_ID :
00652         hsmbus->MspDeInitCallback = pCallback;
00653         break;
00654 
00655       default :
00656         /* Update the error code */
00657         hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK;
00658 
00659         /* Return error status */
00660         status =  HAL_ERROR;
00661         break;
00662     }
00663   }
00664   else if (HAL_SMBUS_STATE_RESET == hsmbus->State)
00665   {
00666     switch (CallbackID)
00667     {
00668       case HAL_SMBUS_MSPINIT_CB_ID :
00669         hsmbus->MspInitCallback = pCallback;
00670         break;
00671 
00672       case HAL_SMBUS_MSPDEINIT_CB_ID :
00673         hsmbus->MspDeInitCallback = pCallback;
00674         break;
00675 
00676       default :
00677         /* Update the error code */
00678         hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK;
00679 
00680         /* Return error status */
00681         status =  HAL_ERROR;
00682         break;
00683     }
00684   }
00685   else
00686   {
00687     /* Update the error code */
00688     hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK;
00689 
00690     /* Return error status */
00691     status =  HAL_ERROR;
00692   }
00693 
00694   /* Release Lock */
00695   __HAL_UNLOCK(hsmbus);
00696   return status;
00697 }
00698 
00699 /**
00700   * @brief  Unregister an SMBUS Callback
00701   *         SMBUS callback is redirected to the weak predefined callback
00702   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
00703   *                the configuration information for the specified SMBUS.
00704   * @param  CallbackID ID of the callback to be unregistered
00705   *         This parameter can be one of the following values:
00706   *         This parameter can be one of the following values:
00707   *          @arg @ref HAL_SMBUS_MASTER_TX_COMPLETE_CB_ID Master Tx Transfer completed callback ID
00708   *          @arg @ref HAL_SMBUS_MASTER_RX_COMPLETE_CB_ID Master Rx Transfer completed callback ID
00709   *          @arg @ref HAL_SMBUS_SLAVE_TX_COMPLETE_CB_ID Slave Tx Transfer completed callback ID
00710   *          @arg @ref HAL_SMBUS_SLAVE_RX_COMPLETE_CB_ID Slave Rx Transfer completed callback ID
00711   *          @arg @ref HAL_SMBUS_LISTEN_COMPLETE_CB_ID Listen Complete callback ID
00712   *          @arg @ref HAL_SMBUS_ERROR_CB_ID Error callback ID
00713   *          @arg @ref HAL_SMBUS_MSPINIT_CB_ID MspInit callback ID
00714   *          @arg @ref HAL_SMBUS_MSPDEINIT_CB_ID MspDeInit callback ID
00715   * @retval HAL status
00716   */
00717 HAL_StatusTypeDef HAL_SMBUS_UnRegisterCallback(SMBUS_HandleTypeDef *hsmbus,
00718                                                HAL_SMBUS_CallbackIDTypeDef CallbackID)
00719 {
00720   HAL_StatusTypeDef status = HAL_OK;
00721 
00722   /* Process locked */
00723   __HAL_LOCK(hsmbus);
00724 
00725   if (HAL_SMBUS_STATE_READY == hsmbus->State)
00726   {
00727     switch (CallbackID)
00728     {
00729       case HAL_SMBUS_MASTER_TX_COMPLETE_CB_ID :
00730         hsmbus->MasterTxCpltCallback = HAL_SMBUS_MasterTxCpltCallback; /* Legacy weak MasterTxCpltCallback */
00731         break;
00732 
00733       case HAL_SMBUS_MASTER_RX_COMPLETE_CB_ID :
00734         hsmbus->MasterRxCpltCallback = HAL_SMBUS_MasterRxCpltCallback; /* Legacy weak MasterRxCpltCallback */
00735         break;
00736 
00737       case HAL_SMBUS_SLAVE_TX_COMPLETE_CB_ID :
00738         hsmbus->SlaveTxCpltCallback = HAL_SMBUS_SlaveTxCpltCallback;   /* Legacy weak SlaveTxCpltCallback  */
00739         break;
00740 
00741       case HAL_SMBUS_SLAVE_RX_COMPLETE_CB_ID :
00742         hsmbus->SlaveRxCpltCallback = HAL_SMBUS_SlaveRxCpltCallback;   /* Legacy weak SlaveRxCpltCallback  */
00743         break;
00744 
00745       case HAL_SMBUS_LISTEN_COMPLETE_CB_ID :
00746         hsmbus->ListenCpltCallback = HAL_SMBUS_ListenCpltCallback;     /* Legacy weak ListenCpltCallback   */
00747         break;
00748 
00749       case HAL_SMBUS_ERROR_CB_ID :
00750         hsmbus->ErrorCallback = HAL_SMBUS_ErrorCallback;               /* Legacy weak ErrorCallback        */
00751         break;
00752 
00753       case HAL_SMBUS_MSPINIT_CB_ID :
00754         hsmbus->MspInitCallback = HAL_SMBUS_MspInit;                   /* Legacy weak MspInit              */
00755         break;
00756 
00757       case HAL_SMBUS_MSPDEINIT_CB_ID :
00758         hsmbus->MspDeInitCallback = HAL_SMBUS_MspDeInit;               /* Legacy weak MspDeInit            */
00759         break;
00760 
00761       default :
00762         /* Update the error code */
00763         hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK;
00764 
00765         /* Return error status */
00766         status =  HAL_ERROR;
00767         break;
00768     }
00769   }
00770   else if (HAL_SMBUS_STATE_RESET == hsmbus->State)
00771   {
00772     switch (CallbackID)
00773     {
00774       case HAL_SMBUS_MSPINIT_CB_ID :
00775         hsmbus->MspInitCallback = HAL_SMBUS_MspInit;                   /* Legacy weak MspInit              */
00776         break;
00777 
00778       case HAL_SMBUS_MSPDEINIT_CB_ID :
00779         hsmbus->MspDeInitCallback = HAL_SMBUS_MspDeInit;               /* Legacy weak MspDeInit            */
00780         break;
00781 
00782       default :
00783         /* Update the error code */
00784         hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK;
00785 
00786         /* Return error status */
00787         status =  HAL_ERROR;
00788         break;
00789     }
00790   }
00791   else
00792   {
00793     /* Update the error code */
00794     hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK;
00795 
00796     /* Return error status */
00797     status =  HAL_ERROR;
00798   }
00799 
00800   /* Release Lock */
00801   __HAL_UNLOCK(hsmbus);
00802   return status;
00803 }
00804 
00805 /**
00806   * @brief  Register the Slave Address Match SMBUS Callback
00807   *         To be used instead of the weak HAL_SMBUS_AddrCallback() predefined callback
00808   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
00809   *                the configuration information for the specified SMBUS.
00810   * @param  pCallback pointer to the Address Match Callback function
00811   * @retval HAL status
00812   */
00813 HAL_StatusTypeDef HAL_SMBUS_RegisterAddrCallback(SMBUS_HandleTypeDef *hsmbus,
00814                                                  pSMBUS_AddrCallbackTypeDef pCallback)
00815 {
00816   HAL_StatusTypeDef status = HAL_OK;
00817 
00818   if (pCallback == NULL)
00819   {
00820     /* Update the error code */
00821     hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK;
00822 
00823     return HAL_ERROR;
00824   }
00825   /* Process locked */
00826   __HAL_LOCK(hsmbus);
00827 
00828   if (HAL_SMBUS_STATE_READY == hsmbus->State)
00829   {
00830     hsmbus->AddrCallback = pCallback;
00831   }
00832   else
00833   {
00834     /* Update the error code */
00835     hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK;
00836 
00837     /* Return error status */
00838     status =  HAL_ERROR;
00839   }
00840 
00841   /* Release Lock */
00842   __HAL_UNLOCK(hsmbus);
00843   return status;
00844 }
00845 
00846 /**
00847   * @brief  UnRegister the Slave Address Match SMBUS Callback
00848   *         Info Ready SMBUS Callback is redirected to the weak HAL_SMBUS_AddrCallback() predefined callback
00849   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
00850   *                the configuration information for the specified SMBUS.
00851   * @retval HAL status
00852   */
00853 HAL_StatusTypeDef HAL_SMBUS_UnRegisterAddrCallback(SMBUS_HandleTypeDef *hsmbus)
00854 {
00855   HAL_StatusTypeDef status = HAL_OK;
00856 
00857   /* Process locked */
00858   __HAL_LOCK(hsmbus);
00859 
00860   if (HAL_SMBUS_STATE_READY == hsmbus->State)
00861   {
00862     hsmbus->AddrCallback = HAL_SMBUS_AddrCallback; /* Legacy weak AddrCallback  */
00863   }
00864   else
00865   {
00866     /* Update the error code */
00867     hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK;
00868 
00869     /* Return error status */
00870     status =  HAL_ERROR;
00871   }
00872 
00873   /* Release Lock */
00874   __HAL_UNLOCK(hsmbus);
00875   return status;
00876 }
00877 
00878 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
00879 
00880 /**
00881   * @}
00882   */
00883 
00884 /** @defgroup SMBUS_Exported_Functions_Group2 Input and Output operation functions
00885   *  @brief   Data transfers functions
00886   *
00887 @verbatim
00888  ===============================================================================
00889                       ##### IO operation functions #####
00890  ===============================================================================
00891     [..]
00892     This subsection provides a set of functions allowing to manage the SMBUS data
00893     transfers.
00894 
00895     (#) Blocking mode function to check if device is ready for usage is :
00896         (++) HAL_SMBUS_IsDeviceReady()
00897 
00898     (#) There is only one mode of transfer:
00899        (++) Non-Blocking mode : The communication is performed using Interrupts.
00900             These functions return the status of the transfer startup.
00901             The end of the data processing will be indicated through the
00902             dedicated SMBUS IRQ when using Interrupt mode.
00903 
00904     (#) Non-Blocking mode functions with Interrupt are :
00905         (++) HAL_SMBUS_Master_Transmit_IT()
00906         (++) HAL_SMBUS_Master_Receive_IT()
00907         (++) HAL_SMBUS_Slave_Transmit_IT()
00908         (++) HAL_SMBUS_Slave_Receive_IT()
00909         (++) HAL_SMBUS_EnableListen_IT() or alias HAL_SMBUS_EnableListen_IT()
00910         (++) HAL_SMBUS_DisableListen_IT()
00911         (++) HAL_SMBUS_EnableAlert_IT()
00912         (++) HAL_SMBUS_DisableAlert_IT()
00913 
00914     (#) A set of Transfer Complete Callbacks are provided in non-Blocking mode:
00915         (++) HAL_SMBUS_MasterTxCpltCallback()
00916         (++) HAL_SMBUS_MasterRxCpltCallback()
00917         (++) HAL_SMBUS_SlaveTxCpltCallback()
00918         (++) HAL_SMBUS_SlaveRxCpltCallback()
00919         (++) HAL_SMBUS_AddrCallback()
00920         (++) HAL_SMBUS_ListenCpltCallback()
00921         (++) HAL_SMBUS_ErrorCallback()
00922 
00923 @endverbatim
00924   * @{
00925   */
00926 
00927 /**
00928   * @brief  Transmit in master/host SMBUS mode an amount of data in non-blocking mode with Interrupt.
00929   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
00930   *                the configuration information for the specified SMBUS.
00931   * @param  DevAddress Target device address: The device 7 bits address value
00932   *         in datasheet must be shifted to the left before calling the interface
00933   * @param  pData Pointer to data buffer
00934   * @param  Size Amount of data to be sent
00935   * @param  XferOptions Options of Transfer, value of @ref SMBUS_XferOptions_definition
00936   * @retval HAL status
00937   */
00938 HAL_StatusTypeDef HAL_SMBUS_Master_Transmit_IT(SMBUS_HandleTypeDef *hsmbus, uint16_t DevAddress,
00939                                                uint8_t *pData, uint16_t Size, uint32_t XferOptions)
00940 {
00941   uint32_t tmp;
00942 
00943   /* Check the parameters */
00944   assert_param(IS_SMBUS_TRANSFER_OPTIONS_REQUEST(XferOptions));
00945 
00946   if (hsmbus->State == HAL_SMBUS_STATE_READY)
00947   {
00948     /* Process Locked */
00949     __HAL_LOCK(hsmbus);
00950 
00951     hsmbus->State = HAL_SMBUS_STATE_MASTER_BUSY_TX;
00952     hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE;
00953     /* Prepare transfer parameters */
00954     hsmbus->pBuffPtr = pData;
00955     hsmbus->XferCount = Size;
00956     hsmbus->XferOptions = XferOptions;
00957 
00958     /* In case of Quick command, remove autoend mode */
00959     /* Manage the stop generation by software */
00960     if (hsmbus->pBuffPtr == NULL)
00961     {
00962       hsmbus->XferOptions &= ~SMBUS_AUTOEND_MODE;
00963     }
00964 
00965     if (Size > MAX_NBYTE_SIZE)
00966     {
00967       hsmbus->XferSize = MAX_NBYTE_SIZE;
00968     }
00969     else
00970     {
00971       hsmbus->XferSize = Size;
00972     }
00973 
00974     /* Send Slave Address */
00975     /* Set NBYTES to write and reload if size > MAX_NBYTE_SIZE and generate RESTART */
00976     if ((hsmbus->XferSize < hsmbus->XferCount) && (hsmbus->XferSize == MAX_NBYTE_SIZE))
00977     {
00978       SMBUS_TransferConfig(hsmbus, DevAddress, (uint8_t)hsmbus->XferSize,
00979                            SMBUS_RELOAD_MODE | (hsmbus->XferOptions & SMBUS_SENDPEC_MODE),
00980                            SMBUS_GENERATE_START_WRITE);
00981     }
00982     else
00983     {
00984       /* If transfer direction not change, do not generate Restart Condition */
00985       /* Mean Previous state is same as current state */
00986 
00987       /* Store current volatile XferOptions, misra rule */
00988       tmp = hsmbus->XferOptions;
00989 
00990       if ((hsmbus->PreviousState == HAL_SMBUS_STATE_MASTER_BUSY_TX) && \
00991           (IS_SMBUS_TRANSFER_OTHER_OPTIONS_REQUEST(tmp) == 0))
00992       {
00993         SMBUS_TransferConfig(hsmbus, DevAddress, (uint8_t)hsmbus->XferSize, hsmbus->XferOptions,
00994                              SMBUS_NO_STARTSTOP);
00995       }
00996       /* Else transfer direction change, so generate Restart with new transfer direction */
00997       else
00998       {
00999         /* Convert OTHER_xxx XferOptions if any */
01000         SMBUS_ConvertOtherXferOptions(hsmbus);
01001 
01002         /* Handle Transfer */
01003         SMBUS_TransferConfig(hsmbus, DevAddress, (uint8_t)hsmbus->XferSize,
01004                              hsmbus->XferOptions,
01005                              SMBUS_GENERATE_START_WRITE);
01006       }
01007 
01008       /* If PEC mode is enable, size to transmit manage by SW part should be Size-1 byte, corresponding to PEC byte */
01009       /* PEC byte is automatically sent by HW block, no need to manage it in Transmit process */
01010       if (SMBUS_GET_PEC_MODE(hsmbus) != 0UL)
01011       {
01012         hsmbus->XferSize--;
01013         hsmbus->XferCount--;
01014       }
01015     }
01016 
01017     /* Process Unlocked */
01018     __HAL_UNLOCK(hsmbus);
01019 
01020     /* Note : The SMBUS interrupts must be enabled after unlocking current process
01021               to avoid the risk of SMBUS interrupt handle execution before current
01022               process unlock */
01023     SMBUS_Enable_IRQ(hsmbus, SMBUS_IT_TX);
01024 
01025     return HAL_OK;
01026   }
01027   else
01028   {
01029     return HAL_BUSY;
01030   }
01031 }
01032 
01033 /**
01034   * @brief  Receive in master/host SMBUS mode an amount of data in non-blocking mode with Interrupt.
01035   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
01036   *                the configuration information for the specified SMBUS.
01037   * @param  DevAddress Target device address: The device 7 bits address value
01038   *         in datasheet must be shifted to the left before calling the interface
01039   * @param  pData Pointer to data buffer
01040   * @param  Size Amount of data to be sent
01041   * @param  XferOptions Options of Transfer, value of @ref SMBUS_XferOptions_definition
01042   * @retval HAL status
01043   */
01044 HAL_StatusTypeDef HAL_SMBUS_Master_Receive_IT(SMBUS_HandleTypeDef *hsmbus, uint16_t DevAddress, uint8_t *pData,
01045                                               uint16_t Size, uint32_t XferOptions)
01046 {
01047   uint32_t tmp;
01048 
01049   /* Check the parameters */
01050   assert_param(IS_SMBUS_TRANSFER_OPTIONS_REQUEST(XferOptions));
01051 
01052   if (hsmbus->State == HAL_SMBUS_STATE_READY)
01053   {
01054     /* Process Locked */
01055     __HAL_LOCK(hsmbus);
01056 
01057     hsmbus->State = HAL_SMBUS_STATE_MASTER_BUSY_RX;
01058     hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE;
01059 
01060     /* Prepare transfer parameters */
01061     hsmbus->pBuffPtr = pData;
01062     hsmbus->XferCount = Size;
01063     hsmbus->XferOptions = XferOptions;
01064 
01065     /* In case of Quick command, remove autoend mode */
01066     /* Manage the stop generation by software */
01067     if (hsmbus->pBuffPtr == NULL)
01068     {
01069       hsmbus->XferOptions &= ~SMBUS_AUTOEND_MODE;
01070     }
01071 
01072     if (Size > MAX_NBYTE_SIZE)
01073     {
01074       hsmbus->XferSize = MAX_NBYTE_SIZE;
01075     }
01076     else
01077     {
01078       hsmbus->XferSize = Size;
01079     }
01080 
01081     /* Send Slave Address */
01082     /* Set NBYTES to write and reload if size > MAX_NBYTE_SIZE and generate RESTART */
01083     if ((hsmbus->XferSize < hsmbus->XferCount) && (hsmbus->XferSize == MAX_NBYTE_SIZE))
01084     {
01085       SMBUS_TransferConfig(hsmbus, DevAddress, (uint8_t)hsmbus->XferSize,
01086                            SMBUS_RELOAD_MODE  | (hsmbus->XferOptions & SMBUS_SENDPEC_MODE),
01087                            SMBUS_GENERATE_START_READ);
01088     }
01089     else
01090     {
01091       /* If transfer direction not change, do not generate Restart Condition */
01092       /* Mean Previous state is same as current state */
01093 
01094       /* Store current volatile XferOptions, Misra rule */
01095       tmp = hsmbus->XferOptions;
01096 
01097       if ((hsmbus->PreviousState == HAL_SMBUS_STATE_MASTER_BUSY_RX) && \
01098           (IS_SMBUS_TRANSFER_OTHER_OPTIONS_REQUEST(tmp) == 0))
01099       {
01100         SMBUS_TransferConfig(hsmbus, DevAddress, (uint8_t)hsmbus->XferSize, hsmbus->XferOptions,
01101                              SMBUS_NO_STARTSTOP);
01102       }
01103       /* Else transfer direction change, so generate Restart with new transfer direction */
01104       else
01105       {
01106         /* Convert OTHER_xxx XferOptions if any */
01107         SMBUS_ConvertOtherXferOptions(hsmbus);
01108 
01109         /* Handle Transfer */
01110         SMBUS_TransferConfig(hsmbus, DevAddress, (uint8_t)hsmbus->XferSize,
01111                              hsmbus->XferOptions,
01112                              SMBUS_GENERATE_START_READ);
01113       }
01114     }
01115 
01116     /* Process Unlocked */
01117     __HAL_UNLOCK(hsmbus);
01118 
01119     /* Note : The SMBUS interrupts must be enabled after unlocking current process
01120               to avoid the risk of SMBUS interrupt handle execution before current
01121               process unlock */
01122     SMBUS_Enable_IRQ(hsmbus, SMBUS_IT_RX);
01123 
01124     return HAL_OK;
01125   }
01126   else
01127   {
01128     return HAL_BUSY;
01129   }
01130 }
01131 
01132 /**
01133   * @brief  Abort a master/host SMBUS process communication with Interrupt.
01134   * @note   This abort can be called only if state is ready
01135   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
01136   *                the configuration information for the specified SMBUS.
01137   * @param  DevAddress Target device address: The device 7 bits address value
01138   *         in datasheet must be shifted to the left before calling the interface
01139   * @retval HAL status
01140   */
01141 HAL_StatusTypeDef HAL_SMBUS_Master_Abort_IT(SMBUS_HandleTypeDef *hsmbus, uint16_t DevAddress)
01142 {
01143   if (hsmbus->State == HAL_SMBUS_STATE_READY)
01144   {
01145     /* Process Locked */
01146     __HAL_LOCK(hsmbus);
01147 
01148     /* Keep the same state as previous */
01149     /* to perform as well the call of the corresponding end of transfer callback */
01150     if (hsmbus->PreviousState == HAL_SMBUS_STATE_MASTER_BUSY_TX)
01151     {
01152       hsmbus->State = HAL_SMBUS_STATE_MASTER_BUSY_TX;
01153     }
01154     else if (hsmbus->PreviousState == HAL_SMBUS_STATE_MASTER_BUSY_RX)
01155     {
01156       hsmbus->State = HAL_SMBUS_STATE_MASTER_BUSY_RX;
01157     }
01158     else
01159     {
01160       /* Wrong usage of abort function */
01161       /* This function should be used only in case of abort monitored by master device */
01162       return HAL_ERROR;
01163     }
01164     hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE;
01165 
01166     /* Set NBYTES to 1 to generate a dummy read on SMBUS peripheral */
01167     /* Set AUTOEND mode, this will generate a NACK then STOP condition to abort the current transfer */
01168     SMBUS_TransferConfig(hsmbus, DevAddress, 1, SMBUS_AUTOEND_MODE, SMBUS_NO_STARTSTOP);
01169 
01170     /* Process Unlocked */
01171     __HAL_UNLOCK(hsmbus);
01172 
01173     /* Note : The SMBUS interrupts must be enabled after unlocking current process
01174               to avoid the risk of SMBUS interrupt handle execution before current
01175               process unlock */
01176     if (hsmbus->State == HAL_SMBUS_STATE_MASTER_BUSY_TX)
01177     {
01178       SMBUS_Enable_IRQ(hsmbus, SMBUS_IT_TX);
01179     }
01180     else if (hsmbus->State == HAL_SMBUS_STATE_MASTER_BUSY_RX)
01181     {
01182       SMBUS_Enable_IRQ(hsmbus, SMBUS_IT_RX);
01183     }
01184     else
01185     {
01186       /* Nothing to do */
01187     }
01188 
01189     return HAL_OK;
01190   }
01191   else
01192   {
01193     return HAL_BUSY;
01194   }
01195 }
01196 
01197 /**
01198   * @brief  Transmit in slave/device SMBUS mode an amount of data in non-blocking mode with Interrupt.
01199   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
01200   *                the configuration information for the specified SMBUS.
01201   * @param  pData Pointer to data buffer
01202   * @param  Size Amount of data to be sent
01203   * @param  XferOptions Options of Transfer, value of @ref SMBUS_XferOptions_definition
01204   * @retval HAL status
01205   */
01206 HAL_StatusTypeDef HAL_SMBUS_Slave_Transmit_IT(SMBUS_HandleTypeDef *hsmbus, uint8_t *pData, uint16_t Size,
01207                                               uint32_t XferOptions)
01208 {
01209   /* Check the parameters */
01210   assert_param(IS_SMBUS_TRANSFER_OPTIONS_REQUEST(XferOptions));
01211 
01212   if ((hsmbus->State & HAL_SMBUS_STATE_LISTEN) == HAL_SMBUS_STATE_LISTEN)
01213   {
01214     if ((pData == NULL) || (Size == 0UL))
01215     {
01216       hsmbus->ErrorCode = HAL_SMBUS_ERROR_INVALID_PARAM;
01217       return HAL_ERROR;
01218     }
01219 
01220     /* Disable Interrupts, to prevent preemption during treatment in case of multicall */
01221     SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_ADDR | SMBUS_IT_TX);
01222 
01223     /* Process Locked */
01224     __HAL_LOCK(hsmbus);
01225 
01226     hsmbus->State = (HAL_SMBUS_STATE_SLAVE_BUSY_TX | HAL_SMBUS_STATE_LISTEN);
01227     hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE;
01228 
01229     /* Set SBC bit to manage Acknowledge at each bit */
01230     hsmbus->Instance->CR1 |= I2C_CR1_SBC;
01231 
01232     /* Enable Address Acknowledge */
01233     hsmbus->Instance->CR2 &= ~I2C_CR2_NACK;
01234 
01235     /* Prepare transfer parameters */
01236     hsmbus->pBuffPtr = pData;
01237     hsmbus->XferCount = Size;
01238     hsmbus->XferOptions = XferOptions;
01239 
01240     /* Convert OTHER_xxx XferOptions if any */
01241     SMBUS_ConvertOtherXferOptions(hsmbus);
01242 
01243     if (Size > MAX_NBYTE_SIZE)
01244     {
01245       hsmbus->XferSize = MAX_NBYTE_SIZE;
01246     }
01247     else
01248     {
01249       hsmbus->XferSize = Size;
01250     }
01251 
01252     /* Set NBYTES to write and reload if size > MAX_NBYTE_SIZE and generate RESTART */
01253     if ((hsmbus->XferSize < hsmbus->XferCount) && (hsmbus->XferSize == MAX_NBYTE_SIZE))
01254     {
01255       SMBUS_TransferConfig(hsmbus, 0, (uint8_t)hsmbus->XferSize,
01256                            SMBUS_RELOAD_MODE | (hsmbus->XferOptions & SMBUS_SENDPEC_MODE),
01257                            SMBUS_NO_STARTSTOP);
01258     }
01259     else
01260     {
01261       /* Set NBYTE to transmit */
01262       SMBUS_TransferConfig(hsmbus, 0, (uint8_t)hsmbus->XferSize, hsmbus->XferOptions,
01263                            SMBUS_NO_STARTSTOP);
01264 
01265       /* If PEC mode is enable, size to transmit should be Size-1 byte, corresponding to PEC byte */
01266       /* PEC byte is automatically sent by HW block, no need to manage it in Transmit process */
01267       if (SMBUS_GET_PEC_MODE(hsmbus) != 0UL)
01268       {
01269         hsmbus->XferSize--;
01270         hsmbus->XferCount--;
01271       }
01272     }
01273 
01274     /* Clear ADDR flag after prepare the transfer parameters */
01275     /* This action will generate an acknowledge to the HOST */
01276     __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_ADDR);
01277 
01278     /* Process Unlocked */
01279     __HAL_UNLOCK(hsmbus);
01280 
01281     /* Note : The SMBUS interrupts must be enabled after unlocking current process
01282               to avoid the risk of SMBUS interrupt handle execution before current
01283               process unlock */
01284     /* REnable ADDR interrupt */
01285     SMBUS_Enable_IRQ(hsmbus, SMBUS_IT_TX | SMBUS_IT_ADDR);
01286 
01287     return HAL_OK;
01288   }
01289   else
01290   {
01291     return HAL_BUSY;
01292   }
01293 }
01294 
01295 /**
01296   * @brief  Receive in slave/device SMBUS mode an amount of data in non-blocking mode with Interrupt.
01297   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
01298   *                the configuration information for the specified SMBUS.
01299   * @param  pData Pointer to data buffer
01300   * @param  Size Amount of data to be sent
01301   * @param  XferOptions Options of Transfer, value of @ref SMBUS_XferOptions_definition
01302   * @retval HAL status
01303   */
01304 HAL_StatusTypeDef HAL_SMBUS_Slave_Receive_IT(SMBUS_HandleTypeDef *hsmbus, uint8_t *pData, uint16_t Size,
01305                                              uint32_t XferOptions)
01306 {
01307   /* Check the parameters */
01308   assert_param(IS_SMBUS_TRANSFER_OPTIONS_REQUEST(XferOptions));
01309 
01310   if ((hsmbus->State & HAL_SMBUS_STATE_LISTEN) == HAL_SMBUS_STATE_LISTEN)
01311   {
01312     if ((pData == NULL) || (Size == 0UL))
01313     {
01314       hsmbus->ErrorCode = HAL_SMBUS_ERROR_INVALID_PARAM;
01315       return HAL_ERROR;
01316     }
01317 
01318     /* Disable Interrupts, to prevent preemption during treatment in case of multicall */
01319     SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_ADDR | SMBUS_IT_RX);
01320 
01321     /* Process Locked */
01322     __HAL_LOCK(hsmbus);
01323 
01324     hsmbus->State = (HAL_SMBUS_STATE_SLAVE_BUSY_RX | HAL_SMBUS_STATE_LISTEN);
01325     hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE;
01326 
01327     /* Set SBC bit to manage Acknowledge at each bit */
01328     hsmbus->Instance->CR1 |= I2C_CR1_SBC;
01329 
01330     /* Enable Address Acknowledge */
01331     hsmbus->Instance->CR2 &= ~I2C_CR2_NACK;
01332 
01333     /* Prepare transfer parameters */
01334     hsmbus->pBuffPtr = pData;
01335     hsmbus->XferSize = Size;
01336     hsmbus->XferCount = Size;
01337     hsmbus->XferOptions = XferOptions;
01338 
01339     /* Convert OTHER_xxx XferOptions if any */
01340     SMBUS_ConvertOtherXferOptions(hsmbus);
01341 
01342     /* Set NBYTE to receive */
01343     /* If XferSize equal "1", or XferSize equal "2" with PEC requested (mean 1 data byte + 1 PEC byte */
01344     /* no need to set RELOAD bit mode, a ACK will be automatically generated in that case */
01345     /* else need to set RELOAD bit mode to generate an automatic ACK at each byte Received */
01346     /* This RELOAD bit will be reset for last BYTE to be receive in SMBUS_Slave_ISR */
01347     if (((SMBUS_GET_PEC_MODE(hsmbus) != 0UL) && (hsmbus->XferSize == 2U)) || (hsmbus->XferSize == 1U))
01348     {
01349       SMBUS_TransferConfig(hsmbus, 0, (uint8_t)hsmbus->XferSize, hsmbus->XferOptions,
01350                            SMBUS_NO_STARTSTOP);
01351     }
01352     else
01353     {
01354       SMBUS_TransferConfig(hsmbus, 0, 1, hsmbus->XferOptions | SMBUS_RELOAD_MODE, SMBUS_NO_STARTSTOP);
01355     }
01356 
01357     /* Clear ADDR flag after prepare the transfer parameters */
01358     /* This action will generate an acknowledge to the HOST */
01359     __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_ADDR);
01360 
01361     /* Process Unlocked */
01362     __HAL_UNLOCK(hsmbus);
01363 
01364     /* Note : The SMBUS interrupts must be enabled after unlocking current process
01365               to avoid the risk of SMBUS interrupt handle execution before current
01366               process unlock */
01367     /* REnable ADDR interrupt */
01368     SMBUS_Enable_IRQ(hsmbus, SMBUS_IT_RX | SMBUS_IT_ADDR);
01369 
01370     return HAL_OK;
01371   }
01372   else
01373   {
01374     return HAL_BUSY;
01375   }
01376 }
01377 
01378 /**
01379   * @brief  Enable the Address listen mode with Interrupt.
01380   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
01381   *                the configuration information for the specified SMBUS.
01382   * @retval HAL status
01383   */
01384 HAL_StatusTypeDef HAL_SMBUS_EnableListen_IT(SMBUS_HandleTypeDef *hsmbus)
01385 {
01386   hsmbus->State = HAL_SMBUS_STATE_LISTEN;
01387 
01388   /* Enable the Address Match interrupt */
01389   SMBUS_Enable_IRQ(hsmbus, SMBUS_IT_ADDR);
01390 
01391   return HAL_OK;
01392 }
01393 
01394 /**
01395   * @brief  Disable the Address listen mode with Interrupt.
01396   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
01397   *                the configuration information for the specified SMBUS.
01398   * @retval HAL status
01399   */
01400 HAL_StatusTypeDef HAL_SMBUS_DisableListen_IT(SMBUS_HandleTypeDef *hsmbus)
01401 {
01402   /* Disable Address listen mode only if a transfer is not ongoing */
01403   if (hsmbus->State == HAL_SMBUS_STATE_LISTEN)
01404   {
01405     hsmbus->State = HAL_SMBUS_STATE_READY;
01406 
01407     /* Disable the Address Match interrupt */
01408     SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_ADDR);
01409 
01410     return HAL_OK;
01411   }
01412   else
01413   {
01414     return HAL_BUSY;
01415   }
01416 }
01417 
01418 /**
01419   * @brief  Enable the SMBUS alert mode with Interrupt.
01420   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
01421   *                the configuration information for the specified SMBUSx peripheral.
01422   * @retval HAL status
01423   */
01424 HAL_StatusTypeDef HAL_SMBUS_EnableAlert_IT(SMBUS_HandleTypeDef *hsmbus)
01425 {
01426   /* Enable SMBus alert */
01427   hsmbus->Instance->CR1 |= I2C_CR1_ALERTEN;
01428 
01429   /* Clear ALERT flag */
01430   __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_ALERT);
01431 
01432   /* Enable Alert Interrupt */
01433   SMBUS_Enable_IRQ(hsmbus, SMBUS_IT_ALERT);
01434 
01435   return HAL_OK;
01436 }
01437 /**
01438   * @brief  Disable the SMBUS alert mode with Interrupt.
01439   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
01440   *                the configuration information for the specified SMBUSx peripheral.
01441   * @retval HAL status
01442   */
01443 HAL_StatusTypeDef HAL_SMBUS_DisableAlert_IT(SMBUS_HandleTypeDef *hsmbus)
01444 {
01445   /* Enable SMBus alert */
01446   hsmbus->Instance->CR1 &= ~I2C_CR1_ALERTEN;
01447 
01448   /* Disable Alert Interrupt */
01449   SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_ALERT);
01450 
01451   return HAL_OK;
01452 }
01453 
01454 /**
01455   * @brief  Check if target device is ready for communication.
01456   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
01457   *                the configuration information for the specified SMBUS.
01458   * @param  DevAddress Target device address: The device 7 bits address value
01459   *         in datasheet must be shifted to the left before calling the interface
01460   * @param  Trials Number of trials
01461   * @param  Timeout Timeout duration
01462   * @retval HAL status
01463   */
01464 HAL_StatusTypeDef HAL_SMBUS_IsDeviceReady(SMBUS_HandleTypeDef *hsmbus, uint16_t DevAddress, uint32_t Trials,
01465                                           uint32_t Timeout)
01466 {
01467   uint32_t tickstart;
01468 
01469   __IO uint32_t SMBUS_Trials = 0UL;
01470 
01471   FlagStatus tmp1;
01472   FlagStatus tmp2;
01473 
01474   if (hsmbus->State == HAL_SMBUS_STATE_READY)
01475   {
01476     if (__HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_BUSY) != RESET)
01477     {
01478       return HAL_BUSY;
01479     }
01480 
01481     /* Process Locked */
01482     __HAL_LOCK(hsmbus);
01483 
01484     hsmbus->State = HAL_SMBUS_STATE_BUSY;
01485     hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE;
01486 
01487     do
01488     {
01489       /* Generate Start */
01490       hsmbus->Instance->CR2 = SMBUS_GENERATE_START(hsmbus->Init.AddressingMode, DevAddress);
01491 
01492       /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
01493       /* Wait until STOPF flag is set or a NACK flag is set*/
01494       tickstart = HAL_GetTick();
01495 
01496       tmp1 = __HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_STOPF);
01497       tmp2 = __HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_AF);
01498 
01499       while ((tmp1 == RESET) && (tmp2 == RESET))
01500       {
01501         if (Timeout != HAL_MAX_DELAY)
01502         {
01503           if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0UL))
01504           {
01505             /* Device is ready */
01506             hsmbus->State = HAL_SMBUS_STATE_READY;
01507 
01508             /* Update SMBUS error code */
01509             hsmbus->ErrorCode |= HAL_SMBUS_ERROR_HALTIMEOUT;
01510 
01511             /* Process Unlocked */
01512             __HAL_UNLOCK(hsmbus);
01513             return HAL_ERROR;
01514           }
01515         }
01516 
01517         tmp1 = __HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_STOPF);
01518         tmp2 = __HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_AF);
01519       }
01520 
01521       /* Check if the NACKF flag has not been set */
01522       if (__HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_AF) == RESET)
01523       {
01524         /* Wait until STOPF flag is reset */
01525         if (SMBUS_WaitOnFlagUntilTimeout(hsmbus, SMBUS_FLAG_STOPF, RESET, Timeout) != HAL_OK)
01526         {
01527           return HAL_ERROR;
01528         }
01529 
01530         /* Clear STOP Flag */
01531         __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_STOPF);
01532 
01533         /* Device is ready */
01534         hsmbus->State = HAL_SMBUS_STATE_READY;
01535 
01536         /* Process Unlocked */
01537         __HAL_UNLOCK(hsmbus);
01538 
01539         return HAL_OK;
01540       }
01541       else
01542       {
01543         /* Wait until STOPF flag is reset */
01544         if (SMBUS_WaitOnFlagUntilTimeout(hsmbus, SMBUS_FLAG_STOPF, RESET, Timeout) != HAL_OK)
01545         {
01546           return HAL_ERROR;
01547         }
01548 
01549         /* Clear NACK Flag */
01550         __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_AF);
01551 
01552         /* Clear STOP Flag, auto generated with autoend*/
01553         __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_STOPF);
01554       }
01555 
01556       /* Check if the maximum allowed number of trials has been reached */
01557       if (SMBUS_Trials == Trials)
01558       {
01559         /* Generate Stop */
01560         hsmbus->Instance->CR2 |= I2C_CR2_STOP;
01561 
01562         /* Wait until STOPF flag is reset */
01563         if (SMBUS_WaitOnFlagUntilTimeout(hsmbus, SMBUS_FLAG_STOPF, RESET, Timeout) != HAL_OK)
01564         {
01565           return HAL_ERROR;
01566         }
01567 
01568         /* Clear STOP Flag */
01569         __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_STOPF);
01570       }
01571 
01572       /* Increment Trials */
01573       SMBUS_Trials++;
01574     } while (SMBUS_Trials < Trials);
01575 
01576     hsmbus->State = HAL_SMBUS_STATE_READY;
01577 
01578     /* Update SMBUS error code */
01579     hsmbus->ErrorCode |= HAL_SMBUS_ERROR_HALTIMEOUT;
01580 
01581     /* Process Unlocked */
01582     __HAL_UNLOCK(hsmbus);
01583 
01584     return HAL_ERROR;
01585   }
01586   else
01587   {
01588     return HAL_BUSY;
01589   }
01590 }
01591 /**
01592   * @}
01593   */
01594 
01595 /** @defgroup SMBUS_IRQ_Handler_and_Callbacks IRQ Handler and Callbacks
01596   * @{
01597   */
01598 
01599 /**
01600   * @brief  Handle SMBUS event interrupt request.
01601   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
01602   *                the configuration information for the specified SMBUS.
01603   * @retval None
01604   */
01605 void HAL_SMBUS_EV_IRQHandler(SMBUS_HandleTypeDef *hsmbus)
01606 {
01607   /* Use a local variable to store the current ISR flags */
01608   /* This action will avoid a wrong treatment due to ISR flags change during interrupt handler */
01609   uint32_t tmpisrvalue = READ_REG(hsmbus->Instance->ISR);
01610   uint32_t tmpcr1value = READ_REG(hsmbus->Instance->CR1);
01611 
01612   /* SMBUS in mode Transmitter ---------------------------------------------------*/
01613   if ((SMBUS_CHECK_IT_SOURCE(tmpcr1value, (SMBUS_IT_TCI | SMBUS_IT_STOPI |
01614                                            SMBUS_IT_NACKI | SMBUS_IT_TXI)) != RESET) &&
01615       ((SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_TXIS) != RESET) ||
01616        (SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_TCR) != RESET) ||
01617        (SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_TC) != RESET) ||
01618        (SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_STOPF) != RESET) ||
01619        (SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_AF) != RESET)))
01620   {
01621     /* Slave mode selected */
01622     if ((hsmbus->State & HAL_SMBUS_STATE_SLAVE_BUSY_TX) == HAL_SMBUS_STATE_SLAVE_BUSY_TX)
01623     {
01624       (void)SMBUS_Slave_ISR(hsmbus, tmpisrvalue);
01625     }
01626     /* Master mode selected */
01627     else if ((hsmbus->State & HAL_SMBUS_STATE_MASTER_BUSY_TX) == HAL_SMBUS_STATE_MASTER_BUSY_TX)
01628     {
01629       (void)SMBUS_Master_ISR(hsmbus, tmpisrvalue);
01630     }
01631     else
01632     {
01633       /* Nothing to do */
01634     }
01635   }
01636 
01637   /* SMBUS in mode Receiver ----------------------------------------------------*/
01638   if ((SMBUS_CHECK_IT_SOURCE(tmpcr1value, (SMBUS_IT_TCI | SMBUS_IT_STOPI |
01639                                            SMBUS_IT_NACKI | SMBUS_IT_RXI)) != RESET) &&
01640       ((SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_RXNE) != RESET) ||
01641        (SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_TCR) != RESET) ||
01642        (SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_TC) != RESET) ||
01643        (SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_STOPF) != RESET) ||
01644        (SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_AF) != RESET)))
01645   {
01646     /* Slave mode selected */
01647     if ((hsmbus->State & HAL_SMBUS_STATE_SLAVE_BUSY_RX) == HAL_SMBUS_STATE_SLAVE_BUSY_RX)
01648     {
01649       (void)SMBUS_Slave_ISR(hsmbus, tmpisrvalue);
01650     }
01651     /* Master mode selected */
01652     else if ((hsmbus->State & HAL_SMBUS_STATE_MASTER_BUSY_RX) == HAL_SMBUS_STATE_MASTER_BUSY_RX)
01653     {
01654       (void)SMBUS_Master_ISR(hsmbus, tmpisrvalue);
01655     }
01656     else
01657     {
01658       /* Nothing to do */
01659     }
01660   }
01661 
01662   /* SMBUS in mode Listener Only --------------------------------------------------*/
01663   if (((SMBUS_CHECK_IT_SOURCE(tmpcr1value, SMBUS_IT_ADDRI) != RESET) ||
01664        (SMBUS_CHECK_IT_SOURCE(tmpcr1value, SMBUS_IT_STOPI) != RESET) ||
01665        (SMBUS_CHECK_IT_SOURCE(tmpcr1value, SMBUS_IT_NACKI) != RESET)) &&
01666       ((SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_ADDR) != RESET) ||
01667        (SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_STOPF) != RESET) ||
01668        (SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_AF) != RESET)))
01669   {
01670     if ((hsmbus->State & HAL_SMBUS_STATE_LISTEN) == HAL_SMBUS_STATE_LISTEN)
01671     {
01672       (void)SMBUS_Slave_ISR(hsmbus, tmpisrvalue);
01673     }
01674   }
01675 }
01676 
01677 /**
01678   * @brief  Handle SMBUS error interrupt request.
01679   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
01680   *                the configuration information for the specified SMBUS.
01681   * @retval None
01682   */
01683 void HAL_SMBUS_ER_IRQHandler(SMBUS_HandleTypeDef *hsmbus)
01684 {
01685   SMBUS_ITErrorHandler(hsmbus);
01686 }
01687 
01688 /**
01689   * @brief  Master Tx Transfer completed callback.
01690   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
01691   *                the configuration information for the specified SMBUS.
01692   * @retval None
01693   */
01694 __weak void HAL_SMBUS_MasterTxCpltCallback(SMBUS_HandleTypeDef *hsmbus)
01695 {
01696   /* Prevent unused argument(s) compilation warning */
01697   UNUSED(hsmbus);
01698 
01699   /* NOTE : This function should not be modified, when the callback is needed,
01700             the HAL_SMBUS_MasterTxCpltCallback() could be implemented in the user file
01701    */
01702 }
01703 
01704 /**
01705   * @brief  Master Rx Transfer completed callback.
01706   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
01707   *                the configuration information for the specified SMBUS.
01708   * @retval None
01709   */
01710 __weak void HAL_SMBUS_MasterRxCpltCallback(SMBUS_HandleTypeDef *hsmbus)
01711 {
01712   /* Prevent unused argument(s) compilation warning */
01713   UNUSED(hsmbus);
01714 
01715   /* NOTE : This function should not be modified, when the callback is needed,
01716             the HAL_SMBUS_MasterRxCpltCallback() could be implemented in the user file
01717    */
01718 }
01719 
01720 /** @brief  Slave Tx Transfer completed callback.
01721   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
01722   *                the configuration information for the specified SMBUS.
01723   * @retval None
01724   */
01725 __weak void HAL_SMBUS_SlaveTxCpltCallback(SMBUS_HandleTypeDef *hsmbus)
01726 {
01727   /* Prevent unused argument(s) compilation warning */
01728   UNUSED(hsmbus);
01729 
01730   /* NOTE : This function should not be modified, when the callback is needed,
01731             the HAL_SMBUS_SlaveTxCpltCallback() could be implemented in the user file
01732    */
01733 }
01734 
01735 /**
01736   * @brief  Slave Rx Transfer completed callback.
01737   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
01738   *                the configuration information for the specified SMBUS.
01739   * @retval None
01740   */
01741 __weak void HAL_SMBUS_SlaveRxCpltCallback(SMBUS_HandleTypeDef *hsmbus)
01742 {
01743   /* Prevent unused argument(s) compilation warning */
01744   UNUSED(hsmbus);
01745 
01746   /* NOTE : This function should not be modified, when the callback is needed,
01747             the HAL_SMBUS_SlaveRxCpltCallback() could be implemented in the user file
01748    */
01749 }
01750 
01751 /**
01752   * @brief  Slave Address Match callback.
01753   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
01754   *                the configuration information for the specified SMBUS.
01755   * @param  TransferDirection Master request Transfer Direction (Write/Read)
01756   * @param  AddrMatchCode Address Match Code
01757   * @retval None
01758   */
01759 __weak void HAL_SMBUS_AddrCallback(SMBUS_HandleTypeDef *hsmbus, uint8_t TransferDirection,
01760                                    uint16_t AddrMatchCode)
01761 {
01762   /* Prevent unused argument(s) compilation warning */
01763   UNUSED(hsmbus);
01764   UNUSED(TransferDirection);
01765   UNUSED(AddrMatchCode);
01766 
01767   /* NOTE : This function should not be modified, when the callback is needed,
01768             the HAL_SMBUS_AddrCallback() could be implemented in the user file
01769    */
01770 }
01771 
01772 /**
01773   * @brief  Listen Complete callback.
01774   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
01775   *                the configuration information for the specified SMBUS.
01776   * @retval None
01777   */
01778 __weak void HAL_SMBUS_ListenCpltCallback(SMBUS_HandleTypeDef *hsmbus)
01779 {
01780   /* Prevent unused argument(s) compilation warning */
01781   UNUSED(hsmbus);
01782 
01783   /* NOTE : This function should not be modified, when the callback is needed,
01784             the HAL_SMBUS_ListenCpltCallback() could be implemented in the user file
01785    */
01786 }
01787 
01788 /**
01789   * @brief  SMBUS error callback.
01790   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
01791   *                the configuration information for the specified SMBUS.
01792   * @retval None
01793   */
01794 __weak void HAL_SMBUS_ErrorCallback(SMBUS_HandleTypeDef *hsmbus)
01795 {
01796   /* Prevent unused argument(s) compilation warning */
01797   UNUSED(hsmbus);
01798 
01799   /* NOTE : This function should not be modified, when the callback is needed,
01800             the HAL_SMBUS_ErrorCallback() could be implemented in the user file
01801    */
01802 }
01803 
01804 /**
01805   * @}
01806   */
01807 
01808 /** @defgroup SMBUS_Exported_Functions_Group3 Peripheral State and Errors functions
01809   *  @brief   Peripheral State and Errors functions
01810   *
01811 @verbatim
01812  ===============================================================================
01813             ##### Peripheral State and Errors functions #####
01814  ===============================================================================
01815     [..]
01816     This subsection permits to get in run-time the status of the peripheral
01817     and the data flow.
01818 
01819 @endverbatim
01820   * @{
01821   */
01822 
01823 /**
01824   * @brief  Return the SMBUS handle state.
01825   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
01826   *                the configuration information for the specified SMBUS.
01827   * @retval HAL state
01828   */
01829 uint32_t HAL_SMBUS_GetState(SMBUS_HandleTypeDef *hsmbus)
01830 {
01831   /* Return SMBUS handle state */
01832   return hsmbus->State;
01833 }
01834 
01835 /**
01836   * @brief  Return the SMBUS error code.
01837   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
01838   *              the configuration information for the specified SMBUS.
01839   * @retval SMBUS Error Code
01840   */
01841 uint32_t HAL_SMBUS_GetError(SMBUS_HandleTypeDef *hsmbus)
01842 {
01843   return hsmbus->ErrorCode;
01844 }
01845 
01846 /**
01847   * @}
01848   */
01849 
01850 /**
01851   * @}
01852   */
01853 
01854 /** @addtogroup SMBUS_Private_Functions SMBUS Private Functions
01855   *  @brief   Data transfers Private functions
01856   * @{
01857   */
01858 
01859 /**
01860   * @brief  Interrupt Sub-Routine which handle the Interrupt Flags Master Mode.
01861   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
01862   *                the configuration information for the specified SMBUS.
01863   * @param  StatusFlags Value of Interrupt Flags.
01864   * @retval HAL status
01865   */
01866 static HAL_StatusTypeDef SMBUS_Master_ISR(SMBUS_HandleTypeDef *hsmbus, uint32_t StatusFlags)
01867 {
01868   uint16_t DevAddress;
01869 
01870   /* Process Locked */
01871   __HAL_LOCK(hsmbus);
01872 
01873   if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_AF) != RESET)
01874   {
01875     /* Clear NACK Flag */
01876     __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_AF);
01877 
01878     /* Set corresponding Error Code */
01879     /* No need to generate STOP, it is automatically done */
01880     hsmbus->ErrorCode |= HAL_SMBUS_ERROR_ACKF;
01881 
01882     /* Flush TX register */
01883     SMBUS_Flush_TXDR(hsmbus);
01884 
01885     /* Process Unlocked */
01886     __HAL_UNLOCK(hsmbus);
01887 
01888     /* Call the Error callback to inform upper layer */
01889 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
01890     hsmbus->ErrorCallback(hsmbus);
01891 #else
01892     HAL_SMBUS_ErrorCallback(hsmbus);
01893 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
01894   }
01895   else if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_STOPF) != RESET)
01896   {
01897     /* Check and treat errors if errors occurs during STOP process */
01898     SMBUS_ITErrorHandler(hsmbus);
01899 
01900     /* Call the corresponding callback to inform upper layer of End of Transfer */
01901     if (hsmbus->State == HAL_SMBUS_STATE_MASTER_BUSY_TX)
01902     {
01903       /* Disable Interrupt */
01904       SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_TX);
01905 
01906       /* Clear STOP Flag */
01907       __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_STOPF);
01908 
01909       /* Clear Configuration Register 2 */
01910       SMBUS_RESET_CR2(hsmbus);
01911 
01912       /* Flush remaining data in Fifo register in case of error occurs before TXEmpty */
01913       /* Disable the selected SMBUS peripheral */
01914       __HAL_SMBUS_DISABLE(hsmbus);
01915 
01916       hsmbus->PreviousState = HAL_SMBUS_STATE_READY;
01917       hsmbus->State = HAL_SMBUS_STATE_READY;
01918 
01919       /* Process Unlocked */
01920       __HAL_UNLOCK(hsmbus);
01921 
01922       /* Re-enable the selected SMBUS peripheral */
01923       __HAL_SMBUS_ENABLE(hsmbus);
01924 
01925       /* Call the corresponding callback to inform upper layer of End of Transfer */
01926 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
01927       hsmbus->MasterTxCpltCallback(hsmbus);
01928 #else
01929       HAL_SMBUS_MasterTxCpltCallback(hsmbus);
01930 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
01931     }
01932     else if (hsmbus->State == HAL_SMBUS_STATE_MASTER_BUSY_RX)
01933     {
01934       /* Store Last receive data if any */
01935       if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_RXNE) != RESET)
01936       {
01937         /* Read data from RXDR */
01938         *hsmbus->pBuffPtr = (uint8_t)(hsmbus->Instance->RXDR);
01939 
01940         /* Increment Buffer pointer */
01941         hsmbus->pBuffPtr++;
01942 
01943         if ((hsmbus->XferSize > 0U))
01944         {
01945           hsmbus->XferSize--;
01946           hsmbus->XferCount--;
01947         }
01948       }
01949 
01950       /* Disable Interrupt */
01951       SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_RX);
01952 
01953       /* Clear STOP Flag */
01954       __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_STOPF);
01955 
01956       /* Clear Configuration Register 2 */
01957       SMBUS_RESET_CR2(hsmbus);
01958 
01959       hsmbus->PreviousState = HAL_SMBUS_STATE_READY;
01960       hsmbus->State = HAL_SMBUS_STATE_READY;
01961 
01962       /* Process Unlocked */
01963       __HAL_UNLOCK(hsmbus);
01964 
01965       /* Call the corresponding callback to inform upper layer of End of Transfer */
01966 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
01967       hsmbus->MasterRxCpltCallback(hsmbus);
01968 #else
01969       HAL_SMBUS_MasterRxCpltCallback(hsmbus);
01970 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
01971     }
01972     else
01973     {
01974       /* Nothing to do */
01975     }
01976   }
01977   else if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_RXNE) != RESET)
01978   {
01979     /* Read data from RXDR */
01980     *hsmbus->pBuffPtr = (uint8_t)(hsmbus->Instance->RXDR);
01981 
01982     /* Increment Buffer pointer */
01983     hsmbus->pBuffPtr++;
01984 
01985     /* Increment Size counter */
01986     hsmbus->XferSize--;
01987     hsmbus->XferCount--;
01988   }
01989   else if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_TXIS) != RESET)
01990   {
01991     /* Write data to TXDR */
01992     hsmbus->Instance->TXDR = *hsmbus->pBuffPtr;
01993 
01994     /* Increment Buffer pointer */
01995     hsmbus->pBuffPtr++;
01996 
01997     /* Increment Size counter */
01998     hsmbus->XferSize--;
01999     hsmbus->XferCount--;
02000   }
02001   else if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_TCR) != RESET)
02002   {
02003     if ((hsmbus->XferCount != 0U) && (hsmbus->XferSize == 0U))
02004     {
02005       DevAddress = (uint16_t)(hsmbus->Instance->CR2 & I2C_CR2_SADD);
02006 
02007       if (hsmbus->XferCount > MAX_NBYTE_SIZE)
02008       {
02009         SMBUS_TransferConfig(hsmbus, DevAddress, MAX_NBYTE_SIZE,
02010                              (SMBUS_RELOAD_MODE | (hsmbus->XferOptions & SMBUS_SENDPEC_MODE)),
02011                              SMBUS_NO_STARTSTOP);
02012         hsmbus->XferSize = MAX_NBYTE_SIZE;
02013       }
02014       else
02015       {
02016         hsmbus->XferSize = hsmbus->XferCount;
02017         SMBUS_TransferConfig(hsmbus, DevAddress, (uint8_t)hsmbus->XferSize, hsmbus->XferOptions,
02018                              SMBUS_NO_STARTSTOP);
02019         /* If PEC mode is enable, size to transmit should be Size-1 byte, corresponding to PEC byte */
02020         /* PEC byte is automatically sent by HW block, no need to manage it in Transmit process */
02021         if (SMBUS_GET_PEC_MODE(hsmbus) != 0UL)
02022         {
02023           hsmbus->XferSize--;
02024           hsmbus->XferCount--;
02025         }
02026       }
02027     }
02028     else if ((hsmbus->XferCount == 0U) && (hsmbus->XferSize == 0U))
02029     {
02030       /* Call TxCpltCallback() if no stop mode is set */
02031       if (SMBUS_GET_STOP_MODE(hsmbus) != SMBUS_AUTOEND_MODE)
02032       {
02033         /* Call the corresponding callback to inform upper layer of End of Transfer */
02034         if (hsmbus->State == HAL_SMBUS_STATE_MASTER_BUSY_TX)
02035         {
02036           /* Disable Interrupt */
02037           SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_TX);
02038           hsmbus->PreviousState = hsmbus->State;
02039           hsmbus->State = HAL_SMBUS_STATE_READY;
02040 
02041           /* Process Unlocked */
02042           __HAL_UNLOCK(hsmbus);
02043 
02044           /* Call the corresponding callback to inform upper layer of End of Transfer */
02045 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
02046           hsmbus->MasterTxCpltCallback(hsmbus);
02047 #else
02048           HAL_SMBUS_MasterTxCpltCallback(hsmbus);
02049 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
02050         }
02051         else if (hsmbus->State == HAL_SMBUS_STATE_MASTER_BUSY_RX)
02052         {
02053           SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_RX);
02054           hsmbus->PreviousState = hsmbus->State;
02055           hsmbus->State = HAL_SMBUS_STATE_READY;
02056 
02057           /* Process Unlocked */
02058           __HAL_UNLOCK(hsmbus);
02059 
02060           /* Call the corresponding callback to inform upper layer of End of Transfer */
02061 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
02062           hsmbus->MasterRxCpltCallback(hsmbus);
02063 #else
02064           HAL_SMBUS_MasterRxCpltCallback(hsmbus);
02065 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
02066         }
02067         else
02068         {
02069           /* Nothing to do */
02070         }
02071       }
02072     }
02073     else
02074     {
02075       /* Nothing to do */
02076     }
02077   }
02078   else if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_TC) != RESET)
02079   {
02080     if (hsmbus->XferCount == 0U)
02081     {
02082       /* Specific use case for Quick command */
02083       if (hsmbus->pBuffPtr == NULL)
02084       {
02085         /* Generate a Stop command */
02086         hsmbus->Instance->CR2 |= I2C_CR2_STOP;
02087       }
02088       /* Call TxCpltCallback() if no stop mode is set */
02089       else if (SMBUS_GET_STOP_MODE(hsmbus) != SMBUS_AUTOEND_MODE)
02090       {
02091         /* No Generate Stop, to permit restart mode */
02092         /* The stop will be done at the end of transfer, when SMBUS_AUTOEND_MODE enable */
02093 
02094         /* Call the corresponding callback to inform upper layer of End of Transfer */
02095         if (hsmbus->State == HAL_SMBUS_STATE_MASTER_BUSY_TX)
02096         {
02097           /* Disable Interrupt */
02098           SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_TX);
02099           hsmbus->PreviousState = hsmbus->State;
02100           hsmbus->State = HAL_SMBUS_STATE_READY;
02101 
02102           /* Process Unlocked */
02103           __HAL_UNLOCK(hsmbus);
02104 
02105           /* Call the corresponding callback to inform upper layer of End of Transfer */
02106 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
02107           hsmbus->MasterTxCpltCallback(hsmbus);
02108 #else
02109           HAL_SMBUS_MasterTxCpltCallback(hsmbus);
02110 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
02111         }
02112         else if (hsmbus->State == HAL_SMBUS_STATE_MASTER_BUSY_RX)
02113         {
02114           SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_RX);
02115           hsmbus->PreviousState = hsmbus->State;
02116           hsmbus->State = HAL_SMBUS_STATE_READY;
02117 
02118           /* Process Unlocked */
02119           __HAL_UNLOCK(hsmbus);
02120 
02121           /* Call the corresponding callback to inform upper layer of End of Transfer */
02122 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
02123           hsmbus->MasterRxCpltCallback(hsmbus);
02124 #else
02125           HAL_SMBUS_MasterRxCpltCallback(hsmbus);
02126 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
02127         }
02128         else
02129         {
02130           /* Nothing to do */
02131         }
02132       }
02133       else
02134       {
02135         /* Nothing to do */
02136       }
02137     }
02138   }
02139   else
02140   {
02141     /* Nothing to do */
02142   }
02143 
02144   /* Process Unlocked */
02145   __HAL_UNLOCK(hsmbus);
02146 
02147   return HAL_OK;
02148 }
02149 /**
02150   * @brief  Interrupt Sub-Routine which handle the Interrupt Flags Slave Mode.
02151   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
02152   *                the configuration information for the specified SMBUS.
02153   * @param  StatusFlags Value of Interrupt Flags.
02154   * @retval HAL status
02155   */
02156 static HAL_StatusTypeDef SMBUS_Slave_ISR(SMBUS_HandleTypeDef *hsmbus, uint32_t StatusFlags)
02157 {
02158   uint8_t TransferDirection;
02159   uint16_t SlaveAddrCode;
02160 
02161   /* Process Locked */
02162   __HAL_LOCK(hsmbus);
02163 
02164   if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_AF) != RESET)
02165   {
02166     /* Check that SMBUS transfer finished */
02167     /* if yes, normal usecase, a NACK is sent by the HOST when Transfer is finished */
02168     /* Mean XferCount == 0*/
02169     /* So clear Flag NACKF only */
02170     if (hsmbus->XferCount == 0U)
02171     {
02172       /* Clear NACK Flag */
02173       __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_AF);
02174 
02175       /* Flush TX register */
02176       SMBUS_Flush_TXDR(hsmbus);
02177 
02178       /* Process Unlocked */
02179       __HAL_UNLOCK(hsmbus);
02180     }
02181     else
02182     {
02183       /* if no, error usecase, a Non-Acknowledge of last Data is generated by the HOST*/
02184       /* Clear NACK Flag */
02185       __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_AF);
02186 
02187       /* Set HAL State to "Idle" State, mean to LISTEN state */
02188       /* So reset Slave Busy state */
02189       hsmbus->PreviousState = hsmbus->State;
02190       hsmbus->State &= ~((uint32_t)HAL_SMBUS_STATE_SLAVE_BUSY_TX);
02191       hsmbus->State &= ~((uint32_t)HAL_SMBUS_STATE_SLAVE_BUSY_RX);
02192 
02193       /* Disable RX/TX Interrupts, keep only ADDR Interrupt */
02194       SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_RX | SMBUS_IT_TX);
02195 
02196       /* Set ErrorCode corresponding to a Non-Acknowledge */
02197       hsmbus->ErrorCode |= HAL_SMBUS_ERROR_ACKF;
02198 
02199       /* Flush TX register */
02200       SMBUS_Flush_TXDR(hsmbus);
02201 
02202       /* Process Unlocked */
02203       __HAL_UNLOCK(hsmbus);
02204 
02205       /* Call the Error callback to inform upper layer */
02206 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
02207       hsmbus->ErrorCallback(hsmbus);
02208 #else
02209       HAL_SMBUS_ErrorCallback(hsmbus);
02210 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
02211     }
02212   }
02213   else if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_ADDR) != RESET)
02214   {
02215     TransferDirection = (uint8_t)(SMBUS_GET_DIR(hsmbus));
02216     SlaveAddrCode = (uint16_t)(SMBUS_GET_ADDR_MATCH(hsmbus));
02217 
02218     /* Disable ADDR interrupt to prevent multiple ADDRInterrupt*/
02219     /* Other ADDRInterrupt will be treat in next Listen usecase */
02220     __HAL_SMBUS_DISABLE_IT(hsmbus, SMBUS_IT_ADDRI);
02221 
02222     /* Process Unlocked */
02223     __HAL_UNLOCK(hsmbus);
02224 
02225     /* Call Slave Addr callback */
02226 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
02227     hsmbus->AddrCallback(hsmbus, TransferDirection, SlaveAddrCode);
02228 #else
02229     HAL_SMBUS_AddrCallback(hsmbus, TransferDirection, SlaveAddrCode);
02230 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
02231   }
02232   else if ((SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_RXNE) != RESET) ||
02233            (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_TCR) != RESET))
02234   {
02235     if ((hsmbus->State & HAL_SMBUS_STATE_SLAVE_BUSY_RX) == HAL_SMBUS_STATE_SLAVE_BUSY_RX)
02236     {
02237       /* Read data from RXDR */
02238       *hsmbus->pBuffPtr = (uint8_t)(hsmbus->Instance->RXDR);
02239 
02240       /* Increment Buffer pointer */
02241       hsmbus->pBuffPtr++;
02242 
02243       hsmbus->XferSize--;
02244       hsmbus->XferCount--;
02245 
02246       if (hsmbus->XferCount == 1U)
02247       {
02248         /* Receive last Byte, can be PEC byte in case of PEC BYTE enabled */
02249         /* or only the last Byte of Transfer */
02250         /* So reset the RELOAD bit mode */
02251         hsmbus->XferOptions &= ~SMBUS_RELOAD_MODE;
02252         SMBUS_TransferConfig(hsmbus, 0, 1, hsmbus->XferOptions, SMBUS_NO_STARTSTOP);
02253       }
02254       else if (hsmbus->XferCount == 0U)
02255       {
02256         /* Last Byte is received, disable Interrupt */
02257         SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_RX);
02258 
02259         /* Remove HAL_SMBUS_STATE_SLAVE_BUSY_RX, keep only HAL_SMBUS_STATE_LISTEN */
02260         hsmbus->PreviousState = hsmbus->State;
02261         hsmbus->State &= ~((uint32_t)HAL_SMBUS_STATE_SLAVE_BUSY_RX);
02262 
02263         /* Process Unlocked */
02264         __HAL_UNLOCK(hsmbus);
02265 
02266         /* Call the corresponding callback to inform upper layer of End of Transfer */
02267 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
02268         hsmbus->SlaveRxCpltCallback(hsmbus);
02269 #else
02270         HAL_SMBUS_SlaveRxCpltCallback(hsmbus);
02271 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
02272       }
02273       else
02274       {
02275         /* Set Reload for next Bytes */
02276         SMBUS_TransferConfig(hsmbus, 0, 1,
02277                              SMBUS_RELOAD_MODE  | (hsmbus->XferOptions & SMBUS_SENDPEC_MODE),
02278                              SMBUS_NO_STARTSTOP);
02279 
02280         /* Ack last Byte Read */
02281         hsmbus->Instance->CR2 &= ~I2C_CR2_NACK;
02282       }
02283     }
02284     else if ((hsmbus->State & HAL_SMBUS_STATE_SLAVE_BUSY_TX) == HAL_SMBUS_STATE_SLAVE_BUSY_TX)
02285     {
02286       if ((hsmbus->XferCount != 0U) && (hsmbus->XferSize == 0U))
02287       {
02288         if (hsmbus->XferCount > MAX_NBYTE_SIZE)
02289         {
02290           SMBUS_TransferConfig(hsmbus, 0, MAX_NBYTE_SIZE,
02291                                (SMBUS_RELOAD_MODE | (hsmbus->XferOptions & SMBUS_SENDPEC_MODE)),
02292                                SMBUS_NO_STARTSTOP);
02293           hsmbus->XferSize = MAX_NBYTE_SIZE;
02294         }
02295         else
02296         {
02297           hsmbus->XferSize = hsmbus->XferCount;
02298           SMBUS_TransferConfig(hsmbus, 0, (uint8_t)hsmbus->XferSize, hsmbus->XferOptions,
02299                                SMBUS_NO_STARTSTOP);
02300           /* If PEC mode is enable, size to transmit should be Size-1 byte, corresponding to PEC byte */
02301           /* PEC byte is automatically sent by HW block, no need to manage it in Transmit process */
02302           if (SMBUS_GET_PEC_MODE(hsmbus) != 0UL)
02303           {
02304             hsmbus->XferSize--;
02305             hsmbus->XferCount--;
02306           }
02307         }
02308       }
02309     }
02310     else
02311     {
02312       /* Nothing to do */
02313     }
02314   }
02315   else if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_TXIS) != RESET)
02316   {
02317     /* Write data to TXDR only if XferCount not reach "0" */
02318     /* A TXIS flag can be set, during STOP treatment      */
02319     /* Check if all Data have already been sent */
02320     /* If it is the case, this last write in TXDR is not sent, correspond to a dummy TXIS event */
02321     if (hsmbus->XferCount > 0U)
02322     {
02323       /* Write data to TXDR */
02324       hsmbus->Instance->TXDR = *hsmbus->pBuffPtr;
02325 
02326       /* Increment Buffer pointer */
02327       hsmbus->pBuffPtr++;
02328 
02329       hsmbus->XferCount--;
02330       hsmbus->XferSize--;
02331     }
02332 
02333     if (hsmbus->XferCount == 0U)
02334     {
02335       /* Last Byte is Transmitted */
02336       /* Remove HAL_SMBUS_STATE_SLAVE_BUSY_TX, keep only HAL_SMBUS_STATE_LISTEN */
02337       SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_TX);
02338       hsmbus->PreviousState = hsmbus->State;
02339       hsmbus->State &= ~((uint32_t)HAL_SMBUS_STATE_SLAVE_BUSY_TX);
02340 
02341       /* Process Unlocked */
02342       __HAL_UNLOCK(hsmbus);
02343 
02344       /* Call the corresponding callback to inform upper layer of End of Transfer */
02345 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
02346       hsmbus->SlaveTxCpltCallback(hsmbus);
02347 #else
02348       HAL_SMBUS_SlaveTxCpltCallback(hsmbus);
02349 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
02350     }
02351   }
02352   else
02353   {
02354     /* Nothing to do */
02355   }
02356 
02357   /* Check if STOPF is set */
02358   if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_STOPF) != RESET)
02359   {
02360     if ((hsmbus->State & HAL_SMBUS_STATE_LISTEN) == HAL_SMBUS_STATE_LISTEN)
02361     {
02362       /* Store Last receive data if any */
02363       if (__HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_RXNE) != RESET)
02364       {
02365         /* Read data from RXDR */
02366         *hsmbus->pBuffPtr = (uint8_t)(hsmbus->Instance->RXDR);
02367 
02368         /* Increment Buffer pointer */
02369         hsmbus->pBuffPtr++;
02370 
02371         if ((hsmbus->XferSize > 0U))
02372         {
02373           hsmbus->XferSize--;
02374           hsmbus->XferCount--;
02375         }
02376       }
02377 
02378       /* Disable RX and TX Interrupts */
02379       SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_RX | SMBUS_IT_TX);
02380 
02381       /* Disable ADDR Interrupt */
02382       SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_ADDR);
02383 
02384       /* Disable Address Acknowledge */
02385       hsmbus->Instance->CR2 |= I2C_CR2_NACK;
02386 
02387       /* Clear Configuration Register 2 */
02388       SMBUS_RESET_CR2(hsmbus);
02389 
02390       /* Clear STOP Flag */
02391       __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_STOPF);
02392 
02393       /* Clear ADDR flag */
02394       __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_ADDR);
02395 
02396       hsmbus->XferOptions = 0;
02397       hsmbus->PreviousState = hsmbus->State;
02398       hsmbus->State = HAL_SMBUS_STATE_READY;
02399 
02400       /* Process Unlocked */
02401       __HAL_UNLOCK(hsmbus);
02402 
02403       /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */
02404 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
02405       hsmbus->ListenCpltCallback(hsmbus);
02406 #else
02407       HAL_SMBUS_ListenCpltCallback(hsmbus);
02408 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
02409     }
02410   }
02411 
02412   /* Process Unlocked */
02413   __HAL_UNLOCK(hsmbus);
02414 
02415   return HAL_OK;
02416 }
02417 /**
02418   * @brief  Manage the enabling of Interrupts.
02419   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
02420   *                the configuration information for the specified SMBUS.
02421   * @param  InterruptRequest Value of @ref SMBUS_Interrupt_configuration_definition.
02422   * @retval HAL status
02423   */
02424 static void SMBUS_Enable_IRQ(SMBUS_HandleTypeDef *hsmbus, uint32_t InterruptRequest)
02425 {
02426   uint32_t tmpisr = 0UL;
02427 
02428   if ((InterruptRequest & SMBUS_IT_ALERT) == SMBUS_IT_ALERT)
02429   {
02430     /* Enable ERR interrupt */
02431     tmpisr |= SMBUS_IT_ERRI;
02432   }
02433 
02434   if ((InterruptRequest & SMBUS_IT_ADDR) == SMBUS_IT_ADDR)
02435   {
02436     /* Enable ADDR, STOP interrupt */
02437     tmpisr |= SMBUS_IT_ADDRI | SMBUS_IT_STOPI | SMBUS_IT_NACKI | SMBUS_IT_ERRI;
02438   }
02439 
02440   if ((InterruptRequest & SMBUS_IT_TX) == SMBUS_IT_TX)
02441   {
02442     /* Enable ERR, TC, STOP, NACK, RXI interrupt */
02443     tmpisr |= SMBUS_IT_ERRI | SMBUS_IT_TCI | SMBUS_IT_STOPI | SMBUS_IT_NACKI | SMBUS_IT_TXI;
02444   }
02445 
02446   if ((InterruptRequest & SMBUS_IT_RX) == SMBUS_IT_RX)
02447   {
02448     /* Enable ERR, TC, STOP, NACK, TXI interrupt */
02449     tmpisr |= SMBUS_IT_ERRI | SMBUS_IT_TCI | SMBUS_IT_STOPI | SMBUS_IT_NACKI | SMBUS_IT_RXI;
02450   }
02451 
02452   /* Enable interrupts only at the end */
02453   /* to avoid the risk of SMBUS interrupt handle execution before */
02454   /* all interrupts requested done */
02455   __HAL_SMBUS_ENABLE_IT(hsmbus, tmpisr);
02456 }
02457 /**
02458   * @brief  Manage the disabling of Interrupts.
02459   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
02460   *                the configuration information for the specified SMBUS.
02461   * @param  InterruptRequest Value of @ref SMBUS_Interrupt_configuration_definition.
02462   * @retval HAL status
02463   */
02464 static void SMBUS_Disable_IRQ(SMBUS_HandleTypeDef *hsmbus, uint32_t InterruptRequest)
02465 {
02466   uint32_t tmpisr = 0UL;
02467   uint32_t tmpstate = hsmbus->State;
02468 
02469   if ((tmpstate == HAL_SMBUS_STATE_READY) && ((InterruptRequest & SMBUS_IT_ALERT) == SMBUS_IT_ALERT))
02470   {
02471     /* Disable ERR interrupt */
02472     tmpisr |= SMBUS_IT_ERRI;
02473   }
02474 
02475   if ((InterruptRequest & SMBUS_IT_TX) == SMBUS_IT_TX)
02476   {
02477     /* Disable TC, STOP, NACK and TXI interrupt */
02478     tmpisr |= SMBUS_IT_TCI | SMBUS_IT_TXI;
02479 
02480     if ((SMBUS_GET_ALERT_ENABLED(hsmbus) == 0UL)
02481         && ((tmpstate & HAL_SMBUS_STATE_LISTEN) != HAL_SMBUS_STATE_LISTEN))
02482     {
02483       /* Disable ERR interrupt */
02484       tmpisr |= SMBUS_IT_ERRI;
02485     }
02486 
02487     if ((tmpstate & HAL_SMBUS_STATE_LISTEN) != HAL_SMBUS_STATE_LISTEN)
02488     {
02489       /* Disable STOP and NACK interrupt */
02490       tmpisr |= SMBUS_IT_STOPI | SMBUS_IT_NACKI;
02491     }
02492   }
02493 
02494   if ((InterruptRequest & SMBUS_IT_RX) == SMBUS_IT_RX)
02495   {
02496     /* Disable TC, STOP, NACK and RXI interrupt */
02497     tmpisr |= SMBUS_IT_TCI | SMBUS_IT_RXI;
02498 
02499     if ((SMBUS_GET_ALERT_ENABLED(hsmbus) == 0UL)
02500         && ((tmpstate & HAL_SMBUS_STATE_LISTEN) != HAL_SMBUS_STATE_LISTEN))
02501     {
02502       /* Disable ERR interrupt */
02503       tmpisr |= SMBUS_IT_ERRI;
02504     }
02505 
02506     if ((tmpstate & HAL_SMBUS_STATE_LISTEN) != HAL_SMBUS_STATE_LISTEN)
02507     {
02508       /* Disable STOP and NACK interrupt */
02509       tmpisr |= SMBUS_IT_STOPI | SMBUS_IT_NACKI;
02510     }
02511   }
02512 
02513   if ((InterruptRequest & SMBUS_IT_ADDR) == SMBUS_IT_ADDR)
02514   {
02515     /* Disable ADDR, STOP and NACK interrupt */
02516     tmpisr |= SMBUS_IT_ADDRI | SMBUS_IT_STOPI | SMBUS_IT_NACKI;
02517 
02518     if (SMBUS_GET_ALERT_ENABLED(hsmbus) == 0UL)
02519     {
02520       /* Disable ERR interrupt */
02521       tmpisr |= SMBUS_IT_ERRI;
02522     }
02523   }
02524 
02525   /* Disable interrupts only at the end */
02526   /* to avoid a breaking situation like at "t" time */
02527   /* all disable interrupts request are not done */
02528   __HAL_SMBUS_DISABLE_IT(hsmbus, tmpisr);
02529 }
02530 
02531 /**
02532   * @brief  SMBUS interrupts error handler.
02533   * @param  hsmbus SMBUS handle.
02534   * @retval None
02535   */
02536 static void SMBUS_ITErrorHandler(SMBUS_HandleTypeDef *hsmbus)
02537 {
02538   uint32_t itflags   = READ_REG(hsmbus->Instance->ISR);
02539   uint32_t itsources = READ_REG(hsmbus->Instance->CR1);
02540   uint32_t tmpstate;
02541   uint32_t tmperror;
02542 
02543   /* SMBUS Bus error interrupt occurred ------------------------------------*/
02544   if (((itflags & SMBUS_FLAG_BERR) == SMBUS_FLAG_BERR) && \
02545       ((itsources & SMBUS_IT_ERRI) == SMBUS_IT_ERRI))
02546   {
02547     hsmbus->ErrorCode |= HAL_SMBUS_ERROR_BERR;
02548 
02549     /* Clear BERR flag */
02550     __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_BERR);
02551   }
02552 
02553   /* SMBUS Over-Run/Under-Run interrupt occurred ----------------------------------------*/
02554   if (((itflags & SMBUS_FLAG_OVR) == SMBUS_FLAG_OVR) && \
02555       ((itsources & SMBUS_IT_ERRI) == SMBUS_IT_ERRI))
02556   {
02557     hsmbus->ErrorCode |= HAL_SMBUS_ERROR_OVR;
02558 
02559     /* Clear OVR flag */
02560     __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_OVR);
02561   }
02562 
02563   /* SMBUS Arbitration Loss error interrupt occurred ------------------------------------*/
02564   if (((itflags & SMBUS_FLAG_ARLO) == SMBUS_FLAG_ARLO) && \
02565       ((itsources & SMBUS_IT_ERRI) == SMBUS_IT_ERRI))
02566   {
02567     hsmbus->ErrorCode |= HAL_SMBUS_ERROR_ARLO;
02568 
02569     /* Clear ARLO flag */
02570     __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_ARLO);
02571   }
02572 
02573   /* SMBUS Timeout error interrupt occurred ---------------------------------------------*/
02574   if (((itflags & SMBUS_FLAG_TIMEOUT) == SMBUS_FLAG_TIMEOUT) && \
02575       ((itsources & SMBUS_IT_ERRI) == SMBUS_IT_ERRI))
02576   {
02577     hsmbus->ErrorCode |= HAL_SMBUS_ERROR_BUSTIMEOUT;
02578 
02579     /* Clear TIMEOUT flag */
02580     __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_TIMEOUT);
02581   }
02582 
02583   /* SMBUS Alert error interrupt occurred -----------------------------------------------*/
02584   if (((itflags & SMBUS_FLAG_ALERT) == SMBUS_FLAG_ALERT) && \
02585       ((itsources & SMBUS_IT_ERRI) == SMBUS_IT_ERRI))
02586   {
02587     hsmbus->ErrorCode |= HAL_SMBUS_ERROR_ALERT;
02588 
02589     /* Clear ALERT flag */
02590     __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_ALERT);
02591   }
02592 
02593   /* SMBUS Packet Error Check error interrupt occurred ----------------------------------*/
02594   if (((itflags & SMBUS_FLAG_PECERR) == SMBUS_FLAG_PECERR) && \
02595       ((itsources & SMBUS_IT_ERRI) == SMBUS_IT_ERRI))
02596   {
02597     hsmbus->ErrorCode |= HAL_SMBUS_ERROR_PECERR;
02598 
02599     /* Clear PEC error flag */
02600     __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_PECERR);
02601   }
02602 
02603   /* Flush TX register */
02604   SMBUS_Flush_TXDR(hsmbus);
02605 
02606   /* Store current volatile hsmbus->ErrorCode, misra rule */
02607   tmperror = hsmbus->ErrorCode;
02608 
02609   /* Call the Error Callback in case of Error detected */
02610   if ((tmperror != HAL_SMBUS_ERROR_NONE) && (tmperror != HAL_SMBUS_ERROR_ACKF))
02611   {
02612     /* Do not Reset the HAL state in case of ALERT error */
02613     if ((tmperror & HAL_SMBUS_ERROR_ALERT) != HAL_SMBUS_ERROR_ALERT)
02614     {
02615       /* Store current volatile hsmbus->State, misra rule */
02616       tmpstate = hsmbus->State;
02617 
02618       if (((tmpstate & HAL_SMBUS_STATE_SLAVE_BUSY_TX) == HAL_SMBUS_STATE_SLAVE_BUSY_TX)
02619           || ((tmpstate & HAL_SMBUS_STATE_SLAVE_BUSY_RX) == HAL_SMBUS_STATE_SLAVE_BUSY_RX))
02620       {
02621         /* Reset only HAL_SMBUS_STATE_SLAVE_BUSY_XX */
02622         /* keep HAL_SMBUS_STATE_LISTEN if set */
02623         hsmbus->PreviousState = HAL_SMBUS_STATE_READY;
02624         hsmbus->State = HAL_SMBUS_STATE_LISTEN;
02625       }
02626     }
02627 
02628     /* Call the Error callback to inform upper layer */
02629 #if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
02630     hsmbus->ErrorCallback(hsmbus);
02631 #else
02632     HAL_SMBUS_ErrorCallback(hsmbus);
02633 #endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
02634   }
02635 }
02636 
02637 /**
02638   * @brief  Handle SMBUS Communication Timeout.
02639   * @param  hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
02640   *                the configuration information for the specified SMBUS.
02641   * @param  Flag Specifies the SMBUS flag to check.
02642   * @param  Status The new Flag status (SET or RESET).
02643   * @param  Timeout Timeout duration
02644   * @retval HAL status
02645   */
02646 static HAL_StatusTypeDef SMBUS_WaitOnFlagUntilTimeout(SMBUS_HandleTypeDef *hsmbus, uint32_t Flag,
02647                                                       FlagStatus Status, uint32_t Timeout)
02648 {
02649   uint32_t tickstart = HAL_GetTick();
02650 
02651   /* Wait until flag is set */
02652   while ((FlagStatus)(__HAL_SMBUS_GET_FLAG(hsmbus, Flag)) == Status)
02653   {
02654     /* Check for the Timeout */
02655     if (Timeout != HAL_MAX_DELAY)
02656     {
02657       if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0UL))
02658       {
02659         hsmbus->PreviousState = hsmbus->State;
02660         hsmbus->State = HAL_SMBUS_STATE_READY;
02661 
02662         /* Update SMBUS error code */
02663         hsmbus->ErrorCode |= HAL_SMBUS_ERROR_HALTIMEOUT;
02664 
02665         /* Process Unlocked */
02666         __HAL_UNLOCK(hsmbus);
02667 
02668         return HAL_ERROR;
02669       }
02670     }
02671   }
02672 
02673   return HAL_OK;
02674 }
02675 
02676 /**
02677   * @brief  SMBUS Tx data register flush process.
02678   * @param  hsmbus SMBUS handle.
02679   * @retval None
02680   */
02681 static void SMBUS_Flush_TXDR(SMBUS_HandleTypeDef *hsmbus)
02682 {
02683   /* If a pending TXIS flag is set */
02684   /* Write a dummy data in TXDR to clear it */
02685   if (__HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_TXIS) != RESET)
02686   {
02687     hsmbus->Instance->TXDR = 0x00U;
02688   }
02689 
02690   /* Flush TX register if not empty */
02691   if (__HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_TXE) == RESET)
02692   {
02693     __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_TXE);
02694   }
02695 }
02696 
02697 /**
02698   * @brief  Handle SMBUSx communication when starting transfer or during transfer (TC or TCR flag are set).
02699   * @param  hsmbus SMBUS handle.
02700   * @param  DevAddress specifies the slave address to be programmed.
02701   * @param  Size specifies the number of bytes to be programmed.
02702   *   This parameter must be a value between 0 and 255.
02703   * @param  Mode New state of the SMBUS START condition generation.
02704   *   This parameter can be one or a combination  of the following values:
02705   *     @arg @ref SMBUS_RELOAD_MODE Enable Reload mode.
02706   *     @arg @ref SMBUS_AUTOEND_MODE Enable Automatic end mode.
02707   *     @arg @ref SMBUS_SOFTEND_MODE Enable Software end mode and Reload mode.
02708   *     @arg @ref SMBUS_SENDPEC_MODE Enable Packet Error Calculation mode.
02709   * @param  Request New state of the SMBUS START condition generation.
02710   *   This parameter can be one of the following values:
02711   *     @arg @ref SMBUS_NO_STARTSTOP Don't Generate stop and start condition.
02712   *     @arg @ref SMBUS_GENERATE_STOP Generate stop condition (Size should be set to 0).
02713   *     @arg @ref SMBUS_GENERATE_START_READ Generate Restart for read request.
02714   *     @arg @ref SMBUS_GENERATE_START_WRITE Generate Restart for write request.
02715   * @retval None
02716   */
02717 static void SMBUS_TransferConfig(SMBUS_HandleTypeDef *hsmbus,  uint16_t DevAddress, uint8_t Size,
02718                                  uint32_t Mode, uint32_t Request)
02719 {
02720   /* Check the parameters */
02721   assert_param(IS_SMBUS_ALL_INSTANCE(hsmbus->Instance));
02722   assert_param(IS_SMBUS_TRANSFER_MODE(Mode));
02723   assert_param(IS_SMBUS_TRANSFER_REQUEST(Request));
02724 
02725   /* update CR2 register */
02726   MODIFY_REG(hsmbus->Instance->CR2,
02727              ((I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_AUTOEND | \
02728                (I2C_CR2_RD_WRN & (uint32_t)(Request >> (31UL - I2C_CR2_RD_WRN_Pos))) | \
02729                I2C_CR2_START | I2C_CR2_STOP | I2C_CR2_PECBYTE)), \
02730              (uint32_t)(((uint32_t)DevAddress & I2C_CR2_SADD) | \
02731                         (((uint32_t)Size << I2C_CR2_NBYTES_Pos) & I2C_CR2_NBYTES) | \
02732                         (uint32_t)Mode | (uint32_t)Request));
02733 }
02734 
02735 /**
02736   * @brief  Convert SMBUSx OTHER_xxx XferOptions to functional XferOptions.
02737   * @param  hsmbus SMBUS handle.
02738   * @retval None
02739   */
02740 static void SMBUS_ConvertOtherXferOptions(SMBUS_HandleTypeDef *hsmbus)
02741 {
02742   /* if user set XferOptions to SMBUS_OTHER_FRAME_NO_PEC   */
02743   /* it request implicitly to generate a restart condition */
02744   /* set XferOptions to SMBUS_FIRST_FRAME                  */
02745   if (hsmbus->XferOptions == SMBUS_OTHER_FRAME_NO_PEC)
02746   {
02747     hsmbus->XferOptions = SMBUS_FIRST_FRAME;
02748   }
02749   /* else if user set XferOptions to SMBUS_OTHER_FRAME_WITH_PEC */
02750   /* it request implicitly to generate a restart condition      */
02751   /* set XferOptions to SMBUS_FIRST_FRAME | SMBUS_SENDPEC_MODE  */
02752   else if (hsmbus->XferOptions == SMBUS_OTHER_FRAME_WITH_PEC)
02753   {
02754     hsmbus->XferOptions = SMBUS_FIRST_FRAME | SMBUS_SENDPEC_MODE;
02755   }
02756   /* else if user set XferOptions to SMBUS_OTHER_AND_LAST_FRAME_NO_PEC */
02757   /* it request implicitly to generate a restart condition             */
02758   /* then generate a stop condition at the end of transfer             */
02759   /* set XferOptions to SMBUS_FIRST_AND_LAST_FRAME_NO_PEC              */
02760   else if (hsmbus->XferOptions == SMBUS_OTHER_AND_LAST_FRAME_NO_PEC)
02761   {
02762     hsmbus->XferOptions = SMBUS_FIRST_AND_LAST_FRAME_NO_PEC;
02763   }
02764   /* else if user set XferOptions to SMBUS_OTHER_AND_LAST_FRAME_WITH_PEC */
02765   /* it request implicitly to generate a restart condition               */
02766   /* then generate a stop condition at the end of transfer               */
02767   /* set XferOptions to SMBUS_FIRST_AND_LAST_FRAME_WITH_PEC              */
02768   else if (hsmbus->XferOptions == SMBUS_OTHER_AND_LAST_FRAME_WITH_PEC)
02769   {
02770     hsmbus->XferOptions = SMBUS_FIRST_AND_LAST_FRAME_WITH_PEC;
02771   }
02772   else
02773   {
02774     /* Nothing to do */
02775   }
02776 }
02777 /**
02778   * @}
02779   */
02780 
02781 #endif /* HAL_SMBUS_MODULE_ENABLED */
02782 /**
02783   * @}
02784   */
02785 
02786 /**
02787   * @}
02788   */