This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 93097be705 samv7: add support for PWM fault protection
93097be705 is described below
commit 93097be705b4b807e9f9bb693d74cbcf0a97bb37
Author: Michal Lenc <[email protected]>
AuthorDate: Mon Feb 27 16:27:44 2023 +0100
samv7: add support for PWM fault protection
This commit adds configurable fault protection to SAMv7 PWM driver.
The fault input can be used from peripherals as ADC or GPIO inputs.
Inputs from GPIO have configurable polarity (high or low). The PWM output
is automatically set to zero if fault input is active and restored
if fault input is not actived.
Signed-off-by: Michal Lenc <[email protected]>
---
arch/arm/src/samv7/Kconfig | 139 ++++++++++++++++++++++++++++++++++++++++
arch/arm/src/samv7/sam_pwm.c | 73 +++++++++++++++++++--
arch/arm/src/samv7/sam_pwm.h | 148 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 354 insertions(+), 6 deletions(-)
diff --git a/arch/arm/src/samv7/Kconfig b/arch/arm/src/samv7/Kconfig
index f10315941d..85019d244c 100644
--- a/arch/arm/src/samv7/Kconfig
+++ b/arch/arm/src/samv7/Kconfig
@@ -770,6 +770,75 @@ config SAMV7_PWM
endmenu
+menu "PWM Fault inputs"
+
+config SAMV7_PWM0_PA9
+ bool "External fault input from PA9"
+ default n
+
+if SAMV7_PWM1_PA9
+
+config SAMV7_PWM1_PA9_POL
+ bool "Inverted polarity"
+ default n
+ ---help---
+ Fault input is by default active on high level. This config
+ inverts the logic and makes fault active on low level.
+
+endif
+
+config SAMV7_PWM0_PD8
+ bool "External fault input from PD8"
+ default n
+
+if SAMV7_PWM1_PD8
+
+config SAMV7_PWM1_PD8_POL
+ bool "Inverted polarity"
+ default n
+ ---help---
+ Fault input is by default active on high level. This config
+ inverts the logic and makes fault active on low level.
+
+endif
+
+config SAMV7_PWM0_PD9
+ bool "External fault input from PD9"
+ default n
+
+if SAMV7_PWM1_PD9
+
+config SAMV7_PWM1_PD9_POL
+ bool "Inverted polarity"
+ default n
+ ---help---
+ Fault input is by default active on high level. This config
+ inverts the logic and makes fault active on low level.
+
+endif
+
+config SAMV7_PWM0_PMC
+ bool "External fault input from PMC"
+ default n
+
+config SAMV7_PWM0_AFEC0
+ bool "External fault input from AFEC0"
+ default n
+
+config SAMV7_PWM0_AFEC1
+ bool "External fault input from AFEC1"
+ default n
+
+config SAMV7_PWM0_ACC
+ bool "External fault input from ACC"
+ default n
+
+config SAMV7_PWM0_TIM0
+ bool "External fault input from Timer 0"
+ default n
+
+endmenu
+
config SAMV7_PWM0_EVENT0
bool "Generate trigger on Event Line 0"
default n
@@ -915,6 +984,76 @@ config SAMV7_PWM1_TRIG7
endmenu
+menu "PWM Fault inputs"
+
+config SAMV7_PWM1_PA21
+ bool "External fault input from PA21"
+ default n
+
+if SAMV7_PWM1_PA21
+
+config SAMV7_PWM1_PA21_POL
+ bool "Inverted polarity"
+ default n
+ ---help---
+ Fault input is by default active on high level. This config
+ inverts the logic and makes fault active on low level.
+
+endif
+
+config SAMV7_PWM1_PA26
+ bool "External fault input from PA26"
+ default n
+
+if SAMV7_PWM1_PA26
+
+config SAMV7_PWM1_PA26_POL
+ bool "Inverted polarity"
+ default n
+ ---help---
+ Fault input is by default active on high level. This config
+ inverts the logic and makes fault active on low level.
+
+endif
+
+config SAMV7_PWM1_PA28
+ bool "External fault input from PA28"
+ default n
+
+if SAMV7_PWM1_PA28
+
+config SAMV7_PWM1_PA28_POL
+ bool "Inverted polarity"
+ default n
+ ---help---
+ Fault input is by default active on high level. This config
+ inverts the logic and makes fault active on low level.
+
+endif
+
+config SAMV7_PWM1_PMC
+ bool "External fault input from PMC"
+ default n
+
+config SAMV7_PWM1_AFEC0
+ bool "External fault input from AFEC0"
+ default n
+
+config SAMV7_PWM1_AFEC1
+ bool "External fault input from AFEC1"
+ default n
+
+config SAMV7_PWM1_ACC
+ bool "External fault input from ACC"
+ default n
+
+config SAMV7_PWM1_TIM0
+ bool "External fault input from Timer 0"
+ default n
+
+endmenu
+
+
config SAMV7_PWM1_EVENT0
bool "Generate trigger on Event Line 0"
default n
diff --git a/arch/arm/src/samv7/sam_pwm.c b/arch/arm/src/samv7/sam_pwm.c
index 67c3c5f369..b59b545e76 100644
--- a/arch/arm/src/samv7/sam_pwm.c
+++ b/arch/arm/src/samv7/sam_pwm.c
@@ -60,6 +60,7 @@
#define CHANNEL_OFFSET 0x20
#define COMP_OFFSET 0x10
+#define FAULT_SEL_OFFSET 0x8
#define CLK_FREQ BOARD_MCK_FREQUENCY
#define PWM_RES 65535
#define COMP_UNITS_NUM 8
@@ -86,11 +87,21 @@ struct sam_pwm_comparison_s
int event1;
};
+struct sam_pwm_fault_s
+{
+ uint8_t source; /* Source of fault input */
+ uint8_t polarity;
+ gpio_pinset_t gpio_0; /* GPIO 1 fault input */
+ gpio_pinset_t gpio_1; /* GPIO 2 fault input */
+ gpio_pinset_t gpio_2; /* GPIO 3 fault input */
+};
+
struct sam_pwm_s
{
const struct pwm_ops_s *ops; /* PWM operations */
const struct sam_pwm_channel_s *channels;
const struct sam_pwm_comparison_s *comparison;
+ const struct sam_pwm_fault_s *fault;
uint8_t channels_num; /* Number of channels */
uintptr_t base; /* Base address of peripheral register */
};
@@ -189,11 +200,21 @@ static struct sam_pwm_comparison_s g_pwm0_comparison =
#endif
};
+static struct sam_pwm_fault_s g_pwm0_fault =
+{
+ .source = PWM0_FAULTS,
+ .polarity = PWM0_POL,
+ .gpio_0 = GPIO_PWMC0_FI0,
+ .gpio_1 = GPIO_PWMC0_FI1,
+ .gpio_2 = GPIO_PWMC0_FI2,
+};
+
static struct sam_pwm_s g_pwm0 =
{
.ops = &g_pwmops,
.channels = g_pwm0_channels,
.comparison = &g_pwm0_comparison,
+ .fault = &g_pwm0_fault,
.channels_num = PWM0_NCHANNELS,
.base = SAM_PWM0_BASE,
};
@@ -270,17 +291,26 @@ static struct sam_pwm_comparison_s g_pwm1_comparison =
#endif
};
+static struct sam_pwm_fault_s g_pwm1_fault =
+{
+ .source = PWM1_FAULTS,
+ .polarity = PWM1_POL,
+ .gpio_0 = GPIO_PWMC1_FI0,
+ .gpio_1 = GPIO_PWMC1_FI1,
+ .gpio_2 = GPIO_PWMC1_FI2,
+};
+
static struct sam_pwm_s g_pwm1 =
{
.ops = &g_pwmops,
.channels = g_pwm1_channels,
.comparison = &g_pwm1_comparison,
+ .fault = &g_pwm1_fault,
.channels_num = PWM1_NCHANNELS,
.base = SAM_PWM1_BASE,
};
#endif
-
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
@@ -566,13 +596,45 @@ static int pwm_setup(struct pwm_lowerhalf_s *dev)
pwm_putreg(priv, SAMV7_PWM_DTX + (channel * CHANNEL_OFFSET), 0);
- /* Fault protection registers */
+ /* Enable fault protection if configured. The protection has to
+ * be enabled for every configured channel separately.
+ */
- pwm_putreg(priv, SAMV7_PWM_FPV1, 0);
- pwm_putreg(priv, SAMV7_PWM_FPV2, 0);
- pwm_putreg(priv, SAMV7_PWM_FPE, 0);
+ regval = pwm_getreg(priv, SAMV7_PWM_FPE);
+ regval |= priv->fault->source << (FAULT_SEL_OFFSET * channel);
+ pwm_putreg(priv, SAMV7_PWM_FPE, regval);
}
+ /* Configure fault GPIOs if used */
+
+ if (priv->fault->source & 1)
+ {
+ sam_configgpio(priv->fault->gpio_0);
+ }
+
+ if (priv->fault->source & (1 << 1))
+ {
+ sam_configgpio(priv->fault->gpio_1);
+ }
+
+ if (priv->fault->source & (1 << 2))
+ {
+ sam_configgpio(priv->fault->gpio_2);
+ }
+
+ /* Set fault polarity. This has to be 1 for peripheral fault
+ * generation (from ADC for example), GPIO generated fault
+ * is set via configuration options.
+ */
+
+ regval = FMR_FPOL_SEL(priv->fault->polarity);
+ pwm_putreg(priv, SAMV7_PWM_FMR, regval);
+
+ /* Force both outputs to 0 if fault occurs */
+
+ pwm_putreg(priv, SAMV7_PWM_FPV1, 0);
+ pwm_putreg(priv, SAMV7_PWM_FPV2, 0);
+
return OK;
}
@@ -653,7 +715,6 @@ static int pwm_start(struct pwm_lowerhalf_s *dev,
info->frequency);
pwm_set_output(dev, priv->channels[index - 1].channel,
info->channels[i].duty);
-
#ifdef CONFIG_PWM_OVERWRITE
if (info->channels[i].ch_outp_ovrwr)
{
diff --git a/arch/arm/src/samv7/sam_pwm.h b/arch/arm/src/samv7/sam_pwm.h
index b21bd6c3e8..a1f1e70f83 100644
--- a/arch/arm/src/samv7/sam_pwm.h
+++ b/arch/arm/src/samv7/sam_pwm.h
@@ -88,6 +88,154 @@
#define PWM1_NCHANNELS (PWM1_CH0 + PWM1_CH1 + PWM1_CH2 + PWM1_CH3)
+/* Fault protection */
+
+#ifdef CONFIG_SAMV7_PWM0_PA9
+#define PWM0_PA9 1
+#ifdef CONFIG_SAMV7_PWM0_PA9_POL
+#define PWM0_PA9_POL 0
+#else
+#define PWM0_PA9_POL 1
+#endif
+#else
+#define PWM0_PA9 0
+#define PWM0_PA9_POL 0
+#endif
+
+#ifdef CONFIG_SAMV7_PWM0_PD8
+#define PWM0_PD8 (1 << 1)
+#ifdef CONFIG_SAMV7_PWM0_PD8_POL
+#define PWM0_PD8_POL 0
+#else
+#define PWM0_PD8_POL (1 << 1)
+#endif
+#else
+#define PWM0_PD8 0
+#define PWM0_PD8_POL 0
+#endif
+
+#ifdef CONFIG_SAMV7_PWM0_PD9
+#define PWM0_PD9 (1 << 2)
+#ifdef CONFIG_SAMV7_PWM0_PD9_POL
+#define PWM0_PD9_POL 0
+#else
+#define PWM0_PD9_POL (1 << 2)
+#endif
+#else
+#define PWM0_PD9 0
+#define PWM0_PD9_POL 0
+#endif
+
+#ifdef CONFIG_SAMV7_PWM0_PMC
+#define PWM0_PMC (1 << 3)
+#else
+#define PWM0_PMC 0
+#endif
+
+#ifdef CONFIG_SAMV7_PWM0_AFEC0
+#define PWM0_AFEC0 (1 << 4)
+#else
+#define PWM0_AFEC0 0
+#endif
+
+#ifdef CONFIG_SAMV7_PWM0_AFEC1
+#define PWM0_AFEC1 (1 << 5)
+#else
+#define PWM0_AFEC1 0
+#endif
+
+#ifdef CONFIG_SAMV7_PWM0_ACC
+#define PWM0_ACC (1 << 6)
+#else
+#define PWM0_ACC 0
+#endif
+
+#ifdef CONFIG_SAMV7_PWM0_TIM0
+#define PWM0_TIM0 (1 << 7)
+#else
+#define PWM0_TIM0 0
+#endif
+
+#define PWM0_FAULTS (PWM0_PA9 + PWM0_PD8 + PWM0_PD9 + PWM0_PMC + \
+ PWM0_AFEC0 + PWM0_AFEC1 + PWM0_ACC + PWM0_TIM0)
+
+#define PWM0_POL (PWM0_PA9_POL + PWM0_PD8_POL + PWM0_PD9_POL + \
+ PWM0_PMC + PWM0_AFEC0 + PWM0_AFEC1 + PWM0_ACC + \
+ PWM0_TIM0)
+
+#ifdef CONFIG_SAMV7_PWM1_PA21
+#define PWM1_PA21 1
+#ifdef CONFIG_SAMV7_PWM1_PA21_POL
+#define PWM1_PA21_POL 0
+#else
+#define PWM1_PA21_POL 1
+#endif
+#else
+#define PWM1_PA21 0
+#define PWM1_PA21_POL 0
+#endif
+
+#ifdef CONFIG_SAMV7_PWM1_PA26
+#define PWM1_PA26 (1 << 1)
+#ifdef CONFIG_SAMV7_PWM1_PA26_POL
+#define PWM1_PA26_POL 0
+#else
+#define PWM1_PA26_POL (1 << 1)
+#endif
+#else
+#define PWM1_PA26 0
+#define PWM1_PA26_POL 0
+#endif
+
+#ifdef CONFIG_SAMV7_PWM1_PA28
+#define PWM1_PA28 (1 << 2)
+#ifdef CONFIG_SAMV7_PWM1_PA28_POL
+#define PWM1_PA28_POL 0
+#else
+#define PWM1_PA28_POL (1 << 2)
+#endif
+#else
+#define PWM1_PA28 0
+#define PWM1_PA28_POL 0
+#endif
+
+#ifdef CONFIG_SAMV7_PWM1_PMC
+#define PWM1_PMC (1 << 3)
+#else
+#define PWM1_PMC 0
+#endif
+
+#ifdef CONFIG_SAMV7_PWM1_AFEC0
+#define PWM1_AFEC0 (1 << 4)
+#else
+#define PWM1_AFEC0 0
+#endif
+
+#ifdef CONFIG_SAMV7_PWM1_AFEC1
+#define PWM1_AFEC1 (1 << 5)
+#else
+#define PWM1_AFEC1 0
+#endif
+
+#ifdef CONFIG_SAMV7_PWM1_ACC
+#define PWM1_ACC (1 << 6)
+#else
+#define PWM1_ACC 0
+#endif
+
+#ifdef CONFIG_SAMV7_PWM1_TIM0
+#define PWM1_TIM0 (1 << 7)
+#else
+#define PWM1_TIM0 0
+#endif
+
+#define PWM1_FAULTS (PWM1_PA21 + PWM1_PA26 + PWM1_PA28 + PWM1_PMC + \
+ PWM1_AFEC0 + PWM1_AFEC1 + PWM1_ACC + PWM1_TIM0)
+
+#define PWM1_POL (PWM1_PA21_POL + PWM1_PA26_POL + PWM1_PA28_POL + \
+ PWM1_PMC + PWM1_AFEC0 + PWM1_AFEC1 + PWM1_ACC + \
+ PWM1_TIM0)
+
/****************************************************************************
* Public Function Prototypes
****************************************************************************/