aboutsummaryrefslogtreecommitdiff
path: root/nuttx/arch/arm/src/stm32/stm32_adc.c
diff options
context:
space:
mode:
Diffstat (limited to 'nuttx/arch/arm/src/stm32/stm32_adc.c')
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_adc.c315
1 files changed, 42 insertions, 273 deletions
diff --git a/nuttx/arch/arm/src/stm32/stm32_adc.c b/nuttx/arch/arm/src/stm32/stm32_adc.c
index 844f1fd0f..b5033b057 100644
--- a/nuttx/arch/arm/src/stm32/stm32_adc.c
+++ b/nuttx/arch/arm/src/stm32/stm32_adc.c
@@ -118,25 +118,12 @@ struct stm32_dev_s
uint32_t freq; /* The desired frequency of conversions */
#endif
uint8_t chanlist[ADC_MAX_SAMPLES];
-#ifdef CONFIG_ADC_DMA
- const unsigned int rxdma_channel; /* DMA channel assigned */
- DMA_HANDLE rxdma; /* currently-open receive DMA stream */
- bool rxenable; /* DMA-based reception en/disable */
- uint32_t rxdmanext; /* Next byte in the DMA buffer to be read */
- int32_t *const rxfifo; /* Receive DMA buffer */
-#endif
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
-# ifdef CONFIG_ADC_DMA
-static int16_t g_adc3dmarxfifo[ADC_MAX_SAMPLES];
-# endif
-
-
-
/* ADC Register access */
static uint32_t adc_getreg(struct stm32_dev_s *priv, int offset);
@@ -179,15 +166,6 @@ static int adc_timinit(FAR struct stm32_dev_s *priv);
static void adc_startconv(FAR struct stm32_dev_s *priv, bool enable);
#endif
-#ifdef CONFIG_ADC_DMA
-static int up_dma_setup(struct adc_dev_s *dev);
-static void up_dma_shutdown(struct adc_dev_s *dev);
-//static int up_dma_receive(struct uart_dev_s *dev, uint32_t *status);
-//static void up_dma_rxint(struct uart_dev_s *dev, bool enable);
-//static bool up_dma_rxavailable(struct uart_dev_s *dev);
-static void up_dma_rxcallback(DMA_HANDLE handle, uint8_t status, FAR struct adc_dev_s *dev);
-#endif
-
/****************************************************************************
* Private Data
****************************************************************************/
@@ -284,10 +262,6 @@ static struct stm32_dev_s g_adcpriv3 =
.pclck = ADC3_TIMER_PCLK_FREQUENCY,
.freq = CONFIG_STM32_ADC3_SAMPLE_FREQUENCY,
#endif
-#ifdef CONFIG_ADC_DMA
- .rxdma_channel = DMAMAP_ADC3_2,
- .rxfifo = g_adc3dmarxfifo,
-#endif
};
static struct adc_dev_s g_adcdev3 =
@@ -569,7 +543,7 @@ static int adc_timinit(FAR struct stm32_dev_s *priv)
* So ( prescaler = pclck / 65535 / freq ) would be optimal.
*/
- prescaler = 128;//(priv->pclck / priv->freq + 65534) / 65535;
+ prescaler = (priv->pclck / priv->freq + 65534) / 65535;
/* We need to decrement the prescaler value by one, but only, the value does
* not underflow.
@@ -591,7 +565,7 @@ static int adc_timinit(FAR struct stm32_dev_s *priv)
timclk = priv->pclck / prescaler;
- reload = priv->freq;//timclk / priv->freq;
+ reload = timclk / priv->freq;
if (reload < 1)
{
adbg("WARNING: Reload value underflowed.\n");
@@ -720,10 +694,10 @@ static int adc_timinit(FAR struct stm32_dev_s *priv)
case 4: /* TimerX TRGO event */
{
-#warning "TRGO support not yet implemented"
-
+ /* TODO: TRGO support not yet implemented */
/* Set the event TRGO */
+ ccenable = 0;
egr = GTIM_EGR_TG;
/* Set the duty cycle by writing to the CCR register for this channel */
@@ -936,139 +910,6 @@ static void adc_rccreset(struct stm32_dev_s *priv, bool reset)
irqrestore(flags);
}
-/****************************************************************************
- * Name: up_dma_setup
- *
- * Description:
- *
- ****************************************************************************/
-
-#ifdef CONFIG_ADC_DMA
-static int up_dma_setup(FAR struct adc_dev_s *dev)
-{
-
- FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
- int result;
- uint32_t regval;
-
-//
-// result = up_setup(dev);
-// if (result != OK)
-// {
-// return result;
-// }
-
- /* Acquire the DMA channel. This should always succeed. */
-
- priv->rxdma = stm32_dmachannel(priv->rxdma_channel);
-
- /* Configure for circular DMA reception into the RX fifo */
-
- stm32_dmasetup(priv->rxdma,
- priv->base + STM32_ADC_DR_OFFSET,
- (uint32_t)priv->rxfifo,
- 4,//buffersize
- DMA_SCR_DIR_P2M |
- DMA_SCR_CIRC |
- DMA_SCR_MINC |
- DMA_SCR_PSIZE_16BITS |
- DMA_SCR_MSIZE_16BITS |
- DMA_SCR_PBURST_SINGLE |
- DMA_SCR_MBURST_SINGLE);
-
- /* Reset our DMA shadow pointer to match the address just
- * programmed above.
- */
-
- //priv->rxdmanext = 0;
-
- /* Enable DMA for the ADC */
-
- /* Start the DMA channel, and arrange for callbacks at the half and
- * full points in the FIFO. This ensures that we have half a FIFO
- * worth of time to claim bytes before they are overwritten.
- */
-
- stm32_dmastart(priv->rxdma, up_dma_rxcallback, (void *)dev, false);
-
- return OK;
-}
-#endif
-/****************************************************************************
- * Name: up_dma_rxcallback
- *
- * Description:
-
- *
- ****************************************************************************/
-
-#ifdef CONFIG_ADC_DMA
-static void up_dma_rxcallback(DMA_HANDLE handle, uint8_t status, FAR struct adc_dev_s *dev)
-{
- //struct up_dev_s *priv = (struct up_dev_s*)arg;
- //uint32_t regval;
- FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
- //struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle;
-
- //if (priv->rxenable && up_dma_rxavailable(&priv->dev))
- {
- /* Give the ADC data to the ADC driver. adc_receive accepts 3 parameters:
- *
- * 1) The first is the ADC device instance for this ADC block.
- * 2) The second is the channel number for the data, and
- * 3) The third is the converted data for the channel.
- */
-
-
- adc_receive(dev, 10, (int32_t)g_adc3dmarxfifo[1]);
- adc_receive(dev, 11, (int32_t)g_adc3dmarxfifo[2]);
- adc_receive(dev, 12, (int32_t)g_adc3dmarxfifo[3]);
- adc_receive(dev, 13, (int32_t)g_adc3dmarxfifo[0]);
-
-
- /* 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;
- }
-
-
- }
-}
-#endif
-
-/****************************************************************************
- * Name: up_dma_shutdown
- *
- * Description:
- * Disable the DMA
- *
- ****************************************************************************/
-
-#ifdef CONFIG_ADC_DMA
-static void up_dma_shutdown(struct adc_dev_s *dev)
-{
-
- FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
-
-
- /* Stop the DMA channel */
-
- stm32_dmastop(priv->rxdma);
-
- /* Release the DMA channel */
-
- stm32_dmafree(priv->rxdma);
- priv->rxdma = NULL;
-}
-#endif
-
-
/*******************************************************************************
* Name: adc_enable
*
@@ -1089,7 +930,7 @@ static void adc_enable(FAR struct stm32_dev_s *priv, bool enable)
{
uint32_t regval;
- // avdbg("enable: %d\n", enable);
+ avdbg("enable: %d\n", enable);
regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
if (enable)
@@ -1123,12 +964,14 @@ static void adc_reset(FAR struct adc_dev_s *dev)
uint32_t regval;
int offset;
int i;
+#ifdef ADC_HAVE_TIMER
int ret;
+#endif
avdbg("intf: ADC%d\n", priv->intf);
flags = irqsave();
- /* Enable ADC reset state */
+ /* Enable ADC reset state */
adc_rccreset(priv, true);
@@ -1146,7 +989,6 @@ static void adc_reset(FAR struct adc_dev_s *dev)
adc_putreg(priv, STM32_ADC_LTR_OFFSET, 0x00000000);
-
/* Initialize the same sample time for each ADC 55.5 cycles
*
* During sample cycles channel selection bits must remain unchanged.
@@ -1179,8 +1021,16 @@ static void adc_reset(FAR struct adc_dev_s *dev)
regval |= ADC_CR1_AWDEN;
regval |= (priv->chanlist[0] << ADC_CR1_AWDCH_SHIFT);
+ /* Enable interrupt flags */
+
+ regval |= ADC_CR1_ALLINTS;
+
#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+ /* Enable or disable Overrun interrupt */
+
+ regval &= ~ADC_CR1_OVRIE;
+
/* Set the resolution of the conversion */
regval |= ACD_CR1_RES_12BIT;
@@ -1229,12 +1079,6 @@ static void adc_reset(FAR struct adc_dev_s *dev)
{
regval |= (uint32_t)priv->chanlist[i] << offset;
}
- /* Set the number of conversions */
-
- DEBUGASSERT(priv->nchannels <= ADC_MAX_SAMPLES);
-
- regval |= (((uint32_t)priv->nchannels-1) << ADC_SQR1_L_SHIFT);
- adc_putreg(priv, STM32_ADC_SQR1_OFFSET, regval);
/* ADC CCR configuration */
@@ -1246,7 +1090,12 @@ static void adc_reset(FAR struct adc_dev_s *dev)
putreg32(regval, STM32_ADC_CCR);
#endif
+ /* Set the number of conversions */
+ DEBUGASSERT(priv->nchannels <= ADC_MAX_SAMPLES);
+
+ regval |= (((uint32_t)priv->nchannels-1) << ADC_SQR1_L_SHIFT);
+ adc_putreg(priv, STM32_ADC_SQR1_OFFSET, regval);
/* Set the channel index of the first conversion */
@@ -1270,29 +1119,24 @@ static void adc_reset(FAR struct adc_dev_s *dev)
adc_enable(priv, true);
#else
-#ifdef CONFIG_ADC_DMA
- //nothing
-#else
adc_startconv(priv, true);
-#endif
#endif /* CONFIG_STM32_STM32F10XX */
#endif /* ADC_HAVE_TIMER */
-
irqrestore(flags);
-// avdbg("SR: 0x%08x CR1: 0x%08x CR2: 0x%08x\n",
-// adc_getreg(priv, STM32_ADC_SR_OFFSET),
-// adc_getreg(priv, STM32_ADC_CR1_OFFSET),
-// adc_getreg(priv, STM32_ADC_CR2_OFFSET));
-// avdbg("SQR1: 0x%08x SQR2: 0x%08x SQR3: 0x%08x\n",
-// adc_getreg(priv, STM32_ADC_SQR1_OFFSET),
-// adc_getreg(priv, STM32_ADC_SQR2_OFFSET),
-// adc_getreg(priv, STM32_ADC_SQR3_OFFSET));
-//#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
-// avdbg("CCR: 0x%08x\n",
-// getreg32(STM32_ADC_CCR));
-//#endif
+ avdbg("SR: 0x%08x CR1: 0x%08x CR2: 0x%08x\n",
+ adc_getreg(priv, STM32_ADC_SR_OFFSET),
+ adc_getreg(priv, STM32_ADC_CR1_OFFSET),
+ adc_getreg(priv, STM32_ADC_CR2_OFFSET));
+ avdbg("SQR1: 0x%08x SQR2: 0x%08x SQR3: 0x%08x\n",
+ adc_getreg(priv, STM32_ADC_SQR1_OFFSET),
+ adc_getreg(priv, STM32_ADC_SQR2_OFFSET),
+ adc_getreg(priv, STM32_ADC_SQR3_OFFSET));
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+ avdbg("CCR: 0x%08x\n",
+ getreg32(STM32_ADC_CCR));
+#endif
}
/****************************************************************************
@@ -1314,86 +1158,21 @@ static int adc_setup(FAR struct adc_dev_s *dev)
{
FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
int ret;
- uint32_t regval;
-
-
- /* the adc seems to need a full reset to be enabled correctly */
- adc_reset(dev);
-#ifndef CONFIG_ADC_DMA
/* Attach the ADC interrupt */
ret = irq_attach(priv->irq, priv->isr);
if (ret == OK)
{
+ /* Make sure that the ADC device is in the powered up, reset state */
+
+ adc_reset(dev);
+
/* Enable the ADC interrupt */
avdbg("Enable the ADC interrupt: irq=%d\n", priv->irq);
up_enable_irq(priv->irq);
}
-#endif
-
-#ifdef CONFIG_ADC_DMA
- up_dma_setup(dev);
-
-
-//#ifndef ADC_HAVE_TIMER
-// /*disable external trigger*/
-// regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
-// regval |= ACD_CR2_EXTEN_NONE;
-// //regval |= ADC_CR1_DISCEN;
-// adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval);
-//#else
-// /*enable external trigger*/
-// regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
-// regval |=ADC_CR2_EXTSEL_T4CC4;
-// regval |=ACD_CR2_EXTEN_BOTH;
-// //regval |= ADC_CR2_CONT;
-// adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval);
-//#endif
-
-
- /*enable scan mode*/
- regval = adc_getreg(priv, STM32_ADC_CR1_OFFSET);
- regval |= ADC_CR1_SCAN;
- //regval |= ADC_CR1_DISCEN;
- adc_putreg(priv, STM32_ADC_CR1_OFFSET, regval);
-
- /* Enable DMA request after last transfer (Single-ADC mode) */
- //ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE);
- regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
- regval |= ADC_CR2_DDS;
- adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval);
-
- /* Enable ADC3 DMA */
- // ADC_DMACmd(ADC3, ENABLE);
- regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
- regval |= ADC_CR2_DMA;
- adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval);
-#endif
-
-
-#ifndef ADC_HAVE_TIMER
- /*set continuous conversion */
- regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
- regval |= ADC_CR2_CONT;
- adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval);
-#endif
-
- /* Enable ADC3 */
- //ADC_Cmd(ADC3, ENABLE);
- regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
- regval |= ADC_CR2_ADON;
- adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval);
-
-//// /*start conversion*/
-// regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
-// regval |= ADC_CR2_SWSTART;
-// adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval);
-
-
-
-
return ret;
}
@@ -1415,24 +1194,14 @@ static void adc_shutdown(FAR struct adc_dev_s *dev)
{
FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
-#ifdef CONFIG_ADC_DMA
- up_dma_shutdown(dev);
-#endif
-
-#ifdef ADC_HAVE_TIMER
- /* stop adc timer */
- adc_timstart(priv, false);
-#endif
+ /* Disable ADC interrupts and detach the ADC interrupt handler */
- /* power down ADC */
- adc_enable(priv, false);
+ up_disable_irq(priv->irq);
+ irq_detach(priv->irq);
- adc_rxint(dev, false);
+ /* Disable and reset the ADC module */
- /* Disable ADC interrupts and detach the ADC interrupt handler */
- up_disable_irq(priv->irq);
-// irq_detach(priv->irq);
- // XXX Why is irq_detach here commented out?
+ adc_rccreset(priv, true);
}
/****************************************************************************