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