diff --git a/arch/arm/src/stm32/Make.defs b/arch/arm/src/stm32/Make.defs index 402a3253308b490ea7ccaae51552066aad12afed..d877516ab80b7167168c1564479a10ca9d4ef6ad 100644 --- a/arch/arm/src/stm32/Make.defs +++ b/arch/arm/src/stm32/Make.defs @@ -83,6 +83,10 @@ ifeq ($(CONFIG_DAC),y) CHIP_CSRCS += stm32_dac.c endif +ifeq ($(CONFIG_PWM),y) +CHIP_CSRCS += stm32_pwm.c +endif + ifeq ($(CONFIG_DEBUG),y) CHIP_CSRCS += stm32_dumpgpio.c endif diff --git a/arch/arm/src/stm32/stm32_adc.c b/arch/arm/src/stm32/stm32_adc.c index b8eac533a497c32685ab0daa03a401e6c6e0b374..64384295264cf2319318d9e3dc002e6014555c71 100644 --- a/arch/arm/src/stm32/stm32_adc.c +++ b/arch/arm/src/stm32/stm32_adc.c @@ -83,7 +83,131 @@ #if defined(CONFIG_STM32_ADC1) || defined(CONFIG_STM32_ADC2) || defined(CONFIG_STM32_ADC3) -/* ADC interrupts */ +/* Timer configuration: If a timer trigger is specified, then get information + * about the timer. + */ + +#if defined(CONFIG_STM32_TIM1_ADC1) +# define ADC1_HAVE_TIMER 1 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T1CC1 +# define ADC1_TIMER_BASE STM32_TIM1_BASE +# define ADC1_TIMER_PCLK_FREQUENCY STM32_PCLK2_FREQUENCY +#elif defined(CONFIG_STM32_TIM2_ADC1) +# define ADC1_HAVE_TIMER 1 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T2CC2 +# define ADC1_TIMER_BASE STM32_TIM2_BASE +# define ADC1_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY +#elif defined(CONFIG_STM32_TIM3_ADC1) +# define ADC1_HAVE_TIMER 1 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T3CC1 +# define ADC1_TIMER_BASE STM32_TIM3_BASE +# define ADC1_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY +#elif defined(CONFIG_STM32_TIM4_ADC1) +# define ADC1_HAVE_TIMER 1 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T4CC4 +# define ADC1_TIMER_BASE STM32_TIM4_BASE +# define ADC1_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY +#elif defined(CONFIG_STM32_TIM5_ADC1) +# define ADC1_HAVE_TIMER 1 +# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T5CC1 +# define ADC1_TIMER_BASE STM32_TIM5_BASE +# define ADC1_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY +#elif defined(CONFIG_STM32_TIM8_ADC1) +# define ADC1_HAVE_TIMER 1 +# define ADC1_EXTSEL_VALUE ??? which ???? +# define ADC1_TIMER_BASE STM32_TIM8_BASE +# define ADC1_TIMER_PCLK_FREQUENCY STM32_PCLK2_FREQUENCY +#else +# undef ADC1_HAVE_TIMER +#endif + +#if defined(ADC1_HAVE_TIMER) && !defined(CONFIG_STM32_ADC1_SAMPLE_FREQUENCY) +# error "CONFIG_STM32_ADC1_SAMPLE_FREQUENCY not defined" +#endif + +#if defined(CONFIG_STM32_TIM1_ADC2) +# define ADC2_HAVE_TIMER 1 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T1CC1 +# define ADC2_TIMER_BASE STM32_TIM1_BASE +# define ADC2_TIMER_PCLK_FREQUENCY STM32_PCLK2_FREQUENCY +#elif defined(CONFIG_STM32_TIM2_ADC2) +# define ADC2_HAVE_TIMER 1 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T2CC2 +# define ADC2_TIMER_BASE STM32_TIM2_BASE +# define ADC2_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY +#elif defined(CONFIG_STM32_TIM3_ADC2) +# define ADC2_HAVE_TIMER 1 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T3CC1 +# define ADC2_TIMER_BASE STM32_TIM3_BASE +# define ADC2_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY +#elif defined(CONFIG_STM32_TIM4_ADC2) +# define ADC2_HAVE_TIMER 1 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T4CC4 +# define ADC2_TIMER_BASE STM32_TIM4_BASE +# define ADC2_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY +#elif defined(CONFIG_STM32_TIM5_ADC2) +# define ADC2_HAVE_TIMER 1 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T5CC1 +# define ADC2_TIMER_BASE STM32_TIM5_BASE +# define ADC2_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY +#elif defined(CONFIG_STM32_TIM8_ADC2) +# define ADC2_HAVE_TIMER 1 +# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T8CC1 +# define ADC2_TIMER_BASE STM32_TIM8_BASE +# define ADC2_TIMER_PCLK_FREQUENCY STM32_PCLK2_FREQUENCY +#else +# undef ADC2_HAVE_TIMER +#endif + +#if defined(ADC2_HAVE_TIMER) && !defined(CONFIG_STM32_ADC2_SAMPLE_FREQUENCY) +# error "CONFIG_STM32_ADC2_SAMPLE_FREQUENCY not defined" +#endif + +#if defined(CONFIG_STM32_TIM1_ADC3) +# define ADC3_HAVE_TIMER 1 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T1CC1 +# define ADC3_TIMER_BASE STM32_TIM1_BASE +# define ADC3_TIMER_PCLK_FREQUENCY STM32_PCLK2_FREQUENCY +#elif defined(CONFIG_STM32_TIM2_ADC3) +# define ADC3_HAVE_TIMER 1 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T2CC2 +# define ADC3_TIMER_BASE STM32_TIM2_BASE +# define ADC3_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY +#elif defined(CONFIG_STM32_TIM3_ADC3) +# define ADC3_HAVE_TIMER 1 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T3CC1 +# define ADC3_TIMER_BASE STM32_TIM3_BASE +# define ADC3_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY +#elif defined(CONFIG_STM32_TIM4_ADC3) +# define ADC3_HAVE_TIMER 1 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T4CC4 +# define ADC3_TIMER_BASE STM32_TIM4_BASE +# define ADC3_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY +#elif defined(CONFIG_STM32_TIM5_ADC3) +# define ADC3_HAVE_TIMER 1 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T5CC1 +# define ADC3_TIMER_BASE STM32_TIM5_BASE +# define ADC3_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY +#elif defined(CONFIG_STM32_TIM8_ADC3) +# define ADC3_HAVE_TIMER 1 +# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T8CC1 +# define ADC3_TIMER_BASE STM32_TIM8_BASE +# define ADC3_TIMER_PCLK_FREQUENCY STM32_PCLK2_FREQUENCY +#else +# undef ADC3_HAVE_TIMER +#endif + +#if defined(ADC3_HAVE_TIMER) && !defined(CONFIG_STM32_ADC3_SAMPLE_FREQUENCY) +# error "CONFIG_STM32_ADC3_SAMPLE_FREQUENCY not defined" +#endif + +#if defined(ADC1_HAVE_TIMER) || defined(ADC2_HAVE_TIMER) || defined(ADC3_HAVE_TIMER) +# define ADC_HAVE_TIMER 1 +#else +# undef ADC_HAVE_TIMER +#endif + +/* ADC interrupts ***********************************************************/ #ifdef CONFIG_STM32_STM32F10XX # define ADC_SR_ALLINTS (ADC_SR_AWD | ADC_SR_EOC | ADC_SR_JEOC) @@ -97,7 +221,24 @@ # define ADC_CR1_ALLINTS (ADC_CR1_AWDIE | ADC_CR1_EOCIE | ADC_CR1_JEOCIE | ADC_CR1_OVRIE) #endif -/* The maximum number of samples */ +/* Timer Setup **************************************************************/ +/* Calculate timer divider values based upon ADCn_TIMER_PCLK_FREQUENCY and + * CONFIG_STM32_ADCn_SAMPLE_FREQUENCY. + */ + +#ifdef ADC1_HAVE_TIMER +# warning "Missing Logic" +#endif + +#ifdef ADC2_HAVE_TIMER +# warning "Missing Logic" +#endif + +#ifdef ADC3_HAVE_TIMER +# warning "Missing Logic" +#endif + +/* The maximum number of channels that can be sampled */ #define ADC_MAX_SAMPLES 16 @@ -115,6 +256,11 @@ struct stm32_dev_s uint8_t current; /* Current ADC channel being converted */ xcpt_t isr; /* Interrupt handler for this ADC block */ uint32_t base; /* Base address of registers unique to this ADC block */ +#ifdef ADC_HAVE_TIMER + uint32_t tbase; /* Base address of timer used by this ADC block */ + uint32_t extsel; /* EXTSEL value used by this ADC block */ + uint32_t pclck; /* The PCLK frequency that drivers this timer */ +#endif uint8_t chanlist[ADC_MAX_SAMPLES]; }; @@ -149,7 +295,12 @@ static int adc_setup(FAR struct adc_dev_s *dev); static void adc_shutdown(FAR struct adc_dev_s *dev); static void adc_rxint(FAR struct adc_dev_s *dev, bool enable); static int adc_ioctl(FAR struct adc_dev_s *dev, int cmd, unsigned long arg); -static void adc_enable(FAR struct adc_dev_s *dev, bool enable); +static void adc_enable(FAR struct stm32_dev_s *priv, bool enable); + +#ifdef ADC_HAVE_TIMER +static int adc_timinit(FAR struct stm32_dev_s *priv); +#endif +static void adc_startconv(FAR struct stm32_dev_s *priv, bool enable); /**************************************************************************** * Private Data @@ -180,6 +331,11 @@ static struct stm32_dev_s g_adcpriv1 = #endif .intf = 1, .base = STM32_ADC1_BASE, +#ifdef ADC1_HAVE_TIMER + .tbase = ADC1_TIMER_BASE, + .extsel = ADC1_EXTSEL_VALUE, + .pclck = ADC1_TIMER_PCLK_FREQUENCY, +#endif }; static struct adc_dev_s g_adcdev1 = @@ -203,6 +359,11 @@ static struct stm32_dev_s g_adcpriv2 = #endif .intf = 2; .base = STM32_ADC2_BASE, +#ifdef ADC2_HAVE_TIMER + .tbase = ADC2_TIMER_BASE, + .extsel = ADC2_EXTSEL_VALUE, + .pclck = ADC2_TIMER_PCLK_FREQUENCY, +#endif }; static struct adc_dev_s g_adcdev2 = @@ -226,6 +387,11 @@ static struct stm32_dev_s g_adcpriv3 = #endif .intf = 3; .base = STM32_ADC3_BASE, +#ifdef ADC3_HAVE_TIMER + .tbase = ADC3_TIMER_BASE, + .extsel = ADC3_EXTSEL_VALUE, + .pclck = ADC3_TIMER_PCLK_FREQUENCY, +#endif }; static struct adc_dev_s g_adcdev3 = @@ -277,6 +443,116 @@ static void adc_putreg(struct stm32_dev_s *priv, int offset, uint32_t value) putreg32(value, priv->base + offset); } +/**************************************************************************** + * Name: tim_getreg + * + * Description: + * Read the value of an ADC timer register. + * + * Input Parameters: + * priv - A reference to the ADC block status + * offset - The offset to the register to read + * + * Returned Value: + * The current contents of the specified register + * + ****************************************************************************/ + +#ifdef HAVE_DMA +static uint32_t tim_getreg(struct stm32_dev_s *priv, int offset) +{ + return getreg32(priv->tbase + offset); +} +#endif + +/**************************************************************************** + * Name: tim_putreg + * + * Description: + * Read the value of an ADC timer register. + * + * Input Parameters: + * priv - A reference to the ADC block status + * offset - The offset to the register to read + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void tim_putreg(struct stm32_dev_s *priv, int offset, uint32_t value) +{ + putreg32(value, priv->tbase + offset); +} +#endif + +/**************************************************************************** + * Name: adc_timinit + * + * Description: + * Initialize the timer that drivers the ADC sampling for this channel using + * the pre-calculated timer divider definitions. + * + * Input Parameters: + * chan - A reference to the DAC channel state data + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +#ifdef ADC_HAVE_TIMER +static int adc_timinit(FAR struct stm32_dev_s *priv) +{ + /* Configure the time base: Timer period, prescaler, clock division, + * counter mode (up). + */ +#warning "Missing Logic" + + /* Selection EXTSEL selection: update */ +#warning "Missing Logic" + + /* Enable the counter */ +#warning "Missing Logic" +} +#endif + +/**************************************************************************** + * Name: adc_startconv + * + * Description: + * Start (or stop) the ADC conversion process + * + * Input Parameters: + * priv - A reference to the ADC block status + * enable - True: Start conversion + * + * Returned Value: + * + ****************************************************************************/ + +static void adc_startconv(struct stm32_dev_s *priv, bool enable) +{ + uint32_t regval; + + avdbg("enable: %d\n", enable); + + regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET); + if (enable) + { + /* Start conversion of regular channles */ + + regval |= ADC_CR2_SWSTART; + } + else + { + /* Disable the conversion of regular channels */ + + regval &= ~ADC_CR2_SWSTART; + } + regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET); +} + /**************************************************************************** * Name: adc_rccreset * @@ -363,9 +639,8 @@ static void adc_rccreset(struct stm32_dev_s *priv, bool reset) * *******************************************************************************/ -static void adc_enable(FAR struct adc_dev_s *dev, bool enable) +static void adc_enable(FAR struct stm32_dev_s *priv, bool enable) { - FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv; uint32_t regval; avdbg("enable: %d\n", enable); @@ -380,6 +655,10 @@ static void adc_enable(FAR struct adc_dev_s *dev, bool enable) regval &= ~ADC_CR2_ADON; } adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval); + + /* Enable or disable conversions */ + +//adc_startconv(priv, enable); } /**************************************************************************** @@ -473,38 +752,47 @@ 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 */ regval |= ADC_CR1_EOCIE; - - adc_putreg(priv, STM32_ADC_CR1_OFFSET, regval); -#warning "Only one channel is able to be guarded for the watchdog" -#warning "The channel is configured in the ADC_CR1_AWDCH [4:0]" -#warning "We have to decide if we need this watchdog " + adc_putreg(priv, STM32_ADC_CR1_OFFSET, regval); /* ADC1 CR2 Configuration */ - - /* Set the ADON bit to wake up the ADC from power down mode */ regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET); - regval |= ADC_CR2_ADON; - + /* Clear CONT, ALIGN (Right = 0) and EXTTRIG bits */ regval &= ~ADC_CR2_CONT; regval &= ~ADC_CR2_ALIGN; regval &= ~ADC_CR2_EXTSEL_MASK; + + /* EXTTRIG: External Trigger Conversion mode for regular channels enable*/ + + //regval |= ADC_CR2_EXTTRIG; - /* SWSTART: Start conversion of regular channels */ + /* EXTSEL[2:0]: External event select for regular group + * These bits select the external event used to trigger the start + * of conversion of a regular group: + * 000: Timer 1 CC1 event + * 001: Timer 1 CC2 event + * 010: Timer 1 CC3 event + * 011: Timer 2 CC2 event + * 100: Timer 3 TRGO event + * 101: Timer 4 CC4 event + * 110: EXTI line11/TIM8_TRGO event (TIM8_TRGO is available only in high-density devices) + * 111: SWSTART + */ + + /* Select trigger when SWSTART is set */ + //regval |= ADC_CR2_EXTSEL_SWSTART; -#warning "Don't you want to finish setting up the registers before starting the conversion?" - regval |= ADC_CR2_SWSTART; adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval); - + /* Configuration of the channel conversions */ regval = adc_getreg(priv, STM32_ADC_SQR3_OFFSET) & ADC_SQR3_RESERVED; @@ -513,7 +801,7 @@ static void adc_reset(FAR struct adc_dev_s *dev) regval |= (uint32_t)priv->chanlist[i] << offset; } adc_putreg(priv, STM32_ADC_SQR3_OFFSET, regval); - + regval = adc_getreg(priv, STM32_ADC_SQR2_OFFSET) & ADC_SQR2_RESERVED; for (i = 6, offset = 0; i < priv->nchannels && i < 12; i++, offset += 5) { @@ -537,15 +825,21 @@ static void adc_reset(FAR struct adc_dev_s *dev) /* Set the channel index of the first conversion */ priv->current = 0; - irqrestore(flags); - avdbg("CR1: 0x%08x CR2: 0x%08x\n", + /* Set ADON to wake up the ADC from Power Down state. */ + + adc_enable(priv, true); + adc_startconv(priv, true); + irqrestore(flags); + + avdbg("SR: %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)) + 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)) + adc_getreg(priv, STM32_ADC_SQR3_OFFSET)); } /**************************************************************************** @@ -632,9 +926,9 @@ static void adc_rxint(FAR struct adc_dev_s *dev, bool enable) regval = adc_getreg(priv, STM32_ADC_CR1_OFFSET); if (enable) { - /* Enable the end-of-conversion ADC interrupt */ + /* Enable the end-of-conversion ADC and analog watchdog interrupts */ - regval |= ADC_CR1_EOCIE; + regval |= (ADC_CR1_EOCIE | ADC_CR1_AWDIE); } else { @@ -659,7 +953,7 @@ static void adc_rxint(FAR struct adc_dev_s *dev, bool enable) static int adc_ioctl(FAR struct adc_dev_s *dev, int cmd, unsigned long arg) { - avdbg("intf: %d\n", priv->intf); + avdbg("Entry\n"); return -ENOTTY; } @@ -680,7 +974,6 @@ static int adc_interrupt(FAR struct adc_dev_s *dev) FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv; uint32_t adcsr; int32_t value; - uint8_t ch; avdbg("intf: %d\n", priv->intf); @@ -700,6 +993,10 @@ static int adc_interrupt(FAR struct adc_dev_s *dev) value = adc_getreg(priv, STM32_ADC_DR_OFFSET); value &= ADC_DR_DATA_MASK; +#ifdef ADC_DUALMODE +#error "not yet implemented" + value &= ADC_DR_ADC2DATA_MASK; +#endif /* Give the ADC data to the ADC dirver. adc_receive accepts 3 parameters: * @@ -708,18 +1005,21 @@ static int adc_interrupt(FAR struct adc_dev_s *dev) * 3) The third is the converted data for the channel. */ - adc_receive(dev, priv->current, value); + avdbg("Calling adc_receive(priv, ch=%d, value=%d)\n", + priv->chanlist[priv->current], value); + adc_receive(dev, priv->chanlist[priv->current], value); + /* Set the channel number of the next channel that will complete conversion */ if (++priv->current >= priv->nchannels) { - /* Restart the conversion sequence from the beginning */ + /* Restart the conversion sequence from the beginning */ #warning "Missing logic" - - /* Reset the index to the first channel to be converted */ - - priv->current = 0; + + /* Reset the index to the first channel to be converted */ + + priv->current = 0; } } @@ -744,7 +1044,7 @@ static int adc12_interrupt(int irq, void *context) uint32_t regval; uint32_t pending; - avdbg("irq: %d\n"); + avdbg("irq: %d\n", irq); /* Check for pending ADC1 interrupts */ @@ -793,7 +1093,7 @@ static int adc3_interrupt(int irq, void *context) uint32_t regval; uint32_t pending; - avdbg("irq: %d\n"); + avdbg("irq: %d\n", irq); /* Check for pending ADC3 interrupts */ @@ -828,7 +1128,7 @@ static int adc123_interrupt(int irq, void *context) uint32_t regval; uint32_t pending; - avdbg("irq: %d\n"); + avdbg("irq: %d\n", irq); /* Check for pending ADC1 interrupts */ diff --git a/arch/arm/src/stm32/stm32_adc.h b/arch/arm/src/stm32/stm32_adc.h index eb5926f288af2773021f8127444302a24770e2c2..ce778c5d24cf37464619b2181ad811bdfe0df3a3 100644 --- a/arch/arm/src/stm32/stm32_adc.h +++ b/arch/arm/src/stm32/stm32_adc.h @@ -47,6 +47,104 @@ #include <nuttx/analog/adc.h> +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ +/* Configuration ********************************************************************/ +/* Timer devices may be used for different purposes. One special purpose is to + * control periodic ADC sampling. If CONFIG_STM32_TIMn is defined then + * CONFIG_STM32_TIMn_ADC must also be defined to indicate that timer "n" is intended + * to be used for that purpose. + */ + +/* For the STM32 F1 line, timers 1-4 may be used. For STM32 F4 line, timers 1-5 and + * 8 may be used. + */ + +#ifndef CONFIG_STM32_TIM1 +# undef CONFIG_STM32_TIM1_ADC +# undef CONFIG_STM32_TIM1_ADC1 +# undef CONFIG_STM32_TIM1_ADC2 +# undef CONFIG_STM32_TIM1_ADC3 +#endif +#ifndef CONFIG_STM32_TIM2 +# undef CONFIG_STM32_TIM2_ADC +# undef CONFIG_STM32_TIM2_ADC1 +# undef CONFIG_STM32_TIM2_ADC2 +# undef CONFIG_STM32_TIM2_ADC3 +#endif +#ifndef CONFIG_STM32_TIM3 +# undef CONFIG_STM32_TIM3_ADC +# undef CONFIG_STM32_TIM3_ADC1 +# undef CONFIG_STM32_TIM3_ADC2 +# undef CONFIG_STM32_TIM3_ADC3 +#endif +#ifndef CONFIG_STM32_TIM4 +# undef CONFIG_STM32_TIM4_ADC +# undef CONFIG_STM32_TIM4_ADC1 +# undef CONFIG_STM32_TIM4_ADC2 +# undef CONFIG_STM32_TIM4_ADC3 +#endif + +#if defined(CONFIG_STM32_STM32F40XX) +# ifndef CONFIG_STM32_TIM5 +# undef CONFIG_STM32_TIM5_ADC +# undef CONFIG_STM32_TIM5_ADC1 +# undef CONFIG_STM32_TIM5_ADC2 +# undef CONFIG_STM32_TIM5_ADC3 +# endif +# ifndef CONFIG_STM32_TIM8 +# undef CONFIG_STM32_TIM8_ADC +# undef CONFIG_STM32_TIM8_ADC1 +# undef CONFIG_STM32_TIM8_ADC2 +# undef CONFIG_STM32_TIM8_ADC3 +# endif +#else +# undef CONFIG_STM32_TIM5_ADC +# undef CONFIG_STM32_TIM5_ADC1 +# undef CONFIG_STM32_TIM5_ADC2 +# undef CONFIG_STM32_TIM5_ADC3 +# undef CONFIG_STM32_TIM8_ADC +# undef CONFIG_STM32_TIM8_ADC1 +# undef CONFIG_STM32_TIM8_ADC2 +# undef CONFIG_STM32_TIM8_ADC3 +#endif + +/* Timers 6, 7, and 10-14 are not used with the ADC by any supported family */ + +#undef CONFIG_STM32_TIM6_ADC +#undef CONFIG_STM32_TIM6_ADC1 +#undef CONFIG_STM32_TIM6_ADC2 +#undef CONFIG_STM32_TIM6_ADC3 +#undef CONFIG_STM32_TIM7_ADC +#undef CONFIG_STM32_TIM7_ADC1 +#undef CONFIG_STM32_TIM7_ADC2 +#undef CONFIG_STM32_TIM7_ADC3 +#undef CONFIG_STM32_TIM9_ADC +#undef CONFIG_STM32_TIM9_ADC1 +#undef CONFIG_STM32_TIM9_ADC2 +#undef CONFIG_STM32_TIM9_ADC3 +#undef CONFIG_STM32_TIM10_ADC +#undef CONFIG_STM32_TIM10_ADC1 +#undef CONFIG_STM32_TIM10_ADC2 +#undef CONFIG_STM32_TIM10_ADC3 +#undef CONFIG_STM32_TIM11_ADC +#undef CONFIG_STM32_TIM11_ADC1 +#undef CONFIG_STM32_TIM11_ADC2 +#undef CONFIG_STM32_TIM11_ADC3 +#undef CONFIG_STM32_TIM12_ADC +#undef CONFIG_STM32_TIM12_ADC1 +#undef CONFIG_STM32_TIM12_ADC2 +#undef CONFIG_STM32_TIM12_ADC3 +#undef CONFIG_STM32_TIM13_ADC +#undef CONFIG_STM32_TIM13_ADC1 +#undef CONFIG_STM32_TIM13_ADC2 +#undef CONFIG_STM32_TIM13_ADC3 +#undef CONFIG_STM32_TIM14_ADC +#undef CONFIG_STM32_TIM14_ADC1 +#undef CONFIG_STM32_TIM14_ADC2 +#undef CONFIG_STM32_TIM14_ADC3 + /************************************************************************************ * Public Function Prototypes ************************************************************************************/ diff --git a/arch/arm/src/stm32/stm32_dac.c b/arch/arm/src/stm32/stm32_dac.c index 8d152c57f74de447018b16fb6977932cd8c5aeb9..ad767371fdb3ca55f02f49c22b7d018d112325ef 100644 --- a/arch/arm/src/stm32/stm32_dac.c +++ b/arch/arm/src/stm32/stm32_dac.c @@ -172,49 +172,49 @@ #ifdef CONFIG_STM32_DAC1_DMA # if CONFIG_STM32_DAC1_TIMER == 6 -# ifndef CONFIG_STM32_TIM6 -# error "CONFIG_STM32_TIM6 required for DAC1" +# ifndef CONFIG_STM32_TIM6_DAC +# error "CONFIG_STM32_TIM6_DAC required for DAC1" # endif # define DAC1_TSEL_VALUE DAC_CR_TSEL_TIM6 # define DAC1_TIMER_BASE STM32_TIM6_BASE # define DAC1_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY # elif CONFIG_STM32_DAC1_TIMER == 3 && defined(CONFIG_STM32_CONNECTIVITYLINE) -# ifndef CONFIG_STM32_TIM3 -# error "CONFIG_STM32_TIM3 required for DAC1" +# ifndef CONFIG_STM32_TIM3_DAC +# error "CONFIG_STM32_TIM3_DAC required for DAC1" # endif # define DAC1_TSEL_VALUE DAC_CR_TSEL_TIM3 # define DAC1_TIMER_BASE STM32_TIM3_BASE # define DAC1_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY # elif CONFIG_STM32_DAC1_TIMER == 8 && !defined(CONFIG_STM32_CONNECTIVITYLINE) -# ifndef CONFIG_STM32_TIM8 -# error "CONFIG_STM32_TIM8 required for DAC1" +# ifndef CONFIG_STM32_TIM8_DAC +# error "CONFIG_STM32_TIM8_DAC required for DAC1" # endif # define DAC1_TSEL_VALUE DAC_CR_TSEL_TIM8 # define DAC1_TIMER_BASE STM32_TIM8_BASE # define DAC1_TIMER_PCLK_FREQUENCY STM32_PCLK2_FREQUENCY # elif CONFIG_STM32_DAC1_TIMER == 7 -# ifndef CONFIG_STM32_TIM7 -# error "CONFIG_STM32_TIM7 required for DAC1" +# ifndef CONFIG_STM32_TIM7_DAC +# error "CONFIG_STM32_TIM7_DAC required for DAC1" # endif # define DAC1_TSEL_VALUE DAC_CR_TSEL_TIM7 # define DAC1_TIMER_BASE STM32_TIM7_BASE # elif CONFIG_STM32_DAC1_TIMER == 5 -# ifndef CONFIG_STM32_TIM5 -# error "CONFIG_STM32_TIM5 required for DAC1" +# ifndef CONFIG_STM32_TIM5_DAC +# error "CONFIG_STM32_TIM5_DAC required for DAC1" # endif # define DAC1_TSEL_VALUE DAC_CR_TSEL_TIM5 # define DAC1_TIMER_BASE STM32_TIM5_BASE # define DAC1_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY # elif CONFIG_STM32_DAC1_TIMER == 2 -# ifndef CONFIG_STM32_TIM2 -# error "CONFIG_STM32_TIM2 required for DAC1" +# ifndef CONFIG_STM32_TIM2_DAC +# error "CONFIG_STM32_TIM2_DAC required for DAC1" # endif # define DAC1_TSEL_VALUE DAC_CR_TSEL_TIM2 # define DAC1_TIMER_BASE STM32_TIM2_BASE # define DAC1_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY # elif CONFIG_STM32_DAC1_TIMER == 4 -# ifndef CONFIG_STM32_TIM4 -# error "CONFIG_STM32_TIM4 required for DAC1" +# ifndef CONFIG_STM32_TIM4_DAC +# error "CONFIG_STM32_TIM4_DAC required for DAC1" # endif # define DAC1_TSEL_VALUE DAC_CR_TSEL_TIM4 # define DAC1_TIMER_BASE STM32_TIM4_BASE @@ -228,50 +228,50 @@ #ifdef CONFIG_STM32_DAC2_DMA # if CONFIG_STM32_DAC2_TIMER == 6 -# ifndef CONFIG_STM32_TIM6 -# error "CONFIG_STM32_TIM6 required for DAC2" +# ifndef CONFIG_STM32_TIM6_DAC +# error "CONFIG_STM32_TIM6_DAC required for DAC2" # endif # define DAC2_TSEL_VALUE DAC_CR_TSEL_TIM6 # define DAC2_TIMER_BASE STM32_TIM6_BASE # define DAC2_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY # elif CONFIG_STM32_DAC2_TIMER == 3 && defined(CONFIG_STM32_CONNECTIVITYLINE) -# ifndef CONFIG_STM32_TIM3 -# error "CONFIG_STM32_TIM3 required for DAC2" +# ifndef CONFIG_STM32_TIM3_DAC +# error "CONFIG_STM32_TIM3_DAC required for DAC2" # endif # define DAC2_TSEL_VALUE DAC_CR_TSEL_TIM3 # define DAC2_TIMER_BASE STM32_TIM3_BASE # define DAC2_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY # elif CONFIG_STM32_DAC2_TIMER == 8 && !defined(CONFIG_STM32_CONNECTIVITYLINE) -# ifndef CONFIG_STM32_TIM8 -# error "CONFIG_STM32_TIM8 required for DAC2" +# ifndef CONFIG_STM32_TIM8_DAC +# error "CONFIG_STM32_TIM8_DAC required for DAC2" # endif # define DAC2_TSEL_VALUE DAC_CR_TSEL_TIM8 # define DAC2_TIMER_BASE STM32_TIM8_BASE # define DAC2_TIMER_PCLK_FREQUENCY STM32_PCLK2_FREQUENCY # elif CONFIG_STM32_DAC2_TIMER == 7 -# ifndef CONFIG_STM32_TIM7 -# error "CONFIG_STM32_TIM7 required for DAC2" +# ifndef CONFIG_STM32_TIM7_DAC +# error "CONFIG_STM32_TIM7_DAC required for DAC2" # endif # define DAC2_TSEL_VALUE DAC_CR_TSEL_TIM7 # define DAC2_TIMER_BASE STM32_TIM7_BASE # define DAC2_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY # elif CONFIG_STM32_DAC2_TIMER == 5 -# ifndef CONFIG_STM32_TIM5 -# error "CONFIG_STM32_TIM5 required for DAC2" +# ifndef CONFIG_STM32_TIM5_DAC +# error "CONFIG_STM32_TIM5_DAC required for DAC2" # endif # define DAC2_TSEL_VALUE DAC_CR_TSEL_TIM5 # define DAC2_TIMER_BASE STM32_TIM5_BASE # define DAC2_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY # elif CONFIG_STM32_DAC2_TIMER == 2 -# ifndef CONFIG_STM32_TIM2 -# error "CONFIG_STM32_TIM2 required for DAC2" +# ifndef CONFIG_STM32_TIM2_DAC +# error "CONFIG_STM32_TIM2_DAC required for DAC2" # endif # define DAC2_TSEL_VALUE DAC_CR_TSEL_TIM2 # define DAC2_TIMER_BASE STM32_TIM2_BASE # define DAC2_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY # elif CONFIG_STM32_DAC2_TIMER == 4 -# ifndef CONFIG_STM32_TIM4 -# error "CONFIG_STM32_TIM4 required for DAC2" +# ifndef CONFIG_STM32_TIM4_DAC +# error "CONFIG_STM32_TIM4_DAC required for DAC2" # endif # define DAC2_TSEL_VALUE DAC_CR_TSEL_TIM4 # define DAC2_TIMER_BASE STM32_TIM4_BASE diff --git a/arch/arm/src/stm32/stm32_dac.h b/arch/arm/src/stm32/stm32_dac.h index 41d681ee76297b9a16710066e0b3990eb03c7a80..44404e6fb3244b981d1acb194a36a9e1479904d0 100644 --- a/arch/arm/src/stm32/stm32_dac.h +++ b/arch/arm/src/stm32/stm32_dac.h @@ -47,6 +47,59 @@ #include <nuttx/analog/dac.h> +/************************************************************************************ + * Pre-processor definitions + ************************************************************************************/ +/* Configuration ********************************************************************/ +/* Timer devices may be used for different purposes. One special purpose is to + * control periodic DAC outputs. If CONFIG_STM32_TIMn is defined then + * CONFIG_STM32_TIMn_DAC must also be defined to indicate that timer "n" is intended + * to be used for that purpose. + */ + +#ifndef CONFIG_STM32_TIM1 +# undef CONFIG_STM32_TIM1_DAC +#endif +#ifndef CONFIG_STM32_TIM2 +# undef CONFIG_STM32_TIM2_DAC +#endif +#ifndef CONFIG_STM32_TIM3 +# undef CONFIG_STM32_TIM3_DAC +#endif +#ifndef CONFIG_STM32_TIM4 +# undef CONFIG_STM32_TIM4_DAC +#endif +#ifndef CONFIG_STM32_TIM5 +# undef CONFIG_STM32_TIM5_DAC +#endif +#ifndef CONFIG_STM32_TIM6 +# undef CONFIG_STM32_TIM6_DAC +#endif +#ifndef CONFIG_STM32_TIM7 +# undef CONFIG_STM32_TIM7_DAC +#endif +#ifndef CONFIG_STM32_TIM8 +# undef CONFIG_STM32_TIM8_DAC +#endif +#ifndef CONFIG_STM32_TIM9 +# undef CONFIG_STM32_TIM9_DAC +#endif +#ifndef CONFIG_STM32_TIM10 +# undef CONFIG_STM32_TIM10_DAC +#endif +#ifndef CONFIG_STM32_TIM11 +# undef CONFIG_STM32_TIM11_DAC +#endif +#ifndef CONFIG_STM32_TIM12 +# undef CONFIG_STM32_TIM12_DAC +#endif +#ifndef CONFIG_STM32_TIM13 +# undef CONFIG_STM32_TIM13_DAC +#endif +#ifndef CONFIG_STM32_TIM14 +# undef CONFIG_STM32_TIM14_DAC +#endif + /************************************************************************************ * Public Function Prototypes ************************************************************************************/ diff --git a/arch/arm/src/stm32/stm32_pwm.c b/arch/arm/src/stm32/stm32_pwm.c new file mode 100644 index 0000000000000000000000000000000000000000..8646bfcd76c30f4736f677d6c8a9d29de48894b6 --- /dev/null +++ b/arch/arm/src/stm32/stm32_pwm.c @@ -0,0 +1,459 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_pwm.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stdint.h> +#include <stdio.h> +#include <assert.h> +#include <debug.h> + +#include <nuttx/pwm.h> + +#include "up_internal.h" +#include "up_arch.h" + +#include "chip.h" +#include "stm32_pwm.h" +#include "stm32_internal.h" + +/* This module then only compiles if there is at least one enabled timer + * intended for use with the PWM upper half driver. + */ + +#if defined(CONFIG_STM32_TIM1_PWM) || defined(CONFIG_STM32_TIM2_PWM) || \ + defined(CONFIG_STM32_TIM3_PWM) || defined(CONFIG_STM32_TIM4_PWM) || \ + defined(CONFIG_STM32_TIM5_PWM) || defined(CONFIG_STM32_TIM6_PWM) || \ + defined(CONFIG_STM32_TIM7_PWM) || defined(CONFIG_STM32_TIM8_PWM) || \ + defined(CONFIG_STM32_TIM9_PWM) || defined(CONFIG_STM32_TIM10_PWM) || \ + defined(CONFIG_STM32_TIM11_PWM) || defined(CONFIG_STM32_TIM12_PWM) || \ + defined(CONFIG_STM32_TIM13_PWM) || defined(CONFIG_STM32_TIM14_PWM) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ +/* This structure representst the state of one PWM timer */ + +struct stm32_pwmtimer_s +{ + uint32_t base; /* The base address of the timer */ +}; + +/**************************************************************************** + * Static Function Prototypes + ****************************************************************************/ + +static int pwm_setup(FAR struct pwm_lowerhalf_s *dev); +static int pwm_shutdown(FAR struct pwm_lowerhalf_s *dev); +static int pwm_start(FAR struct pwm_lowerhalf_s *dev, FAR const struct pwm_info_s *info); +static int pwm_stop(FAR struct pwm_lowerhalf_s *dev); +static int pwm_pulsecount(FAR struct pwm_lowerhalf_s *dev, FAR pwm_count_t *count); +static int pwm_ioctl(FAR struct pwm_lowerhalf_s *dev, int cmd, unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ +/* This is the list of lower half PWM driver methods used by the upper half driver */ + +static const struct pwm_ops_s g_pwmops = +{ + .setup = pwm_setup(FAR struct pwm_lowerhalf_s *dev); + .shutdown = pwm_shutdown(FAR struct pwm_lowerhalf_s *dev); + .start = pwm_start(FAR struct pwm_lowerhalf_s *dev, FAR const struct pwm_info_s *info); + .stop = pwm_stop(FAR struct pwm_lowerhalf_s *dev); + .pulsecount = pwm_pulsecount(FAR struct pwm_lowerhalf_s *dev, FAR pwm_count_t *count); + .ioctl = pwm_ioctl(FAR struct pwm_lowerhalf_s *dev, int cmd, unsigned long arg); +}; + +/* The following represent the state of each possible PWM driver */ + +#ifdef CONFIG_STM32_TIM1_PWM +static struct stm32_pwmtimer_s g_pwm1dev = +{ + .ops = *g_pwmops; + .base = STM32_TIM1_BASE; +}; +#endif + +#ifdef CONFIG_STM32_TIM2_PWM +static struct stm32_pwmtimer_s g_pwm2dev = +{ + .ops = *g_pwmops; + .base = STM32_TIM2_BASE; +}; +#endif + +#ifdef CONFIG_STM32_TIM3_PWM +static struct stm32_pwmtimer_s g_pwm3dev = +{ + .ops = *g_pwmops; + .base = STM32_TIM3_BASE; +}; +#endif + +#ifdef CONFIG_STM32_TIM4_PWM +static struct stm32_pwmtimer_s g_pwm4dev = +{ + .ops = *g_pwmops; + .base = STM32_TIM4_BASE; +}; +#endif + +#ifdef CONFIG_STM32_TIM5_PWM +static struct stm32_pwmtimer_s g_pwm5dev = +{ + .ops = *g_pwmops; + .base = STM32_TIM5_BASE; +}; +#endif + +#ifdef CONFIG_STM32_TIM6_PWM +static struct stm32_pwmtimer_s g_pwm6dev = +{ + .ops = *g_pwmops; + .base = STM32_TIM6_BASE; +}; +#endif + +#ifdef CONFIG_STM32_TIM7_PWM +static struct stm32_pwmtimer_s g_pwm7dev = +{ + .ops = *g_pwmops; + .base = STM32_TIM7_BASE; +}; +#endif + +#ifdef CONFIG_STM32_TIM8_PWM +static struct stm32_pwmtimer_s g_pwm8dev = +{ + .ops = *g_pwmops; + .base = STM32_TIM8_BASE; +}; +#endif + +#ifdef CONFIG_STM32_TIM9_PWM +static struct stm32_pwmtimer_s g_pwm9dev = +{ + .ops = *g_pwmops; + .base = STM32_TIM9_BASE; +}; +#endif + +#ifdef CONFIG_STM32_TIM10_PWM +static struct stm32_pwmtimer_s g_pwm10dev = +{ + .ops = *g_pwmops; + .base = STM32_TIM10_BASE; +}; +#endif + +#ifdef CONFIG_STM32_TIM11_PWM +static struct stm32_pwmtimer_s g_pwm11dev = +{ + .ops = *g_pwmops; + .base = STM32_TIM11_BASE; +}; +#endif + +#ifdef CONFIG_STM32_TIM12_PWM +static struct stm32_pwmtimer_s g_pwm12dev = +{ + .ops = *g_pwmops; + .base = STM32_TIM12_BASE; +}; +#endif + +#ifdef CONFIG_STM32_TIM13_PWM +static struct stm32_pwmtimer_s g_pwm13dev = +{ + .ops = *g_pwmops; + .base = STM32_TIM13_BASE; +}; +#endif + +#ifdef CONFIG_STM32_TIM14_PWM +static struct stm32_pwmtimer_s g_pwm14dev = +{ + .ops = *g_pwmops; + .base = STM32_TIM14_BASE; +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pwm_setup + * + * Description: + * This method is called when the driver is opened. The lower half driver + * should configure and initialize the device so that it is ready for use. + * It should not, however, output pulses until the start method is called. + * + * Input parameters: + * dev - A reference to the lower half PWM driver state structure + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + ****************************************************************************/ + +static int pwm_setup(FAR struct pwm_lowerhalf_s *dev) +{ +#warning "Missing logic" + return -ENOSYS; +} + +/**************************************************************************** + * Name: pwm_shutdown + * + * Description: + * This method is called when the driver is closed. The lower half driver + * stop pulsed output, free any resources, disable the timer hardware, and + * put the system into the lowest possible power usage state + * + * Input parameters: + * dev - A reference to the lower half PWM driver state structure + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + ****************************************************************************/ + +static int pwm_shutdown(FAR struct pwm_lowerhalf_s *dev) +{ +#warning "Missing logic" + return -ENOSYS; +} + +/**************************************************************************** + * Name: pwm_start + * + * Description: + * (Re-)initialize the timer resources and start the pulsed output + * + * Input parameters: + * dev - A reference to the lower half PWM driver state structure + * info - A reference to the characteristics of the pulsed output + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + ****************************************************************************/ + +static int pwm_start(FAR struct pwm_lowerhalf_s *dev, FAR const struct pwm_info_s *info) +{ +#warning "Missing logic" + return -ENOSYS; +} + +/**************************************************************************** + * Name: pwm_stop + * + * Description: + * Stop the pulsed output and reset the timer resources + * + * Input parameters: + * dev - A reference to the lower half PWM driver state structure + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + ****************************************************************************/ + +static int pwm_stop(FAR struct pwm_lowerhalf_s *dev) +{ +#warning "Missing logic" + return -ENOSYS; +} + +/**************************************************************************** + * Name: pwm_pulsecount + * + * Description: + * Get the number of pulses generated + * + * Input parameters: + * dev - A reference to the lower half PWM driver state structure + * count - A pointer to the location to return the pulse count + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + ****************************************************************************/ + +static int pwm_pulsecount(FAR struct pwm_lowerhalf_s *dev, FAR pwm_count_t *count) +{ +#warning "Missing logic" + return -ENOSYS; +} + +/**************************************************************************** + * Name: + * + * Description: + * Lower-half logic may support platform-specific ioctl commands + * + * Input parameters: + * dev - A reference to the lower half PWM driver state structure + * cmd - The ioctl command + * arg - The argument accompanying the ioctl command + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + ****************************************************************************/ + +static int pwm_ioctl(FAR struct pwm_lowerhalf_s *dev, int cmd, unsigned long arg) +{ + /* There are no platform-specific ioctl commands */ + + return -ENOTTY; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_pwminitialize + * + * Description: + * Initialize one timer for use with the upper_level PWM driver. + * + * Input Parameters: + * timer - A number identifying the timer use. The number of valid timer + * IDs varies with the STM32 MCU and MCU family but is somewhere in + * the range of {1,..,14}. + * + * Returned Value: + * On success, a pointer to the STM32 lower half PWM driver is returned. + * NULL is returned on any failure. + * + ****************************************************************************/ + +FAR struct pwm_lowerhalf_s *stm32_pwminitialize(int timer) +{ + FAR struct stm32_pwmtimer_s *lower; + + switch (timer) + { +#ifdef CONFIG_STM32_TIM1_PWM + case 1: + lower = &g_pwm1dev; + break; +#endif +#ifdef CONFIG_STM32_TIM2_PWM + case 2: + lower = &g_pwm2dev; + break; +#endif +#ifdef CONFIG_STM32_TIM3_PWM + case 3: + lower = &g_pwm3dev; + break; +#endif +#ifdef CONFIG_STM32_TIM4_PWM + case 4: + lower = &g_pwm4dev; + break; +#endif +#ifdef CONFIG_STM32_TIM5_PWM + case 5: + lower = &g_pwm5dev; + break; +#endif +#ifdef CONFIG_STM32_TIM6_PWM + case 6: + lower = &g_pwm6dev; + break; +#endif +#ifdef CONFIG_STM32_TIM7_PWM + case 7: + lower = &g_pwm7dev; + break; +#endif +#ifdef CONFIG_STM32_TIM8_PWM + case 8: + lower = &g_pwm8dev; + break; +#endif +#ifdef CONFIG_STM32_TIM9_PWM + case 9: + lower = &g_pwm9dev; + break; +#endif +#ifdef CONFIG_STM32_TIM10_PWM + case 10: + lower = &g_pwm10dev; + break; +#endif +#ifdef CONFIG_STM32_TIM11_PWM + case 11: + lower = &g_pwm11dev; + break; +#endif +#ifdef CONFIG_STM32_TIM12_PWM + case 12: + lower = &g_pwm12dev; + break; +#endif +#ifdef CONFIG_STM32_TIM13_PWM + case 13: + lower = &g_pwm13dev; + break; +#endif +#ifdef CONFIG_STM32_TIM14_PWM + case 14: + lower = &g_pwm14dev; + break; +#endif + default: + return NULL; + } + + return (FAR struct pwm_lowerhalf_s *)lower; +} + +#endif /* CONFIG_STM32_TIMn_PWM, n = 1,...,14 */ diff --git a/arch/arm/src/stm32/stm32_pwm.h b/arch/arm/src/stm32/stm32_pwm.h new file mode 100644 index 0000000000000000000000000000000000000000..6204cda210f7f624b2213b2a2ed89bd4ce14766d --- /dev/null +++ b/arch/arm/src/stm32/stm32_pwm.h @@ -0,0 +1,154 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_pwm.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <gnutt@nuttx.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_STM32_TIM_H +#define __ARCH_ARM_SRC_STM32_STM32_TIM_H + +/* The STM32 does not have dedicated PWM hardware. Rather, pulsed output control + * is a capabilitiy of the STM32 timers. The logic in this file implements the + * lower half of the standard, NuttX PWM interface using the STM32 timers. That + * interface is described in include/nuttx/pwm.h. + */ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include <nuttx/config.h> + +#include "chip.h" +#include "chip/stm32_tim.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ +/* Configuration ********************************************************************/ +/* 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 then the CONFIG_STM32_TIMn_PWM must also be defined to indicate that + * timer "n" is intended to be used for pulsed output signal generation. + */ + +#ifndef CONFIG_STM32_TIM1 +# undef CONFIG_STM32_TIM1_PWM +#endif +#ifndef CONFIG_STM32_TIM2 +# undef CONFIG_STM32_TIM2_PWM +#endif +#ifndef CONFIG_STM32_TIM3 +# undef CONFIG_STM32_TIM3_PWM +#endif +#ifndef CONFIG_STM32_TIM4 +# undef CONFIG_STM32_TIM4_PWM +#endif +#ifndef CONFIG_STM32_TIM5 +# undef CONFIG_STM32_TIM5_PWM +#endif +#ifndef CONFIG_STM32_TIM6 +# undef CONFIG_STM32_TIM6_PWM +#endif +#ifndef CONFIG_STM32_TIM7 +# undef CONFIG_STM32_TIM7_PWM +#endif +#ifndef CONFIG_STM32_TIM8 +# undef CONFIG_STM32_TIM8_PWM +#endif +#ifndef CONFIG_STM32_TIM9 +# undef CONFIG_STM32_TIM9_PWM +#endif +#ifndef CONFIG_STM32_TIM10 +# undef CONFIG_STM32_TIM10_PWM +#endif +#ifndef CONFIG_STM32_TIM11 +# undef CONFIG_STM32_TIM11_PWM +#endif +#ifndef CONFIG_STM32_TIM12 +# undef CONFIG_STM32_TIM12_PWM +#endif +#ifndef CONFIG_STM32_TIM13 +# undef CONFIG_STM32_TIM13_PWM +#endif +#ifndef CONFIG_STM32_TIM14 +# undef CONFIG_STM32_TIM14_PWM +#endif + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_pwminitialize + * + * Description: + * Initialize one timer for use with the upper_level PWM driver. + * + * Input Parameters: + * timer - A number identifying the timer use. The number of valid timer + * IDs varies with the STM32 MCU and MCU family but is somewhere in + * the range of {1,..,14}. + * + * Returned Value: + * On success, a pointer to the STM32 lower half PWM driver is returned. + * NULL is returned on any failure. + * + ************************************************************************************/ + +EXTERN FAR struct pwm_lowerhalf_s *stm32_pwminitialize(int timer); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_STM32_STM32_TIM_H */ diff --git a/arch/arm/src/stm32/stm32_tim.c b/arch/arm/src/stm32/stm32_tim.c index 5ce4951789193f37c914754da125247d221dc41b..e25f02df46a4a400aca5ef082267bf435cd93252 100644 --- a/arch/arm/src/stm32/stm32_tim.c +++ b/arch/arm/src/stm32/stm32_tim.c @@ -4,6 +4,11 @@ * Copyright (C) 2011 Uros Platise. All rights reserved. * Author: Uros Platise <uros.platise@isotel.eu> * + * With modifications and updates by: + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <gnutt@nuttx.org> + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,10 +38,9 @@ * ************************************************************************************/ -/** \file - * \author Uros Platise - * \brief STM32 Basic, General and Advanced Timers - */ +/************************************************************************************ + * Included Files + ************************************************************************************/ #include <nuttx/config.h> #include <nuttx/arch.h> @@ -59,6 +63,74 @@ #include "stm32_gpio.h" #include "stm32_tim.h" +/************************************************************************************ + * Private Types + ************************************************************************************/ +/* Configuration ********************************************************************/ +/* Timer devices may be used for different purposes. Such special purposes include: + * + * - To generate modulated outputs for such things as motor control. If CONFIG_STM32_TIMn + * is defined then the CONFIG_STM32_TIMn_PWM may also be defined to indicate that + * the timer is intended to be used for pulsed output modulation. + * + * - To control periodic ADC input sampling. If CONFIG_STM32_TIMn is defined then + * CONFIG_STM32_TIMn_ADC may also be defined to indicate that timer "n" is intended + * to be used for that purpose. + * + * - To control periodic DAC outputs. If CONFIG_STM32_TIMn is defined then + * CONFIG_STM32_TIMn_DAC may also be defined to indicate that timer "n" is intended + * to be used for that purpose. + * + * In any of these cases, the timer will not be used by this timer module. + */ + +#if defined(CONFIG_STM32_TIM1_PWM) || defined (CONFIG_STM32_TIM1_ADC) || defined(CONFIG_STM32_TIM1_DAC) +# undef CONFIG_STM32_TIM1 +#endif +#if defined(CONFIG_STM32_TIM2_PWM || defined (CONFIG_STM32_TIM2_ADC) || defined(CONFIG_STM32_TIM2_DAC) +# undef CONFIG_STM32_TIM2 +#endif +#if defined(CONFIG_STM32_TIM3_PWM || defined (CONFIG_STM32_TIM3_ADC) || defined(CONFIG_STM32_TIM3_DAC) +# undef CONFIG_STM32_TIM3 +#endif +#if defined(CONFIG_STM32_TIM4_PWM || defined (CONFIG_STM32_TIM4_ADC) || defined(CONFIG_STM32_TIM4_DAC) +# undef CONFIG_STM32_TIM4 +#endif +#if defined(CONFIG_STM32_TIM5_PWM || defined (CONFIG_STM32_TIM5_ADC) || defined(CONFIG_STM32_TIM5_DAC) +# undef CONFIG_STM32_TIM5 +#endif +#if defined(CONFIG_STM32_TIM6_PWM || defined (CONFIG_STM32_TIM6_ADC) || defined(CONFIG_STM32_TIM6_DAC) +# undef CONFIG_STM32_TIM6 +#endif +#if defined(CONFIG_STM32_TIM7_PWM || defined (CONFIG_STM32_TIM7_ADC) || defined(CONFIG_STM32_TIM7_DAC) +# undef CONFIG_STM32_TIM7 +#endif +#if defined(CONFIG_STM32_TIM8_PWM || defined (CONFIG_STM32_TIM8_ADC) || defined(CONFIG_STM32_TIM8_DAC) +# undef CONFIG_STM32_TIM8 +#endif +#if defined(CONFIG_STM32_TIM9_PWM || defined (CONFIG_STM32_TIM9_ADC) || defined(CONFIG_STM32_TIM9_DAC) +# undef CONFIG_STM32_TIM9 +#endif +#if defined(CONFIG_STM32_TIM10_PWM || defined (CONFIG_STM32_TIM10_ADC) || defined(CONFIG_STM32_TIM10_DAC) +# undef CONFIG_STM32_TIM10 +#endif +#if defined(CONFIG_STM32_TIM11_PWM || defined (CONFIG_STM32_TIM11_ADC) || defined(CONFIG_STM32_TIM11_DAC) +# undef CONFIG_STM32_TIM11 +#endif +#if defined(CONFIG_STM32_TIM12_PWM || defined (CONFIG_STM32_TIM12_ADC) || defined(CONFIG_STM32_TIM12_DAC) +# undef CONFIG_STM32_TIM12 +#endif +#if defined(CONFIG_STM32_TIM13_PWM || defined (CONFIG_STM32_TIM13_ADC) || defined(CONFIG_STM32_TIM13_DAC) +# undef CONFIG_STM32_TIM13 +#endif +#if defined(CONFIG_STM32_TIM14_PWM || defined (CONFIG_STM32_TIM14_ADC) || defined(CONFIG_STM32_TIM14_DAC) +# undef CONFIG_STM32_TIM14 +#endif + +/* This module then only compiles if there are enabled timers that are not intended for + * some other purpose. + */ + #if defined(CONFIG_STM32_TIM1) || defined(CONFIG_STM32_TIM2) || defined(CONFIG_STM32_TIM3) || \ defined(CONFIG_STM32_TIM4) || defined(CONFIG_STM32_TIM5) || defined(CONFIG_STM32_TIM6) || \ defined(CONFIG_STM32_TIM7) || defined(CONFIG_STM32_TIM8) diff --git a/arch/arm/src/stm32/stm32_tim.h b/arch/arm/src/stm32/stm32_tim.h index 1aa18328e281fc2c66b6222456908bb5e4873b79..8f12b187560233157979ebd13121aecc3c77471e 100644 --- a/arch/arm/src/stm32/stm32_tim.h +++ b/arch/arm/src/stm32/stm32_tim.h @@ -4,6 +4,11 @@ * Copyright (C) 2011 Uros Platise. All rights reserved. * Author: Uros Platise <uros.platise@isotel.eu> * + * With modifications and updates by: + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <gnutt@nuttx.org> + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,14 +38,13 @@ * ************************************************************************************/ -/** \file - * \author Uros Platise - * \brief STM32 Timer Device Driver - */ - #ifndef __ARCH_ARM_SRC_STM32_STM32_TIM_H #define __ARCH_ARM_SRC_STM32_STM32_TIM_H +/************************************************************************************ + * Included Files + ************************************************************************************/ + #include <nuttx/config.h> #include "chip.h" @@ -49,6 +53,22 @@ /************************************************************************************ * Pre-processor Definitions ************************************************************************************/ +/* Helpers **************************************************************************/ + +#define STM32_TIM_SETMODE(d,mode) ((d)->ops->setmode(d,mode)) +#define STM32_TIM_SETCLOCK(d,freq) ((d)->ops->setclock(d,freq)) +#define STM32_TIM_SETPERIOD(d,period) ((d)->ops->setperiod(d,period)) +#define STM32_TIM_SETCHANNEL(d,ch,mode) ((d)->ops->setchannel(d,ch,mode)) +#define STM32_TIM_SETCOMPARE(d,ch,comp) ((d)->ops->setcompare(d,ch,comp)) +#define STM32_TIM_GETCAPTURE(d,ch) ((d)->ops->getcapture(d,ch)) +#define STM32_TIM_SETISR(d,hnd,s) ((d)->ops->setisr(d,hnd,s)) +#define STM32_TIM_ENABLEINT(d,s) ((d)->ops->enableint(d,s)) +#define STM32_TIM_DISABLEINT(d,s) ((d)->ops->disableint(d,s)) +#define STM32_TIM_ACKINT(d,s) ((d)->ops->ackint(d,s)) + +/************************************************************************************ + * Public Types + ************************************************************************************/ #ifndef __ASSEMBLY__ @@ -60,119 +80,107 @@ extern "C" { #define EXTERN extern #endif -/************************************************************************************ - * Public Types - ************************************************************************************/ +/* TIM Device Structure */ -/** TIM Device Structure - */ -struct stm32_tim_dev_s { - struct stm32_tim_ops_s *ops; +struct stm32_tim_dev_s +{ + struct stm32_tim_ops_s *ops; }; +/* TIM Modes of Operation */ -/** TIM Modes of Operation - */ -typedef enum { - STM32_TIM_MODE_UNUSED = -1, +typedef enum +{ + STM32_TIM_MODE_UNUSED = -1, - /* One of the following */ - STM32_TIM_MODE_MASK = 0x0310, - STM32_TIM_MODE_DISABLED = 0x0000, - STM32_TIM_MODE_UP = 0x0100, - STM32_TIM_MODE_DOWN = 0x0110, - STM32_TIM_MODE_UPDOWN = 0x0200, - STM32_TIM_MODE_PULSE = 0x0300, + /* One of the following */ + + STM32_TIM_MODE_MASK = 0x0310, + STM32_TIM_MODE_DISABLED = 0x0000, + STM32_TIM_MODE_UP = 0x0100, + STM32_TIM_MODE_DOWN = 0x0110, + STM32_TIM_MODE_UPDOWN = 0x0200, + STM32_TIM_MODE_PULSE = 0x0300, - /* One of the following */ - STM32_TIM_MODE_CK_INT = 0x0000, -// STM32_TIM_MODE_CK_INT_TRIG = 0x0400, -// STM32_TIM_MODE_CK_EXT = 0x0800, -// STM32_TIM_MODE_CK_EXT_TRIG = 0x0C00, - - /* Clock sources, OR'ed with CK_EXT */ -// STM32_TIM_MODE_CK_CHINVALID = 0x0000, -// STM32_TIM_MODE_CK_CH1 = 0x0001, -// STM32_TIM_MODE_CK_CH2 = 0x0002, -// STM32_TIM_MODE_CK_CH3 = 0x0003, -// STM32_TIM_MODE_CK_CH4 = 0x0004 + /* One of the following */ + + STM32_TIM_MODE_CK_INT = 0x0000, +//STM32_TIM_MODE_CK_INT_TRIG = 0x0400, +//STM32_TIM_MODE_CK_EXT = 0x0800, +//STM32_TIM_MODE_CK_EXT_TRIG = 0x0C00, + + /* Clock sources, OR'ed with CK_EXT */ + +//STM32_TIM_MODE_CK_CHINVALID = 0x0000, +//STM32_TIM_MODE_CK_CH1 = 0x0001, +//STM32_TIM_MODE_CK_CH2 = 0x0002, +//STM32_TIM_MODE_CK_CH3 = 0x0003, +//STM32_TIM_MODE_CK_CH4 = 0x0004 - /* Todo: external trigger block */ + /* Todo: external trigger block */ } stm32_tim_mode_t; +/* TIM Channel Modes */ -/** TIM Channel Modes - */ -typedef enum { - STM32_TIM_CH_DISABLED = 0x00, +typedef enum +{ + STM32_TIM_CH_DISABLED = 0x00, - /* Common configuration */ - STM32_TIM_CH_POLARITY_POS = 0x00, - STM32_TIM_CH_POLARITY_NEG = 0x01, + /* Common configuration */ + + STM32_TIM_CH_POLARITY_POS = 0x00, + STM32_TIM_CH_POLARITY_NEG = 0x01, - /* MODES: */ - STM32_TIM_CH_MODE_MASK = 0x06, + /* MODES: */ + + STM32_TIM_CH_MODE_MASK = 0x06, - /* Output Compare Modes */ - STM32_TIM_CH_OUTPWM = 0x04, /** Enable standard PWM mode, active high when counter < compare */ -// STM32_TIM_CH_OUTCOMPARE = 0x06, + /* Output Compare Modes */ + + STM32_TIM_CH_OUTPWM = 0x04, /** Enable standard PWM mode, active high when counter < compare */ +//STM32_TIM_CH_OUTCOMPARE = 0x06, - // TODO other modes ... as PWM capture, ENCODER and Hall Sensor -// STM32_TIM_CH_INCAPTURE = 0x10, -// STM32_TIM_CH_INPWM = 0x20 -// STM32_TIM_CH_DRIVE_OC -- open collector mode + // TODO other modes ... as PWM capture, ENCODER and Hall Sensor +//STM32_TIM_CH_INCAPTURE = 0x10, +//STM32_TIM_CH_INPWM = 0x20 +//STM32_TIM_CH_DRIVE_OC -- open collector mode } stm32_tim_channel_t; +/* TIM Operations */ -/** TIM Operations - */ -struct stm32_tim_ops_s { +struct stm32_tim_ops_s +{ + /* Basic Timers */ - /* Basic Timers */ - - int (*setmode)(FAR struct stm32_tim_dev_s *dev, stm32_tim_mode_t mode); - int (*setclock)(FAR struct stm32_tim_dev_s *dev, uint32_t freq); - void (*setperiod)(FAR struct stm32_tim_dev_s *dev, uint16_t period); + int (*setmode)(FAR struct stm32_tim_dev_s *dev, stm32_tim_mode_t mode); + int (*setclock)(FAR struct stm32_tim_dev_s *dev, uint32_t freq); + void (*setperiod)(FAR struct stm32_tim_dev_s *dev, uint16_t period); - /* General and Advanced Timers Adds */ + /* General and Advanced Timers Adds */ - int (*setchannel)(FAR struct stm32_tim_dev_s *dev, uint8_t channel, stm32_tim_channel_t mode); - int (*setcompare)(FAR struct stm32_tim_dev_s *dev, uint8_t channel, uint16_t compare); - int (*getcapture)(FAR struct stm32_tim_dev_s *dev, uint8_t channel); - - int (*setisr)(FAR struct stm32_tim_dev_s *dev, int (*handler)(int irq, void *context), int source); - void (*enableint)(FAR struct stm32_tim_dev_s *dev, int source); - void (*disableint)(FAR struct stm32_tim_dev_s *dev, int source); - void (*ackint)(FAR struct stm32_tim_dev_s *dev, int source); + int (*setchannel)(FAR struct stm32_tim_dev_s *dev, uint8_t channel, stm32_tim_channel_t mode); + int (*setcompare)(FAR struct stm32_tim_dev_s *dev, uint8_t channel, uint16_t compare); + int (*getcapture)(FAR struct stm32_tim_dev_s *dev, uint8_t channel); + + int (*setisr)(FAR struct stm32_tim_dev_s *dev, int (*handler)(int irq, void *context), int source); + void (*enableint)(FAR struct stm32_tim_dev_s *dev, int source); + void (*disableint)(FAR struct stm32_tim_dev_s *dev, int source); + void (*ackint)(FAR struct stm32_tim_dev_s *dev, int source); }; - -/* Helpers */ - -#define STM32_TIM_SETMODE(d,mode) ((d)->ops->setmode(d,mode)) -#define STM32_TIM_SETCLOCK(d,freq) ((d)->ops->setclock(d,freq)) -#define STM32_TIM_SETPERIOD(d,period) ((d)->ops->setperiod(d,period)) -#define STM32_TIM_SETCHANNEL(d,ch,mode) ((d)->ops->setchannel(d,ch,mode)) -#define STM32_TIM_SETCOMPARE(d,ch,comp) ((d)->ops->setcompare(d,ch,comp)) -#define STM32_TIM_GETCAPTURE(d,ch) ((d)->ops->getcapture(d,ch)) -#define STM32_TIM_SETISR(d,hnd,s) ((d)->ops->setisr(d,hnd,s)) -#define STM32_TIM_ENABLEINT(d,s) ((d)->ops->enableint(d,s)) -#define STM32_TIM_DISABLEINT(d,s) ((d)->ops->disableint(d,s)) -#define STM32_TIM_ACKINT(d,s) ((d)->ops->ackint(d,s)) - - /************************************************************************************ * Public Functions ************************************************************************************/ -/** Power-up timer and get its structure */ +/* Power-up timer and get its structure */ + EXTERN FAR struct stm32_tim_dev_s * stm32_tim_init(int timer); -/** Power-down timer, mark it as unused */ -EXTERN int stm32_tim_deinit(FAR struct stm32_tim_dev_s * dev); +/* Power-down timer, mark it as unused */ +EXTERN int stm32_tim_deinit(FAR struct stm32_tim_dev_s * dev); #undef EXTERN #if defined(__cplusplus) diff --git a/configs/stm3210e-eval/README.txt b/configs/stm3210e-eval/README.txt index 25496db2db1feacd7de2f5ff81771210b159fc79..eb7c49b95cfc67b67300cf82df61ab4e2a4850ad 100755 --- a/configs/stm3210e-eval/README.txt +++ b/configs/stm3210e-eval/README.txt @@ -481,7 +481,40 @@ STM3210E-EVAL-specific Configuration Options CONFIG_STM32_FORCEPOWER - Alternate pin mappings (should not be used with the STM3210E-EVAL board): + 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 + the timer is intended to be used for pulsed output modulation, ADC conversion, + or DAC conversion. + + CONFIG_STM32_TIM1_PWM + CONFIG_STM32_TIM2_PWM + CONFIG_STM32_TIM3_PWM + CONFIG_STM32_TIM4_PWM + CONFIG_STM32_TIM5_PWM + CONFIG_STM32_TIM6_PWM + CONFIG_STM32_TIM7_PWM + CONFIG_STM32_TIM8_PWM + + CONFIG_STM32_TIM1_ADC + CONFIG_STM32_TIM2_ADC + CONFIG_STM32_TIM3_ADC + CONFIG_STM32_TIM4_ADC + CONFIG_STM32_TIM5_ADC + CONFIG_STM32_TIM6_ADC + CONFIG_STM32_TIM7_ADC + CONFIG_STM32_TIM8_ADC + + CONFIG_STM32_TIM1_DAC + CONFIG_STM32_TIM2_DAC + CONFIG_STM32_TIM3_DAC + CONFIG_STM32_TIM4_DAC + CONFIG_STM32_TIM5_DAC + CONFIG_STM32_TIM6_DAC + CONFIG_STM32_TIM7_DAC + CONFIG_STM32_TIM8_DAC + + Alternate pin mappings (should not be used with the STM3210E-EVAL board): CONFIG_STM32_TIM1_FULL_REMAP CONFIG_STM32_TIM1_PARTIAL_REMAP diff --git a/configs/stm3240g-eval/README.txt b/configs/stm3240g-eval/README.txt index 78b384c3149c002c9f9ee318127b562b32366198..257cb95e0d8c5ef0d69f9c93f8d868355957e2ad 100755 --- a/configs/stm3240g-eval/README.txt +++ b/configs/stm3240g-eval/README.txt @@ -360,7 +360,47 @@ STM3240G-EVAL-specific Configuration Options 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 + the timer is intended to be used for pulsed output modulation, ADC conversion, + or DAC conversion. + + CONFIG_STM32_TIM1_PWM + CONFIG_STM32_TIM2_PWM + CONFIG_STM32_TIM3_PWM + CONFIG_STM32_TIM4_PWM + CONFIG_STM32_TIM5_PWM + CONFIG_STM32_TIM6_PWM + CONFIG_STM32_TIM7_PWM + CONFIG_STM32_TIM8_PWM + CONFIG_STM32_TIM9_PWM + CONFIG_STM32_TIM10_PWM + CONFIG_STM32_TIM11_PWM + CONFIG_STM32_TIM12_PWM + CONFIG_STM32_TIM13_PWM + CONFIG_STM32_TIM14_PWM + + CONFIG_STM32_TIM1_ADC + CONFIG_STM32_TIM2_ADC + CONFIG_STM32_TIM3_ADC + CONFIG_STM32_TIM4_ADC + CONFIG_STM32_TIM5_ADC + CONFIG_STM32_TIM6_ADC + CONFIG_STM32_TIM7_ADC + CONFIG_STM32_TIM8_ADC + + CONFIG_STM32_TIM1_DAC + CONFIG_STM32_TIM2_DAC + CONFIG_STM32_TIM3_DAC + CONFIG_STM32_TIM4_DAC + CONFIG_STM32_TIM5_DAC + CONFIG_STM32_TIM6_DAC + CONFIG_STM32_TIM7_DAC + CONFIG_STM32_TIM8_DAC + JTAG Enable settings (by default JTAG-DP and SW-DP are disabled): + CONFIG_STM32_JTAG_FULL_ENABLE - Enables full SWJ (JTAG-DP + SW-DP) CONFIG_STM32_JTAG_NOJNTRST_ENABLE - Enables full SWJ (JTAG-DP + SW-DP) but without JNTRST. diff --git a/include/nuttx/pwm.h b/include/nuttx/pwm.h new file mode 100644 index 0000000000000000000000000000000000000000..2e954d2fc862273959f272b2755315ed3267ebcf --- /dev/null +++ b/include/nuttx/pwm.h @@ -0,0 +1,253 @@ +/**************************************************************************** + * include/nuttx/pwm.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <gnutt@nuttx.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_PWM_H +#define __INCLUDE_NUTTX_PWM_H + +/* For the purposes of this driver, a PWM device is any devices and generates + * periodic outputs of controlled frequency and pulse width. Such is device + * might be use, for example, to perform pulse-width modulated output or + * frequency/pulse-count modulated output (such as might be needed to control + * a stepper motor. + * + * The PWM driver is split into two parts: + * + * 1) An "upper half", generic driver that provides the comman PWM interface + * to application level code, and + * 2) An "lower half" platform-specific driver that implements the low-level + * timer controls to implement the PWM functionality. + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> +#include <nuttx/compiler.h> + +#include <fixedmath.h> + +#include <nuttx/ioctl.h> + +#ifdef CONFIG_PWM + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ +/* The PWM module uses a standard character driver framework. However, since + * the PWM driver is a devices control interface and not a data transfer + * interface, the majority of the functionality is implemented in driver + * ioctl calls. The PWM ioctal commands are lised below: + * + * PWMIOC_SETCHARACTERISTICS - Set the characteristics of the next pulsed + * output. This command will neither start nor stop the pulsed output. + * It will either setup the configuration that will be used when the + * output is started; or it will change the characteristics of the pulsed + * output on the fly if the timer is already started. + * + * ioctl argument: A read-only reference to struct pwm_info_s that provides + * the characteristics of the pulsed output. + * + * PWMIOC_GETCHARACTERISTICS - Get the currently selected characteristics of + * the pulsed output (independent of whether the output is start or stopped). + * + * ioctl argument: A reference to struct pwm_info_s to recevie the + * characteristics of the pulsed output. + * + * PWMIOC_START - Start the pulsed output. The PWMIOC_SETCHARACTERISTICS + * command must have previously been sent. + * + * ioctl argument: None + * + * PWMIOC_STOP - Stop the pulsed output. + * + * ioctl argument: None + * + * PWMIOC_GETPULSECOUNT - Return the number of pulses generated. + * + * ioctl argument: A pointer to a pwm_count_t variable that will be used to + * receive the pulse count + */ + +#define PWMIOC_SETCHARACTERISTICS _PWMIOC(1) +#define PWMIOC_GETCHARACTERISTICS _PWMIOC(2) +#define PWMIOC_START _PWMIOC(3) +#define PWMIOC_STOP _PWMIOC(4) +#define PWMIOC_GETPULSECOUNT _PWMIOC(5) + +/**************************************************************************** + * Public Types + ****************************************************************************/ +/* This structure describes the characteristics of the pulsed output */ + +struct pwm_info_s +{ + uint32_t frequency; /* Frequency of the pulse train */ + b16_t duty; /* Duty of the pulse train, "1" to "0" duration */ +}; + +/* This type is used to return pulse counts */ + +#ifdef CONFIG_HAVE_LONG_LONG +typedef uint16_t pwm_count_t; +#else +struct pwm_count_s +{ + uint32_t ms; /* Most significant 32-bits of the 64-count */ + uint32_t ls; /* Least significant 32-bits of the 64-count */ +}; +typedef struct pwm_count_s pwm_count_t; +#endif + +/* This structure is a set a callback functions used to call from the upper- + * half, generic PWM driver into lower-half, platform-specific logic that + * supports the low-level timer outputs. + */ + +struct pwm_lowerhalf_s; +struct pwm_ops_s +{ + /* This method is called when the driver is opened. The lower half driver + * should configure and initialize the device so that it is ready for use. + * It should not, however, output pulses until the start method is called. + */ + + CODE int (*setup)(FAR struct pwm_lowerhalf_s *dev); + + /* This method is called when the driver is closed. The lower half driver + * stop pulsed output, free any resources, disable the timer hardware, and + * put the system into the lowest possible power usage state + */ + + CODE int (*shutdown)(FAR struct pwm_lowerhalf_s *dev); + + /* (Re-)initialize the timer resources and start the pulsed output */ + + CODE int (*start)(FAR struct pwm_lowerhalf_s *dev, FAR const struct pwm_info_s *info); + + /* Stop the pulsed output and reset the timer resources*/ + + CODE int (*stop)(FAR struct pwm_lowerhalf_s *dev); + + /* Get the number of pulses generated */ + + CODE int (*pulsecount)(FAR struct pwm_lowerhalf_s *dev, FAR pwm_count_t *count); + + /* Lower-half logic may support platform-specific ioctl commands */ + + CODE int (*ioctl)(FAR struct pwm_lowerhalf_s *dev, int cmd, unsigned long arg); +}; + +/* This structure is the generic form of state structure used by lower half + * timer driver. This state structure is passed to the pwm driver when the + * driver is initialized. Then, on subsequent callbacks into the lower half + * timer logic, this structure is provided so that the timer logic can + * maintain state information. + * + * Normally that timer logic will have its own, custom state structure + * that is simply cast to struct pwm_lowerhalf_s. In order to perform such casts, + * the initial fields of the custom state structure match the initial fields + * of the following generic PWM state structure. + */ + +struct pwm_lowerhalf_s +{ + /* The first field of this state structure must be a pointer to the PWM + * callback structure: + */ + + FAR const struct pwm_ops_s *ops; + + /* The custom timer state structure may include additional fields after + * the pointer to the PWM callback structgure. + */ +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * "Upper-Half" ADC Driver Interfaces + ****************************************************************************/ +/**************************************************************************** + * Name: pwm_register + * + * Description: + * This function binds an instance of a "lower half" timer driver with the + * "upper half" PWM device and registers that device so that can be used + * by application code. + * + * When this function is called, the "lower half" driver should be in the + * reset state (as if the shutdown() method had already been called). + * + * Input parameters: + * path - The full path to the driver to be registers in the NuttX pseudo- + * filesystem. The recommended convention is to name all PWM drivers + * as "/dev/pwm0", "/dev/pwm1", etc. where the driver path differs only + * in the "minor" number at the end of the device name. + * dev - A pointer to an instance of lower half timer driver. This instance + * is bound to the PWM driver and must persists as long as the driver + * persists. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +int pwm_register(FAR const char *path, FAR struct pwm_lowerhalf_s *dev); + +/**************************************************************************** + * Platform-Independent "Lower-Half" ADC Driver Interfaces + ****************************************************************************/ + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_PWM */ +#endif /* __INCLUDE_NUTTX_PWM_H */