From 0ef224f0edcdc24a123dd2f229256dac3a38c277 Mon Sep 17 00:00:00 2001 From: patacongo Date: Thu, 22 Dec 2011 00:31:47 +0000 Subject: STM32 ADC driver update git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4211 42af7a65-404d-4744-a932-0658087f49c3 --- apps/examples/adc/adc_main.c | 24 ++++--- nuttx/arch/arm/src/stm32/stm32_adc.c | 100 +++++++++++++++------------- nuttx/arch/arm/src/stm32/stm32_can.c | 10 +++ nuttx/configs/hymini-stm32v/include/board.h | 4 +- nuttx/configs/stm3210e-eval/include/board.h | 4 +- nuttx/configs/stm3210e-eval/src/up_adc.c | 10 ++- nuttx/configs/stm3240g-eval/include/board.h | 2 +- nuttx/configs/vsn/include/board.h | 4 +- 8 files changed, 90 insertions(+), 68 deletions(-) diff --git a/apps/examples/adc/adc_main.c b/apps/examples/adc/adc_main.c index f0876bb60..2d5414410 100644 --- a/apps/examples/adc/adc_main.c +++ b/apps/examples/adc/adc_main.c @@ -149,8 +149,6 @@ int MAIN_NAME(int argc, char *argv[]) * ADC samples. */ - message(MAIN_STRING "Entering the main loop\n"); - #if defined(CONFIG_NSH_BUILTIN_APPS) for (; nsamples > 0; nsamples--) #elif defined(CONFIG_EXAMPLES_ADC_NSAMPLES) @@ -186,21 +184,29 @@ int MAIN_NAME(int argc, char *argv[]) message(MAIN_STRING "Interrupted read...\n"); } - else if (nbytes != readsize) + else if (nbytes == 0) { - message(MAIN_STRING "Unexpected read size=%d, expected=%d, Ignoring\n", - nbytes, readsize); + message(MAIN_STRING "No data read, Ignoring\n"); } /* Print the sample data on successful return */ else { - message("Sample :\n"); - for (i = 0; i < CONFIG_EXAMPLES_ADC_GROUPSIZE; i++) + int nsamples = nbytes / sizeof(struct adc_msg_s); + if (nsamples * sizeof(struct adc_msg_s) != nbytes) + { + message(MAIN_STRING "read size=%d is not a multiple of sample size=%d, Ignoring\n", + nbytes, sizeof(struct adc_msg_s)); + } + else { - message("%d: channel: %d value: %d\n", - i, sample[i].am_channel, sample[i].am_data); + message("Sample: "); + for (i = 0; i < nsamples ; i++) + { + message("%d: channel: %d value: %d\n", + i, sample[i].am_channel, sample[i].am_data); + } } } } diff --git a/nuttx/arch/arm/src/stm32/stm32_adc.c b/nuttx/arch/arm/src/stm32/stm32_adc.c index 3f56c5803..5cd22582d 100644 --- a/nuttx/arch/arm/src/stm32/stm32_adc.c +++ b/nuttx/arch/arm/src/stm32/stm32_adc.c @@ -371,9 +371,8 @@ static void adc_tim_dumpregs(struct stm32_dev_s *priv, FAR const char *msg) tim_getreg(priv, STM32_GTIM_CR2_OFFSET), tim_getreg(priv, STM32_GTIM_SMCR_OFFSET), tim_getreg(priv, STM32_GTIM_DIER_OFFSET)); - avdbg(" SR: %04x EGR: %04x CCMR1: %04x CCMR2: %04x\n", + avdbg(" SR: %04x EGR: XXXX CCMR1: %04x CCMR2: %04x\n", tim_getreg(priv, STM32_GTIM_SR_OFFSET), - tim_getreg(priv, STM32_GTIM_EGR_OFFSET), tim_getreg(priv, STM32_GTIM_CCMR1_OFFSET), tim_getreg(priv, STM32_GTIM_CCMR2_OFFSET)); avdbg(" CCER: %04x CNT: %04x PSC: %04x ARR: %04x\n", @@ -475,6 +474,7 @@ static int adc_timinit(FAR struct stm32_dev_s *priv) uint16_t ocmode2; uint16_t ccenable; uint16_t ccer; + uint16_t egr; avdbg("Num Channels:%d, ADC:%d, Channel:%d, trigger:%d, Extsel:%08x, Desired Freq:%d\n", priv->nchannels, priv->intf, priv->current, priv->trigger, priv->extsel, priv->freq); @@ -602,6 +602,7 @@ static int adc_timinit(FAR struct stm32_dev_s *priv) if (priv->tbase == STM32_TIM1_BASE || priv->tbase == STM32_TIM8_BASE) { tim_putreg(priv, STM32_ATIM_RCR_OFFSET, 0); + tim_putreg(priv, STM32_ATIM_BDTR_OFFSET, ATIM_BDTR_MOE); /* Check me */ } /* TIMx event generation: Bit 0 UG: Update generation */ @@ -615,13 +616,14 @@ static int adc_timinit(FAR struct stm32_dev_s *priv) switch (priv->trigger) { - case 0: /* Timer x CC1 event */ + case 0: /* TimerX CC1 event */ { ccenable = ATIM_CCER_CC1E; ocmode1 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC1S_SHIFT) | (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR1_OC1M_SHIFT) | ATIM_CCMR1_OC1PE; - avdbg("Timer x CC%d event\n", priv->trigger+1); + egr = ATIM_EGR_CC1G; + avdbg("TimerX CC%d event\n", priv->trigger+1); /* Set the duty cycle by writing to the CCR register for this channel */ @@ -629,13 +631,14 @@ static int adc_timinit(FAR struct stm32_dev_s *priv) } break; - case 1: /* Timer x CC2 event */ + case 1: /* TimerX CC2 event */ { ccenable = ATIM_CCER_CC2E; ocmode1 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC2S_SHIFT) | (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR1_OC2M_SHIFT) | ATIM_CCMR1_OC2PE; - avdbg("Timer x CC%d event\n", priv->trigger+1); + egr = ATIM_EGR_CC2G; + avdbg("TimerX CC%d event\n", priv->trigger+1); /* Set the duty cycle by writing to the CCR register for this channel */ @@ -643,13 +646,14 @@ static int adc_timinit(FAR struct stm32_dev_s *priv) } break; - case 2: /* Timer x CC3 event */ + case 2: /* TimerX CC3 event */ { ccenable = ATIM_CCER_CC3E; ocmode2 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR2_CC3S_SHIFT) | (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR2_OC3M_SHIFT) | ATIM_CCMR2_OC3PE; - avdbg("Timer x CC%d event\n", priv->trigger+1); + egr = ATIM_EGR_CC3G; + avdbg("TimerX CC%d event\n", priv->trigger+1); /* Set the duty cycle by writing to the CCR register for this channel */ @@ -657,13 +661,14 @@ static int adc_timinit(FAR struct stm32_dev_s *priv) } break; - case 3: /* Timer x CC4 event */ + case 3: /* TimerX CC4 event */ { ccenable = ATIM_CCER_CC4E; ocmode2 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR2_CC4S_SHIFT) | (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR2_OC4M_SHIFT) | - ATIM_CCMR2_OC3PE; - avdbg("Timer x CC%d event\n", priv->trigger+1); + ATIM_CCMR2_OC4PE; + egr = ATIM_EGR_CC4G; + avdbg("TimerX CC%d event\n", priv->trigger+1); /* Set the duty cycle by writing to the CCR register for this channel */ @@ -671,10 +676,11 @@ static int adc_timinit(FAR struct stm32_dev_s *priv) } break; - case 4: /* Timer x TRGO event */ + case 4: /* TimerX TRGO event */ { #warning "missing logic, I want the Timer-x-CCx-event working first" - avdbg("Timer x TRGO trigger=%d\n", priv->trigger); + egr = GTIM_EGR_TG; + avdbg("TimerX TRGO trigger=%d\n", priv->trigger); } break; @@ -745,6 +751,7 @@ static int adc_timinit(FAR struct stm32_dev_s *priv) tim_putreg(priv, STM32_GTIM_CCMR1_OFFSET, ccmr1); tim_putreg(priv, STM32_GTIM_CCMR2_OFFSET, ccmr2); tim_putreg(priv, STM32_GTIM_CCER_OFFSET, ccer); + tim_putreg(priv, STM32_GTIM_EGR_OFFSET, egr); /* Set the ARR Preload Bit */ @@ -925,7 +932,7 @@ static void adc_reset(FAR struct adc_dev_s *dev) int ret; int i; - avdbg("intf: %d\n", priv->intf); + avdbg("intf: ADC%d\n", priv->intf); flags = irqsave(); /* Enable ADC reset state */ @@ -976,20 +983,9 @@ static void adc_reset(FAR struct adc_dev_s *dev) regval |= ADC_CR1_AWDEN; - /* AWDIE: Analog watchdog interrupt enable */ - - regval |= ADC_CR1_AWDIE; - - /* EOCIE: Interrupt enable for EOC */ + /* Enable interrupt flags */ - regval |= ADC_CR1_EOCIE; - - /* Number of channels to be converted in discont mode - * Bits 15:13 DISCNUM[2:0]: - */ - - //regval |= ( (priv->nchannels)<nchannels <= 16); - regval |= ((uint32_t)priv->nchannels << ADC_SQR1_L_SHIFT); + 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 */ @@ -1064,14 +1068,15 @@ static void adc_reset(FAR struct adc_dev_s *dev) irqrestore(flags); - avdbg("SR: 0x%08x \t CR1: 0x%08x \t CR2: 0x%08x\n", + 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 \t SQR2: 0x%08x \t SQR3: 0x%08x\n", + 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)); + avdbg("\n"); } /**************************************************************************** @@ -1094,7 +1099,7 @@ 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; - avdbg("intf: %d\n", priv->intf); + avdbg("intf: ADC%d\n", priv->intf); /* Attach the ADC interrupt */ @@ -1108,6 +1113,7 @@ static int adc_setup(FAR struct adc_dev_s *dev) } avdbg("Returning %d\n",ret); + return ret; } @@ -1128,7 +1134,7 @@ static void adc_shutdown(FAR struct adc_dev_s *dev) { FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv; - avdbg("intf: %d\n", priv->intf); + avdbg("intf: ADC%d irq: %d\n", priv->intf, priv->irq); /* Disable ADC interrupts and detach the ADC interrupt handler */ @@ -1136,6 +1142,8 @@ static void adc_shutdown(FAR struct adc_dev_s *dev) irq_detach(priv->irq); /* Disable and reset the ADC module */ + + adc_rccreset(priv, true); } /**************************************************************************** @@ -1162,7 +1170,7 @@ static void adc_rxint(FAR struct adc_dev_s *dev, bool enable) { /* Enable the end-of-conversion ADC and analog watchdog interrupts */ - regval |= (ADC_CR1_EOCIE | ADC_CR1_AWDIE); + regval |= ADC_CR1_ALLINTS; } else { @@ -1210,7 +1218,7 @@ static int adc_interrupt(FAR struct adc_dev_s *dev) uint32_t regval; int32_t value; - avdbg("intf: %d\n", priv->intf); + avdbg("intf: ADC%d\n", priv->intf); /* Identifies the interruption AWD or EOC */ @@ -1224,40 +1232,40 @@ static int adc_interrupt(FAR struct adc_dev_s *dev) if ((adcsr & ADC_SR_EOC) != 0) { - /* Read the converted value */ + /* Read the converted value and clear EOC bit + *(It is cleared by reading the ADC_DR) + */ value = adc_getreg(priv, STM32_ADC_DR_OFFSET); value &= ADC_DR_DATA_MASK; - /* Give the ADC data to the ADC dirver. adc_receive accepts 3 parameters: + /* 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. */ - avdbg("Calling adc_receive(dev, priv->chanlist[%d], value=%d)\n", priv->current, value); adc_receive(dev, priv->chanlist[priv->current], value); - - priv->current++; + avdbg("Calling adc_receive(chanlist[%d], data=%d)\n", priv->current, value); /* 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 */ -#warning "Missing logic" + + avdbg("Last conversion done, conversion=%d\n",priv->current); /* Reset the index to the first channel to be converted */ priv->current = 0; + } } - regval = adc_getreg(priv, STM32_ADC_SR_OFFSET); - regval &= ~ADC_SR_ALLINTS; - adc_putreg(priv, STM32_ADC_SR_OFFSET, regval); - return OK; } diff --git a/nuttx/arch/arm/src/stm32/stm32_can.c b/nuttx/arch/arm/src/stm32/stm32_can.c index 2be900ab2..46e01797b 100755 --- a/nuttx/arch/arm/src/stm32/stm32_can.c +++ b/nuttx/arch/arm/src/stm32/stm32_can.c @@ -690,6 +690,7 @@ static int can_rx0interrupt(int irq, void *context) FAR struct stm32_can_s *priv; uint8_t data[CAN_MAXDATALEN]; uint32_t regval; + int npending; int id; int rtr; int dlc; @@ -715,6 +716,15 @@ static int can_rx0interrupt(int irq, void *context) #endif priv = dev->cd_priv; + /* Verify that a message is pending in FIFO 0 */ + + regval = can_getreg(priv, STM32_CAN_RF0R_OFFSET); + npending = (regval & CAN_RFR_FMP_MASK) >> CAN_RFR_FMP_SHIFT; + if (npending < 1) + { + return OK; + } + /* Get the CAN identifier. Only standard 11-bit IDs are supported */ regval = can_getreg(priv, STM32_CAN_RI0R_OFFSET); diff --git a/nuttx/configs/hymini-stm32v/include/board.h b/nuttx/configs/hymini-stm32v/include/board.h index 719ad1c74..333f83b89 100755 --- a/nuttx/configs/hymini-stm32v/include/board.h +++ b/nuttx/configs/hymini-stm32v/include/board.h @@ -90,8 +90,8 @@ /* APB2 timers 1 and 8 will receive PCLK2. */ -#define STM32_APB1_TIM1_CLKIN (STM32_PCLK2_FREQUENCY) -#define STM32_APB1_TIM8_CLKIN (STM32_PCLK2_FREQUENCY) +#define STM32_APB2_TIM1_CLKIN (STM32_PCLK2_FREQUENCY) +#define STM32_APB2_TIM8_CLKIN (STM32_PCLK2_FREQUENCY) /* APB1 clock (PCLK1) is HCLK/2 (36MHz) */ diff --git a/nuttx/configs/stm3210e-eval/include/board.h b/nuttx/configs/stm3210e-eval/include/board.h index 653ec8999..8e2e88612 100755 --- a/nuttx/configs/stm3210e-eval/include/board.h +++ b/nuttx/configs/stm3210e-eval/include/board.h @@ -86,8 +86,8 @@ /* APB2 timers 1 and 8 will receive PCLK2. */ -#define STM32_APB1_TIM1_CLKIN (STM32_PCLK2_FREQUENCY) -#define STM32_APB1_TIM8_CLKIN (STM32_PCLK2_FREQUENCY) +#define STM32_APB2_TIM1_CLKIN (STM32_PCLK2_FREQUENCY) +#define STM32_APB2_TIM8_CLKIN (STM32_PCLK2_FREQUENCY) /* APB1 clock (PCLK1) is HCLK/2 (36MHz) */ diff --git a/nuttx/configs/stm3210e-eval/src/up_adc.c b/nuttx/configs/stm3210e-eval/src/up_adc.c index 8f2cfbd38..f84a88d58 100644 --- a/nuttx/configs/stm3210e-eval/src/up_adc.c +++ b/nuttx/configs/stm3210e-eval/src/up_adc.c @@ -82,13 +82,13 @@ * Private Data ************************************************************************************/ -/* Identifying number of each ADC channel: Variable Resistor , BNC_CN5 and BNC_CN3 */ +/* Identifying number of each ADC channel: Variable Resistor and BNC_CN5 */ -static const uint8_t g_chanlist[ADC_NCHANNELS] = {14, 10}; +static const uint8_t g_chanlist[ADC_NCHANNELS] = {14, 11}; /* Configurations of pins used byte each ADC channels */ -static const uint32_t g_pinlist[ADC_NCHANNELS] = {GPIO_ADC1_IN14 , GPIO_ADC1_IN10}; +static const uint32_t g_pinlist[ADC_NCHANNELS] = {GPIO_ADC1_IN14 , GPIO_ADC1_IN11}; /************************************************************************************ * Private Functions @@ -114,13 +114,11 @@ int adc_devinit(void) int ret; int i; - avdbg("Entry\n"); - /* Configure the pins as analog inputs for the selected channels */ for(i = 0; i < ADC_NCHANNELS; i++) { - stm32_configgpio(g_chanlist[i]); + stm32_configgpio(g_pinlist[i]); } /* Call stm32_adcinitialize() to get an instance of the ADC interface */ diff --git a/nuttx/configs/stm3240g-eval/include/board.h b/nuttx/configs/stm3240g-eval/include/board.h index caf93e54f..6c3b32497 100755 --- a/nuttx/configs/stm3240g-eval/include/board.h +++ b/nuttx/configs/stm3240g-eval/include/board.h @@ -146,7 +146,7 @@ #define STM32_RCC_CFGR_PPRE2 RCC_CFGR_PPRE2_HCLKd2 /* PCLK2 = HCLK / 2 */ #define STM32_PCLK2_FREQUENCY (STM32_HCLK_FREQUENCY/2) -/* Timers driven from APB12will be twice PCLK2 */ +/* Timers driven from APB2 will be twice PCLK2 */ #define STM32_APB2_TIM1_CLKIN (2*STM32_PCLK2_FREQUENCY) #define STM32_APB2_TIM8_CLKIN (2*STM32_PCLK1_FREQUENCY) diff --git a/nuttx/configs/vsn/include/board.h b/nuttx/configs/vsn/include/board.h index b47df4d6e..9fa58de00 100644 --- a/nuttx/configs/vsn/include/board.h +++ b/nuttx/configs/vsn/include/board.h @@ -99,8 +99,8 @@ /* APB2 timers 1 and 8 will receive PCLK2. */ -#define STM32_APB1_TIM1_CLKIN (STM32_PCLK2_FREQUENCY) -#define STM32_APB1_TIM8_CLKIN (STM32_PCLK2_FREQUENCY) +#define STM32_APB2_TIM1_CLKIN (STM32_PCLK2_FREQUENCY) +#define STM32_APB2_TIM8_CLKIN (STM32_PCLK2_FREQUENCY) /* APB1 clock (PCLK1) is HCLK (36MHz) */ -- cgit v1.2.3