Browse Source

Merge pull request #6230 from haukepetersen/opt_kinetis_pwm

cpu/kinetis: reworked PWM driver implementation
pr/spi.typo
Peter Kietzmann 6 years ago committed by GitHub
parent
commit
280a200377
  1. 42
      boards/frdm-k64f/include/periph_conf.h
  2. 66
      boards/mulle/include/periph_conf.h
  3. 45
      boards/pba-d-01-kw2x/include/periph_conf.h
  4. 37
      cpu/kinetis_common/include/periph_cpu.h
  5. 427
      cpu/kinetis_common/periph/pwm.c

42
boards/frdm-k64f/include/periph_conf.h

@ -125,36 +125,24 @@ static const adc_conf_t adc_config[] = {
/** @} */
/**
* @name PWM configuration
* @brief PWM configuration
* @{
*/
#define PWM_NUMOF (1U)
#define PWM_0_EN 1
#define PWM_MAX_CHANNELS 8
#define PWM_MAX_VALUE 0xffff
static const pwm_conf_t pwm_config[] = {
{
.ftm = FTM0,
.chan = {
{ .pin = GPIO_PIN(PORT_A, 4), .af = 3, .ftm_chan = 6 },
{ .pin = GPIO_PIN(PORT_A, 2), .af = 3, .ftm_chan = 7 },
{ .pin = GPIO_PIN(PORT_C, 2), .af = 4, .ftm_chan = 1 },
{ .pin = GPIO_PIN(PORT_C, 3), .af = 4, .ftm_chan = 2 }
},
.chan_numof = 4,
.ftm_num = 0
}
};
/* PWM 0 device configuration */
#define PWM_0_DEV FTM0
#define PWM_0_CHANNELS 4
#define PWM_0_CLK CLOCK_CORECLOCK
#define PWM_0_CLKEN() (SIM->SCGC6 |= (SIM_SCGC6_FTM0_MASK))
#define PWM_0_CLKDIS() (SIM->SCGC6 &= ~(SIM_SCGC6_FTM0_MASK))
/* Arduino Connector D3 */
#define PWM_0_CH0_GPIO GPIO_PIN(PORT_A, 1)
#define PWM_0_CH0_FTMCHAN 6
#define PWM_0_CH0_AF 3
/* Arduino Connector D5 */
#define PWM_0_CH1_GPIO GPIO_PIN(PORT_A, 2)
#define PWM_0_CH1_FTMCHAN 7
#define PWM_0_CH1_AF 3
/* Arduino Connector D6 */
#define PWM_0_CH2_GPIO GPIO_PIN(PORT_C, 2)
#define PWM_0_CH2_FTMCHAN 1
#define PWM_0_CH2_AF 4
/* Arduino Connector D7 */
#define PWM_0_CH3_GPIO GPIO_PIN(PORT_C, 3)
#define PWM_0_CH3_FTMCHAN 2
#define PWM_0_CH3_AF 4
#define PWM_NUMOF (sizeof(pwm_config) / sizeof(pwm_config[0]))
/** @} */

66
boards/mulle/include/periph_conf.h

@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 Eistec AB
* 2016 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
@ -15,6 +16,7 @@
* @name Peripheral MCU configuration for the Eistec Mulle
*
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*/
#ifndef MULLE_PERIPH_CONF_H_
@ -181,47 +183,35 @@ static const adc_conf_t adc_config[] = {
/** @} */
/**
* @name PWM configuration
* @brief PWM configuration
* @{
*/
#define PWM_NUMOF (2U)
#define PWM_0_EN 1
#define PWM_1_EN 1
#define PWM_MAX_CHANNELS 8
#define PWM_MAX_VALUE 0xffff
/* PWM 0 device configuration */
#define PWM_0_DEV FTM0
#define PWM_0_CHANNELS 2
#define PWM_0_CLK (SystemBusClock)
#define PWM_0_CLKEN() (BITBAND_REG32(SIM->SCGC6, SIM_SCGC6_FTM0_SHIFT) = 1)
#define PWM_0_CLKDIS() (BITBAND_REG32(SIM->SCGC6, SIM_SCGC6_FTM0_SHIFT) = 0)
/* PWM 0 pin configuration */
#define PWM_0_CH0_GPIO GPIO_PIN(PORT_C, 1)
#define PWM_0_CH0_FTMCHAN 0
#define PWM_0_CH0_AF 4
#define PWM_0_CH1_GPIO GPIO_PIN(PORT_C, 2)
#define PWM_0_CH1_FTMCHAN 1
#define PWM_0_CH1_AF 4
/* PWM 1 device configuration */
#define PWM_1_DEV FTM1
#define PWM_1_CHANNELS 2
#define PWM_1_CLK (SystemBusClock)
#define PWM_1_CLKEN() (BITBAND_REG32(SIM->SCGC6, SIM_SCGC6_FTM1_SHIFT) = 1)
#define PWM_1_CLKDIS() (BITBAND_REG32(SIM->SCGC6, SIM_SCGC6_FTM1_SHIFT) = 0)
/* PWM 1 pin configuration */
#define PWM_1_CH0_GPIO GPIO_PIN(PORT_A, 12)
#define PWM_1_CH0_FTMCHAN 0
#define PWM_1_CH0_AF 3
#define PWM_1_CH1_GPIO GPIO_PIN(PORT_A, 13)
#define PWM_1_CH1_FTMCHAN 1
#define PWM_1_CH1_AF 3
static const pwm_conf_t pwm_config[] = {
{
.ftm = FTM0,
.chan = {
{ .pin = GPIO_PIN(PORT_C, 1), .af = 4, .ftm_chan = 0 },
{ .pin = GPIO_PIN(PORT_C, 2), .af = 4, .ftm_chan = 1 },
{ .pin = GPIO_UNDEF, .af = 0, .ftm_chan = 0 },
{ .pin = GPIO_UNDEF, .af = 0, .ftm_chan = 0 }
},
.chan_numof = 2,
.ftm_num = 0
},
{
.ftm = FTM1,
.chan = {
{ .pin = GPIO_PIN(PORT_A, 12), .af = 3, .ftm_chan = 0 },
{ .pin = GPIO_PIN(PORT_A, 13), .af = 3, .ftm_chan = 1 },
{ .pin = GPIO_UNDEF, .af = 0, .ftm_chan = 0 },
{ .pin = GPIO_UNDEF, .af = 0, .ftm_chan = 0 }
},
.chan_numof = 2,
.ftm_num = 1
}
};
#define PWM_NUMOF (sizeof(pwm_config) / sizeof(pwm_config[0]))
/** @} */
/**

45
boards/pba-d-01-kw2x/include/periph_conf.h

@ -141,37 +141,24 @@ static const adc_conf_t adc_config[] = {
/** @} */
/**
* @name PWM configuration
* @brief PWM configuration
* @{
*/
#define PWM_NUMOF (1U)
#define PWM_0_EN 1
#define PWM_MAX_CHANNELS 4
#define PWM_MAX_VALUE 0xffff
/* PWM 0 device configuration */
#define PWM_0_DEV FTM0
#define PWM_0_CHANNELS 3
#define PWM_0_CLK (48e6)
#define PWM_0_CLKEN() (SIM->SCGC6 |= (SIM_SCGC6_FTM0_MASK))
#define PWM_0_CLKDIS() (SIM->SCGC6 &= ~(SIM_SCGC6_FTM0_MASK))
/* PWM 0 pin configuration */
#define PWM_0_CH0_GPIO GPIO_PIN(PORT_A, 4)
#define PWM_0_CH0_FTMCHAN 1
#define PWM_0_CH0_AF 3
#define PWM_0_CH1_GPIO GPIO_PIN(PORT_D, 4)
#define PWM_0_CH1_FTMCHAN 4
#define PWM_0_CH1_AF 4
#define PWM_0_CH2_GPIO GPIO_PIN(PORT_D, 6)
#define PWM_0_CH2_FTMCHAN 6
#define PWM_0_CH2_AF 4
#define PWM_0_CH3_GPIO GPIO_PIN(PORT_A, 1)
#define PWM_0_CH3_FTMCHAN 1
#define PWM_0_CH3_AF 3
static const pwm_conf_t pwm_config[] = {
{
.ftm = FTM0,
.chan = {
{ .pin = GPIO_PIN(PORT_A, 4), .af = 3, .ftm_chan = 1 },
{ .pin = GPIO_PIN(PORT_D, 4), .af = 4, .ftm_chan = 4 },
{ .pin = GPIO_PIN(PORT_D, 6), .af = 4, .ftm_chan = 6 },
{ .pin = GPIO_PIN(PORT_A, 1), .af = 3, .ftm_chan = 1 }
},
.chan_numof = 4,
.ftm_num = 0
}
};
#define PWM_NUMOF (sizeof(pwm_config) / sizeof(pwm_config[0]))
/** @} */

37
cpu/kinetis_common/include/periph_cpu.h

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015 Freie Universität Berlin
* Copyright (C) 2015-2016 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
@ -61,6 +61,11 @@ typedef uint16_t gpio_t;
*/
#define GPIO_MODE(pu, pe, od, out) (pu | (pe << 1) | (od << 5) | (out << 7))
/**
* @brief Define the maximum number of PWM channels that can be configured
*/
#define PWM_CHAN_MAX (4U)
#ifndef DOXYGEN
/**
* @brief Override GPIO modes
@ -142,6 +147,18 @@ typedef enum {
ADC_RES_16BIT = ADC_CFG1_MODE(3) /**< ADC resolution: 16 bit */
} adc_res_t;
/** @} */
/**
* @brief Override default PWM mode configuration
* @{
*/
#define HAVE_PWM_MODE_T
typedef enum {
PWM_LEFT = (FTM_CnSC_MSB_MASK | FTM_CnSC_ELSB_MASK), /**< left aligned */
PWM_RIGHT = (FTM_CnSC_MSB_MASK | FTM_CnSC_ELSA_MASK), /**< right aligned */
PWM_CENTER = (FTM_CnSC_MSB_MASK) /**< center aligned */
} pwm_mode_t;
/** @} */
#endif /* ndef DOXYGEN */
/**
@ -186,12 +203,26 @@ typedef struct {
uint8_t index;
} lptmr_conf_t;
/**
* @brief PWM configuration structure
*/
typedef struct {
FTM_Type* ftm; /**< used FTM */
struct { /**< logical channel configuration */
gpio_t pin; /**< GPIO pin used, set to GPIO_UNDEF */
uint8_t af; /**< alternate function mapping */
uint8_t ftm_chan; /**< the actual FTM channel used */
} chan[PWM_CHAN_MAX];
uint8_t chan_numof; /**< number of actually configured channels */
uint8_t ftm_num; /**< FTM number used */
} pwm_conf_t;
/**
* @brief Possible timer module types
*/
enum {
TIMER_PIT,
TIMER_LPTMR,
TIMER_PIT, /**< PIT */
TIMER_LPTMR, /**< LPTMR */
};
/**

427
cpu/kinetis_common/periph/pwm.c

@ -1,11 +1,11 @@
/*
* Copyright (C) 2014 Freie Universität Berlin
* Copyright (C) 2014-2016 Freie Universität Berlin
* Copyright (C) 2014 PHYTEC Messtechnik GmbH
* Copyright (C) 2015-2016 Eistec AB
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
* details.
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
@ -24,375 +24,130 @@
* @}
*/
#include <stdint.h>
#include <string.h>
#include "cpu.h"
#include "assert.h"
#include "periph/pwm.h"
#include "periph_conf.h"
/* FTM channel look up tables */
#if PWM_0_EN
static const uint8_t ftm0chan[] = {
#if PWM_0_CHANNELS > 0
PWM_0_CH0_FTMCHAN,
#endif
#if PWM_0_CHANNELS > 1
PWM_0_CH1_FTMCHAN,
#endif
#if PWM_0_CHANNELS > 2
PWM_0_CH2_FTMCHAN,
#endif
#if PWM_0_CHANNELS > 3
PWM_0_CH3_FTMCHAN,
#endif
#if PWM_0_CHANNELS > 4
PWM_0_CH4_FTMCHAN,
#endif
#if PWM_0_CHANNELS > 5
PWM_0_CH5_FTMCHAN,
#endif
#if PWM_0_CHANNELS > 6
PWM_0_CH6_FTMCHAN,
#endif
#if PWM_0_CHANNELS > 7
PWM_0_CH7_FTMCHAN,
#endif
};
#endif
#if PWM_1_EN
static const uint8_t ftm1chan[] = {
#if PWM_1_CHANNELS > 0
PWM_1_CH0_FTMCHAN,
#endif
#if PWM_1_CHANNELS > 1
PWM_1_CH1_FTMCHAN,
#endif
#if PWM_1_CHANNELS > 2
PWM_1_CH2_FTMCHAN,
#endif
#if PWM_1_CHANNELS > 3
PWM_1_CH3_FTMCHAN,
#endif
#if PWM_1_CHANNELS > 4
PWM_1_CH4_FTMCHAN,
#endif
#if PWM_1_CHANNELS > 5
PWM_1_CH5_FTMCHAN,
#endif
#if PWM_1_CHANNELS > 6
PWM_1_CH6_FTMCHAN,
#endif
#if PWM_1_CHANNELS > 7
PWM_1_CH7_FTMCHAN,
#endif
};
#endif
#define PRESCALER_MAX (7U)
uint32_t pwm_init(pwm_t dev, pwm_mode_t mode, uint32_t freq, uint16_t res)
static inline FTM_Type *ftm(pwm_t pwm)
{
FTM_Type *ftm;
int channels = 0;
uint32_t pwm_clk = 0;
const uint8_t *ftmchan = NULL;
switch (dev) {
#if PWM_0_EN
case PWM_0:
channels = PWM_0_CHANNELS;
pwm_clk = PWM_0_CLK;
ftm = PWM_0_DEV;
ftmchan = &ftm0chan[0];
break;
#endif
#if PWM_1_EN
case PWM_1:
channels = PWM_1_CHANNELS;
pwm_clk = PWM_1_CLK;
ftm = PWM_1_DEV;
ftmchan = &ftm1chan[0];
break;
#endif
default:
return 0;
}
switch (mode) {
case PWM_LEFT:
case PWM_RIGHT:
case PWM_CENTER:
break;
return pwm_config[pwm].ftm;
}
default:
return 0;
}
uint32_t pwm_init(pwm_t pwm, pwm_mode_t mode, uint32_t freq, uint16_t res)
{
uint8_t pre = 0;
if ((unsigned int)res > (PWM_MAX_VALUE + 1) || (res * freq) > pwm_clk) {
if (pwm >= PWM_NUMOF || ((res * freq) > CLOCK_BUSCLOCK)) {
return 0;
}
/* Try to find a good prescaler value */
/* The prescaler divides the module clock by a power of two, between 2^0 and 2^7 */
uint8_t prescaler = 0;
/* (resolution * frequency) is the number of timer ticks per second */
while ((pwm_clk >> prescaler) > (res * freq)) {
++prescaler;
if (prescaler > 7) {
/* Module clock is too fast to reach the requested frequency using the
* hardware supported prescaler values */
/* Note: The frequency might be reachable if the requested resolution
* is increased. */
return 0;
}
/* figure out the clock settings
* the resulting frequency is calculated by
* ticks := BUS_CLK / 2 ^ pre
* where `ticks` is `freq * res`
* and `pre` must be between [0, 7].
*
* The resulting prescaler yields a timer frequency, which is the closest
* possible frequency requested. */
while ((CLOCK_BUSCLOCK >> pre) > (res * freq)) {
++pre;
}
/* The chosen prescaler yields a timer frequency which is the
* nearest possible frequency less than the requested frequency */
/* Turn on the peripheral */
pwm_poweron(dev);
switch (dev) {
#if PWM_0_EN
case PWM_0:
#if PWM_0_CHANNELS > 0
gpio_init_port(PWM_0_CH0_GPIO, PORT_PCR_MUX(PWM_0_CH0_AF));
#endif
#if PWM_0_CHANNELS > 1
gpio_init_port(PWM_0_CH1_GPIO, PORT_PCR_MUX(PWM_0_CH1_AF));
#endif
#if PWM_0_CHANNELS > 2
gpio_init_port(PWM_0_CH2_GPIO, PORT_PCR_MUX(PWM_0_CH2_AF));
#endif
#if PWM_0_CHANNELS > 3
gpio_init_port(PWM_0_CH3_GPIO, PORT_PCR_MUX(PWM_0_CH3_AF));
#endif
#if PWM_0_CHANNELS > 4
gpio_init_port(PWM_0_CH4_GPIO, PORT_PCR_MUX(PWM_0_CH4_AF));
#endif
#if PWM_0_CHANNELS > 5
gpio_init_port(PWM_0_CH5_GPIO, PORT_PCR_MUX(PWM_0_CH5_AF));
#endif
#if PWM_0_CHANNELS > 6
gpio_init_port(PWM_0_CH6_GPIO, PORT_PCR_MUX(PWM_0_CH6_AF));
#endif
#if PWM_0_CHANNELS > 7
gpio_init_port(PWM_0_CH7_GPIO, PORT_PCR_MUX(PWM_0_CH7_AF));
#endif
break;
#endif
#if PWM_1_EN
case PWM_1:
#if PWM_1_CHANNELS > 0
gpio_init_port(PWM_1_CH0_GPIO, PORT_PCR_MUX(PWM_1_CH0_AF));
#endif
#if PWM_1_CHANNELS > 1
gpio_init_port(PWM_1_CH1_GPIO, PORT_PCR_MUX(PWM_1_CH1_AF));
#endif
#if PWM_1_CHANNELS > 2
gpio_init_port(PWM_1_CH2_GPIO, PORT_PCR_MUX(PWM_1_CH2_AF));
#endif
#if PWM_1_CHANNELS > 3
gpio_init_port(PWM_1_CH3_GPIO, PORT_PCR_MUX(PWM_1_CH3_AF));
#endif
#if PWM_1_CHANNELS > 4
gpio_init_port(PWM_1_CH4_GPIO, PORT_PCR_MUX(PWM_1_CH4_AF));
#endif
#if PWM_1_CHANNELS > 5
gpio_init_port(PWM_1_CH5_GPIO, PORT_PCR_MUX(PWM_1_CH5_AF));
#endif
#if PWM_1_CHANNELS > 6
gpio_init_port(PWM_1_CH6_GPIO, PORT_PCR_MUX(PWM_1_CH6_AF));
#endif
#if PWM_1_CHANNELS > 7
gpio_init_port(PWM_1_CH7_GPIO, PORT_PCR_MUX(PWM_1_CH7_AF));
#endif
break;
#endif
default:
return 0;
/* make sure the calculated prescaler is valid, else return */
if (pre > PRESCALER_MAX) {
return 0;
}
/* configure the used timer */
pwm_poweron(pwm);
/* disable write protect for changing settings */
ftm->MODE = FTM_MODE_WPDIS_MASK;
/* reset timer match value */
for (int i = 0; i < channels; i++) {
ftm->CONTROLS[i].CnV = 0;
ftm(pwm)->MODE = FTM_MODE_WPDIS_MASK;
/* clear any existing configuration */
ftm(pwm)->COMBINE = 0;
ftm(pwm)->CNTIN = 0;
ftm(pwm)->SWOCTRL = 0;
/* apply prescaler and set resolution */
ftm(pwm)->SC = FTM_SC_PS(pre);
ftm(pwm)->MOD = (res - 1);
/* set CPWMS bit in the SC register in case of center aligned mode */
if (mode == PWM_CENTER) {
BITBAND_REG32(ftm(pwm)->SC, FTM_SC_CPWMS_SHIFT) = 1;
}
/* reset timer configuration registers */
ftm->COMBINE = 0;
ftm->CNTIN = 0;
ftm->SWOCTRL = 0;
/* set prescale and mod registers to matching values for resolution and frequency */
ftm->SC = FTM_SC_PS(prescaler);
ftm->MOD = res - 1;
/* set PWM mode */
uint32_t mode_mask = 0;
switch (mode) {
case PWM_LEFT:
mode_mask = (1 << FTM_CnSC_MSB_SHIFT) | (1 << FTM_CnSC_ELSB_SHIFT);
break;
case PWM_RIGHT:
mode_mask = (1 << FTM_CnSC_MSB_SHIFT) | (1 << FTM_CnSC_ELSA_SHIFT);
break;
case PWM_CENTER:
mode_mask = (1 << FTM_CnSC_MSB_SHIFT);
ftm->SC |= (1 << FTM_SC_CPWMS_SHIFT);
break;
}
for (int i = 0; i < channels; i++) {
/* cppcheck thinks ftmchan may be NULL here, but the variable is
* assigned in all non-returning branches of the switch at the top of
* this function. */
/* cppcheck-suppress nullPointer ftmchan */
ftm->CONTROLS[ftmchan[i]].CnSC = mode_mask;
/* setup the configured channels */
for (int i = 0; i < (int)pwm_config[pwm].chan_numof; i++) {
/* configure the used pin */
gpio_init_port(pwm_config[pwm].chan[i].pin,
PORT_PCR_MUX(pwm_config[pwm].chan[i].af));
/* set the given mode */
ftm(pwm)->CONTROLS[pwm_config[pwm].chan[i].ftm_chan].CnSC = mode;
/* and reset the PWM to 0% duty cycle */
ftm(pwm)->CONTROLS[pwm_config[pwm].chan[i].ftm_chan].CnV = 0;
}
/* enable timer ergo the PWM generation */
pwm_start(dev);
/* and now we start the actual waveform generation */
pwm_start(pwm);
/* Return actual frequency */
return (pwm_clk / (1 << prescaler)) / res;
/* finally we need to return the actual applied PWM frequency */
return (CLOCK_BUSCLOCK >> pre) / res;
}
uint8_t pwm_channels(pwm_t dev)
uint8_t pwm_channels(pwm_t pwm)
{
switch (dev) {
#if PWM_0_EN
case PWM_0:
return PWM_0_CHANNELS;
#endif
#if PWM_1_EN
case PWM_1:
return PWM_1_CHANNELS;
#endif
default:
return 0;
}
assert(pwm < PWM_NUMOF);
return pwm_config[pwm].chan_numof;
}
void pwm_set(pwm_t dev, uint8_t channel, uint16_t value)
void pwm_set(pwm_t pwm, uint8_t channel, uint16_t value)
{
FTM_Type *ftm;
const uint8_t *ftmchan = NULL;
switch (dev) {
#if PWM_0_EN
case PWM_0:
if (channel > PWM_0_CHANNELS) {
return;
}
ftm = PWM_0_DEV;
ftmchan = &ftm0chan[0];
break;
#endif
#if PWM_1_EN
case PWM_1:
if (channel > PWM_1_CHANNELS) {
return;
}
ftm = PWM_1_DEV;
ftmchan = &ftm1chan[0];
break;
#endif
default:
return;
}
/* clamp value to maximum possible value */
if (value > PWM_MAX_VALUE) {
value = PWM_MAX_VALUE;
}
/* cppcheck thinks ftmchan may be NULL here, but the variable is
* assigned in all non-returning branches of the switch at the top of
* this function. */
/* cppcheck-suppress nullPointer */
ftm->CONTROLS[ftmchan[channel]].CnV = value;
assert((pwm < PWM_NUMOF) && (channel < pwm_config[pwm].chan_numof));
ftm(pwm)->CONTROLS[pwm_config[pwm].chan[channel].ftm_chan].CnV = value;
}
void pwm_start(pwm_t dev)
void pwm_start(pwm_t pwm)
{
switch (dev) {
#if PWM_0_EN
case PWM_0:
PWM_0_DEV->SC |= FTM_SC_CLKS(1);
break;
#endif
#if PWM_1_EN
case PWM_1:
PWM_1_DEV->SC |= FTM_SC_CLKS(1);
break;
#endif
}
assert(pwm < PWM_NUMOF);
ftm(pwm)->SC |= FTM_SC_CLKS(1);
}
void pwm_stop(pwm_t dev)
void pwm_stop(pwm_t pwm)
{
switch (dev) {
#if PWM_0_EN
case PWM_0:
PWM_0_DEV->SC &= ~FTM_SC_CLKS_MASK;
break;
#endif
#if PWM_1_EN
case PWM_1:
PWM_1_DEV->SC &= ~FTM_SC_CLKS_MASK;
break;
#endif
}
assert(pwm < PWM_NUMOF);
ftm(pwm)->SC &= ~(FTM_SC_CLKS_MASK);
}
void pwm_poweron(pwm_t dev)
void pwm_poweron(pwm_t pwm)
{
switch (dev) {
#if PWM_0_EN
case PWM_0:
PWM_0_CLKEN();
break;
#endif
#if PWM_1_EN
case PWM_1:
PWM_1_CLKEN();
break;
#endif
assert(pwm < PWM_NUMOF);
int ftm = pwm_config[pwm].ftm_num;
#ifdef SIM_SCGC6_FTM2_SHIFT
BITBAND_REG32(SIM->SCGC6, SIM_SCGC6_FTM0_SHIFT + ftm) = 1;
#else
if (ftm < 2) {
BITBAND_REG32(SIM->SCGC6, SIM_SCGC6_FTM0_SHIFT + ftm) = 1;
}
else if (ftm == 2) {
BITBAND_REG32(SIM->SCGC3, SIM_SCGC3_FTM2_SHIFT) = 1;
}
#endif
}
void pwm_poweroff(pwm_t dev)
void pwm_poweroff(pwm_t pwm)
{
switch (dev) {
#if PWM_0_EN
case PWM_0:
PWM_0_CLKDIS();
break;
#endif
#if PWM_1_EN
case PWM_1:
PWM_1_CLKDIS();
break;
#endif
assert(pwm < PWM_NUMOF);
int ftm = pwm_config[pwm].ftm_num;
#ifdef SIM_SCGC6_FTM2_SHIFT
BITBAND_REG32(SIM->SCGC6, SIM_SCGC6_FTM0_SHIFT + ftm) = 0;
#else
if (ftm < 2) {
BITBAND_REG32(SIM->SCGC6, SIM_SCGC6_FTM0_SHIFT + ftm) = 0;
}
else if (ftm == 2) {
BITBAND_REG32(SIM->SCGC3, SIM_SCGC3_FTM2_SHIFT) = 0;
}
#endif
}

Loading…
Cancel
Save