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