arch/arm/src/samv7/sam_pwm.c: option to make channels synchronous
Make channels synchronous (i.e. share the same timebase) with the help of SAMV7_PWMx_CHy_SYNC defines. All the channels share the same timebase of channel 0, so this channel must be defined too. Signed-off-by: Stepan Pressl <pressste@fel.cvut.cz>
This commit is contained in:
parent
b049b490b8
commit
297b3b0209
@ -669,6 +669,18 @@ menuconfig SAMV7_PWM0
|
|||||||
|
|
||||||
if SAMV7_PWM0
|
if SAMV7_PWM0
|
||||||
|
|
||||||
|
config SAMV7_PWM0_SYNC
|
||||||
|
bool "PWM0 synchronous channels"
|
||||||
|
depends on PWM_MULTICHAN
|
||||||
|
default n
|
||||||
|
---help---
|
||||||
|
This option makes the synchronization between channels possible.
|
||||||
|
This means every synchronized channel has the same clock, the
|
||||||
|
same period and the same alignment. If any channel is defined
|
||||||
|
as synchronous, channel 0 is defined as synchronous too because
|
||||||
|
channel 0's counter is used by other synchronous channels.
|
||||||
|
This option automatically defines channel 0 as synchronous.
|
||||||
|
|
||||||
config SAMV7_PWM0_CH0
|
config SAMV7_PWM0_CH0
|
||||||
bool "PWM0 Channel 0"
|
bool "PWM0 Channel 0"
|
||||||
default n
|
default n
|
||||||
@ -701,6 +713,11 @@ config SAMV7_PWM0_CH1_COMP
|
|||||||
depends on !SAMV7_PWM0_CH1_LONLY
|
depends on !SAMV7_PWM0_CH1_LONLY
|
||||||
default n
|
default n
|
||||||
|
|
||||||
|
config SAMV7_PWM0_CH1_SYNC
|
||||||
|
bool "Synchronous channel"
|
||||||
|
depends on SAMV7_PWM0_SYNC
|
||||||
|
default n
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
config SAMV7_PWM0_CH2
|
config SAMV7_PWM0_CH2
|
||||||
@ -718,6 +735,11 @@ config SAMV7_PWM0_CH2_COMP
|
|||||||
depends on !SAMV7_PWM0_CH2_LONLY
|
depends on !SAMV7_PWM0_CH2_LONLY
|
||||||
default n
|
default n
|
||||||
|
|
||||||
|
config SAMV7_PWM0_CH2_SYNC
|
||||||
|
bool "Synchronous channel"
|
||||||
|
depends on SAMV7_PWM0_SYNC
|
||||||
|
default n
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
config SAMV7_PWM0_CH3
|
config SAMV7_PWM0_CH3
|
||||||
@ -735,6 +757,11 @@ config SAMV7_PWM0_CH3_COMP
|
|||||||
depends on !SAMV7_PWM0_CH3_LONLY
|
depends on !SAMV7_PWM0_CH3_LONLY
|
||||||
default n
|
default n
|
||||||
|
|
||||||
|
config SAMV7_PWM0_CH3_SYNC
|
||||||
|
bool "Synchronous channel"
|
||||||
|
depends on SAMV7_PWM0_SYNC
|
||||||
|
default n
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
menu "PWM Comparison units"
|
menu "PWM Comparison units"
|
||||||
@ -905,6 +932,18 @@ menuconfig SAMV7_PWM1
|
|||||||
|
|
||||||
if SAMV7_PWM1
|
if SAMV7_PWM1
|
||||||
|
|
||||||
|
config SAMV7_PWM1_SYNC
|
||||||
|
bool "PWM1 synchronous channels"
|
||||||
|
depends on PWM_MULTICHAN
|
||||||
|
default n
|
||||||
|
---help---
|
||||||
|
This option makes the synchronization between channels possible.
|
||||||
|
This means every synchronized channel has the same clock, the
|
||||||
|
same period and the same alignment. If any channel is defined
|
||||||
|
as synchronous, channel 0 is defined as synchronous too because
|
||||||
|
channel 0's counter is used by other synchronous channels.
|
||||||
|
This option automatically defines channel 0 as synchronous.
|
||||||
|
|
||||||
config SAMV7_PWM1_CH0
|
config SAMV7_PWM1_CH0
|
||||||
bool "PWM1 Channel 0"
|
bool "PWM1 Channel 0"
|
||||||
default n
|
default n
|
||||||
@ -937,6 +976,11 @@ config SAMV7_PWM1_CH1_COMP
|
|||||||
depends on !SAMV7_PWM1_CH1_LONLY
|
depends on !SAMV7_PWM1_CH1_LONLY
|
||||||
default n
|
default n
|
||||||
|
|
||||||
|
config SAMV7_PWM1_CH1_SYNC
|
||||||
|
bool "Synchronous channel"
|
||||||
|
depends on SAMV7_PWM1_SYNC
|
||||||
|
default n
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
config SAMV7_PWM1_CH2
|
config SAMV7_PWM1_CH2
|
||||||
@ -954,6 +998,11 @@ config SAMV7_PWM1_CH2_COMP
|
|||||||
depends on !SAMV7_PWM1_CH2_LONLY
|
depends on !SAMV7_PWM1_CH2_LONLY
|
||||||
default n
|
default n
|
||||||
|
|
||||||
|
config SAMV7_PWM1_CH2_SYNC
|
||||||
|
bool "Synchronous channel"
|
||||||
|
depends on SAMV7_PWM1_SYNC
|
||||||
|
default n
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
config SAMV7_PWM1_CH3
|
config SAMV7_PWM1_CH3
|
||||||
@ -971,6 +1020,11 @@ config SAMV7_PWM1_CH3_COMP
|
|||||||
depends on !SAMV7_PWM1_CH3_LONLY
|
depends on !SAMV7_PWM1_CH3_LONLY
|
||||||
default n
|
default n
|
||||||
|
|
||||||
|
config SAMV7_PWM1_CH3_SYNC
|
||||||
|
bool "Synchronous channel"
|
||||||
|
depends on SAMV7_PWM1_SYNC
|
||||||
|
default n
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
menu "PWM Comparison units"
|
menu "PWM Comparison units"
|
||||||
|
@ -65,6 +65,13 @@
|
|||||||
#define PWM_RES 65535
|
#define PWM_RES 65535
|
||||||
#define COMP_UNITS_NUM 8
|
#define COMP_UNITS_NUM 8
|
||||||
|
|
||||||
|
/* Sync offset flags defines */
|
||||||
|
|
||||||
|
#define CH0_SYNC_FLAG (1 << 0)
|
||||||
|
#define CH1_SYNC_FLAG (1 << 1)
|
||||||
|
#define CH2_SYNC_FLAG (1 << 2)
|
||||||
|
#define CH3_SYNC_FLAG (1 << 3)
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -104,6 +111,7 @@ struct sam_pwm_s
|
|||||||
const struct sam_pwm_fault_s *fault;
|
const struct sam_pwm_fault_s *fault;
|
||||||
uint8_t channels_num; /* Number of channels */
|
uint8_t channels_num; /* Number of channels */
|
||||||
uintptr_t base; /* Base address of peripheral register */
|
uintptr_t base; /* Base address of peripheral register */
|
||||||
|
uint8_t sync; /* Flags of synchronized channels */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* PWM driver methods */
|
/* PWM driver methods */
|
||||||
@ -229,6 +237,38 @@ static struct sam_pwm_fault_s g_pwm0_fault =
|
|||||||
.gpio_2 = GPIO_PWMC0_FI2,
|
.gpio_2 = GPIO_PWMC0_FI2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Define sync flags */
|
||||||
|
|
||||||
|
#ifdef CONFIG_SAMV7_PWM0_SYNC
|
||||||
|
#define PWM0_CH0_SYNC_FLAG CH0_SYNC_FLAG
|
||||||
|
|
||||||
|
#ifdef CONFIG_SAMV7_PWM0_CH1_SYNC
|
||||||
|
#define PWM0_CH1_SYNC_FLAG CH1_SYNC_FLAG
|
||||||
|
#else
|
||||||
|
#define PWM0_CH1_SYNC_FLAG 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_SAMV7_PWM0_CH2_SYNC
|
||||||
|
#define PWM0_CH2_SYNC_FLAG CH2_SYNC_FLAG
|
||||||
|
#else
|
||||||
|
#define PWM0_CH2_SYNC_FLAG 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_SAMV7_PWM0_CH3_SYNC
|
||||||
|
#define PWM0_CH3_SYNC_FLAG CH3_SYNC_FLAG
|
||||||
|
#else
|
||||||
|
#define PWM0_CH3_SYNC_FLAG 0
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define PWM0_CH0_SYNC_FLAG 0
|
||||||
|
#define PWM0_CH1_SYNC_FLAG 0
|
||||||
|
#define PWM0_CH2_SYNC_FLAG 0
|
||||||
|
#define PWM0_CH3_SYNC_FLAG 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PWM0_SYNC_FLAGS (PWM0_CH0_SYNC_FLAG | PWM0_CH1_SYNC_FLAG | \
|
||||||
|
PWM0_CH2_SYNC_FLAG | PWM0_CH3_SYNC_FLAG)
|
||||||
|
|
||||||
static struct sam_pwm_s g_pwm0 =
|
static struct sam_pwm_s g_pwm0 =
|
||||||
{
|
{
|
||||||
.ops = &g_pwmops,
|
.ops = &g_pwmops,
|
||||||
@ -237,6 +277,7 @@ static struct sam_pwm_s g_pwm0 =
|
|||||||
.fault = &g_pwm0_fault,
|
.fault = &g_pwm0_fault,
|
||||||
.channels_num = PWM0_NCHANNELS,
|
.channels_num = PWM0_NCHANNELS,
|
||||||
.base = SAM_PWM0_BASE,
|
.base = SAM_PWM0_BASE,
|
||||||
|
.sync = PWM0_SYNC_FLAGS,
|
||||||
};
|
};
|
||||||
#endif /* CONFIG_SAMV7_PWM0 */
|
#endif /* CONFIG_SAMV7_PWM0 */
|
||||||
|
|
||||||
@ -340,6 +381,38 @@ static struct sam_pwm_fault_s g_pwm1_fault =
|
|||||||
.gpio_2 = GPIO_PWMC1_FI2,
|
.gpio_2 = GPIO_PWMC1_FI2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Define sync flags */
|
||||||
|
|
||||||
|
#ifdef CONFIG_SAMV7_PWM1_SYNC
|
||||||
|
#define PWM1_CH0_SYNC_FLAG CH0_SYNC_FLAG
|
||||||
|
|
||||||
|
#ifdef CONFIG_SAMV7_PWM1_CH1_SYNC
|
||||||
|
#define PWM1_CH1_SYNC_FLAG CH1_SYNC_FLAG
|
||||||
|
#else
|
||||||
|
#define PWM1_CH1_SYNC_FLAG 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_SAMV7_PWM1_CH2_SYNC
|
||||||
|
#define PWM1_CH2_SYNC_FLAG CH2_SYNC_FLAG
|
||||||
|
#else
|
||||||
|
#define PWM1_CH2_SYNC_FLAG 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_SAMV7_PWM1_CH3_SYNC
|
||||||
|
#define PWM1_CH3_SYNC_FLAG CH3_SYNC_FLAG
|
||||||
|
#else
|
||||||
|
#define PWM1_CH3_SYNC_FLAG 0
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define PWM1_CH0_SYNC_FLAG 0
|
||||||
|
#define PWM1_CH1_SYNC_FLAG 0
|
||||||
|
#define PWM1_CH2_SYNC_FLAG 0
|
||||||
|
#define PWM1_CH3_SYNC_FLAG 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PWM1_SYNC_FLAGS (PWM1_CH0_SYNC_FLAG | PWM1_CH1_SYNC_FLAG | \
|
||||||
|
PWM1_CH2_SYNC_FLAG | PWM1_CH3_SYNC_FLAG)
|
||||||
|
|
||||||
static struct sam_pwm_s g_pwm1 =
|
static struct sam_pwm_s g_pwm1 =
|
||||||
{
|
{
|
||||||
.ops = &g_pwmops,
|
.ops = &g_pwmops,
|
||||||
@ -348,6 +421,7 @@ static struct sam_pwm_s g_pwm1 =
|
|||||||
.fault = &g_pwm1_fault,
|
.fault = &g_pwm1_fault,
|
||||||
.channels_num = PWM1_NCHANNELS,
|
.channels_num = PWM1_NCHANNELS,
|
||||||
.base = SAM_PWM1_BASE,
|
.base = SAM_PWM1_BASE,
|
||||||
|
.sync = PWM1_SYNC_FLAGS,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -496,10 +570,14 @@ static void pwm_set_output(struct pwm_lowerhalf_s *dev, uint8_t channel,
|
|||||||
width);
|
width);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable the channel */
|
|
||||||
|
|
||||||
regval = CHID_SEL(1 << channel);
|
regval = CHID_SEL(1 << channel);
|
||||||
pwm_putreg(priv, SAMV7_PWM_ENA, regval);
|
|
||||||
|
/* The enabling of a channel should be only done on unsynced channels */
|
||||||
|
|
||||||
|
if (!(priv->sync & regval))
|
||||||
|
{
|
||||||
|
pwm_putreg(priv, SAMV7_PWM_ENA, regval);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -684,6 +762,13 @@ static void pwm_set_polarity(struct pwm_lowerhalf_s *dev, uint8_t channel,
|
|||||||
struct sam_pwm_s *priv = (struct sam_pwm_s *)dev;
|
struct sam_pwm_s *priv = (struct sam_pwm_s *)dev;
|
||||||
uint16_t regval;
|
uint16_t regval;
|
||||||
|
|
||||||
|
/* Can't change polarity, if the channel is enabled! */
|
||||||
|
|
||||||
|
if (pwm_getreg(priv, SAMV7_PWM_SR) & CHID_SEL(1 << channel))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
regval = pwm_getreg(priv, SAMV7_PWM_CMRX + (channel * CHANNEL_OFFSET));
|
regval = pwm_getreg(priv, SAMV7_PWM_CMRX + (channel * CHANNEL_OFFSET));
|
||||||
regval &= ~CMR_CPOL;
|
regval &= ~CMR_CPOL;
|
||||||
regval &= ~CMR_DPOLI;
|
regval &= ~CMR_DPOLI;
|
||||||
@ -810,6 +895,14 @@ static int pwm_setup(struct pwm_lowerhalf_s *dev)
|
|||||||
pwm_putreg(priv, SAMV7_PWM_FPV1, 0);
|
pwm_putreg(priv, SAMV7_PWM_FPV1, 0);
|
||||||
pwm_putreg(priv, SAMV7_PWM_FPV2, 0);
|
pwm_putreg(priv, SAMV7_PWM_FPV2, 0);
|
||||||
|
|
||||||
|
/* Enable synchronous channels. The flags in priv->sync
|
||||||
|
* correspond to the lowest bits in PWM_SCM.
|
||||||
|
* UPDM[1:0] is set to zero (manual update of deadtime, duty).
|
||||||
|
*/
|
||||||
|
|
||||||
|
regval = (uint32_t)priv->sync;
|
||||||
|
pwm_putreg(priv, SAMV7_PWM_SCM, regval);
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -864,9 +957,7 @@ static int pwm_start(struct pwm_lowerhalf_s *dev,
|
|||||||
const struct pwm_info_s *info)
|
const struct pwm_info_s *info)
|
||||||
{
|
{
|
||||||
struct sam_pwm_s *priv = (struct sam_pwm_s *)dev;
|
struct sam_pwm_s *priv = (struct sam_pwm_s *)dev;
|
||||||
#ifdef CONFIG_PWM_OVERWRITE
|
|
||||||
uint32_t regval;
|
uint32_t regval;
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_PWM_MULTICHAN
|
#ifdef CONFIG_PWM_MULTICHAN
|
||||||
for (int i = 0; i < PWM_NCHANNELS; i++)
|
for (int i = 0; i < PWM_NCHANNELS; i++)
|
||||||
@ -920,6 +1011,25 @@ static int pwm_start(struct pwm_lowerhalf_s *dev,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Perform the update of synchronized PWM channels */
|
||||||
|
|
||||||
|
if (priv->sync)
|
||||||
|
{
|
||||||
|
regval = SCUC_UPDULOCK;
|
||||||
|
|
||||||
|
/* Enable the Channel 0 if synchronous channels are used.
|
||||||
|
* Channel 0's counter is used by all synchronous channels and
|
||||||
|
* enabling CH0 results in enabling all synchronous channels.
|
||||||
|
*
|
||||||
|
* Enable the CH0 here after all setting all channel parameters,
|
||||||
|
* because setting polarity configurations requires disabled
|
||||||
|
* channels.
|
||||||
|
*/
|
||||||
|
|
||||||
|
pwm_putreg(priv, SAMV7_PWM_ENA, CHID_SEL(1));
|
||||||
|
pwm_putreg(priv, SAMV7_PWM_SCUC, regval);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
/* Set the frequency and enable PWM output just for first channel */
|
/* Set the frequency and enable PWM output just for first channel */
|
||||||
|
|
||||||
@ -969,6 +1079,12 @@ static int pwm_stop(struct pwm_lowerhalf_s *dev)
|
|||||||
pwm_putreg(priv, SAMV7_PWM_DIS, regval);
|
pwm_putreg(priv, SAMV7_PWM_DIS, regval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Just to be sure, disable all sync channels too */
|
||||||
|
|
||||||
|
regval = pwm_getreg(priv, SAMV7_PWM_SCM);
|
||||||
|
regval &= ~(CHID_SEL(1 << 0) | CHID_SEL(1 << 1) |
|
||||||
|
CHID_SEL(1 << 2) | CHID_SEL(1 << 3));
|
||||||
|
pwm_putreg(priv, SAMV7_PWM_SCM, regval);
|
||||||
#else
|
#else
|
||||||
regval = CHID_SEL(1 << priv->channels[0].channel);
|
regval = CHID_SEL(1 << priv->channels[0].channel);
|
||||||
pwm_putreg(priv, SAMV7_PWM_DIS, regval);
|
pwm_putreg(priv, SAMV7_PWM_DIS, regval);
|
||||||
|
Loading…
Reference in New Issue
Block a user