diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-12-15 16:39:06 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-12-15 16:39:06 +0000 |
commit | 35efe997b4ea5352c341b8a1e8661ac83d1bc5ae (patch) | |
tree | 6f95e16854e297c82ed428daed9959ac41f5d86e /nuttx/arch/arm/src/stm32/stm32_dac.c | |
parent | 27c16edcc1befe9afeb4a1996c3b22bc9acd8380 (diff) | |
download | px4-nuttx-35efe997b4ea5352c341b8a1e8661ac83d1bc5ae.tar.gz px4-nuttx-35efe997b4ea5352c341b8a1e8661ac83d1bc5ae.tar.bz2 px4-nuttx-35efe997b4ea5352c341b8a1e8661ac83d1bc5ae.zip |
More STM32 DAC driver logic
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4186 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/arch/arm/src/stm32/stm32_dac.c')
-rw-r--r-- | nuttx/arch/arm/src/stm32/stm32_dac.c | 248 |
1 files changed, 236 insertions, 12 deletions
diff --git a/nuttx/arch/arm/src/stm32/stm32_dac.c b/nuttx/arch/arm/src/stm32/stm32_dac.c index a7d46707c..09cdb76f1 100644 --- a/nuttx/arch/arm/src/stm32/stm32_dac.c +++ b/nuttx/arch/arm/src/stm32/stm32_dac.c @@ -61,9 +61,8 @@ #ifdef CONFIG_DAC /**************************************************************************** - * Private Types + * Pre-processor Definitions ****************************************************************************/ - /* Configuration ************************************************************/ /* Up to 2 DAC interfaces are supported */ @@ -78,8 +77,32 @@ #if defined(CONFIG_STM32_DAC1) || defined(CONFIG_STM32_DAC2) /**************************************************************************** + * 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 */ + uint8_t intf; /* DAC zero-based interface number (0 or 1) */ +}; + +/**************************************************************************** * Private Function Prototypes ****************************************************************************/ +/* DAC Register access */ + +static uint32_t dac_getreg(struct stm32_chan_s *chan, int offset); +static void dac_putreg(struct stm32_chan_s *chan, int offset, uint32_t value); + /* Interrupt handler */ #ifdef CONFIG_STM32_STM32F40XX @@ -96,6 +119,11 @@ 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); static int dac_interrupt(int irq, void *context); +/* Initialization */ + +static int dac_chaninit(struct stm32_chan_s *chan); +static int dac_blockinit(void); + /**************************************************************************** * Private Data ****************************************************************************/ @@ -110,16 +138,79 @@ static const struct dac_ops_s g_dacops = .ao_ioctl = dac_ioctl, }; -static struct dac_dev_s g_dacdev = +#ifdef CONFIG_STM32_DAC1 +static struct stm32_chan_s g_dac1priv = +{ + .intf = 0; +} + +static struct dac_dev_s g_dac1dev = +{ + .ad_ops = &g_dacops, + .ad_priv = &g_dac1priv, +}; +#endif + +#ifdef CONFIG_STM32_DAC2 +static struct stm32_chan_s g_dac2priv = +{ + .intf = 1; +} + +static struct dac_dev_s g_dac2dev = { - .ad_ops = &g_dacops, + .ad_ops = &g_dacops, + .ad_priv = &g_dac2priv, }; +#endif + +static struct stm32_dac_s g_dacblock; /**************************************************************************** * Private Functions ****************************************************************************/ /**************************************************************************** + * Name: dac_getreg + * + * Description: + * Read the value of an DAC 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 + * + ****************************************************************************/ + +static uint32_t dac_getreg(struct stm32_chan_s *chan, int offset) +{ + return getreg32(chan->base + offset); +} + +/**************************************************************************** + * Name: dac_getreg + * + * Description: + * Read the value of an DAC register. + * + * Input Parameters: + * chan - A reference to the DAC block status + * offset - The offset to the register to read + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void dac_putreg(struct stm32_chan_s *chan, int offset, uint32_t value) +{ + putreg32(value, chan->base + offset); +} + +/**************************************************************************** * Name: dac_interrupt * * Description: @@ -129,6 +220,7 @@ static struct dac_dev_s g_dacdev = * Input Parameters: * * Returned Value: + * OK * ****************************************************************************/ @@ -143,12 +235,15 @@ static int dac_interrupt(int irq, void *context) * Name: dac_reset * * Description: - * Reset the DAC device. Called early to initialize the hardware. This + * 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 * ****************************************************************************/ @@ -156,11 +251,11 @@ static void dac_reset(FAR struct dac_dev_s *dev) { irqstate_t flags; uint32_t regval; - - flags = irqsave(); -# warning "Missing logic" - + flags = irqsave(); + +#warning "Missing logic" + irqrestore(flags); } @@ -176,6 +271,7 @@ static void dac_reset(FAR struct dac_dev_s *dev) * Input Parameters: * * Returned Value: + * Zero on success; a negated errno value on failure. * ****************************************************************************/ @@ -195,6 +291,7 @@ static int dac_setup(FAR struct dac_dev_s *dev) * Input Parameters: * * Returned Value: + * None * ****************************************************************************/ @@ -212,6 +309,7 @@ static void dac_shutdown(FAR struct dac_dev_s *dev) * Input Parameters: * * Returned Value: + * None * ****************************************************************************/ @@ -229,6 +327,7 @@ static void dac_txint(FAR struct dac_dev_s *dev, bool enable) * Input Parameters: * * Returned Value: + * Zero on success; a negated errno value on failure. * ****************************************************************************/ @@ -247,6 +346,7 @@ static int dac_send(FAR struct dac_dev_s *dev, FAR struct dac_msg_s *msg) * Input Parameters: * * Returned Value: + * Zero on success; a negated errno value on failure. * ****************************************************************************/ @@ -256,6 +356,82 @@ static int dac_ioctl(FAR struct dac_dev_s *dev, int cmd, unsigned long arg) } /**************************************************************************** + * 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_chaninit(struct stm32_chan_s *chan) +{ + /* Is the selected channel already in-use? */ + + if (chan->inuse) + { + /* Yes.. then return EBUSY */ + + return -EBUSY; + } + + /* Mark the DAC channel "in-use" */ + + chan->inuse = 1; + 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_blockinit(void) +{ + irqstate_t flags; + uint32_t regval; + + /* Has the DMA 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 = irqsave(); + regval = getreg32(STM32_RCC_APB1RSTR); + regval |= RCC_APB1RSTR_DACRST + putreg32(regval, STM32_RCC_APB1RSTR); + + /* Take the DAC out of reset state */ + + regval &= ~RCC_APB1RSTR_DACRST + putreg32(regval, STM32_RCC_APB1RSTR); + irqrestore(flags); + + /* Mark the DAC block as initialized */ + + g_dacblock.init = 1; + return OK; +} + +/**************************************************************************** * Public Functions ****************************************************************************/ @@ -263,19 +439,67 @@ static int dac_ioctl(FAR struct dac_dev_s *dev, int cmd, unsigned long arg) * Name: stm32_dacinitialize * * Description: - * Initialize the DAC + * Initialize the DAC. * * Input Parameters: * intf - The DAC interface number. * * Returned Value: - * Valid dac device structure reference on succcess; a NULL on failure + * Valid dac device structure reference on succcess; 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 *stm32_dacinitialize(int intf) { - return &g_dacdev; + FAR struct dac_dev_s *dev; + FAR struct stm32_chan_s *chan; + int ret; + +#ifdef CONFIG_STM32_DAC1 + if (intf == 1) + { + avdbg("DAC1 Selected\n"); + dev = &g_dacdev1; + } + else +#endif +#ifdef CONFIG_STM32_DAC2 + if (intf == 2) + { + avdbg("DAC2 Selected\n"); + dev = &g_dac2dev; + } + else +#endif + { + adbg("No such DAC interface: %d\n", intf); + return NULL; + } + + /* Make sure that the DAC block has been initialized */ + + ret = dac_blockinit(); + if (ret < 0) + { + adbg("Failed to initialize the DAC block: %d\n", ret); + return ret; + } + + /* Configure the selected DAC channel */ + + chan = dev->ad_priv; + ret = dac_chaninit(chan); + if (ret < 0) + { + adbg("Failed to initialize DAC channel %d: %d\n", intf, ret); + return ret; + } + + return dev; } #endif /* CONFIG_STM32_DAC1 || CONFIG_STM32_DAC2 */ |