STM32L4 DAC: Added basic support for low level operations

This commit is contained in:
Daniel P. Carvalho 2022-07-22 17:00:33 -03:00 committed by Xiang Xiao
parent 7e6b4f6e07
commit 40e6c8dca4
3 changed files with 244 additions and 0 deletions

View File

@ -5473,6 +5473,12 @@ config STM32L4_DAC2_OUTPUT_ADC
---help---
Route DAC2 output to ADC input instead of external pin.
config STM32L4_DAC_LL_OPS
bool "DAC low-level operations"
default n
---help---
Enable low-level DAC ops.
endmenu
menu "DFSDM Configuration"

View File

@ -305,6 +305,9 @@ struct stm32_dac_s
struct stm32_chan_s
{
#ifdef CONFIG_STM32L4_DAC_LL_OPS
const struct stm32_dac_ops_s *llops; /* Low-level DAC ops */
#endif
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 */
@ -333,6 +336,9 @@ struct stm32_chan_s
/* DAC Register access */
static uint32_t dac_getreg(struct stm32_chan_s *priv, int offset);
static void dac_dumpregs(struct stm32_chan_s *priv);
#ifdef HAVE_DMA
static inline void tim_putreg(struct stm32_chan_s *chan, int offset,
uint32_t value);
@ -357,6 +363,16 @@ static int dac_timinit(struct stm32_chan_s *chan);
static int dac_chaninit(struct stm32_chan_s *chan);
static void dac_blockinit(void);
#ifdef CONFIG_STM32L4_DAC_LL_OPS
static void dac_llops_enable(struct stm32_dac_dev_s *dev, bool enabled);
static void dac_llops_writedro(struct stm32_dac_dev_s *dev, uint16_t data);
#ifdef HAVE_DMA
static void dac_llops_startdma(struct stm32_dac_dev_s *dev);
static void dac_llops_stopdma(struct stm32_dac_dev_s *dev);
#endif
static void dac_llops_dumpregs(struct stm32_dac_dev_s *dev);
#endif /* CONFIG_STM32L4_DAC_LL_OPS */
/****************************************************************************
* Private Data
****************************************************************************/
@ -371,6 +387,21 @@ static const struct dac_ops_s g_dacops =
.ao_ioctl = dac_ioctl,
};
/* Publicly visible DAC lower-half operations */
#ifdef CONFIG_STM32L4_DAC_LL_OPS
static const struct stm32_dac_ops_s g_dac_llops =
{
.enable = dac_llops_enable,
.write_dro = dac_llops_writedro,
#ifdef HAVE_DMA
.start_dma = dac_llops_startdma,
.stop_dma = dac_llops_stopdma,
#endif
.dump_regs = dac_llops_dumpregs
};
#endif /* CONFIG_STM32L4_DAC_LL_OPS */
#ifdef CONFIG_STM32L4_DAC1
/* Channel 1 */
@ -380,6 +411,9 @@ uint16_t stm32l4_dac1_dmabuffer[CONFIG_STM32L4_DAC1_DMA_BUFFER_SIZE];
static struct stm32_chan_s g_dac1priv =
{
#ifdef CONFIG_STM32L4_DAC_LL_OPS
.llops = &g_dac_llops,
#endif
.intf = 0,
#ifdef CONFIG_STM32L4_DAC1_OUTPUT_ADC
.pin = 0xffffffffu,
@ -417,6 +451,9 @@ uint16_t stm32l4_dac2_dmabuffer[CONFIG_STM32L4_DAC2_DMA_BUFFER_SIZE];
static struct stm32_chan_s g_dac2priv =
{
#ifdef CONFIG_STM32L4_DAC_LL_OPS
.llops = &g_dac_llops,
#endif
.intf = 1,
#ifdef CONFIG_STM32L4_DAC2_OUTPUT_ADC
.pin = 0xffffffffu,
@ -451,6 +488,26 @@ static struct stm32_dac_s g_dacblock;
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: dac_getreg
*
* Description:
* Read the value of an DAC register.
*
* Input Parameters:
* priv - A reference to the DAC block status
* offset - The offset to the register to read
*
* Returned Value:
* The current contents of the specified register
*
****************************************************************************/
static uint32_t dac_getreg(struct stm32_chan_s *priv, int offset)
{
return getreg32(STM32L4_DAC_BASE + offset);
}
/****************************************************************************
* Name: stm32l4_dac_modify_cr
*
@ -519,6 +576,22 @@ static inline void stm32l4_dac_modify_mcr(struct stm32_chan_s *chan,
modifyreg32(STM32L4_DAC_MCR, clearbits << shift, setbits << shift);
}
/****************************************************************************
* Name: dac_dumpregs
****************************************************************************/
static void dac_dumpregs(struct stm32_chan_s *priv)
{
UNUSED(priv);
ainfo("CR: 0x%08" PRIx32 " SWTRGR: 0x%08" PRIx32
"SR: 0x%08" PRIx32 " MCR: 0x%08" PRIx32 "\n",
dac_getreg(priv, STM32L4_DAC_CR_OFFSET),
dac_getreg(priv, STM32L4_DAC_SWTRIGR_OFFSET),
dac_getreg(priv, STM32L4_DAC_SR_OFFSET),
dac_getreg(priv, STM32L4_DAC_MCR_OFFSET));
}
/****************************************************************************
* Name: tim_putreg
*
@ -1140,6 +1213,112 @@ static void dac_blockinit(void)
g_dacblock.init = 1;
}
#ifdef CONFIG_STM32L4_DAC_LL_OPS
/****************************************************************************
* Name: dac_llops_enable
****************************************************************************/
static void dac_llops_enable(struct stm32_dac_dev_s *dev, bool enabled)
{
struct stm32_chan_s *priv = (struct stm32_chan_s *)dev;
/* Enable/disable DAC Channel */
if (enabled)
{
stm32l4_dac_modify_cr(priv, 0, DAC_CR_EN);
}
else
{
stm32l4_dac_modify_cr(priv, DAC_CR_EN, 0);
}
}
/****************************************************************************
* Name: dac_llops_writedro
****************************************************************************/
static void dac_llops_writedro(struct stm32_dac_dev_s *dev, uint16_t data)
{
struct stm32_chan_s *priv = (struct stm32_chan_s *)dev;
putreg16(data, priv->dro);
}
/****************************************************************************
* Name: dac_llops_startdma
****************************************************************************/
#ifdef HAVE_DMA
static void dac_llops_startdma(struct stm32_dac_dev_s *dev)
{
struct stm32_chan_s *priv = (struct stm32_chan_s *)dev;
/* 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(priv->dma, priv->dro, (uint32_t)priv->dmabuffer,
priv->buffer_len, DAC_DMA_CONTROL_WORD);
/* Start the DMA */
priv->result = -EBUSY;
stm32l4_dmastart(priv->dma, dac_dmatxcallback, priv, false);
/* Enable DMA for DAC Channel */
stm32l4_dac_modify_cr(priv, 0, DAC_CR_DMAEN);
/* Reset counters (generate an update) */
tim_modifyreg(priv, STM32L4_GTIM_EGR_OFFSET, 0, GTIM_EGR_UG);
}
/****************************************************************************
* Name: dac_llops_stopdma
****************************************************************************/
static void dac_llops_stopdma(struct stm32_dac_dev_s *dev)
{
struct stm32_chan_s *priv = (struct stm32_chan_s *)dev;
/* Stop the DMA */
priv->result = -EBUSY;
stm32l4_dmastop(priv->dma);
/* Enable DMA for DAC Channel */
stm32l4_dac_modify_cr(priv, 0, DAC_CR_DMAEN);
}
#endif
/****************************************************************************
* Name: adc_llops_dumpregs
****************************************************************************/
static void dac_llops_dumpregs(struct stm32_dac_dev_s *dev)
{
struct stm32_chan_s *priv = (struct stm32_chan_s *)dev;
dac_dumpregs(priv);
}
#endif /* CONFIG_STM32L4_DAC_LL_OPS */
/****************************************************************************
* Public Functions
****************************************************************************/

View File

@ -78,6 +78,65 @@
# undef CONFIG_STM32L4_TIM17_DAC
#endif
/* Low-level ops helpers ****************************************************/
#define DAC_ENABLE(dac,d) \
(dac)->llops->enable(dac,d)
#define DAC_WRITE_DRO(dac,d) \
(dac)->llops->write_dro(dac,d)
#define DAC_START_DMA(dac) \
(dac)->llops->start_dma(dac)
#define DAC_STOP_DMA(dac) \
(dac)->llops->stop_dma(dac)
#define DAC_DUMP_REGS(dac) \
(dac)->llops->dump_regs(dac)
/****************************************************************************
* Public Types
****************************************************************************/
#ifdef CONFIG_STM32L4_DAC_LL_OPS
/* This structure provides the publicly visible representation of the
* "lower-half" DAC driver structure.
*/
struct stm32_dac_dev_s
{
/* Publicly visible portion of the "lower-half" ADC driver structure */
const struct stm32_dac_ops_s *llops;
/* Require cast-compatibility with private "lower-half" ADC structure */
};
/* Low-level operations for DAC */
struct stm32_dac_ops_s
{
/* Enable / Disable DAC */
void (*enable)(struct stm32_dac_dev_s *dev, bool enabled);
/* Write DRO */
void (*write_dro)(struct stm32_dac_dev_s *dev, uint16_t data);
/* Start DMA */
void (*start_dma)(struct stm32_dac_dev_s *dev);
/* Stop DMA */
void (*stop_dma)(struct stm32_dac_dev_s *dev);
/* Dump DAC regs */
void (*dump_regs)(struct stm32_dac_dev_s *dev);
};
#endif /* CONFIG_STM32L4_DAC_LL_OPS */
/****************************************************************************
* Public Data
****************************************************************************/