From 1ce380108671fbfb5792353666950f47c92fc272 Mon Sep 17 00:00:00 2001 From: patacongo Date: Sun, 21 Oct 2012 16:53:38 +0000 Subject: [PATCH] STM32 ADC driver fixes git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5247 42af7a65-404d-4744-a932-0658087f49c3 --- ChangeLog | 5 +++++ arch/arm/src/stm32/stm32_adc.c | 10 +++++++--- arch/arm/src/stm32/stm32_adc.h | 2 +- configs/shenzhou/README.txt | 7 +++++++ drivers/analog/adc.c | 15 +++++++++++++-- 5 files changed, 33 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 44f38ee10a..f9e1bf5d03 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3496,3 +3496,8 @@ optimized for size. * lib/strings/lib_memset.c: CONFIG_MEMSET_64BIT will perform 64-bit aligned memset() operations. + * arch/arm/src/stm32/stm32_adc.c: Need to put the ADC back into the + initial reset in the open/setup logic. Opening the ADC driver works + the first time, but not the second because the device is left in a + powered down state on the last close. + diff --git a/arch/arm/src/stm32/stm32_adc.c b/arch/arm/src/stm32/stm32_adc.c index 777f624aa4..b5033b0576 100644 --- a/arch/arm/src/stm32/stm32_adc.c +++ b/arch/arm/src/stm32/stm32_adc.c @@ -694,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 */ @@ -971,7 +971,7 @@ static void adc_reset(FAR struct adc_dev_s *dev) avdbg("intf: ADC%d\n", priv->intf); flags = irqsave(); - /* Enable ADC reset state */ + /* Enable ADC reset state */ adc_rccreset(priv, true); @@ -1164,6 +1164,10 @@ static int adc_setup(FAR struct adc_dev_s *dev) 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); diff --git a/arch/arm/src/stm32/stm32_adc.h b/arch/arm/src/stm32/stm32_adc.h index 34f29020c7..060fcdfb90 100644 --- a/arch/arm/src/stm32/stm32_adc.h +++ b/arch/arm/src/stm32/stm32_adc.h @@ -287,7 +287,7 @@ #if defined(ADC1_HAVE_TIMER) || defined(ADC2_HAVE_TIMER) || defined(ADC3_HAVE_TIMER) # define ADC_HAVE_TIMER 1 -# if defined(CONFIG_STM32_STM32F10XX) && defined(CONFIG_STM32_FORCEPOWER) +# if defined(CONFIG_STM32_STM32F10XX) && !defined(CONFIG_STM32_FORCEPOWER) # warning "CONFIG_STM32_FORCEPOWER must be defined to enable the timer(s)" # endif #else diff --git a/configs/shenzhou/README.txt b/configs/shenzhou/README.txt index a60019a279..48f183aee4 100644 --- a/configs/shenzhou/README.txt +++ b/configs/shenzhou/README.txt @@ -593,6 +593,12 @@ Shenzhou-specific Configuration Options CONFIG_STM32_ADC1 CONFIG_STM32_ADC2 + Timer and I2C devices may need to the following to force power to be applied + unconditionally at power up. (Otherwise, the device is powered when it is + initialized). + + CONFIG_STM32_FORCEPOWER + Timer devices may be used for different purposes. One special purpose is to generate modulated outputs for such things as motor control. If CONFIG_STM32_TIMn is defined (as above) then the following may also be defined to indicate that @@ -798,6 +804,7 @@ Where is one of the following: CONFIG_STM32_TIM1_ADC1=y : Allocate Timer 1 to ADC 1 CONFIG_STM32_ADC1_SAMPLE_FREQUENCY=100 : Set sampling frequency to 100Hz CONFIG_STM32_ADC1_TIMTRIG=0 : Trigger on timer output 0 + CONFIG_STM32_FORCEPOWER=y : Apply power to TIM1 a boot up time CONFIG_EXAMPLES_ADC=y : Enable the apps/examples/adc built-in nxwm diff --git a/drivers/analog/adc.c b/drivers/analog/adc.c index 84070f162a..72f19452a4 100644 --- a/drivers/analog/adc.c +++ b/drivers/analog/adc.c @@ -143,7 +143,7 @@ static int adc_open(FAR struct file *filep) dev->ad_recv.af_head = 0; dev->ad_recv.af_tail = 0; - /* Finally, Enable the CAN RX interrupt */ + /* Finally, Enable the ADC RX interrupt */ dev->ad_ops->ao_rxint(dev, true); @@ -151,9 +151,11 @@ static int adc_open(FAR struct file *filep) dev->ad_ocount = tmp; } + irqrestore(flags); } } + sem_post(&dev->ad_closesem); } return ret; @@ -370,6 +372,10 @@ static int adc_ioctl(FAR struct file *filep, int cmd, unsigned long arg) * Public Functions ****************************************************************************/ +/**************************************************************************** + * Name: adc_receive + ****************************************************************************/ + int adc_receive(FAR struct adc_dev_s *dev, uint8_t ch, int32_t data) { FAR struct adc_fifo_s *fifo = &dev->ad_recv; @@ -390,7 +396,7 @@ int adc_receive(FAR struct adc_dev_s *dev, uint8_t ch, int32_t data) if (nexttail != fifo->af_head) { - /* Add the new, decoded CAN message at the tail of the FIFO */ + /* Add the new, decoded ADC sample at the tail of the FIFO */ fifo->af_buffer[fifo->af_tail].am_channel = ch; fifo->af_buffer[fifo->af_tail].am_data = data; @@ -403,11 +409,16 @@ int adc_receive(FAR struct adc_dev_s *dev, uint8_t ch, int32_t data) { sem_post(&fifo->af_sem); } + err = OK; } return err; } +/**************************************************************************** + * Name: adc_register + ****************************************************************************/ + int adc_register(FAR const char *path, FAR struct adc_dev_s *dev) { /* Initialize the ADC device structure */