mirror of
https://github.com/apache/nuttx.git
synced 2026-05-28 03:45:50 +08:00
STM32L4 DAC: add option for routing DAC output to ADC
Actually write something to the DAC DMA buffer. Change-Id: I1b2516ac26fb17f5242611b56be8926c5f40c2c7 Signed-off-by: Juha Niskanen <juha.niskanen@haltian.com>
This commit is contained in:
@@ -157,7 +157,7 @@
|
|||||||
# define DAC_CR_WAVE_TRIANGLE (2 << DAC_CR_WAVE_SHIFT) /* Triangle 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_SHIFT (8) /* Bits 8-11: DAC channel mask/amplitude selector */
|
||||||
#define DAC_CR_MAMP_MASK (15 << DAC_CR_MAMP_SHIFT)
|
#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_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_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_AMP15 (3 << DAC_CR_MAMP_SHIFT) /* Unmask bits[3:0] of LFSR/triangle amplitude=15 */
|
||||||
|
|||||||
@@ -3271,6 +3271,13 @@ config STM32L4_DAC1_TIMER_FREQUENCY
|
|||||||
|
|
||||||
endif
|
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
|
config STM32L4_DAC2_DMA
|
||||||
bool "DAC2 DMA"
|
bool "DAC2 DMA"
|
||||||
depends on STM32L4_DAC2
|
depends on STM32L4_DAC2
|
||||||
@@ -3296,8 +3303,16 @@ config STM32L4_DAC2_TIMER_FREQUENCY
|
|||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
config STM32L4_DAC_DMA_BUFFER_SIZE
|
config STM32L4_DAC_DMA_BUFFER_SIZE
|
||||||
int "DAC DMA buffer size"
|
int "DAC DMA buffer size"
|
||||||
|
depends on STM32L4_DAC1_DMA || STM32L4_DAC2_DMA
|
||||||
default 256
|
default 256
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|||||||
@@ -120,7 +120,7 @@
|
|||||||
# define DAC_CR_WAVE_TRIANGLE (2 << DAC_CR_WAVE_SHIFT) /* Triangle 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_SHIFT (8) /* Bits 8-11: DAC channel mask/amplitude selector */
|
||||||
#define DAC_CR_MAMP_MASK (15 << DAC_CR_MAMP_SHIFT)
|
#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_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_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_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_SHIFT(n) (((n)-1) << 4)
|
||||||
#define DAC_MCR_MODE_MASK(n) (0x7 << DAC_MCR_MODE_SHIFT(n))
|
#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_SHIFT (0) /* Bits 0-2: DAC channel 1 mode */
|
||||||
#define DAC_MCR_MODE1_MASK (0x7 << DAC_MCR_MODE1_SHIFT)
|
#define DAC_MCR_MODE1_MASK (0x7 << DAC_MCR_MODE1_SHIFT)
|
||||||
|
|||||||
@@ -1253,8 +1253,9 @@ static int adc_setup(FAR struct adc_dev_s *dev)
|
|||||||
ADC_CCR_TSEN | ADC_CCR_VBATEN;
|
ADC_CCR_TSEN | ADC_CCR_VBATEN;
|
||||||
setbits = ADC_CCR_PRESC_NOT_DIV;
|
setbits = ADC_CCR_PRESC_NOT_DIV;
|
||||||
|
|
||||||
/* REVISIT: there is no way to select DAC1 or DAC2 output here on
|
/* On STM32L4X3 devices DAC1 and DAC2 outputs are multiplexed with ADC1 TS and VBAT.
|
||||||
* STM32L4X3 devices where they are multiplexed with ADC1 TSEN 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);
|
adc_internal(priv, &setbits);
|
||||||
@@ -1434,11 +1435,14 @@ static bool adc_internal(FAR struct stm32_dev_s * priv, uint32_t *adc_ccr)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 17:
|
case 17:
|
||||||
|
#if !(defined(CONFIG_STM32L4_STM32L4X3) && defined(CONFIG_STM32L4_DAC1_OUTPUT_ADC))
|
||||||
*adc_ccr |= ADC_CCR_TSEN;
|
*adc_ccr |= ADC_CCR_TSEN;
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 18:
|
case 18:
|
||||||
|
#if !(defined(CONFIG_STM32L4_STM32L4X3) && defined(CONFIG_STM32L4_DAC2_OUTPUT_ADC))
|
||||||
*adc_ccr |= ADC_CCR_VBATEN;
|
*adc_ccr |= ADC_CCR_VBATEN;
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -266,7 +266,7 @@
|
|||||||
# define DAC2_TSEL_VALUE DAC_CR_TSEL_SW
|
# define DAC2_TSEL_VALUE DAC_CR_TSEL_SW
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_STM32L4_DAC_DMA_BUFFER_SIZE
|
#if !defined(CONFIG_STM32L4_DAC_DMA_BUFFER_SIZE) || CONFIG_STM32L4_DAC_DMA_BUFFER_SIZE < 1
|
||||||
# define CONFIG_STM32L4_DAC_DMA_BUFFER_SIZE 256
|
# define CONFIG_STM32L4_DAC_DMA_BUFFER_SIZE 256
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -315,6 +315,7 @@ struct stm32_chan_s
|
|||||||
uint32_t tbase; /* Timer base address */
|
uint32_t tbase; /* Timer base address */
|
||||||
uint32_t tfrequency; /* Timer frequency */
|
uint32_t tfrequency; /* Timer frequency */
|
||||||
int result; /* DMA result */
|
int result; /* DMA result */
|
||||||
|
uint16_t dmapos; /* Position in dmabuffer where to write new value */
|
||||||
uint16_t dmabuffer[CONFIG_STM32L4_DAC_DMA_BUFFER_SIZE]; /* DMA transfer buffer */
|
uint16_t dmabuffer[CONFIG_STM32L4_DAC_DMA_BUFFER_SIZE]; /* DMA transfer buffer */
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
@@ -488,6 +489,38 @@ static inline void stm32l4_dac_modify_cr(FAR struct stm32_chan_s *chan,
|
|||||||
modifyreg32(chan->cr, clearbits << shift, setbits << shift);
|
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;
|
||||||
|
|
||||||
|
/* DAC1 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
|
* Name: tim_putreg
|
||||||
*
|
*
|
||||||
@@ -710,6 +743,18 @@ static int dac_send(FAR struct dac_dev_s *dev, FAR struct dac_msg_s *msg)
|
|||||||
#ifdef HAVE_DMA
|
#ifdef HAVE_DMA
|
||||||
if (chan->hasdma)
|
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 would be better to initialize dmabuffer with desired pattern
|
||||||
|
* beforehand. If want to write just one value at a time with DMA, set
|
||||||
|
* CONFIG_STM32L4_DAC_DMA_BUFFER_SIZE to 1.
|
||||||
|
*/
|
||||||
|
|
||||||
|
chan->dmabuffer[chan->dmapos] = (uint16_t)msg->am_data;
|
||||||
|
chan->dmapos = (chan->dmapos + 1) % CONFIG_STM32L4_DAC_DMA_BUFFER_SIZE;
|
||||||
|
|
||||||
/* Configure the DMA stream/channel.
|
/* Configure the DMA stream/channel.
|
||||||
*
|
*
|
||||||
* - Channel number
|
* - Channel number
|
||||||
@@ -1001,7 +1046,28 @@ static int dac_chaninit(FAR struct stm32_chan_s *chan)
|
|||||||
DAC_CR_WAVE_DISABLED; /* Set no noise */
|
DAC_CR_WAVE_DISABLED; /* Set no noise */
|
||||||
stm32l4_dac_modify_cr(chan, clearbits, setbits);
|
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
|
#ifdef HAVE_DMA
|
||||||
/* Determine if DMA is supported by this channel */
|
/* Determine if DMA is supported by this channel */
|
||||||
|
|||||||
Reference in New Issue
Block a user