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:
Juha Niskanen 2017-08-29 17:53:49 +03:00
parent 91d473b816
commit 4025205772
5 changed files with 102 additions and 7 deletions

View File

@ -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 */

View File

@ -3271,6 +3271,13 @@ config STM32L4_DAC1_TIMER_FREQUENCY
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
@ -3296,8 +3303,16 @@ config STM32L4_DAC2_TIMER_FREQUENCY
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
int "DAC DMA buffer size"
depends on STM32L4_DAC1_DMA || STM32L4_DAC2_DMA
default 256
endmenu

View File

@ -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)

View File

@ -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;
}
}

View File

@ -266,7 +266,7 @@
# define DAC2_TSEL_VALUE DAC_CR_TSEL_SW
#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
#endif
@ -315,6 +315,7 @@ struct stm32_chan_s
uint32_t tbase; /* Timer base address */
uint32_t tfrequency; /* Timer frequency */
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 */
#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);
}
/****************************************************************************
* 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
*
@ -710,6 +743,18 @@ 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 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.
*
* - Channel number
@ -1001,7 +1046,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 */