From 35efe997b4ea5352c341b8a1e8661ac83d1bc5ae Mon Sep 17 00:00:00 2001 From: patacongo Date: Thu, 15 Dec 2011 16:39:06 +0000 Subject: More STM32 DAC driver logic git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4186 42af7a65-404d-4744-a932-0658087f49c3 --- nuttx/arch/arm/src/lpc17xx/lpc17_dac.c | 58 ++--- nuttx/arch/arm/src/lpc17xx/lpc17_internal.h | 17 +- nuttx/arch/arm/src/stm32/chip/stm32f103ze_pinmap.h | 59 +++++ nuttx/arch/arm/src/stm32/chip/stm32f40xxx_pinmap.h | 61 +++++ nuttx/arch/arm/src/stm32/stm32_dac.c | 248 ++++++++++++++++++++- nuttx/arch/arm/src/stm32/stm32f10xxx_rcc.c | 2 +- nuttx/arch/arm/src/stm32/stm32f40xxx_rcc.c | 2 +- nuttx/drivers/analog/dac.c | 51 ++--- nuttx/include/nuttx/analog/dac.h | 41 +++- 9 files changed, 461 insertions(+), 78 deletions(-) diff --git a/nuttx/arch/arm/src/lpc17xx/lpc17_dac.c b/nuttx/arch/arm/src/lpc17xx/lpc17_dac.c index 4f9a9332c..13ac212f6 100644 --- a/nuttx/arch/arm/src/lpc17xx/lpc17_dac.c +++ b/nuttx/arch/arm/src/lpc17xx/lpc17_dac.c @@ -65,7 +65,7 @@ #include "lpc17_pinconn.h" #include "lpc17_dac.h" -#if defined(CONFIG_LPC17_DAC) +#ifdef CONFIG_LPC17_DAC /**************************************************************************** * Private Types @@ -91,17 +91,17 @@ static int dac_interrupt(int irq, void *context); static const struct dac_ops_s g_dacops = { - .ao_reset =dac_reset, - .ao_setup = dac_setup, - .ao_shutdown = dac_shutdown, - .ao_txint = dac_txint, - .ao_send = dac_send, - .ao_ioctl = dac_ioctl, + .ao_reset =dac_reset, + .ao_setup = dac_setup, + .ao_shutdown = dac_shutdown, + .ao_txint = dac_txint, + .ao_send = dac_send, + .ao_ioctl = dac_ioctl, }; static struct dac_dev_s g_dacdev = { - .ad_ops = &g_dacops, + .ad_ops = &g_dacops, }; /**************************************************************************** @@ -114,22 +114,21 @@ static struct dac_dev_s g_dacdev = static void dac_reset(FAR struct dac_dev_s *dev) { - irqstate_t flags; - uint32_t regval; + irqstate_t flags; + uint32_t regval; - flags = irqsave(); + flags = irqsave(); - regval = getreg32(LPC17_SYSCON_PCLKSEL0); - regval &= ~SYSCON_PCLKSEL0_DAC_MASK; - regval |= (SYSCON_PCLKSEL_CCLK8 << SYSCON_PCLKSEL0_DAC_SHIFT); - putreg32(regval, LPC17_SYSCON_PCLKSEL0); + regval = getreg32(LPC17_SYSCON_PCLKSEL0); + regval &= ~SYSCON_PCLKSEL0_DAC_MASK; + regval |= (SYSCON_PCLKSEL_CCLK8 << SYSCON_PCLKSEL0_DAC_SHIFT); + putreg32(regval, LPC17_SYSCON_PCLKSEL0); - //putreg32(DAC_CTRL_DBLBUFEN,LPC17_DAC_CTRL); ? + //putreg32(DAC_CTRL_DBLBUFEN,LPC17_DAC_CTRL); ? - lpc17_configgpio(GPIO_AOUT); - - irqrestore(flags); + lpc17_configgpio(GPIO_AOUT); + irqrestore(flags); } /* Configure the DAC. This method is called the first time that the DAC @@ -140,7 +139,7 @@ static void dac_reset(FAR struct dac_dev_s *dev) static int dac_setup(FAR struct dac_dev_s *dev) { - return OK; + return OK; } /* Disable the DAC. This method is called when the DAC device is closed. @@ -159,17 +158,17 @@ static void dac_txint(FAR struct dac_dev_s *dev, bool enable) static int dac_send(FAR struct dac_dev_s *dev, FAR struct dac_msg_s *msg) { - putreg32((msg->am_data>>16)&0xfffff,LPC17_DAC_CR); - dac_txdone(&g_dacdev); - return 0; + putreg32((msg->am_data>>16)&0xfffff,LPC17_DAC_CR); + dac_txdone(&g_dacdev); + return 0; } /* All ioctl calls will be routed through this method */ static int dac_ioctl(FAR struct dac_dev_s *dev, int cmd, unsigned long arg) { - dbg("Fix me:Not Implemented\n"); - return 0; + dbg("Fix me:Not Implemented\n"); + return 0; } static int dac_interrupt(int irq, void *context) @@ -181,7 +180,7 @@ static int dac_interrupt(int irq, void *context) ****************************************************************************/ /**************************************************************************** - * Name: up_dacinitialize + * Name: lpc17_dacinitialize * * Description: * Initialize the DAC @@ -191,9 +190,10 @@ static int dac_interrupt(int irq, void *context) * ****************************************************************************/ -FAR struct dac_dev_s *up_dacinitialize() +FAR struct dac_dev_s *lpc17_dacinitialize(void) { - return &g_dacdev; + return &g_dacdev; } -#endif + +#endif /* CONFIG_LPC17_DAC */ diff --git a/nuttx/arch/arm/src/lpc17xx/lpc17_internal.h b/nuttx/arch/arm/src/lpc17xx/lpc17_internal.h index aa2ddc489..107200e4d 100755 --- a/nuttx/arch/arm/src/lpc17xx/lpc17_internal.h +++ b/nuttx/arch/arm/src/lpc17xx/lpc17_internal.h @@ -609,7 +609,7 @@ EXTERN int lpc17_ssp1cmddata(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bo #endif /**************************************************************************** - * Name: ssp_flush + * Name: spi_flush * * Description: * Flush and discard any words left in the RX fifo. This can be called @@ -756,6 +756,21 @@ EXTERN void lpc17_dmadump(DMA_HANDLE handle, const struct lpc17_dmaregs_s *regs, #endif #endif +/**************************************************************************** + * Name: lpc17_dacinitialize + * + * Description: + * Initialize the DAC + * + * Returned Value: + * Valid dac device structure reference on succcess; a NULL on failure + * + ****************************************************************************/ + +#ifdef CONFIG_LPC17_DAC +EXTERN FAR struct dac_dev_s *lpc17_dacinitialize(void); +#endif + #undef EXTERN #if defined(__cplusplus) } diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f103ze_pinmap.h b/nuttx/arch/arm/src/stm32/chip/stm32f103ze_pinmap.h index 3caf54279..8446a2472 100644 --- a/nuttx/arch/arm/src/stm32/chip/stm32f103ze_pinmap.h +++ b/nuttx/arch/arm/src/stm32/chip/stm32f103ze_pinmap.h @@ -48,6 +48,65 @@ /* Alternate Pin Functions: */ +/* ADC */ + +#define GPIO_ADC1_IN0 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +#define GPIO_ADC1_IN1 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1) +#define GPIO_ADC1_IN2 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2) +#define GPIO_ADC1_IN3 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +#define GPIO_ADC1_IN4 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN4) +#define GPIO_ADC1_IN5 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN5) +#define GPIO_ADC1_IN6 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6) +#define GPIO_ADC1_IN7 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN7) +#define GPIO_ADC1_IN8 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0) +#define GPIO_ADC1_IN9 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1) +#define GPIO_ADC1_IN10 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN0) +#define GPIO_ADC1_IN11 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN1) +#define GPIO_ADC1_IN12 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN2) +#define GPIO_ADC1_IN13 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN3) +#define GPIO_ADC1_IN14 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN4) +#define GPIO_ADC1_IN15 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN5) + +#define GPIO_ADC2_IN0 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +#define GPIO_ADC2_IN1 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1) +#define GPIO_ADC2_IN2 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2) +#define GPIO_ADC2_IN3 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +#define GPIO_ADC2_IN4 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN4) +#define GPIO_ADC2_IN5 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN5) +#define GPIO_ADC2_IN6 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6) +#define GPIO_ADC2_IN7 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN7) +#define GPIO_ADC2_IN8 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0) +#define GPIO_ADC2_IN9 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1) +#define GPIO_ADC2_IN10 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN0) +#define GPIO_ADC2_IN11 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN1) +#define GPIO_ADC2_IN12 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN2) +#define GPIO_ADC2_IN13 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN3) +#define GPIO_ADC2_IN14 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN4) +#define GPIO_ADC2_IN15 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN5) + +#define GPIO_ADC3_IN0 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0) +#define GPIO_ADC3_IN1 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1) +#define GPIO_ADC3_IN2 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2) +#define GPIO_ADC3_IN3 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3) +#define GPIO_ADC3_IN4 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTF|GPIO_PIN6) +#define GPIO_ADC3_IN5 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTF|GPIO_PIN7) +#define GPIO_ADC3_IN6 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTF|GPIO_PIN8) +#define GPIO_ADC3_IN7 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTF|GPIO_PIN9) +#define GPIO_ADC3_IN8 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTF|GPIO_PIN10) +#define GPIO_ADC3_IN10 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN0) +#define GPIO_ADC3_IN11 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN1) +#define GPIO_ADC3_IN12 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN2) +#define GPIO_ADC3_IN13 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN3) + +/* DAC - "Once the DAC channelx is enabled, the corresponding GPIO pin + * (PA4 or PA5) is automatically connected to the analog converter output + * (DAC_OUTx). In order to avoid parasitic consumption, the PA4 or PA5 pin + * should first be configured to analog (AIN)." + */ + +#define GPIO_DAC_OUT1 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTF|GPIO_PIN10) +#define GPIO_DAC_OUT2 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PIN10) + /* TIMERS */ #if defined(CONFIG_STM32_TIM1_FULL_REMAP) diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_pinmap.h b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_pinmap.h index cd0dbd196..50c49cdbc 100644 --- a/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_pinmap.h +++ b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_pinmap.h @@ -68,6 +68,58 @@ * pins in this file. */ +/* ADC */ + +#define GPIO_ADC1_IN0 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN0) +#define GPIO_ADC1_IN1 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN1) +#define GPIO_ADC1_IN2 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN2) +#define GPIO_ADC1_IN3 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN3) +#define GPIO_ADC1_IN4 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN4) +#define GPIO_ADC1_IN5 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN5) +#define GPIO_ADC1_IN6 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN6) +#define GPIO_ADC1_IN7 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN7) +#define GPIO_ADC1_IN8 (GPIO_ANALOG|GPIO_PORTB|GPIO_PIN0) +#define GPIO_ADC1_IN9 (GPIO_ANALOG|GPIO_PORTB|GPIO_PIN1) +#define GPIO_ADC1_IN10 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN0) +#define GPIO_ADC1_IN11 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN1) +#define GPIO_ADC1_IN12 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN2) +#define GPIO_ADC1_IN13 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN3) +#define GPIO_ADC1_IN14 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN4) +#define GPIO_ADC1_IN15 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN5) + +#define GPIO_ADC2_IN0 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN0) +#define GPIO_ADC2_IN1 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN1) +#define GPIO_ADC2_IN2 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN2) +#define GPIO_ADC2_IN3 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN3) +#define GPIO_ADC2_IN4 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN4) +#define GPIO_ADC2_IN5 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN5) +#define GPIO_ADC2_IN6 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN6) +#define GPIO_ADC2_IN7 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN7) +#define GPIO_ADC2_IN8 (GPIO_ANALOG|GPIO_PORTB|GPIO_PIN0) +#define GPIO_ADC2_IN9 (GPIO_ANALOG|GPIO_PORTB|GPIO_PIN1) +#define GPIO_ADC2_IN10 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN0) +#define GPIO_ADC2_IN11 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN1) +#define GPIO_ADC2_IN12 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN2) +#define GPIO_ADC2_IN13 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN3) +#define GPIO_ADC2_IN14 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN4) +#define GPIO_ADC2_IN15 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN5) + +#define GPIO_ADC3_IN0 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN0) +#define GPIO_ADC3_IN1 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN1) +#define GPIO_ADC3_IN2 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN2) +#define GPIO_ADC3_IN3 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN3) +#define GPIO_ADC3_IN4 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN6) +#define GPIO_ADC3_IN5 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN7) +#define GPIO_ADC3_IN6 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN8) +#define GPIO_ADC3_IN7 (GPIO_ANALOG|GPIO_PORT |GPIO_PIN9) +#define GPIO_ADC3_IN9 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN3) +#define GPIO_ADC3_IN10 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN0) +#define GPIO_ADC3_IN11 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN1) +#define GPIO_ADC3_IN12 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN2) +#define GPIO_ADC3_IN13 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN3) +#define GPIO_ADC3_IN14 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN4) +#define GPIO_ADC3_IN15 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN5) + /* CAN */ #define GPIO_CAN1_RX_1 (GPIO_ALT|GPIO_AF9|GPIO_PORTA|GPIO_PIN11) @@ -84,6 +136,15 @@ #define GPIO_CAN2_TX_1 (GPIO_ALT|GPIO_AF9|GPIO_PORTB|GPIO_PIN13) #define GPIO_CAN2_TX_2 (GPIO_ALT|GPIO_AF9|GPIO_PORTB|GPIO_PIN6) +/* DAC -" Once the DAC channelx is enabled, the corresponding GPIO pin + * (PA4 or PA5) is automatically connected to the analog converter output + * (DAC_OUTx). In order to avoid parasitic consumption, the PA4 or PA5 pin + * should first be configured to analog (AIN)". + */ + +#define GPIO_DAC1_OUT (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN4) +#define GPIO_DAC2_OUT (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN5) + /* Digital Camera Interface (DCMI) */ #define GPIO_DCMI_D0_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTA|GPIO_PIN9) 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 */ @@ -77,9 +76,33 @@ #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,15 +138,78 @@ 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 * @@ -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. * ****************************************************************************/ @@ -255,6 +355,82 @@ static int dac_ioctl(FAR struct dac_dev_s *dev, int cmd, unsigned long arg) return -ENOTTY; } +/**************************************************************************** + * 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 */ diff --git a/nuttx/arch/arm/src/stm32/stm32f10xxx_rcc.c b/nuttx/arch/arm/src/stm32/stm32f10xxx_rcc.c index 07dda8a59..9976e4870 100644 --- a/nuttx/arch/arm/src/stm32/stm32f10xxx_rcc.c +++ b/nuttx/arch/arm/src/stm32/stm32f10xxx_rcc.c @@ -298,7 +298,7 @@ static inline void rcc_enableapb1(void) regval |= RCC_APB1ENR_PWREN; #endif -#if CONFIG_STM32_DAC +#ifdefined (CONFIG_STM32_DAC1) || defined(CONFIG_STM32_DAC2) /* DAC interface clock enable */ regval |= RCC_APB1ENR_DACEN; diff --git a/nuttx/arch/arm/src/stm32/stm32f40xxx_rcc.c b/nuttx/arch/arm/src/stm32/stm32f40xxx_rcc.c index e06a84d65..4b8a16790 100644 --- a/nuttx/arch/arm/src/stm32/stm32f40xxx_rcc.c +++ b/nuttx/arch/arm/src/stm32/stm32f40xxx_rcc.c @@ -431,7 +431,7 @@ static inline void rcc_enableapb1(void) regval |= RCC_APB1ENR_PWREN; -#if CONFIG_STM32_DAC +#ifdefined (CONFIG_STM32_DAC1) || defined(CONFIG_STM32_DAC2) /* DAC interface clock enable */ regval |= RCC_APB1ENR_DACEN; diff --git a/nuttx/drivers/analog/dac.c b/nuttx/drivers/analog/dac.c index a5f4c1473..b283a5bf5 100644 --- a/nuttx/drivers/analog/dac.c +++ b/nuttx/drivers/analog/dac.c @@ -296,17 +296,17 @@ static ssize_t dac_write(FAR struct file *filep, FAR const char *buffer, size_t */ if (buflen % 5 ==0 ) - msglen=5; + msglen=5; else if (buflen % 4 ==0 ) - msglen=4; + msglen=4; else if (buflen % 3 ==0 ) - msglen=3; + msglen=3; else if (buflen % 2 ==0 ) - msglen=2; + msglen=2; else if (buflen == 1) - msglen=1; + msglen=1; else - msglen=5; + msglen=5; while ((buflen - nsent) >= msglen ) { @@ -369,35 +369,36 @@ static ssize_t dac_write(FAR struct file *filep, FAR const char *buffer, size_t /* We get here if there is space at the end of the FIFO. Add the new * CAN message at the tail of the FIFO. */ - if(msglen==5) + + if (msglen==5) { - msg = (FAR struct dac_msg_s *)&buffer[nsent]; - memcpy(&fifo->af_buffer[fifo->af_tail], msg, msglen); + msg = (FAR struct dac_msg_s *)&buffer[nsent]; + memcpy(&fifo->af_buffer[fifo->af_tail], msg, msglen); } else if(msglen == 4) { - fifo->af_buffer[fifo->af_tail].am_channel=buffer[nsent]; - fifo->af_buffer[fifo->af_tail].am_data=*(uint32_t *)&buffer[nsent]; - fifo->af_buffer[fifo->af_tail].am_data&=0xffffff00; - } + fifo->af_buffer[fifo->af_tail].am_channel=buffer[nsent]; + fifo->af_buffer[fifo->af_tail].am_data=*(uint32_t *)&buffer[nsent]; + fifo->af_buffer[fifo->af_tail].am_data&=0xffffff00; + } else if(msglen == 3) { - fifo->af_buffer[fifo->af_tail].am_channel=buffer[nsent]; - fifo->af_buffer[fifo->af_tail].am_data=(*(uint16_t *)&buffer[nsent+1]); - fifo->af_buffer[fifo->af_tail].am_data<<=16; - } + fifo->af_buffer[fifo->af_tail].am_channel=buffer[nsent]; + fifo->af_buffer[fifo->af_tail].am_data=(*(uint16_t *)&buffer[nsent+1]); + fifo->af_buffer[fifo->af_tail].am_data<<=16; + } else if(msglen == 2) { - fifo->af_buffer[fifo->af_tail].am_channel=0; - fifo->af_buffer[fifo->af_tail].am_data=(*(uint16_t *)&buffer[nsent]); - fifo->af_buffer[fifo->af_tail].am_data<<=16; - } + fifo->af_buffer[fifo->af_tail].am_channel=0; + fifo->af_buffer[fifo->af_tail].am_data=(*(uint16_t *)&buffer[nsent]); + fifo->af_buffer[fifo->af_tail].am_data<<=16; + } else if(msglen == 1) { - fifo->af_buffer[fifo->af_tail].am_channel=0; - fifo->af_buffer[fifo->af_tail].am_data=buffer[nsent]; - fifo->af_buffer[fifo->af_tail].am_data<<=24; - } + fifo->af_buffer[fifo->af_tail].am_channel=0; + fifo->af_buffer[fifo->af_tail].am_data=buffer[nsent]; + fifo->af_buffer[fifo->af_tail].am_data<<=24; + } /* Increment the tail of the circular buffer */ fifo->af_tail = nexttail; diff --git a/nuttx/include/nuttx/analog/dac.h b/nuttx/include/nuttx/analog/dac.h index 7359e6c3a..23cbb9941 100644 --- a/nuttx/include/nuttx/analog/dac.h +++ b/nuttx/include/nuttx/analog/dac.h @@ -6,6 +6,7 @@ * History: 0.1 2011-08-04 initial version * * Derived from include/nuttx/can.h + * * Copyright (C) 2008, 2009 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * @@ -71,10 +72,11 @@ /************************************************************************************ * Public Types ************************************************************************************/ + struct dac_msg_s { - uint8_t am_channel; /* The 8-bit DAC Channel */ - int32_t am_data; /* DAC convert result (4 bytes) */ + uint8_t am_channel; /* The 8-bit DAC Channel */ + int32_t am_data; /* DAC convert result (4 bytes) */ }; struct dac_fifo_s @@ -138,12 +140,12 @@ struct dac_ops_s struct dac_dev_s { - uint8_t ad_ocount; /* The number of times the device has been opened */ - uint8_t ad_nchannel; /* Number of dac channel */ - sem_t ad_closesem; /* Locks out new opens while close is in progress */ - struct dac_fifo_s ad_xmit; /* Describes receive FIFO */ - const struct dac_ops_s *ad_ops; /* Arch-specific operations */ - void *ad_priv; /* Used by the arch-specific logic */ + uint8_t ad_ocount; /* The number of times the device has been opened */ + uint8_t ad_nchannel; /* Number of dac channel */ + sem_t ad_closesem; /* Locks out new opens while close is in progress */ + struct dac_fifo_s ad_xmit; /* Describes receive FIFO */ + const struct dac_ops_s *ad_ops; /* Arch-specific operations */ + void *ad_priv; /* Used by the arch-specific logic */ }; /************************************************************************************ @@ -157,12 +159,21 @@ struct dac_dev_s #if defined(__cplusplus) extern "C" { #endif + /************************************************************************************ * Name: dac_register * * Description: * Register a dac driver. * + * Input Parameters: + * path - The full path to the DAC device to be registered. This could be, as an + * example, "/dev/dac0" + * dev - An instance of the device-specific DAC interface + * + * Returned Value: + * Zero on success; A negated errno value on failure. + * ************************************************************************************/ int dac_register(FAR const char *path, FAR struct dac_dev_s *dev); @@ -173,14 +184,26 @@ int dac_register(FAR const char *path, FAR struct dac_dev_s *dev); * Description: * Called from the DAC interrupt handler at the completion of a send operation. * + * Input Parameters: + * dev - An instance of the device-specific DAC interface + * * Return: * OK on success; a negated errno on failure. * ************************************************************************************/ + int dac_txdone(FAR struct dac_dev_s *dev); +/************************************************************************************ + * DAC Initialization functions + * + * Architecture-specific versions will have prototypes in architect-specific header + * files. Common DAC implementations in drivers/analog will have prototypes listed + * below. + * + ************************************************************************************/ + FAR struct dac_dev_s *up_ad5410initialize(FAR struct spi_dev_s *spi, unsigned int devno); -FAR struct dac_dev_s *up_dacinitialize(); #if defined(__cplusplus) } -- cgit v1.2.3