diff --git a/arch/arm/src/stm32/Kconfig b/arch/arm/src/stm32/Kconfig index 6b9aabc0e1c..4c4dd327c0c 100644 --- a/arch/arm/src/stm32/Kconfig +++ b/arch/arm/src/stm32/Kconfig @@ -5367,7 +5367,7 @@ if STM32_DAC1_DMA config STM32_DAC1_TIMER int "DAC1 timer" - range 2 7 + range 2 8 config STM32_DAC1_TIMER_FREQUENCY int "DAC1 timer frequency" @@ -5390,7 +5390,7 @@ if STM32_DAC2_DMA config STM32_DAC2_TIMER int "DAC2 timer" default 0 - range 2 7 + range 2 8 config STM32_DAC2_TIMER_FREQUENCY int "DAC2 timer frequency" diff --git a/arch/arm/src/stm32/chip/stm32_tim.h b/arch/arm/src/stm32/chip/stm32_tim.h index db4608f89b3..56c748a98f4 100644 --- a/arch/arm/src/stm32/chip/stm32_tim.h +++ b/arch/arm/src/stm32/chip/stm32_tim.h @@ -479,12 +479,10 @@ #define ATIM_CR2_CCDS (1 << 3) /* Bit 3: Capture/Compare DMA Selection */ #define ATIM_CR2_MMS_SHIFT (4) /* Bits 6-4: Master Mode Selection */ #define ATIM_CR2_MMS_MASK (7 << ATIM_CR2_MMS_SHIFT) -#ifdef CONFIG_STM32_STM32F30XX -# define ATIM_CR2_MMS_RESET (0 << ATIM_CR2_MMS_SHIFT) /* 000: Reset - TIMx_EGR UG bit is TRG9 */ +# define ATIM_CR2_MMS_RESET (0 << ATIM_CR2_MMS_SHIFT) /* 000: Reset - TIMx_EGR UG bit is TRGO */ # define ATIM_CR2_MMS_ENABLE (1 << ATIM_CR2_MMS_SHIFT) /* 001: Enable - CNT_EN is TRGO */ -# define ATIM_CR2_MMS_UPDATE (2 << ATIM_CR2_MMS_SHIFT) /* 010: Update event is TRGH0*/ +# define ATIM_CR2_MMS_UPDATE (2 << ATIM_CR2_MMS_SHIFT) /* 010: Update event is TRGO */ # define ATIM_CR2_MMS_COMPP (3 << ATIM_CR2_MMS_SHIFT) /* 010: Compare Pulse - CC1IF flag */ -#endif # define ATIM_CR2_MMS_OC1REF (4 << ATIM_CR2_MMS_SHIFT) /* 100: Compare OC1REF is TRGO */ # define ATIM_CR2_MMS_OC2REF (5 << ATIM_CR2_MMS_SHIFT) /* 101: Compare OC2REF is TRGO */ # define ATIM_CR2_MMS_OC3REF (6 << ATIM_CR2_MMS_SHIFT) /* 110: Compare OC3REF is TRGO */ @@ -966,14 +964,14 @@ #define GTIM_CR2_CCDS (1 << 3) /* Bit 3: Capture/Compare DMA Selection (TIM2-5,1,&16 only) */ #define GTIM_CR2_MMS_SHIFT (4) /* Bits 6-4: Master Mode Selection (not TIM16) */ #define GTIM_CR2_MMS_MASK (7 << GTIM_CR2_MMS_SHIFT) -# define GTIM_CR2_RESET (0 << GTIM_CR2_MMS_SHIFT) /* 000: Reset */ -# define GTIM_CR2_ENAB (1 << GTIM_CR2_MMS_SHIFT) /* 001: Enable */ -# define GTIM_CR2_UPDT (2 << GTIM_CR2_MMS_SHIFT) /* 010: Update */ -# define GTIM_CR2_CMPP (3 << GTIM_CR2_MMS_SHIFT) /* 011: Compare Pulse */ -# define GTIM_CR2_CMP1 (4 << GTIM_CR2_MMS_SHIFT) /* 100: Compare - OC1REF signal is used as trigger output (TRGO) */ -# define GTIM_CR2_CMP2 (5 << GTIM_CR2_MMS_SHIFT) /* 101: Compare - OC2REF signal is used as trigger output (TRGO) */ -# define GTIM_CR2_CMP3 (6 << GTIM_CR2_MMS_SHIFT) /* 110: Compare - OC3REF signal is used as trigger output (TRGO, TIM2-5 and TIM15 only) */ -# define GTIM_CR2_CMP4 (7 << GTIM_CR2_MMS_SHIFT) /* 111: Compare - OC4REF signal is used as trigger output (TRGO, TIM2-5 and TIM15 only) */ +# define GTIM_CR2_MMS_RESET (0 << GTIM_CR2_MMS_SHIFT) /* 000: Reset */ +# define GTIM_CR2_MMS_ENABLE (1 << GTIM_CR2_MMS_SHIFT) /* 001: Enable */ +# define GTIM_CR2_MMS_UPDATE (2 << GTIM_CR2_MMS_SHIFT) /* 010: Update */ +# define GTIM_CR2_MMS_COMPP (3 << GTIM_CR2_MMS_SHIFT) /* 011: Compare Pulse */ +# define GTIM_CR2_MMS_OC1REF (4 << GTIM_CR2_MMS_SHIFT) /* 100: Compare - OC1REF signal is used as trigger output (TRGO) */ +# define GTIM_CR2_MMS_OC2REF (5 << GTIM_CR2_MMS_SHIFT) /* 101: Compare - OC2REF signal is used as trigger output (TRGO) */ +# define GTIM_CR2_MMS_OC3REF (6 << GTIM_CR2_MMS_SHIFT) /* 110: Compare - OC3REF signal is used as trigger output (TRGO, TIM2-5 and TIM15 only) */ +# define GTIM_CR2_MMS_OC4REF (7 << GTIM_CR2_MMS_SHIFT) /* 111: Compare - OC4REF signal is used as trigger output (TRGO, TIM2-5 and TIM15 only) */ #define GTIM_CR2_TI1S (1 << 7) /* Bit 7: TI1 Selection (not TIM16) */ #define GTIM_CR2_OIS1 (1 << 8) /* Bit 8: COutput Idle state 1 (OC1 output) (TIM15-17 only) */ #define GTIM_CR2_OIS1N (1 << 9) /* Bit 9: Output Idle state 1 (OC1N output) (TIM15-17 only) */ diff --git a/arch/arm/src/stm32/stm32_dac.c b/arch/arm/src/stm32/stm32_dac.c index fce79ce301a..b6fb31bdcd0 100644 --- a/arch/arm/src/stm32/stm32_dac.c +++ b/arch/arm/src/stm32/stm32_dac.c @@ -311,6 +311,22 @@ #warning "Missing Logic" +/* DMA stream/channel configuration */ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define DAC_DMA_CONTROL_WORD (DMA_SCR_MSIZE_16BITS | \ + DMA_SCR_PSIZE_16BITS | \ + DMA_SCR_MINC | \ + DMA_SCR_CIRC | \ + DMA_SCR_DIR_M2P) +#else +# define DAC_DMA_CONTROL_WORD (DMA_CCR_MSIZE_16BITS | \ + DMA_CCR_PSIZE_16BITS | \ + DMA_CCR_MINC | \ + DMA_CCR_CIRC | \ + DMA_CCR_DIR) +#endif + /**************************************************************************** * Private Types ****************************************************************************/ @@ -349,14 +365,15 @@ struct stm32_chan_s /* DAC Register access */ #ifdef HAVE_DMA -static uint32_t tim_getreg(struct stm32_chan_s *chan, int offset); -static void tim_putreg(struct stm32_chan_s *chan, int offset, uint32_t value); +static uint32_t tim_getreg(FAR struct stm32_chan_s *chan, int offset); +static void tim_putreg(FAR struct stm32_chan_s *chan, int offset, + uint32_t value); #endif /* Interrupt handler */ #if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) -static int dac_interrupt(int irq, void *context); +static int dac_interrupt(int irq, FAR void *context); #endif /* DAC methods */ @@ -371,9 +388,9 @@ static int dac_ioctl(FAR struct dac_dev_s *dev, int cmd, unsigned long arg); /* Initialization */ #ifdef HAVE_DMA -static int dac_timinit(struct stm32_chan_s *chan); +static int dac_timinit(FAR struct stm32_chan_s *chan); #endif -static int dac_chaninit(struct stm32_chan_s *chan); +static int dac_chaninit(FAR struct stm32_chan_s *chan); static int dac_blockinit(void); /**************************************************************************** @@ -422,7 +439,7 @@ static struct stm32_chan_s g_dac2priv = .dmachan = DAC2_DMA_CHAN, .timer = CONFIG_STM32_DAC2_TIMER, .tsel = DAC2_TSEL_VALUE, - .tbase = DAC2_TIMER_BASE + .tbase = DAC2_TIMER_BASE, .tfrequency = CONFIG_STM32_DAC2_TIMER_FREQUENCY, #endif }; @@ -456,12 +473,13 @@ static struct stm32_dac_s g_dacblock; * ****************************************************************************/ -static inline void stm32_dac_modify_cr(FAR struct stm32_chan_s *priv, +static inline void stm32_dac_modify_cr(FAR struct stm32_chan_s *chan, uint32_t clearbits, uint32_t setbits) { - uint32_t cr = getreg32(STM32_DAC_CR); - modifyreg32(STM32_DAC_CR, clearbits << (priv->intf*16), setbits << (priv->intf*16)); - uint32_t cr1 = getreg32(STM32_DAC_CR); + uint32_t shift; + + shift = chan->intf * 16; + modifyreg32(STM32_DAC_CR, clearbits << shift, setbits << shift); } /**************************************************************************** @@ -480,7 +498,7 @@ static inline void stm32_dac_modify_cr(FAR struct stm32_chan_s *priv, ****************************************************************************/ #ifdef HAVE_DMA -static uint32_t tim_getreg(struct stm32_chan_s *chan, int offset) +static uint32_t tim_getreg(FAR struct stm32_chan_s *chan, int offset) { return getreg32(chan->tbase + offset); } @@ -502,7 +520,8 @@ static uint32_t tim_getreg(struct stm32_chan_s *chan, int offset) ****************************************************************************/ #ifdef HAVE_DMA -static void tim_putreg(struct stm32_chan_s *chan, int offset, uint32_t value) +static void tim_putreg(FAR struct stm32_chan_s *chan, int offset, + uint32_t value) { putreg32(value, chan->tbase + offset); } @@ -517,8 +536,8 @@ static void tim_putreg(struct stm32_chan_s *chan, int offset, uint32_t value) * Input Parameters: * priv - Driver state instance * offset - The timer register offset - * clear_bits - Bits in the control register to be cleared - * set_bits - Bits in the control register to be set + * clearbits - Bits in the control register to be cleared + * setbits - Bits in the control register to be set * * Returned Value: * None @@ -526,10 +545,10 @@ static void tim_putreg(struct stm32_chan_s *chan, int offset, uint32_t value) ****************************************************************************/ #ifdef HAVE_DMA -static void tim_modifyreg(struct stm32_chan_s *chan, int offset, - uint32_t clear_bits, uint32_t set_bits) +static void tim_modifyreg(FAR struct stm32_chan_s *chan, int offset, + uint32_t clearbits, uint32_t setbits) { - modifyreg32(chan->tbase + offset, clear_bits, set_bits); + modifyreg32(chan->tbase + offset, clearbits, setbits); } #endif @@ -548,7 +567,7 @@ static void tim_modifyreg(struct stm32_chan_s *chan, int offset, ****************************************************************************/ #if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) -static int dac_interrupt(int irq, void *context) +static int dac_interrupt(int irq, FAR void *context) { #warning "Missing logic" return OK; @@ -574,7 +593,6 @@ static int dac_interrupt(int irq, void *context) static void dac_reset(FAR struct dac_dev_s *dev) { irqstate_t flags; - uint32_t regval; /* Reset only the selected DAC channel; the other DAC channel must remain * functional. @@ -605,8 +623,8 @@ static void dac_reset(FAR struct dac_dev_s *dev) static int dac_setup(FAR struct dac_dev_s *dev) { -# warning "Missing logic" - return -ENOSYS; +#warning "Missing logic" + return OK; } /**************************************************************************** @@ -625,7 +643,7 @@ static int dac_setup(FAR struct dac_dev_s *dev) static void dac_shutdown(FAR struct dac_dev_s *dev) { -# warning "Missing logic" +#warning "Missing logic" } /**************************************************************************** @@ -643,7 +661,7 @@ static void dac_shutdown(FAR struct dac_dev_s *dev) static void dac_txint(FAR struct dac_dev_s *dev, bool enable) { -# warning "Missing logic" +#warning "Missing logic" } /**************************************************************************** @@ -659,7 +677,7 @@ static void dac_txint(FAR struct dac_dev_s *dev, bool enable) * ****************************************************************************/ -static void dac_dmatxcallback(DMA_HANDLE handle, uint8_t isr, void *arg) +static void dac_dmatxcallback(DMA_HANDLE handle, uint8_t isr, FAR void *arg) { } @@ -678,7 +696,7 @@ static void dac_dmatxcallback(DMA_HANDLE handle, uint8_t isr, void *arg) static int dac_send(FAR struct dac_dev_s *dev, FAR struct dac_msg_s *msg) { - struct stm32_chan_s * chan = dev->ad_priv; + FAR struct stm32_chan_s *chan = dev->ad_priv; /* Enable DAC Channel */ @@ -703,15 +721,8 @@ static int dac_send(FAR struct dac_dev_s *dev, FAR struct dac_msg_s *msg) * - Peripheral Burst: single */ - uint32_t ccr = - DMA_CCR_MSIZE_16BITS | /* Memory size */ - DMA_CCR_PSIZE_16BITS | /* Peripheral size */ - DMA_CCR_MINC | /* Memory increment mode */ - DMA_CCR_CIRC | /* Circular buffer */ - DMA_CCR_DIR; /* Read from memory */ - stm32_dmasetup(chan->dma, chan->dro, (uint32_t)chan->dmabuffer, - CONFIG_STM32_DAC_DMA_BUFFER_SIZE, ccr); + CONFIG_STM32_DAC_DMA_BUFFER_SIZE, DAC_DMA_CONTROL_WORD); /* Enable DMA */ @@ -760,7 +771,7 @@ static int dac_send(FAR struct dac_dev_s *dev, FAR struct dac_msg_s *msg) * ****************************************************************************/ -static int dac_ioctl(FAR struct dac_dev_s *dev, int cmd, unsigned long arg) +static int dac_ioctl(FAR struct dac_dev_s *dev, int cmd, unsigned long arg) { return -ENOTTY; } @@ -781,10 +792,12 @@ static int dac_ioctl(FAR struct dac_dev_s *dev, int cmd, unsigned long arg) ****************************************************************************/ #ifdef HAVE_DMA -static int dac_timinit(struct stm32_chan_s *chan) +static int dac_timinit(FAR struct stm32_chan_s *chan) { + uint32_t pclk; uint32_t prescaler; - uint32_t numerator; + uint32_t timclk; + uint32_t reload; uint32_t regaddr; uint32_t setbits; @@ -796,46 +809,46 @@ static int dac_timinit(struct stm32_chan_s *chan) * default) will be enabled */ - numerator = 2 * STM32_TIM27_FREQUENCY; - regaddr = STM32_RCC_APB1ENR; + pclk = STM32_TIM27_FREQUENCY; + regaddr = STM32_RCC_APB1ENR; switch (chan->timer) { #ifdef NEED_TIM2 case 2: - setbits = RCC_APB1ENR_TIM2EN; + setbits = RCC_APB1ENR_TIM2EN; break; #endif #ifdef NEED_TIM3 case 3: - setbits = RCC_APB1ENR_TIM3EN; + setbits = RCC_APB1ENR_TIM3EN; break; #endif #ifdef NEED_TIM4 case 4: - setbits = RCC_APB1ENR_TIM4EN; + setbits = RCC_APB1ENR_TIM4EN; break; #endif #ifdef NEED_TIM5 case 5: - setbits = RCC_APB1ENR_TIM5EN; + setbits = RCC_APB1ENR_TIM5EN; break; #endif #ifdef NEED_TIM6 case 6: - setbits = RCC_APB1ENR_TIM6EN; - break; -#endif -#ifdef NEED_TIM8 - case 8: - regaddr = STM32_RCC_APB2ENR; - setbits = RCC_APB2ENR_TIM8EN; - numerator = 2 * STM32_TIM18_FREQUENCY + setbits = RCC_APB1ENR_TIM6EN; break; #endif #ifdef NEED_TIM7 case 7: - setbits = RCC_APB1ENR_TIM7EN; + setbits = RCC_APB1ENR_TIM7EN; + break; +#endif +#ifdef NEED_TIM8 + case 8: + regaddr = STM32_RCC_APB2ENR; + setbits = RCC_APB2ENR_TIM8EN; + pclk = STM32_TIM18_FREQUENCY; break; #endif default: @@ -847,31 +860,65 @@ static int dac_timinit(struct stm32_chan_s *chan) modifyreg32(regaddr, 0, setbits); - /* Calculate the pre-scaler value */ - - prescaler = numerator / chan->tfrequency; - - /* We need to decrement value for '1', but only, if we are allowed to - * not to cause underflow. Check for overflow. + /* Calculate optimal values for the timer prescaler and for the timer reload + * register. If 'frequency' is the desired frequency, then + * + * reload = timclk / frequency + * timclk = pclk / presc + * + * Or, + * + * reload = pclk / presc / frequency + * + * There are many solutions to this this, but the best solution will be the + * one that has the largest reload value and the smallest prescaler value. + * That is the solution that should give us the most accuracy in the timer + * control. Subject to: + * + * 0 <= presc <= 65536 + * 1 <= reload <= 65535 + * + * So presc = pclk / 65535 / frequency would be optimal. + * + * Example: + * + * pclk = 42 MHz + * frequency = 100 Hz + * + * prescaler = 42,000,000 / 65,535 / 100 + * = 6.4 (or 7 -- taking the ceiling always) + * timclk = 42,000,000 / 7 + * = 6,000,000 + * reload = 6,000,000 / 100 + * = 60,000 */ - if (prescaler > 0) + prescaler = (pclk / chan->tfrequency + 65534) / 65535; + if (prescaler < 1) { - prescaler--; + prescaler = 1; + } + else if (prescaler > 65536) + { + prescaler = 65536; } - if (prescaler > 0xffff) + timclk = pclk / prescaler; + + reload = timclk / chan->tfrequency; + if (reload < 1) { - prescaler = 0xffff; + reload = 1; + } + else if (reload > 65535) + { + reload = 65535; } - /* Set prescaler */ + /* Set the reload and prescaler values */ - tim_putreg(chan, STM32_BTIM_PSC_OFFSET, 0); - - /* Set period */ - - tim_putreg(chan, STM32_BTIM_ARR_OFFSET, prescaler); + tim_putreg(chan, STM32_BTIM_ARR_OFFSET, (uint16_t)reload); + tim_putreg(chan, STM32_BTIM_PSC_OFFSET, (uint16_t)(prescaler - 1)); /* Count mode up, auto reload */ @@ -908,9 +955,11 @@ static int dac_timinit(struct stm32_chan_s *chan) * ****************************************************************************/ -static int dac_chaninit(struct stm32_chan_s *chan) +static int dac_chaninit(FAR struct stm32_chan_s *chan) { int ret; + uint16_t clearbits; + uint16_t setbits; /* Is the selected channel already in-use? */ @@ -942,14 +991,16 @@ static int dac_chaninit(struct stm32_chan_s *chan) stm32_dac_modify_cr(chan, DAC_CR_EN, 0); - uint16_t clear = - DAC_CR_TSEL_MASK | DAC_CR_MAMP_MASK | DAC_CR_WAVE_MASK | DAC_CR_BOFF; - uint16_t set = + clearbits = DAC_CR_TSEL_MASK | + DAC_CR_MAMP_MASK | + DAC_CR_WAVE_MASK | + DAC_CR_BOFF; + setbits = chan->tsel | /* Set trigger source (SW or timer TRGO event) */ DAC_CR_MAMP_AMP1 | /* Set waveform characteristics */ DAC_CR_WAVE_DISABLED | /* Set no noise */ DAC_CR_BOFF; /* Enable output buffer */ - stm32_dac_modify_cr(chan, clear, set); + stm32_dac_modify_cr(chan, clearbits, setbits); #ifdef HAVE_DMA /* Determine if DMA is supported by this channel */ @@ -977,7 +1028,6 @@ static int dac_chaninit(struct stm32_chan_s *chan) adbg("Failed to initialize the DMA timer: %d\n", ret); return ret; } - } #endif @@ -1089,7 +1139,7 @@ FAR struct dac_dev_s *stm32_dacinitialize(int intf) if (ret < 0) { adbg("Failed to initialize the DAC block: %d\n", ret); - errno = ret; + errno = -ret; return NULL; } @@ -1100,7 +1150,7 @@ FAR struct dac_dev_s *stm32_dacinitialize(int intf) if (ret < 0) { adbg("Failed to initialize DAC channel %d: %d\n", intf, ret); - errno = ret; + errno = -ret; return NULL; } diff --git a/arch/arm/src/stm32/stm32_dma2d.c b/arch/arm/src/stm32/stm32_dma2d.c index 0f9c01d0054..442b88c3ffc 100644 --- a/arch/arm/src/stm32/stm32_dma2d.c +++ b/arch/arm/src/stm32/stm32_dma2d.c @@ -1997,7 +1997,7 @@ FAR struct dma2d_layer_s *up_dma2dcreatelayer(fb_coord_t width, if (ret != OK) { - errno = ret; + errno = -ret; return NULL; } diff --git a/arch/arm/src/stm32/stm32_pwm.c b/arch/arm/src/stm32/stm32_pwm.c index 72be1bd6afe..8779d18692f 100644 --- a/arch/arm/src/stm32/stm32_pwm.c +++ b/arch/arm/src/stm32/stm32_pwm.c @@ -1090,7 +1090,7 @@ static int pwm_timer(FAR struct stm32_pwmtimer_s *priv, #endif /* Calculate optimal values for the timer prescaler and for the timer reload - * register. If' frequency' is the desired frequency, then + * register. If 'frequency' is the desired frequency, then * * reload = timclk / frequency * timclk = pclk / presc @@ -1118,7 +1118,7 @@ static int pwm_timer(FAR struct stm32_pwmtimer_s *priv, * = 6.4 (or 7 -- taking the ceiling always) * timclk = 42,000,000 / 7 * = 6,000,000 - * reload = 7,000,000 / 100 + * reload = 6,000,000 / 100 * = 60,000 */