29#if HAL_USE_PWM || defined(__DOXYGEN__)
36#define CHANNEL CONTROLS
48#if KINETIS_PWM_USE_FTM0 || defined(__DOXYGEN__)
56#if KINETIS_PWM_USE_FTM1 || defined(__DOXYGEN__)
64#if KINETIS_PWM_USE_FTM2 || defined(__DOXYGEN__)
72#if KINETIS_PWM_USE_FTM3 || defined(__DOXYGEN__)
88 pwmp->
ftm->SC = sr&(~FTM_SC_TOFx);
90 if (((sr & FTM_SC_TOFx) != 0) &&
91 ((sr & FTM_SC_TOIEx) != 0) &&
98 sr = pwmp->
ftm->CHANNEL[n].CnSC;
99 pwmp->
ftm->CHANNEL[n].CnSC = sr&(~FTM_CnSC_CHFx);
100 if (((sr & FTM_CnSC_CHFx) != 0) &&
101 ((sr & FTM_CnSC_CHIEx) != 0) &&
112#if KINETIS_PWM_USE_FTM0
125#if KINETIS_PWM_USE_FTM1
139#if KINETIS_PWM_USE_FTM2
153#if KINETIS_PWM_USE_FTM3
178#if KINETIS_PWM_USE_FTM0
179 pwmObjectInit(&
PWMD1);
184#if KINETIS_PWM_USE_FTM1
185 pwmObjectInit(&
PWMD2);
190#if KINETIS_PWM_USE_FTM2
191 pwmObjectInit(&
PWMD3);
196#if KINETIS_PWM_USE_FTM3
197 pwmObjectInit(&
PWMD4);
216 if (pwmp->
state == PWM_STOP) {
218#if KINETIS_PWM_USE_FTM0
219 if (&
PWMD1 == pwmp) {
223 SIM->SCGC6 |= SIM_SCGC6_FTM0;
225 nvicEnableVector(FTM0_IRQn, KINETIS_PWM_FTM0_PRIORITY);
229#if KINETIS_PWM_USE_FTM1
230 if (&
PWMD2 == pwmp) {
234 SIM->SCGC6 |= SIM_SCGC6_FTM1;
236 nvicEnableVector(FTM1_IRQn, KINETIS_PWM_FTM1_PRIORITY);
240#if KINETIS_PWM_USE_FTM2
241 if (&
PWMD3 == pwmp) {
245 SIM->SCGC3 |= SIM_SCGC3_FTM2;
247 nvicEnableVector(FTM2_IRQn, KINETIS_PWM_FTM2_PRIORITY);
251#if KINETIS_PWM_USE_FTM3
252 if (&
PWMD4 == pwmp) {
256 SIM->SCGC3 |= SIM_SCGC3_FTM3;
258 nvicEnableVector(FTM3_IRQn, KINETIS_PWM_FTM3_PRIORITY);
262 pwmp->
ftm->MODE = FTM_MODE_FTMEN_MASK|FTM_MODE_PWMSYNC_MASK;
263 pwmp->
ftm->SYNC = FTM_SYNC_CNTMIN_MASK|FTM_SYNC_CNTMAX_MASK
264 |FTM_SYNC_SWSYNC_MASK;
265 pwmp->
ftm->COMBINE = FTM_COMBINE_SYNCEN3_MASK | FTM_COMBINE_SYNCEN2_MASK
266 | FTM_COMBINE_SYNCEN1_MASK | FTM_COMBINE_SYNCEN0_MASK;
267 pwmp->
ftm->SYNCONF = FTM_SYNCONF_SYNCMODE_MASK;
269 pwmp->
ftm->CNTIN = 0x0000;
271 pwmp->
ftm->CNT = 0x0000;
276 osalDbgAssert(psc <= 128 && !(psc & (psc - 1)),
"invalid frequency");
280 for (i = 0; i < 8; i++) {
281 if (psc == (
unsigned)(1 << i)) {
291 pwmp->
ftm->SC = FTM_SC_CLKS(1) | FTM_SC_PS(i);
294 pwmp->
ftm->PWMLOAD = FTM_PWMLOAD_LDOK_MASK;
307 if (pwmp->
state == PWM_READY) {
308#if KINETIS_PWM_USE_FTM0
309 if (&
PWMD1 == pwmp) {
311 PCC->CLKCFG[PCC_FLEXTMR0_INDEX] &= ~PCC_CLKCFG_CGC(1);
313 SIM->SCGC6 &= ~SIM_SCGC6_FTM0;
315 nvicDisableVector(FTM0_IRQn);
319#if KINETIS_PWM_USE_FTM1
320 if (&
PWMD2 == pwmp) {
322 PCC->CLKCFG[PCC_FLEXTMR1_INDEX] &= ~PCC_CLKCFG_CGC(1);
324 SIM->SCGC6 &= ~SIM_SCGC6_FTM1;
326 nvicDisableVector(FTM1_IRQn);
330#if KINETIS_PWM_USE_FTM2
331 if (&
PWMD3 == pwmp) {
333 PCC->CLKCFG[PCC_FLEXTMR2_INDEX] &= ~PCC_CLKCFG_CGC(1);
335 SIM->SCGC3 &= ~SIM_SCGC3_FTM2;
337 nvicDisableVector(FTM2_IRQn);
341#if KINETIS_PWM_USE_FTM3
342 if (&
PWMD4 == pwmp) {
344 PCC->CLKCFG[PCC_FLEXTMR3_INDEX] &= ~PCC_CLKCFG_CGC(1);
346 SIM->SCGC3 &= ~SIM_SCGC3_FTM3;
348 nvicDisableVector(FTM3_IRQn);
373 uint32_t mode = FTM_CnSC_MSBx;
376 case PWM_OUTPUT_ACTIVE_HIGH:
377 mode |= FTM_CnSC_ELSBx;
379 case PWM_OUTPUT_ACTIVE_LOW:
380 mode |= FTM_CnSC_ELSAx;
384 if (pwmp->
ftm->CHANNEL[
channel].CnSC & FTM_CnSC_CHIEx)
385 mode |= FTM_CnSC_CHIEx;
389 pwmp->
ftm->PWMLOAD = FTM_PWMLOAD_LDOK_MASK;
420 pwmp->
ftm->SC |= FTM_SC_TOIEx;
433 pwmp->
ftm->SC &= ~FTM_SC_TOIEx;
449 pwmp->
ftm->CHANNEL[
channel].CnSC |= FTM_CnSC_CHIEx;
465 pwmp->
ftm->CHANNEL[
channel].CnSC &= ~FTM_CnSC_CHIEx;
static void pwm_lld_serve_interrupt(PWMDriver *pwmp)
void pwm_lld_disable_periodic_notification(PWMDriver *pwmp)
Disables the periodic activation edge notification.
OSAL_IRQ_HANDLER(KINETIS_FTM0_IRQ_VECTOR)
FTM0 interrupt handler.
PWMDriver PWMD2
PWMD2 driver identifier.
void pwm_lld_stop(PWMDriver *pwmp)
Deactivates the PWM peripheral.
void pwm_lld_disable_channel_notification(PWMDriver *pwmp, pwmchannel_t channel)
Disables a channel de-activation edge notification.
void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel)
Disables a PWM channel and its notification.
void pwm_lld_init(void)
Low level PWM driver initialization.
void pwm_lld_start(PWMDriver *pwmp)
Configures and activates the PWM peripheral.
void pwm_lld_enable_channel(PWMDriver *pwmp, pwmchannel_t channel, pwmcnt_t width)
Enables a PWM channel.
void pwm_lld_enable_periodic_notification(PWMDriver *pwmp)
Enables the periodic activation edge notification.
void pwm_lld_enable_channel_notification(PWMDriver *pwmp, pwmchannel_t channel)
Enables a channel de-activation edge notification.
PWMDriver PWMD1
PWMD1 driver identifier.
PWMDriver PWMD4
PWMD4 driver identifier.
PWMDriver PWMD3
PWMD3 driver identifier.
static void CLOCK_EnableClock(clock_ip_name_t name)
Enable the clock for specific IP.
uint8_t pwmchannel_t
Type of a PWM channel.
uint16_t pwmcnt_t
Type of a PWM counter.
This is needed for better compatibility with STM32 or other CPUs of Kinetis family.
pwmcallback_t callback
Channel callback pointer.
pwmmode_t mode
Channel active logic level.
pwmcallback_t callback
Periodic callback pointer.
PWMChannelConfig channels[PWM_CHANNELS]
Channels configurations.
uint32_t frequency
Timer clock in Hz.
Structure representing a PWM driver.
pwmcnt_t period
Current PWM period in ticks.
PWM_DRIVER_EXT_FIELDS FTM_TypeDef * ftm
Pointer to the FTM registers block.
pwmchannel_t channels
Number of channels in this instance.
const PWMConfig * config
Current driver configuration data.
pwmstate_t state
Driver state.