diff --git a/arch/arm/src/stm32l4/Make.defs b/arch/arm/src/stm32l4/Make.defs index 5454ddc1270..b527948b445 100644 --- a/arch/arm/src/stm32l4/Make.defs +++ b/arch/arm/src/stm32l4/Make.defs @@ -127,6 +127,10 @@ ifeq ($(CONFIG_BUILD_PROTECTED),y) CHIP_CSRCS += stm32l4_userspace.c stm32l4_mpuinit.c endif +ifeq ($(CONFIG_STM32L4_DAC),y) +CHIP_CSRCS += stm32l4_dac.c +endif + ifeq ($(CONFIG_STM32L4_DMA),y) CHIP_CSRCS += stm32l4_dma.c endif diff --git a/arch/arm/src/stm32l4/README.txt b/arch/arm/src/stm32l4/README.txt index 6adf0eac12e..98182043ffe 100644 --- a/arch/arm/src/stm32l4/README.txt +++ b/arch/arm/src/stm32l4/README.txt @@ -1,7 +1,7 @@ This is a port of NuttX to the STM32L4 Family -Used development boards are the Nucleo L476RG, Nucleo L496ZG and -STM32L4VGDiscovery +Used development boards are the Nucleo L476RG, Nucleo L496ZG, +Nucleo L452RE and STM32L4VGDiscovery. Most code is copied and adapted from the STM32 Port. @@ -24,7 +24,6 @@ USART : Working in normal mode (no DMA, to be tested, code is written) DMA : works; at least tested with QSPI SRAM2 : OK; can be included in MM region or left separate for special app : purposes -FIREWALL : Code written, to be tested, requires support from ldscript SPI : OK, tested (Including DMA) I2C : Code written, to be tested RTC : works @@ -45,18 +44,19 @@ WWDG : TODO IWDG : works MMCSD : TODO ADC : TODO -DAC : TODO +DAC : Code written, to be tested DMA2D : TODO (Chrom-Art Accelerator for image manipulation) New peripherals with implementation to be written from scratch These are Low Priority TODO items, unless someone requests or contributes it. +FIREWALL : Code written, to be tested, requires support from ldscript TSC : TODO (Touch Screen Controller) SWP : TODO (Single wire protocol master, to connect with NFC enabled : SIM cards) LPUART : TODO (Low power UART working with LSE at low baud rates) -LPTIMER : TODO (Low power TIMER) +LPTIM : Code written, to be tested (Low power TIMER) OPAMP : TODO (Analog operational amplifier) COMP : There is some code (Analog comparators) DFSDM : TODO (Digital Filter and Sigma-Delta Modulator) diff --git a/arch/arm/src/stm32l4/chip/stm32l4_dac.h b/arch/arm/src/stm32l4/chip/stm32l4_dac.h new file mode 100644 index 00000000000..3326538c6db --- /dev/null +++ b/arch/arm/src/stm32l4/chip/stm32l4_dac.h @@ -0,0 +1,331 @@ +/************************************************************************************ + * arch/arm/src/stm32l4/chip/stm32l4_dac.h + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * Juha Niskanen + * + * 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_STM32L4_CHIP_STM32L4_DAC_H +#define __ARCH_ARM_SRC_STM32L4_CHIP_STM32L4_DAC_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include "chip.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Register Offsets *****************************************************************/ + +#define STM32L4_DAC_CR_OFFSET 0x0000 /* DAC control register */ +#define STM32L4_DAC_SWTRIGR_OFFSET 0x0004 /* DAC software trigger register */ +#define STM32L4_DAC_DHR12R1_OFFSET 0x0008 /* DAC channel 1 12-bit right-aligned data holding register */ +#define STM32L4_DAC_DHR12L1_OFFSET 0x000c /* DAC channel 1 12-bit left aligned data holding register */ +#define STM32L4_DAC_DHR8R1_OFFSET 0x0010 /* DAC channel 1 8-bit right aligned data holding register */ +#define STM32L4_DAC_DHR12R2_OFFSET 0x0014 /* DAC channel 2 12-bit right aligned data holding register */ +#define STM32L4_DAC_DHR12L2_OFFSET 0x0018 /* DAC channel 2 12-bit left aligned data holding register */ +#define STM32L4_DAC_DHR8R2_OFFSET 0x001c /* DAC channel 2 8-bit right-aligned data holding register */ +#define STM32L4_DAC_DHR12RD_OFFSET 0x0020 /* Dual DAC 12-bit right-aligned data holding register */ +#define STM32L4_DAC_DHR12LD_OFFSET 0x0024 /* DUAL DAC 12-bit left aligned data holding register */ +#define STM32L4_DAC_DHR8RD_OFFSET 0x0028 /* DUAL DAC 8-bit right aligned data holding register */ +#define STM32L4_DAC_DOR1_OFFSET 0x002c /* DAC channel 1 data output register */ +#define STM32L4_DAC_DOR2_OFFSET 0x0030 /* DAC channel 2 data output register */ +#define STM32L4_DAC_SR_OFFSET 0x0034 /* DAC status register */ + /* New registers not in STM32L1: */ +#define STM32L4_DAC_CCR_OFFSET 0x0038 /* DAC calibration control register */ +#define STM32L4_DAC_MCR_OFFSET 0x003c /* DAC mode control register */ +#define STM32L4_DAC_SHSR1_OFFSET 0x0040 /* DAC Sample and Hold sample time register 1 */ +#define STM32L4_DAC_SHSR2_OFFSET 0x0044 /* DAC Sample and Hold sample time register 2 */ +#define STM32L4_DAC_SHHR_OFFSET 0x0048 /* DAC Sample and Hold hold time register */ +#define STM32L4_DAC_SHRR_OFFSET 0x004c /* DAC Sample and Hold refresh time register */ + +/* Register Addresses ***************************************************************/ + +#define STM32L4_DAC_CR (STM32L4_DAC_BASE+STM32L4_DAC_CR_OFFSET) +#define STM32L4_DAC_SWTRIGR (STM32L4_DAC_BASE+STM32L4_DAC_SWTRIGR_OFFSET) +#define STM32L4_DAC_DHR12R1 (STM32L4_DAC_BASE+STM32L4_DAC_DHR12R1_OFFSET) +#define STM32L4_DAC_DHR12L1 (STM32L4_DAC_BASE+STM32L4_DAC_DHR12L1_OFFSET) +#define STM32L4_DAC_DHR8R1 (STM32L4_DAC_BASE+STM32L4_DAC_DHR8R1_OFFSET) +#define STM32L4_DAC_DHR12R2 (STM32L4_DAC_BASE+STM32L4_DAC_DHR12R2_OFFSET) +#define STM32L4_DAC_DHR12L2 (STM32L4_DAC_BASE+STM32L4_DAC_DHR12L2_OFFSET) +#define STM32L4_DAC_DHR8R2 (STM32L4_DAC_BASE+STM32L4_DAC_DHR8R2_OFFSET) +#define STM32L4_DAC_DHR12RD (STM32L4_DAC_BASE+STM32L4_DAC_DHR12RD_OFFSET) +#define STM32L4_DAC_DHR12LD (STM32L4_DAC_BASE+STM32L4_DAC_DHR12LD_OFFSET) +#define STM32L4_DAC_DHR8RD (STM32L4_DAC_BASE+STM32L4_DAC_DHR8RD_OFFSET) +#define STM32L4_DAC_DOR1 (STM32L4_DAC_BASE+STM32L4_DAC_DOR1_OFFSET) +#define STM32L4_DAC_DOR2 (STM32L4_DAC_BASE+STM32L4_DAC_DOR2_OFFSET) +#define STM32L4_DAC_SR (STM32L4_DAC_BASE+STM32L4_DAC_SR_OFFSET) +#define STM32L4_DAC_CCR (STM32L4_DAC_BASE+STM32L4_DAC_CCR_OFFSET) +#define STM32L4_DAC_MCR (STM32L4_DAC_BASE+STM32L4_DAC_MCR_OFFSET) +#define STM32L4_DAC_SHSR1 (STM32L4_DAC_BASE+STM32L4_DAC_SHSR1_OFFSET) +#define STM32L4_DAC_SHSR2 (STM32L4_DAC_BASE+STM32L4_DAC_SHSR2_OFFSET) +#define STM32L4_DAC_SHHR (STM32L4_DAC_BASE+STM32L4_DAC_SHHR_OFFSET) +#define STM32L4_DAC_SHRR (STM32L4_DAC_BASE+STM32L4_DAC_SHRR_OFFSET) + +/* Register Bitfield Definitions ****************************************************/ + +/* DAC control register */ +/* These definitions may be used for 16-bit values of either channel */ + +#define DAC_CR_EN (1 << 0) /* Bit 0: DAC channel enable */ + /* Bit 1: reserved */ +#define DAC_CR_TEN (1 << 2) /* Bit 2: DAC channel trigger enable */ +#define DAC_CR_TSEL_SHIFT (3) /* Bits 3-5: DAC channel trigger selection */ +#define DAC_CR_TSEL_MASK (7 << DAC_CR_TSEL_SHIFT) +# define DAC_CR_TSEL_TIM6 (0 << DAC_CR_TSEL_SHIFT) /* Timer 6 TRGO event */ +# define DAC_CR_TSEL_TIM8 (1 << DAC_CR_TSEL_SHIFT) /* Timer 8 TRGO event */ +# define DAC_CR_TSEL_TIM7 (2 << DAC_CR_TSEL_SHIFT) /* Timer 7 TRGO event */ +# define DAC_CR_TSEL_TIM5 (3 << DAC_CR_TSEL_SHIFT) /* Timer 5 TRGO event */ +# define DAC_CR_TSEL_TIM2 (4 << DAC_CR_TSEL_SHIFT) /* Timer 2 TRGO event */ +# define DAC_CR_TSEL_TIM4 (5 << DAC_CR_TSEL_SHIFT) /* Timer 4 TRGO event */ +# define DAC_CR_TSEL_EXT9 (6 << DAC_CR_TSEL_SHIFT) /* External line9 */ +# define DAC_CR_TSEL_SW (7 << DAC_CR_TSEL_SHIFT) /* Software trigger */ +#define DAC_CR_WAVE_SHIFT (6) /* Bits 6-7: DAC channel noise/triangle wave generation */ +#define DAC_CR_WAVE_MASK (3 << DAC_CR_WAVE_SHIFT) +# define DAC_CR_WAVE_DISABLED (0 << DAC_CR_WAVE_SHIFT) /* Wave generation disabled */ +# define DAC_CR_WAVE_NOISE (1 << DAC_CR_WAVE_SHIFT) /* Noise wave generation enabled */ +# define DAC_CR_WAVE_TRIANGLE (2 << DAC_CR_WAVE_SHIFT) /* Triangle wave generation enabled */ +#define DAC_CR_MAMP_SHIFT (8) /* Bits 8-11: DAC channel mask/amplitude selector */ +#define DAC_CR_MAMP_MASK (15 << DAC_CR_MAMP_SHIFT) +# define DAC_CR_MAMP_AMP1 (0 << DAC_CR_MAMP1_SHIFT) /* Unmask bit0 of LFSR/triangle amplitude=1 */ +# define DAC_CR_MAMP_AMP3 (1 << DAC_CR_MAMP_SHIFT) /* Unmask bits[1:0] of LFSR/triangle amplitude=3 */ +# define DAC_CR_MAMP_AMP7 (2 << DAC_CR_MAMP_SHIFT) /* Unmask bits[2:0] of LFSR/triangle amplitude=7 */ +# define DAC_CR_MAMP_AMP15 (3 << DAC_CR_MAMP_SHIFT) /* Unmask bits[3:0] of LFSR/triangle amplitude=15 */ +# define DAC_CR_MAMP_AMP31 (4 << DAC_CR_MAMP_SHIFT) /* Unmask bits[4:0] of LFSR/triangle amplitude=31 */ +# define DAC_CR_MAMP_AMP63 (5 << DAC_CR_MAMP_SHIFT) /* Unmask bits[5:0] of LFSR/triangle amplitude=63 */ +# define DAC_CR_MAMP_AMP127 (6 << DAC_CR_MAMP_SHIFT) /* Unmask bits[6:0] of LFSR/triangle amplitude=127 */ +# define DAC_CR_MAMP_AMP255 (7 << DAC_CR_MAMP_SHIFT) /* Unmask bits[7:0] of LFSR/triangle amplitude=255 */ +# define DAC_CR_MAMP_AMP511 (8 << DAC_CR_MAMP_SHIFT) /* Unmask bits[8:0] of LFSR/triangle amplitude=511 */ +# define DAC_CR_MAMP_AMP1023 (9 << DAC_CR_MAMP_SHIFT) /* Unmask bits[9:0] of LFSR/triangle amplitude=1023 */ +# define DAC_CR_MAMP_AMP2047 (10 << DAC_CR_MAMP_SHIFT) /* Unmask bits[10:0] of LFSR/triangle amplitude=2047 */ +# define DAC_CR_MAMP_AMP4095 (11 << DAC_CR_MAMP_SHIFT) /* Unmask bits[11:0] of LFSR/triangle amplitude=4095 */ +#define DAC_CR_DMAEN (1 << 12) /* Bit 12: DAC channel DMA enable */ +#define DAC_CR_DMAUDRIE (1 << 13) /* Bit 13: DAC channel DMA Underrun Interrupt enable */ +#define DAC_CR_CEN (1 << 14) /* Bit 14: DAC channel calibration enable */ + +/* These definitions may be used with the full, 32-bit register */ + +#define DAC_CR_EN1 (1 << 0) /* Bit 0: DAC channel 1 enable */ + /* Bit 1: reserved */ +#define DAC_CR_TEN1 (1 << 2) /* Bit 2: DAC channel 1 trigger enable */ +#define DAC_CR_TSEL1_SHIFT (3) /* Bits 3-5: DAC channel 1 trigger selection */ +#define DAC_CR_TSEL1_MASK (7 << DAC_CR_TSEL1_SHIFT) +# define DAC_CR_TSEL1_TIM6 (0 << DAC_CR_TSEL1_SHIFT) /* Timer 6 TRGO event */ +# define DAC_CR_TSEL1_TIM8 (1 << DAC_CR_TSEL1_SHIFT) /* Timer 8 TRGO event */ +# define DAC_CR_TSEL1_TIM7 (2 << DAC_CR_TSEL1_SHIFT) /* Timer 7 TRGO event */ +# define DAC_CR_TSEL1_TIM5 (3 << DAC_CR_TSEL1_SHIFT) /* Timer 5 TRGO event */ +# define DAC_CR_TSEL1_TIM2 (4 << DAC_CR_TSEL1_SHIFT) /* Timer 2 TRGO event */ +# define DAC_CR_TSEL1_TIM4 (5 << DAC_CR_TSEL1_SHIFT) /* Timer 4 TRGO event */ +# define DAC_CR_TSEL1_EXT9 (6 << DAC_CR_TSEL1_SHIFT) /* External line9 */ +# define DAC_CR_TSEL1_SW (7 << DAC_CR_TSEL1_SHIFT) /* Software trigger */ +#define DAC_CR_WAVE1_SHIFT (6) /* Bits 6-7: DAC channel 1 noise/triangle wave generation */ +#define DAC_CR_WAVE1_MASK (3 << DAC_CR_WAVE1_SHIFT) +# define DAC_CR_WAVE1_DISABLED (0 << DAC_CR_WAVE1_SHIFT) /* Wave generation disabled */ +# define DAC_CR_WAVE1_NOISE (1 << DAC_CR_WAVE1_SHIFT) /* Noise wave generation enabled */ +# define DAC_CR_WAVE1_TRIANGLE (2 << DAC_CR_WAVE1_SHIFT) /* Triangle wave generation enabled */ +#define DAC_CR_MAMP1_SHIFT (8) /* Bits 8-11: DAC channel 1 mask/amplitude selector */ +#define DAC_CR_MAMP1_MASK (15 << DAC_CR_MAMP1_SHIFT) +# define DAC_CR_MAMP1_AMP1 (0 << DAC_CR_MAMP1_SHIFT) /* Unmask bit0 of LFSR/triangle amplitude=1 */ +# define DAC_CR_MAMP1_AMP3 (1 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[1:0] of LFSR/triangle amplitude=3 */ +# define DAC_CR_MAMP1_AMP7 (2 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[2:0] of LFSR/triangle amplitude=7 */ +# define DAC_CR_MAMP1_AMP15 (3 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[3:0] of LFSR/triangle amplitude=15 */ +# define DAC_CR_MAMP1_AMP31 (4 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[4:0] of LFSR/triangle amplitude=31 */ +# define DAC_CR_MAMP1_AMP63 (5 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[5:0] of LFSR/triangle amplitude=63 */ +# define DAC_CR_MAMP1_AMP127 (6 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[6:0] of LFSR/triangle amplitude=127 */ +# define DAC_CR_MAMP1_AMP255 (7 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[7:0] of LFSR/triangle amplitude=255 */ +# define DAC_CR_MAMP1_AMP511 (8 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[8:0] of LFSR/triangle amplitude=511 */ +# define DAC_CR_MAMP1_AMP1023 (9 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[9:0] of LFSR/triangle amplitude=1023 */ +# define DAC_CR_MAMP1_AMP2047 (10 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[10:0] of LFSR/triangle amplitude=2047 */ +# define DAC_CR_MAMP1_AMP4095 (11 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[11:0] of LFSR/triangle amplitude=4095 */ +#define DAC_CR_DMAEN1 (1 << 12) /* Bit 12: DAC channel 1 DMA enable */ +#define DAC_CR_DMAUDRIE1 (1 << 13) /* Bit 13: DAC channel 1 DMA Underrun Interrupt enable */ +#define DAC_CR_CEN1 (1 << 14) /* Bit 14: DAC channel 1 calibration enable */ + +#define DAC_CR_EN2 (1 << 16) /* Bit 16: DAC channel 2 enable */ +#define DAC_CR_BOFF2 (1 << 17) /* Bit 17: DAC channel 2 output buffer disable */ +#define DAC_CR_TEN2 (1 << 18) /* Bit 18: DAC channel 2 trigger enable */ +#define DAC_CR_TSEL2_SHIFT (19) /* Bits 19-21: DAC channel 2 trigger selection */ +#define DAC_CR_TSEL2_MASK (7 << DAC_CR_TSEL2_SHIFT) +# define DAC_CR_TSEL2_TIM6 (0 << DAC_CR_TSEL2_SHIFT) /* Timer 6 TRGO event */ +# define DAC_CR_TSEL2_TIM8 (1 << DAC_CR_TSEL2_SHIFT) /* Timer 8 TRGO event */ +# define DAC_CR_TSEL2_TIM7 (2 << DAC_CR_TSEL2_SHIFT) /* Timer 7 TRGO event */ +# define DAC_CR_TSEL2_TIM5 (3 << DAC_CR_TSEL2_SHIFT) /* Timer 5 TRGO event */ +# define DAC_CR_TSEL2_TIM2 (4 << DAC_CR_TSEL2_SHIFT) /* Timer 2 TRGO event */ +# define DAC_CR_TSEL2_TIM4 (5 << DAC_CR_TSEL2_SHIFT) /* Timer 4 TRGO event */ +# define DAC_CR_TSEL2_EXT9 (6 << DAC_CR_TSEL2_SHIFT) /* External line9 */ +# define DAC_CR_TSEL2_SW (7 << DAC_CR_TSEL2_SHIFT) /* Software trigger */ +#define DAC_CR_WAVE2_SHIFT (22) /* Bit 22-23: DAC channel 2 noise/triangle wave generation enable */ +#define DAC_CR_WAVE2_MASK (3 << DAC_CR_WAVE2_SHIFT) +# define DAC_CR_WAVE2_DISABLED (0 << DAC_CR_WAVE2_SHIFT) /* Wave generation disabled */ +# define DAC_CR_WAVE2_NOISE (1 << DAC_CR_WAVE2_SHIFT) /* Noise wave generation enabled */ +# define DAC_CR_WAVE2_TRIANGLE (2 << DAC_CR_WAVE2_SHIFT) /* Triangle wave generation enabled */ +#define DAC_CR_MAMP2_SHIFT (24) /* Bit 24-27: DAC channel 2 mask/amplitude selector */ +#define DAC_CR_MAMP2_MASK (15 << DAC_CR_MAMP2_SHIFT) +# define DAC_CR_MAMP2_AMP1 (0 << DAC_CR_MAMP2_SHIFT) /* Unmask bit0 of LFSR/triangle amplitude=1 */ +# define DAC_CR_MAMP2_AMP3 (1 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[1:0] of LFSR/triangle amplitude=3 */ +# define DAC_CR_MAMP2_AMP7 (2 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[2:0] of LFSR/triangle amplitude=7 */ +# define DAC_CR_MAMP2_AMP15 (3 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[3:0] of LFSR/triangle amplitude=15 */ +# define DAC_CR_MAMP2_AMP31 (4 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[4:0] of LFSR/triangle amplitude=31 */ +# define DAC_CR_MAMP2_AMP63 (5 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[5:0] of LFSR/triangle amplitude=63 */ +# define DAC_CR_MAMP2_AMP127 (6 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[6:0] of LFSR/triangle amplitude=127 */ +# define DAC_CR_MAMP2_AMP255 (7 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[7:0] of LFSR/triangle amplitude=255 */ +# define DAC_CR_MAMP2_AMP511 (8 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[8:0] of LFSR/triangle amplitude=511 */ +# define DAC_CR_MAMP2_AMP1023 (9 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[9:0] of LFSR/triangle amplitude=1023 */ +# define DAC_CR_MAMP2_AMP2047 (10 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[10:0] of LFSR/triangle amplitude=2047 */ +# define DAC_CR_MAMP2_AMP4095 (11 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[11:0] of LFSR/triangle amplitude=4095 */ +#define DAC_CR_DMAEN2 (1 << 28) /* Bit 28: DAC channel 2 DMA enable */ +#define DAC_CR_DMAUDRIE2 (1 << 29) /* Bit 29: DAC channel 2 DMA underrun interrupt enable */ +#define DAC_CR_CEN2 (1 << 30) /* Bit 30: DAC channel 2 calibration enable */ + +/* DAC software trigger register */ + +#define DAC_SWTRIGR_SWTRIG(n) (1 << ((n)-1)) +#define DAC_SWTRIGR_SWTRIG1 (1 << 0) /* Bit 0: DAC channel 1 software trigger */ +#define DAC_SWTRIGR_SWTRIG2 (1 << 1) /* Bit 1: DAC channel 2 software trigger */ + +/* DAC channel 1/2 12-bit right-aligned data holding register */ + +#define DAC_DHR12R_MASK (0x0fff) + +/* DAC channel 1/2 12-bit left aligned data holding register */ + +#define DAC_DHR12L_MASK (0xfff0) + +/* DAC channel 1/2 8-bit right aligned data holding register */ + +#define DAC_DHR8R_MASK (0x00ff) + +/* Dual DAC 12-bit right-aligned data holding register */ + +#define DAC_DHR12RD_DACC_SHIFT(n) (((n)-1) << 4) +#define DAC_DHR12RD_DACC_MASK(n) (0xfff << DAC_DHR12RD_DACC_SHIFT(n)) + +#define DAC_DHR12RD_DACC1_SHIFT (0) /* Bits 0-11: DAC channel 1 12-bit right-aligned data */ +#define DAC_DHR12RD_DACC1_MASK (0xfff << DAC_DHR12RD_DACC1_SHIFT) +#define DAC_DHR12RD_DACC2_SHIFT (16) /* Bits 16-27: DAC channel 2 12-bit right-aligned data */ +#define DAC_DHR12RD_DACC2_MASK (0xfff << DAC_DHR12RD_DACC2_SHIFT) + +/* Dual DAC 12-bit left-aligned data holding register */ + +#define DAC_DHR12LD_DACC_SHIFT(n) ((((n)-1) << 4) + 4) +#define DAC_DHR12LD_DACC_MASK(n) (0xfff << DAC_DHR12LD_DACC_SHIFT(n)) + +#define DAC_DHR12LD_DACC1_SHIFT (4) /* Bits 4-15: DAC channel 1 12-bit left-aligned data */ +#define DAC_DHR12LD_DACC1_MASK (0xfff << DAC_DHR12LD_DACC1_SHIFT) +#define DAC_DHR12LD_DACC2_SHIFT (20) /* Bits 20-31: DAC channel 2 12-bit left-aligned data */ +#define DAC_DHR12LD_DACC2_MASK (0xfff << DAC_DHR12LD_DACC2_SHIFT) + +/* DUAL DAC 8-bit right aligned data holding register */ + +#define DAC_DHR8RD_DACC_SHIFT(n) (((n)-1) << 3) +#define DAC_DHR8RD_DACC_MASK(n) (0xff << DAC_DHR8RD_DACC_SHIFT(n)) + +#define DAC_DHR8RD_DACC1_SHIFT (0) /* Bits 0-7: DAC channel 1 8-bit right-aligned data */ +#define DAC_DHR8RD_DACC1_MASK (0xff << DAC_DHR8RD_DACC1_SHIFT) +#define DAC_DHR8RD_DACC2_SHIFT (8) /* Bits 8-15: DAC channel 2 8-bit right-aligned data */ +#define DAC_DHR8RD_DACC2_MASK (0xff << DAC_DHR8RD_DACC2_SHIFT) + +/* DAC channel 1/2 data output register */ + +#define DAC_DOR_MASK (0x0fff) + +/* DAC status register */ + +#define DAC_SR_DMAUDR(n) (1 << ((((n)-1) << 4) + 13)) +#define DAC_SR_DMAUDR1 (1 << 13) /* Bit 13: DAC channel 1 DMA underrun flag */ +#define DAC_SR_DMAUDR2 (1 << 29) /* Bit 29: DAC channel 2 DMA underrun flag */ + +#define DAC_SR_CALFLAG(n) (1 << ((((n)-1) << 4) + 14)) +#define DAC_SR_CALFLAG1 (1 << 14) /* Bit 14: DAC channel 1 calibration offset status */ +#define DAC_SR_CALFLAG2 (1 << 30) /* Bit 30: DAC channel 2 calibration offset status */ + +#define DAC_SR_BWST(n) (1 << ((((n)-1) << 4) + 15)) +#define DAC_SR_BWST1 (1 << 15) /* Bit 15 DAC channel 1 busy writing sample time flag */ +#define DAC_SR_BWST2 (1 << 31) /* Bit 31: DAC channel 2 busy writing sample time flag */ + +/* DAC calibration control register (DAC_CCR) */ + +#define DAC_CCR_OTRIM_SHIFT(n) (((n)-1) << 4) +#define DAC_CCR_OTRIM_MASK(n) (0x1f << DAC_CCR_OTRIM_SHIFT(n)) + +#define DAC_CCR_OTRIM1_SHIFT (0) /* Bits 0-4: DAC channel 1 offset trimming value */ +#define DAC_CCR_OTRIM1_MASK (0x1f << DAC_CCR_OTRIM1_SHIFT) + +#define DAC_CCR_OTRIM2_SHIFT (16) /* Bits 16-20: DAC channel 2 offset trimming value */ +#define DAC_CCR_OTRIM2_MASK (0x1f << DAC_CCR_OTRIM2_SHIFT) + +/* DAC mode control register (DAC_MCR) */ + +#define DAC_MCR_MODE_SHIFT(n) (((n)-1) << 4) +#define DAC_MCR_MODE_MASK(n) (0x7 << DAC_MCR_MODE_SHIFT(n)) + +#define DAC_MCR_MODE1_SHIFT (0) /* Bits 0-2: DAC channel 1 mode */ +#define DAC_MCR_MODE1_MASK (0x7 << DAC_MCR_MODE1_SHIFT) + +#define DAC_MCR_MODE2_SHIFT (16) /* Bits 16-18: DAC channel 2 mode */ +#define DAC_MCR_MODE2_MASK (0x7 << DAC_MCR_MODE2_SHIFT) + +/* DAC Sample and Hold sample time register 1 (DAC_SHSR1) */ + +#define DAC_SHSR1_TSAMPLE1_MASK (0x3ff) + +/* DAC Sample and Hold sample time register 2 (DAC_SHSR2) */ + +#define DAC_SHSR2_TSAMPLE2_MASK (0x3ff) + +/* DAC Sample and Hold hold time register (DAC_SHHR) */ + +#define DAC_SHHR_THOLD_SHIFT(n) (((n)-1) << 4) +#define DAC_SHHR_THOLD_MASK(n) (0x3ff << DAC_SHHR_THOLD_SHIFT(n)) + +#define DAC_SHHR_THOLD1_SHIFT (0) /* Bits 0-9: DAC channel 1 hold time */ +#define DAC_SHHR_THOLD1_MASK (0x3ff << DAC_SHHR_THOLD1_SHIFT) + +#define DAC_SHHR_THOLD2_SHIFT (16) /* Bits 16-25: DAC channel 2 hold time */ +#define DAC_SHHR_THOLD2_MASK (0x3ff << DAC_SHHR_THOLD2_SHIFT) + +/* DAC Sample and Hold refresh time register (DAC_SHRR) */ + +#define DAC_SHRR_TREFRESH_SHIFT(n) (((n)-1) << 4) +#define DAC_SHRR_TREFRESH_MASK(n) (0xff << DAC_SHRR_TREFRESH_SHIFT(n)) + +#define DAC_SHRR_TREFRESH1_SHIFT (0) /* Bits 0-7: DAC channel 1 refresh time */ +#define DAC_SHRR_TREFRESH1_MASK (0xff << DAC_SHRR_TREFRESH1_SHIFT) + +#define DAC_SHRR_TREFRESH2_SHIFT (16) /* Bits 16-23: DAC channel 2 refresh time */ +#define DAC_SHRR_TREFRESH2_MASK (0xff << DAC_SHRR_TREFRESH2_SHIFT) + +#endif /* __ARCH_ARM_SRC_STM32L4_CHIP_STM32L4_DAC_H */ diff --git a/arch/arm/src/stm32l4/stm32l4_dac.c b/arch/arm/src/stm32l4/stm32l4_dac.c new file mode 100644 index 00000000000..a984d773c81 --- /dev/null +++ b/arch/arm/src/stm32l4/stm32l4_dac.c @@ -0,0 +1,1164 @@ +/************************************************************************************ + * arch/arm/src/stm32l4/stm32l4_dac.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * Juha Niskanen + * + * 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 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "up_internal.h" +#include "up_arch.h" + +#include "chip.h" +#include "stm32l4.h" +#include "stm32l4_dac.h" +#include "stm32l4_rcc.h" +#include "stm32l4_dma.h" + +#ifdef CONFIG_DAC + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* Up to 2 DAC interfaces for up to 3 channels are supported */ + +#if STM32L4_NDAC < 2 +# undef CONFIG_STM32L4_DAC2 +# undef CONFIG_STM32L4_DAC2_DMA +# undef CONFIG_STM32L4_DAC2_TIMER +# undef CONFIG_STM32L4_DAC2_TIMER_FREQUENCY +#endif + +#if STM32L4_NDAC < 1 +# undef CONFIG_STM32L4_DAC1 +# undef CONFIG_STM32L4_DAC1_DMA +# undef CONFIG_STM32L4_DAC1_TIMER +# undef CONFIG_STM32L4_DAC1_TIMER_FREQUENCY +#endif + +#if defined(CONFIG_STM32L4_DAC1) || defined(CONFIG_STM32L4_DAC2) + +/* 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 timer and output frequency must also be + * provided to support the DMA transfer. The DMA transfer could be + * supported by and EXTI trigger, but this feature is not currently + * supported by the driver. + */ + +#ifdef CONFIG_STM32L4_DAC1_DMA +# if !defined(CONFIG_STM32L4_DAC1_TIMER) +# warning "A timer number must be specificed in CONFIG_STM32L4_DAC1_TIMER" +# undef CONFIG_STM32L4_DAC1_DMA +# undef CONFIG_STM32L4_DAC1_TIMER_FREQUENCY +# elif !defined(CONFIG_STM32L4_DAC1_TIMER_FREQUENCY) +# warning "A timer frequency must be specificed in CONFIG_STM32L4_DAC1_TIMER_FREQUENCY" +# undef CONFIG_STM32L4_DAC1_DMA +# undef CONFIG_STM32L4_DAC1_TIMER +# endif +#endif + +#ifdef CONFIG_STM32L4_DAC2_DMA +# if !defined(CONFIG_STM32L4_DAC2_TIMER) +# warning "A timer number must be specificed in CONFIG_STM32L4_DAC2_TIMER" +# undef CONFIG_STM32L4_DAC2_DMA +# undef CONFIG_STM32L4_DAC2_TIMER_FREQUENCY +# elif !defined(CONFIG_STM32L4_DAC2_TIMER_FREQUENCY) +# warning "A timer frequency must be specificed in CONFIG_STM32L4_DAC2_TIMER_FREQUENCY" +# undef CONFIG_STM32L4_DAC2_DMA +# undef CONFIG_STM32L4_DAC2_TIMER +# endif +#endif + +/* DMA *********************************************************************/ + +#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 +#endif + +/* Timer configuration. The STM32L4 supports 8 different trigger for DAC + * output: + * + * TSEL SOURCE DEVICES + * ---- ----------------------- ------------------------------------- + * 000 Timer 6 TRGO event ALL + * 001 Timer 8 TRGO event STM32L4x5 and STM32L4x6 + * 010 Timer 7 TRGO event Not on STM32L45xxx and STM32L46xxx + * 011 Timer 5 TRGO event STM32L4x5 and STM32L4x6 + * 100 Timer 2 TRGO event ALL + * 101 Timer 4 TRGO event STM32L4x5 and STM32L4x6 + * 110 EXTI line9 ALL + * 111 SWTRIG Software control ALL + * + * This driver does not support the EXTI trigger. + */ + +#undef NEED_TIM6 +#undef NEED_TIM8 +#undef NEED_TIM7 +#undef NEED_TIM5 +#undef NEED_TIM2 +#undef NEED_TIM4 + +#ifdef CONFIG_STM32L4_DAC1_DMA +# if CONFIG_STM32L4_DAC1_TIMER == 6 +# ifndef CONFIG_STM32L4_TIM6_DAC +# error "CONFIG_STM32L4_TIM6_DAC required for DAC1" +# endif +# define NEED_TIM6 +# define DAC1_TSEL_VALUE DAC_CR_TSEL_TIM6 +# define DAC1_TIMER_BASE STM32L4_TIM6_BASE +# define DAC1_TIMER_PCLK_FREQUENCY STM32L4_PCLK1_FREQUENCY +# elif CONFIG_STM32L4_DAC1_TIMER == 8 +# ifndef CONFIG_STM32L4_TIM8_DAC +# error "CONFIG_STM32L4_TIM8_DAC required for DAC1" +# endif +# define NEED_TIM8 +# define DAC1_TSEL_VALUE DAC_CR_TSEL_TIM8 +# define DAC1_TIMER_BASE STM32L4_TIM8_BASE +# define DAC1_TIMER_PCLK_FREQUENCY STM32L4_PCLK2_FREQUENCY +# elif CONFIG_STM32L4_DAC1_TIMER == 7 +# ifndef CONFIG_STM32L4_TIM7_DAC +# error "CONFIG_STM32L4_TIM7_DAC required for DAC1" +# endif +# define NEED_TIM7 +# define DAC1_TSEL_VALUE DAC_CR_TSEL_TIM7 +# define DAC1_TIMER_BASE STM32L4_TIM7_BASE +# elif CONFIG_STM32L4_DAC1_TIMER == 5 +# ifndef CONFIG_STM32L4_TIM5_DAC +# error "CONFIG_STM32L4_TIM5_DAC required for DAC1" +# endif +# define NEED_TIM5 +# define DAC1_TSEL_VALUE DAC_CR_TSEL_TIM5 +# define DAC1_TIMER_BASE STM32L4_TIM5_BASE +# define DAC1_TIMER_PCLK_FREQUENCY STM32L4_PCLK1_FREQUENCY +# elif CONFIG_STM32L4_DAC1_TIMER == 2 +# ifndef CONFIG_STM32L4_TIM2_DAC +# error "CONFIG_STM32L4_TIM2_DAC required for DAC1" +# endif +# define NEED_TIM2 +# define DAC1_TSEL_VALUE DAC_CR_TSEL_TIM2 +# define DAC1_TIMER_BASE STM32L4_TIM2_BASE +# define DAC1_TIMER_PCLK_FREQUENCY STM32L4_PCLK1_FREQUENCY +# elif CONFIG_STM32L4_DAC1_TIMER == 4 +# ifndef CONFIG_STM32L4_TIM4_DAC +# error "CONFIG_STM32L4_TIM4_DAC required for DAC1" +# endif +# define NEED_TIM4 +# define DAC1_TSEL_VALUE DAC_CR_TSEL_TIM4 +# define DAC1_TIMER_BASE STM32L4_TIM4_BASE +# define DAC1_TIMER_PCLK_FREQUENCY STM32L4_PCLK1_FREQUENCY +# else +# error "Unsupported CONFIG_STM32_DAC1_TIMER" +# endif +#else +# define DAC1_TSEL_VALUE DAC_CR_TSEL_SW +#endif + +#ifdef CONFIG_STM32L4_DAC2_DMA +# if CONFIG_STM32L4_DAC2_TIMER == 6 +# ifndef CONFIG_STM32L4_TIM6_DAC +# error "CONFIG_STM32L4_TIM6_DAC required for DAC2" +# endif +# define DAC2_TSEL_VALUE DAC_CR_TSEL_TIM6 +# define DAC2_TIMER_BASE STM32L4_TIM6_BASE +# define DAC2_TIMER_PCLK_FREQUENCY STM32L4_PCLK1_FREQUENCY +# elif CONFIG_STM32L4_DAC2_TIMER == 8 +# ifndef CONFIG_STM32L4_TIM8_DAC +# error "CONFIG_STM32L4_TIM8_DAC required for DAC2" +# endif +# define DAC2_TSEL_VALUE DAC_CR_TSEL_TIM8 +# define DAC2_TIMER_BASE STM32L4_TIM8_BASE +# define DAC2_TIMER_PCLK_FREQUENCY STM32L4_PCLK2_FREQUENCY +# elif CONFIG_STM32L4_DAC2_TIMER == 7 +# ifndef CONFIG_STM32L4_TIM7_DAC +# error "CONFIG_STM32L4_TIM7_DAC required for DAC2" +# endif +# define DAC2_TSEL_VALUE DAC_CR_TSEL_TIM7 +# define DAC2_TIMER_BASE STM32L4_TIM7_BASE +# define DAC2_TIMER_PCLK_FREQUENCY STM32L4_PCLK1_FREQUENCY +# elif CONFIG_STM32L4_DAC2_TIMER == 5 +# ifndef CONFIG_STM32L4_TIM5_DAC +# error "CONFIG_STM32L4_TIM5_DAC required for DAC2" +# endif +# define DAC2_TSEL_VALUE DAC_CR_TSEL_TIM5 +# define DAC2_TIMER_BASE STM32L4_TIM5_BASE +# define DAC2_TIMER_PCLK_FREQUENCY STM32L4_PCLK1_FREQUENCY +# elif CONFIG_STM32L4_DAC2_TIMER == 2 +# ifndef CONFIG_STM32L4_TIM2_DAC +# error "CONFIG_STM32L4_TIM2_DAC required for DAC2" +# endif +# define DAC2_TSEL_VALUE DAC_CR_TSEL_TIM2 +# define DAC2_TIMER_BASE STM32L4_TIM2_BASE +# define DAC2_TIMER_PCLK_FREQUENCY STM32L4_PCLK1_FREQUENCY +# elif CONFIG_STM32L4_DAC2_TIMER == 4 +# ifndef CONFIG_STM32L4_TIM4_DAC +# error "CONFIG_STM32L4_TIM4_DAC required for DAC2" +# endif +# define DAC2_TSEL_VALUE DAC_CR_TSEL_TIM4 +# define DAC2_TIMER_BASE STM32L4_TIM4_BASE +# define DAC2_TIMER_PCLK_FREQUENCY STM32L4_PCLK1_FREQUENCY +# else +# error "Unsupported CONFIG_STM32L4_DAC2_TIMER" +# endif +#else +# define DAC2_TSEL_VALUE DAC_CR_TSEL_SW +#endif + +#ifndef CONFIG_STM32L4_DAC_DMA_BUFFER_SIZE +# define CONFIG_STM32L4_DAC_DMA_BUFFER_SIZE 256 +#endif + +/* Calculate timer divider values based upon DACn_TIMER_PCLK_FREQUENCY and + * CONFIG_STM32_DACn_TIMER_FREQUENCY. + */ + +#warning "Missing Logic" + +/* DMA stream/channel configuration */ + +#define DAC_DMA_CONTROL_WORD (DMA_CCR_MSIZE_16BITS | \ + DMA_CCR_PSIZE_16BITS | \ + DMA_CCR_MINC | \ + DMA_CCR_CIRC | \ + DMA_CCR_DIR) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure represents the internal state of the single STM32 DAC block */ + +struct stm32_dac_s +{ + uint8_t init : 1; /* True, the DAC block has been initialized */ +}; + +/* This structure represents the internal state of one STM32 DAC channel */ + +struct stm32_chan_s +{ + uint8_t inuse : 1; /* True, the driver is in use and not available */ +#ifdef HAVE_DMA + uint8_t hasdma : 1; /* True, this channel supports DMA */ + uint8_t timer; /* Timer number 2-8 */ +#endif + uint8_t intf; /* DAC zero-based interface number (0 or 1) */ + uint32_t pin; /* Pin configuration */ + uint32_t dro; /* Data output register */ + uint32_t cr; /* Control register */ + uint32_t tsel; /* CR trigger select value */ +#ifdef HAVE_DMA + uint16_t dmachan; /* DMA channel needed by this DAC */ + DMA_HANDLE dma; /* Allocated DMA channel */ + uint32_t tbase; /* Timer base address */ + uint32_t tfrequency; /* Timer frequency */ + uint16_t dmabuffer[CONFIG_STM32L4_DAC_DMA_BUFFER_SIZE]; /* DMA transfer buffer */ +#endif +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* DAC Register access */ + +#ifdef HAVE_DMA +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 + +/* DAC methods */ + +static void dac_reset(FAR struct dac_dev_s *dev); +static int dac_setup(FAR struct dac_dev_s *dev); +static void dac_shutdown(FAR struct dac_dev_s *dev); +static void dac_txint(FAR struct dac_dev_s *dev, bool enable); +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); + +/* Initialization */ + +#ifdef HAVE_DMA +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); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct dac_ops_s g_dacops = +{ + .ao_reset = dac_reset, + .ao_setup = dac_setup, + .ao_shutdown = dac_shutdown, + .ao_txint = dac_txint, + .ao_send = dac_send, + .ao_ioctl = dac_ioctl, +}; + +#ifdef CONFIG_STM32L4_DAC1 +/* Channel 1 */ + +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, + .timer = CONFIG_STM32L4_DAC1_TIMER, + .tsel = DAC1_TSEL_VALUE, + .tbase = DAC1_TIMER_BASE, + .tfrequency = CONFIG_STM32L4_DAC1_TIMER_FREQUENCY, +#endif +}; + +static struct dac_dev_s g_dac1dev = +{ + .ad_ops = &g_dacops, + .ad_priv = &g_dac1priv, +}; + +#if STM32L4_NDAC > 1 +/* Channel 2: Note that some STM32L4 chips don't have + * the DAC1 second output channel. + */ + +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, + .timer = CONFIG_STM32L4_DAC2_TIMER, + .tsel = DAC2_TSEL_VALUE, + .tbase = DAC2_TIMER_BASE, + .tfrequency = CONFIG_STM32L4_DAC2_TIMER_FREQUENCY, +#endif +}; + +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 + +static struct stm32_dac_s g_dacblock; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32l4_dac_modify_cr + * + * Description: + * Modify the contents of the DAC control register. + * + * Input Parameters: + * priv - Driver state instance + * clearbits - Bits in the control register to be cleared + * setbits - Bits in the control register to be set + * + * Returned Value: + * None + * + ****************************************************************************/ + +static inline void stm32l4_dac_modify_cr(FAR struct stm32_chan_s *chan, + uint32_t clearbits, uint32_t setbits) +{ + 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. + * + * Bit 0 = 0: Shift = 0 + * Bit 0 = 1: Shift = 16 + */ + + shift = (chan->intf & 1) << 4; + modifyreg32(chan->cr, clearbits << shift, setbits << shift); +} + +/**************************************************************************** + * Name: tim_getreg + * + * Description: + * Read the value of an DMA timer register. + * + * Input Parameters: + * chan - A reference to the DAC 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(FAR struct stm32_chan_s *chan, int offset) +{ + return getreg32(chan->tbase + offset); +} +#endif + +/**************************************************************************** + * Name: tim_putreg + * + * Description: + * Read the value of an DMA timer register. + * + * Input Parameters: + * chan - A reference to the DAC block status + * offset - The offset to the register to read + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef HAVE_DMA +static void tim_putreg(FAR struct stm32_chan_s *chan, int offset, + uint32_t value) +{ + putreg32(value, chan->tbase + offset); +} +#endif + +/**************************************************************************** + * Name: tim_modifyreg + * + * Description: + * Modify the value of an DMA timer register. + * + * Input Parameters: + * priv - Driver state instance + * offset - The timer register offset + * clearbits - Bits in the control register to be cleared + * setbits - Bits in the control register to be set + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef HAVE_DMA +static void tim_modifyreg(FAR struct stm32_chan_s *chan, int offset, + uint32_t clearbits, uint32_t setbits) +{ + modifyreg32(chan->tbase + offset, clearbits, setbits); +} +#endif + +/**************************************************************************** + * Name: dac_reset + * + * Description: + * Reset the DAC channel. Called early to initialize the hardware. This + * is called, before dac_setup() and on error conditions. + * + * NOTE: DAC reset will reset both DAC channels! + * + * Input Parameters: + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void dac_reset(FAR struct dac_dev_s *dev) +{ + irqstate_t flags; + + /* Reset only the selected DAC channel; the other DAC channel must remain + * functional. + */ + + flags = enter_critical_section(); + +#warning "Missing logic" + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: dac_setup + * + * Description: + * Configure the DAC. This method is called the first time that the DAC + * device is opened. This will occur when the port is first opened. + * This setup includes configuring and attaching DAC interrupts. Interrupts + * are all disabled upon return. + * + * Input Parameters: + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int dac_setup(FAR struct dac_dev_s *dev) +{ + return OK; +} + +/**************************************************************************** + * Name: dac_shutdown + * + * Description: + * Disable the DAC. This method is called when the DAC device is closed. + * This method reverses the operation the setup method. + * + * Input Parameters: + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void dac_shutdown(FAR struct dac_dev_s *dev) +{ +#warning "Missing logic" +} + +/**************************************************************************** + * Name: dac_txint + * + * Description: + * Call to enable or disable TX interrupts. + * + * Input Parameters: + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void dac_txint(FAR struct dac_dev_s *dev, bool enable) +{ +#warning "Missing logic" +} + +/**************************************************************************** + * Name: dac_dmatxcallback + * + * Description: + * DMA callback function. + * + * Input Parameters: + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef HAVE_DMA +static void dac_dmatxcallback(DMA_HANDLE handle, uint8_t isr, FAR void *arg) +{ +} +#endif + +/**************************************************************************** + * Name: dac_send + * + * Description: + * Set the DAC output. + * + * Input Parameters: + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int dac_send(FAR struct dac_dev_s *dev, FAR struct dac_msg_s *msg) +{ + FAR struct stm32_chan_s *chan = dev->ad_priv; + + /* Enable DAC Channel */ + + stm32l4_dac_modify_cr(chan, 0, DAC_CR_EN); + +#ifdef HAVE_DMA + if (chan->hasdma) + { + /* Configure the DMA stream/channel. + * + * - Channel number + * - Peripheral address + * - Direction: Memory to peripheral + * - Disable peripheral address increment + * - Enable memory address increment + * - Peripheral data size: half word + * - Mode: circular??? + * - Priority: ? + * - FIFO mode: disable + * - FIFO threshold: half full + * - Memory Burst: single + * - Peripheral Burst: single + */ + + stm32l4_dmasetup(chan->dma, chan->dro, (uint32_t)chan->dmabuffer, + CONFIG_STM32L4_DAC_DMA_BUFFER_SIZE, DAC_DMA_CONTROL_WORD); + + /* Enable DMA */ + + stm32l4_dmastart(chan->dma, dac_dmatxcallback, chan, false); + + /* Enable DMA for DAC Channel */ + + stm32l4_dac_modify_cr(chan, 0, DAC_CR_DMAEN); + } + else +#endif + { + /* Non-DMA transfer */ + + putreg16(msg->am_data, chan->dro); + dac_txdone(dev); + } + + /* Reset counters (generate an update) */ + +#ifdef HAVE_DMA + tim_modifyreg(chan, STM32L4_BTIM_EGR_OFFSET, 0, ATIM_EGR_UG); +#endif + return OK; +} + +/**************************************************************************** + * Name: dac_ioctl + * + * Description: + * All ioctl calls will be routed through this method. + * + * Input Parameters: + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int dac_ioctl(FAR struct dac_dev_s *dev, int cmd, unsigned long arg) +{ + return -ENOTTY; +} + +/**************************************************************************** + * Name: dac_timinit + * + * Description: + * Initialize the timer that drivers the DAC DMA 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 HAVE_DMA +static int dac_timinit(FAR struct stm32_chan_s *chan) +{ + uint32_t pclk; + uint32_t prescaler; + uint32_t timclk; + uint32_t reload; + uint32_t regaddr; + uint32_t setbits; + + /* Configure the time base: Timer period, prescaler, clock division, + * counter mode (up). + */ + + /* Enable the timer. At most, two of the following cases (pluse the + * default) will be enabled + */ + + regaddr = STM32L4_RCC_APB1ENR1; + + switch (chan->timer) + { +#ifdef NEED_TIM2 + case 2: + setbits = RCC_APB1ENR1_TIM2EN; + pclk = BOARD_TIM2_FREQUENCY; + break; +#endif +#ifdef NEED_TIM3 + case 3: + setbits = RCC_APB1ENR1_TIM3EN; + pclk = BOARD_TIM3_FREQUENCY; + break; +#endif +#ifdef NEED_TIM4 + case 4: + setbits = RCC_APB1ENR1_TIM4EN; + pclk = BOARD_TIM4_FREQUENCY; + break; +#endif +#ifdef NEED_TIM5 + case 5: + setbits = RCC_APB1ENR1_TIM5EN; + pclk = BOARD_TIM5_FREQUENCY; + break; +#endif +#ifdef NEED_TIM6 + case 6: + setbits = RCC_APB1ENR1_TIM6EN; + pclk = BOARD_TIM6_FREQUENCY; + break; +#endif +#ifdef NEED_TIM7 + case 7: + setbits = RCC_APB1ENR1_TIM7EN; + pclk = BOARD_TIM7_FREQUENCY; + break; +#endif +#ifdef NEED_TIM8 + case 8: + regaddr = STM32L4_RCC_APB2ENR; + setbits = RCC_APB2ENR_TIM8EN; + pclk = BOARD_TIM8_FREQUENCY; + break; +#endif + default: + aerr("ERROR: Could not enable timer\n"); + return -EINVAL; + } + + /* Enable the timer. */ + + modifyreg32(regaddr, 0, setbits); + + /* 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 + */ + + prescaler = (pclk / chan->tfrequency + 65534) / 65535; + if (prescaler < 1) + { + prescaler = 1; + } + else if (prescaler > 65536) + { + prescaler = 65536; + } + + timclk = pclk / prescaler; + + reload = timclk / chan->tfrequency; + if (reload < 1) + { + reload = 1; + } + else if (reload > 65535) + { + reload = 65535; + } + + /* Set the reload and prescaler values */ + + tim_putreg(chan, STM32L4_BTIM_ARR_OFFSET, (uint16_t)reload); + tim_putreg(chan, STM32L4_BTIM_PSC_OFFSET, (uint16_t)(prescaler - 1)); + + /* Count mode up, auto reload */ + + tim_modifyreg(chan, STM32L4_BTIM_CR1_OFFSET, 0, ATIM_CR1_ARPE); + + /* Selection TRGO selection: update */ + + tim_modifyreg(chan, STM32L4_BTIM_CR2_OFFSET, ATIM_CR2_MMS_MASK, + ATIM_CR2_MMS_UPDATE); + + /* Update DMA request enable ???? */ +#if 0 + tim_modifyreg(chan, STM32L4_BTIM_DIER_OFFSET, 0, ATIM_DIER_UDE); +#endif + + /* Enable the counter */ + + tim_modifyreg(chan, STM32L4_BTIM_CR1_OFFSET, 0, ATIM_CR1_CEN); + return OK; +} +#endif + +/**************************************************************************** + * Name: dac_chaninit + * + * Description: + * Initialize the DAC channel. + * + * Input Parameters: + * chan - A reference to the DAC channel state data + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int dac_chaninit(FAR struct stm32_chan_s *chan) +{ + uint16_t clearbits; + uint16_t setbits; + + /* Is the selected channel already in-use? */ + + if (chan->inuse) + { + /* Yes.. then return EBUSY */ + + return -EBUSY; + } + + /* Configure the DAC output pin: + * + * DAC -" Once the DAC channelx is enabled, the corresponding GPIO pin + * (PA4 or PA5) is automatically connected to the analog converter output + * (DAC_OUTx). In order to avoid parasitic consumption, the PA4 or PA5 pin + * should first be configured to analog (AIN)". + */ + + stm32l4_configgpio(chan->pin); + + /* DAC channel configuration: + * + * - Set the trigger selection based upon the configuration. + * - Set wave generation == None. + * - Enable the output buffer. + */ + + /* Disable before change */ + + stm32l4_dac_modify_cr(chan, DAC_CR_EN, 0); + + clearbits = DAC_CR_TSEL_MASK | + DAC_CR_MAMP_MASK | + DAC_CR_WAVE_MASK; + 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 */ + stm32l4_dac_modify_cr(chan, clearbits, setbits); + + /* TODO: Enable output buffer? */ + +#ifdef HAVE_DMA + /* Determine if DMA is supported by this channel */ + + if (chan->hasdma) + { + int ret; + + /* Yes.. DAC trigger enable */ + + stm32l4_dac_modify_cr(chan, 0, DAC_CR_TEN); + + /* Allocate a DMA channel */ + + chan->dma = stm32l4_dmachannel(chan->dmachan); + if (!chan->dma) + { + aerr("ERROR: Failed to allocate a DMA channel\n"); + return -EBUSY; + } + + /* Configure the timer that supports the DMA operation */ + + ret = dac_timinit(chan); + if (ret < 0) + { + aerr("ERROR: Failed to initialize the DMA timer: %d\n", ret); + return ret; + } + } +#endif + + /* Mark the DAC channel "in-use" */ + + chan->inuse = 1; + return OK; +} + +/**************************************************************************** + * Name: dac_blockinit + * + * Description: + * Initialize the DAC block. + * + * Input Parameters: + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int dac_blockinit(void) +{ + irqstate_t flags; + uint32_t regval; + + /* Has the DAC block already been initialized? */ + + if (g_dacblock.init) + { + /* Yes.. then return success We only have to do this once */ + + return OK; + } + + /* 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; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32l4_dacinitialize + * + * Description: + * Initialize the DAC. + * + * Input Parameters: + * intf - The DAC interface number. + * + * Returned Value: + * Valid dac device structure reference on success; a NULL on failure. + * + * Assumptions: + * 1. Clock to the DAC block has enabled, + * 2. Board-specific logic has already configured + * + ****************************************************************************/ + +FAR struct dac_dev_s *stm32l4_dacinitialize(int intf) +{ + FAR struct dac_dev_s *dev; + FAR struct stm32_chan_s *chan; + int ret; + +#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; + } +#endif + else +#endif /* CONFIG_STM32L4_DAC1 */ +#ifdef CONFIG_STM32L4_DAC2 + if (intf == 2) + { + ainfo("DAC2-1 Selected\n"); + dev = &g_dac3dev; + } + else +#endif + { + 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; + } + + /* Configure the selected DAC channel */ + + chan = dev->ad_priv; + ret = dac_chaninit(chan); + if (ret < 0) + { + aerr("ERROR: Failed to initialize DAC channel %d: %d\n", intf, ret); + errno = -ret; + return NULL; + } + + return dev; +} + +#endif /* CONFIG_STM32L4_DAC1 || CONFIG_STM32L4_DAC2 */ +#endif /* CONFIG_DAC */ diff --git a/arch/arm/src/stm32l4/stm32l4_dac.h b/arch/arm/src/stm32l4/stm32l4_dac.h new file mode 100644 index 00000000000..19c8ad65c3a --- /dev/null +++ b/arch/arm/src/stm32l4/stm32l4_dac.h @@ -0,0 +1,131 @@ +/************************************************************************************ + * arch/arm/src/stm32l4/stm32l4_dac.h + * + * Copyright (C) 2011, 2015, 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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_STM32L4_STM32L4_DAC_H +#define __ARCH_ARM_SRC_STM32L4_STM32L4_DAC_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include "chip.h" +#include "chip/stm32l4_dac.h" + +#include + +/************************************************************************************ + * Pre-processor definitions + ************************************************************************************/ + +/* Configuration ********************************************************************/ +/* Timer devices may be used for different purposes. One special purpose is to + * control periodic DAC outputs. If CONFIG_STM32L4_TIMn is defined then + * CONFIG_STM32L4_TIMn_DAC must also be defined to indicate that timer "n" is + * intended to be used for that purpose. + */ + +#ifndef CONFIG_STM32L4_TIM1 +# undef CONFIG_STM32L4_TIM1_DAC +#endif +#ifndef CONFIG_STM32L4_TIM2 +# undef CONFIG_STM32L4_TIM2_DAC +#endif +#ifndef CONFIG_STM32L4_TIM3 +# undef CONFIG_STM32L4_TIM3_DAC +#endif +#ifndef CONFIG_STM32L4_TIM4 +# undef CONFIG_STM32L4_TIM4_DAC +#endif +#ifndef CONFIG_STM32L4_TIM5 +# undef CONFIG_STM32L4_TIM5_DAC +#endif +#ifndef CONFIG_STM32L4_TIM6 +# undef CONFIG_STM32L4_TIM6_DAC +#endif +#ifndef CONFIG_STM32L4_TIM7 +# undef CONFIG_STM32L4_TIM7_DAC +#endif +#ifndef CONFIG_STM32L4_TIM8 +# undef CONFIG_STM32L4_TIM8_DAC +#endif +#ifndef CONFIG_STM32L4_TIM15 +# undef CONFIG_STM32L4_TIM15_DAC +#endif +#ifndef CONFIG_STM32L4_TIM16 +# undef CONFIG_STM32L4_TIM16_DAC +#endif +#ifndef CONFIG_STM32L4_TIM17 +# undef CONFIG_STM32L4_TIM17_DAC +#endif + +/************************************************************************************ + * Public Function Prototypes + ************************************************************************************/ + +#ifndef __ASSEMBLY__ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: stm32l4_dacinitialize + * + * Description: + * Initialize the DAC + * + * Input Parameters: + * intf - The DAC interface number. + * + * Returned Value: + * Valid dac device structure reference on success; a NULL on failure + * + ****************************************************************************/ + +struct dac_dev_s; +FAR struct dac_dev_s *stm32l4_dacinitialize(int intf); + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif /* __ASSEMBLY__ */ + +#endif /* __ARCH_ARM_SRC_STM32L4_STM32L4_DAC_H */ diff --git a/arch/arm/src/stm32l4/stm32l4x3xx_rcc.c b/arch/arm/src/stm32l4/stm32l4x3xx_rcc.c index 855481df090..b54cde4f99f 100644 --- a/arch/arm/src/stm32l4/stm32l4x3xx_rcc.c +++ b/arch/arm/src/stm32l4/stm32l4x3xx_rcc.c @@ -369,7 +369,7 @@ static inline void rcc_enableapb1(void) #if defined (CONFIG_STM32L4_DAC1) || defined(CONFIG_STM32L4_DAC2) /* DAC interface clock enable */ - regval |= RCC_APB1ENR1_DACEN; + regval |= RCC_APB1ENR1_DAC1EN; #endif #ifdef CONFIG_STM32L4_OPAMP diff --git a/arch/arm/src/stm32l4/stm32l4x5xx_rcc.c b/arch/arm/src/stm32l4/stm32l4x5xx_rcc.c index 4f104f391a2..66c31fd387e 100644 --- a/arch/arm/src/stm32l4/stm32l4x5xx_rcc.c +++ b/arch/arm/src/stm32l4/stm32l4x5xx_rcc.c @@ -386,7 +386,7 @@ static inline void rcc_enableapb1(void) #if defined (CONFIG_STM32L4_DAC1) || defined(CONFIG_STM32L4_DAC2) /* DAC interface clock enable */ - regval |= RCC_APB1ENR1_DACEN; + regval |= RCC_APB1ENR1_DAC1EN; #endif #ifdef CONFIG_STM32L4_OPAMP diff --git a/arch/arm/src/stm32l4/stm32l4x6xx_rcc.c b/arch/arm/src/stm32l4/stm32l4x6xx_rcc.c index 08dd4f4b304..32562bbdbce 100644 --- a/arch/arm/src/stm32l4/stm32l4x6xx_rcc.c +++ b/arch/arm/src/stm32l4/stm32l4x6xx_rcc.c @@ -425,7 +425,7 @@ static inline void rcc_enableapb1(void) #if defined (CONFIG_STM32L4_DAC1) || defined(CONFIG_STM32L4_DAC2) /* DAC interface clock enable */ - regval |= RCC_APB1ENR1_DACEN; + regval |= RCC_APB1ENR1_DAC1EN; #endif #ifdef CONFIG_STM32L4_OPAMP