1 /**
2   ******************************************************************************
3   * @file    stm32g0xx_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) 2018 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 STM32G0xx 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 STM32G0xx 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 
159 /* Includes ------------------------------------------------------------------*/
160 #include "stm32g0xx_hal.h"
161 
162 /** @addtogroup STM32G0xx_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 #if defined(COMP3)
238   __IO uint32_t * comp_common_odd;
239   __IO uint32_t * comp_common_even;
240 #endif /* COMP3 */
241 
242   /* Check the COMP handle allocation and lock status */
243   if(hcomp == NULL)
244   {
245     status = HAL_ERROR;
246   }
247   else if(__HAL_COMP_IS_LOCKED(hcomp))
248   {
249     status = HAL_ERROR;
250   }
251   else
252   {
253     /* Check the parameters */
254     assert_param(IS_COMP_ALL_INSTANCE(hcomp->Instance));
255     assert_param(IS_COMP_INPUT_PLUS(hcomp->Instance, hcomp->Init.InputPlus));
256     assert_param(IS_COMP_INPUT_MINUS(hcomp->Instance, hcomp->Init.InputMinus));
257     assert_param(IS_COMP_OUTPUTPOL(hcomp->Init.OutputPol));
258     assert_param(IS_COMP_POWERMODE(hcomp->Init.Mode));
259     assert_param(IS_COMP_HYSTERESIS(hcomp->Init.Hysteresis));
260     assert_param(IS_COMP_BLANKINGSRC_INSTANCE(hcomp->Instance, hcomp->Init.BlankingSrce));
261     assert_param(IS_COMP_TRIGGERMODE(hcomp->Init.TriggerMode));
262     assert_param(IS_COMP_WINDOWMODE(hcomp->Instance, hcomp->Init.WindowMode));
263     if(hcomp->Init.WindowMode != COMP_WINDOWMODE_DISABLE)
264     {
265       assert_param(IS_COMP_WINDOWOUTPUT(hcomp->Init.WindowOutput));
266     }
267 
268     if(hcomp->State == HAL_COMP_STATE_RESET)
269     {
270       /* Allocate lock resource and initialize it */
271       hcomp->Lock = HAL_UNLOCKED;
272 
273       /* Set COMP error code to none */
274       COMP_CLEAR_ERRORCODE(hcomp);
275 
276 
277 #if (USE_HAL_COMP_REGISTER_CALLBACKS == 1)
278       /* Init the COMP Callback settings */
279       hcomp->TriggerCallback = HAL_COMP_TriggerCallback; /* Legacy weak callback */
280 
281       if (hcomp->MspInitCallback == NULL)
282       {
283         hcomp->MspInitCallback = HAL_COMP_MspInit; /* Legacy weak MspInit  */
284       }
285 
286       /* Init the low level hardware */
287       /* Note: Internal control clock of the comparators must                 */
288       /*       be enabled in "HAL_COMP_MspInit()"                             */
289       /*       using "__HAL_RCC_SYSCFG_CLK_ENABLE()".                         */
290       hcomp->MspInitCallback(hcomp);
291 #else
292       /* Init the low level hardware */
293       /* Note: Internal control clock of the comparators must                 */
294       /*       be enabled in "HAL_COMP_MspInit()"                             */
295       /*       using "__HAL_RCC_SYSCFG_CLK_ENABLE()".                         */
296       HAL_COMP_MspInit(hcomp);
297 #endif /* USE_HAL_COMP_REGISTER_CALLBACKS */
298     }
299 
300     /* Memorize voltage scaler state before initialization */
301     comp_voltage_scaler_initialized = READ_BIT(hcomp->Instance->CSR, (COMP_CSR_INMSEL_1 | COMP_CSR_INMSEL_0));
302 
303     /* Set COMP parameters */
304     tmp_csr = (  hcomp->Init.InputMinus
305                | hcomp->Init.InputPlus
306                | hcomp->Init.BlankingSrce
307                | hcomp->Init.Hysteresis
308                | hcomp->Init.OutputPol
309                | hcomp->Init.Mode
310               );
311 
312     /* Set parameters in COMP register */
313     /* Note: Update all bits except read-only, lock and enable bits */
314     MODIFY_REG(hcomp->Instance->CSR,
315                COMP_CSR_PWRMODE  | COMP_CSR_INMSEL   | COMP_CSR_INPSEL  |
316                COMP_CSR_WINMODE  | COMP_CSR_POLARITY | COMP_CSR_HYST    |
317                COMP_CSR_BLANKING                                         ,
318                tmp_csr
319               );
320 
321     /* Set window mode */
322     /* Note: Window mode bit is located into 1 out of the 2 pairs of COMP     */
323     /*       instances. Therefore, this function can update another COMP      */
324     /*       instance that the one currently selected.                        */
325 #if defined(COMP3)
326     if(hcomp->Instance == COMP3)
327     {
328       /* Note: Exception for STM32G0 devices featuring ADC3 instance: in common   */
329       /*       group of COMP2 and COMP3, instances odd and even are inverted.     */
330       /*       Perform switch of parameter selected.                              */
331       comp_common_odd = &(COMP23_COMMON->CSR_EVEN);
332       comp_common_even = &(COMP23_COMMON->CSR_ODD);
333     }
334     else
335     {
336       comp_common_odd = &(COMP12_COMMON->CSR_ODD);
337       comp_common_even = &(COMP12_COMMON->CSR_EVEN);
338     }
339 
340     if(hcomp->Init.WindowMode == COMP_WINDOWMODE_COMP1_INPUT_PLUS_COMMON)
341     {
342       CLEAR_BIT(*comp_common_odd, COMP_CSR_WINMODE);
343       SET_BIT(*comp_common_even, COMP_CSR_WINMODE);
344     }
345     else if(hcomp->Init.WindowMode == COMP_WINDOWMODE_COMP2_INPUT_PLUS_COMMON)
346     {
347       SET_BIT(*comp_common_odd, COMP_CSR_WINMODE);
348       CLEAR_BIT(*comp_common_even, COMP_CSR_WINMODE);
349     }
350     else
351     {
352       CLEAR_BIT(*comp_common_odd, COMP_CSR_WINMODE);
353       CLEAR_BIT(*comp_common_even, COMP_CSR_WINMODE);
354     }
355 
356     /* Set window mode output */
357     /* Note: Window mode mode output can also be used when window mode        */
358     /*       is disabled, to use comparators in independent mode with their   */
359     /*       output connected through exclusive-or circuitry.                 */
360     switch (hcomp->Init.WindowOutput)
361     {
362       case COMP_WINDOWOUTPUT_COMP1: /* idem COMP_WINDOWOUTPUT_COMP3 (same literal value) */
363         SET_BIT(*comp_common_odd, COMP_CSR_WINOUT);
364         CLEAR_BIT(*comp_common_even, COMP_CSR_WINOUT);
365         break;
366 
367       case COMP_WINDOWOUTPUT_COMP2:
368         CLEAR_BIT(*comp_common_odd, COMP_CSR_WINOUT);
369         SET_BIT(*comp_common_even, COMP_CSR_WINOUT);
370         break;
371 
372       case COMP_WINDOWOUTPUT_BOTH:
373         SET_BIT(*comp_common_odd, COMP_CSR_WINOUT);
374         SET_BIT(*comp_common_even, COMP_CSR_WINOUT);
375         break;
376 
377       default: /* COMP_WINDOWOUTPUT_EACH_COMP */
378         CLEAR_BIT(*comp_common_odd, COMP_CSR_WINOUT);
379         CLEAR_BIT(*comp_common_even, COMP_CSR_WINOUT);
380         break;
381     }
382 #else
383     if(hcomp->Init.WindowMode == COMP_WINDOWMODE_COMP1_INPUT_PLUS_COMMON)
384     {
385       CLEAR_BIT(COMP12_COMMON->CSR_ODD, COMP_CSR_WINMODE);
386       SET_BIT(COMP12_COMMON->CSR_EVEN, COMP_CSR_WINMODE);
387     }
388     else if(hcomp->Init.WindowMode == COMP_WINDOWMODE_COMP2_INPUT_PLUS_COMMON)
389     {
390       SET_BIT(COMP12_COMMON->CSR_ODD, COMP_CSR_WINMODE);
391       CLEAR_BIT(COMP12_COMMON->CSR_EVEN, COMP_CSR_WINMODE);
392     }
393     else
394     {
395       CLEAR_BIT(COMP12_COMMON->CSR_ODD, COMP_CSR_WINMODE);
396       CLEAR_BIT(COMP12_COMMON->CSR_EVEN, COMP_CSR_WINMODE);
397     }
398 
399     /* Set window mode output */
400     /* Note: Window mode mode output can also be used when window mode        */
401     /*       is disabled, to use comparators in independent mode with their   */
402     /*       output connected through exclusive-or circuitry.                 */
403     switch (hcomp->Init.WindowOutput)
404     {
405       case COMP_WINDOWOUTPUT_COMP1:
406         SET_BIT(COMP12_COMMON->CSR_ODD, COMP_CSR_WINOUT);
407         CLEAR_BIT(COMP12_COMMON->CSR_EVEN, COMP_CSR_WINOUT);
408         break;
409 
410       case COMP_WINDOWOUTPUT_COMP2:
411         CLEAR_BIT(COMP12_COMMON->CSR_ODD, COMP_CSR_WINOUT);
412         SET_BIT(COMP12_COMMON->CSR_EVEN, COMP_CSR_WINOUT);
413         break;
414 
415       case COMP_WINDOWOUTPUT_BOTH:
416         SET_BIT(COMP12_COMMON->CSR_ODD, COMP_CSR_WINOUT);
417         SET_BIT(COMP12_COMMON->CSR_EVEN, COMP_CSR_WINOUT);
418         break;
419 
420       default: /* COMP_WINDOWOUTPUT_EACH_COMP */
421         CLEAR_BIT(COMP12_COMMON->CSR_ODD, COMP_CSR_WINOUT);
422         CLEAR_BIT(COMP12_COMMON->CSR_EVEN, COMP_CSR_WINOUT);
423         break;
424     }
425 #endif /* COMP3 */
426 
427     /* Delay for COMP scaler bridge voltage stabilization */
428     /* Apply the delay if voltage scaler bridge is required and not already enabled */
429     if ((READ_BIT(hcomp->Instance->CSR, (COMP_CSR_INMSEL_1 | COMP_CSR_INMSEL_0)) != 0UL) &&
430         (comp_voltage_scaler_initialized == 0UL)               )
431     {
432       /* Wait loop initialization and execution */
433       /* Note: Variable divided by 2 to compensate partially              */
434       /*       CPU processing cycles, scaling in us split to not          */
435       /*       exceed 32 bits register capacity and handle low frequency. */
436       wait_loop_index = ((COMP_DELAY_VOLTAGE_SCALER_STAB_US / 10UL) * ((SystemCoreClock / (100000UL * 2UL)) + 1UL));
437       while(wait_loop_index != 0UL)
438       {
439         wait_loop_index--;
440       }
441     }
442 
443     /* Get the EXTI line corresponding to the selected COMP instance */
444     exti_line = COMP_GET_EXTI_LINE(hcomp->Instance);
445 
446     /* Manage EXTI settings */
447     if((hcomp->Init.TriggerMode & (COMP_EXTI_IT | COMP_EXTI_EVENT)) != 0UL)
448     {
449       /* Configure EXTI rising edge */
450       if((hcomp->Init.TriggerMode & COMP_EXTI_RISING) != 0UL)
451       {
452         LL_EXTI_EnableRisingTrig_0_31(exti_line);
453       }
454       else
455       {
456         LL_EXTI_DisableRisingTrig_0_31(exti_line);
457       }
458 
459       /* Configure EXTI falling edge */
460       if((hcomp->Init.TriggerMode & COMP_EXTI_FALLING) != 0UL)
461       {
462         LL_EXTI_EnableFallingTrig_0_31(exti_line);
463       }
464       else
465       {
466         LL_EXTI_DisableFallingTrig_0_31(exti_line);
467       }
468 
469       /* Clear COMP EXTI pending bit (if any) */
470       LL_EXTI_ClearRisingFlag_0_31(exti_line);
471       LL_EXTI_ClearFallingFlag_0_31(exti_line);
472 
473       /* Configure EXTI event mode */
474       if((hcomp->Init.TriggerMode & COMP_EXTI_EVENT) != 0UL)
475       {
476         LL_EXTI_EnableEvent_0_31(exti_line);
477       }
478       else
479       {
480         LL_EXTI_DisableEvent_0_31(exti_line);
481       }
482 
483       /* Configure EXTI interrupt mode */
484       if((hcomp->Init.TriggerMode & COMP_EXTI_IT) != 0UL)
485       {
486         LL_EXTI_EnableIT_0_31(exti_line);
487       }
488       else
489       {
490         LL_EXTI_DisableIT_0_31(exti_line);
491       }
492     }
493     else
494     {
495       /* Disable EXTI event mode */
496       LL_EXTI_DisableEvent_0_31(exti_line);
497 
498       /* Disable EXTI interrupt mode */
499       LL_EXTI_DisableIT_0_31(exti_line);
500     }
501 
502     /* Set HAL COMP handle state */
503     /* Note: Transition from state reset to state ready,                      */
504     /*       otherwise (coming from state ready or busy) no state update.     */
505     if (hcomp->State == HAL_COMP_STATE_RESET)
506     {
507       hcomp->State = HAL_COMP_STATE_READY;
508     }
509   }
510 
511   return status;
512 }
513 
514 /**
515   * @brief  DeInitialize the COMP peripheral.
516   * @note   Deinitialization cannot be performed if the COMP configuration is locked.
517   *         To unlock the configuration, perform a system reset.
518   * @param  hcomp  COMP handle
519   * @retval HAL status
520   */
HAL_COMP_DeInit(COMP_HandleTypeDef * hcomp)521 HAL_StatusTypeDef HAL_COMP_DeInit(COMP_HandleTypeDef *hcomp)
522 {
523   HAL_StatusTypeDef status = HAL_OK;
524 
525   /* Check the COMP handle allocation and lock status */
526   if(hcomp == NULL)
527   {
528     status = HAL_ERROR;
529   }
530   else if(__HAL_COMP_IS_LOCKED(hcomp))
531   {
532     status = HAL_ERROR;
533   }
534   else
535   {
536     /* Check the parameter */
537     assert_param(IS_COMP_ALL_INSTANCE(hcomp->Instance));
538 
539     /* Set COMP_CSR register to reset value */
540     WRITE_REG(hcomp->Instance->CSR, 0x00000000UL);
541 
542 #if (USE_HAL_COMP_REGISTER_CALLBACKS == 1)
543     if (hcomp->MspDeInitCallback == NULL)
544     {
545       hcomp->MspDeInitCallback = HAL_COMP_MspDeInit; /* Legacy weak MspDeInit  */
546     }
547 
548     /* DeInit the low level hardware: GPIO, RCC clock, NVIC */
549     hcomp->MspDeInitCallback(hcomp);
550 #else
551     /* DeInit the low level hardware: GPIO, RCC clock, NVIC */
552     HAL_COMP_MspDeInit(hcomp);
553 #endif /* USE_HAL_COMP_REGISTER_CALLBACKS */
554 
555     /* Set HAL COMP handle state */
556     hcomp->State = HAL_COMP_STATE_RESET;
557 
558     /* Release Lock */
559     __HAL_UNLOCK(hcomp);
560   }
561 
562   return status;
563 }
564 
565 /**
566   * @brief  Initialize the COMP MSP.
567   * @param  hcomp  COMP handle
568   * @retval None
569   */
HAL_COMP_MspInit(COMP_HandleTypeDef * hcomp)570 __weak void HAL_COMP_MspInit(COMP_HandleTypeDef *hcomp)
571 {
572   /* Prevent unused argument(s) compilation warning */
573   UNUSED(hcomp);
574 
575   /* NOTE : This function should not be modified, when the callback is needed,
576             the HAL_COMP_MspInit could be implemented in the user file
577    */
578 }
579 
580 /**
581   * @brief  DeInitialize the COMP MSP.
582   * @param  hcomp  COMP handle
583   * @retval None
584   */
HAL_COMP_MspDeInit(COMP_HandleTypeDef * hcomp)585 __weak void HAL_COMP_MspDeInit(COMP_HandleTypeDef *hcomp)
586 {
587   /* Prevent unused argument(s) compilation warning */
588   UNUSED(hcomp);
589 
590   /* NOTE : This function should not be modified, when the callback is needed,
591             the HAL_COMP_MspDeInit could be implemented in the user file
592    */
593 }
594 
595 #if (USE_HAL_COMP_REGISTER_CALLBACKS == 1)
596 /**
597   * @brief  Register a User COMP Callback
598   *         To be used instead of the weak predefined callback
599   * @param  hcomp Pointer to a COMP_HandleTypeDef structure that contains
600   *                the configuration information for the specified COMP.
601   * @param  CallbackID ID of the callback to be registered
602   *         This parameter can be one of the following values:
603   *          @arg @ref HAL_COMP_TRIGGER_CB_ID Trigger callback ID
604   *          @arg @ref HAL_COMP_MSPINIT_CB_ID MspInit callback ID
605   *          @arg @ref HAL_COMP_MSPDEINIT_CB_ID MspDeInit callback ID
606   * @param  pCallback pointer to the Callback function
607   * @retval HAL status
608   */
HAL_COMP_RegisterCallback(COMP_HandleTypeDef * hcomp,HAL_COMP_CallbackIDTypeDef CallbackID,pCOMP_CallbackTypeDef pCallback)609 HAL_StatusTypeDef HAL_COMP_RegisterCallback(COMP_HandleTypeDef *hcomp, HAL_COMP_CallbackIDTypeDef CallbackID, pCOMP_CallbackTypeDef pCallback)
610 {
611   HAL_StatusTypeDef status = HAL_OK;
612 
613   if (pCallback == NULL)
614   {
615     /* Update the error code */
616     hcomp->ErrorCode |= HAL_COMP_ERROR_INVALID_CALLBACK;
617 
618     return HAL_ERROR;
619   }
620 
621   if (HAL_COMP_STATE_READY == hcomp->State)
622   {
623     switch (CallbackID)
624     {
625       case HAL_COMP_TRIGGER_CB_ID :
626         hcomp->TriggerCallback = pCallback;
627         break;
628 
629       case HAL_COMP_MSPINIT_CB_ID :
630         hcomp->MspInitCallback = pCallback;
631         break;
632 
633       case HAL_COMP_MSPDEINIT_CB_ID :
634         hcomp->MspDeInitCallback = pCallback;
635         break;
636 
637       default :
638         /* Update the error code */
639         hcomp->ErrorCode |= HAL_COMP_ERROR_INVALID_CALLBACK;
640 
641         /* Return error status */
642         status = HAL_ERROR;
643         break;
644     }
645   }
646   else if (HAL_COMP_STATE_RESET == hcomp->State)
647   {
648     switch (CallbackID)
649     {
650       case HAL_COMP_MSPINIT_CB_ID :
651         hcomp->MspInitCallback = pCallback;
652         break;
653 
654       case HAL_COMP_MSPDEINIT_CB_ID :
655         hcomp->MspDeInitCallback = pCallback;
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
668   {
669     /* Update the error code */
670     hcomp->ErrorCode |= HAL_COMP_ERROR_INVALID_CALLBACK;
671 
672     /* Return error status */
673     status =  HAL_ERROR;
674   }
675 
676   return status;
677 }
678 
679 /**
680   * @brief  Unregister a COMP Callback
681   *         COMP callback is redirected to the weak predefined callback
682   * @param  hcomp Pointer to a COMP_HandleTypeDef structure that contains
683   *                the configuration information for the specified COMP.
684   * @param  CallbackID ID of the callback to be unregistered
685   *         This parameter can be one of the following values:
686   *          @arg @ref HAL_COMP_TRIGGER_CB_ID Trigger callback ID
687   *          @arg @ref HAL_COMP_MSPINIT_CB_ID MspInit callback ID
688   *          @arg @ref HAL_COMP_MSPDEINIT_CB_ID MspDeInit callback ID
689   * @retval HAL status
690   */
HAL_COMP_UnRegisterCallback(COMP_HandleTypeDef * hcomp,HAL_COMP_CallbackIDTypeDef CallbackID)691 HAL_StatusTypeDef HAL_COMP_UnRegisterCallback(COMP_HandleTypeDef *hcomp, HAL_COMP_CallbackIDTypeDef CallbackID)
692 {
693   HAL_StatusTypeDef status = HAL_OK;
694 
695   if (HAL_COMP_STATE_READY == hcomp->State)
696   {
697     switch (CallbackID)
698     {
699       case HAL_COMP_TRIGGER_CB_ID :
700         hcomp->TriggerCallback = HAL_COMP_TriggerCallback;         /* Legacy weak callback */
701         break;
702 
703       case HAL_COMP_MSPINIT_CB_ID :
704         hcomp->MspInitCallback = HAL_COMP_MspInit;                 /* Legacy weak MspInit */
705         break;
706 
707       case HAL_COMP_MSPDEINIT_CB_ID :
708         hcomp->MspDeInitCallback = HAL_COMP_MspDeInit;             /* Legacy weak MspDeInit */
709         break;
710 
711       default :
712         /* Update the error code */
713         hcomp->ErrorCode |= HAL_COMP_ERROR_INVALID_CALLBACK;
714 
715         /* Return error status */
716         status =  HAL_ERROR;
717         break;
718     }
719   }
720   else if (HAL_COMP_STATE_RESET == hcomp->State)
721   {
722     switch (CallbackID)
723     {
724       case HAL_COMP_MSPINIT_CB_ID :
725         hcomp->MspInitCallback = HAL_COMP_MspInit;                 /* Legacy weak MspInit */
726         break;
727 
728       case HAL_COMP_MSPDEINIT_CB_ID :
729         hcomp->MspDeInitCallback = HAL_COMP_MspDeInit;             /* Legacy weak MspDeInit */
730         break;
731 
732       default :
733         /* Update the error code */
734         hcomp->ErrorCode |= HAL_COMP_ERROR_INVALID_CALLBACK;
735 
736         /* Return error status */
737         status =  HAL_ERROR;
738         break;
739     }
740   }
741   else
742   {
743     /* Update the error code */
744     hcomp->ErrorCode |= HAL_COMP_ERROR_INVALID_CALLBACK;
745 
746     /* Return error status */
747     status =  HAL_ERROR;
748   }
749 
750   return status;
751 }
752 
753 #endif /* USE_HAL_COMP_REGISTER_CALLBACKS */
754 
755 /**
756   * @}
757   */
758 
759 /** @defgroup COMP_Exported_Functions_Group2 Start-Stop operation functions
760   *  @brief   Start-Stop operation functions.
761   *
762 @verbatim
763  ===============================================================================
764                       ##### IO operation functions #####
765  ===============================================================================
766     [..]  This section provides functions allowing to:
767       (+) Start a comparator instance.
768       (+) Stop a comparator instance.
769 
770 @endverbatim
771   * @{
772   */
773 
774 /**
775   * @brief  Start the comparator.
776   * @param  hcomp  COMP handle
777   * @retval HAL status
778   */
HAL_COMP_Start(COMP_HandleTypeDef * hcomp)779 HAL_StatusTypeDef HAL_COMP_Start(COMP_HandleTypeDef *hcomp)
780 {
781   __IO uint32_t wait_loop_index = 0UL;
782   HAL_StatusTypeDef status = HAL_OK;
783 
784   /* Check the COMP handle allocation and lock status */
785   if(hcomp == NULL)
786   {
787     status = HAL_ERROR;
788   }
789   else if(__HAL_COMP_IS_LOCKED(hcomp))
790   {
791     status = HAL_ERROR;
792   }
793   else
794   {
795     /* Check the parameter */
796     assert_param(IS_COMP_ALL_INSTANCE(hcomp->Instance));
797 
798     if(hcomp->State == HAL_COMP_STATE_READY)
799     {
800       /* Enable the selected comparator */
801       SET_BIT(hcomp->Instance->CSR, COMP_CSR_EN);
802 
803       /* Set HAL COMP handle state */
804       hcomp->State = HAL_COMP_STATE_BUSY;
805 
806       /* Delay for COMP startup time */
807       /* Wait loop initialization and execution */
808       /* Note: Variable divided by 2 to compensate partially              */
809       /*       CPU processing cycles, scaling in us split to not          */
810       /*       exceed 32 bits register capacity and handle low frequency. */
811       wait_loop_index = ((COMP_DELAY_STARTUP_US / 10UL) * ((SystemCoreClock / (100000UL * 2UL)) + 1UL));
812       while(wait_loop_index != 0UL)
813       {
814         wait_loop_index--;
815       }
816     }
817     else
818     {
819       status = HAL_ERROR;
820     }
821   }
822 
823   return status;
824 }
825 
826 /**
827   * @brief  Stop the comparator.
828   * @param  hcomp  COMP handle
829   * @retval HAL status
830   */
HAL_COMP_Stop(COMP_HandleTypeDef * hcomp)831 HAL_StatusTypeDef HAL_COMP_Stop(COMP_HandleTypeDef *hcomp)
832 {
833   HAL_StatusTypeDef status = HAL_OK;
834 
835   /* Check the COMP handle allocation and lock status */
836   if(hcomp == NULL)
837   {
838     status = HAL_ERROR;
839   }
840   else if(__HAL_COMP_IS_LOCKED(hcomp))
841   {
842     status = HAL_ERROR;
843   }
844   else
845   {
846     /* Check the parameter */
847     assert_param(IS_COMP_ALL_INSTANCE(hcomp->Instance));
848 
849     /* Check compliant states: HAL_COMP_STATE_READY or HAL_COMP_STATE_BUSY    */
850     /* (all states except HAL_COMP_STATE_RESET and except locked status.      */
851     if(hcomp->State != HAL_COMP_STATE_RESET)
852     {
853       /* Disable the selected comparator */
854       CLEAR_BIT(hcomp->Instance->CSR, COMP_CSR_EN);
855 
856       /* Set HAL COMP handle state */
857       hcomp->State = HAL_COMP_STATE_READY;
858     }
859     else
860     {
861       status = HAL_ERROR;
862     }
863   }
864 
865   return status;
866 }
867 
868 /**
869   * @brief  Comparator IRQ handler.
870   * @param  hcomp  COMP handle
871   * @retval None
872   */
HAL_COMP_IRQHandler(COMP_HandleTypeDef * hcomp)873 void HAL_COMP_IRQHandler(COMP_HandleTypeDef *hcomp)
874 {
875   /* Get the EXTI line corresponding to the selected COMP instance */
876   uint32_t exti_line = COMP_GET_EXTI_LINE(hcomp->Instance);
877   uint32_t comparator_window_mode;
878   uint32_t comparator_window_exti_lines;
879 
880 #if defined(COMP3)
881   if(hcomp->Instance == COMP3)
882   {
883     /* Case of window mode with COMP2 and COMP3 */
884     comparator_window_mode = READ_BIT(COMP23_COMMON->CSR_EVEN, COMP_CSR_WINMODE);
885     comparator_window_exti_lines = (COMP_EXTI_LINE_COMP2 | COMP_EXTI_LINE_COMP3);
886   }
887   else
888   {
889     comparator_window_mode = READ_BIT(COMP23_COMMON->CSR_EVEN, COMP_CSR_WINMODE);
890     if( (hcomp->Instance == COMP2) && (comparator_window_mode != 0UL))
891     {
892       /* Case of window mode with COMP2 and COMP3 */
893       comparator_window_exti_lines = (COMP_EXTI_LINE_COMP2 | COMP_EXTI_LINE_COMP3);
894     }
895     else
896     {
897       /* Case of window mode with COMP1 and COMP2 */
898       comparator_window_mode = READ_BIT(COMP12_COMMON->CSR_ODD, COMP_CSR_WINMODE);
899       comparator_window_mode |= READ_BIT(COMP12_COMMON->CSR_EVEN, COMP_CSR_WINMODE);
900       comparator_window_exti_lines = (COMP_EXTI_LINE_COMP1 | COMP_EXTI_LINE_COMP2);
901     }
902   }
903 #else
904     comparator_window_mode = READ_BIT(COMP12_COMMON->CSR_ODD, COMP_CSR_WINMODE);
905     comparator_window_mode |= READ_BIT(COMP12_COMMON->CSR_EVEN, COMP_CSR_WINMODE);
906     comparator_window_exti_lines = (COMP_EXTI_LINE_COMP1 | COMP_EXTI_LINE_COMP2);
907 #endif /* COMP3 */
908 
909   /* Check COMP EXTI flag */
910   if(LL_EXTI_IsActiveRisingFlag_0_31(exti_line) != 0UL)
911   {
912     /* Check whether comparator is in independent or window mode */
913     if(comparator_window_mode != 0UL)
914     {
915       /* Clear COMP EXTI line pending bit of the pair of comparators          */
916       /* in window mode.                                                      */
917       /* Note: Pair of comparators in window mode can both trig IRQ when      */
918       /*       input voltage is changing from "out of window" area            */
919       /*       (low or high ) to the other "out of window" area (high or low).*/
920       /*       Both flags must be cleared to call comparator trigger          */
921       /*       callback is called once.                                       */
922       LL_EXTI_ClearRisingFlag_0_31(comparator_window_exti_lines);
923     }
924     else
925     {
926       /* Clear COMP EXTI line pending bit */
927       LL_EXTI_ClearRisingFlag_0_31(exti_line);
928     }
929 
930     /* COMP trigger user callback */
931 #if (USE_HAL_COMP_REGISTER_CALLBACKS == 1)
932     hcomp->TriggerCallback(hcomp);
933 #else
934     HAL_COMP_TriggerCallback(hcomp);
935 #endif /* USE_HAL_COMP_REGISTER_CALLBACKS */
936   }
937   else if(LL_EXTI_IsActiveFallingFlag_0_31(exti_line) != 0UL)
938   {
939     /* Check whether comparator is in independent or window mode */
940     if(comparator_window_mode != 0UL)
941     {
942       /* Clear COMP EXTI line pending bit of the pair of comparators          */
943       /* in window mode.                                                      */
944       /* Note: Pair of comparators in window mode can both trig IRQ when      */
945       /*       input voltage is changing from "out of window" area            */
946       /*       (low or high ) to the other "out of window" area (high or low).*/
947       /*       Both flags must be cleared to call comparator trigger          */
948       /*       callback is called once.                                       */
949       LL_EXTI_ClearFallingFlag_0_31(comparator_window_exti_lines);
950     }
951     else
952     {
953       /* Clear COMP EXTI line pending bit */
954       LL_EXTI_ClearFallingFlag_0_31(exti_line);
955     }
956 
957     /* COMP trigger callback */
958 #if (USE_HAL_COMP_REGISTER_CALLBACKS == 1)
959     hcomp->TriggerCallback(hcomp);
960 #else
961     HAL_COMP_TriggerCallback(hcomp);
962 #endif /* USE_HAL_COMP_REGISTER_CALLBACKS */
963   }
964   else
965   {
966     /* nothing to do */
967   }
968 }
969 
970 /**
971   * @}
972   */
973 
974 /** @defgroup COMP_Exported_Functions_Group3 Peripheral Control functions
975   *  @brief   Management functions.
976   *
977 @verbatim
978  ===============================================================================
979                       ##### Peripheral Control functions #####
980  ===============================================================================
981     [..]
982     This subsection provides a set of functions allowing to control the comparators.
983 
984 @endverbatim
985   * @{
986   */
987 
988 /**
989   * @brief  Lock the selected comparator configuration.
990   * @note   A system reset is required to unlock the comparator configuration.
991   * @note   Locking the comparator from reset state is possible
992   *         if __HAL_RCC_SYSCFG_CLK_ENABLE() is being called before.
993   * @param  hcomp  COMP handle
994   * @retval HAL status
995   */
HAL_COMP_Lock(COMP_HandleTypeDef * hcomp)996 HAL_StatusTypeDef HAL_COMP_Lock(COMP_HandleTypeDef *hcomp)
997 {
998   HAL_StatusTypeDef status = HAL_OK;
999 
1000   /* Check the COMP handle allocation and lock status */
1001   if(hcomp == NULL)
1002   {
1003     status = HAL_ERROR;
1004   }
1005   else if(__HAL_COMP_IS_LOCKED(hcomp))
1006   {
1007     status = HAL_ERROR;
1008   }
1009   else
1010   {
1011     /* Check the parameter */
1012     assert_param(IS_COMP_ALL_INSTANCE(hcomp->Instance));
1013 
1014     /* Set HAL COMP handle state */
1015     switch(hcomp->State)
1016     {
1017       case HAL_COMP_STATE_RESET:
1018         hcomp->State = HAL_COMP_STATE_RESET_LOCKED;
1019         break;
1020       case HAL_COMP_STATE_READY:
1021         hcomp->State = HAL_COMP_STATE_READY_LOCKED;
1022         break;
1023       default: /* HAL_COMP_STATE_BUSY */
1024         hcomp->State = HAL_COMP_STATE_BUSY_LOCKED;
1025         break;
1026     }
1027   }
1028 
1029   if(status == HAL_OK)
1030   {
1031     /* Set the lock bit corresponding to selected comparator */
1032     __HAL_COMP_LOCK(hcomp);
1033   }
1034 
1035   return status;
1036 }
1037 
1038 /**
1039   * @brief  Return the output level (high or low) of the selected comparator.
1040   *         The output level depends on the selected polarity.
1041   *         If the polarity is not inverted:
1042   *           - Comparator output is low when the input plus is at a lower
1043   *             voltage than the input minus
1044   *           - Comparator output is high when the input plus is at a higher
1045   *             voltage than the input minus
1046   *         If the polarity is inverted:
1047   *           - Comparator output is high when the input plus is at a lower
1048   *             voltage than the input minus
1049   *           - Comparator output is low when the input plus is at a higher
1050   *             voltage than the input minus
1051   * @param  hcomp  COMP handle
1052   * @retval Returns the selected comparator output level:
1053   *         @arg COMP_OUTPUT_LEVEL_LOW
1054   *         @arg COMP_OUTPUT_LEVEL_HIGH
1055   *
1056   */
HAL_COMP_GetOutputLevel(COMP_HandleTypeDef * hcomp)1057 uint32_t HAL_COMP_GetOutputLevel(COMP_HandleTypeDef *hcomp)
1058 {
1059   /* Check the parameter */
1060   assert_param(IS_COMP_ALL_INSTANCE(hcomp->Instance));
1061 
1062   return (uint32_t)(READ_BIT(hcomp->Instance->CSR, COMP_CSR_VALUE)
1063                     >> COMP_OUTPUT_LEVEL_BITOFFSET_POS);
1064 }
1065 
1066 /**
1067   * @brief  Comparator trigger callback.
1068   * @param  hcomp  COMP handle
1069   * @retval None
1070   */
HAL_COMP_TriggerCallback(COMP_HandleTypeDef * hcomp)1071 __weak void HAL_COMP_TriggerCallback(COMP_HandleTypeDef *hcomp)
1072 {
1073   /* Prevent unused argument(s) compilation warning */
1074   UNUSED(hcomp);
1075 
1076   /* NOTE : This function should not be modified, when the callback is needed,
1077             the HAL_COMP_TriggerCallback should be implemented in the user file
1078    */
1079 }
1080 
1081 
1082 /**
1083   * @}
1084   */
1085 
1086 /** @defgroup COMP_Exported_Functions_Group4 Peripheral State functions
1087   *  @brief   Peripheral State functions.
1088   *
1089 @verbatim
1090  ===============================================================================
1091                       ##### Peripheral State functions #####
1092  ===============================================================================
1093     [..]
1094     This subsection permit to get in run-time the status of the peripheral.
1095 
1096 @endverbatim
1097   * @{
1098   */
1099 
1100 /**
1101   * @brief  Return the COMP handle state.
1102   * @param  hcomp  COMP handle
1103   * @retval HAL state
1104   */
HAL_COMP_GetState(COMP_HandleTypeDef * hcomp)1105 HAL_COMP_StateTypeDef HAL_COMP_GetState(COMP_HandleTypeDef *hcomp)
1106 {
1107   /* Check the COMP handle allocation */
1108   if(hcomp == NULL)
1109   {
1110     return HAL_COMP_STATE_RESET;
1111   }
1112 
1113   /* Check the parameter */
1114   assert_param(IS_COMP_ALL_INSTANCE(hcomp->Instance));
1115 
1116   /* Return HAL COMP handle state */
1117   return hcomp->State;
1118 }
1119 
1120 /**
1121   * @brief  Return the COMP error code.
1122   * @param hcomp COMP handle
1123   * @retval COMP error code
1124   */
HAL_COMP_GetError(COMP_HandleTypeDef * hcomp)1125 uint32_t HAL_COMP_GetError(COMP_HandleTypeDef *hcomp)
1126 {
1127   /* Check the parameters */
1128   assert_param(IS_COMP_ALL_INSTANCE(hcomp->Instance));
1129 
1130   return hcomp->ErrorCode;
1131 }
1132 
1133 /**
1134   * @}
1135   */
1136 
1137 /**
1138   * @}
1139   */
1140 
1141 /**
1142   * @}
1143   */
1144 
1145 #endif /* COMP1 || COMP2 */
1146 
1147 #endif /* HAL_COMP_MODULE_ENABLED */
1148 
1149 /**
1150   * @}
1151   */
1152