summaryrefslogtreecommitdiff
path: root/nuttx/arch/arm/src/stm32/stm32_dac.c
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-12-15 16:39:06 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-12-15 16:39:06 +0000
commit35efe997b4ea5352c341b8a1e8661ac83d1bc5ae (patch)
tree6f95e16854e297c82ed428daed9959ac41f5d86e /nuttx/arch/arm/src/stm32/stm32_dac.c
parent27c16edcc1befe9afeb4a1996c3b22bc9acd8380 (diff)
downloadpx4-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.c248
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 */