From 258fa08e699d2e80cf510230b17c5e431cc45f46 Mon Sep 17 00:00:00 2001 From: Juha Niskanen Date: Fri, 1 Sep 2017 09:03:11 +0300 Subject: [PATCH] STM32L4 DAC: Fix naming so that DAC1 and DAC2 always refer to channels 1 and 2 User should not be bothered by details like how many IP blocks there are. As no current STM32L4 has second DAC block (channel 3), remove support for such hypothetical hardware. DMA channels corrected. Change-Id: I2cba7e55803871f1ff945538113f12cf5088f68d Signed-off-by: Juha Niskanen --- arch/arm/src/stm32l4/Kconfig | 7 +- arch/arm/src/stm32l4/chip/stm32l4x3xx_dma.h | 6 +- arch/arm/src/stm32l4/chip/stm32l4x5xx_dma.h | 2 +- arch/arm/src/stm32l4/chip/stm32l4x6xx_dma.h | 6 +- arch/arm/src/stm32l4/stm32l4_dac.c | 207 +++++++------------- arch/arm/src/stm32l4/stm32l4_dac.h | 11 ++ 6 files changed, 96 insertions(+), 143 deletions(-) diff --git a/arch/arm/src/stm32l4/Kconfig b/arch/arm/src/stm32l4/Kconfig index 09a1afd6bf3..a323f7d0bec 100644 --- a/arch/arm/src/stm32l4/Kconfig +++ b/arch/arm/src/stm32l4/Kconfig @@ -420,6 +420,7 @@ config STM32L4_STM32L431XX bool default n select STM32L4_STM32L4X1 + select STM32L4_HAVE_DAC2 select STM32L4_HAVE_TIM7 select STM32L4_HAVE_SDMMC1 if (STM32L4_IO_CONFIG_V || STM32L4_IO_CONFIG_R) @@ -427,18 +428,21 @@ config STM32L4_STM32L432XX bool default n select STM32L4_STM32L4X2 + select STM32L4_HAVE_DAC2 select STM32L4_HAVE_TIM7 config STM32L4_STM32L433XX bool default n select STM32L4_STM32L4X3 + select STM32L4_HAVE_DAC2 select STM32L4_HAVE_TIM7 config STM32L4_STM32L442XX bool default n select STM32L4_STM32L4X2 + select STM32L4_HAVE_DAC2 select STM32L4_HAVE_TIM7 select STM32L4_HAVE_AES @@ -446,6 +450,7 @@ config STM32L4_STM32L443XX bool default n select STM32L4_STM32L4X3 + select STM32L4_HAVE_DAC2 select STM32L4_HAVE_TIM7 select STM32L4_HAVE_SDMMC1 select STM32L4_HAVE_AES @@ -3245,7 +3250,7 @@ config STM32L4_ADC3_DMA endmenu menu "DAC Configuration" - depends on STM32L4_DAC1 || STM32L4_DAC2 + depends on STM32L4_DAC config STM32L4_DAC1_DMA bool "DAC1 DMA" diff --git a/arch/arm/src/stm32l4/chip/stm32l4x3xx_dma.h b/arch/arm/src/stm32l4/chip/stm32l4x3xx_dma.h index e312e0f9e8a..8723fc1c0aa 100644 --- a/arch/arm/src/stm32l4/chip/stm32l4x3xx_dma.h +++ b/arch/arm/src/stm32l4/chip/stm32l4x3xx_dma.h @@ -332,8 +332,10 @@ /* DAC */ #define DMACHAN_DAC1_1 DMACHAN_SETTING(STM32L4_DMA1_CHAN3, 6) -#define DMACHAN_DAC1_2 DMACHAN_SETTING(STM32L4_DMA1_CHAN4, 5) -#define DMACHAN_DAC1_3 DMACHAN_SETTING(STM32L4_DMA2_CHAN4, 3) +#define DMACHAN_DAC1_2 DMACHAN_SETTING(STM32L4_DMA2_CHAN4, 3) + +#define DMACHAN_DAC2_1 DMACHAN_SETTING(STM32L4_DMA1_CHAN4, 5) +#define DMACHAN_DAC2_2 DMACHAN_SETTING(STM32L4_DMA2_CHAN5, 3) /* DCMI */ diff --git a/arch/arm/src/stm32l4/chip/stm32l4x5xx_dma.h b/arch/arm/src/stm32l4/chip/stm32l4x5xx_dma.h index 2b44d7f839c..2eceae8292e 100644 --- a/arch/arm/src/stm32l4/chip/stm32l4x5xx_dma.h +++ b/arch/arm/src/stm32l4/chip/stm32l4x5xx_dma.h @@ -331,7 +331,7 @@ /* DAC */ #define DMACHAN_DAC1_1 DMACHAN_SETTING(STM32L4_DMA1_CHAN3, 6) -#define DMACHAN_DAC1_3 DMACHAN_SETTING(STM32L4_DMA2_CHAN4, 3) +#define DMACHAN_DAC1_2 DMACHAN_SETTING(STM32L4_DMA2_CHAN4, 3) #define DMACHAN_DAC2_1 DMACHAN_SETTING(STM32L4_DMA1_CHAN4, 5) #define DMACHAN_DAC2_2 DMACHAN_SETTING(STM32L4_DMA2_CHAN5, 3) diff --git a/arch/arm/src/stm32l4/chip/stm32l4x6xx_dma.h b/arch/arm/src/stm32l4/chip/stm32l4x6xx_dma.h index 8ff0edfca21..cf90c3e18dc 100644 --- a/arch/arm/src/stm32l4/chip/stm32l4x6xx_dma.h +++ b/arch/arm/src/stm32l4/chip/stm32l4x6xx_dma.h @@ -338,10 +338,10 @@ /* DAC */ #define DMACHAN_DAC1_1 DMACHAN_SETTING(STM32L4_DMA1_CHAN3, 6) -#define DMACHAN_DAC1_2 DMACHAN_SETTING(STM32L4_DMA1_CHAN4, 5) -#define DMACHAN_DAC1_3 DMACHAN_SETTING(STM32L4_DMA2_CHAN4, 3) +#define DMACHAN_DAC1_2 DMACHAN_SETTING(STM32L4_DMA2_CHAN4, 3) -#define DMACHAN_DAC2 DMACHAN_SETTING(STM32L4_DMA2_CHAN5, 3) +#define DMACHAN_DAC2_1 DMACHAN_SETTING(STM32L4_DMA1_CHAN4, 5) +#define DMACHAN_DAC2_2 DMACHAN_SETTING(STM32L4_DMA2_CHAN5, 3) /* DCMI */ diff --git a/arch/arm/src/stm32l4/stm32l4_dac.c b/arch/arm/src/stm32l4/stm32l4_dac.c index 90b87e7949a..36cf044a6b0 100644 --- a/arch/arm/src/stm32l4/stm32l4_dac.c +++ b/arch/arm/src/stm32l4/stm32l4_dac.c @@ -67,7 +67,11 @@ * Pre-processor Definitions ****************************************************************************/ /* Configuration ************************************************************/ -/* Up to 2 DAC interfaces for up to 3 channels are supported */ +/* Up to 1 DAC interface for up to 2 channels are supported */ + +#if STM32L4_NDAC > 2 +# warning "Extra DAC channels. Only DAC1 and DAC2 are supported" +#endif #if STM32L4_NDAC < 2 # undef CONFIG_STM32L4_DAC2 @@ -87,14 +91,6 @@ /* DMA configuration. */ -#if defined(CONFIG_STM32L4_DAC1_DMA) || defined(CONFIG_STM32L4_DAC2_DMA) -# if !defined(CONFIG_STM32L4_DMA1) -# warning "STM32L4 DAC DMA support requires CONFIG_STM32L4_DMA1" -# undef CONFIG_STM32L4_DAC1_DMA -# undef CONFIG_STM32L4_DAC2_DMA -# endif -#endif - /* If DMA is selected, then a buffer, a timer and output frequency must * also be provided to support the DMA transfer. The DMA transfer could be * supported by an EXTI trigger, but this feature is not currently @@ -133,15 +129,28 @@ # endif #endif -/* DMA *********************************************************************/ +/* Select DMA channels, favor DMA1 if configured. */ #undef HAVE_DMA -#if defined(CONFIG_STM32L4_DAC1_DMA) || defined(CONFIG_STM32L4_DAC2_DMA) -# define HAVE_DMA 1 -# define DAC_DMA 1 -# define DAC1_DMA_CHAN DMACHAN_DAC1_1 -# define DAC2_DMA_CHAN DMACHAN_DAC1_2 +#ifdef CONFIG_STM32L4_DAC1_DMA +# if defined(CONFIG_STM32L4_DMA1) +# define DAC1_DMA_CHAN DMACHAN_DAC1_1 +# elif defined(CONFIG_STM32L4_DMA2) +# define DAC1_DMA_CHAN DMACHAN_DAC1_2 +# else +# error "No DMA channel for DAC1" +# endif #endif +#ifdef CONFIG_STM32L4_DAC2_DMA +# if defined(CONFIG_STM32L4_DMA1) +# define DAC2_DMA_CHAN DMACHAN_DAC2_1 +# elif defined(CONFIG_STM32L4_DMA2) +# define DAC2_DMA_CHAN DMACHAN_DAC2_2 +# else +# error "No DMA channel for DAC2" +# endif +#endif +#define HAVE_DMA /* Timer configuration. The STM32L4 supports 8 different trigger for DAC * output: @@ -351,7 +360,7 @@ static int dac_ioctl(FAR struct dac_dev_s *dev, int cmd, unsigned long arg); static int dac_timinit(FAR struct stm32_chan_s *chan); #endif static int dac_chaninit(FAR struct stm32_chan_s *chan); -static int dac_blockinit(void); +static void dac_blockinit(void); /**************************************************************************** * Private Data @@ -371,26 +380,20 @@ static const struct dac_ops_s g_dacops = /* Channel 1 */ #ifdef CONFIG_STM32L4_DAC1_DMA -static uint16_t dac1_dmabuffer[CONFIG_STM32L4_DAC1_DMA_BUFFER_SIZE]; +uint16_t stm32l4_dac1_dmabuffer[CONFIG_STM32L4_DAC1_DMA_BUFFER_SIZE]; #endif static struct stm32_chan_s g_dac1priv = { .intf = 0, -#if STM32L4_NDAC < 3 .pin = GPIO_DAC1_OUT, .dro = STM32L4_DAC_DHR12R1, .cr = STM32L4_DAC_CR, -#else - .pin = GPIO_DAC1_OUT1, - .dro = STM32L4_DAC1_DHR12R1, - .cr = STM32L4_DAC1_CR, -#endif #ifdef CONFIG_STM32L4_DAC1_DMA .hasdma = 1, .dmachan = DAC1_DMA_CHAN, .buffer_len = CONFIG_STM32L4_DAC1_DMA_BUFFER_SIZE, - .dmabuffer = dac1_dmabuffer, + .dmabuffer = stm32l4_dac1_dmabuffer, .timer = CONFIG_STM32L4_DAC1_TIMER, .tsel = DAC1_TSEL_VALUE, .tbase = DAC1_TIMER_BASE, @@ -404,32 +407,26 @@ static struct dac_dev_s g_dac1dev = .ad_priv = &g_dac1priv, }; -#if STM32L4_NDAC > 1 -/* Channel 2: Note that some STM32L4 chips don't have - * the DAC1 second output channel. - */ +#endif /* CONFIG_STM32L4_DAC1 */ + +#ifdef CONFIG_STM32L4_DAC2 +/* Channel 2 */ #ifdef CONFIG_STM32L4_DAC2_DMA -static uint16_t dac2_dmabuffer[CONFIG_STM32L4_DAC2_DMA_BUFFER_SIZE]; +uint16_t stm32l4_dac2_dmabuffer[CONFIG_STM32L4_DAC2_DMA_BUFFER_SIZE]; #endif static struct stm32_chan_s g_dac2priv = { .intf = 1, -#if STM32L4_NDAC < 3 .pin = GPIO_DAC2_OUT, .dro = STM32L4_DAC_DHR12R2, .cr = STM32L4_DAC_CR, -#else - .pin = GPIO_DAC1_OUT2, - .dro = STM32L4_DAC1_DHR12R2, - .cr = STM32L4_DAC1_CR, -#endif #ifdef CONFIG_STM32L4_DAC2_DMA .hasdma = 1, .dmachan = DAC2_DMA_CHAN, .buffer_len = CONFIG_STM32L4_DAC2_DMA_BUFFER_SIZE, - .dmabuffer = dac2_dmabuffer, + .dmabuffer = stm32l4_dac2_dmabuffer, .timer = CONFIG_STM32L4_DAC2_TIMER, .tsel = DAC2_TSEL_VALUE, .tbase = DAC2_TIMER_BASE, @@ -442,27 +439,8 @@ static struct dac_dev_s g_dac2dev = .ad_ops = &g_dacops, .ad_priv = &g_dac2priv, }; -#endif -#endif /* CONFIG_STM32L4_DAC1 */ - -#ifdef CONFIG_STM32L4_DAC2 -/* Channel 3: Does not actually exit in any current STM32L4 */ - -static struct stm32_chan_s g_dac3priv = -{ - .intf = 2, - .pin = GPIO_DAC2_OUT1, - .dro = STM32L4_DAC2_DHR12R1, - .cr = STM32L4_DAC2_CR, -}; - -static struct dac_dev_s g_dac3dev = -{ - .ad_ops = &g_dacops, - .ad_priv = &g_dac3priv, -}; -#endif +#endif /* CONFIG_STM32L4_DAC2 */ static struct stm32_dac_s g_dacblock; @@ -491,10 +469,10 @@ static inline void stm32l4_dac_modify_cr(FAR struct stm32_chan_s *chan, { unsigned int shift; - /* DAC1 channels 1 and 2 share the STM32L4_DAC[1]_CR control register. DAC2 - * channel 1 (and perhaps channel 2) uses the STM32L4_DAC2_CR control - * register. In either case, bit 0 of the interface number provides the - * correct shift. + /* DAC channels 1 and 2 share the STM32L4_DAC[1]_CR control register. If + * future chips have DAC channel 3 (and perhaps channel 4) they likely have + * their own register like in STM32. In either case, bit 0 of the interface + * number provides the correct shift. * * Bit 0 = 0: Shift = 0 * Bit 0 = 1: Shift = 16 @@ -525,7 +503,7 @@ static inline void stm32l4_dac_modify_mcr(FAR struct stm32_chan_s *chan, { unsigned int shift; - /* DAC1 channels 1 and 2 share the STM32L4_DAC_MCR control register. + /* DAC channels 1 and 2 share the STM32L4_DAC_MCR control register. * Bit 0 of the interface number provides the correct shift. * * Bit 0 = 0: Shift = 0 @@ -694,28 +672,21 @@ static void dac_dmatxcallback(DMA_HANDLE handle, uint8_t isr, FAR void *arg) DEBUGASSERT(chan); + switch (chan->intf) + { #ifdef CONFIG_STM32L4_DAC1 - if (chan->intf == 0) - { - dev = &g_dac1dev; - } -#if STM32L4_NDAC > 1 - else if (chan->intf == 1) - { - dev = &g_dac2dev; - } + case 0: + dev = &g_dac1dev; + break; #endif - else -#endif /* CONFIG_STM32L4_DAC1 */ #ifdef CONFIG_STM32L4_DAC2 - if (chan->intf == 2) - { - dev = &g_dac3dev; - } - else + case 1: + dev = &g_dac2dev; + break; #endif - { - DEBUGPANIC(); + default: + DEBUGPANIC(); + break; } DEBUGASSERT(dev->ad_priv == chan); @@ -762,9 +733,10 @@ static int dac_send(FAR struct dac_dev_s *dev, FAR struct dac_msg_s *msg) * writing e.g. monotonously increasing values creates a continuosly repeating * ramp-effect, alternating with periods of zero output. * - * In real use it would be better to initialize dmabuffer with desired pattern - * beforehand. If want to write just one value at a time with DMA, set - * the buffer size to 1. + * In real use it the dmabuffer should be initialized with a desired pattern + * beforehand, followed by a single dummy write to initiate circular DMA. If want + * to write just one value at a time with DMA, set the buffer size to 1 (mostly + * useful for just testing the functionality). */ chan->dmabuffer[chan->buffer_pos] = (uint16_t)msg->am_data; @@ -1131,11 +1103,10 @@ static int dac_chaninit(FAR struct stm32_chan_s *chan) * Input Parameters: * * Returned Value: - * Zero on success; a negated errno value on failure. * ****************************************************************************/ -static int dac_blockinit(void) +static void dac_blockinit(void) { irqstate_t flags; uint32_t regval; @@ -1144,46 +1115,25 @@ static int dac_blockinit(void) if (g_dacblock.init) { - /* Yes.. then return success We only have to do this once */ - - return OK; + return; } /* Put the entire DAC block in reset state */ flags = enter_critical_section(); regval = getreg32(STM32L4_RCC_APB1RSTR1); -#if STM32L4_NDAC < 2 regval |= RCC_APB1RSTR1_DAC1RST; -#else -#ifdef CONFIG_STM32L4_DAC1 - regval |= RCC_APB1RSTR1_DAC1RST; -#endif -#ifdef CONFIG_STM32L4_DAC2 - regval |= RCC_APB1RSTR1_DAC2RST; -#endif -#endif putreg32(regval, STM32L4_RCC_APB1RSTR1); /* Take the DAC out of reset state */ -#if STM32L4_NDAC < 2 regval &= ~RCC_APB1RSTR1_DAC1RST; -#else -#ifdef CONFIG_STM32L4_DAC1 - regval &= ~RCC_APB1RSTR1_DAC1RST; -#endif -#ifdef CONFIG_STM32L4_DAC2 - regval &= ~RCC_APB1RSTR1_DAC2RST; -#endif -#endif putreg32(regval, STM32L4_RCC_APB1RSTR1); leave_critical_section(flags); /* Mark the DAC block as initialized */ g_dacblock.init = 1; - return OK; } /**************************************************************************** @@ -1214,44 +1164,29 @@ FAR struct dac_dev_s *stm32l4_dacinitialize(int intf) FAR struct stm32_chan_s *chan; int ret; + switch (intf) + { #ifdef CONFIG_STM32L4_DAC1 - if (intf == 0) - { - ainfo("DAC1-1 Selected\n"); - dev = &g_dac1dev; - } -#if STM32L4_NDAC > 1 - else if (intf == 1) - { - ainfo("DAC1-2 Selected\n"); - dev = &g_dac2dev; - } + case 0: + ainfo("DAC1-1 Selected\n"); + dev = &g_dac1dev; + break; #endif - else -#endif /* CONFIG_STM32L4_DAC1 */ #ifdef CONFIG_STM32L4_DAC2 - if (intf == 2) - { - ainfo("DAC2-1 Selected\n"); - dev = &g_dac3dev; - } - else + case 1: + ainfo("DAC1-2 Selected\n"); + dev = &g_dac2dev; + break; #endif - { - aerr("ERROR: No such DAC interface: %d\n", intf); - errno = ENODEV; - return NULL; + default: + aerr("ERROR: No such DAC interface: %d\n", intf); + errno = ENODEV; + return NULL; } /* Make sure that the DAC block has been initialized */ - ret = dac_blockinit(); - if (ret < 0) - { - aerr("ERROR: Failed to initialize the DAC block: %d\n", ret); - errno = -ret; - return NULL; - } + dac_blockinit(); /* Configure the selected DAC channel */ diff --git a/arch/arm/src/stm32l4/stm32l4_dac.h b/arch/arm/src/stm32l4/stm32l4_dac.h index 19c8ad65c3a..b6e370f0e02 100644 --- a/arch/arm/src/stm32l4/stm32l4_dac.h +++ b/arch/arm/src/stm32l4/stm32l4_dac.h @@ -92,6 +92,17 @@ # undef CONFIG_STM32L4_TIM17_DAC #endif +/************************************************************************************ + * Public Data + ************************************************************************************/ + +#ifdef CONFIG_STM32L4_DAC1_DMA +extern uint16_t stm32l4_dac1_dmabuffer[]; +#endif +#ifdef CONFIG_STM32L4_DAC2_DMA +extern uint16_t stm32l4_dac2_dmabuffer[]; +#endif + /************************************************************************************ * Public Function Prototypes ************************************************************************************/