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