1 /**
2   ******************************************************************************
3   * @file    stm32wbaxx_hal_comp.c
4   * @author  MCD Application Team
5   * @brief   COMP HAL module driver.
6   *          This file provides firmware functions to manage the following
7   *          functionalities of the COMP peripheral:
8   *           + Initialization and de-initialization functions
9   *           + Peripheral control functions
10   *           + Peripheral state functions
11   *
12   ******************************************************************************
13   * @attention
14   *
15   * Copyright (c) 2022 STMicroelectronics.
16   * All rights reserved.
17   *
18   * This software is licensed under terms that can be found in the LICENSE file
19   * in the root directory of this software component.
20   * If no LICENSE file comes with this software, it is provided AS-IS.
21   *
22   ******************************************************************************
23   @verbatim
24   ==============================================================================
25           ##### COMP Peripheral features #####
26   ==============================================================================
27 
28   [..]
29       The STM32WBAxx device family integrates two analog comparators instances:
30       COMP1, COMP2.
31       (#) Comparators input minus (inverting input) and input plus (non inverting input)
32           can be set to internal references or to GPIO pins
33           (refer to GPIO list in reference manual).
34 
35       (#) Comparators output level is available using HAL_COMP_GetOutputLevel()
36           and can be redirected to other peripherals: GPIO pins (in mode
37           alternate functions for comparator), timers.
38           (refer to GPIO list in reference manual).
39 
40       (#) The comparators have interrupt capability through the EXTI controller
41           with wake-up from sleep and stop modes.
42 
43       (#) Pairs of comparators instances can be combined in window mode
44           (2 consecutive instances odd and even COMP<x> and COMP<x+1>).
45 
46           From the corresponding IRQ handler, the right interrupt source can be retrieved
47           using macro __HAL_COMP_COMPx_EXTI_GET_FLAG().
48 
49             ##### How to use this driver #####
50   ==============================================================================
51   [..]
52       This driver provides functions to configure and program the comparator instances
53       of STM32WBAxx devices.
54 
55       To use the comparator, perform the following steps:
56 
57       (#)  Initialize the COMP low level resources by implementing the HAL_COMP_MspInit():
58       (++) Configure the GPIO connected to comparator inputs plus and minus in analog mode
59            using HAL_GPIO_Init().
60       (++) If needed, configure the GPIO connected to comparator output in alternate function mode
61            using HAL_GPIO_Init().
62       (++) If required enable the COMP interrupt by configuring and enabling EXTI line in Interrupt mode and
63            selecting the desired sensitivity level using HAL_GPIO_Init() function. After that enable the comparator
64            interrupt vector using HAL_NVIC_EnableIRQ() function.
65 
66       (#) Configure the comparator using HAL_COMP_Init() function:
67       (++) Select the input minus (inverting input)
68       (++) Select the input plus (non-inverting input)
69       (++) Select the hysteresis
70       (++) Select the blanking source
71       (++) Select the output polarity
72       (++) Select the power mode
73       (++) Select the window mode
74 
75       -@@- HAL_COMP_Init() calls internally __HAL_RCC_SYSCFG_CLK_ENABLE()
76           to enable internal control clock of the comparators.
77           However, this is a legacy strategy. In future STM32 families,
78           COMP clock enable must be implemented by user in "HAL_COMP_MspInit()".
79           Therefore, for compatibility anticipation, it is recommended to
80           implement __HAL_RCC_SYSCFG_CLK_ENABLE() in "HAL_COMP_MspInit()".
81 
82       (#) Reconfiguration on-the-fly of comparator can be done by calling again
83           function HAL_COMP_Init() with new input structure parameters values.
84 
85       (#) Enable the comparator using HAL_COMP_Start() function.
86 
87       (#) Use HAL_COMP_TriggerCallback() or HAL_COMP_GetOutputLevel() functions
88           to manage comparator outputs (events and output level).
89 
90       (#) Disable the comparator using HAL_COMP_Stop() function.
91 
92       (#) De-initialize the comparator using HAL_COMP_DeInit() function.
93 
94       (#) For safety purpose, comparator configuration can be locked using HAL_COMP_Lock() function.
95           The only way to unlock the comparator is a device hardware reset.
96 
97     *** Callback registration ***
98     =============================================
99     [..]
100 
101      The compilation flag USE_HAL_COMP_REGISTER_CALLBACKS, when set to 1,
102      allows the user to configure dynamically the driver callbacks.
103      Use Functions HAL_COMP_RegisterCallback()
104      to register an interrupt callback.
105     [..]
106 
107      Function HAL_COMP_RegisterCallback() allows to register following callbacks:
108        (+) TriggerCallback       : callback for COMP trigger.
109        (+) MspInitCallback       : callback for Msp Init.
110        (+) MspDeInitCallback     : callback for Msp DeInit.
111      This function takes as parameters the HAL peripheral handle, the Callback ID
112      and a pointer to the user callback function.
113     [..]
114 
115      Use function HAL_COMP_UnRegisterCallback to reset a callback to the default
116      weak function.
117     [..]
118 
119      HAL_COMP_UnRegisterCallback takes as parameters the HAL peripheral handle,
120      and the Callback ID.
121      This function allows to reset following callbacks:
122        (+) TriggerCallback       : callback for COMP trigger.
123        (+) MspInitCallback       : callback for Msp Init.
124        (+) MspDeInitCallback     : callback for Msp DeInit.
125      [..]
126 
127      By default, after the HAL_COMP_Init() and when the state is HAL_COMP_STATE_RESET
128      all callbacks are set to the corresponding weak functions:
129      example HAL_COMP_TriggerCallback().
130      Exception done for MspInit and MspDeInit functions that are
131      reset to the legacy weak functions in the HAL_COMP_Init()/ HAL_COMP_DeInit() only when
132      these callbacks are null (not registered beforehand).
133     [..]
134 
135      If MspInit or MspDeInit are not null, the HAL_COMP_Init()/ HAL_COMP_DeInit()
136      keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state.
137      [..]
138 
139      Callbacks can be registered/unregistered in HAL_COMP_STATE_READY state only.
140      Exception done MspInit/MspDeInit functions that can be registered/unregistered
141      in HAL_COMP_STATE_READY or HAL_COMP_STATE_RESET state,
142      thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit.
143     [..]
144 
145      Then, the user first registers the MspInit/MspDeInit user callbacks
146      using HAL_COMP_RegisterCallback() before calling HAL_COMP_DeInit()
147      or HAL_COMP_Init() function.
148      [..]
149 
150      When the compilation flag USE_HAL_COMP_REGISTER_CALLBACKS is set to 0 or
151      not defined, the callback registration feature is not available and all callbacks
152      are set to the corresponding weak functions.
153 
154   @endverbatim
155   ******************************************************************************
156   */
157 
158 /* Includes ------------------------------------------------------------------*/
159 #include "stm32wbaxx_hal.h"
160 
161 /** @addtogroup STM32WBAxx_HAL_Driver
162   * @{
163   */
164 
165 #ifdef HAL_COMP_MODULE_ENABLED
166 
167 #if defined (COMP1) || defined (COMP2)
168 
169 /** @defgroup COMP COMP
170   * @brief COMP HAL module driver
171   * @{
172   */
173 
174 /* Private typedef -----------------------------------------------------------*/
175 /* Private define ------------------------------------------------------------*/
176 /** @addtogroup COMP_Private_Constants
177   * @{
178   */
179 
180 /* Delay for COMP startup time.                                               */
181 /* Note: Delay required to reach propagation delay specification.             */
182 /* Literal set to maximum value (refer to device datasheet,                   */
183 /* parameter "tSTART").                                                       */
184 /* Unit: us                                                                   */
185 #define COMP_DELAY_STARTUP_US          (80UL)      /*!< Delay for COMP startup time */
186 
187 /* Delay for COMP voltage scaler stabilization time.                          */
188 /* Literal set to maximum value (refer to device datasheet,                   */
189 /* parameter "tSTART_SCALER").                                                */
190 /* Unit: us                                                                   */
191 #define COMP_DELAY_VOLTAGE_SCALER_STAB_US (200UL)  /*!< Delay for COMP voltage scaler stabilization time */
192 
193 #define COMP_OUTPUT_LEVEL_BITOFFSET_POS    (30UL)
194 
195 /**
196   * @}
197   */
198 
199 /* Private macro -------------------------------------------------------------*/
200 /* Private variables ---------------------------------------------------------*/
201 /* Private function prototypes -----------------------------------------------*/
202 /* Exported functions --------------------------------------------------------*/
203 
204 /** @defgroup COMP_Exported_Functions COMP Exported Functions
205   * @{
206   */
207 
208 /** @defgroup COMP_Exported_Functions_Group1 Initialization/de-initialization functions
209   *  @brief    Initialization and de-initialization functions.
210   *
211 @verbatim
212  ===============================================================================
213               ##### Initialization and de-initialization functions #####
214  ===============================================================================
215     [..]  This section provides functions to initialize and de-initialize comparators
216 
217 @endverbatim
218   * @{
219   */
220 
221 /**
222   * @brief  Initialize the COMP according to the specified
223   *         parameters in the COMP_InitTypeDef and initialize the associated handle.
224   * @note   If the selected comparator is locked, initialization can't be performed.
225   *         To unlock the configuration, perform a system reset.
226   * @param  hcomp  COMP handle
227   * @retval HAL status
228   */
HAL_COMP_Init(COMP_HandleTypeDef * hcomp)229 HAL_StatusTypeDef HAL_COMP_Init(COMP_HandleTypeDef *hcomp)
230 {
231   uint32_t tmp_csr;
232   uint32_t exti_line;
233   uint32_t comp_voltage_scaler_initialized; /* Value "0" if comparator voltage scaler is not initialized */
234   __IO uint32_t wait_loop_index = 0UL;
235   HAL_StatusTypeDef status = HAL_OK;
236 
237   /* Check the COMP handle allocation and lock status */
238   if (hcomp == NULL)
239   {
240     status = HAL_ERROR;
241   }
242   else if (__HAL_COMP_IS_LOCKED(hcomp))
243   {
244     status = HAL_ERROR;
245   }
246   else
247   {
248     /* Check the parameters */
249     assert_param(IS_COMP_ALL_INSTANCE(hcomp->Instance));
250     assert_param(IS_COMP_INPUT_PLUS(hcomp->Instance, hcomp->Init.InputPlus));
251     assert_param(IS_COMP_INPUT_MINUS(hcomp->Instance, hcomp->Init.InputMinus));
252     assert_param(IS_COMP_OUTPUTPOL(hcomp->Init.OutputPol));
253     assert_param(IS_COMP_POWERMODE(hcomp->Init.Mode));
254     assert_param(IS_COMP_HYSTERESIS(hcomp->Init.Hysteresis));
255     assert_param(IS_COMP_BLANKINGSRC_INSTANCE(hcomp->Instance, hcomp->Init.BlankingSrce));
256     assert_param(IS_COMP_TRIGGERMODE(hcomp->Init.TriggerMode));
257 
258     assert_param(IS_COMP_WINDOWMODE(hcomp->Instance, hcomp->Init.WindowMode));
259     if (hcomp->Init.WindowMode != COMP_WINDOWMODE_DISABLE)
260     {
261       assert_param(IS_COMP_WINDOWOUTPUT(hcomp->Init.WindowOutput));
262     }
263 
264 
265     if (hcomp->State == HAL_COMP_STATE_RESET)
266     {
267       /* Allocate lock resource and initialize it */
268       hcomp->Lock = HAL_UNLOCKED;
269 
270       /* Set COMP error code to none */
271       COMP_CLEAR_ERRORCODE(hcomp);
272 
273 #if (USE_HAL_COMP_REGISTER_CALLBACKS == 1)
274       /* Init the COMP Callback settings */
275       hcomp->TriggerCallback = HAL_COMP_TriggerCallback; /* Legacy weak callback */
276 
277       if (hcomp->MspInitCallback == NULL)
278       {
279         hcomp->MspInitCallback = HAL_COMP_MspInit; /* Legacy weak MspInit  */
280       }
281 
282       /* Init the low level hardware */
283       /* Note: Internal control clock of the comparators must                 */
284       /*       be enabled in "HAL_COMP_MspInit()"                             */
285       /*       using "__HAL_RCC_SYSCFG_CLK_ENABLE()".                         */
286       hcomp->MspInitCallback(hcomp);
287 #else
288       /* Init the low level hardware */
289       /* Note: Internal control clock of the comparators must                 */
290       /*       be enabled in "HAL_COMP_MspInit()"                             */
291       /*       using "__HAL_RCC_SYSCFG_CLK_ENABLE()".                         */
292       HAL_COMP_MspInit(hcomp);
293 #endif /* USE_HAL_COMP_REGISTER_CALLBACKS */
294     }
295 
296     /* Memorize voltage scaler state before initialization */
297     comp_voltage_scaler_initialized = READ_BIT(hcomp->Instance->CSR, (COMP_CSR_INMSEL_1 | COMP_CSR_INMSEL_0));
298 
299     /* Set COMP parameters */
300     tmp_csr = (hcomp->Init.InputMinus
301                | hcomp->Init.InputPlus
302                | hcomp->Init.BlankingSrce
303                | hcomp->Init.Hysteresis
304                | hcomp->Init.OutputPol
305                | hcomp->Init.Mode
306               );
307 
308     /* Set parameters in COMP register */
309     /* Note: Update all bits except read-only, lock and enable bits */
310     MODIFY_REG(hcomp->Instance->CSR,
311                COMP_CSR_PWRMODE  | COMP_CSR_INMSEL   | COMP_CSR_INPSEL  |
312                COMP_CSR_WINMODE  | COMP_CSR_POLARITY | COMP_CSR_HYST    |
313                COMP_CSR_BLANKSEL,
314                tmp_csr
315               );
316 
317 
318     /* Set window mode */
319     /* Note: Window mode bit is located into 1 out of the 2 pairs of COMP     */
320     /*       instances. Therefore, this function can update another COMP      */
321     /*       instance that the one currently selected.                        */
322 
323     if (hcomp->Init.WindowMode == COMP_WINDOWMODE_COMP1_INPUT_PLUS_COMMON)
324     {
325       CLEAR_BIT(COMP12_COMMON->CSR_ODD, COMP_CSR_WINMODE);
326       SET_BIT(COMP12_COMMON->CSR_EVEN, COMP_CSR_WINMODE);
327     }
328     else if (hcomp->Init.WindowMode == COMP_WINDOWMODE_COMP2_INPUT_PLUS_COMMON)
329     {
330       SET_BIT(COMP12_COMMON->CSR_ODD, COMP_CSR_WINMODE);
331       CLEAR_BIT(COMP12_COMMON->CSR_EVEN, COMP_CSR_WINMODE);
332     }
333     else
334     {
335       CLEAR_BIT(COMP12_COMMON->CSR_ODD, COMP_CSR_WINMODE);
336       CLEAR_BIT(COMP12_COMMON->CSR_EVEN, COMP_CSR_WINMODE);
337     }
338 
339     /* Set window mode output */
340     /* Note: Window mode mode output can also be used when window mode        */
341     /*       is disabled, to use comparators in independent mode with their   */
342     /*       output connected through exclusive-or circuitry.                 */
343     switch (hcomp->Init.WindowOutput)
344     {
345       case COMP_WINDOWOUTPUT_COMP1:
346         SET_BIT(COMP12_COMMON->CSR_ODD, COMP_CSR_WINOUT);
347         CLEAR_BIT(COMP12_COMMON->CSR_EVEN, COMP_CSR_WINOUT);
348         break;
349 
350       case COMP_WINDOWOUTPUT_COMP2:
351         CLEAR_BIT(COMP12_COMMON->CSR_ODD, COMP_CSR_WINOUT);
352         SET_BIT(COMP12_COMMON->CSR_EVEN, COMP_CSR_WINOUT);
353         break;
354 
355       case COMP_WINDOWOUTPUT_BOTH:
356         SET_BIT(COMP12_COMMON->CSR_ODD, COMP_CSR_WINOUT);
357         SET_BIT(COMP12_COMMON->CSR_EVEN, COMP_CSR_WINOUT);
358         break;
359 
360       default: /* COMP_WINDOWOUTPUT_EACH_COMP */
361         CLEAR_BIT(COMP12_COMMON->CSR_ODD, COMP_CSR_WINOUT);
362         CLEAR_BIT(COMP12_COMMON->CSR_EVEN, COMP_CSR_WINOUT);
363         break;
364     }
365 
366 
367     /* Delay for COMP scaler bridge voltage stabilization */
368     /* Apply the delay if voltage scaler bridge is required and not already enabled */
369     if ((READ_BIT(hcomp->Instance->CSR, (COMP_CSR_INMSEL_1 | COMP_CSR_INMSEL_0)) != 0UL) &&
370         (comp_voltage_scaler_initialized == 0UL))
371     {
372       /* Wait loop initialization and execution */
373       /* Note: Variable divided by 2 to compensate partially              */
374       /*       CPU processing cycles, scaling in us split to not          */
375       /*       exceed 32 bits register capacity and handle low frequency. */
376       wait_loop_index = ((COMP_DELAY_VOLTAGE_SCALER_STAB_US / 10UL) * ((SystemCoreClock / (100000UL * 2UL)) + 1UL));
377       while (wait_loop_index != 0UL)
378       {
379         wait_loop_index--;
380       }
381     }
382 
383     /* Get the EXTI line corresponding to the selected COMP instance */
384     exti_line = COMP_GET_EXTI_LINE(hcomp->Instance);
385 
386     /* Manage EXTI settings */
387     if ((hcomp->Init.TriggerMode & (COMP_EXTI_IT | COMP_EXTI_EVENT)) != 0UL)
388     {
389       /* Configure EXTI rising edge */
390       if ((hcomp->Init.TriggerMode & COMP_EXTI_RISING) != 0UL)
391       {
392         LL_EXTI_EnableRisingTrig_0_31(exti_line);
393       }
394       else
395       {
396         LL_EXTI_DisableRisingTrig_0_31(exti_line);
397       }
398 
399       /* Configure EXTI falling edge */
400       if ((hcomp->Init.TriggerMode & COMP_EXTI_FALLING) != 0UL)
401       {
402         LL_EXTI_EnableFallingTrig_0_31(exti_line);
403       }
404       else
405       {
406         LL_EXTI_DisableFallingTrig_0_31(exti_line);
407       }
408 
409       /* Clear COMP EXTI pending bit (if any) */
410       LL_EXTI_ClearRisingFlag_0_31(exti_line);
411       LL_EXTI_ClearFallingFlag_0_31(exti_line);
412 
413       /* Configure EXTI event mode */
414       if ((hcomp->Init.TriggerMode & COMP_EXTI_EVENT) != 0UL)
415       {
416         LL_EXTI_EnableEvent_0_31(exti_line);
417       }
418       else
419       {
420         LL_EXTI_DisableEvent_0_31(exti_line);
421       }
422 
423       /* Configure EXTI interrupt mode */
424       if ((hcomp->Init.TriggerMode & COMP_EXTI_IT) != 0UL)
425       {
426         LL_EXTI_EnableIT_0_31(exti_line);
427       }
428       else
429       {
430         LL_EXTI_DisableIT_0_31(exti_line);
431       }
432     }
433     else
434     {
435       /* Disable EXTI event mode */
436       LL_EXTI_DisableEvent_0_31(exti_line);
437 
438       /* Disable EXTI interrupt mode */
439       LL_EXTI_DisableIT_0_31(exti_line);
440     }
441 
442     /* Set HAL COMP handle state */
443     /* Note: Transition from state reset to state ready,                      */
444     /*       otherwise (coming from state ready or busy) no state update.     */
445     if (hcomp->State == HAL_COMP_STATE_RESET)
446     {
447       hcomp->State = HAL_COMP_STATE_READY;
448     }
449   }
450 
451   return status;
452 }
453 
454 /**
455   * @brief  DeInitialize the COMP peripheral.
456   * @note   Deinitialization cannot be performed if the COMP configuration is locked.
457   *         To unlock the configuration, perform a system reset.
458   * @param  hcomp  COMP handle
459   * @retval HAL status
460   */
HAL_COMP_DeInit(COMP_HandleTypeDef * hcomp)461 HAL_StatusTypeDef HAL_COMP_DeInit(COMP_HandleTypeDef *hcomp)
462 {
463   HAL_StatusTypeDef status = HAL_OK;
464 
465   /* Check the COMP handle allocation and lock status */
466   if (hcomp == NULL)
467   {
468     status = HAL_ERROR;
469   }
470   else if (__HAL_COMP_IS_LOCKED(hcomp))
471   {
472     status = HAL_ERROR;
473   }
474   else
475   {
476     /* Check the parameter */
477     assert_param(IS_COMP_ALL_INSTANCE(hcomp->Instance));
478 
479     /* Set COMP_CSR register to reset value */
480     WRITE_REG(hcomp->Instance->CSR, 0x00000000UL);
481 
482 #if (USE_HAL_COMP_REGISTER_CALLBACKS == 1)
483     if (hcomp->MspDeInitCallback == NULL)
484     {
485       hcomp->MspDeInitCallback = HAL_COMP_MspDeInit; /* Legacy weak MspDeInit  */
486     }
487 
488     /* DeInit the low level hardware: GPIO, RCC clock, NVIC */
489     hcomp->MspDeInitCallback(hcomp);
490 #else
491     /* DeInit the low level hardware: GPIO, RCC clock, NVIC */
492     HAL_COMP_MspDeInit(hcomp);
493 #endif /* USE_HAL_COMP_REGISTER_CALLBACKS */
494 
495     /* Set HAL COMP handle state */
496     hcomp->State = HAL_COMP_STATE_RESET;
497 
498     /* Release Lock */
499     __HAL_UNLOCK(hcomp);
500   }
501 
502   return status;
503 }
504 
505 /**
506   * @brief  Initialize the COMP MSP.
507   * @param  hcomp  COMP handle
508   * @retval None
509   */
HAL_COMP_MspInit(COMP_HandleTypeDef * hcomp)510 __weak void HAL_COMP_MspInit(COMP_HandleTypeDef *hcomp)
511 {
512   /* Prevent unused argument(s) compilation warning */
513   UNUSED(hcomp);
514 
515   /* NOTE : This function should not be modified, when the callback is needed,
516             the HAL_COMP_MspInit could be implemented in the user file
517    */
518 }
519 
520 /**
521   * @brief  DeInitialize the COMP MSP.
522   * @param  hcomp  COMP handle
523   * @retval None
524   */
HAL_COMP_MspDeInit(COMP_HandleTypeDef * hcomp)525 __weak void HAL_COMP_MspDeInit(COMP_HandleTypeDef *hcomp)
526 {
527   /* Prevent unused argument(s) compilation warning */
528   UNUSED(hcomp);
529 
530   /* NOTE : This function should not be modified, when the callback is needed,
531             the HAL_COMP_MspDeInit could be implemented in the user file
532    */
533 }
534 
535 #if (USE_HAL_COMP_REGISTER_CALLBACKS == 1)
536 /**
537   * @brief  Register a User COMP Callback
538   *         To be used instead of the weak predefined callback
539   * @param  hcomp Pointer to a COMP_HandleTypeDef structure that contains
540   *                the configuration information for the specified COMP.
541   * @param  CallbackID ID of the callback to be registered
542   *         This parameter can be one of the following values:
543   *          @arg @ref HAL_COMP_TRIGGER_CB_ID Trigger callback ID
544   *          @arg @ref HAL_COMP_MSPINIT_CB_ID MspInit callback ID
545   *          @arg @ref HAL_COMP_MSPDEINIT_CB_ID MspDeInit callback ID
546   * @param  pCallback pointer to the Callback function
547   * @retval HAL status
548   */
HAL_COMP_RegisterCallback(COMP_HandleTypeDef * hcomp,HAL_COMP_CallbackIDTypeDef CallbackID,pCOMP_CallbackTypeDef pCallback)549 HAL_StatusTypeDef HAL_COMP_RegisterCallback(COMP_HandleTypeDef *hcomp, HAL_COMP_CallbackIDTypeDef CallbackID,
550                                             pCOMP_CallbackTypeDef pCallback)
551 {
552   HAL_StatusTypeDef status = HAL_OK;
553 
554   if (pCallback == NULL)
555   {
556     /* Update the error code */
557     hcomp->ErrorCode |= HAL_COMP_ERROR_INVALID_CALLBACK;
558 
559     return HAL_ERROR;
560   }
561 
562   if (HAL_COMP_STATE_READY == hcomp->State)
563   {
564     switch (CallbackID)
565     {
566       case HAL_COMP_TRIGGER_CB_ID :
567         hcomp->TriggerCallback = pCallback;
568         break;
569 
570       case HAL_COMP_MSPINIT_CB_ID :
571         hcomp->MspInitCallback = pCallback;
572         break;
573 
574       case HAL_COMP_MSPDEINIT_CB_ID :
575         hcomp->MspDeInitCallback = pCallback;
576         break;
577 
578       default :
579         /* Update the error code */
580         hcomp->ErrorCode |= HAL_COMP_ERROR_INVALID_CALLBACK;
581 
582         /* Return error status */
583         status = HAL_ERROR;
584         break;
585     }
586   }
587   else if (HAL_COMP_STATE_RESET == hcomp->State)
588   {
589     switch (CallbackID)
590     {
591       case HAL_COMP_MSPINIT_CB_ID :
592         hcomp->MspInitCallback = pCallback;
593         break;
594 
595       case HAL_COMP_MSPDEINIT_CB_ID :
596         hcomp->MspDeInitCallback = pCallback;
597         break;
598 
599       default :
600         /* Update the error code */
601         hcomp->ErrorCode |= HAL_COMP_ERROR_INVALID_CALLBACK;
602 
603         /* Return error status */
604         status = HAL_ERROR;
605         break;
606     }
607   }
608   else
609   {
610     /* Update the error code */
611     hcomp->ErrorCode |= HAL_COMP_ERROR_INVALID_CALLBACK;
612 
613     /* Return error status */
614     status =  HAL_ERROR;
615   }
616 
617   return status;
618 }
619 
620 /**
621   * @brief  Unregister a COMP Callback
622   *         COMP callback is redirected to the weak predefined callback
623   * @param  hcomp Pointer to a COMP_HandleTypeDef structure that contains
624   *                the configuration information for the specified COMP.
625   * @param  CallbackID ID of the callback to be unregistered
626   *         This parameter can be one of the following values:
627   *          @arg @ref HAL_COMP_TRIGGER_CB_ID Trigger callback ID
628   *          @arg @ref HAL_COMP_MSPINIT_CB_ID MspInit callback ID
629   *          @arg @ref HAL_COMP_MSPDEINIT_CB_ID MspDeInit callback ID
630   * @retval HAL status
631   */
HAL_COMP_UnRegisterCallback(COMP_HandleTypeDef * hcomp,HAL_COMP_CallbackIDTypeDef CallbackID)632 HAL_StatusTypeDef HAL_COMP_UnRegisterCallback(COMP_HandleTypeDef *hcomp, HAL_COMP_CallbackIDTypeDef CallbackID)
633 {
634   HAL_StatusTypeDef status = HAL_OK;
635 
636   if (HAL_COMP_STATE_READY == hcomp->State)
637   {
638     switch (CallbackID)
639     {
640       case HAL_COMP_TRIGGER_CB_ID :
641         hcomp->TriggerCallback = HAL_COMP_TriggerCallback;         /* Legacy weak callback */
642         break;
643 
644       case HAL_COMP_MSPINIT_CB_ID :
645         hcomp->MspInitCallback = HAL_COMP_MspInit;                 /* Legacy weak MspInit */
646         break;
647 
648       case HAL_COMP_MSPDEINIT_CB_ID :
649         hcomp->MspDeInitCallback = HAL_COMP_MspDeInit;             /* Legacy weak MspDeInit */
650         break;
651 
652       default :
653         /* Update the error code */
654         hcomp->ErrorCode |= HAL_COMP_ERROR_INVALID_CALLBACK;
655 
656         /* Return error status */
657         status =  HAL_ERROR;
658         break;
659     }
660   }
661   else if (HAL_COMP_STATE_RESET == hcomp->State)
662   {
663     switch (CallbackID)
664     {
665       case HAL_COMP_MSPINIT_CB_ID :
666         hcomp->MspInitCallback = HAL_COMP_MspInit;                 /* Legacy weak MspInit */
667         break;
668 
669       case HAL_COMP_MSPDEINIT_CB_ID :
670         hcomp->MspDeInitCallback = HAL_COMP_MspDeInit;             /* Legacy weak MspDeInit */
671         break;
672 
673       default :
674         /* Update the error code */
675         hcomp->ErrorCode |= HAL_COMP_ERROR_INVALID_CALLBACK;
676 
677         /* Return error status */
678         status =  HAL_ERROR;
679         break;
680     }
681   }
682   else
683   {
684     /* Update the error code */
685     hcomp->ErrorCode |= HAL_COMP_ERROR_INVALID_CALLBACK;
686 
687     /* Return error status */
688     status =  HAL_ERROR;
689   }
690 
691   return status;
692 }
693 
694 #endif /* USE_HAL_COMP_REGISTER_CALLBACKS */
695 
696 /**
697   * @}
698   */
699 
700 /** @defgroup COMP_Exported_Functions_Group2 Start-Stop operation functions
701   *  @brief   Start-Stop operation functions.
702   *
703 @verbatim
704  ===============================================================================
705                       ##### IO operation functions #####
706  ===============================================================================
707     [..]  This section provides functions allowing to:
708       (+) Start a comparator instance.
709       (+) Stop a comparator instance.
710 
711 @endverbatim
712   * @{
713   */
714 
715 /**
716   * @brief  Start the comparator.
717   * @param  hcomp  COMP handle
718   * @retval HAL status
719   */
HAL_COMP_Start(COMP_HandleTypeDef * hcomp)720 HAL_StatusTypeDef HAL_COMP_Start(COMP_HandleTypeDef *hcomp)
721 {
722   __IO uint32_t wait_loop_index = 0UL;
723   HAL_StatusTypeDef status = HAL_OK;
724 
725   /* Check the COMP handle allocation and lock status */
726   if (hcomp == NULL)
727   {
728     status = HAL_ERROR;
729   }
730   else if (__HAL_COMP_IS_LOCKED(hcomp))
731   {
732     status = HAL_ERROR;
733   }
734   else
735   {
736     /* Check the parameter */
737     assert_param(IS_COMP_ALL_INSTANCE(hcomp->Instance));
738 
739     if (hcomp->State == HAL_COMP_STATE_READY)
740     {
741       /* Enable the selected comparator */
742       SET_BIT(hcomp->Instance->CSR, COMP_CSR_EN);
743 
744       /* Set HAL COMP handle state */
745       hcomp->State = HAL_COMP_STATE_BUSY;
746 
747       /* Delay for COMP startup time */
748       /* Wait loop initialization and execution */
749       /* Note: Variable divided by 2 to compensate partially              */
750       /*       CPU processing cycles, scaling in us split to not          */
751       /*       exceed 32 bits register capacity and handle low frequency. */
752       wait_loop_index = ((COMP_DELAY_STARTUP_US / 10UL) * ((SystemCoreClock / (100000UL * 2UL)) + 1UL));
753       while (wait_loop_index != 0UL)
754       {
755         wait_loop_index--;
756       }
757     }
758     else
759     {
760       status = HAL_ERROR;
761     }
762   }
763 
764   return status;
765 }
766 
767 /**
768   * @brief  Stop the comparator.
769   * @param  hcomp  COMP handle
770   * @retval HAL status
771   */
HAL_COMP_Stop(COMP_HandleTypeDef * hcomp)772 HAL_StatusTypeDef HAL_COMP_Stop(COMP_HandleTypeDef *hcomp)
773 {
774   HAL_StatusTypeDef status = HAL_OK;
775 
776   /* Check the COMP handle allocation and lock status */
777   if (hcomp == NULL)
778   {
779     status = HAL_ERROR;
780   }
781   else if (__HAL_COMP_IS_LOCKED(hcomp))
782   {
783     status = HAL_ERROR;
784   }
785   else
786   {
787     /* Check the parameter */
788     assert_param(IS_COMP_ALL_INSTANCE(hcomp->Instance));
789 
790     /* Check compliant states: HAL_COMP_STATE_READY or HAL_COMP_STATE_BUSY    */
791     /* (all states except HAL_COMP_STATE_RESET and except locked status.      */
792     if (hcomp->State != HAL_COMP_STATE_RESET)
793     {
794       /* Disable the selected comparator */
795       CLEAR_BIT(hcomp->Instance->CSR, COMP_CSR_EN);
796 
797       /* Set HAL COMP handle state */
798       hcomp->State = HAL_COMP_STATE_READY;
799     }
800     else
801     {
802       status = HAL_ERROR;
803     }
804   }
805 
806   return status;
807 }
808 
809 /**
810   * @brief  Comparator IRQ handler.
811   * @param  hcomp  COMP handle
812   * @retval None
813   */
HAL_COMP_IRQHandler(COMP_HandleTypeDef * hcomp)814 void HAL_COMP_IRQHandler(COMP_HandleTypeDef *hcomp)
815 {
816   /* Get the EXTI line corresponding to the selected COMP instance */
817   uint32_t exti_line = COMP_GET_EXTI_LINE(hcomp->Instance);
818   uint32_t comparator_window_mode;
819 
820   comparator_window_mode = READ_BIT(COMP12_COMMON->CSR_ODD, COMP_CSR_WINMODE);
821   comparator_window_mode |= READ_BIT(COMP12_COMMON->CSR_EVEN, COMP_CSR_WINMODE);
822 
823   /* Check COMP EXTI flag */
824   if (LL_EXTI_IsActiveRisingFlag_0_31(exti_line) != 0UL)
825   {
826     /* Check whether comparator is in independent or window mode */
827     if (comparator_window_mode != 0UL)
828     {
829       /* Clear COMP EXTI line pending bit of the pair of comparators          */
830       /* in window mode.                                                      */
831       /* Note: Pair of comparators in window mode can both trig IRQ when      */
832       /*       input voltage is changing from "out of window" area            */
833       /*       (low or high ) to the other "out of window" area (high or low).*/
834       /*       Both flags must be cleared to call comparator trigger          */
835       /*       callback is called once.                                       */
836       LL_EXTI_ClearRisingFlag_0_31((COMP_EXTI_LINE_COMP1 | COMP_EXTI_LINE_COMP2));
837     }
838     else
839     {
840       /* Clear COMP EXTI line pending bit */
841       LL_EXTI_ClearRisingFlag_0_31(exti_line);
842     }
843 
844     /* COMP trigger user callback */
845 #if (USE_HAL_COMP_REGISTER_CALLBACKS == 1)
846     hcomp->TriggerCallback(hcomp);
847 #else
848     HAL_COMP_TriggerCallback(hcomp);
849 #endif /* USE_HAL_COMP_REGISTER_CALLBACKS */
850   }
851   else if (LL_EXTI_IsActiveFallingFlag_0_31(exti_line) != 0UL)
852   {
853     /* Check whether comparator is in independent or window mode */
854     if (comparator_window_mode != 0UL)
855     {
856       /* Clear COMP EXTI line pending bit of the pair of comparators          */
857       /* in window mode.                                                      */
858       /* Note: Pair of comparators in window mode can both trig IRQ when      */
859       /*       input voltage is changing from "out of window" area            */
860       /*       (low or high ) to the other "out of window" area (high or low).*/
861       /*       Both flags must be cleared to call comparator trigger          */
862       /*       callback is called once.                                       */
863       LL_EXTI_ClearFallingFlag_0_31((COMP_EXTI_LINE_COMP1 | COMP_EXTI_LINE_COMP2));
864     }
865     else
866     {
867       /* Clear COMP EXTI line pending bit */
868       LL_EXTI_ClearFallingFlag_0_31(exti_line);
869     }
870 
871     /* COMP trigger callback */
872 #if (USE_HAL_COMP_REGISTER_CALLBACKS == 1)
873     hcomp->TriggerCallback(hcomp);
874 #else
875     HAL_COMP_TriggerCallback(hcomp);
876 #endif /* USE_HAL_COMP_REGISTER_CALLBACKS */
877   }
878   else
879   {
880     /* nothing to do */
881   }
882 }
883 
884 /**
885   * @}
886   */
887 
888 /** @defgroup COMP_Exported_Functions_Group3 Peripheral Control functions
889   *  @brief   Management functions.
890   *
891 @verbatim
892  ===============================================================================
893                       ##### Peripheral Control functions #####
894  ===============================================================================
895     [..]
896     This subsection provides a set of functions allowing to control the comparators.
897 
898 @endverbatim
899   * @{
900   */
901 
902 /**
903   * @brief  Lock the selected comparator configuration.
904   * @note   A system reset is required to unlock the comparator configuration.
905   * @note   Locking the comparator from reset state is possible
906   *         if __HAL_RCC_SYSCFG_CLK_ENABLE() is being called before.
907   * @param  hcomp  COMP handle
908   * @retval HAL status
909   */
HAL_COMP_Lock(COMP_HandleTypeDef * hcomp)910 HAL_StatusTypeDef HAL_COMP_Lock(COMP_HandleTypeDef *hcomp)
911 {
912   HAL_StatusTypeDef status = HAL_OK;
913 
914   /* Check the COMP handle allocation and lock status */
915   if (hcomp == NULL)
916   {
917     status = HAL_ERROR;
918   }
919   else if (__HAL_COMP_IS_LOCKED(hcomp))
920   {
921     status = HAL_ERROR;
922   }
923   else
924   {
925     /* Check the parameter */
926     assert_param(IS_COMP_ALL_INSTANCE(hcomp->Instance));
927 
928     /* Set HAL COMP handle state */
929     switch (hcomp->State)
930     {
931       case HAL_COMP_STATE_RESET:
932         hcomp->State = HAL_COMP_STATE_RESET_LOCKED;
933         break;
934       case HAL_COMP_STATE_READY:
935         hcomp->State = HAL_COMP_STATE_READY_LOCKED;
936         break;
937       default: /* HAL_COMP_STATE_BUSY */
938         hcomp->State = HAL_COMP_STATE_BUSY_LOCKED;
939         break;
940     }
941 
942     /* Set the lock bit corresponding to selected comparator */
943     __HAL_COMP_LOCK(hcomp);
944   }
945 
946   return status;
947 }
948 
949 /**
950   * @brief  Return the output level (high or low) of the selected comparator.
951   *         The output level depends on the selected polarity.
952   *         If the polarity is not inverted:
953   *           - Comparator output is low when the input plus is at a lower
954   *             voltage than the input minus
955   *           - Comparator output is high when the input plus is at a higher
956   *             voltage than the input minus
957   *         If the polarity is inverted:
958   *           - Comparator output is high when the input plus is at a lower
959   *             voltage than the input minus
960   *           - Comparator output is low when the input plus is at a higher
961   *             voltage than the input minus
962   * @param  hcomp  COMP handle
963   * @retval Returns the selected comparator output level:
964   *         @arg COMP_OUTPUT_LEVEL_LOW
965   *         @arg COMP_OUTPUT_LEVEL_HIGH
966   *
967   */
HAL_COMP_GetOutputLevel(const COMP_HandleTypeDef * hcomp)968 uint32_t HAL_COMP_GetOutputLevel(const COMP_HandleTypeDef *hcomp)
969 {
970   /* Check the parameter */
971   assert_param(IS_COMP_ALL_INSTANCE(hcomp->Instance));
972 
973   return (uint32_t)(READ_BIT(hcomp->Instance->CSR, COMP_CSR_VALUE)
974                     >> COMP_OUTPUT_LEVEL_BITOFFSET_POS);
975 }
976 
977 /**
978   * @brief  Comparator trigger callback.
979   * @param  hcomp  COMP handle
980   * @retval None
981   */
HAL_COMP_TriggerCallback(COMP_HandleTypeDef * hcomp)982 __weak void HAL_COMP_TriggerCallback(COMP_HandleTypeDef *hcomp)
983 {
984   /* Prevent unused argument(s) compilation warning */
985   UNUSED(hcomp);
986 
987   /* NOTE : This function should not be modified, when the callback is needed,
988             the HAL_COMP_TriggerCallback should be implemented in the user file
989    */
990 }
991 
992 
993 /**
994   * @}
995   */
996 
997 /** @defgroup COMP_Exported_Functions_Group4 Peripheral State functions
998   *  @brief   Peripheral State functions.
999   *
1000 @verbatim
1001  ===============================================================================
1002                       ##### Peripheral State functions #####
1003  ===============================================================================
1004     [..]
1005     This subsection permit to get in run-time the status of the peripheral.
1006 
1007 @endverbatim
1008   * @{
1009   */
1010 
1011 /**
1012   * @brief  Return the COMP handle state.
1013   * @param  hcomp  COMP handle
1014   * @retval HAL state
1015   */
HAL_COMP_GetState(const COMP_HandleTypeDef * hcomp)1016 HAL_COMP_StateTypeDef HAL_COMP_GetState(const COMP_HandleTypeDef *hcomp)
1017 {
1018   /* Check the COMP handle allocation */
1019   if (hcomp == NULL)
1020   {
1021     return HAL_COMP_STATE_RESET;
1022   }
1023 
1024   /* Check the parameter */
1025   assert_param(IS_COMP_ALL_INSTANCE(hcomp->Instance));
1026 
1027   /* Return HAL COMP handle state */
1028   return hcomp->State;
1029 }
1030 
1031 /**
1032   * @brief  Return the COMP error code.
1033   * @param hcomp COMP handle
1034   * @retval COMP error code
1035   */
HAL_COMP_GetError(const COMP_HandleTypeDef * hcomp)1036 uint32_t HAL_COMP_GetError(const COMP_HandleTypeDef *hcomp)
1037 {
1038   /* Check the parameters */
1039   assert_param(IS_COMP_ALL_INSTANCE(hcomp->Instance));
1040 
1041   return hcomp->ErrorCode;
1042 }
1043 
1044 /**
1045   * @}
1046   */
1047 
1048 /**
1049   * @}
1050   */
1051 
1052 /**
1053   * @}
1054   */
1055 
1056 #endif /* COMP1 || COMP2 */
1057 
1058 #endif /* HAL_COMP_MODULE_ENABLED */
1059 
1060 /**
1061   * @}
1062   */
1063