1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2019 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_acmp.h"
10 
11 /*******************************************************************************
12  * Definitions
13  ******************************************************************************/
14 
15 /* Component ID definition, used by tools. */
16 #ifndef FSL_COMPONENT_ID
17 #define FSL_COMPONENT_ID "platform.drivers.acmp"
18 #endif
19 
20 /*******************************************************************************
21  * Prototypes
22  ******************************************************************************/
23 /*!
24  * @brief Get the ACMP instance from the peripheral base address.
25  *
26  * @param base ACMP peripheral base address.
27  * @return ACMP instance.
28  */
29 static uint32_t ACMP_GetInstance(CMP_Type *base);
30 
31 /*******************************************************************************
32  * Variables
33  ******************************************************************************/
34 /* Array of ACMP peripheral base address. */
35 static CMP_Type *const s_acmpBases[] = CMP_BASE_PTRS;
36 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
37 /* Clock name of ACMP. */
38 static const clock_ip_name_t s_acmpClock[] = CMP_CLOCKS;
39 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
40 
41 /*******************************************************************************
42  * Codes
43  ******************************************************************************/
ACMP_GetInstance(CMP_Type * base)44 static uint32_t ACMP_GetInstance(CMP_Type *base)
45 {
46     uint32_t instance = 0U;
47 
48     /* Find the instance index from base address mappings. */
49     for (instance = 0; instance < ARRAY_SIZE(s_acmpBases); instance++)
50     {
51         if (s_acmpBases[instance] == base)
52         {
53             break;
54         }
55     }
56 
57     assert(instance < ARRAY_SIZE(s_acmpBases));
58 
59     return instance;
60 }
61 
62 /*!
63  * brief Initializes the ACMP.
64  *
65  * The default configuration can be got by calling ACMP_GetDefaultConfig().
66  *
67  * param base ACMP peripheral base address.
68  * param config Pointer to ACMP configuration structure.
69  */
ACMP_Init(CMP_Type * base,const acmp_config_t * config)70 void ACMP_Init(CMP_Type *base, const acmp_config_t *config)
71 {
72     assert(NULL != config);
73 
74     uint32_t tmp32;
75 
76 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
77     /* Open clock gate. */
78     CLOCK_EnableClock(s_acmpClock[ACMP_GetInstance(base)]);
79 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
80 
81     /* Disable the module before configuring it. */
82     ACMP_Enable(base, false);
83 
84     /* CMPx_C0
85      * Set control bit. Avoid clearing status flags at the same time.
86      */
87     tmp32 = (base->C0 & (~(CMP_C0_PMODE_MASK | CMP_C0_INVT_MASK | CMP_C0_COS_MASK | CMP_C0_OPE_MASK |
88                            CMP_C0_HYSTCTR_MASK | CMP_C0_CFx_MASK)));
89 #if defined(FSL_FEATURE_ACMP_HAS_C0_OFFSET_BIT) && (FSL_FEATURE_ACMP_HAS_C0_OFFSET_BIT == 1U)
90     tmp32 &= ~CMP_C0_OFFSET_MASK;
91 #endif /* FSL_FEATURE_ACMP_HAS_C0_OFFSET_BIT */
92     if (config->enableHighSpeed)
93     {
94         tmp32 |= CMP_C0_PMODE_MASK;
95     }
96     if (config->enableInvertOutput)
97     {
98         tmp32 |= CMP_C0_INVT_MASK;
99     }
100     if (config->useUnfilteredOutput)
101     {
102         tmp32 |= CMP_C0_COS_MASK;
103     }
104     if (config->enablePinOut)
105     {
106         tmp32 |= CMP_C0_OPE_MASK;
107     }
108     tmp32 |= CMP_C0_HYSTCTR(config->hysteresisMode);
109 #if defined(FSL_FEATURE_ACMP_HAS_C0_OFFSET_BIT) && (FSL_FEATURE_ACMP_HAS_C0_OFFSET_BIT == 1U)
110     tmp32 |= CMP_C0_OFFSET(config->offsetMode);
111 #endif /* FSL_FEATURE_ACMP_HAS_C0_OFFSET_BIT */
112     base->C0 = tmp32;
113 }
114 
115 /*!
116  * brief Deinitializes the ACMP.
117  *
118  * param base ACMP peripheral base address.
119  */
ACMP_Deinit(CMP_Type * base)120 void ACMP_Deinit(CMP_Type *base)
121 {
122     /* Disable the module. */
123     ACMP_Enable(base, false);
124 
125 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
126     /* Disable clock gate. */
127     CLOCK_DisableClock(s_acmpClock[ACMP_GetInstance(base)]);
128 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
129 }
130 
131 /*!
132  * brief Gets the default configuration for ACMP.
133  *
134  * This function initializes the user configuration structure to default value. The default value are:
135  *
136  * Example:
137    code
138    config->enableHighSpeed = false;
139    config->enableInvertOutput = false;
140    config->useUnfilteredOutput = false;
141    config->enablePinOut = false;
142    config->enableHysteresisBothDirections = false;
143    config->hysteresisMode = kACMP_hysteresisMode0;
144    endcode
145  *
146  * param config Pointer to ACMP configuration structure.
147  */
ACMP_GetDefaultConfig(acmp_config_t * config)148 void ACMP_GetDefaultConfig(acmp_config_t *config)
149 {
150     assert(NULL != config);
151 
152     /* Initializes the configure structure to zero. */
153     (void)memset(config, 0, sizeof(*config));
154 
155     /* Fill default configuration */
156     config->enableHighSpeed     = false;
157     config->enableInvertOutput  = false;
158     config->useUnfilteredOutput = false;
159     config->enablePinOut        = false;
160 #if defined(FSL_FEATURE_ACMP_HAS_C0_OFFSET_BIT) && (FSL_FEATURE_ACMP_HAS_C0_OFFSET_BIT == 1U)
161     config->offsetMode = kACMP_OffsetLevel0;
162 #endif /* FSL_FEATURE_ACMP_HAS_C0_OFFSET_BIT */
163     config->hysteresisMode = kACMP_HysteresisLevel0;
164 }
165 
166 /*!
167  * brief Enables or disables the ACMP.
168  *
169  * param base ACMP peripheral base address.
170  * param enable True to enable the ACMP.
171  */
ACMP_Enable(CMP_Type * base,bool enable)172 void ACMP_Enable(CMP_Type *base, bool enable)
173 {
174     /* CMPx_C0
175      * Set control bit. Avoid clearing status flags at the same time.
176      */
177     if (enable)
178     {
179         base->C0 = ((base->C0 | CMP_C0_EN_MASK) & ~CMP_C0_CFx_MASK);
180     }
181     else
182     {
183         base->C0 &= ~(CMP_C0_EN_MASK | CMP_C0_CFx_MASK);
184     }
185 }
186 
187 #if defined(FSL_FEATURE_ACMP_HAS_C0_LINKEN_BIT) && (FSL_FEATURE_ACMP_HAS_C0_LINKEN_BIT == 1U)
188 /*!
189  * brief Enables the link from CMP to DAC enable.
190  *
191  * When this bit is set, the DAC enable/disable is controlled by the bit CMP_C0[EN] instead of CMP_C1[DACEN].
192  *
193  * param base ACMP peripheral base address.
194  * param enable Enable the feature or not.
195  */
ACMP_EnableLinkToDAC(CMP_Type * base,bool enable)196 void ACMP_EnableLinkToDAC(CMP_Type *base, bool enable)
197 {
198     /* CMPx_C0_LINKEN
199      * Set control bit. Avoid clearing status flags at the same time.
200      */
201     if (enable)
202     {
203         base->C0 = ((base->C0 | CMP_C0_LINKEN_MASK) & ~CMP_C0_CFx_MASK);
204     }
205     else
206     {
207         base->C0 &= ~(CMP_C0_LINKEN_MASK | CMP_C0_CFx_MASK);
208     }
209 }
210 #endif /* FSL_FEATURE_ACMP_HAS_C0_LINKEN_BIT */
211 
212 /*!
213  * brief Sets the channel configuration.
214  *
215  * Note that the plus/minus mux's setting is only valid when the positive/negative port's input isn't from DAC but
216  * from channel mux.
217  *
218  * Example:
219    code
220    acmp_channel_config_t configStruct = {0};
221    configStruct.positivePortInput = kACMP_PortInputFromDAC;
222    configStruct.negativePortInput = kACMP_PortInputFromMux;
223    configStruct.minusMuxInput = 1U;
224    ACMP_SetChannelConfig(CMP0, &configStruct);
225    endcode
226  *
227  * param base ACMP peripheral base address.
228  * param config Pointer to channel configuration structure.
229  */
ACMP_SetChannelConfig(CMP_Type * base,const acmp_channel_config_t * config)230 void ACMP_SetChannelConfig(CMP_Type *base, const acmp_channel_config_t *config)
231 {
232     assert(NULL != config);
233 
234     uint32_t tmp32 = (base->C1 & (~(CMP_C1_PSEL_MASK | CMP_C1_MSEL_MASK)));
235 
236 /* CMPx_C1
237  * Set the input of CMP's positive port.
238  */
239 #if (defined(FSL_FEATURE_ACMP_HAS_C1_INPSEL_BIT) && (FSL_FEATURE_ACMP_HAS_C1_INPSEL_BIT == 1U))
240     tmp32 &= ~CMP_C1_INPSEL_MASK;
241     tmp32 |= CMP_C1_INPSEL(config->positivePortInput);
242 #endif /* FSL_FEATURE_ACMP_HAS_C1_INPSEL_BIT */
243 
244 #if (defined(FSL_FEATURE_ACMP_HAS_C1_INNSEL_BIT) && (FSL_FEATURE_ACMP_HAS_C1_INNSEL_BIT == 1U))
245     tmp32 &= ~CMP_C1_INNSEL_MASK;
246     tmp32 |= CMP_C1_INNSEL(config->negativePortInput);
247 #endif /* FSL_FEATURE_ACMP_HAS_C1_INPSEL_BIT */
248 
249     tmp32 |= CMP_C1_PSEL(config->plusMuxInput) | CMP_C1_MSEL(config->minusMuxInput);
250 
251     base->C1 = tmp32;
252 }
253 
254 /*!
255  * brief Enables or disables DMA.
256  *
257  * param base ACMP peripheral base address.
258  * param enable True to enable DMA.
259  */
ACMP_EnableDMA(CMP_Type * base,bool enable)260 void ACMP_EnableDMA(CMP_Type *base, bool enable)
261 {
262     /* CMPx_C0
263      * Set control bit. Avoid clearing status flags at the same time.
264      */
265     if (enable)
266     {
267         base->C0 = ((base->C0 | CMP_C0_DMAEN_MASK) & ~CMP_C0_CFx_MASK);
268     }
269     else
270     {
271         base->C0 &= ~(CMP_C0_DMAEN_MASK | CMP_C0_CFx_MASK);
272     }
273 }
274 
275 /*!
276  * brief Enables or disables window mode.
277  *
278  * param base ACMP peripheral base address.
279  * param enable True to enable window mode.
280  */
ACMP_EnableWindowMode(CMP_Type * base,bool enable)281 void ACMP_EnableWindowMode(CMP_Type *base, bool enable)
282 {
283     /* CMPx_C0
284      * Set control bit. Avoid clearing status flags at the same time.
285      */
286     if (enable)
287     {
288         base->C0 = ((base->C0 | CMP_C0_WE_MASK) & ~CMP_C0_CFx_MASK);
289     }
290     else
291     {
292         base->C0 &= ~(CMP_C0_WE_MASK | CMP_C0_CFx_MASK);
293     }
294 }
295 
296 /*!
297  * brief Configures the filter.
298  *
299  * The filter can be enabled when the filter count is bigger than 1, the filter period is greater than 0 and the sample
300  * clock is from divided bus clock or the filter is bigger than 1 and the sample clock is from external clock. Detailed
301  * usage can be got from the reference manual.
302  *
303  * Example:
304    code
305    acmp_filter_config_t configStruct = {0};
306    configStruct.filterCount = 5U;
307    configStruct.filterPeriod = 200U;
308    configStruct.enableSample = false;
309    ACMP_SetFilterConfig(CMP0, &configStruct);
310    endcode
311  *
312  * param base ACMP peripheral base address.
313  * param config Pointer to filter configuration structure.
314  */
ACMP_SetFilterConfig(CMP_Type * base,const acmp_filter_config_t * config)315 void ACMP_SetFilterConfig(CMP_Type *base, const acmp_filter_config_t *config)
316 {
317     assert(NULL != config);
318 
319     /* CMPx_C0
320      * Set control bit. Avoid clearing status flags at the same time.
321      */
322     uint32_t tmp32 = (base->C0 & (~(CMP_C0_FILTER_CNT_MASK | CMP_C0_FPR_MASK | CMP_C0_SE_MASK | CMP_C0_CFx_MASK)));
323 
324     if (config->enableSample)
325     {
326         tmp32 |= CMP_C0_SE_MASK;
327     }
328     tmp32 |= (CMP_C0_FILTER_CNT(config->filterCount) | CMP_C0_FPR(config->filterPeriod));
329     base->C0 = tmp32;
330 }
331 
332 /*!
333  * brief Configures the internal DAC.
334  *
335  * Example:
336    code
337    acmp_dac_config_t configStruct = {0};
338    configStruct.referenceVoltageSource = kACMP_VrefSourceVin1;
339    configStruct.DACValue = 20U;
340    configStruct.enableOutput = false;
341    configStruct.workMode = kACMP_DACWorkLowSpeedMode;
342    ACMP_SetDACConfig(CMP0, &configStruct);
343    endcode
344  *
345  * param base ACMP peripheral base address.
346  * param config Pointer to DAC configuration structure. "NULL" is for disabling the feature.
347  */
ACMP_SetDACConfig(CMP_Type * base,const acmp_dac_config_t * config)348 void ACMP_SetDACConfig(CMP_Type *base, const acmp_dac_config_t *config)
349 {
350     uint32_t tmp32;
351 
352     /* CMPx_C1
353      * NULL configuration means to disable the feature.
354      */
355     if (NULL == config)
356     {
357         base->C1 &= ~CMP_C1_DACEN_MASK;
358         return;
359     }
360 
361     tmp32 = (base->C1 & (~(CMP_C1_VRSEL_MASK | CMP_C1_VOSEL_MASK)));
362     /* Set configuration and enable the feature. */
363     tmp32 |= (CMP_C1_VRSEL(config->referenceVoltageSource) | CMP_C1_VOSEL(config->DACValue) | CMP_C1_DACEN_MASK);
364 
365 #if defined(FSL_FEATURE_ACMP_HAS_C1_DACOE_BIT) && (FSL_FEATURE_ACMP_HAS_C1_DACOE_BIT == 1U)
366     tmp32 &= ~CMP_C1_DACOE_MASK;
367     if (config->enableOutput)
368     {
369         tmp32 |= CMP_C1_DACOE_MASK;
370     }
371 #endif /* FSL_FEATURE_ACMP_HAS_C1_DACOE_BIT */
372 
373 #if defined(FSL_FEATURE_ACMP_HAS_C1_DMODE_BIT) && (FSL_FEATURE_ACMP_HAS_C1_DMODE_BIT == 1U)
374     switch (config->workMode)
375     {
376         case kACMP_DACWorkLowSpeedMode:
377             tmp32 &= ~CMP_C1_DMODE_MASK;
378             break;
379         case kACMP_DACWorkHighSpeedMode:
380             tmp32 |= CMP_C1_DMODE_MASK;
381             break;
382         default:
383             assert(false);
384             break;
385     }
386 #endif /* FSL_FEATURE_ACMP_HAS_C1_DMODE_BIT */
387 
388     base->C1 = tmp32;
389 }
390 
391 /*!
392  * brief Configures the round robin mode.
393  *
394  * Example:
395    code
396    acmp_round_robin_config_t configStruct = {0};
397    configStruct.fixedPort = kACMP_FixedPlusPort;
398    configStruct.fixedChannelNumber = 3U;
399    configStruct.checkerChannelMask = 0xF7U;
400    configStruct.sampleClockCount = 0U;
401    configStruct.delayModulus = 0U;
402    ACMP_SetRoundRobinConfig(CMP0, &configStruct);
403    endcode
404  * param base ACMP peripheral base address.
405  * param config Pointer to round robin mode configuration structure. "NULL" is for disabling the feature.
406  */
ACMP_SetRoundRobinConfig(CMP_Type * base,const acmp_round_robin_config_t * config)407 void ACMP_SetRoundRobinConfig(CMP_Type *base, const acmp_round_robin_config_t *config)
408 {
409     uint32_t tmp32;
410 
411     /* CMPx_C2
412      * Set control bit. Avoid clearing status flags at the same time.
413      * NULL configuration means to disable the feature.
414      */
415     if (NULL == config)
416     {
417         tmp32 = CMP_C2_CHnF_MASK;
418 #if defined(FSL_FEATURE_ACMP_HAS_C2_RRE_BIT) && (FSL_FEATURE_ACMP_HAS_C2_RRE_BIT == 1U)
419         tmp32 |= CMP_C2_RRE_MASK;
420 #endif /* FSL_FEATURE_ACMP_HAS_C2_RRE_BIT */
421         base->C2 &= ~(tmp32);
422         return;
423     }
424 
425     /* CMPx_C1
426      * Set all channel's round robin checker enable mask.
427      */
428     tmp32 = (base->C1 & ~(CMP_C1_CHNn_MASK));
429     tmp32 |= ((config->checkerChannelMask) << CMP_C1_CHN0_SHIFT);
430     base->C1 = tmp32;
431 
432     /* CMPx_C2
433      * Set configuration and enable the feature.
434      */
435     tmp32 = (base->C2 &
436              (~(CMP_C2_FXMP_MASK | CMP_C2_FXMXCH_MASK | CMP_C2_NSAM_MASK | CMP_C2_INITMOD_MASK | CMP_C2_CHnF_MASK)));
437     tmp32 |= (CMP_C2_FXMP(config->fixedPort) | CMP_C2_FXMXCH(config->fixedChannelNumber) |
438               CMP_C2_NSAM(config->sampleClockCount) | CMP_C2_INITMOD(config->delayModulus));
439 #if defined(FSL_FEATURE_ACMP_HAS_C2_RRE_BIT) && (FSL_FEATURE_ACMP_HAS_C2_RRE_BIT == 1U)
440     tmp32 |= CMP_C2_RRE_MASK;
441 #endif /* FSL_FEATURE_ACMP_HAS_C2_RRE_BIT */
442     base->C2 = tmp32;
443 }
444 
445 /*!
446  * brief Defines the pre-set state of channels in round robin mode.
447  *
448  * Note: The pre-state has different circuit with get-round-robin-result in the SOC even though they are same bits.
449  * So get-round-robin-result can't return the same value as the value are set by pre-state.
450  *
451  * param base ACMP peripheral base address.
452  * param mask Mask of round robin channel index. Available range is channel0:0x01 to channel7:0x80.
453  */
ACMP_SetRoundRobinPreState(CMP_Type * base,uint32_t mask)454 void ACMP_SetRoundRobinPreState(CMP_Type *base, uint32_t mask)
455 {
456     /* CMPx_C2
457      * Set control bit. Avoid clearing status flags at the same time.
458      */
459     uint32_t tmp32 = (base->C2 & ~(CMP_C2_ACOn_MASK | CMP_C2_CHnF_MASK));
460 
461     tmp32 |= (mask << CMP_C2_ACOn_SHIFT);
462     base->C2 = tmp32;
463 }
464 
465 /*!
466  * brief Clears the channel input changed flags in round robin mode.
467  *
468  * param base ACMP peripheral base address.
469  * param mask Mask of channel index. Available range is channel0:0x01 to channel7:0x80.
470  */
ACMP_ClearRoundRobinStatusFlags(CMP_Type * base,uint32_t mask)471 void ACMP_ClearRoundRobinStatusFlags(CMP_Type *base, uint32_t mask)
472 {
473     /* CMPx_C2 */
474     uint32_t tmp32 = (base->C2 & (~CMP_C2_CHnF_MASK));
475 
476     tmp32 |= (mask << CMP_C2_CH0F_SHIFT);
477     base->C2 = tmp32;
478 }
479 
480 /*!
481  * brief Enables interrupts.
482  *
483  * param base ACMP peripheral base address.
484  * param mask Interrupts mask. See "_acmp_interrupt_enable".
485  */
ACMP_EnableInterrupts(CMP_Type * base,uint32_t mask)486 void ACMP_EnableInterrupts(CMP_Type *base, uint32_t mask)
487 {
488     uint32_t tmp32;
489 
490     /* CMPx_C0
491      * Set control bit. Avoid clearing status flags at the same time.
492      * Set CMP interrupt enable flag.
493      */
494     tmp32 = base->C0 & ~CMP_C0_CFx_MASK; /* To protect the W1C flags. */
495     if ((uint32_t)kACMP_OutputRisingInterruptEnable == (mask & (uint32_t)kACMP_OutputRisingInterruptEnable))
496     {
497         tmp32 = ((tmp32 | CMP_C0_IER_MASK) & ~CMP_C0_CFx_MASK);
498     }
499     if ((uint32_t)kACMP_OutputFallingInterruptEnable == (mask & (uint32_t)kACMP_OutputFallingInterruptEnable))
500     {
501         tmp32 = ((tmp32 | CMP_C0_IEF_MASK) & ~CMP_C0_CFx_MASK);
502     }
503     base->C0 = tmp32;
504 
505     /* CMPx_C2
506      * Set round robin interrupt enable flag.
507      */
508     if ((uint32_t)kACMP_RoundRobinInterruptEnable == (mask & (uint32_t)kACMP_RoundRobinInterruptEnable))
509     {
510         tmp32 = base->C2;
511         /* Set control bit. Avoid clearing status flags at the same time. */
512         tmp32    = ((tmp32 | CMP_C2_RRIE_MASK) & ~CMP_C2_CHnF_MASK);
513         base->C2 = tmp32;
514     }
515 }
516 
517 /*!
518  * brief Disables interrupts.
519  *
520  * param base ACMP peripheral base address.
521  * param mask Interrupts mask. See "_acmp_interrupt_enable".
522  */
ACMP_DisableInterrupts(CMP_Type * base,uint32_t mask)523 void ACMP_DisableInterrupts(CMP_Type *base, uint32_t mask)
524 {
525     uint32_t tmp32;
526 
527     /* CMPx_C0
528      * Set control bit. Avoid clearing status flags at the same time.
529      * Clear CMP interrupt enable flag.
530      */
531     tmp32 = base->C0;
532     if ((uint32_t)kACMP_OutputRisingInterruptEnable == (mask & (uint32_t)kACMP_OutputRisingInterruptEnable))
533     {
534         tmp32 &= ~(CMP_C0_IER_MASK | CMP_C0_CFx_MASK);
535     }
536     if ((uint32_t)kACMP_OutputFallingInterruptEnable == (mask & (uint32_t)kACMP_OutputFallingInterruptEnable))
537     {
538         tmp32 &= ~(CMP_C0_IEF_MASK | CMP_C0_CFx_MASK);
539     }
540     base->C0 = tmp32;
541 
542     /* CMPx_C2
543      * Clear round robin interrupt enable flag.
544      */
545     if ((uint32_t)kACMP_RoundRobinInterruptEnable == (mask & (uint32_t)kACMP_RoundRobinInterruptEnable))
546     {
547         tmp32 = base->C2;
548         /* Set control bit. Avoid clearing status flags at the same time. */
549         tmp32 &= ~(CMP_C2_RRIE_MASK | CMP_C2_CHnF_MASK);
550         base->C2 = tmp32;
551     }
552 }
553 
554 /*!
555  * brief Gets status flags.
556  *
557  * param base ACMP peripheral base address.
558  * return Status flags asserted mask. See "_acmp_status_flags".
559  */
ACMP_GetStatusFlags(CMP_Type * base)560 uint32_t ACMP_GetStatusFlags(CMP_Type *base)
561 {
562     uint32_t status = 0U;
563     uint32_t tmp32  = base->C0;
564 
565     /* CMPx_C0
566      * Check if each flag is set.
567      */
568     if (CMP_C0_CFR_MASK == (tmp32 & CMP_C0_CFR_MASK))
569     {
570         status |= (uint32_t)kACMP_OutputRisingEventFlag;
571     }
572     if (CMP_C0_CFF_MASK == (tmp32 & CMP_C0_CFF_MASK))
573     {
574         status |= (uint32_t)kACMP_OutputFallingEventFlag;
575     }
576     if (CMP_C0_COUT_MASK == (tmp32 & CMP_C0_COUT_MASK))
577     {
578         status |= (uint32_t)kACMP_OutputAssertEventFlag;
579     }
580 
581     return status;
582 }
583 
584 /*!
585  * brief Clears status flags.
586  *
587  * param base ACMP peripheral base address.
588  * param mask Status flags mask. See "_acmp_status_flags".
589  */
ACMP_ClearStatusFlags(CMP_Type * base,uint32_t mask)590 void ACMP_ClearStatusFlags(CMP_Type *base, uint32_t mask)
591 {
592     /* CMPx_C0 */
593     uint32_t tmp32 = (base->C0 & (~(CMP_C0_CFR_MASK | CMP_C0_CFF_MASK)));
594 
595     /* Clear flag according to mask. */
596     if ((uint32_t)kACMP_OutputRisingEventFlag == (mask & (uint32_t)kACMP_OutputRisingEventFlag))
597     {
598         tmp32 |= CMP_C0_CFR_MASK;
599     }
600     if ((uint32_t)kACMP_OutputFallingEventFlag == (mask & (uint32_t)kACMP_OutputFallingEventFlag))
601     {
602         tmp32 |= CMP_C0_CFF_MASK;
603     }
604     base->C0 = tmp32;
605 }
606 
607 #if defined(FSL_FEATURE_ACMP_HAS_C3_REG) && (FSL_FEATURE_ACMP_HAS_C3_REG == 1U)
608 /*!
609  * brief Configure the discrete mode.
610  *
611  * Configure the discrete mode when supporting 3V domain with 1.8V core.
612  *
613  * param base ACMP peripheral base address.
614  * param config Pointer to configuration structure. See "acmp_discrete_mode_config_t".
615  */
ACMP_SetDiscreteModeConfig(CMP_Type * base,const acmp_discrete_mode_config_t * config)616 void ACMP_SetDiscreteModeConfig(CMP_Type *base, const acmp_discrete_mode_config_t *config)
617 {
618     uint32_t tmp32 = 0U;
619 
620     if (!config->enablePositiveChannelDiscreteMode)
621     {
622         tmp32 |= CMP_C3_PCHCTEN_MASK;
623     }
624     if (!config->enableNegativeChannelDiscreteMode)
625     {
626         tmp32 |= CMP_C3_NCHCTEN_MASK;
627     }
628     if (config->enableResistorDivider)
629     {
630         tmp32 |= CMP_C3_RDIVE_MASK;
631     }
632 
633     tmp32 |= CMP_C3_DMCS(config->clockSource)      /* Select the clock. */
634              | CMP_C3_ACSAT(config->sampleTime)    /* Sample time period. */
635              | CMP_C3_ACPH1TC(config->phase1Time)  /* Phase 1 sample time. */
636              | CMP_C3_ACPH2TC(config->phase2Time); /* Phase 2 sample time. */
637 
638     base->C3 = tmp32;
639 }
640 
641 /*!
642  * brief Get the default configuration for discrete mode setting.
643  *
644  * param config Pointer to configuration structure to be restored with the setting values.
645  */
ACMP_GetDefaultDiscreteModeConfig(acmp_discrete_mode_config_t * config)646 void ACMP_GetDefaultDiscreteModeConfig(acmp_discrete_mode_config_t *config)
647 {
648     assert(NULL != config);
649 
650     /* Initializes the configure structure to zero. */
651     (void)memset(config, 0, sizeof(*config));
652 
653     config->enablePositiveChannelDiscreteMode = false;
654     config->enableNegativeChannelDiscreteMode = false;
655     config->enableResistorDivider             = false;
656     config->clockSource                       = kACMP_DiscreteClockSlow;
657     config->sampleTime                        = kACMP_DiscreteSampleTimeAs1T;
658     config->phase1Time                        = kACMP_DiscretePhaseTimeAlt0;
659     config->phase2Time                        = kACMP_DiscretePhaseTimeAlt0;
660 }
661 
662 #endif /* FSL_FEATURE_ACMP_HAS_C3_REG */
663