Merged in juniskane/nuttx_stm32l4/dac_work2 (pull request #475)
Some STM32L4 DAC changes Approved-by: Gregory Nutt <gnutt@nuttx.org>
This commit is contained in:
commit
8b3555dac7
@ -157,7 +157,7 @@
|
||||
# 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_AMP1 (0 << DAC_CR_MAMP_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 */
|
||||
|
@ -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"
|
||||
@ -3254,7 +3259,7 @@ config STM32L4_DAC1_DMA
|
||||
---help---
|
||||
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 an EXTI trigger, but this feature is not currently
|
||||
supported by the driver.
|
||||
|
||||
if STM32L4_DAC1_DMA
|
||||
@ -3269,8 +3274,19 @@ config STM32L4_DAC1_TIMER_FREQUENCY
|
||||
---help---
|
||||
DAC1 output frequency. Default: 100Hz
|
||||
|
||||
config STM32L4_DAC1_DMA_BUFFER_SIZE
|
||||
int "DAC1 DMA buffer size"
|
||||
default 1
|
||||
|
||||
endif
|
||||
|
||||
config STM32L4_DAC1_OUTPUT_ADC
|
||||
bool "DAC1 output to ADC"
|
||||
depends on STM32L4_DAC1
|
||||
default n
|
||||
---help---
|
||||
Route DAC1 output to ADC input instead of external pin.
|
||||
|
||||
config STM32L4_DAC2_DMA
|
||||
bool "DAC2 DMA"
|
||||
depends on STM32L4_DAC2
|
||||
@ -3278,7 +3294,7 @@ config STM32L4_DAC2_DMA
|
||||
---help---
|
||||
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 an EXTI trigger, but this feature is not currently
|
||||
supported by the driver.
|
||||
|
||||
if STM32L4_DAC2_DMA
|
||||
@ -3294,11 +3310,18 @@ config STM32L4_DAC2_TIMER_FREQUENCY
|
||||
---help---
|
||||
DAC2 output frequency. Default: 100Hz
|
||||
|
||||
config STM32L4_DAC2_DMA_BUFFER_SIZE
|
||||
int "DAC2 DMA buffer size"
|
||||
default 1
|
||||
|
||||
endif
|
||||
|
||||
config STM32L4_DAC_DMA_BUFFER_SIZE
|
||||
int "DAC DMA buffer size"
|
||||
default 256
|
||||
config STM32L4_DAC2_OUTPUT_ADC
|
||||
bool "DAC2 output to ADC"
|
||||
depends on STM32L4_DAC2
|
||||
default n
|
||||
---help---
|
||||
Route DAC2 output to ADC input instead of external pin.
|
||||
|
||||
endmenu
|
||||
|
||||
|
@ -120,7 +120,7 @@
|
||||
# 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_AMP1 (0 << DAC_CR_MAMP_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 */
|
||||
@ -291,6 +291,16 @@
|
||||
|
||||
#define DAC_MCR_MODE_SHIFT(n) (((n)-1) << 4)
|
||||
#define DAC_MCR_MODE_MASK(n) (0x7 << DAC_MCR_MODE_SHIFT(n))
|
||||
/* DAC channel in normal mode: */
|
||||
# define DAC_MCR_MODE_EXTBUF (0) /* DAC channel connected to external pin, Buffer enabled */
|
||||
# define DAC_MCR_MODE_EXTINBUF (1) /* DAC channel connected to external pin, on-chip peripherals, Buffer enabled */
|
||||
# define DAC_MCR_MODE_EXT (2) /* DAC channel connected to external pin, Buffer disabled */
|
||||
# define DAC_MCR_MODE_IN (3) /* DAC channel connected to on-chip peripherals, Buffer disabled */
|
||||
/* DAC channel in Sample and Hold mode: */
|
||||
# define DAC_MCR_MODE_SHEXTBUF (4) /* DAC channel connected to external pin, Buffer enabled */
|
||||
# define DAC_MCR_MODE_SHEXTINBUF (5) /* DAC channel connected to external pin, on-chip peripherals, Buffer enabled */
|
||||
# define DAC_MCR_MODE_SHEXTIN (6) /* DAC channel connected to external pin, on-chip peripherals, Buffer disabled */
|
||||
# define DAC_MCR_MODE_SHIN (7) /* DAC channel connected to on-chip peripherals, Buffer disabled */
|
||||
|
||||
#define DAC_MCR_MODE1_SHIFT (0) /* Bits 0-2: DAC channel 1 mode */
|
||||
#define DAC_MCR_MODE1_MASK (0x7 << DAC_MCR_MODE1_SHIFT)
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -1253,8 +1253,9 @@ static int adc_setup(FAR struct adc_dev_s *dev)
|
||||
ADC_CCR_TSEN | ADC_CCR_VBATEN;
|
||||
setbits = ADC_CCR_PRESC_NOT_DIV;
|
||||
|
||||
/* REVISIT: there is no way to select DAC1 or DAC2 output here on
|
||||
* STM32L4X3 devices where they are multiplexed with ADC1 TSEN and VBAT.
|
||||
/* On STM32L4X3 devices DAC1 and DAC2 outputs are multiplexed with ADC1 TS and VBAT.
|
||||
* adc_internal() knows about this and does not set TSEN or VBATEN bits if configuration
|
||||
* has requested DAC output to be connected to ADC.
|
||||
*/
|
||||
|
||||
adc_internal(priv, &setbits);
|
||||
@ -1434,11 +1435,14 @@ static bool adc_internal(FAR struct stm32_dev_s * priv, uint32_t *adc_ccr)
|
||||
break;
|
||||
|
||||
case 17:
|
||||
#if !(defined(CONFIG_STM32L4_STM32L4X3) && defined(CONFIG_STM32L4_DAC1_OUTPUT_ADC))
|
||||
*adc_ccr |= ADC_CCR_TSEN;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 18:
|
||||
#if !(defined(CONFIG_STM32L4_STM32L4X3) && defined(CONFIG_STM32L4_DAC2_OUTPUT_ADC))
|
||||
*adc_ccr |= ADC_CCR_VBATEN;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -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,21 +91,16 @@
|
||||
|
||||
/* 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
|
||||
/* 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
|
||||
* supported by the driver.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_STM32L4_DAC1_DMA
|
||||
# if !defined(CONFIG_STM32L4_DAC1_DMA_BUFFER_SIZE) || CONFIG_STM32L4_DAC1_DMA_BUFFER_SIZE < 1
|
||||
# define CONFIG_STM32L4_DAC1_DMA_BUFFER_SIZE 1
|
||||
# endif
|
||||
# if !defined(CONFIG_STM32L4_DAC1_TIMER)
|
||||
# warning "A timer number must be specified in CONFIG_STM32L4_DAC1_TIMER"
|
||||
# undef CONFIG_STM32L4_DAC1_DMA
|
||||
@ -115,6 +114,9 @@
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32L4_DAC2_DMA
|
||||
# if !defined(CONFIG_STM32L4_DAC2_DMA_BUFFER_SIZE) || CONFIG_STM32L4_DAC2_DMA_BUFFER_SIZE < 1
|
||||
# define CONFIG_STM32L4_DAC2_DMA_BUFFER_SIZE 1
|
||||
# endif
|
||||
# if !defined(CONFIG_STM32L4_DAC2_TIMER)
|
||||
# warning "A timer number must be specified in CONFIG_STM32L4_DAC2_TIMER"
|
||||
# undef CONFIG_STM32L4_DAC2_DMA
|
||||
@ -127,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:
|
||||
@ -266,10 +281,6 @@
|
||||
# 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_STM32L4_DACn_TIMER_FREQUENCY.
|
||||
*/
|
||||
@ -311,11 +322,13 @@ struct stm32_chan_s
|
||||
uint32_t tsel; /* CR trigger select value */
|
||||
#ifdef HAVE_DMA
|
||||
uint16_t dmachan; /* DMA channel needed by this DAC */
|
||||
uint16_t buffer_len; /* DMA buffer length */
|
||||
DMA_HANDLE dma; /* Allocated DMA channel */
|
||||
uint32_t tbase; /* Timer base address */
|
||||
uint32_t tfrequency; /* Timer frequency */
|
||||
int result; /* DMA result */
|
||||
uint16_t dmabuffer[CONFIG_STM32L4_DAC_DMA_BUFFER_SIZE]; /* DMA transfer buffer */
|
||||
uint16_t buffer_pos; /* Position in dmabuffer where to write new value */
|
||||
uint16_t *dmabuffer; /* DMA transfer buffer */
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -347,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
|
||||
@ -366,21 +379,21 @@ static const struct dac_ops_s g_dacops =
|
||||
#ifdef CONFIG_STM32L4_DAC1
|
||||
/* Channel 1 */
|
||||
|
||||
#ifdef CONFIG_STM32L4_DAC1_DMA
|
||||
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 = stm32l4_dac1_dmabuffer,
|
||||
.timer = CONFIG_STM32L4_DAC1_TIMER,
|
||||
.tsel = DAC1_TSEL_VALUE,
|
||||
.tbase = DAC1_TIMER_BASE,
|
||||
@ -394,26 +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
|
||||
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 = stm32l4_dac2_dmabuffer,
|
||||
.timer = CONFIG_STM32L4_DAC2_TIMER,
|
||||
.tsel = DAC2_TSEL_VALUE,
|
||||
.tbase = DAC2_TIMER_BASE,
|
||||
@ -426,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;
|
||||
|
||||
@ -475,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
|
||||
@ -488,6 +482,38 @@ static inline void stm32l4_dac_modify_cr(FAR struct stm32_chan_s *chan,
|
||||
modifyreg32(chan->cr, clearbits << shift, setbits << shift);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32l4_dac_modify_mcr
|
||||
*
|
||||
* Description:
|
||||
* Modify the contents of the DAC mode register.
|
||||
*
|
||||
* Input Parameters:
|
||||
* chan - A reference to the DAC channel state data
|
||||
* 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_mcr(FAR struct stm32_chan_s *chan,
|
||||
uint32_t clearbits, uint32_t setbits)
|
||||
{
|
||||
unsigned int shift;
|
||||
|
||||
/* 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
|
||||
* Bit 0 = 1: Shift = 16
|
||||
*/
|
||||
|
||||
shift = (chan->intf & 1) << 4;
|
||||
modifyreg32(STM32L4_DAC_MCR, clearbits << shift, setbits << shift);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tim_putreg
|
||||
*
|
||||
@ -646,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);
|
||||
@ -710,6 +729,19 @@ static int dac_send(FAR struct dac_dev_s *dev, FAR struct dac_msg_s *msg)
|
||||
#ifdef HAVE_DMA
|
||||
if (chan->hasdma)
|
||||
{
|
||||
/* Copy the value to circular buffer. Since dmabuffer is initialized to zero,
|
||||
* writing e.g. monotonously increasing values creates a continuosly repeating
|
||||
* ramp-effect, alternating with periods of zero output.
|
||||
*
|
||||
* 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;
|
||||
chan->buffer_pos = (chan->buffer_pos + 1) % chan->buffer_len;
|
||||
|
||||
/* Configure the DMA stream/channel.
|
||||
*
|
||||
* - Channel number
|
||||
@ -727,7 +759,7 @@ static int dac_send(FAR struct dac_dev_s *dev, FAR struct dac_msg_s *msg)
|
||||
*/
|
||||
|
||||
stm32l4_dmasetup(chan->dma, chan->dro, (uint32_t)chan->dmabuffer,
|
||||
CONFIG_STM32L4_DAC_DMA_BUFFER_SIZE, DAC_DMA_CONTROL_WORD);
|
||||
chan->buffer_len, DAC_DMA_CONTROL_WORD);
|
||||
|
||||
/* Start the DMA */
|
||||
|
||||
@ -1001,7 +1033,28 @@ static int dac_chaninit(FAR struct stm32_chan_s *chan)
|
||||
DAC_CR_WAVE_DISABLED; /* Set no noise */
|
||||
stm32l4_dac_modify_cr(chan, clearbits, setbits);
|
||||
|
||||
/* TODO: Enable output buffer? */
|
||||
/* Enable output buffer or route DAC output to on-chip peripherals (ADC) */
|
||||
|
||||
clearbits = DAC_MCR_MODE1_MASK;
|
||||
#if defined(CONFIG_STM32L4_DAC1_OUTPUT_ADC)
|
||||
if (chan->intf == 0)
|
||||
{
|
||||
setbits = DAC_MCR_MODE_IN;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#if defined(CONFIG_STM32L4_DAC2_OUTPUT_ADC)
|
||||
if (chan->intf == 1)
|
||||
{
|
||||
setbits = DAC_MCR_MODE_IN;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
setbits = DAC_MCR_MODE_EXTBUF;
|
||||
}
|
||||
|
||||
stm32l4_dac_modify_mcr(chan, clearbits, setbits);
|
||||
|
||||
#ifdef HAVE_DMA
|
||||
/* Determine if DMA is supported by this channel */
|
||||
@ -1050,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;
|
||||
@ -1063,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;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -1133,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 */
|
||||
|
||||
|
@ -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
|
||||
************************************************************************************/
|
||||
|
@ -194,6 +194,25 @@
|
||||
|
||||
#endif
|
||||
|
||||
/* Timer Frequencies, if APBx is set to 1, frequency is same to APBx
|
||||
* otherwise frequency is 2xAPBx.
|
||||
* Note: TIM1,8,15,16,17 are on APB2, others on APB1
|
||||
*/
|
||||
|
||||
#define BOARD_TIM1_FREQUENCY STM32L4_HCLK_FREQUENCY
|
||||
#define BOARD_TIM2_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2)
|
||||
#define BOARD_TIM3_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2)
|
||||
#define BOARD_TIM4_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2)
|
||||
#define BOARD_TIM5_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2)
|
||||
#define BOARD_TIM6_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2)
|
||||
#define BOARD_TIM7_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2)
|
||||
#define BOARD_TIM8_FREQUENCY STM32L4_HCLK_FREQUENCY
|
||||
#define BOARD_TIM15_FREQUENCY STM32L4_HCLK_FREQUENCY
|
||||
#define BOARD_TIM16_FREQUENCY STM32L4_HCLK_FREQUENCY
|
||||
#define BOARD_TIM17_FREQUENCY STM32L4_HCLK_FREQUENCY
|
||||
#define BOARD_LPTIM1_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2)
|
||||
#define BOARD_LPTIM2_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2)
|
||||
|
||||
/* SDMMC dividers. Note that slower clocking is required when DMA is disabled
|
||||
* in order to avoid RX overrun/TX underrun errors due to delayed responses
|
||||
* to service FIFOs in interrupt driven mode. These values have not been
|
||||
|
@ -61,6 +61,10 @@ ifeq ($(CONFIG_ADC),y)
|
||||
CSRCS += stm32_adc.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_DAC),y)
|
||||
CSRCS += stm32_dac.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_MMCSD),y)
|
||||
CSRCS += stm32_sdio.c
|
||||
endif
|
||||
|
@ -281,5 +281,17 @@ void stm32_usbinitialize(void);
|
||||
int stm32_adc_setup(void);
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
* Name: stm32_dac_setup
|
||||
*
|
||||
* Description:
|
||||
* Initialize DAC and register the DAC driver.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#ifdef CONFIG_DAC
|
||||
int stm32_dac_setup(void);
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __CONFIGS_NUCLEO_L496ZG_SRC_NUCLEO_144_H */
|
||||
|
@ -132,6 +132,16 @@ int board_app_initialize(uintptr_t arg)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DAC
|
||||
/* Initialize DAC and register the DAC driver. */
|
||||
|
||||
ret = stm32_dac_setup();
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: stm32_dac_setup failed: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_FAT_DMAMEMORY)
|
||||
if (stm32_dma_alloc_init() < 0)
|
||||
{
|
||||
|
117
configs/nucleo-l496zg/src/stm32_dac.c
Normal file
117
configs/nucleo-l496zg/src/stm32_dac.c
Normal file
@ -0,0 +1,117 @@
|
||||
/*****************************************************************************
|
||||
* configs/nucleo-l496zg/src/stm32_dac.c
|
||||
*
|
||||
* Copyright (C) 2017 Haltian Ltd. All rights reserved.
|
||||
* Authors: Juha Niskanen <juha.niskanen@haltian.com>
|
||||
*
|
||||
* 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 <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/board.h>
|
||||
#include <nuttx/analog/dac.h>
|
||||
#include <arch/board/board.h>
|
||||
#include "stm32l4_gpio.h"
|
||||
#include "stm32l4_dac.h"
|
||||
#include "nucleo-144.h"
|
||||
|
||||
#ifdef CONFIG_DAC
|
||||
|
||||
/************************************************************************************
|
||||
* Private Data
|
||||
************************************************************************************/
|
||||
|
||||
#ifdef CONFIG_STM32L4_DAC1
|
||||
static struct dac_dev_s *g_dac1;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32L4_DAC2
|
||||
static struct dac_dev_s *g_dac2;
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
* Public Functions
|
||||
************************************************************************************/
|
||||
|
||||
/************************************************************************************
|
||||
* Name: stm32_dac_setup
|
||||
************************************************************************************/
|
||||
|
||||
int stm32_dac_setup(void)
|
||||
{
|
||||
static bool initialized = false;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
int ret;
|
||||
|
||||
#ifdef CONFIG_STM32L4_DAC1
|
||||
g_dac1 = stm32l4_dacinitialize(0);
|
||||
if (g_dac1 == NULL)
|
||||
{
|
||||
aerr("ERROR: Failed to get DAC1 interface\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = dac_register("/dev/dac0", g_dac1);
|
||||
if (ret < 0)
|
||||
{
|
||||
aerr("ERROR: dac_register failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_STM32L4_DAC2
|
||||
g_dac2 = stm32l4_dacinitialize(1);
|
||||
if (g_dac2 == NULL)
|
||||
{
|
||||
aerr("ERROR: Failed to get DAC2 interface\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = dac_register("/dev/dac1", g_dac2);
|
||||
if (ret < 0)
|
||||
{
|
||||
aerr("ERROR: dac_register failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
UNUSED(ret);
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
#endif /* CONFIG_DAC */
|
Loading…
Reference in New Issue
Block a user