Kevin Kadooka / mbed-dev

Fork of mbed-dev by mbed official

Committer:
kkado
Date:
Tue Jun 20 11:06:37 2017 +0000
Revision:
167:356ef919c855
Parent:
154:37f96f9d4de2
Build 137 with reduced HSE timeout

Who changed what in which revision?

UserRevisionLine numberNew contents of line
<> 154:37f96f9d4de2 1 /*
<> 154:37f96f9d4de2 2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
<> 154:37f96f9d4de2 3 * All rights reserved.
<> 154:37f96f9d4de2 4 *
<> 154:37f96f9d4de2 5 * Redistribution and use in source and binary forms, with or without modification,
<> 154:37f96f9d4de2 6 * are permitted provided that the following conditions are met:
<> 154:37f96f9d4de2 7 *
<> 154:37f96f9d4de2 8 * o Redistributions of source code must retain the above copyright notice, this list
<> 154:37f96f9d4de2 9 * of conditions and the following disclaimer.
<> 154:37f96f9d4de2 10 *
<> 154:37f96f9d4de2 11 * o Redistributions in binary form must reproduce the above copyright notice, this
<> 154:37f96f9d4de2 12 * list of conditions and the following disclaimer in the documentation and/or
<> 154:37f96f9d4de2 13 * other materials provided with the distribution.
<> 154:37f96f9d4de2 14 *
<> 154:37f96f9d4de2 15 * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
<> 154:37f96f9d4de2 16 * contributors may be used to endorse or promote products derived from this
<> 154:37f96f9d4de2 17 * software without specific prior written permission.
<> 154:37f96f9d4de2 18 *
<> 154:37f96f9d4de2 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
<> 154:37f96f9d4de2 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
<> 154:37f96f9d4de2 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
<> 154:37f96f9d4de2 22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
<> 154:37f96f9d4de2 23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
<> 154:37f96f9d4de2 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
<> 154:37f96f9d4de2 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
<> 154:37f96f9d4de2 26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
<> 154:37f96f9d4de2 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
<> 154:37f96f9d4de2 28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<> 154:37f96f9d4de2 29 */
<> 154:37f96f9d4de2 30
<> 154:37f96f9d4de2 31 #include "fsl_ftm.h"
<> 154:37f96f9d4de2 32
<> 154:37f96f9d4de2 33 /*******************************************************************************
<> 154:37f96f9d4de2 34 * Prototypes
<> 154:37f96f9d4de2 35 ******************************************************************************/
<> 154:37f96f9d4de2 36 /*!
<> 154:37f96f9d4de2 37 * @brief Gets the instance from the base address
<> 154:37f96f9d4de2 38 *
<> 154:37f96f9d4de2 39 * @param base FTM peripheral base address
<> 154:37f96f9d4de2 40 *
<> 154:37f96f9d4de2 41 * @return The FTM instance
<> 154:37f96f9d4de2 42 */
<> 154:37f96f9d4de2 43 static uint32_t FTM_GetInstance(FTM_Type *base);
<> 154:37f96f9d4de2 44
<> 154:37f96f9d4de2 45 /*!
<> 154:37f96f9d4de2 46 * @brief Sets the FTM register PWM synchronization method
<> 154:37f96f9d4de2 47 *
<> 154:37f96f9d4de2 48 * This function will set the necessary bits for the PWM synchronization mode that
<> 154:37f96f9d4de2 49 * user wishes to use.
<> 154:37f96f9d4de2 50 *
<> 154:37f96f9d4de2 51 * @param base FTM peripheral base address
<> 154:37f96f9d4de2 52 * @param syncMethod Syncronization methods to use to update buffered registers. This is a logical
<> 154:37f96f9d4de2 53 * OR of members of the enumeration ::ftm_pwm_sync_method_t
<> 154:37f96f9d4de2 54 */
<> 154:37f96f9d4de2 55 static void FTM_SetPwmSync(FTM_Type *base, uint32_t syncMethod);
<> 154:37f96f9d4de2 56
<> 154:37f96f9d4de2 57 /*!
<> 154:37f96f9d4de2 58 * @brief Sets the reload points used as loading points for register update
<> 154:37f96f9d4de2 59 *
<> 154:37f96f9d4de2 60 * This function will set the necessary bits based on what the user wishes to use as loading
<> 154:37f96f9d4de2 61 * points for FTM register update. When using this it is not required to use PWM synchnronization.
<> 154:37f96f9d4de2 62 *
<> 154:37f96f9d4de2 63 * @param base FTM peripheral base address
<> 154:37f96f9d4de2 64 * @param reloadPoints FTM reload points. This is a logical OR of members of the
<> 154:37f96f9d4de2 65 * enumeration ::ftm_reload_point_t
<> 154:37f96f9d4de2 66 */
<> 154:37f96f9d4de2 67 static void FTM_SetReloadPoints(FTM_Type *base, uint32_t reloadPoints);
<> 154:37f96f9d4de2 68
<> 154:37f96f9d4de2 69 /*******************************************************************************
<> 154:37f96f9d4de2 70 * Variables
<> 154:37f96f9d4de2 71 ******************************************************************************/
<> 154:37f96f9d4de2 72 /*! @brief Pointers to FTM bases for each instance. */
<> 154:37f96f9d4de2 73 static FTM_Type *const s_ftmBases[] = FTM_BASE_PTRS;
<> 154:37f96f9d4de2 74
<> 154:37f96f9d4de2 75 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
<> 154:37f96f9d4de2 76 /*! @brief Pointers to FTM clocks for each instance. */
<> 154:37f96f9d4de2 77 static const clock_ip_name_t s_ftmClocks[] = FTM_CLOCKS;
<> 154:37f96f9d4de2 78 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
<> 154:37f96f9d4de2 79
<> 154:37f96f9d4de2 80 /*******************************************************************************
<> 154:37f96f9d4de2 81 * Code
<> 154:37f96f9d4de2 82 ******************************************************************************/
<> 154:37f96f9d4de2 83 static uint32_t FTM_GetInstance(FTM_Type *base)
<> 154:37f96f9d4de2 84 {
<> 154:37f96f9d4de2 85 uint32_t instance;
<> 154:37f96f9d4de2 86 uint32_t ftmArrayCount = (sizeof(s_ftmBases) / sizeof(s_ftmBases[0]));
<> 154:37f96f9d4de2 87
<> 154:37f96f9d4de2 88 /* Find the instance index from base address mappings. */
<> 154:37f96f9d4de2 89 for (instance = 0; instance < ftmArrayCount; instance++)
<> 154:37f96f9d4de2 90 {
<> 154:37f96f9d4de2 91 if (s_ftmBases[instance] == base)
<> 154:37f96f9d4de2 92 {
<> 154:37f96f9d4de2 93 break;
<> 154:37f96f9d4de2 94 }
<> 154:37f96f9d4de2 95 }
<> 154:37f96f9d4de2 96
<> 154:37f96f9d4de2 97 assert(instance < ftmArrayCount);
<> 154:37f96f9d4de2 98
<> 154:37f96f9d4de2 99 return instance;
<> 154:37f96f9d4de2 100 }
<> 154:37f96f9d4de2 101
<> 154:37f96f9d4de2 102 static void FTM_SetPwmSync(FTM_Type *base, uint32_t syncMethod)
<> 154:37f96f9d4de2 103 {
<> 154:37f96f9d4de2 104 uint8_t chnlNumber = 0;
<> 154:37f96f9d4de2 105 uint32_t reg = 0, syncReg = 0;
<> 154:37f96f9d4de2 106
<> 154:37f96f9d4de2 107 syncReg = base->SYNC;
<> 154:37f96f9d4de2 108 /* Enable PWM synchronization of output mask register */
<> 154:37f96f9d4de2 109 syncReg |= FTM_SYNC_SYNCHOM_MASK;
<> 154:37f96f9d4de2 110
<> 154:37f96f9d4de2 111 reg = base->COMBINE;
<> 154:37f96f9d4de2 112 for (chnlNumber = 0; chnlNumber < (FSL_FEATURE_FTM_CHANNEL_COUNTn(base) / 2); chnlNumber++)
<> 154:37f96f9d4de2 113 {
<> 154:37f96f9d4de2 114 /* Enable PWM synchronization of registers C(n)V and C(n+1)V */
<> 154:37f96f9d4de2 115 reg |= (1U << (FTM_COMBINE_SYNCEN0_SHIFT + (FTM_COMBINE_COMBINE1_SHIFT * chnlNumber)));
<> 154:37f96f9d4de2 116 }
<> 154:37f96f9d4de2 117 base->COMBINE = reg;
<> 154:37f96f9d4de2 118
<> 154:37f96f9d4de2 119 reg = base->SYNCONF;
<> 154:37f96f9d4de2 120
<> 154:37f96f9d4de2 121 /* Use enhanced PWM synchronization method. Use PWM sync to update register values */
<> 154:37f96f9d4de2 122 reg |= (FTM_SYNCONF_SYNCMODE_MASK | FTM_SYNCONF_CNTINC_MASK | FTM_SYNCONF_INVC_MASK | FTM_SYNCONF_SWOC_MASK);
<> 154:37f96f9d4de2 123
<> 154:37f96f9d4de2 124 if (syncMethod & FTM_SYNC_SWSYNC_MASK)
<> 154:37f96f9d4de2 125 {
<> 154:37f96f9d4de2 126 /* Enable needed bits for software trigger to update registers with its buffer value */
<> 154:37f96f9d4de2 127 reg |= (FTM_SYNCONF_SWRSTCNT_MASK | FTM_SYNCONF_SWWRBUF_MASK | FTM_SYNCONF_SWINVC_MASK |
<> 154:37f96f9d4de2 128 FTM_SYNCONF_SWSOC_MASK | FTM_SYNCONF_SWOM_MASK);
<> 154:37f96f9d4de2 129 }
<> 154:37f96f9d4de2 130
<> 154:37f96f9d4de2 131 if (syncMethod & (FTM_SYNC_TRIG0_MASK | FTM_SYNC_TRIG1_MASK | FTM_SYNC_TRIG2_MASK))
<> 154:37f96f9d4de2 132 {
<> 154:37f96f9d4de2 133 /* Enable needed bits for hardware trigger to update registers with its buffer value */
<> 154:37f96f9d4de2 134 reg |= (FTM_SYNCONF_HWRSTCNT_MASK | FTM_SYNCONF_HWWRBUF_MASK | FTM_SYNCONF_HWINVC_MASK |
<> 154:37f96f9d4de2 135 FTM_SYNCONF_HWSOC_MASK | FTM_SYNCONF_HWOM_MASK);
<> 154:37f96f9d4de2 136
<> 154:37f96f9d4de2 137 /* Enable the appropriate hardware trigger that is used for PWM sync */
<> 154:37f96f9d4de2 138 if (syncMethod & FTM_SYNC_TRIG0_MASK)
<> 154:37f96f9d4de2 139 {
<> 154:37f96f9d4de2 140 syncReg |= FTM_SYNC_TRIG0_MASK;
<> 154:37f96f9d4de2 141 }
<> 154:37f96f9d4de2 142 if (syncMethod & FTM_SYNC_TRIG1_MASK)
<> 154:37f96f9d4de2 143 {
<> 154:37f96f9d4de2 144 syncReg |= FTM_SYNC_TRIG1_MASK;
<> 154:37f96f9d4de2 145 }
<> 154:37f96f9d4de2 146 if (syncMethod & FTM_SYNC_TRIG2_MASK)
<> 154:37f96f9d4de2 147 {
<> 154:37f96f9d4de2 148 syncReg |= FTM_SYNC_TRIG2_MASK;
<> 154:37f96f9d4de2 149 }
<> 154:37f96f9d4de2 150 }
<> 154:37f96f9d4de2 151
<> 154:37f96f9d4de2 152 /* Write back values to the SYNC register */
<> 154:37f96f9d4de2 153 base->SYNC = syncReg;
<> 154:37f96f9d4de2 154
<> 154:37f96f9d4de2 155 /* Write the PWM synch values to the SYNCONF register */
<> 154:37f96f9d4de2 156 base->SYNCONF = reg;
<> 154:37f96f9d4de2 157 }
<> 154:37f96f9d4de2 158
<> 154:37f96f9d4de2 159 static void FTM_SetReloadPoints(FTM_Type *base, uint32_t reloadPoints)
<> 154:37f96f9d4de2 160 {
<> 154:37f96f9d4de2 161 uint32_t chnlNumber = 0;
<> 154:37f96f9d4de2 162 uint32_t reg = 0;
<> 154:37f96f9d4de2 163
<> 154:37f96f9d4de2 164 /* Need CNTINC bit to be 1 for CNTIN register to update with its buffer value on reload */
<> 154:37f96f9d4de2 165 base->SYNCONF |= FTM_SYNCONF_CNTINC_MASK;
<> 154:37f96f9d4de2 166
<> 154:37f96f9d4de2 167 reg = base->COMBINE;
<> 154:37f96f9d4de2 168 for (chnlNumber = 0; chnlNumber < (FSL_FEATURE_FTM_CHANNEL_COUNTn(base) / 2); chnlNumber++)
<> 154:37f96f9d4de2 169 {
<> 154:37f96f9d4de2 170 /* Need SYNCEN bit to be 1 for CnV reg to update with its buffer value on reload */
<> 154:37f96f9d4de2 171 reg |= (1U << (FTM_COMBINE_SYNCEN0_SHIFT + (FTM_COMBINE_COMBINE1_SHIFT * chnlNumber)));
<> 154:37f96f9d4de2 172 }
<> 154:37f96f9d4de2 173 base->COMBINE = reg;
<> 154:37f96f9d4de2 174
<> 154:37f96f9d4de2 175 /* Set the reload points */
<> 154:37f96f9d4de2 176 reg = base->PWMLOAD;
<> 154:37f96f9d4de2 177
<> 154:37f96f9d4de2 178 /* Enable the selected channel match reload points */
<> 154:37f96f9d4de2 179 reg &= ~((1U << FSL_FEATURE_FTM_CHANNEL_COUNTn(base)) - 1);
<> 154:37f96f9d4de2 180 reg |= (reloadPoints & ((1U << FSL_FEATURE_FTM_CHANNEL_COUNTn(base)) - 1));
<> 154:37f96f9d4de2 181
<> 154:37f96f9d4de2 182 #if defined(FSL_FEATURE_FTM_HAS_HALFCYCLE_RELOAD) && (FSL_FEATURE_FTM_HAS_HALFCYCLE_RELOAD)
<> 154:37f96f9d4de2 183 /* Enable half cycle match as a reload point */
<> 154:37f96f9d4de2 184 if (reloadPoints & kFTM_HalfCycMatch)
<> 154:37f96f9d4de2 185 {
<> 154:37f96f9d4de2 186 reg |= FTM_PWMLOAD_HCSEL_MASK;
<> 154:37f96f9d4de2 187 }
<> 154:37f96f9d4de2 188 else
<> 154:37f96f9d4de2 189 {
<> 154:37f96f9d4de2 190 reg &= ~FTM_PWMLOAD_HCSEL_MASK;
<> 154:37f96f9d4de2 191 }
<> 154:37f96f9d4de2 192 #endif /* FSL_FEATURE_FTM_HAS_HALFCYCLE_RELOAD */
<> 154:37f96f9d4de2 193
<> 154:37f96f9d4de2 194 base->PWMLOAD = reg;
<> 154:37f96f9d4de2 195
<> 154:37f96f9d4de2 196 /* These reload points are used when counter is in up-down counting mode */
<> 154:37f96f9d4de2 197 reg = base->SYNC;
<> 154:37f96f9d4de2 198 if (reloadPoints & kFTM_CntMax)
<> 154:37f96f9d4de2 199 {
<> 154:37f96f9d4de2 200 /* Reload when counter turns from up to down */
<> 154:37f96f9d4de2 201 reg |= FTM_SYNC_CNTMAX_MASK;
<> 154:37f96f9d4de2 202 }
<> 154:37f96f9d4de2 203 else
<> 154:37f96f9d4de2 204 {
<> 154:37f96f9d4de2 205 reg &= ~FTM_SYNC_CNTMAX_MASK;
<> 154:37f96f9d4de2 206 }
<> 154:37f96f9d4de2 207
<> 154:37f96f9d4de2 208 if (reloadPoints & kFTM_CntMin)
<> 154:37f96f9d4de2 209 {
<> 154:37f96f9d4de2 210 /* Reload when counter turns from down to up */
<> 154:37f96f9d4de2 211 reg |= FTM_SYNC_CNTMIN_MASK;
<> 154:37f96f9d4de2 212 }
<> 154:37f96f9d4de2 213 else
<> 154:37f96f9d4de2 214 {
<> 154:37f96f9d4de2 215 reg &= ~FTM_SYNC_CNTMIN_MASK;
<> 154:37f96f9d4de2 216 }
<> 154:37f96f9d4de2 217 base->SYNC = reg;
<> 154:37f96f9d4de2 218 }
<> 154:37f96f9d4de2 219
<> 154:37f96f9d4de2 220 status_t FTM_Init(FTM_Type *base, const ftm_config_t *config)
<> 154:37f96f9d4de2 221 {
<> 154:37f96f9d4de2 222 assert(config);
<> 154:37f96f9d4de2 223
<> 154:37f96f9d4de2 224 uint32_t reg;
<> 154:37f96f9d4de2 225
<> 154:37f96f9d4de2 226 if (!(config->pwmSyncMode &
<> 154:37f96f9d4de2 227 (FTM_SYNC_TRIG0_MASK | FTM_SYNC_TRIG1_MASK | FTM_SYNC_TRIG2_MASK | FTM_SYNC_SWSYNC_MASK)))
<> 154:37f96f9d4de2 228 {
<> 154:37f96f9d4de2 229 /* Invalid PWM sync mode */
<> 154:37f96f9d4de2 230 return kStatus_Fail;
<> 154:37f96f9d4de2 231 }
<> 154:37f96f9d4de2 232
<> 154:37f96f9d4de2 233 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
<> 154:37f96f9d4de2 234 /* Ungate the FTM clock*/
<> 154:37f96f9d4de2 235 CLOCK_EnableClock(s_ftmClocks[FTM_GetInstance(base)]);
<> 154:37f96f9d4de2 236 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
<> 154:37f96f9d4de2 237
<> 154:37f96f9d4de2 238 /* Configure the fault mode, enable FTM mode and disable write protection */
<> 154:37f96f9d4de2 239 base->MODE = FTM_MODE_FAULTM(config->faultMode) | FTM_MODE_FTMEN_MASK | FTM_MODE_WPDIS_MASK;
<> 154:37f96f9d4de2 240
<> 154:37f96f9d4de2 241 /* Configure the update mechanism for buffered registers */
<> 154:37f96f9d4de2 242 FTM_SetPwmSync(base, config->pwmSyncMode);
<> 154:37f96f9d4de2 243
<> 154:37f96f9d4de2 244 /* Setup intermediate register reload points */
<> 154:37f96f9d4de2 245 FTM_SetReloadPoints(base, config->reloadPoints);
<> 154:37f96f9d4de2 246
<> 154:37f96f9d4de2 247 /* Set the clock prescale factor */
<> 154:37f96f9d4de2 248 base->SC = FTM_SC_PS(config->prescale);
<> 154:37f96f9d4de2 249
<> 154:37f96f9d4de2 250 /* Setup the counter operation */
<> 154:37f96f9d4de2 251 base->CONF = (FTM_CONF_BDMMODE(config->bdmMode) | FTM_CONF_GTBEEN(config->useGlobalTimeBase));
<> 154:37f96f9d4de2 252
<> 154:37f96f9d4de2 253 /* Initial state of channel output */
<> 154:37f96f9d4de2 254 base->OUTINIT = config->chnlInitState;
<> 154:37f96f9d4de2 255
<> 154:37f96f9d4de2 256 /* Channel polarity */
<> 154:37f96f9d4de2 257 base->POL = config->chnlPolarity;
<> 154:37f96f9d4de2 258
<> 154:37f96f9d4de2 259 /* Set the external trigger sources */
<> 154:37f96f9d4de2 260 base->EXTTRIG = config->extTriggers;
<> 154:37f96f9d4de2 261 #if defined(FSL_FEATURE_FTM_HAS_RELOAD_INITIALIZATION_TRIGGER) && (FSL_FEATURE_FTM_HAS_RELOAD_INITIALIZATION_TRIGGER)
<> 154:37f96f9d4de2 262 if (config->extTriggers & kFTM_ReloadInitTrigger)
<> 154:37f96f9d4de2 263 {
<> 154:37f96f9d4de2 264 base->CONF |= FTM_CONF_ITRIGR_MASK;
<> 154:37f96f9d4de2 265 }
<> 154:37f96f9d4de2 266 else
<> 154:37f96f9d4de2 267 {
<> 154:37f96f9d4de2 268 base->CONF &= ~FTM_CONF_ITRIGR_MASK;
<> 154:37f96f9d4de2 269 }
<> 154:37f96f9d4de2 270 #endif /* FSL_FEATURE_FTM_HAS_RELOAD_INITIALIZATION_TRIGGER */
<> 154:37f96f9d4de2 271
<> 154:37f96f9d4de2 272 /* FTM deadtime insertion control */
<> 154:37f96f9d4de2 273 base->DEADTIME = (0u |
<> 154:37f96f9d4de2 274 #if defined(FSL_FEATURE_FTM_HAS_EXTENDED_DEADTIME_VALUE) && (FSL_FEATURE_FTM_HAS_EXTENDED_DEADTIME_VALUE)
<> 154:37f96f9d4de2 275 /* Has extended deadtime value register) */
<> 154:37f96f9d4de2 276 FTM_DEADTIME_DTVALEX(config->deadTimeValue >> 6) |
<> 154:37f96f9d4de2 277 #endif /* FSL_FEATURE_FTM_HAS_EXTENDED_DEADTIME_VALUE */
<> 154:37f96f9d4de2 278 FTM_DEADTIME_DTPS(config->deadTimePrescale) |
<> 154:37f96f9d4de2 279 FTM_DEADTIME_DTVAL(config->deadTimeValue));
<> 154:37f96f9d4de2 280
<> 154:37f96f9d4de2 281 /* FTM fault filter value */
<> 154:37f96f9d4de2 282 reg = base->FLTCTRL;
<> 154:37f96f9d4de2 283 reg &= ~FTM_FLTCTRL_FFVAL_MASK;
<> 154:37f96f9d4de2 284 reg |= FTM_FLTCTRL_FFVAL(config->faultFilterValue);
<> 154:37f96f9d4de2 285 base->FLTCTRL = reg;
<> 154:37f96f9d4de2 286
<> 154:37f96f9d4de2 287 return kStatus_Success;
<> 154:37f96f9d4de2 288 }
<> 154:37f96f9d4de2 289
<> 154:37f96f9d4de2 290 void FTM_Deinit(FTM_Type *base)
<> 154:37f96f9d4de2 291 {
<> 154:37f96f9d4de2 292 /* Set clock source to none to disable counter */
<> 154:37f96f9d4de2 293 base->SC &= ~(FTM_SC_CLKS_MASK);
<> 154:37f96f9d4de2 294
<> 154:37f96f9d4de2 295 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
<> 154:37f96f9d4de2 296 /* Gate the FTM clock */
<> 154:37f96f9d4de2 297 CLOCK_DisableClock(s_ftmClocks[FTM_GetInstance(base)]);
<> 154:37f96f9d4de2 298 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
<> 154:37f96f9d4de2 299 }
<> 154:37f96f9d4de2 300
<> 154:37f96f9d4de2 301 void FTM_GetDefaultConfig(ftm_config_t *config)
<> 154:37f96f9d4de2 302 {
<> 154:37f96f9d4de2 303 assert(config);
<> 154:37f96f9d4de2 304
<> 154:37f96f9d4de2 305 /* Divide FTM clock by 1 */
<> 154:37f96f9d4de2 306 config->prescale = kFTM_Prescale_Divide_1;
<> 154:37f96f9d4de2 307 /* FTM behavior in BDM mode */
<> 154:37f96f9d4de2 308 config->bdmMode = kFTM_BdmMode_0;
<> 154:37f96f9d4de2 309 /* Software trigger will be used to update registers */
<> 154:37f96f9d4de2 310 config->pwmSyncMode = kFTM_SoftwareTrigger;
<> 154:37f96f9d4de2 311 /* No intermediate register load */
<> 154:37f96f9d4de2 312 config->reloadPoints = 0;
<> 154:37f96f9d4de2 313 /* Fault control disabled for all channels */
<> 154:37f96f9d4de2 314 config->faultMode = kFTM_Fault_Disable;
<> 154:37f96f9d4de2 315 /* Disable the fault filter */
<> 154:37f96f9d4de2 316 config->faultFilterValue = 0;
<> 154:37f96f9d4de2 317 /* Divide the system clock by 1 */
<> 154:37f96f9d4de2 318 config->deadTimePrescale = kFTM_Deadtime_Prescale_1;
<> 154:37f96f9d4de2 319 /* No counts are inserted */
<> 154:37f96f9d4de2 320 config->deadTimeValue = 0;
<> 154:37f96f9d4de2 321 /* No external trigger */
<> 154:37f96f9d4de2 322 config->extTriggers = 0;
<> 154:37f96f9d4de2 323 /* Initialization value is 0 for all channels */
<> 154:37f96f9d4de2 324 config->chnlInitState = 0;
<> 154:37f96f9d4de2 325 /* Active high polarity for all channels */
<> 154:37f96f9d4de2 326 config->chnlPolarity = 0;
<> 154:37f96f9d4de2 327 /* Use internal FTM counter as timebase */
<> 154:37f96f9d4de2 328 config->useGlobalTimeBase = false;
<> 154:37f96f9d4de2 329 }
<> 154:37f96f9d4de2 330
<> 154:37f96f9d4de2 331 status_t FTM_SetupPwm(FTM_Type *base,
<> 154:37f96f9d4de2 332 const ftm_chnl_pwm_signal_param_t *chnlParams,
<> 154:37f96f9d4de2 333 uint8_t numOfChnls,
<> 154:37f96f9d4de2 334 ftm_pwm_mode_t mode,
<> 154:37f96f9d4de2 335 uint32_t pwmFreq_Hz,
<> 154:37f96f9d4de2 336 uint32_t srcClock_Hz)
<> 154:37f96f9d4de2 337 {
<> 154:37f96f9d4de2 338 assert(chnlParams);
<> 154:37f96f9d4de2 339 assert(srcClock_Hz);
<> 154:37f96f9d4de2 340 assert(pwmFreq_Hz);
<> 154:37f96f9d4de2 341 assert(numOfChnls);
<> 154:37f96f9d4de2 342
<> 154:37f96f9d4de2 343 uint32_t mod, reg;
<> 154:37f96f9d4de2 344 uint32_t ftmClock = (srcClock_Hz / (1U << (base->SC & FTM_SC_PS_MASK)));
<> 154:37f96f9d4de2 345 uint16_t cnv, cnvFirstEdge;
<> 154:37f96f9d4de2 346 uint8_t i;
<> 154:37f96f9d4de2 347
<> 154:37f96f9d4de2 348 switch (mode)
<> 154:37f96f9d4de2 349 {
<> 154:37f96f9d4de2 350 case kFTM_EdgeAlignedPwm:
<> 154:37f96f9d4de2 351 case kFTM_CombinedPwm:
<> 154:37f96f9d4de2 352 base->SC &= ~FTM_SC_CPWMS_MASK;
<> 154:37f96f9d4de2 353 mod = (ftmClock / pwmFreq_Hz) - 1;
<> 154:37f96f9d4de2 354 break;
<> 154:37f96f9d4de2 355 case kFTM_CenterAlignedPwm:
<> 154:37f96f9d4de2 356 base->SC |= FTM_SC_CPWMS_MASK;
<> 154:37f96f9d4de2 357 mod = ftmClock / (pwmFreq_Hz * 2);
<> 154:37f96f9d4de2 358 break;
<> 154:37f96f9d4de2 359 default:
<> 154:37f96f9d4de2 360 return kStatus_Fail;
<> 154:37f96f9d4de2 361 }
<> 154:37f96f9d4de2 362
<> 154:37f96f9d4de2 363 /* Return an error in case we overflow the registers, probably would require changing
<> 154:37f96f9d4de2 364 * clock source to get the desired frequency */
<> 154:37f96f9d4de2 365 if (mod > 65535U)
<> 154:37f96f9d4de2 366 {
<> 154:37f96f9d4de2 367 return kStatus_Fail;
<> 154:37f96f9d4de2 368 }
<> 154:37f96f9d4de2 369 /* Set the PWM period */
<> 154:37f96f9d4de2 370 base->MOD = mod;
<> 154:37f96f9d4de2 371
<> 154:37f96f9d4de2 372 /* Setup each FTM channel */
<> 154:37f96f9d4de2 373 for (i = 0; i < numOfChnls; i++)
<> 154:37f96f9d4de2 374 {
<> 154:37f96f9d4de2 375 /* Return error if requested dutycycle is greater than the max allowed */
<> 154:37f96f9d4de2 376 if (chnlParams->dutyCyclePercent > 100)
<> 154:37f96f9d4de2 377 {
<> 154:37f96f9d4de2 378 return kStatus_Fail;
<> 154:37f96f9d4de2 379 }
<> 154:37f96f9d4de2 380
<> 154:37f96f9d4de2 381 if ((mode == kFTM_EdgeAlignedPwm) || (mode == kFTM_CenterAlignedPwm))
<> 154:37f96f9d4de2 382 {
<> 154:37f96f9d4de2 383 /* Clear the current mode and edge level bits */
<> 154:37f96f9d4de2 384 reg = base->CONTROLS[chnlParams->chnlNumber].CnSC;
<> 154:37f96f9d4de2 385 reg &= ~(FTM_CnSC_MSA_MASK | FTM_CnSC_MSB_MASK | FTM_CnSC_ELSA_MASK | FTM_CnSC_ELSB_MASK);
<> 154:37f96f9d4de2 386
<> 154:37f96f9d4de2 387 /* Setup the active level */
<> 154:37f96f9d4de2 388 reg |= (uint32_t)(chnlParams->level << FTM_CnSC_ELSA_SHIFT);
<> 154:37f96f9d4de2 389
<> 154:37f96f9d4de2 390 /* Edge-aligned mode needs MSB to be 1, don't care for Center-aligned mode */
<> 154:37f96f9d4de2 391 reg |= FTM_CnSC_MSB(1U);
<> 154:37f96f9d4de2 392
<> 154:37f96f9d4de2 393 /* Update the mode and edge level */
<> 154:37f96f9d4de2 394 base->CONTROLS[chnlParams->chnlNumber].CnSC = reg;
<> 154:37f96f9d4de2 395
<> 154:37f96f9d4de2 396 if (chnlParams->dutyCyclePercent == 0)
<> 154:37f96f9d4de2 397 {
<> 154:37f96f9d4de2 398 /* Signal stays low */
<> 154:37f96f9d4de2 399 cnv = 0;
<> 154:37f96f9d4de2 400 }
<> 154:37f96f9d4de2 401 else
<> 154:37f96f9d4de2 402 {
<> 154:37f96f9d4de2 403 cnv = (mod * chnlParams->dutyCyclePercent) / 100;
<> 154:37f96f9d4de2 404 /* For 100% duty cycle */
<> 154:37f96f9d4de2 405 if (cnv >= mod)
<> 154:37f96f9d4de2 406 {
<> 154:37f96f9d4de2 407 cnv = mod + 1;
<> 154:37f96f9d4de2 408 }
<> 154:37f96f9d4de2 409 }
<> 154:37f96f9d4de2 410
<> 154:37f96f9d4de2 411 base->CONTROLS[chnlParams->chnlNumber].CnV = cnv;
<> 154:37f96f9d4de2 412 #if defined(FSL_FEATURE_FTM_HAS_ENABLE_PWM_OUTPUT) && (FSL_FEATURE_FTM_HAS_ENABLE_PWM_OUTPUT)
<> 154:37f96f9d4de2 413 /* Set to output mode */
<> 154:37f96f9d4de2 414 FTM_SetPwmOutputEnable(base, chnlParams->chnlNumber, true);
<> 154:37f96f9d4de2 415 #endif
<> 154:37f96f9d4de2 416 }
<> 154:37f96f9d4de2 417 else
<> 154:37f96f9d4de2 418 {
<> 154:37f96f9d4de2 419 /* This check is added for combined mode as the channel number should be the pair number */
<> 154:37f96f9d4de2 420 if (chnlParams->chnlNumber >= (FSL_FEATURE_FTM_CHANNEL_COUNTn(base) / 2))
<> 154:37f96f9d4de2 421 {
<> 154:37f96f9d4de2 422 return kStatus_Fail;
<> 154:37f96f9d4de2 423 }
<> 154:37f96f9d4de2 424
<> 154:37f96f9d4de2 425 /* Return error if requested value is greater than the max allowed */
<> 154:37f96f9d4de2 426 if (chnlParams->firstEdgeDelayPercent > 100)
<> 154:37f96f9d4de2 427 {
<> 154:37f96f9d4de2 428 return kStatus_Fail;
<> 154:37f96f9d4de2 429 }
<> 154:37f96f9d4de2 430
<> 154:37f96f9d4de2 431 /* Configure delay of the first edge */
<> 154:37f96f9d4de2 432 if (chnlParams->firstEdgeDelayPercent == 0)
<> 154:37f96f9d4de2 433 {
<> 154:37f96f9d4de2 434 /* No delay for the first edge */
<> 154:37f96f9d4de2 435 cnvFirstEdge = 0;
<> 154:37f96f9d4de2 436 }
<> 154:37f96f9d4de2 437 else
<> 154:37f96f9d4de2 438 {
<> 154:37f96f9d4de2 439 cnvFirstEdge = (mod * chnlParams->firstEdgeDelayPercent) / 100;
<> 154:37f96f9d4de2 440 }
<> 154:37f96f9d4de2 441
<> 154:37f96f9d4de2 442 /* Configure dutycycle */
<> 154:37f96f9d4de2 443 if (chnlParams->dutyCyclePercent == 0)
<> 154:37f96f9d4de2 444 {
<> 154:37f96f9d4de2 445 /* Signal stays low */
<> 154:37f96f9d4de2 446 cnv = 0;
<> 154:37f96f9d4de2 447 cnvFirstEdge = 0;
<> 154:37f96f9d4de2 448 }
<> 154:37f96f9d4de2 449 else
<> 154:37f96f9d4de2 450 {
<> 154:37f96f9d4de2 451 cnv = (mod * chnlParams->dutyCyclePercent) / 100;
<> 154:37f96f9d4de2 452 /* For 100% duty cycle */
<> 154:37f96f9d4de2 453 if (cnv >= mod)
<> 154:37f96f9d4de2 454 {
<> 154:37f96f9d4de2 455 cnv = mod + 1;
<> 154:37f96f9d4de2 456 }
<> 154:37f96f9d4de2 457 }
<> 154:37f96f9d4de2 458
<> 154:37f96f9d4de2 459 /* Clear the current mode and edge level bits for channel n */
<> 154:37f96f9d4de2 460 reg = base->CONTROLS[chnlParams->chnlNumber * 2].CnSC;
<> 154:37f96f9d4de2 461 reg &= ~(FTM_CnSC_MSA_MASK | FTM_CnSC_MSB_MASK | FTM_CnSC_ELSA_MASK | FTM_CnSC_ELSB_MASK);
<> 154:37f96f9d4de2 462
<> 154:37f96f9d4de2 463 /* Setup the active level for channel n */
<> 154:37f96f9d4de2 464 reg |= (uint32_t)(chnlParams->level << FTM_CnSC_ELSA_SHIFT);
<> 154:37f96f9d4de2 465
<> 154:37f96f9d4de2 466 /* Update the mode and edge level for channel n */
<> 154:37f96f9d4de2 467 base->CONTROLS[chnlParams->chnlNumber * 2].CnSC = reg;
<> 154:37f96f9d4de2 468
<> 154:37f96f9d4de2 469 /* Clear the current mode and edge level bits for channel n + 1 */
<> 154:37f96f9d4de2 470 reg = base->CONTROLS[(chnlParams->chnlNumber * 2) + 1].CnSC;
<> 154:37f96f9d4de2 471 reg &= ~(FTM_CnSC_MSA_MASK | FTM_CnSC_MSB_MASK | FTM_CnSC_ELSA_MASK | FTM_CnSC_ELSB_MASK);
<> 154:37f96f9d4de2 472
<> 154:37f96f9d4de2 473 /* Setup the active level for channel n + 1 */
<> 154:37f96f9d4de2 474 reg |= (uint32_t)(chnlParams->level << FTM_CnSC_ELSA_SHIFT);
<> 154:37f96f9d4de2 475
<> 154:37f96f9d4de2 476 /* Update the mode and edge level for channel n + 1*/
<> 154:37f96f9d4de2 477 base->CONTROLS[(chnlParams->chnlNumber * 2) + 1].CnSC = reg;
<> 154:37f96f9d4de2 478
<> 154:37f96f9d4de2 479 /* Set the combine bit for the channel pair */
<> 154:37f96f9d4de2 480 base->COMBINE |=
<> 154:37f96f9d4de2 481 (1U << (FTM_COMBINE_COMBINE0_SHIFT + (FTM_COMBINE_COMBINE1_SHIFT * chnlParams->chnlNumber)));
<> 154:37f96f9d4de2 482
<> 154:37f96f9d4de2 483 /* Set the channel pair values */
<> 154:37f96f9d4de2 484 base->CONTROLS[chnlParams->chnlNumber * 2].CnV = cnvFirstEdge;
<> 154:37f96f9d4de2 485 base->CONTROLS[(chnlParams->chnlNumber * 2) + 1].CnV = cnvFirstEdge + cnv;
<> 154:37f96f9d4de2 486
<> 154:37f96f9d4de2 487 #if defined(FSL_FEATURE_FTM_HAS_ENABLE_PWM_OUTPUT) && (FSL_FEATURE_FTM_HAS_ENABLE_PWM_OUTPUT)
<> 154:37f96f9d4de2 488 /* Set to output mode */
<> 154:37f96f9d4de2 489 FTM_SetPwmOutputEnable(base, (ftm_chnl_t)((uint8_t)chnlParams->chnlNumber * 2), true);
<> 154:37f96f9d4de2 490 FTM_SetPwmOutputEnable(base, (ftm_chnl_t)((uint8_t)chnlParams->chnlNumber * 2 + 1), true);
<> 154:37f96f9d4de2 491 #endif
<> 154:37f96f9d4de2 492 }
<> 154:37f96f9d4de2 493 chnlParams++;
<> 154:37f96f9d4de2 494 }
<> 154:37f96f9d4de2 495
<> 154:37f96f9d4de2 496 return kStatus_Success;
<> 154:37f96f9d4de2 497 }
<> 154:37f96f9d4de2 498
<> 154:37f96f9d4de2 499 void FTM_UpdatePwmDutycycle(FTM_Type *base,
<> 154:37f96f9d4de2 500 ftm_chnl_t chnlNumber,
<> 154:37f96f9d4de2 501 ftm_pwm_mode_t currentPwmMode,
<> 154:37f96f9d4de2 502 uint8_t dutyCyclePercent)
<> 154:37f96f9d4de2 503 {
<> 154:37f96f9d4de2 504 uint16_t cnv, cnvFirstEdge = 0, mod;
<> 154:37f96f9d4de2 505
<> 154:37f96f9d4de2 506 mod = base->MOD;
<> 154:37f96f9d4de2 507 if ((currentPwmMode == kFTM_EdgeAlignedPwm) || (currentPwmMode == kFTM_CenterAlignedPwm))
<> 154:37f96f9d4de2 508 {
<> 154:37f96f9d4de2 509 cnv = (mod * dutyCyclePercent) / 100;
<> 154:37f96f9d4de2 510 /* For 100% duty cycle */
<> 154:37f96f9d4de2 511 if (cnv >= mod)
<> 154:37f96f9d4de2 512 {
<> 154:37f96f9d4de2 513 cnv = mod + 1;
<> 154:37f96f9d4de2 514 }
<> 154:37f96f9d4de2 515 base->CONTROLS[chnlNumber].CnV = cnv;
<> 154:37f96f9d4de2 516 }
<> 154:37f96f9d4de2 517 else
<> 154:37f96f9d4de2 518 {
<> 154:37f96f9d4de2 519 /* This check is added for combined mode as the channel number should be the pair number */
<> 154:37f96f9d4de2 520 if (chnlNumber >= (FSL_FEATURE_FTM_CHANNEL_COUNTn(base) / 2))
<> 154:37f96f9d4de2 521 {
<> 154:37f96f9d4de2 522 return;
<> 154:37f96f9d4de2 523 }
<> 154:37f96f9d4de2 524
<> 154:37f96f9d4de2 525 cnv = (mod * dutyCyclePercent) / 100;
<> 154:37f96f9d4de2 526 cnvFirstEdge = base->CONTROLS[chnlNumber * 2].CnV;
<> 154:37f96f9d4de2 527 /* For 100% duty cycle */
<> 154:37f96f9d4de2 528 if (cnv >= mod)
<> 154:37f96f9d4de2 529 {
<> 154:37f96f9d4de2 530 cnv = mod + 1;
<> 154:37f96f9d4de2 531 }
<> 154:37f96f9d4de2 532 base->CONTROLS[(chnlNumber * 2) + 1].CnV = cnvFirstEdge + cnv;
<> 154:37f96f9d4de2 533 }
<> 154:37f96f9d4de2 534 }
<> 154:37f96f9d4de2 535
<> 154:37f96f9d4de2 536 void FTM_UpdateChnlEdgeLevelSelect(FTM_Type *base, ftm_chnl_t chnlNumber, uint8_t level)
<> 154:37f96f9d4de2 537 {
<> 154:37f96f9d4de2 538 uint32_t reg = base->CONTROLS[chnlNumber].CnSC;
<> 154:37f96f9d4de2 539
<> 154:37f96f9d4de2 540 /* Clear the field and write the new level value */
<> 154:37f96f9d4de2 541 reg &= ~(FTM_CnSC_ELSA_MASK | FTM_CnSC_ELSB_MASK);
<> 154:37f96f9d4de2 542 reg |= ((uint32_t)level << FTM_CnSC_ELSA_SHIFT) & (FTM_CnSC_ELSA_MASK | FTM_CnSC_ELSB_MASK);
<> 154:37f96f9d4de2 543
<> 154:37f96f9d4de2 544 base->CONTROLS[chnlNumber].CnSC = reg;
<> 154:37f96f9d4de2 545 }
<> 154:37f96f9d4de2 546
<> 154:37f96f9d4de2 547 void FTM_SetupInputCapture(FTM_Type *base,
<> 154:37f96f9d4de2 548 ftm_chnl_t chnlNumber,
<> 154:37f96f9d4de2 549 ftm_input_capture_edge_t captureMode,
<> 154:37f96f9d4de2 550 uint32_t filterValue)
<> 154:37f96f9d4de2 551 {
<> 154:37f96f9d4de2 552 uint32_t reg;
<> 154:37f96f9d4de2 553
<> 154:37f96f9d4de2 554 /* Clear the combine bit for the channel pair */
<> 154:37f96f9d4de2 555 base->COMBINE &= ~(1U << (FTM_COMBINE_COMBINE0_SHIFT + (FTM_COMBINE_COMBINE1_SHIFT * (chnlNumber >> 1))));
<> 154:37f96f9d4de2 556 /* Clear the dual edge capture mode because it's it's higher priority */
<> 154:37f96f9d4de2 557 base->COMBINE &= ~(1U << (FTM_COMBINE_DECAPEN0_SHIFT + (FTM_COMBINE_COMBINE1_SHIFT * (chnlNumber >> 1))));
<> 154:37f96f9d4de2 558 /* Clear the quadrature decoder mode beacause it's higher priority */
<> 154:37f96f9d4de2 559 base->QDCTRL &= ~FTM_QDCTRL_QUADEN_MASK;
<> 154:37f96f9d4de2 560
<> 154:37f96f9d4de2 561 reg = base->CONTROLS[chnlNumber].CnSC;
<> 154:37f96f9d4de2 562 reg &= ~(FTM_CnSC_MSA_MASK | FTM_CnSC_MSB_MASK | FTM_CnSC_ELSA_MASK | FTM_CnSC_ELSB_MASK);
<> 154:37f96f9d4de2 563 reg |= captureMode;
<> 154:37f96f9d4de2 564
<> 154:37f96f9d4de2 565 /* Set the requested input capture mode */
<> 154:37f96f9d4de2 566 base->CONTROLS[chnlNumber].CnSC = reg;
<> 154:37f96f9d4de2 567 /* Input filter available only for channels 0, 1, 2, 3 */
<> 154:37f96f9d4de2 568 if (chnlNumber < kFTM_Chnl_4)
<> 154:37f96f9d4de2 569 {
<> 154:37f96f9d4de2 570 reg = base->FILTER;
<> 154:37f96f9d4de2 571 reg &= ~(FTM_FILTER_CH0FVAL_MASK << (FTM_FILTER_CH1FVAL_SHIFT * chnlNumber));
<> 154:37f96f9d4de2 572 reg |= (filterValue << (FTM_FILTER_CH1FVAL_SHIFT * chnlNumber));
<> 154:37f96f9d4de2 573 base->FILTER = reg;
<> 154:37f96f9d4de2 574 }
<> 154:37f96f9d4de2 575 #if defined(FSL_FEATURE_FTM_HAS_ENABLE_PWM_OUTPUT) && (FSL_FEATURE_FTM_HAS_ENABLE_PWM_OUTPUT)
<> 154:37f96f9d4de2 576 /* Set to input mode */
<> 154:37f96f9d4de2 577 FTM_SetPwmOutputEnable(base, chnlNumber, false);
<> 154:37f96f9d4de2 578 #endif
<> 154:37f96f9d4de2 579 }
<> 154:37f96f9d4de2 580
<> 154:37f96f9d4de2 581 void FTM_SetupOutputCompare(FTM_Type *base,
<> 154:37f96f9d4de2 582 ftm_chnl_t chnlNumber,
<> 154:37f96f9d4de2 583 ftm_output_compare_mode_t compareMode,
<> 154:37f96f9d4de2 584 uint32_t compareValue)
<> 154:37f96f9d4de2 585 {
<> 154:37f96f9d4de2 586 uint32_t reg;
<> 154:37f96f9d4de2 587
<> 154:37f96f9d4de2 588 /* Clear the combine bit for the channel pair */
<> 154:37f96f9d4de2 589 base->COMBINE &= ~(1U << (FTM_COMBINE_COMBINE0_SHIFT + (FTM_COMBINE_COMBINE1_SHIFT * (chnlNumber >> 1))));
<> 154:37f96f9d4de2 590 /* Clear the dual edge capture mode because it's it's higher priority */
<> 154:37f96f9d4de2 591 base->COMBINE &= ~(1U << (FTM_COMBINE_DECAPEN0_SHIFT + (FTM_COMBINE_COMBINE1_SHIFT * (chnlNumber >> 1))));
<> 154:37f96f9d4de2 592 /* Clear the quadrature decoder mode beacause it's higher priority */
<> 154:37f96f9d4de2 593 base->QDCTRL &= ~FTM_QDCTRL_QUADEN_MASK;
<> 154:37f96f9d4de2 594
<> 154:37f96f9d4de2 595 reg = base->CONTROLS[chnlNumber].CnSC;
<> 154:37f96f9d4de2 596 reg &= ~(FTM_CnSC_MSA_MASK | FTM_CnSC_MSB_MASK | FTM_CnSC_ELSA_MASK | FTM_CnSC_ELSB_MASK);
<> 154:37f96f9d4de2 597 reg |= compareMode;
<> 154:37f96f9d4de2 598 /* Setup the channel output behaviour when a match occurs with the compare value */
<> 154:37f96f9d4de2 599 base->CONTROLS[chnlNumber].CnSC = reg;
<> 154:37f96f9d4de2 600
<> 154:37f96f9d4de2 601 /* Set output on match to the requested level */
<> 154:37f96f9d4de2 602 base->CONTROLS[chnlNumber].CnV = compareValue;
<> 154:37f96f9d4de2 603
<> 154:37f96f9d4de2 604 #if defined(FSL_FEATURE_FTM_HAS_ENABLE_PWM_OUTPUT) && (FSL_FEATURE_FTM_HAS_ENABLE_PWM_OUTPUT)
<> 154:37f96f9d4de2 605 /* Set to output mode */
<> 154:37f96f9d4de2 606 FTM_SetPwmOutputEnable(base, chnlNumber, true);
<> 154:37f96f9d4de2 607 #endif
<> 154:37f96f9d4de2 608 }
<> 154:37f96f9d4de2 609
<> 154:37f96f9d4de2 610 void FTM_SetupDualEdgeCapture(FTM_Type *base,
<> 154:37f96f9d4de2 611 ftm_chnl_t chnlPairNumber,
<> 154:37f96f9d4de2 612 const ftm_dual_edge_capture_param_t *edgeParam,
<> 154:37f96f9d4de2 613 uint32_t filterValue)
<> 154:37f96f9d4de2 614 {
<> 154:37f96f9d4de2 615 assert(edgeParam);
<> 154:37f96f9d4de2 616
<> 154:37f96f9d4de2 617 uint32_t reg;
<> 154:37f96f9d4de2 618
<> 154:37f96f9d4de2 619 reg = base->COMBINE;
<> 154:37f96f9d4de2 620 /* Clear the combine bit for the channel pair */
<> 154:37f96f9d4de2 621 reg &= ~(1U << (FTM_COMBINE_COMBINE0_SHIFT + (FTM_COMBINE_COMBINE1_SHIFT * chnlPairNumber)));
<> 154:37f96f9d4de2 622 /* Enable the DECAPEN bit */
<> 154:37f96f9d4de2 623 reg |= (1U << (FTM_COMBINE_DECAPEN0_SHIFT + (FTM_COMBINE_COMBINE1_SHIFT * chnlPairNumber)));
<> 154:37f96f9d4de2 624 reg |= (1U << (FTM_COMBINE_DECAP0_SHIFT + (FTM_COMBINE_COMBINE1_SHIFT * chnlPairNumber)));
<> 154:37f96f9d4de2 625 base->COMBINE = reg;
<> 154:37f96f9d4de2 626
<> 154:37f96f9d4de2 627 /* Setup the edge detection from channel n and n + 1 */
<> 154:37f96f9d4de2 628 reg = base->CONTROLS[chnlPairNumber * 2].CnSC;
<> 154:37f96f9d4de2 629 reg &= ~(FTM_CnSC_MSA_MASK | FTM_CnSC_MSB_MASK | FTM_CnSC_ELSA_MASK | FTM_CnSC_ELSB_MASK);
<> 154:37f96f9d4de2 630 reg |= ((uint32_t)edgeParam->mode | (uint32_t)edgeParam->currChanEdgeMode);
<> 154:37f96f9d4de2 631 base->CONTROLS[chnlPairNumber * 2].CnSC = reg;
<> 154:37f96f9d4de2 632
<> 154:37f96f9d4de2 633 reg = base->CONTROLS[(chnlPairNumber * 2) + 1].CnSC;
<> 154:37f96f9d4de2 634 reg &= ~(FTM_CnSC_MSA_MASK | FTM_CnSC_MSB_MASK | FTM_CnSC_ELSA_MASK | FTM_CnSC_ELSB_MASK);
<> 154:37f96f9d4de2 635 reg |= ((uint32_t)edgeParam->mode | (uint32_t)edgeParam->nextChanEdgeMode);
<> 154:37f96f9d4de2 636 base->CONTROLS[(chnlPairNumber * 2) + 1].CnSC = reg;
<> 154:37f96f9d4de2 637
<> 154:37f96f9d4de2 638 /* Input filter available only for channels 0, 1, 2, 3 */
<> 154:37f96f9d4de2 639 if (chnlPairNumber < kFTM_Chnl_4)
<> 154:37f96f9d4de2 640 {
<> 154:37f96f9d4de2 641 reg = base->FILTER;
<> 154:37f96f9d4de2 642 reg &= ~(FTM_FILTER_CH0FVAL_MASK << (FTM_FILTER_CH1FVAL_SHIFT * chnlPairNumber));
<> 154:37f96f9d4de2 643 reg |= (filterValue << (FTM_FILTER_CH1FVAL_SHIFT * chnlPairNumber));
<> 154:37f96f9d4de2 644 base->FILTER = reg;
<> 154:37f96f9d4de2 645 }
<> 154:37f96f9d4de2 646
<> 154:37f96f9d4de2 647 #if defined(FSL_FEATURE_FTM_HAS_ENABLE_PWM_OUTPUT) && (FSL_FEATURE_FTM_HAS_ENABLE_PWM_OUTPUT)
<> 154:37f96f9d4de2 648 /* Set to input mode */
<> 154:37f96f9d4de2 649 FTM_SetPwmOutputEnable(base, chnlPairNumber, false);
<> 154:37f96f9d4de2 650 #endif
<> 154:37f96f9d4de2 651 }
<> 154:37f96f9d4de2 652
<> 154:37f96f9d4de2 653 void FTM_SetupQuadDecode(FTM_Type *base,
<> 154:37f96f9d4de2 654 const ftm_phase_params_t *phaseAParams,
<> 154:37f96f9d4de2 655 const ftm_phase_params_t *phaseBParams,
<> 154:37f96f9d4de2 656 ftm_quad_decode_mode_t quadMode)
<> 154:37f96f9d4de2 657 {
<> 154:37f96f9d4de2 658 assert(phaseAParams);
<> 154:37f96f9d4de2 659 assert(phaseBParams);
<> 154:37f96f9d4de2 660
<> 154:37f96f9d4de2 661 uint32_t reg;
<> 154:37f96f9d4de2 662
<> 154:37f96f9d4de2 663 /* Set Phase A filter value if phase filter is enabled */
<> 154:37f96f9d4de2 664 if (phaseAParams->enablePhaseFilter)
<> 154:37f96f9d4de2 665 {
<> 154:37f96f9d4de2 666 reg = base->FILTER;
<> 154:37f96f9d4de2 667 reg &= ~(FTM_FILTER_CH0FVAL_MASK);
<> 154:37f96f9d4de2 668 reg |= FTM_FILTER_CH0FVAL(phaseAParams->phaseFilterVal);
<> 154:37f96f9d4de2 669 base->FILTER = reg;
<> 154:37f96f9d4de2 670 }
<> 154:37f96f9d4de2 671
<> 154:37f96f9d4de2 672 /* Set Phase B filter value if phase filter is enabled */
<> 154:37f96f9d4de2 673 if (phaseBParams->enablePhaseFilter)
<> 154:37f96f9d4de2 674 {
<> 154:37f96f9d4de2 675 reg = base->FILTER;
<> 154:37f96f9d4de2 676 reg &= ~(FTM_FILTER_CH1FVAL_MASK);
<> 154:37f96f9d4de2 677 reg |= FTM_FILTER_CH1FVAL(phaseBParams->phaseFilterVal);
<> 154:37f96f9d4de2 678 base->FILTER = reg;
<> 154:37f96f9d4de2 679 }
<> 154:37f96f9d4de2 680
<> 154:37f96f9d4de2 681 /* Set Quadrature decode properties */
<> 154:37f96f9d4de2 682 reg = base->QDCTRL;
<> 154:37f96f9d4de2 683 reg &= ~(FTM_QDCTRL_QUADMODE_MASK | FTM_QDCTRL_PHAFLTREN_MASK | FTM_QDCTRL_PHBFLTREN_MASK | FTM_QDCTRL_PHAPOL_MASK |
<> 154:37f96f9d4de2 684 FTM_QDCTRL_PHBPOL_MASK);
<> 154:37f96f9d4de2 685 reg |= (FTM_QDCTRL_QUADMODE(quadMode) | FTM_QDCTRL_PHAFLTREN(phaseAParams->enablePhaseFilter) |
<> 154:37f96f9d4de2 686 FTM_QDCTRL_PHBFLTREN(phaseBParams->enablePhaseFilter) | FTM_QDCTRL_PHAPOL(phaseAParams->phasePolarity) |
<> 154:37f96f9d4de2 687 FTM_QDCTRL_PHBPOL(phaseBParams->phasePolarity));
<> 154:37f96f9d4de2 688 base->QDCTRL = reg;
<> 154:37f96f9d4de2 689 /* Enable Quad decode */
<> 154:37f96f9d4de2 690 base->QDCTRL |= FTM_QDCTRL_QUADEN_MASK;
<> 154:37f96f9d4de2 691 }
<> 154:37f96f9d4de2 692
<> 154:37f96f9d4de2 693 void FTM_SetupFault(FTM_Type *base, ftm_fault_input_t faultNumber, const ftm_fault_param_t *faultParams)
<> 154:37f96f9d4de2 694 {
<> 154:37f96f9d4de2 695 assert(faultParams);
<> 154:37f96f9d4de2 696
<> 154:37f96f9d4de2 697 uint32_t reg;
<> 154:37f96f9d4de2 698
<> 154:37f96f9d4de2 699 reg = base->FLTCTRL;
<> 154:37f96f9d4de2 700 if (faultParams->enableFaultInput)
<> 154:37f96f9d4de2 701 {
<> 154:37f96f9d4de2 702 /* Enable the fault input */
<> 154:37f96f9d4de2 703 reg |= (FTM_FLTCTRL_FAULT0EN_MASK << faultNumber);
<> 154:37f96f9d4de2 704 }
<> 154:37f96f9d4de2 705 else
<> 154:37f96f9d4de2 706 {
<> 154:37f96f9d4de2 707 /* Disable the fault input */
<> 154:37f96f9d4de2 708 reg &= ~(FTM_FLTCTRL_FAULT0EN_MASK << faultNumber);
<> 154:37f96f9d4de2 709 }
<> 154:37f96f9d4de2 710
<> 154:37f96f9d4de2 711 if (faultParams->useFaultFilter)
<> 154:37f96f9d4de2 712 {
<> 154:37f96f9d4de2 713 /* Enable the fault filter */
<> 154:37f96f9d4de2 714 reg |= (FTM_FLTCTRL_FFLTR0EN_MASK << (FTM_FLTCTRL_FFLTR0EN_SHIFT + faultNumber));
<> 154:37f96f9d4de2 715 }
<> 154:37f96f9d4de2 716 else
<> 154:37f96f9d4de2 717 {
<> 154:37f96f9d4de2 718 /* Disable the fault filter */
<> 154:37f96f9d4de2 719 reg &= ~(FTM_FLTCTRL_FFLTR0EN_MASK << (FTM_FLTCTRL_FFLTR0EN_SHIFT + faultNumber));
<> 154:37f96f9d4de2 720 }
<> 154:37f96f9d4de2 721 base->FLTCTRL = reg;
<> 154:37f96f9d4de2 722
<> 154:37f96f9d4de2 723 if (faultParams->faultLevel)
<> 154:37f96f9d4de2 724 {
<> 154:37f96f9d4de2 725 /* Active low polarity for the fault input pin */
<> 154:37f96f9d4de2 726 base->FLTPOL |= (1U << faultNumber);
<> 154:37f96f9d4de2 727 }
<> 154:37f96f9d4de2 728 else
<> 154:37f96f9d4de2 729 {
<> 154:37f96f9d4de2 730 /* Active high polarity for the fault input pin */
<> 154:37f96f9d4de2 731 base->FLTPOL &= ~(1U << faultNumber);
<> 154:37f96f9d4de2 732 }
<> 154:37f96f9d4de2 733 }
<> 154:37f96f9d4de2 734
<> 154:37f96f9d4de2 735 void FTM_EnableInterrupts(FTM_Type *base, uint32_t mask)
<> 154:37f96f9d4de2 736 {
<> 154:37f96f9d4de2 737 uint32_t chnlInts = (mask & 0xFFU);
<> 154:37f96f9d4de2 738 uint8_t chnlNumber = 0;
<> 154:37f96f9d4de2 739
<> 154:37f96f9d4de2 740 /* Enable the timer overflow interrupt */
<> 154:37f96f9d4de2 741 if (mask & kFTM_TimeOverflowInterruptEnable)
<> 154:37f96f9d4de2 742 {
<> 154:37f96f9d4de2 743 base->SC |= FTM_SC_TOIE_MASK;
<> 154:37f96f9d4de2 744 }
<> 154:37f96f9d4de2 745
<> 154:37f96f9d4de2 746 /* Enable the fault interrupt */
<> 154:37f96f9d4de2 747 if (mask & kFTM_FaultInterruptEnable)
<> 154:37f96f9d4de2 748 {
<> 154:37f96f9d4de2 749 base->MODE |= FTM_MODE_FAULTIE_MASK;
<> 154:37f96f9d4de2 750 }
<> 154:37f96f9d4de2 751
<> 154:37f96f9d4de2 752 #if defined(FSL_FEATURE_FTM_HAS_RELOAD_INTERRUPT) && (FSL_FEATURE_FTM_HAS_RELOAD_INTERRUPT)
<> 154:37f96f9d4de2 753 /* Enable the reload interrupt available only on certain SoC's */
<> 154:37f96f9d4de2 754 if (mask & kFTM_ReloadInterruptEnable)
<> 154:37f96f9d4de2 755 {
<> 154:37f96f9d4de2 756 base->SC |= FTM_SC_RIE_MASK;
<> 154:37f96f9d4de2 757 }
<> 154:37f96f9d4de2 758 #endif
<> 154:37f96f9d4de2 759
<> 154:37f96f9d4de2 760 /* Enable the channel interrupts */
<> 154:37f96f9d4de2 761 while (chnlInts)
<> 154:37f96f9d4de2 762 {
<> 154:37f96f9d4de2 763 if (chnlInts & 0x1)
<> 154:37f96f9d4de2 764 {
<> 154:37f96f9d4de2 765 base->CONTROLS[chnlNumber].CnSC |= FTM_CnSC_CHIE_MASK;
<> 154:37f96f9d4de2 766 }
<> 154:37f96f9d4de2 767 chnlNumber++;
<> 154:37f96f9d4de2 768 chnlInts = chnlInts >> 1U;
<> 154:37f96f9d4de2 769 }
<> 154:37f96f9d4de2 770 }
<> 154:37f96f9d4de2 771
<> 154:37f96f9d4de2 772 void FTM_DisableInterrupts(FTM_Type *base, uint32_t mask)
<> 154:37f96f9d4de2 773 {
<> 154:37f96f9d4de2 774 uint32_t chnlInts = (mask & 0xFF);
<> 154:37f96f9d4de2 775 uint8_t chnlNumber = 0;
<> 154:37f96f9d4de2 776
<> 154:37f96f9d4de2 777 /* Disable the timer overflow interrupt */
<> 154:37f96f9d4de2 778 if (mask & kFTM_TimeOverflowInterruptEnable)
<> 154:37f96f9d4de2 779 {
<> 154:37f96f9d4de2 780 base->SC &= ~FTM_SC_TOIE_MASK;
<> 154:37f96f9d4de2 781 }
<> 154:37f96f9d4de2 782 /* Disable the fault interrupt */
<> 154:37f96f9d4de2 783 if (mask & kFTM_FaultInterruptEnable)
<> 154:37f96f9d4de2 784 {
<> 154:37f96f9d4de2 785 base->MODE &= ~FTM_MODE_FAULTIE_MASK;
<> 154:37f96f9d4de2 786 }
<> 154:37f96f9d4de2 787
<> 154:37f96f9d4de2 788 #if defined(FSL_FEATURE_FTM_HAS_RELOAD_INTERRUPT) && (FSL_FEATURE_FTM_HAS_RELOAD_INTERRUPT)
<> 154:37f96f9d4de2 789 /* Disable the reload interrupt available only on certain SoC's */
<> 154:37f96f9d4de2 790 if (mask & kFTM_ReloadInterruptEnable)
<> 154:37f96f9d4de2 791 {
<> 154:37f96f9d4de2 792 base->SC &= ~FTM_SC_RIE_MASK;
<> 154:37f96f9d4de2 793 }
<> 154:37f96f9d4de2 794 #endif
<> 154:37f96f9d4de2 795
<> 154:37f96f9d4de2 796 /* Disable the channel interrupts */
<> 154:37f96f9d4de2 797 while (chnlInts)
<> 154:37f96f9d4de2 798 {
<> 154:37f96f9d4de2 799 if (chnlInts & 0x1)
<> 154:37f96f9d4de2 800 {
<> 154:37f96f9d4de2 801 base->CONTROLS[chnlNumber].CnSC &= ~FTM_CnSC_CHIE_MASK;
<> 154:37f96f9d4de2 802 }
<> 154:37f96f9d4de2 803 chnlNumber++;
<> 154:37f96f9d4de2 804 chnlInts = chnlInts >> 1U;
<> 154:37f96f9d4de2 805 }
<> 154:37f96f9d4de2 806 }
<> 154:37f96f9d4de2 807
<> 154:37f96f9d4de2 808 uint32_t FTM_GetEnabledInterrupts(FTM_Type *base)
<> 154:37f96f9d4de2 809 {
<> 154:37f96f9d4de2 810 uint32_t enabledInterrupts = 0;
<> 154:37f96f9d4de2 811 int8_t chnlCount = FSL_FEATURE_FTM_CHANNEL_COUNTn(base);
<> 154:37f96f9d4de2 812
<> 154:37f96f9d4de2 813 /* The CHANNEL_COUNT macro returns -1 if it cannot match the FTM instance */
<> 154:37f96f9d4de2 814 assert(chnlCount != -1);
<> 154:37f96f9d4de2 815
<> 154:37f96f9d4de2 816 /* Check if timer overflow interrupt is enabled */
<> 154:37f96f9d4de2 817 if (base->SC & FTM_SC_TOIE_MASK)
<> 154:37f96f9d4de2 818 {
<> 154:37f96f9d4de2 819 enabledInterrupts |= kFTM_TimeOverflowInterruptEnable;
<> 154:37f96f9d4de2 820 }
<> 154:37f96f9d4de2 821 /* Check if fault interrupt is enabled */
<> 154:37f96f9d4de2 822 if (base->MODE & FTM_MODE_FAULTIE_MASK)
<> 154:37f96f9d4de2 823 {
<> 154:37f96f9d4de2 824 enabledInterrupts |= kFTM_FaultInterruptEnable;
<> 154:37f96f9d4de2 825 }
<> 154:37f96f9d4de2 826
<> 154:37f96f9d4de2 827 #if defined(FSL_FEATURE_FTM_HAS_RELOAD_INTERRUPT) && (FSL_FEATURE_FTM_HAS_RELOAD_INTERRUPT)
<> 154:37f96f9d4de2 828 /* Check if the reload interrupt is enabled */
<> 154:37f96f9d4de2 829 if (base->SC & FTM_SC_RIE_MASK)
<> 154:37f96f9d4de2 830 {
<> 154:37f96f9d4de2 831 enabledInterrupts |= kFTM_ReloadInterruptEnable;
<> 154:37f96f9d4de2 832 }
<> 154:37f96f9d4de2 833 #endif
<> 154:37f96f9d4de2 834
<> 154:37f96f9d4de2 835 /* Check if the channel interrupts are enabled */
<> 154:37f96f9d4de2 836 while (chnlCount > 0)
<> 154:37f96f9d4de2 837 {
<> 154:37f96f9d4de2 838 chnlCount--;
<> 154:37f96f9d4de2 839 if (base->CONTROLS[chnlCount].CnSC & FTM_CnSC_CHIE_MASK)
<> 154:37f96f9d4de2 840 {
<> 154:37f96f9d4de2 841 enabledInterrupts |= (1U << chnlCount);
<> 154:37f96f9d4de2 842 }
<> 154:37f96f9d4de2 843 }
<> 154:37f96f9d4de2 844
<> 154:37f96f9d4de2 845 return enabledInterrupts;
<> 154:37f96f9d4de2 846 }
<> 154:37f96f9d4de2 847
<> 154:37f96f9d4de2 848 uint32_t FTM_GetStatusFlags(FTM_Type *base)
<> 154:37f96f9d4de2 849 {
<> 154:37f96f9d4de2 850 uint32_t statusFlags = 0;
<> 154:37f96f9d4de2 851
<> 154:37f96f9d4de2 852 /* Check the timer flag */
<> 154:37f96f9d4de2 853 if (base->SC & FTM_SC_TOF_MASK)
<> 154:37f96f9d4de2 854 {
<> 154:37f96f9d4de2 855 statusFlags |= kFTM_TimeOverflowFlag;
<> 154:37f96f9d4de2 856 }
<> 154:37f96f9d4de2 857 /* Check fault flag */
<> 154:37f96f9d4de2 858 if (base->FMS & FTM_FMS_FAULTF_MASK)
<> 154:37f96f9d4de2 859 {
<> 154:37f96f9d4de2 860 statusFlags |= kFTM_FaultFlag;
<> 154:37f96f9d4de2 861 }
<> 154:37f96f9d4de2 862 /* Check channel trigger flag */
<> 154:37f96f9d4de2 863 if (base->EXTTRIG & FTM_EXTTRIG_TRIGF_MASK)
<> 154:37f96f9d4de2 864 {
<> 154:37f96f9d4de2 865 statusFlags |= kFTM_ChnlTriggerFlag;
<> 154:37f96f9d4de2 866 }
<> 154:37f96f9d4de2 867 #if defined(FSL_FEATURE_FTM_HAS_RELOAD_INTERRUPT) && (FSL_FEATURE_FTM_HAS_RELOAD_INTERRUPT)
<> 154:37f96f9d4de2 868 /* Check reload flag */
<> 154:37f96f9d4de2 869 if (base->SC & FTM_SC_RF_MASK)
<> 154:37f96f9d4de2 870 {
<> 154:37f96f9d4de2 871 statusFlags |= kFTM_ReloadFlag;
<> 154:37f96f9d4de2 872 }
<> 154:37f96f9d4de2 873 #endif
<> 154:37f96f9d4de2 874
<> 154:37f96f9d4de2 875 /* Lower 8 bits contain the channel status flags */
<> 154:37f96f9d4de2 876 statusFlags |= (base->STATUS & 0xFFU);
<> 154:37f96f9d4de2 877
<> 154:37f96f9d4de2 878 return statusFlags;
<> 154:37f96f9d4de2 879 }
<> 154:37f96f9d4de2 880
<> 154:37f96f9d4de2 881 void FTM_ClearStatusFlags(FTM_Type *base, uint32_t mask)
<> 154:37f96f9d4de2 882 {
<> 154:37f96f9d4de2 883 /* Clear the timer overflow flag by writing a 0 to the bit while it is set */
<> 154:37f96f9d4de2 884 if (mask & kFTM_TimeOverflowFlag)
<> 154:37f96f9d4de2 885 {
<> 154:37f96f9d4de2 886 base->SC &= ~FTM_SC_TOF_MASK;
<> 154:37f96f9d4de2 887 }
<> 154:37f96f9d4de2 888 /* Clear fault flag by writing a 0 to the bit while it is set */
<> 154:37f96f9d4de2 889 if (mask & kFTM_FaultFlag)
<> 154:37f96f9d4de2 890 {
<> 154:37f96f9d4de2 891 base->FMS &= ~FTM_FMS_FAULTF_MASK;
<> 154:37f96f9d4de2 892 }
<> 154:37f96f9d4de2 893 /* Clear channel trigger flag */
<> 154:37f96f9d4de2 894 if (mask & kFTM_ChnlTriggerFlag)
<> 154:37f96f9d4de2 895 {
<> 154:37f96f9d4de2 896 base->EXTTRIG &= ~FTM_EXTTRIG_TRIGF_MASK;
<> 154:37f96f9d4de2 897 }
<> 154:37f96f9d4de2 898
<> 154:37f96f9d4de2 899 #if defined(FSL_FEATURE_FTM_HAS_RELOAD_INTERRUPT) && (FSL_FEATURE_FTM_HAS_RELOAD_INTERRUPT)
<> 154:37f96f9d4de2 900 /* Check reload flag by writing a 0 to the bit while it is set */
<> 154:37f96f9d4de2 901 if (mask & kFTM_ReloadFlag)
<> 154:37f96f9d4de2 902 {
<> 154:37f96f9d4de2 903 base->SC &= ~FTM_SC_RF_MASK;
<> 154:37f96f9d4de2 904 }
<> 154:37f96f9d4de2 905 #endif
<> 154:37f96f9d4de2 906 /* Clear the channel status flags by writing a 0 to the bit */
<> 154:37f96f9d4de2 907 base->STATUS &= ~(mask & 0xFFU);
<> 154:37f96f9d4de2 908 }