samv7: add support for ADC conversion triggering with PWM
This commit enhances ADC and PWM drivers with option to trigger ADC conversion with events generated by PWM comparison units. The generation of PWM events is handled by comparison units set up from Kconfig option SAMV7_PWMx_TRIGn. ADC triggering from PWM can be selected by AFECn_PWMTRIG option. Signed-off-by: Michal Lenc <michallenc@seznam.cz>
This commit is contained in:
parent
d77b53957c
commit
49ce1c5df7
@ -387,10 +387,18 @@ config SAMV7_ADC
|
||||
bool "12-bit ADC Controller (ADC)"
|
||||
default n
|
||||
|
||||
config SAMV7_AFEC_SWTRIG
|
||||
bool
|
||||
default n
|
||||
|
||||
config SAMV7_AFEC_TIOATRIG
|
||||
bool
|
||||
default n
|
||||
|
||||
config SAMV7_AFEC_PWMTRIG
|
||||
bool
|
||||
default n
|
||||
|
||||
menuconfig SAMV7_AFEC0
|
||||
bool "Analog Front End 0 (AFEC0)"
|
||||
default n
|
||||
@ -437,8 +445,15 @@ config SAMV7_AFEC0_TIOATRIG
|
||||
---help---
|
||||
Use output of Timer/Counter as a trigger.
|
||||
|
||||
config SAMV7_AFEC0_PWMTRIG
|
||||
bool "PWM trigger"
|
||||
select SAMV7_AFEC_PWMTRIG
|
||||
---help---
|
||||
Use output of PWM as a trigger.
|
||||
|
||||
config SAMV7_AFEC0_SWTRIG
|
||||
bool "Software trigger"
|
||||
select SAMV7_AFEC_SWTRIG
|
||||
---help---
|
||||
Use software trigger.
|
||||
|
||||
@ -462,6 +477,17 @@ config SAMV7_AFEC0_TIOACHAN
|
||||
|
||||
endif #SAMV7_AFEC0_TIOATRIG
|
||||
|
||||
if SAMV7_AFEC0_PWMTRIG
|
||||
|
||||
config SAMV7_AFEC0_PWMEVENT
|
||||
int "PWM Event Line"
|
||||
default 0
|
||||
range 0 1
|
||||
---help---
|
||||
PWM event line used for AFEC triggering. Can be either 0 or 1.
|
||||
|
||||
endif # SAMV7_AFEC0_PWM_TRIG
|
||||
|
||||
endif # SAMV7_AFEC0
|
||||
|
||||
menuconfig SAMV7_AFEC1
|
||||
@ -510,8 +536,15 @@ config SAMV7_AFEC1_TIOATRIG
|
||||
---help---
|
||||
Use output of Timer/Counter as a trigger.
|
||||
|
||||
config SAMV7_AFEC1_PWMTRIG
|
||||
bool "PWM trigger"
|
||||
select SAMV7_AFEC_PWMTRIG
|
||||
---help---
|
||||
Use output of PWM as a trigger.
|
||||
|
||||
config SAMV7_AFEC1_SWTRIG
|
||||
bool "Software trigger"
|
||||
select SAMV7_AFEC_SWTRIG
|
||||
---help---
|
||||
Use software trigger.
|
||||
|
||||
@ -535,6 +568,17 @@ config SAMV7_AFEC1_TIOACHAN
|
||||
|
||||
endif #SAMV7_AFEC1_TIOATRIG
|
||||
|
||||
if SAMV7_AFEC1_PWMTRIG
|
||||
|
||||
config SAMV7_AFEC1_PWMEVENT
|
||||
int "PWM Event Line"
|
||||
default 0
|
||||
range 0 1
|
||||
---help---
|
||||
PWM event line used for AFEC triggering. Can be either 0 or 1.
|
||||
|
||||
endif # SAMV7_AFEC1_PWM_TRIG
|
||||
|
||||
endif # SAMV7_AFEC1
|
||||
|
||||
config SAMV7_MCAN0
|
||||
@ -656,6 +700,94 @@ config SAMV7_PWM0_CH3_COMP
|
||||
|
||||
endif
|
||||
|
||||
menu "PWM Comparison units"
|
||||
|
||||
config SAMV7_PWM0_TRIG0
|
||||
int "PWM0 Comparison Unit 0 value"
|
||||
range 0 100
|
||||
default 0
|
||||
---help---
|
||||
Timer value on which the comparison unit generates
|
||||
an event. Value is in percentages.
|
||||
|
||||
config SAMV7_PWM0_TRIG1
|
||||
int "PWM0 Comparison Unit 1 value"
|
||||
range 0 100
|
||||
default 0
|
||||
---help---
|
||||
Timer value on which the comparison unit generates
|
||||
an event. Value is in percentages.
|
||||
|
||||
config SAMV7_PWM0_TRIG2
|
||||
int "PWM0 Comparison Unit 2 value"
|
||||
range 0 100
|
||||
default 0
|
||||
---help---
|
||||
Timer value on which the comparison unit generates
|
||||
an event. Value is in percentages.
|
||||
|
||||
config SAMV7_PWM0_TRIG3
|
||||
int "PWM0 Comparison Unit 3 value"
|
||||
range 0 100
|
||||
default 0
|
||||
---help---
|
||||
Timer value on which the comparison unit generates
|
||||
an event. Value is in percentages.
|
||||
|
||||
config SAMV7_PWM0_TRIG4
|
||||
int "PWM0 Comparison Unit 4 value"
|
||||
range 0 100
|
||||
default 0
|
||||
---help---
|
||||
Timer value on which the comparison unit generates
|
||||
an event. Value is in percentages.
|
||||
|
||||
config SAMV7_PWM0_TRIG5
|
||||
int "PWM0 Comparison Unit 5 value"
|
||||
range 0 100
|
||||
default 0
|
||||
---help---
|
||||
Timer value on which the comparison unit generates
|
||||
an event. Value is in percentages.
|
||||
|
||||
config SAMV7_PWM0_TRIG6
|
||||
int "PWM0 Comparison Unit 6 value"
|
||||
range 0 100
|
||||
default 0
|
||||
---help---
|
||||
Timer value on which the comparison unit generates
|
||||
an event. Value is in percentages.
|
||||
|
||||
config SAMV7_PWM0_TRIG7
|
||||
int "PWM0 Comparison Unit 7 value"
|
||||
range 0 100
|
||||
default 0
|
||||
---help---
|
||||
Timer value on which the comparison unit generates
|
||||
an event. Value is in percentages.
|
||||
|
||||
config SAMV7_PWM
|
||||
|
||||
endmenu
|
||||
|
||||
config SAMV7_PWM0_EVENT0
|
||||
bool "Generate trigger on Event Line 0"
|
||||
default n
|
||||
---help---
|
||||
PWM allows trigger generation on event lines. This can be
|
||||
used for ADC conversion triggering for example. It is
|
||||
necessary to set a comparison unit in order to generate an
|
||||
event.
|
||||
|
||||
config SAMV7_PWM0_EVENT1
|
||||
bool "Generate trigger on Event Line 1"
|
||||
default n
|
||||
---help---
|
||||
PWM allows trigger generation on event lines. This can be
|
||||
used for ADC conversion triggering for example. It is
|
||||
necessary to set a comparison unit in order to generate an
|
||||
event.
|
||||
|
||||
endif
|
||||
|
||||
menuconfig SAMV7_PWM1
|
||||
@ -715,6 +847,92 @@ config SAMV7_PWM1_CH3_COMP
|
||||
|
||||
endif
|
||||
|
||||
menu "PWM Comparison units"
|
||||
|
||||
config SAMV7_PWM1_TRIG0
|
||||
int "PWM1 Comparison Unit 0 value"
|
||||
range 0 100
|
||||
default 0
|
||||
---help---
|
||||
Timer value on which the comparison unit generates
|
||||
an event. Value is in percentages.
|
||||
|
||||
config SAMV7_PWM1_TRIG1
|
||||
int "PWM1 Comparison Unit 1 value"
|
||||
range 0 100
|
||||
default 0
|
||||
---help---
|
||||
Timer value on which the comparison unit generates
|
||||
an event. Value is in percentages.
|
||||
|
||||
config SAMV7_PWM1_TRIG2
|
||||
int "PWM1 Comparison Unit 2 value"
|
||||
range 0 100
|
||||
default 0
|
||||
---help---
|
||||
Timer value on which the comparison unit generates
|
||||
an event. Value is in percentages.
|
||||
|
||||
config SAMV7_PWM1_TRIG3
|
||||
int "PWM1 Comparison Unit 3 value"
|
||||
range 0 100
|
||||
default 0
|
||||
---help---
|
||||
Timer value on which the comparison unit generates
|
||||
an event. Value is in percentages.
|
||||
|
||||
config SAMV7_PWM1_TRIG4
|
||||
int "PWM1 Comparison Unit 4 value"
|
||||
range 0 100
|
||||
default 0
|
||||
---help---
|
||||
Timer value on which the comparison unit generates
|
||||
an event. Value is in percentages.
|
||||
|
||||
config SAMV7_PWM1_TRIG5
|
||||
int "PWM1 Comparison Unit 5 value"
|
||||
range 0 100
|
||||
default 0
|
||||
---help---
|
||||
Timer value on which the comparison unit generates
|
||||
an event. Value is in percentages.
|
||||
|
||||
config SAMV7_PWM1_TRIG6
|
||||
int "PWM1 Comparison Unit 6 value"
|
||||
range 0 100
|
||||
default 0
|
||||
---help---
|
||||
Timer value on which the comparison unit generates
|
||||
an event. Value is in percentages.
|
||||
|
||||
config SAMV7_PWM1_TRIG7
|
||||
int "PWM1 Comparison Unit 7 value"
|
||||
range 0 100
|
||||
default 0
|
||||
---help---
|
||||
Timer value on which the comparison unit generates
|
||||
an event. Value is in percentages.
|
||||
|
||||
endmenu
|
||||
|
||||
config SAMV7_PWM1_EVENT0
|
||||
bool "Generate trigger on Event Line 0"
|
||||
default n
|
||||
---help---
|
||||
PWM allows trigger generation on event lines. This can be
|
||||
used for ADC conversion triggering for example. It is
|
||||
necessary to set a comparison unit in order to generate an
|
||||
event.
|
||||
|
||||
config SAMV7_PWM1_EVENT1
|
||||
bool "Generate trigger on Event Line 1"
|
||||
default n
|
||||
---help---
|
||||
PWM allows trigger generation on event lines. This can be
|
||||
used for ADC conversion triggering for example. It is
|
||||
necessary to set a comparison unit in order to generate an
|
||||
event.
|
||||
|
||||
endif
|
||||
|
||||
config SAMV7_QSPI
|
||||
|
@ -94,6 +94,7 @@ struct samv7_dev_s
|
||||
uint8_t resolution; /* ADC resolution (SAMV7_AFECn_RES) */
|
||||
uint8_t trigger; /* ADC trigger (software, timer...) */
|
||||
uint8_t timer_channel; /* Timer channel to trigger ADC */
|
||||
uint8_t event_line; /* PWM event line to trigger ADC */
|
||||
uint32_t frequency; /* Frequency of the timer */
|
||||
int irq; /* ADC IRQ number */
|
||||
int pid; /* ADC PID number */
|
||||
@ -177,12 +178,15 @@ static struct samv7_dev_s g_adcpriv0 =
|
||||
.intf = 0,
|
||||
.initialized = 0,
|
||||
.resolution = CONFIG_SAMV7_AFEC0_RES,
|
||||
#ifdef CONFIG_SAMV7_AFEC0_SWTRIG
|
||||
.trigger = 0,
|
||||
#else
|
||||
#if defined (CONFIG_SAMV7_AFEC0_PWMTRIG)
|
||||
.trigger = 2,
|
||||
.event_line = CONFIG_SAMV7_AFEC0_PWMEVENT,
|
||||
#elif defined (CONFIG_SAMV7_AFEC0_TIOATRIG)
|
||||
.trigger = 1,
|
||||
.timer_channel = CONFIG_SAMV7_AFEC0_TIOACHAN,
|
||||
.frequency = CONFIG_SAMV7_AFEC0_TIOAFREQ,
|
||||
#else
|
||||
.trigger = 0,
|
||||
#endif
|
||||
.base = SAM_AFEC0_BASE,
|
||||
};
|
||||
@ -217,12 +221,15 @@ static struct samv7_dev_s g_adcpriv1 =
|
||||
.intf = 1,
|
||||
.initialized = 0,
|
||||
.resolution = CONFIG_SAMV7_AFEC1_RES,
|
||||
#ifdef CONFIG_SAMV7_AFEC1_SWTRIG
|
||||
.trigger = 0,
|
||||
#else
|
||||
#if defined (CONFIG_SAMV7_AFEC1_PWMTRIG)
|
||||
.trigger = 2,
|
||||
.event_line = CONFIG_SAMV7_AFEC0_PWMEVENT,
|
||||
#elif defined (CONFIG_SAMV7_AFEC1_TIOATRIG)
|
||||
.trigger = 1,
|
||||
.timer_channel = CONFIG_SAMV7_AFEC1_TIOACHAN,
|
||||
.frequency = CONFIG_SAMV7_AFEC1_TIOAFREQ,
|
||||
#else
|
||||
.trigger = 0,
|
||||
#endif
|
||||
.base = SAM_AFEC1_BASE,
|
||||
};
|
||||
@ -624,7 +631,9 @@ static int sam_afec_trigger(struct samv7_dev_s *priv)
|
||||
regval &= ~AFEC_MR_TRGSEL_MASK;
|
||||
afec_putreg(priv, SAM_AFEC_MR_OFFSET, regval);
|
||||
}
|
||||
#elif CONFIG_SAMV7_AFEC_TIOATRIG
|
||||
|
||||
#endif
|
||||
#ifdef CONFIG_SAMV7_AFEC_TIOATRIG
|
||||
if (priv->trigger == 1)
|
||||
{
|
||||
ainfo("Setup timer/counter trigger\n");
|
||||
@ -655,6 +664,31 @@ static int sam_afec_trigger(struct samv7_dev_s *priv)
|
||||
|
||||
afec_putreg(priv, SAM_AFEC_MR_OFFSET, regval);
|
||||
}
|
||||
|
||||
#endif
|
||||
#ifdef CONFIG_SAMV7_AFEC_PWMTRIG
|
||||
if (priv->trigger == 2)
|
||||
{
|
||||
regval = afec_getreg(priv, SAM_AFEC_MR_OFFSET);
|
||||
regval &= ~AFEC_MR_TRGSEL_MASK;
|
||||
|
||||
if (priv->event_line == 1)
|
||||
{
|
||||
/* PWM Event Line 1 is used for AFEC triggering */
|
||||
|
||||
regval |= AFEC_MR_TRGSEL_PWM1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* PWM Event Line 0 is used for AFEC triggering */
|
||||
|
||||
regval |= AFEC_MR_TRGSEL_PWM0;
|
||||
}
|
||||
|
||||
regval |= AFEC_MR_TRGEN;
|
||||
|
||||
afec_putreg(priv, SAM_AFEC_MR_OFFSET, regval);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
|
@ -59,8 +59,10 @@
|
||||
#endif
|
||||
|
||||
#define CHANNEL_OFFSET 0x20
|
||||
#define COMP_OFFSET 0x10
|
||||
#define CLK_FREQ BOARD_MCK_FREQUENCY
|
||||
#define PWM_RES 65535
|
||||
#define COMP_UNITS_NUM 8
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
@ -77,10 +79,18 @@ struct sam_pwm_channel_s
|
||||
gpio_pinset_t pin_l; /* PWM L output pin */
|
||||
};
|
||||
|
||||
struct sam_pwm_comparison_s
|
||||
{
|
||||
int comp_vals[COMP_UNITS_NUM];
|
||||
int event0;
|
||||
int event1;
|
||||
};
|
||||
|
||||
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;
|
||||
uint8_t channels_num; /* Number of channels */
|
||||
uintptr_t base; /* Base address of peripheral register */
|
||||
};
|
||||
@ -158,10 +168,32 @@ static struct sam_pwm_channel_s g_pwm0_channels[] =
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct sam_pwm_comparison_s g_pwm0_comparison =
|
||||
{
|
||||
.comp_vals =
|
||||
{
|
||||
CONFIG_SAMV7_PWM0_TRIG0, CONFIG_SAMV7_PWM0_TRIG1,
|
||||
CONFIG_SAMV7_PWM0_TRIG2, CONFIG_SAMV7_PWM0_TRIG3,
|
||||
CONFIG_SAMV7_PWM0_TRIG4, CONFIG_SAMV7_PWM0_TRIG5,
|
||||
CONFIG_SAMV7_PWM0_TRIG6, CONFIG_SAMV7_PWM0_TRIG7
|
||||
},
|
||||
#ifdef CONFIG_SAMV7_PWM0_EVENT0
|
||||
.event0 = 1,
|
||||
#else
|
||||
.event0 = 0,
|
||||
#endif
|
||||
#ifdef CONFIG_SAMV7_PWM0_EVENT1
|
||||
.event1 = 1,
|
||||
#else
|
||||
.event1 = 0,
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct sam_pwm_s g_pwm0 =
|
||||
{
|
||||
.ops = &g_pwmops,
|
||||
.channels = g_pwm0_channels,
|
||||
.comparison = &g_pwm0_comparison,
|
||||
.channels_num = PWM0_NCHANNELS,
|
||||
.base = SAM_PWM0_BASE,
|
||||
};
|
||||
@ -217,10 +249,32 @@ static struct sam_pwm_channel_s g_pwm1_channels[] =
|
||||
#endif
|
||||
}; /* CONFIG_SAMV7_PWM1 */
|
||||
|
||||
static struct sam_pwm_comparison_s g_pwm1_comparison =
|
||||
{
|
||||
.comp_vals =
|
||||
{
|
||||
CONFIG_SAMV7_PWM1_TRIG0, CONFIG_SAMV7_PWM1_TRIG1,
|
||||
CONFIG_SAMV7_PWM1_TRIG2, CONFIG_SAMV7_PWM1_TRIG3,
|
||||
CONFIG_SAMV7_PWM1_TRIG4, CONFIG_SAMV7_PWM1_TRIG5,
|
||||
CONFIG_SAMV7_PWM1_TRIG6, CONFIG_SAMV7_PWM1_TRIG7
|
||||
},
|
||||
#ifdef CONFIG_SAMV7_PWM0_EVENT0
|
||||
.event0 = 1,
|
||||
#else
|
||||
.event0 = 0,
|
||||
#endif
|
||||
#ifdef CONFIG_SAMV7_PWM0_EVENT1
|
||||
.event1 = 1,
|
||||
#else
|
||||
.event1 = 0,
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct sam_pwm_s g_pwm1 =
|
||||
{
|
||||
.ops = &g_pwmops,
|
||||
.channels = g_pwm1_channels,
|
||||
.comparison = &g_pwm1_comparison,
|
||||
.channels_num = PWM1_NCHANNELS,
|
||||
.base = SAM_PWM1_BASE,
|
||||
};
|
||||
@ -241,6 +295,7 @@ 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);
|
||||
static void pwm_set_comparison(struct pwm_lowerhalf_s *dev);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
@ -370,6 +425,81 @@ static void pwm_set_output(struct pwm_lowerhalf_s *dev, uint8_t channel,
|
||||
pwm_putreg(priv, SAMV7_PWM_ENA, regval);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pwm_set_comparison
|
||||
*
|
||||
* Description:
|
||||
* Set comparison units.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - A reference to the lower half PWM driver state structure
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void pwm_set_comparison(struct pwm_lowerhalf_s *dev)
|
||||
{
|
||||
struct sam_pwm_s *priv = (struct sam_pwm_s *)dev;
|
||||
uint16_t period;
|
||||
uint16_t width;
|
||||
uint16_t comp_value;
|
||||
uint8_t comp_en;
|
||||
int i;
|
||||
|
||||
/* Get the period value */
|
||||
|
||||
period = pwm_getreg(priv, SAMV7_PWM_CPRDX);
|
||||
|
||||
/* Compute PWM width (count value to set PWM low) */
|
||||
|
||||
comp_en = 0;
|
||||
|
||||
for (i = 0; i < COMP_UNITS_NUM; i++)
|
||||
{
|
||||
if (priv->comparison->comp_vals[i] == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
comp_value = b16divi(uitoub16(priv->comparison->comp_vals[i]), 100);
|
||||
|
||||
width = b16toi(comp_value * period + b16HALF);
|
||||
|
||||
/* Generate event line */
|
||||
|
||||
if (pwm_getreg(priv, SAMV7_PWM_CMPMX + COMP_OFFSET * i) & CMPM_CEN)
|
||||
{
|
||||
/* Use update register if comparision unit is used */
|
||||
|
||||
pwm_putreg(priv, SAMV7_PWM_CMPVUPDX + COMP_OFFSET * i, width);
|
||||
pwm_putreg(priv, SAMV7_PWM_CMPMUPDX + COMP_OFFSET * i, CMPM_CEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
pwm_putreg(priv, SAMV7_PWM_CMPVX + COMP_OFFSET * i, width);
|
||||
pwm_putreg(priv, SAMV7_PWM_CMPMX + COMP_OFFSET * i, CMPM_CEN);
|
||||
}
|
||||
|
||||
comp_en += 1 << i;
|
||||
}
|
||||
|
||||
if (priv->comparison->event0)
|
||||
{
|
||||
/* Enable output on Event Line 0 */
|
||||
|
||||
pwm_putreg(priv, SAMV7_PWM_ELMR1, comp_en);
|
||||
}
|
||||
|
||||
if (priv->comparison->event1)
|
||||
{
|
||||
/* Enable output on Event Line 1 */
|
||||
|
||||
pwm_putreg(priv, SAMV7_PWM_ELMR2, comp_en);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pwm_setup
|
||||
*
|
||||
@ -552,6 +682,8 @@ static int pwm_start(struct pwm_lowerhalf_s *dev,
|
||||
pwm_set_output(dev, priv->channels[0].channel, info->duty);
|
||||
#endif
|
||||
|
||||
pwm_set_comparison(dev);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user