mirror of
https://github.com/apache/nuttx.git
synced 2026-09-22 22:55:02 +08:00
arch/arm/samv7: Fix PWM operation for single channel mode
The current SAMv7 PWM driver assumes that all PWM channels should work in sync mode, but that is a partial case of a generic PWM driver operation. Start SAMv7 PWM channels in async mode. The sync mode should be implemeted either using ioctl command or via a separate Kconfig option. Signed-off-by: Petro Karashchenko <petro.karashchenko@gmail.com>
This commit is contained in:
committed by
Xiang Xiao
parent
3ea7d4bab4
commit
7a6253cb89
@@ -569,13 +569,13 @@ static int pwm_change_freq(struct pwm_lowerhalf_s *dev,
|
||||
uint16_t regval;
|
||||
uint16_t olddiv = getreg16(priv->base + IMXRT_FLEXPWM_SM0VAL1_OFFSET
|
||||
+ MODULE_OFFSET * shift);
|
||||
uint16_t newdiv = (uint32_t)((float)CLK_FREQ / info->frequency + 0.5f);
|
||||
uint32_t newdiv = (CLK_FREQ + (info->frequency / 2)) / info->frequency - 1;
|
||||
uint16_t prescale = 0;
|
||||
|
||||
while (newdiv > PWM_RES && prescale < 7)
|
||||
{
|
||||
newdiv = newdiv >> 1;
|
||||
prescale = prescale + 1;
|
||||
prescale++;
|
||||
}
|
||||
|
||||
if (newdiv > PWM_RES)
|
||||
@@ -595,8 +595,8 @@ static int pwm_change_freq(struct pwm_lowerhalf_s *dev,
|
||||
putreg16(regval, priv->base + IMXRT_FLEXPWM_SM0CTRL_OFFSET
|
||||
+ MODULE_OFFSET * shift);
|
||||
|
||||
putreg16(newdiv - 1, priv->base + IMXRT_FLEXPWM_SM0VAL1_OFFSET
|
||||
+ MODULE_OFFSET * shift);
|
||||
putreg16(newdiv, priv->base + IMXRT_FLEXPWM_SM0VAL1_OFFSET
|
||||
+ MODULE_OFFSET * shift);
|
||||
|
||||
/* Update VAL0, VAL3 and VAL5 registers */
|
||||
|
||||
@@ -644,7 +644,6 @@ static int pwm_set_output(struct pwm_lowerhalf_s *dev, uint8_t channel,
|
||||
uint16_t period;
|
||||
uint16_t width;
|
||||
uint16_t regval;
|
||||
double duty_pct;
|
||||
uint8_t shift = channel - 1; /* Shift submodle offset addresses */
|
||||
|
||||
/* Get the period value */
|
||||
@@ -654,8 +653,7 @@ static int pwm_set_output(struct pwm_lowerhalf_s *dev, uint8_t channel,
|
||||
|
||||
/* Compute PWM width (count value to set PWM low) */
|
||||
|
||||
duty_pct = (duty / 65536.0) * 100;
|
||||
width = (uint16_t)(((uint16_t)duty_pct * period) / 100);
|
||||
width = b16toi(duty * period + b16HALF);
|
||||
|
||||
/* Clear corresponding MCTRL[LDOK] bit */
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
# define CLK_DIVB_CLKB_POFF (0 << CLK_DIVB_SHIFT) /* CLKB clock is turned off */
|
||||
# define CLK_DIVB_PREB (1 << CLK_DIVB_SHIFT) /* CLKB clock is selected by PREB */
|
||||
|
||||
#define CLK_PREB_SHIFT (24) /* Bits: 24-27 CLKA Source Clock Selection */
|
||||
#define CLK_PREB_SHIFT (24) /* Bits: 24-27 CLKB Source Clock Selection */
|
||||
#define CLK_PREB_MASK (0x7 << CLK_PREB_SHIFT)
|
||||
# define CLK_PREB_CLK (0 << CLK_PREB_SHIFT) /* Peripheral Clock */
|
||||
# define CLK_PREB_CLK_DIV2 (1 << CLK_PREB_SHIFT) /* Peripheral Clock/2 */
|
||||
@@ -172,7 +172,7 @@
|
||||
/* DMA Register */
|
||||
|
||||
#define DMAR_DMADUTY_SHIFT (0) /* Bits: 0-23 Duty Cycle Holding Register */
|
||||
#define DMAR_DMADUTY_MAS (0xfffff << DMAR_DMADUTY_SHIFT)
|
||||
#define DMAR_DMADUTY_MASK (0xffff << DMAR_DMADUTY_SHIFT)
|
||||
# define DMAR_DMADUTY_SEL(n) ((uint32_t)(n) << DMAR_DMADUTY_SHIFT)
|
||||
|
||||
/* Sync Channels Update Control Register */
|
||||
|
||||
+83
-172
@@ -53,14 +53,14 @@
|
||||
#ifdef CONFIG_SAMV7_PWM
|
||||
|
||||
#ifdef CONFIG_PWM_NCHANNELS
|
||||
# define PWM_NCHANNELS CONFIG_PWM_NCHANNELS
|
||||
# define PWM_NCHANNELS CONFIG_PWM_NCHANNELS
|
||||
#else
|
||||
# define PWM_NCHANNELS 1
|
||||
# define PWM_NCHANNELS 1
|
||||
#endif
|
||||
|
||||
#define CHANNEL_OFFSET 0x20
|
||||
#define CLK_FREQ BOARD_MCK_FREQUENCY
|
||||
#define PWM_RES 65535
|
||||
#define CHANNEL_OFFSET 0x20
|
||||
#define CLK_FREQ BOARD_MCK_FREQUENCY
|
||||
#define PWM_RES 65535
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
@@ -73,8 +73,7 @@
|
||||
struct sam_pwm_channel_s
|
||||
{
|
||||
uint8_t channel; /* Number of PWM module */
|
||||
bool used; /* True if the module is used */
|
||||
uint32_t pin; /* PWM output pin */
|
||||
gpio_pinset_t pin; /* PWM output pin */
|
||||
};
|
||||
|
||||
struct sam_pwm_s
|
||||
@@ -82,8 +81,7 @@ struct sam_pwm_s
|
||||
const struct pwm_ops_s *ops; /* PWM operations */
|
||||
const struct sam_pwm_channel_s *channels;
|
||||
uint8_t channels_num; /* Number of channels */
|
||||
uint32_t frequency; /* PWM frequency */
|
||||
uint32_t base; /* Base address of peripheral register */
|
||||
uintptr_t base; /* Base address of peripheral register */
|
||||
};
|
||||
|
||||
/* PWM driver methods */
|
||||
@@ -116,28 +114,24 @@ static struct sam_pwm_channel_s g_pwm0_channels[] =
|
||||
#ifdef CONFIG_SAMV7_PWM0_CH0
|
||||
{
|
||||
.channel = 0,
|
||||
.used = true,
|
||||
.pin = GPIO_PWMC0_H0,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_SAMV7_PWM0_CH1
|
||||
{
|
||||
.channel = 1,
|
||||
.used = true,
|
||||
.pin = GPIO_PWMC0_H1,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_SAMV7_PWM0_CH2
|
||||
{
|
||||
.channel = 2,
|
||||
.used = true,
|
||||
.pin = GPIO_PWMC0_H2,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_SAMV7_PWM0_CH3
|
||||
{
|
||||
.channel = 3,
|
||||
.used = true,
|
||||
.pin = GPIO_PWMC0_H3,
|
||||
},
|
||||
#endif
|
||||
@@ -148,7 +142,6 @@ static struct sam_pwm_s g_pwm0 =
|
||||
.ops = &g_pwmops,
|
||||
.channels = g_pwm0_channels,
|
||||
.channels_num = PWM0_NCHANNELS,
|
||||
.frequency = 0,
|
||||
.base = SAM_PWM0_BASE,
|
||||
};
|
||||
#endif /* CONFIG_SAMV7_PWM0 */
|
||||
@@ -160,28 +153,24 @@ static struct sam_pwm_channel_s g_pwm1_channels[] =
|
||||
#ifdef CONFIG_SAMV7_PWM1_CH0
|
||||
{
|
||||
.channel = 0,
|
||||
.used = true,
|
||||
.pin = GPIO_PWMC1_H0
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_SAMV7_PWM1_CH1
|
||||
{
|
||||
.channel = 1,
|
||||
.used = true,
|
||||
.pin = GPIO_PWMC1_H1
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_SAMV7_PWM1_CH2
|
||||
{
|
||||
.channel = 2,
|
||||
.used = true,
|
||||
.pin = GPIO_PWMC1_H2
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_SAMV7_PWM1_CH3
|
||||
{
|
||||
.channel = 3,
|
||||
.used = true,
|
||||
.pin = GPIO_PWMC1_H3
|
||||
},
|
||||
#endif
|
||||
@@ -192,7 +181,6 @@ static struct sam_pwm_s g_pwm1 =
|
||||
.ops = &g_pwmops,
|
||||
.channels = g_pwm1_channels,
|
||||
.channels_num = PWM1_NCHANNELS,
|
||||
.frequency = 0,
|
||||
.base = SAM_PWM1_BASE,
|
||||
};
|
||||
|
||||
@@ -208,10 +196,10 @@ static uint32_t pwm_getreg(struct sam_pwm_s *priv, uint32_t offset);
|
||||
|
||||
/* Helper functions */
|
||||
|
||||
static int pwm_set_output(struct pwm_lowerhalf_s *dev, uint8_t channel,
|
||||
ub16_t duty);
|
||||
static int pwm_change_freq(struct pwm_lowerhalf_s *dev,
|
||||
const struct pwm_info_s *info, uint8_t channel);
|
||||
static void pwm_set_output(struct pwm_lowerhalf_s *dev, uint8_t channel,
|
||||
ub16_t duty);
|
||||
static void pwm_set_freq(struct pwm_lowerhalf_s *dev, uint8_t channel,
|
||||
uint32_t frequency);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
@@ -229,40 +217,34 @@ static uint32_t pwm_getreg(struct sam_pwm_s *priv, uint32_t offset)
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pwm_change_freq
|
||||
* Name: pwm_set_freq
|
||||
*
|
||||
* Description:
|
||||
* Set timer frequency and change registers value to respect that
|
||||
* frequency.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - A reference to the lower half PWM driver state structure
|
||||
* info - A reference to the characteristics of the pulsed output
|
||||
* dev - A reference to the lower half PWM driver state structure
|
||||
* channel - Channel to by updated
|
||||
* frequency - New frequency
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value on failure
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int pwm_change_freq(struct pwm_lowerhalf_s *dev,
|
||||
const struct pwm_info_s *info, uint8_t channel)
|
||||
static void pwm_set_freq(struct pwm_lowerhalf_s *dev, uint8_t channel,
|
||||
uint32_t frequency)
|
||||
{
|
||||
struct sam_pwm_s *priv = (struct sam_pwm_s *)dev;
|
||||
#ifdef CONFIG_PWM_MULTICHAN
|
||||
uint8_t shift = info->channels[channel].channel - 1;
|
||||
#else
|
||||
uint8_t shift = priv->channels[0].channel;
|
||||
#endif
|
||||
uint32_t regval;
|
||||
uint32_t olddiv = pwm_getreg(priv, SAMV7_PWM_CPRDX
|
||||
+ (shift * CHANNEL_OFFSET));
|
||||
uint32_t newdiv = (uint32_t)((float)CLK_FREQ / info->frequency + 0.5f);
|
||||
uint32_t newdiv = (CLK_FREQ + (frequency / 2)) / frequency - 1;
|
||||
uint32_t prescale = 0;
|
||||
|
||||
while (newdiv > PWM_RES && prescale < 11)
|
||||
{
|
||||
newdiv = newdiv >> 1;
|
||||
prescale = prescale + 1;
|
||||
prescale++;
|
||||
}
|
||||
|
||||
if (newdiv > PWM_RES)
|
||||
@@ -274,19 +256,26 @@ static int pwm_change_freq(struct pwm_lowerhalf_s *dev,
|
||||
newdiv = 2;
|
||||
}
|
||||
|
||||
regval = pwm_getreg(priv, SAMV7_PWM_CMRX + (shift * CHANNEL_OFFSET));
|
||||
regval = pwm_getreg(priv, SAMV7_PWM_CMRX + (channel * CHANNEL_OFFSET));
|
||||
regval &= ~CMR_CPRE_MASK;
|
||||
regval |= CMR_CPRE_SEL(prescale);
|
||||
pwm_putreg(priv, SAMV7_PWM_CMRX + (shift * CHANNEL_OFFSET), regval);
|
||||
|
||||
pwm_putreg(priv, SAMV7_PWM_CPRDUPDX + (shift * CHANNEL_OFFSET),
|
||||
newdiv - 1);
|
||||
if (pwm_getreg(priv, SAMV7_PWM_SR) & CHID_SEL(1 << channel))
|
||||
{
|
||||
pwm_putreg(priv, SAMV7_PWM_CMUPDX + (channel * CHANNEL_OFFSET),
|
||||
regval);
|
||||
|
||||
regval = pwm_getreg(priv, SAMV7_PWM_CDTYX + (shift * CHANNEL_OFFSET));
|
||||
regval = regval * newdiv / olddiv;
|
||||
pwm_putreg(priv, SAMV7_PWM_CDTYUPDX + (shift * CHANNEL_OFFSET),
|
||||
regval);
|
||||
pwm_putreg(priv, SAMV7_PWM_CPRDUPDX + (channel * CHANNEL_OFFSET),
|
||||
CPRD_CPRD_SEL(newdiv));
|
||||
}
|
||||
else
|
||||
{
|
||||
pwm_putreg(priv, SAMV7_PWM_CMRX + (channel * CHANNEL_OFFSET),
|
||||
regval);
|
||||
|
||||
return OK;
|
||||
pwm_putreg(priv, SAMV7_PWM_CPRDX + (channel * CHANNEL_OFFSET),
|
||||
CPRD_CPRD_SEL(newdiv));
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -301,37 +290,43 @@ static int pwm_change_freq(struct pwm_lowerhalf_s *dev,
|
||||
* duty - New duty
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value on failure
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int pwm_set_output(struct pwm_lowerhalf_s *dev, uint8_t channel,
|
||||
ub16_t duty)
|
||||
static void pwm_set_output(struct pwm_lowerhalf_s *dev, uint8_t channel,
|
||||
ub16_t duty)
|
||||
{
|
||||
struct sam_pwm_s *priv = (struct sam_pwm_s *)dev;
|
||||
uint16_t period;
|
||||
uint16_t width;
|
||||
uint16_t regval;
|
||||
double duty_pct;
|
||||
uint8_t shift = channel; /* Shift submodle offset addresses */
|
||||
|
||||
/* Get the period value */
|
||||
|
||||
period = pwm_getreg(priv, SAMV7_PWM_CPRDX + (shift * CHANNEL_OFFSET));
|
||||
period = pwm_getreg(priv, SAMV7_PWM_CPRDX + (channel * CHANNEL_OFFSET));
|
||||
|
||||
/* Compute PWM width (count value to set PWM low) */
|
||||
|
||||
duty_pct = (duty / 65536.0) * 100;
|
||||
width = (uint16_t)(((uint16_t)duty_pct * period) / 100);
|
||||
width = b16toi(duty * period + b16HALF);
|
||||
|
||||
/* Update duty cycle */
|
||||
|
||||
pwm_putreg(priv, SAMV7_PWM_CDTYUPDX + (shift * CHANNEL_OFFSET), width);
|
||||
if (pwm_getreg(priv, SAMV7_PWM_SR) & CHID_SEL(1 << channel))
|
||||
{
|
||||
pwm_putreg(priv, SAMV7_PWM_CDTYUPDX + (channel * CHANNEL_OFFSET),
|
||||
width);
|
||||
}
|
||||
else
|
||||
{
|
||||
pwm_putreg(priv, SAMV7_PWM_CDTYX + (channel * CHANNEL_OFFSET),
|
||||
width);
|
||||
}
|
||||
|
||||
regval = CHID_SEL(1 << shift);
|
||||
/* Enable the channel */
|
||||
|
||||
regval = CHID_SEL(1 << channel);
|
||||
pwm_putreg(priv, SAMV7_PWM_ENA, regval);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -353,7 +348,8 @@ static int pwm_set_output(struct pwm_lowerhalf_s *dev, uint8_t channel,
|
||||
static int pwm_setup(struct pwm_lowerhalf_s *dev)
|
||||
{
|
||||
struct sam_pwm_s *priv = (struct sam_pwm_s *)dev;
|
||||
uint32_t pin = 0;
|
||||
gpio_pinset_t pin = 0;
|
||||
uint8_t channel;
|
||||
uint32_t regval;
|
||||
|
||||
/* Unlock User Interface */
|
||||
@@ -368,13 +364,6 @@ static int pwm_setup(struct pwm_lowerhalf_s *dev)
|
||||
|
||||
for (int i = 0; i < priv->channels_num; i++)
|
||||
{
|
||||
/* Configure the channel only if is set to be used */
|
||||
|
||||
if (priv->channels[i].used != 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
pin = priv->channels[i].pin;
|
||||
|
||||
if (pin != 0)
|
||||
@@ -382,39 +371,28 @@ static int pwm_setup(struct pwm_lowerhalf_s *dev)
|
||||
sam_configgpio(pin);
|
||||
}
|
||||
|
||||
sam_configgpio(pin);
|
||||
channel = priv->channels[i].channel;
|
||||
|
||||
regval = CMR_CPOL | CMR_DPOLI;
|
||||
pwm_putreg(priv, SAMV7_PWM_CMRX + (i * CHANNEL_OFFSET), regval);
|
||||
pwm_putreg(priv, SAMV7_PWM_CMRX + (channel * CHANNEL_OFFSET), regval);
|
||||
|
||||
/* Set duty cycle register */
|
||||
/* Reset duty cycle register */
|
||||
|
||||
pwm_putreg(priv, SAMV7_PWM_CDTYX + (i * CHANNEL_OFFSET), 0);
|
||||
pwm_putreg(priv, SAMV7_PWM_CDTYX + (channel * CHANNEL_OFFSET), 0);
|
||||
|
||||
/* Set period register with default period */
|
||||
/* Reset period register */
|
||||
|
||||
regval = 0x82b8;
|
||||
pwm_putreg(priv, SAMV7_PWM_CPRDX + (i * CHANNEL_OFFSET), regval);
|
||||
pwm_putreg(priv, SAMV7_PWM_CPRDX + (channel * CHANNEL_OFFSET), 0);
|
||||
|
||||
/* Reset Dead Time Register */
|
||||
|
||||
pwm_putreg(priv, SAMV7_PWM_DTX + (i * CHANNEL_OFFSET), 0);
|
||||
pwm_putreg(priv, SAMV7_PWM_DTX + (channel * CHANNEL_OFFSET), 0);
|
||||
|
||||
/* Fault protection registers */
|
||||
|
||||
pwm_putreg(priv, SAMV7_PWM_FPV1, 0);
|
||||
pwm_putreg(priv, SAMV7_PWM_FPV2, 0);
|
||||
pwm_putreg(priv, SAMV7_PWM_FPE, 0);
|
||||
|
||||
/* Enable the channel */
|
||||
|
||||
regval = CHID_SEL(1 << i);
|
||||
pwm_putreg(priv, SAMV7_PWM_ENA, regval);
|
||||
|
||||
/* Set synchronous output */
|
||||
|
||||
regval = SCM_SYNC_SEL(1 << i);
|
||||
pwm_putreg(priv, SAMV7_PWM_SCM, regval);
|
||||
}
|
||||
|
||||
return OK;
|
||||
@@ -449,28 +427,6 @@ static int pwm_shutdown(struct pwm_lowerhalf_s *dev)
|
||||
regval = IR1_CHID_SEL(CHID_MASK);
|
||||
pwm_putreg(priv, SAMV7_PWM_IDR1, regval);
|
||||
|
||||
for (int i = 0; i < priv->channels_num; i++)
|
||||
{
|
||||
/* Skip modules that are not used */
|
||||
|
||||
if (priv->channels[i].used != 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Reset period register */
|
||||
|
||||
pwm_putreg(priv, SAMV7_PWM_CPRDX + (i * CHANNEL_OFFSET), 0);
|
||||
|
||||
/* Reset duty cycle register */
|
||||
|
||||
pwm_putreg(priv, SAMV7_PWM_CDTYX + (i * CHANNEL_OFFSET), 0);
|
||||
|
||||
/* Reset Dead Time Register */
|
||||
|
||||
pwm_putreg(priv, SAMV7_PWM_DTX + (i * CHANNEL_OFFSET), 0);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -493,71 +449,39 @@ static int pwm_start(struct pwm_lowerhalf_s *dev,
|
||||
const struct pwm_info_s *info)
|
||||
{
|
||||
struct sam_pwm_s *priv = (struct sam_pwm_s *)dev;
|
||||
int ret = OK;
|
||||
|
||||
/* Change frequency only if it is needed */
|
||||
|
||||
if (info->frequency != priv->frequency)
|
||||
{
|
||||
#ifdef CONFIG_PWM_MULTICHAN
|
||||
for (int i = 0; i < PWM_NCHANNELS; i++)
|
||||
{
|
||||
#ifdef CONFIG_PWM_MULTICHAN
|
||||
int8_t index = info->channels[i].channel;
|
||||
|
||||
/* Break the loop if all following channels are not configured */
|
||||
|
||||
if (info->channels[i].channel == -1)
|
||||
if (index == -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Configure the module freq only if is set to be used */
|
||||
|
||||
if (info->channels[i].channel != 0)
|
||||
if (index > 0 && (index - 1) < priv->channels_num)
|
||||
{
|
||||
ret = pwm_change_freq(dev, info, i);
|
||||
/* Set the frequency and enable PWM output for each channel */
|
||||
|
||||
pwm_set_freq(dev, priv->channels[index - 1].channel,
|
||||
info->frequency);
|
||||
pwm_set_output(dev, priv->channels[index - 1].channel,
|
||||
info->channels[i].duty);
|
||||
}
|
||||
}
|
||||
#else
|
||||
ret = pwm_change_freq(dev, info, i);
|
||||
/* Set the frequency and enable PWM output just for first channel */
|
||||
|
||||
pwm_set_freq(dev, priv->channels[0].channel, info->frequency);
|
||||
pwm_set_output(dev, priv->channels[0].channel, info->duty);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Save current frequency */
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
priv->frequency = info->frequency;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PWM_MULTICHAN
|
||||
for (int i = 0; ret == OK && i < PWM_NCHANNELS; i++)
|
||||
{
|
||||
/* Break the loop if all following channels are not configured */
|
||||
|
||||
if (info->channels[i].channel == -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Enable PWM output for each channel */
|
||||
|
||||
if (info->channels[i].channel != 0)
|
||||
{
|
||||
ret = pwm_set_output(dev, info->channels[i].channel - 1,
|
||||
info->channels[i].duty);
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* Enable PWM output just for first channel */
|
||||
|
||||
ret = pwm_set_output(dev, priv->channels[0].channel, info->duty);
|
||||
|
||||
#endif /* CONFIG_PWM_MULTICHAN */
|
||||
|
||||
/* Set sychnronous outputs */
|
||||
|
||||
pwm_putreg(priv, SAMV7_PWM_SCUC, SCUC_UPDULOCK);
|
||||
|
||||
return ret;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -582,31 +506,18 @@ static int pwm_start(struct pwm_lowerhalf_s *dev,
|
||||
static int pwm_stop(struct pwm_lowerhalf_s *dev)
|
||||
{
|
||||
struct sam_pwm_s *priv = (struct sam_pwm_s *)dev;
|
||||
uint8_t shift;
|
||||
uint32_t regval;
|
||||
|
||||
#ifdef CONFIG_PWM_MULTICHAN
|
||||
for (int i = 0; i < priv->channels_num; i++)
|
||||
{
|
||||
/* Skip settings if channel is not configured */
|
||||
|
||||
if (!priv->channels[i].used)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
shift = priv->channels[i].channel - 1;
|
||||
|
||||
regval = CHID_SEL(1 << shift);
|
||||
regval = CHID_SEL(1 << priv->channels[i].channel);
|
||||
pwm_putreg(priv, SAMV7_PWM_DIS, regval);
|
||||
}
|
||||
|
||||
#else
|
||||
shift = priv->channels[0].channel;
|
||||
|
||||
regval = CHID_SEL(1 << shift);
|
||||
pwm_putreg(priv, SAMV7_PWM_DIS, regval);
|
||||
|
||||
regval = CHID_SEL(1 << priv->channels[0].channel);
|
||||
pwm_putreg(priv, SAMV7_PWM_DIS, regval);
|
||||
#endif /* CONFIG_PWM_MULTICHAN */
|
||||
|
||||
return OK;
|
||||
|
||||
@@ -60,8 +60,7 @@
|
||||
#define PWM0_CH3 0
|
||||
#endif
|
||||
|
||||
#define PWM0_NCHANNELS (PWM0_CH0 + PWM0_CH1 + \
|
||||
PWM0_CH2 + PWM0_CH3)
|
||||
#define PWM0_NCHANNELS (PWM0_CH0 + PWM0_CH1 + PWM0_CH2 + PWM0_CH3)
|
||||
|
||||
#ifdef CONFIG_SAMV7_PWM1_CH0
|
||||
#define PWM1_CH0 1
|
||||
@@ -87,8 +86,7 @@
|
||||
#define PWM1_CH3 0
|
||||
#endif
|
||||
|
||||
#define PWM1_NCHANNELS (PWM1_CH0 + PWM1_CH1 + \
|
||||
PWM1_CH2 + PWM1_CH3)
|
||||
#define PWM1_NCHANNELS (PWM1_CH0 + PWM1_CH1 + PWM1_CH2 + PWM1_CH3)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
#ifdef CONFIG_PWM_MULTICHAN
|
||||
struct pwm_chan_s
|
||||
{
|
||||
ub16_t duty;
|
||||
ub16_t duty;
|
||||
int8_t channel;
|
||||
};
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user