mirror of
https://github.com/apache/nuttx.git
synced 2026-05-30 05:16:47 +08:00
imxrt: add support for ADC triggering by an external signal
Config option IMXRT_ADCx_ETC can now be used to select an external HW trigger to be used instead of continous trigger. Continous trigger is used if IMXRT_ADCx_ETC = -1 (default option). Otherwise the source signal is routed through XBAR and used as a trigger. Hardware triggering is currently limited to maximum of 8 channels. HW trigger is automatically disabled if there are more than 8 channels. The external triggering was tested with PWM signal as a source. Signed-off-by: Michal Lenc <michallenc@seznam.cz>
This commit is contained in:
@@ -87,6 +87,18 @@ ADC
|
|||||||
ADC driver with the successive approximation analog/digital converter. The lower-half of
|
ADC driver with the successive approximation analog/digital converter. The lower-half of
|
||||||
this driver is initialize by calling :c:func:`imxrt_adcinitialize`.
|
this driver is initialize by calling :c:func:`imxrt_adcinitialize`.
|
||||||
|
|
||||||
|
ADC module can use either continous trigger (next conversion is started as soon as the
|
||||||
|
previous is finished) or hardware trigger. This option is selected by IMXRT_ADCx_ETC
|
||||||
|
(x = 1, 2) config option. If IMXRT_ADCx_ETC = -1 then continous trigger is used. If
|
||||||
|
corresponding XBAR number is put in IMXRT_ADCx_ETC then that signal is used to trigger
|
||||||
|
the ADC conversion (for example PWM signal can be used as a source). For PWM XBAR options
|
||||||
|
please refer to PWM chapter of this documentation.
|
||||||
|
|
||||||
|
Hardware triggering is currently limited to maximum of 8 channels. HW trigger is automatically
|
||||||
|
disabled if there are more than 8 channels.
|
||||||
|
|
||||||
|
DMA is currently not supported for ADC modules.
|
||||||
|
|
||||||
CAN
|
CAN
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1274,11 +1274,45 @@ menuconfig IMXRT_ADC1
|
|||||||
default n
|
default n
|
||||||
select IMXRT_ADC
|
select IMXRT_ADC
|
||||||
|
|
||||||
|
if IMXRT_ADC1
|
||||||
|
|
||||||
|
config IMXRT_ADC1_ETC
|
||||||
|
int "ADC1 External Trigger"
|
||||||
|
range -1 130
|
||||||
|
default -1
|
||||||
|
---help---
|
||||||
|
ADC module can be triggered by an external source (timer, PWM, etc).
|
||||||
|
This config option selects the signal's source. The number in
|
||||||
|
IMXRT_ADC1_ETC corresponds with the XBAR number of the source (please
|
||||||
|
refer to the documentation for XBAR numbers).
|
||||||
|
|
||||||
|
-1 (default value) means the conversion is not to be triggered by an
|
||||||
|
external source.
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
menuconfig IMXRT_ADC2
|
menuconfig IMXRT_ADC2
|
||||||
bool "ADC2"
|
bool "ADC2"
|
||||||
default n
|
default n
|
||||||
select IMXRT_ADC
|
select IMXRT_ADC
|
||||||
|
|
||||||
|
if IMXRT_ADC2
|
||||||
|
|
||||||
|
config IMXRT_ADC2_ETC
|
||||||
|
int "ADC2 External Trigger"
|
||||||
|
range -1 130
|
||||||
|
default -1
|
||||||
|
---help---
|
||||||
|
ADC module can be triggered by an external source (timer, PWM, etc).
|
||||||
|
This config option selects the signal's source. The number in
|
||||||
|
IMXRT_ADC2_ETC corresponds with the XBAR number of the source (please
|
||||||
|
refer to the documentation for XBAR numbers).
|
||||||
|
|
||||||
|
-1 (default value) means the conversion is not to be triggered by an
|
||||||
|
external source.
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
config IMXRT_SEMC
|
config IMXRT_SEMC
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define TRIG_OFFSET 0x28
|
#define TRIG_OFFSET 0x28
|
||||||
|
#define IRQ_OFFSET 0x10
|
||||||
#define CHAIN_OFFSET 0x4
|
#define CHAIN_OFFSET 0x4
|
||||||
#define RESULT_OFFSET 0x4
|
#define RESULT_OFFSET 0x4
|
||||||
|
|
||||||
|
|||||||
+241
-14
@@ -42,9 +42,11 @@
|
|||||||
#include "arm_internal.h"
|
#include "arm_internal.h"
|
||||||
#include "chip.h"
|
#include "chip.h"
|
||||||
#include "hardware/imxrt_adc.h"
|
#include "hardware/imxrt_adc.h"
|
||||||
|
#include "hardware/imxrt_adc_etc.h"
|
||||||
#include "hardware/imxrt_pinmux.h"
|
#include "hardware/imxrt_pinmux.h"
|
||||||
#include "imxrt_gpio.h"
|
#include "imxrt_gpio.h"
|
||||||
#include "imxrt_periphclks.h"
|
#include "imxrt_periphclks.h"
|
||||||
|
#include "imxrt_xbar.h"
|
||||||
|
|
||||||
#ifdef CONFIG_IMXRT_ADC
|
#ifdef CONFIG_IMXRT_ADC
|
||||||
|
|
||||||
@@ -69,9 +71,15 @@ struct imxrt_dev_s
|
|||||||
uint32_t base; /* ADC register base */
|
uint32_t base; /* ADC register base */
|
||||||
uint8_t initialized; /* ADC initialization counter */
|
uint8_t initialized; /* ADC initialization counter */
|
||||||
int irq; /* ADC IRQ number */
|
int irq; /* ADC IRQ number */
|
||||||
|
int irq_etc; /* ADC_ETC IRQ number */
|
||||||
int nchannels; /* Number of configured ADC channels */
|
int nchannels; /* Number of configured ADC channels */
|
||||||
uint8_t chanlist[ADC_MAX_CHANNELS]; /* ADC channel list */
|
uint8_t chanlist[ADC_MAX_CHANNELS]; /* ADC channel list */
|
||||||
uint8_t current; /* Current channel being converted */
|
uint8_t current; /* Current channel being converted */
|
||||||
|
uint8_t trig_num; /* First usable trigger number
|
||||||
|
* (ADC1 = 0, ADC2 = 4)
|
||||||
|
*/
|
||||||
|
int16_t trig_src; /* Conversion trigger source */
|
||||||
|
uint32_t trig_clear; /* ADC_ETC IRQ clear bit */
|
||||||
};
|
};
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -83,6 +91,7 @@ static void adc_putreg(struct imxrt_dev_s *priv, uint32_t offset,
|
|||||||
static uint32_t adc_getreg(struct imxrt_dev_s *priv, uint32_t offset);
|
static uint32_t adc_getreg(struct imxrt_dev_s *priv, uint32_t offset);
|
||||||
static void adc_modifyreg(struct imxrt_dev_s *priv, uint32_t offset,
|
static void adc_modifyreg(struct imxrt_dev_s *priv, uint32_t offset,
|
||||||
uint32_t clearbits, uint32_t setbits);
|
uint32_t clearbits, uint32_t setbits);
|
||||||
|
static int adc_reset_etc(struct imxrt_dev_s *priv);
|
||||||
|
|
||||||
/* ADC methods */
|
/* ADC methods */
|
||||||
|
|
||||||
@@ -113,9 +122,13 @@ static const struct adc_ops_s g_adcops =
|
|||||||
static struct imxrt_dev_s g_adcpriv1 =
|
static struct imxrt_dev_s g_adcpriv1 =
|
||||||
{
|
{
|
||||||
.irq = IMXRT_IRQ_ADC1,
|
.irq = IMXRT_IRQ_ADC1,
|
||||||
|
.irq_etc = IMXRT_IRQ_ADCETC_0,
|
||||||
.intf = 1,
|
.intf = 1,
|
||||||
.initialized = 0,
|
.initialized = 0,
|
||||||
.base = IMXRT_ADC1_BASE,
|
.base = IMXRT_ADC1_BASE,
|
||||||
|
.trig_num = 0,
|
||||||
|
.trig_src = CONFIG_IMXRT_ADC1_ETC,
|
||||||
|
.trig_clear = ADC_ETC_DONE01_IRQ_TRIG0_DONE0,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct adc_dev_s g_adcdev1 =
|
static struct adc_dev_s g_adcdev1 =
|
||||||
@@ -149,9 +162,13 @@ gpio_pinset_t g_adcpinlist1[ADC_MAX_CHANNELS] =
|
|||||||
static struct imxrt_dev_s g_adcpriv2 =
|
static struct imxrt_dev_s g_adcpriv2 =
|
||||||
{
|
{
|
||||||
.irq = IMXRT_IRQ_ADC2,
|
.irq = IMXRT_IRQ_ADC2,
|
||||||
|
.irq_etc = IMXRT_IRQ_ADCETC_1,
|
||||||
.intf = 2,
|
.intf = 2,
|
||||||
.initialized = 0,
|
.initialized = 0,
|
||||||
.base = IMXRT_ADC2_BASE,
|
.base = IMXRT_ADC2_BASE,
|
||||||
|
.trig_num = 4,
|
||||||
|
.trig_src = CONFIG_IMXRT_ADC2_ETC,
|
||||||
|
.trig_clear = ADC_ETC_DONE01_IRQ_TRIG4_DONE1,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct adc_dev_s g_adcdev2 =
|
static struct adc_dev_s g_adcdev2 =
|
||||||
@@ -202,6 +219,117 @@ static void adc_modifyreg(struct imxrt_dev_s *priv, uint32_t offset,
|
|||||||
modifyreg32(priv->base + offset, clearbits, setbits);
|
modifyreg32(priv->base + offset, clearbits, setbits);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: adc_reset_etc
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Setup registers and channels/triggers for external trigering of ADC
|
||||||
|
* conversion. This functions also takes care of connecting XBARs.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int adc_reset_etc(struct imxrt_dev_s *priv)
|
||||||
|
{
|
||||||
|
uint32_t adc_cfg;
|
||||||
|
uint32_t regval;
|
||||||
|
uint8_t chain_num;
|
||||||
|
uint8_t chain_last;
|
||||||
|
int i;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = OK;
|
||||||
|
|
||||||
|
/* Enable HW trigger */
|
||||||
|
|
||||||
|
adc_cfg = adc_getreg(priv, IMXRT_ADC_CFG_OFFSET);
|
||||||
|
adc_cfg |= ADC_CFG_ADTRG_HW;
|
||||||
|
adc_putreg(priv, IMXRT_ADC_CFG_OFFSET, adc_cfg);
|
||||||
|
|
||||||
|
/* Disable soft reset first */
|
||||||
|
|
||||||
|
putreg32(0, IMXRT_ADCETC_BASE + IMXRT_ADC_ETC_CTRL_OFFSET);
|
||||||
|
|
||||||
|
/* Set trigger: Trigger 0 for ADC1 and trigger 4 for ADC2 */
|
||||||
|
|
||||||
|
regval = ADC_ETC_CTRL_TRIG_EN(1 << priv->trig_num);
|
||||||
|
putreg32(regval, IMXRT_ADCETC_BASE + IMXRT_ADC_ETC_CTRL_OFFSET);
|
||||||
|
|
||||||
|
/* 0 means trigger length is 1 so we need to set priv->nchannels -1
|
||||||
|
* length. Priority is set to 7 (highest).
|
||||||
|
*/
|
||||||
|
|
||||||
|
regval = ADC_ETC_TRIG_CTRL_TRIG_CHAIN(priv->nchannels - 1) |
|
||||||
|
ADC_ETC_TRIG_CTRL_TRIG_PR(7);
|
||||||
|
putreg32(regval, IMXRT_ADCETC_BASE + IMXRT_ADC_ETC_TRIG_CTRL_OFFSET
|
||||||
|
+ TRIG_OFFSET * priv->trig_num);
|
||||||
|
|
||||||
|
chain_num = 0;
|
||||||
|
chain_last = 0;
|
||||||
|
for (i = 0; i < priv->nchannels; i++)
|
||||||
|
{
|
||||||
|
/* Check whether this is the last chain to be added */
|
||||||
|
|
||||||
|
if (i == priv->nchannels - 1)
|
||||||
|
{
|
||||||
|
/* If this is last chain we need to enable interrupt for it.
|
||||||
|
* 1 for ADC1, 2 for ADC0.
|
||||||
|
*/
|
||||||
|
|
||||||
|
chain_last = priv->intf;
|
||||||
|
}
|
||||||
|
|
||||||
|
regval = getreg32(IMXRT_ADCETC_BASE +
|
||||||
|
IMXRT_ADC_ETC_TRIG_CHAIN_OFFSET +
|
||||||
|
TRIG_OFFSET * priv->trig_num +
|
||||||
|
CHAIN_OFFSET * chain_num);
|
||||||
|
|
||||||
|
/* Set up chain registers */
|
||||||
|
|
||||||
|
if (i % 2 == 0)
|
||||||
|
{
|
||||||
|
regval &= ~(ADC_ETC_TRIG_CHAIN_CSEL0_MASK |
|
||||||
|
ADC_ETC_TRIG_CHAIN_HTWS0_MASK |
|
||||||
|
ADC_ETC_TRIG_CHAIN_IE0_MASK |
|
||||||
|
ADC_ETC_TRIG_CHAIN_B2B0);
|
||||||
|
regval |= ADC_ETC_TRIG_CHAIN_CSEL0(priv->chanlist[i]) |
|
||||||
|
ADC_ETC_TRIG_CHAIN_HWTS0(1 << i) |
|
||||||
|
ADC_ETC_TRIG_CHAIN_IE0(chain_last) |
|
||||||
|
ADC_ETC_TRIG_CHAIN_B2B0;
|
||||||
|
putreg32(regval, IMXRT_ADCETC_BASE +
|
||||||
|
IMXRT_ADC_ETC_TRIG_CHAIN_OFFSET +
|
||||||
|
TRIG_OFFSET * priv->trig_num +
|
||||||
|
CHAIN_OFFSET * chain_num);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
regval &= ~(ADC_ETC_TRIG_CHAIN_CSEL1_MASK |
|
||||||
|
ADC_ETC_TRIG_CHAIN_HTWS1_MASK |
|
||||||
|
ADC_ETC_TRIG_CHAIN_IE1_MASK |
|
||||||
|
ADC_ETC_TRIG_CHAIN_B2B1);
|
||||||
|
regval |= ADC_ETC_TRIG_CHAIN_CSEL1(priv->chanlist[i]) |
|
||||||
|
ADC_ETC_TRIG_CHAIN_HWTS1(1 << i) |
|
||||||
|
ADC_ETC_TRIG_CHAIN_IE1(chain_last) |
|
||||||
|
ADC_ETC_TRIG_CHAIN_B2B1;
|
||||||
|
putreg32(regval, IMXRT_ADCETC_BASE +
|
||||||
|
IMXRT_ADC_ETC_TRIG_CHAIN_OFFSET +
|
||||||
|
TRIG_OFFSET * priv->trig_num +
|
||||||
|
CHAIN_OFFSET * chain_num);
|
||||||
|
chain_num += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = imxrt_xbar_connect(IMXRT_XBARA1_OUT_ADC_ETC_XBAR0_TRIG0_SEL_OFFSET
|
||||||
|
+ priv->trig_num,
|
||||||
|
IMXRT_XBARA1(XBAR_OUTPUT, priv->trig_src));
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
aerr("ERROR: imxrt_xbar_connect failed: %d\n", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: adc_bind
|
* Name: adc_bind
|
||||||
*
|
*
|
||||||
@@ -234,6 +362,7 @@ static void adc_reset(struct adc_dev_s *dev)
|
|||||||
{
|
{
|
||||||
struct imxrt_dev_s *priv = (struct imxrt_dev_s *)dev->ad_priv;
|
struct imxrt_dev_s *priv = (struct imxrt_dev_s *)dev->ad_priv;
|
||||||
irqstate_t flags;
|
irqstate_t flags;
|
||||||
|
int ret;
|
||||||
|
|
||||||
flags = enter_critical_section();
|
flags = enter_critical_section();
|
||||||
|
|
||||||
@@ -333,6 +462,31 @@ static void adc_reset(struct adc_dev_s *dev)
|
|||||||
imxrt_config_gpio(pinset);
|
imxrt_config_gpio(pinset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* priv->nchannels > 8 check is used because there are only 8 control
|
||||||
|
* registers for HW triggers. HW triggering is not yet implemented if
|
||||||
|
* more than 8 ADC channels are used.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((priv->trig_src != -1) && (priv->nchannels > 8))
|
||||||
|
{
|
||||||
|
/* Disable external triggering */
|
||||||
|
|
||||||
|
aerr("Cannot use HW trigger as %d channels are used. "
|
||||||
|
"HW trigger can be used for 8 or less channels. "
|
||||||
|
"Switched to software trigger.\n",
|
||||||
|
priv->nchannels);
|
||||||
|
priv->trig_src = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->trig_src != -1)
|
||||||
|
{
|
||||||
|
ret = adc_reset_etc(priv);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
aerr("ERROR: adc_reset_etc() failed: %d.\n", ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
exit_leave_critical:
|
exit_leave_critical:
|
||||||
@@ -353,6 +507,7 @@ exit_leave_critical:
|
|||||||
static int adc_setup(struct adc_dev_s *dev)
|
static int adc_setup(struct adc_dev_s *dev)
|
||||||
{
|
{
|
||||||
struct imxrt_dev_s *priv = (struct imxrt_dev_s *)dev->ad_priv;
|
struct imxrt_dev_s *priv = (struct imxrt_dev_s *)dev->ad_priv;
|
||||||
|
int ret;
|
||||||
|
|
||||||
/* Do nothing when the ADC device is already set up */
|
/* Do nothing when the ADC device is already set up */
|
||||||
|
|
||||||
@@ -363,20 +518,45 @@ static int adc_setup(struct adc_dev_s *dev)
|
|||||||
|
|
||||||
priv->initialized++;
|
priv->initialized++;
|
||||||
|
|
||||||
int ret = irq_attach(priv->irq, adc_interrupt, dev);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
ainfo("irq_attach failed: %d\n", ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
up_enable_irq(priv->irq);
|
|
||||||
|
|
||||||
/* Start the first conversion */
|
|
||||||
|
|
||||||
priv->current = 0;
|
priv->current = 0;
|
||||||
adc_putreg(priv, IMXRT_ADC_HC0_OFFSET,
|
|
||||||
ADC_HC_ADCH(priv->chanlist[priv->current]));
|
if (priv->trig_src != -1)
|
||||||
|
{
|
||||||
|
/* Atach and enable ADCETC interrupt */
|
||||||
|
|
||||||
|
ret = irq_attach(priv->irq_etc, adc_interrupt, dev);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
aerr("irq_attach for %d failed: %d\n", IMXRT_IRQ_ADCETC_0, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
up_enable_irq(priv->irq_etc);
|
||||||
|
|
||||||
|
/* For every used channel set ADC_ETC trigger */
|
||||||
|
|
||||||
|
for (int i = 0; i < priv->nchannels; i++)
|
||||||
|
{
|
||||||
|
adc_putreg(priv, IMXRT_ADC_HC0_OFFSET + 4 * i,
|
||||||
|
ADC_HC_ADCH_EXT_ADC_ETC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = irq_attach(priv->irq, adc_interrupt, dev);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
ainfo("irq_attach for %d failed: %d\n", priv->irq, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
up_enable_irq(priv->irq);
|
||||||
|
|
||||||
|
/* Start the first conversion */
|
||||||
|
|
||||||
|
adc_putreg(priv, IMXRT_ADC_HC0_OFFSET,
|
||||||
|
ADC_HC_ADCH(priv->chanlist[priv->current]));
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -407,6 +587,14 @@ static void adc_shutdown(struct adc_dev_s *dev)
|
|||||||
* level of the NVIC.
|
* level of the NVIC.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if (priv->trig_src != -1)
|
||||||
|
{
|
||||||
|
/* Disable and detach an interrupt for ADC_ETC module */
|
||||||
|
|
||||||
|
up_disable_irq(priv->irq_etc);
|
||||||
|
irq_detach(priv->irq_etc);
|
||||||
|
}
|
||||||
|
|
||||||
/* Disable interrupt and stop any on-going conversion */
|
/* Disable interrupt and stop any on-going conversion */
|
||||||
|
|
||||||
adc_putreg(priv, IMXRT_ADC_HC0_OFFSET, ~ADC_HC_AIEN | ADC_HC_ADCH_DIS);
|
adc_putreg(priv, IMXRT_ADC_HC0_OFFSET, ~ADC_HC_AIEN | ADC_HC_ADCH_DIS);
|
||||||
@@ -506,7 +694,7 @@ static int adc_interrupt(int irq, void *context, void *arg)
|
|||||||
if (priv->cb != NULL)
|
if (priv->cb != NULL)
|
||||||
{
|
{
|
||||||
DEBUGASSERT(priv->cb->au_receive != NULL);
|
DEBUGASSERT(priv->cb->au_receive != NULL);
|
||||||
priv->cb->au_receive(dev, priv->chanlist[priv->current], data);
|
priv->cb->au_receive(dev, priv->chanlist[priv->current], data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the channel number of the next channel that will complete
|
/* Set the channel number of the next channel that will complete
|
||||||
@@ -527,6 +715,45 @@ static int adc_interrupt(int irq, void *context, void *arg)
|
|||||||
adc_modifyreg(priv, IMXRT_ADC_HC0_OFFSET, ADC_HC_ADCH_MASK,
|
adc_modifyreg(priv, IMXRT_ADC_HC0_OFFSET, ADC_HC_ADCH_MASK,
|
||||||
ADC_HC_ADCH(priv->chanlist[priv->current]));
|
ADC_HC_ADCH(priv->chanlist[priv->current]));
|
||||||
}
|
}
|
||||||
|
else if ((getreg32(IMXRT_ADCETC_BASE + IMXRT_ADC_ETC_DONE01_IRQ_OFFSET)
|
||||||
|
& priv->trig_clear) != 0)
|
||||||
|
{
|
||||||
|
/* Read data */
|
||||||
|
|
||||||
|
for (int i = 0; i < priv->nchannels; i++)
|
||||||
|
{
|
||||||
|
data = (int32_t)adc_getreg(priv, IMXRT_ADC_R0_OFFSET + 4 * i);
|
||||||
|
if (priv->cb != NULL)
|
||||||
|
{
|
||||||
|
DEBUGASSERT(priv->cb->au_receive != NULL);
|
||||||
|
priv->cb->au_receive(dev, priv->chanlist[priv->current], data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the channel number of the next channel that will complete
|
||||||
|
* conversion.
|
||||||
|
*/
|
||||||
|
|
||||||
|
priv->current++;
|
||||||
|
if (priv->current >= priv->nchannels)
|
||||||
|
{
|
||||||
|
/* Restart the conversion sequence from the beginning */
|
||||||
|
|
||||||
|
priv->current = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
adc_modifyreg(priv, IMXRT_ADC_HC0_OFFSET + 4 * i,
|
||||||
|
ADC_HC_ADCH_MASK, ADC_HC_ADCH_EXT_ADC_ETC);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear the interrpt bit. The interrupt access is a little bit
|
||||||
|
* unfortunate here. We need to access ADC_ETC_DONE01_IRQ_TRIG0_DONE0
|
||||||
|
* for ADC1 and ADC_ETC_DONE01_IRQ_TRIG4_DONE1 for ADC2 and since we
|
||||||
|
* want to avoid unnecessary if statemants we need to .
|
||||||
|
*/
|
||||||
|
|
||||||
|
putreg32(priv->trig_clear, IMXRT_ADCETC_BASE
|
||||||
|
+ IMXRT_ADC_ETC_DONE01_IRQ_OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
/* There are no interrupt flags left to clear */
|
/* There are no interrupt flags left to clear */
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user