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