Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:01

0001 /*
0002  * Copyright 2017-2022 NXP
0003  * All rights reserved.
0004  *
0005  * SPDX-License-Identifier: BSD-3-Clause
0006  */
0007 
0008 #include "fsl_qtmr.h"
0009 #ifdef __rtems__
0010 #include <bsp.h>
0011 #include <bsp/irq.h>
0012 #include <libfdt.h>
0013 #endif /* __rtems__ */
0014 
0015 /* Component ID definition, used by tools. */
0016 #ifndef FSL_COMPONENT_ID
0017 #define FSL_COMPONENT_ID "platform.drivers.qtmr"
0018 #endif
0019 
0020 /*******************************************************************************
0021  * Prototypes
0022  ******************************************************************************/
0023 /*!
0024  * @brief Gets the instance from the base address to be used to gate or ungate the module clock
0025  *
0026  * @param base Quad Timer peripheral base address
0027  *
0028  * @return The Quad Timer instance
0029  */
0030 static uint32_t QTMR_GetInstance(TMR_Type *base);
0031 
0032 /*******************************************************************************
0033  * Variables
0034  ******************************************************************************/
0035 /*! @brief Pointers to Quad Timer bases for each instance. */
0036 static TMR_Type *const s_qtmrBases[] = TMR_BASE_PTRS;
0037 
0038 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0039 /*! @brief Pointers to Quad Timer clocks for each instance. */
0040 static const clock_ip_name_t s_qtmrClocks[] = TMR_CLOCKS;
0041 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
0042 
0043 static uint8_t s_qtmrGetPwmDutyCycle[FSL_FEATURE_SOC_TMR_COUNT] = {0U};
0044 
0045 /*******************************************************************************
0046  * Code
0047  ******************************************************************************/
0048 static uint32_t QTMR_GetInstance(TMR_Type *base)
0049 {
0050     uint32_t instance;
0051 
0052     /* Find the instance index from base address mappings. */
0053     for (instance = 0; instance < ARRAY_SIZE(s_qtmrBases); instance++)
0054     {
0055         if (s_qtmrBases[instance] == base)
0056         {
0057             break;
0058         }
0059     }
0060 
0061     assert(instance < ARRAY_SIZE(s_qtmrBases));
0062 
0063     return instance;
0064 }
0065 
0066 #ifdef __rtems__
0067 TMR_Type *QTMR_get_regs_from_fdt(const void *fdt, int node)
0068 {
0069     int rv;
0070     TMR_Type *regs;
0071 
0072     rv = fdt_node_check_compatible(fdt, node, "nxp,imxrt-qtimer");
0073     if (rv != 0) {
0074         return NULL;
0075     }
0076     regs = imx_get_reg_of_node(fdt, node);
0077     return regs;
0078 }
0079 
0080 rtems_vector_number QTMR_get_IRQ_from_fdt(const void *fdt, int node)
0081 {
0082     int rv;
0083     rtems_vector_number irq;
0084 
0085     rv = fdt_node_check_compatible(fdt, node, "nxp,imxrt-qtimer");
0086     if (rv != 0) {
0087         return BSP_INTERRUPT_VECTOR_INVALID;
0088     }
0089     irq = imx_get_irq_of_node(fdt, node, 0);
0090     return irq;
0091 }
0092 
0093 uint32_t QTMR_get_src_clk(TMR_Type *base)
0094 {
0095 #if IMXRT_IS_MIMXRT10xx
0096     (void) base;
0097 
0098     return CLOCK_GetFreq(kCLOCK_IpgClk);
0099 #elif IMXRT_IS_MIMXRT11xx
0100     (void) base;
0101 
0102     return CLOCK_GetRootClockFreq(kCLOCK_Root_Bus);
0103 #else
0104   #error Getting Timer clock frequency is not implemented for this chip
0105 #endif
0106 }
0107 
0108 #endif /* __rtems__ */
0109 /*!
0110  * brief Ungates the Quad Timer clock and configures the peripheral for basic operation.
0111  *
0112  * note This API should be called at the beginning of the application using the Quad Timer driver.
0113  *
0114  * param base     Quad Timer peripheral base address
0115  * param channel  Quad Timer channel number
0116  * param config   Pointer to user's Quad Timer config structure
0117  */
0118 void QTMR_Init(TMR_Type *base, qtmr_channel_selection_t channel, const qtmr_config_t *config)
0119 {
0120     assert(NULL != config);
0121 
0122 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0123     /* Enable the module clock */
0124     CLOCK_EnableClock(s_qtmrClocks[QTMR_GetInstance(base)]);
0125 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
0126 
0127     /* Setup the counter sources */
0128     base->CHANNEL[channel].CTRL = (TMR_CTRL_PCS(config->primarySource) | TMR_CTRL_SCS(config->secondarySource));
0129 
0130     /* Setup the master mode operation */
0131     base->CHANNEL[channel].SCTRL =
0132         (TMR_SCTRL_EEOF(config->enableExternalForce) | TMR_SCTRL_MSTR(config->enableMasterMode));
0133 
0134     /* Setup debug mode */
0135     base->CHANNEL[channel].CSCTRL = TMR_CSCTRL_DBG_EN(config->debugMode);
0136 
0137     base->CHANNEL[channel].FILT &= (uint16_t)(~(TMR_FILT_FILT_CNT_MASK | TMR_FILT_FILT_PER_MASK));
0138     /* Setup input filter */
0139     base->CHANNEL[channel].FILT =
0140         (TMR_FILT_FILT_CNT(config->faultFilterCount) | TMR_FILT_FILT_PER(config->faultFilterPeriod));
0141 }
0142 
0143 /*!
0144  * brief Stops the counter and gates the Quad Timer clock
0145  *
0146  * param base     Quad Timer peripheral base address
0147  * param channel  Quad Timer channel number
0148  */
0149 void QTMR_Deinit(TMR_Type *base, qtmr_channel_selection_t channel)
0150 {
0151     /* Stop the counter */
0152     base->CHANNEL[channel].CTRL &= (uint16_t)(~TMR_CTRL_CM_MASK);
0153 
0154 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0155     /* Disable the module clock */
0156     CLOCK_DisableClock(s_qtmrClocks[QTMR_GetInstance(base)]);
0157 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
0158 }
0159 
0160 /*!
0161  * brief  Fill in the Quad Timer config struct with the default settings
0162  *
0163  * The default values are:
0164  * code
0165  *    config->debugMode = kQTMR_RunNormalInDebug;
0166  *    config->enableExternalForce = false;
0167  *    config->enableMasterMode = false;
0168  *    config->faultFilterCount = 0;
0169  *    config->faultFilterPeriod = 0;
0170  *    config->primarySource = kQTMR_ClockDivide_2;
0171  *    config->secondarySource = kQTMR_Counter0InputPin;
0172  * endcode
0173  * param config Pointer to user's Quad Timer config structure.
0174  */
0175 void QTMR_GetDefaultConfig(qtmr_config_t *config)
0176 {
0177     assert(NULL != config);
0178 
0179     /* Initializes the configure structure to zero. */
0180     (void)memset(config, 0, sizeof(*config));
0181 
0182     /* Halt counter during debug mode */
0183     config->debugMode = kQTMR_RunNormalInDebug;
0184     /* Another counter cannot force state of OFLAG signal */
0185     config->enableExternalForce = false;
0186     /* Compare function's output from this counter is not broadcast to other counters */
0187     config->enableMasterMode = false;
0188     /* Fault filter count is set to 0 */
0189     config->faultFilterCount = 0;
0190     /* Fault filter period is set to 0 which disables the fault filter */
0191     config->faultFilterPeriod = 0;
0192     /* Primary count source is IP bus clock divide by 2 */
0193     config->primarySource = kQTMR_ClockDivide_2;
0194     /* Secondary count source is counter 0 input pin */
0195     config->secondarySource = kQTMR_Counter0InputPin;
0196 }
0197 
0198 /*!
0199  * brief Sets up Quad timer module for PWM signal output.
0200  *
0201  * The function initializes the timer module according to the parameters passed in by the user. The
0202  * function also sets up the value compare registers to match the PWM signal requirements.
0203  *
0204  * param base             Quad Timer peripheral base address
0205  * param channel          Quad Timer channel number
0206  * param pwmFreqHz        PWM signal frequency in Hz
0207  * param dutyCyclePercent PWM pulse width, value should be between 0 to 100
0208  *                         0=inactive signal(0% duty cycle)...
0209  *                         100=active signal (100% duty cycle)
0210  * param outputPolarity   true: invert polarity of the output signal, false: no inversion
0211  * param srcClock_Hz      Main counter clock in Hz.
0212  *
0213  * return Returns an error if there was error setting up the signal.
0214  */
0215 status_t QTMR_SetupPwm(TMR_Type *base,
0216                        qtmr_channel_selection_t channel,
0217                        uint32_t pwmFreqHz,
0218                        uint8_t dutyCyclePercent,
0219                        bool outputPolarity,
0220                        uint32_t srcClock_Hz)
0221 {
0222     uint32_t periodCount, highCount, lowCount;
0223     uint16_t reg;
0224     status_t status;
0225 
0226     if (dutyCyclePercent <= 100U)
0227     {
0228         /* Set OFLAG pin for output mode and force out a low on the pin */
0229         base->CHANNEL[channel].SCTRL |= (TMR_SCTRL_FORCE_MASK | TMR_SCTRL_OEN_MASK);
0230 
0231         /* Counter values to generate a PWM signal */
0232         periodCount = srcClock_Hz / pwmFreqHz;
0233         highCount   = periodCount * dutyCyclePercent / 100U;
0234         lowCount    = periodCount - highCount;
0235 
0236         if (highCount > 0U)
0237         {
0238             highCount -= 1U;
0239         }
0240         if (lowCount > 0U)
0241         {
0242             lowCount -= 1U;
0243         }
0244 
0245         if ((highCount > 0xFFFFU) || (lowCount > 0xFFFFU))
0246         {
0247             /* This should not be a 16-bit overflow value. If it is, change to a larger divider for clock source. */
0248             return kStatus_Fail;
0249         }
0250 
0251         /* Setup the compare registers for PWM output */
0252         base->CHANNEL[channel].COMP1 = (uint16_t)lowCount;
0253         base->CHANNEL[channel].COMP2 = (uint16_t)highCount;
0254 
0255         /* Setup the pre-load registers for PWM output */
0256         base->CHANNEL[channel].CMPLD1 = (uint16_t)lowCount;
0257         base->CHANNEL[channel].CMPLD2 = (uint16_t)highCount;
0258 
0259         reg = base->CHANNEL[channel].CSCTRL;
0260         /* Setup the compare load control for COMP1 and COMP2.
0261          * Load COMP1 when CSCTRL[TCF2] is asserted, load COMP2 when CSCTRL[TCF1] is asserted
0262          */
0263         reg &= (uint16_t)(~(TMR_CSCTRL_CL1_MASK | TMR_CSCTRL_CL2_MASK));
0264         reg |= (TMR_CSCTRL_CL1(kQTMR_LoadOnComp2) | TMR_CSCTRL_CL2(kQTMR_LoadOnComp1));
0265         base->CHANNEL[channel].CSCTRL = reg;
0266 
0267         if (outputPolarity)
0268         {
0269             /* Invert the polarity */
0270             base->CHANNEL[channel].SCTRL |= TMR_SCTRL_OPS_MASK;
0271         }
0272         else
0273         {
0274             /* True polarity, no inversion */
0275             base->CHANNEL[channel].SCTRL &= ~(uint16_t)TMR_SCTRL_OPS_MASK;
0276         }
0277 
0278         reg = base->CHANNEL[channel].CTRL;
0279         reg &= ~(uint16_t)TMR_CTRL_OUTMODE_MASK;
0280         if (dutyCyclePercent == 100U)
0281         {
0282             /* Set OFLAG output on compare */
0283             reg |= (TMR_CTRL_LENGTH_MASK | TMR_CTRL_OUTMODE(kQTMR_SetOnCompare));
0284         }
0285         else if (dutyCyclePercent == 0U)
0286         {
0287             /* Clear OFLAG output on compare */
0288             reg |= (TMR_CTRL_LENGTH_MASK | TMR_CTRL_OUTMODE(kQTMR_ClearOnCompare));
0289         }
0290         else
0291         {
0292             /* Toggle OFLAG output using alternating compare register */
0293             reg |= (TMR_CTRL_LENGTH_MASK | TMR_CTRL_OUTMODE(kQTMR_ToggleOnAltCompareReg));
0294         }
0295 
0296         base->CHANNEL[channel].CTRL = reg;
0297 
0298         /* Get pwm duty cycle */
0299         s_qtmrGetPwmDutyCycle[channel] = dutyCyclePercent;
0300 
0301         status = kStatus_Success;
0302     }
0303     else
0304     {
0305         /* Invalid dutycycle */
0306         status = kStatus_Fail;
0307     }
0308 
0309     return status;
0310 }
0311 
0312 /*!
0313  * brief Allows the user to count the source clock cycles until a capture event arrives.
0314  *
0315  * The count is stored in the capture register.
0316  *
0317  * param base            Quad Timer peripheral base address
0318  * param channel         Quad Timer channel number
0319  * param capturePin      Pin through which we receive the input signal to trigger the capture
0320  * param inputPolarity   true: invert polarity of the input signal, false: no inversion
0321  * param reloadOnCapture true: reload the counter when an input capture occurs, false: no reload
0322  * param captureMode     Specifies which edge of the input signal  triggers a capture
0323  */
0324 void QTMR_SetupInputCapture(TMR_Type *base,
0325                             qtmr_channel_selection_t channel,
0326                             qtmr_input_source_t capturePin,
0327                             bool inputPolarity,
0328                             bool reloadOnCapture,
0329                             qtmr_input_capture_edge_t captureMode)
0330 {
0331     uint16_t reg;
0332 
0333     /* Clear the prior value for the input source for capture */
0334     reg = base->CHANNEL[channel].CTRL & (uint16_t)(~TMR_CTRL_SCS_MASK);
0335 
0336     /* Set the new input source */
0337     reg |= TMR_CTRL_SCS(capturePin);
0338     base->CHANNEL[channel].CTRL = reg;
0339 
0340     /* Clear the prior values for input polarity, capture mode. Set the external pin as input */
0341     reg = base->CHANNEL[channel].SCTRL &
0342           (uint16_t)(~(TMR_SCTRL_IPS_MASK | TMR_SCTRL_CAPTURE_MODE_MASK | TMR_SCTRL_OEN_MASK));
0343     /* Set the new values */
0344     reg |= (TMR_SCTRL_IPS(inputPolarity) | TMR_SCTRL_CAPTURE_MODE(captureMode));
0345     base->CHANNEL[channel].SCTRL = reg;
0346 
0347     /* Setup if counter should reload when a capture occurs */
0348     if (reloadOnCapture)
0349     {
0350         base->CHANNEL[channel].CSCTRL |= TMR_CSCTRL_ROC_MASK;
0351     }
0352     else
0353     {
0354         base->CHANNEL[channel].CSCTRL &= (uint16_t)(~TMR_CSCTRL_ROC_MASK);
0355     }
0356 }
0357 
0358 /*!
0359  * brief Enables the selected Quad Timer interrupts
0360  *
0361  * param base      Quad Timer peripheral base address
0362  * param channel   Quad Timer channel number
0363  * param mask      The interrupts to enable. This is a logical OR of members of the
0364  *                  enumeration ::qtmr_interrupt_enable_t
0365  */
0366 void QTMR_EnableInterrupts(TMR_Type *base, qtmr_channel_selection_t channel, uint32_t mask)
0367 {
0368     uint16_t reg;
0369 
0370     reg = base->CHANNEL[channel].SCTRL;
0371     /* Compare interrupt */
0372     if ((mask & (uint16_t)kQTMR_CompareInterruptEnable) != 0UL)
0373     {
0374         reg |= TMR_SCTRL_TCFIE_MASK;
0375     }
0376     /* Overflow interrupt */
0377     if ((mask & (uint16_t)kQTMR_OverflowInterruptEnable) != 0UL)
0378     {
0379         reg |= TMR_SCTRL_TOFIE_MASK;
0380     }
0381     /* Input edge interrupt */
0382     if ((mask & (uint16_t)kQTMR_EdgeInterruptEnable) != 0UL)
0383     {
0384         /* Restriction: Do not set both SCTRL[IEFIE] and DMA[IEFDE] */
0385         base->CHANNEL[channel].DMA &= ~(uint16_t)TMR_DMA_IEFDE_MASK;
0386         reg |= TMR_SCTRL_IEFIE_MASK;
0387     }
0388     base->CHANNEL[channel].SCTRL = reg;
0389 
0390     reg = base->CHANNEL[channel].CSCTRL;
0391     /* Compare 1 interrupt */
0392     if ((mask & (uint16_t)kQTMR_Compare1InterruptEnable) != 0UL)
0393     {
0394         reg |= TMR_CSCTRL_TCF1EN_MASK;
0395     }
0396     /* Compare 2 interrupt */
0397     if ((mask & (uint16_t)kQTMR_Compare2InterruptEnable) != 0UL)
0398     {
0399         reg |= TMR_CSCTRL_TCF2EN_MASK;
0400     }
0401     base->CHANNEL[channel].CSCTRL = reg;
0402 }
0403 
0404 /*!
0405  * brief Disables the selected Quad Timer interrupts
0406  *
0407  * param base     Quad Timer peripheral base addres
0408  * param channel  Quad Timer channel number
0409  * param mask The interrupts to enable. This is a logical OR of members of the
0410  *             enumeration ::qtmr_interrupt_enable_t
0411  */
0412 void QTMR_DisableInterrupts(TMR_Type *base, qtmr_channel_selection_t channel, uint32_t mask)
0413 {
0414     uint16_t reg;
0415 
0416     reg = base->CHANNEL[channel].SCTRL;
0417     /* Compare interrupt */
0418     if ((mask & (uint16_t)kQTMR_CompareInterruptEnable) != 0UL)
0419     {
0420         reg &= (uint16_t)(~TMR_SCTRL_TCFIE_MASK);
0421     }
0422     /* Overflow interrupt */
0423     if ((mask & (uint16_t)kQTMR_OverflowInterruptEnable) != 0UL)
0424     {
0425         reg &= (uint16_t)(~TMR_SCTRL_TOFIE_MASK);
0426     }
0427     /* Input edge interrupt */
0428     if ((mask & (uint16_t)kQTMR_EdgeInterruptEnable) != 0UL)
0429     {
0430         reg &= (uint16_t)(~TMR_SCTRL_IEFIE_MASK);
0431     }
0432     base->CHANNEL[channel].SCTRL = reg;
0433 
0434     reg = base->CHANNEL[channel].CSCTRL;
0435     /* Compare 1 interrupt */
0436     if ((mask & (uint16_t)kQTMR_Compare1InterruptEnable) != 0UL)
0437     {
0438         reg &= ~(uint16_t)TMR_CSCTRL_TCF1EN_MASK;
0439     }
0440     /* Compare 2 interrupt */
0441     if ((mask & (uint16_t)kQTMR_Compare2InterruptEnable) != 0UL)
0442     {
0443         reg &= ~(uint16_t)TMR_CSCTRL_TCF2EN_MASK;
0444     }
0445     base->CHANNEL[channel].CSCTRL = reg;
0446 }
0447 
0448 /*!
0449  * brief Gets the enabled Quad Timer interrupts
0450  *
0451  * param base    Quad Timer peripheral base address
0452  * param channel Quad Timer channel number
0453  *
0454  * return The enabled interrupts. This is the logical OR of members of the
0455  *         enumeration ::qtmr_interrupt_enable_t
0456  */
0457 uint32_t QTMR_GetEnabledInterrupts(TMR_Type *base, qtmr_channel_selection_t channel)
0458 {
0459     uint32_t enabledInterrupts = 0;
0460     uint16_t reg;
0461 
0462     reg = base->CHANNEL[channel].SCTRL;
0463     /* Compare interrupt */
0464     if ((reg & TMR_SCTRL_TCFIE_MASK) != 0U)
0465     {
0466         enabledInterrupts |= (uint32_t)kQTMR_CompareFlag;
0467     }
0468     /* Overflow interrupt */
0469     if ((reg & TMR_SCTRL_TOFIE_MASK) != 0U)
0470     {
0471         enabledInterrupts |= (uint32_t)kQTMR_OverflowInterruptEnable;
0472     }
0473     /* Input edge interrupt */
0474     if ((reg & TMR_SCTRL_IEFIE_MASK) != 0U)
0475     {
0476         enabledInterrupts |= (uint32_t)kQTMR_EdgeInterruptEnable;
0477     }
0478 
0479     reg = base->CHANNEL[channel].CSCTRL;
0480     /* Compare 1 interrupt */
0481     if ((reg & TMR_CSCTRL_TCF1EN_MASK) != 0U)
0482     {
0483         enabledInterrupts |= (uint32_t)kQTMR_Compare1InterruptEnable;
0484     }
0485     /* Compare 2 interrupt */
0486     if ((reg & TMR_CSCTRL_TCF2EN_MASK) != 0U)
0487     {
0488         enabledInterrupts |= (uint32_t)kQTMR_Compare2InterruptEnable;
0489     }
0490 
0491     return enabledInterrupts;
0492 }
0493 
0494 /*!
0495  * brief Gets the Quad Timer status flags
0496  *
0497  * param base     Quad Timer peripheral base address
0498  * param channel  Quad Timer channel number
0499  *
0500  * return The status flags. This is the logical OR of members of the
0501  *         enumeration ::qtmr_status_flags_t
0502  */
0503 uint32_t QTMR_GetStatus(TMR_Type *base, qtmr_channel_selection_t channel)
0504 {
0505     uint32_t statusFlags = 0;
0506     uint16_t reg;
0507 
0508     reg = base->CHANNEL[channel].SCTRL;
0509     /* Timer compare flag */
0510     if ((reg & TMR_SCTRL_TCF_MASK) != 0U)
0511     {
0512         statusFlags |= (uint32_t)kQTMR_CompareFlag;
0513     }
0514     /* Timer overflow flag */
0515     if ((reg & TMR_SCTRL_TOF_MASK) != 0U)
0516     {
0517         statusFlags |= (uint32_t)kQTMR_OverflowFlag;
0518     }
0519     /* Input edge flag */
0520     if ((reg & TMR_SCTRL_IEF_MASK) != 0U)
0521     {
0522         statusFlags |= (uint32_t)kQTMR_EdgeFlag;
0523     }
0524 
0525     reg = base->CHANNEL[channel].CSCTRL;
0526     /* Compare 1 flag */
0527     if ((reg & TMR_CSCTRL_TCF1_MASK) != 0U)
0528     {
0529         statusFlags |= (uint32_t)kQTMR_Compare1Flag;
0530     }
0531     /* Compare 2 flag */
0532     if ((reg & TMR_CSCTRL_TCF2_MASK) != 0U)
0533     {
0534         statusFlags |= (uint32_t)kQTMR_Compare2Flag;
0535     }
0536 
0537     return statusFlags;
0538 }
0539 
0540 /*!
0541  * brief Clears the Quad Timer status flags.
0542  *
0543  * param base     Quad Timer peripheral base address
0544  * param channel  Quad Timer channel number
0545  * param mask The status flags to clear. This is a logical OR of members of the
0546  *             enumeration ::qtmr_status_flags_t
0547  */
0548 void QTMR_ClearStatusFlags(TMR_Type *base, qtmr_channel_selection_t channel, uint32_t mask)
0549 {
0550     uint16_t reg;
0551 
0552     reg = base->CHANNEL[channel].SCTRL;
0553     /* Timer compare flag */
0554     if ((mask & (uint32_t)kQTMR_CompareFlag) != 0U)
0555     {
0556         reg &= (uint16_t)(~TMR_SCTRL_TCF_MASK);
0557     }
0558     /* Timer overflow flag */
0559     if ((mask & (uint32_t)kQTMR_OverflowFlag) != 0U)
0560     {
0561         reg &= (uint16_t)(~TMR_SCTRL_TOF_MASK);
0562     }
0563     /* Input edge flag */
0564     if ((mask & (uint32_t)kQTMR_EdgeFlag) != 0U)
0565     {
0566         reg &= (uint16_t)(~TMR_SCTRL_IEF_MASK);
0567     }
0568     base->CHANNEL[channel].SCTRL = reg;
0569 
0570     reg = base->CHANNEL[channel].CSCTRL;
0571     /* Compare 1 flag */
0572     if ((mask & (uint32_t)kQTMR_Compare1Flag) != 0U)
0573     {
0574         reg &= ~(uint16_t)TMR_CSCTRL_TCF1_MASK;
0575     }
0576     /* Compare 2 flag */
0577     if ((mask & (uint32_t)kQTMR_Compare2Flag) != 0U)
0578     {
0579         reg &= ~(uint16_t)TMR_CSCTRL_TCF2_MASK;
0580     }
0581     base->CHANNEL[channel].CSCTRL = reg;
0582 }
0583 
0584 /*!
0585  * brief Sets the timer period in ticks.
0586  *
0587  * Timers counts from initial value till it equals the count value set here. The counter
0588  * will then reinitialize to the value specified in the Load register.
0589  *
0590  * note
0591  * 1. This function will write the time period in ticks to COMP1 or COMP2 register
0592  *    depending on the count direction
0593  * 2. User can call the utility macros provided in fsl_common.h to convert to ticks
0594  * 3. This function supports cases, providing only primary source clock without secondary source clock.
0595  * 4. The load register is reset before the counter is reinitialized to the value
0596       specified in the load register.
0597  *
0598  * param base     Quad Timer peripheral base address
0599  * param channel  Quad Timer channel number
0600  * param ticks Timer period in units of ticks
0601  */
0602 void QTMR_SetTimerPeriod(TMR_Type *base, qtmr_channel_selection_t channel, uint16_t ticks)
0603 {
0604     /* Set the length bit to reinitialize the counters on a match */
0605     base->CHANNEL[channel].CTRL |= TMR_CTRL_LENGTH_MASK;
0606 
0607     /* Reset LOAD register to reinitialize the counters */
0608     base->CHANNEL[channel].LOAD &= (uint16_t)(~TMR_LOAD_LOAD_MASK);
0609 
0610     if ((base->CHANNEL[channel].CTRL & TMR_CTRL_DIR_MASK) != 0U)
0611     {
0612         /* Counting down */
0613         base->CHANNEL[channel].COMP2 = ticks - 1U;
0614     }
0615     else
0616     {
0617         /* Counting up */
0618         base->CHANNEL[channel].COMP1 = ticks - 1U;
0619     }
0620 }
0621 
0622 /*!
0623  * brief Set compare value.
0624  *
0625  * This function sets the value used for comparison with the counter value.
0626  *
0627  * param base     Quad Timer peripheral base address
0628  * param channel  Quad Timer channel number
0629  * param ticks    Timer period in units of ticks.
0630  */
0631 void QTMR_SetCompareValue(TMR_Type *base, qtmr_channel_selection_t channel, uint16_t ticks)
0632 {
0633     base->CHANNEL[channel].CTRL |= TMR_CTRL_LENGTH_MASK;
0634 
0635     if ((base->CHANNEL[channel].CTRL & TMR_CTRL_DIR_MASK) != 0U)
0636     {
0637         /* Counting down */
0638         base->CHANNEL[channel].COMP2 = ticks;
0639     }
0640     else
0641     {
0642         /* Counting up */
0643         base->CHANNEL[channel].COMP1 = ticks;
0644     }
0645 }
0646 
0647 /*!
0648  * brief Enable the Quad Timer DMA.
0649  *
0650  * param base     Quad Timer peripheral base address
0651  * param channel  Quad Timer channel number
0652  * param mask     The DMA to enable. This is a logical OR of members of the
0653  *                  enumeration ::qtmr_dma_enable_t
0654  */
0655 void QTMR_EnableDma(TMR_Type *base, qtmr_channel_selection_t channel, uint32_t mask)
0656 {
0657     uint16_t reg;
0658 
0659     reg = base->CHANNEL[channel].DMA;
0660     /* Input Edge Flag DMA Enable */
0661     if ((mask & (uint32_t)kQTMR_InputEdgeFlagDmaEnable) != 0U)
0662     {
0663         /* Restriction: Do not set both DMA[IEFDE] and SCTRL[IEFIE] */
0664         base->CHANNEL[channel].SCTRL &= (uint16_t)(~TMR_SCTRL_IEFIE_MASK);
0665         reg |= TMR_DMA_IEFDE_MASK;
0666     }
0667     /* Comparator Preload Register 1 DMA Enable */
0668     if ((mask & (uint32_t)kQTMR_ComparatorPreload1DmaEnable) != 0U)
0669     {
0670         reg |= TMR_DMA_CMPLD1DE_MASK;
0671     }
0672     /* Comparator Preload Register 2 DMA Enable */
0673     if ((mask & (uint32_t)kQTMR_ComparatorPreload2DmaEnable) != 0U)
0674     {
0675         reg |= TMR_DMA_CMPLD2DE_MASK;
0676     }
0677     base->CHANNEL[channel].DMA = reg;
0678 }
0679 
0680 /*!
0681  * brief Disable the Quad Timer DMA.
0682  *
0683  * param base     Quad Timer peripheral base address
0684  * param channel  Quad Timer channel number
0685  * param mask     The DMA to enable. This is a logical OR of members of the
0686  *                  enumeration ::qtmr_dma_enable_t
0687  */
0688 void QTMR_DisableDma(TMR_Type *base, qtmr_channel_selection_t channel, uint32_t mask)
0689 {
0690     uint16_t reg;
0691 
0692     reg = base->CHANNEL[channel].DMA;
0693     /* Input Edge Flag DMA Enable */
0694     if ((mask & (uint32_t)kQTMR_InputEdgeFlagDmaEnable) != 0U)
0695     {
0696         reg &= ~(uint16_t)TMR_DMA_IEFDE_MASK;
0697     }
0698     /* Comparator Preload Register 1 DMA Enable */
0699     if ((mask & (uint32_t)kQTMR_ComparatorPreload1DmaEnable) != 0U)
0700     {
0701         reg &= ~(uint16_t)TMR_DMA_CMPLD1DE_MASK;
0702     }
0703     /* Comparator Preload Register 2 DMA Enable */
0704     if ((mask & (uint32_t)kQTMR_ComparatorPreload2DmaEnable) != 0U)
0705     {
0706         reg &= ~(uint16_t)TMR_DMA_CMPLD2DE_MASK;
0707     }
0708     base->CHANNEL[channel].DMA = reg;
0709 }
0710 
0711 /*!
0712  * brief Set PWM output in idle status (high or low).
0713  *
0714  * Note: When the PWM is set again, the counting needs to be restarted.
0715  *
0716  * param base     Quad Timer peripheral base address
0717  * param channel  Quad Timer channel number
0718  * param idleStatus   True: PWM output is high in idle status; false: PWM output is low in idle status.
0719  */
0720 void QTMR_SetPwmOutputToIdle(TMR_Type *base, qtmr_channel_selection_t channel, bool idleStatus)
0721 {
0722     uint16_t reg = base->CHANNEL[channel].SCTRL;
0723 
0724     /* Stop qtimer channel counter first */
0725     base->CHANNEL[channel].CTRL &= (uint16_t)(~TMR_CTRL_CM_MASK);
0726     /* Clear count value */
0727     base->CHANNEL[channel].CNTR = 0U;
0728 
0729     if (0U != (reg & ((uint16_t)TMR_SCTRL_OPS_MASK)))
0730     {
0731         /* Inverted polarity. */
0732         reg |= (TMR_SCTRL_FORCE_MASK | TMR_SCTRL_VAL(!idleStatus));
0733     }
0734     else
0735     {
0736         /* True polarity. */
0737         reg |= (TMR_SCTRL_FORCE_MASK | TMR_SCTRL_VAL(idleStatus));
0738     }
0739     base->CHANNEL[channel].SCTRL = reg;
0740 
0741     s_qtmrGetPwmDutyCycle[channel] = 0x0;
0742 }
0743 
0744 /*!
0745  * brief Get the PWM channel dutycycle value.
0746  *
0747  * param base     Quad Timer peripheral base address
0748  * param channel  Quad Timer channel number
0749  *
0750  * return Current channel dutycycle value.
0751  */
0752 uint8_t QTMR_GetPwmChannelStatus(TMR_Type *base, qtmr_channel_selection_t channel)
0753 {
0754     return s_qtmrGetPwmDutyCycle[channel];
0755 }
0756 
0757 /*!
0758  * brief This function set the value of the prescaler on QTimer channels.
0759  *
0760  * param base         Quad Timer peripheral base address
0761  * param channel      Quad Timer channel number
0762  * param prescaler    Set prescaler value
0763  */
0764 void QTMR_SetPwmClockMode(TMR_Type *base, qtmr_channel_selection_t channel, qtmr_primary_count_source_t prescaler)
0765 {
0766     assert((uint32_t)prescaler > 7U);
0767 
0768     uint16_t reg = base->CHANNEL[channel].CTRL;
0769 
0770     /* Clear qtimer channel counter mode */
0771     base->CHANNEL[channel].CTRL = reg & (uint16_t)(~TMR_CTRL_CM_MASK);
0772 
0773     /* Set the new clock prescaler value and restore qtimer channel counter mode*/
0774     reg &= (uint16_t)(~(TMR_CTRL_PCS_MASK));
0775     reg |= TMR_CTRL_PCS(prescaler);
0776     base->CHANNEL[channel].CTRL = reg;
0777 }