diff options
Diffstat (limited to 'os/hal')
-rw-r--r-- | os/hal/platforms/LPC17xx/dac_lld.c | 210 | ||||
-rw-r--r-- | os/hal/platforms/LPC17xx/dac_lld.h | 207 | ||||
-rw-r--r-- | os/hal/platforms/LPC17xx/lpc17xx_dma.h | 9 | ||||
-rw-r--r-- | os/hal/platforms/LPC17xx/platform.mk | 3 | ||||
-rw-r--r-- | os/hal/src/hal.c | 3 |
5 files changed, 430 insertions, 2 deletions
diff --git a/os/hal/platforms/LPC17xx/dac_lld.c b/os/hal/platforms/LPC17xx/dac_lld.c new file mode 100644 index 000000000..11a423d69 --- /dev/null +++ b/os/hal/platforms/LPC17xx/dac_lld.c @@ -0,0 +1,210 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + LPC17xx DAC driver - Copyright (C) 2013 Marcin Jokel + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file LPC17xx/dac_lld.c + * @brief LPC17xx DAC subsystem low level driver source. + * + * @addtogroup DAC + * @{ + */ + +#include "ch.h" +#include "hal.h" + +#if HAL_USE_DAC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief CHN1 driver identifier.*/ +DACDriver DACD1; + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +static lpc17xx_dma_lli_config_t lpc_dac_lli[2] __attribute__((aligned(0x10))); + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + + +/** + * @brief DAC DMA interrupt function. + * + * @param[in] dacp pointer to the @p DACDriver object + * @param[in] flags dma error flags + */ +static void dac_serve_dma_interrupt(DACDriver *dacp, uint32_t flags) { + + if ((flags & (1 << LPC17xx_DAC_DMA_CHANNEL)) != 0) { + _dac_isr_error_code(dacp, flags); /* DMA errors handling.*/ + } + else { + if (dacp->half_buffer == false) { + _dac_isr_half_code(dacp); + dacp->half_buffer = true; + } + else { + _dac_isr_full_code(dacp); + dacp->half_buffer = false; + } + } +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level DAC driver initialization. + * + * @notapi + */ +void dac_lld_init(void) { + dacObjectInit(&DACD1); +} + +/** + * @brief Configures and activates the DAC peripheral. + * + * @param[in] dacp pointer to the @p DACDriver object + * + * @notapi + */ +void dac_lld_start(DACDriver *dacp) { + + if (dacp->state == DAC_STOP) { + + /* Enable DAC */ + LPC_PINCON->PINSEL1 |= (2UL << 20); /* Set AOUT P0.26 pin.*/ + + LPC_DAC->CR = 0; + LPC_DAC->CTRL = 0; + LPC_DAC->CNTVAL = LPC17xx_PCLK/dacp->config->frequency; + + dmaChannelAllocate(LPC17xx_DAC_DMA_CHANNEL, \ + (lpc17xx_dmaisr_t)dac_serve_dma_interrupt, \ + (void *)dacp); + } +} + +/** + * @brief Deactivates the DAC peripheral. + * + * @param[in] dacp pointer to the @p DACDriver object + * + * @notapi + */ +void dac_lld_stop(DACDriver *dacp) { + + /* If in ready state then disables the DAC clock.*/ + if (dacp->state == DAC_READY) { + + /* DMA disable.*/ + dmaChannelDisable(LPC17xx_DAC_DMA_CHANNEL); + dmaChannelRelease(LPC17xx_DAC_DMA_CHANNEL); + + /* Disable DAC */ + LPC_PINCON->PINSEL1 &= ~(2UL << 20); /* Disable AOUT P0.26 pin.*/ + } +} + +/** + * @brief Sends data over the DAC bus. + * @details This asynchronous function starts a transmit operation. + * @post At the end of the operation the configured callback is invoked. + * + * @param[in] dacp pointer to the @p DACDriver object + * @param[in] n number of words to send + * @param[in] txbuf the pointer to the transmit buffer + * + * @notapi + */ +void dac_lld_start_conversion(DACDriver *dacp) { + + dacp->half_buffer = false; + uint32_t dma_ch_config; + + /* DMA configuration */ + lpc_dac_lli[0].srcaddr = (uint32_t) &dacp->samples[0]; + lpc_dac_lli[0].dstaddr = (uint32_t)&LPC_DAC->CR; + lpc_dac_lli[0].lli = (uint32_t) &lpc_dac_lli[1]; + lpc_dac_lli[0].control = + DMA_CTRL_TRANSFER_SIZE(dacp->depth/2) | + DMA_CTRL_SRC_BSIZE_1 | + DMA_CTRL_DST_BSIZE_1 | + DMA_CTRL_SRC_WIDTH_WORD | + DMA_CTRL_DST_WIDTH_WORD | + DMA_CTRL_SRC_INC | + DMA_CTRL_DST_NOINC | + DMA_CTRL_PROT1_USER | + DMA_CTRL_PROT2_NONBUFF | + DMA_CTRL_PROT3_NONCACHE | + DMA_CTRL_INT; + + lpc_dac_lli[1].srcaddr = (uint32_t) &dacp->samples[dacp->depth/2]; + lpc_dac_lli[1].dstaddr = lpc_dac_lli[0].dstaddr; + lpc_dac_lli[1].control = lpc_dac_lli[0].control; + + if (dacp->grpp->circular == true) { + lpc_dac_lli[1].lli = (uint32_t) &lpc_dac_lli[0]; + } + else { + lpc_dac_lli[1].lli = 0; + } + + dma_ch_config = + DMA_CFG_CH_ENABLE | + DMA_CFG_DST_PERIPH(DMA_DAC) | + DMA_CFG_TTYPE_M2P | + DMA_CFG_IE | + DMA_CFG_ITC; + + dmaChannelSrcAddr(LPC17xx_DAC_DMA_CHANNEL, lpc_dac_lli[0].srcaddr); + dmaChannelDstAddr(LPC17xx_DAC_DMA_CHANNEL, lpc_dac_lli[0].dstaddr); + dmaChannelLinkedList(LPC17xx_DAC_DMA_CHANNEL, lpc_dac_lli[0].lli); + dmaChannelControl(LPC17xx_DAC_DMA_CHANNEL, lpc_dac_lli[0].control); + dmaChannelConfig(LPC17xx_DAC_DMA_CHANNEL, dma_ch_config); + + LPC_DAC->CTRL = DACCTRL_DMA_ENA | DACCTRL_CNT_ENA | DACCTRL_DBLBUF_ENA; +} + +void dac_lld_stop_conversion(DACDriver *dacp) { + + /* If in active state then disables the DAC.*/ + if (dacp->state == DAC_ACTIVE) { + + /* DMA disable.*/ + dmaChannelDisable(LPC17xx_DAC_DMA_CHANNEL); + } +}; + +#endif /* HAL_USE_DAC */ + +/** @} */ diff --git a/os/hal/platforms/LPC17xx/dac_lld.h b/os/hal/platforms/LPC17xx/dac_lld.h new file mode 100644 index 000000000..26c23da11 --- /dev/null +++ b/os/hal/platforms/LPC17xx/dac_lld.h @@ -0,0 +1,207 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + LPC17xx DAC driver - Copyright (C) 2013 Marcin Jokel + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file LPC17xx/dac_lld.h + * @brief LPC17xx DAC subsystem low level driver header. + * + * @addtogroup DAC + * @{ + */ + +#ifndef _DAC_LLD_H_ +#define _DAC_LLD_H_ + +#if HAL_USE_DAC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +#define DACR_BIAS (1UL << 16) + +#define DACCTRL_INT_DMA_REQ (1UL << 0) +#define DACCTRL_DBLBUF_ENA (1UL << 1) +#define DACCTRL_CNT_ENA (1UL << 2) +#define DACCTRL_DMA_ENA (1UL << 3) + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ + +/** + * @brief DMA stream used for DAC CHN1 TX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(LPC17xx_DAC_DMA_CHANNEL) || defined(__DOXYGEN__) +#define LPC17xx_DAC_DMA_CHANNEL DMA_CHANNEL5 +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if !defined(LPC17xx_DMA_REQUIRED) +#define LPC17xx_DMA_REQUIRED +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of a structure representing an DAC driver. + */ +typedef struct DACDriver DACDriver; + +/** + * @brief Type representing a DAC sample. + */ +typedef uint32_t dacsample_t; + +/** + * @brief DAC notification callback type. + * + * @param[in] dacp pointer to the @p DACDriver object triggering the + * callback + */ +typedef void (*dacendcallback_t)(DACDriver *dacp, const dacsample_t * samples, size_t pos); + +/** + * @brief DAC notification callback type. + * + * @param[in] dacp pointer to the @p DACDriver object triggering the + * callback + */ +typedef void (*dacerrcallback_t)(DACDriver *dacp, uint32_t flags); + +/** + * @brief DAC Conversion group structure. + */ +typedef struct { + /** + * @brief Number of DAC channels. + */ + uint16_t num_channels; + /** + * @brief Operation complete callback or @p NULL. + */ + dacendcallback_t end_cb; + /** + * @brief Error handling callback or @p NULL. + */ + dacerrcallback_t error_cb; + /** + * @brief Error handling callback or @p NULL. + */ + bool circular; + +} DACConversionGroup; + +/** + * @brief Driver configuration structure. + */ +typedef struct { + /** + * @brief Timer frequency in Hz. + */ + uint32_t frequency; + /* End of the mandatory fields.*/ +} DACConfig; + +/** + * @brief Structure representing a DAC driver. + */ +struct DACDriver { + /** + * @brief Driver state. + */ + dacstate_t state; + /** + * @brief Conversion group. + */ + const DACConversionGroup *grpp; + /** + * @brief Samples buffer pointer. + */ + const dacsample_t *samples; + /** + * @brief Samples buffer size. + */ + uint16_t depth; + /** + * @brief Current configuration data. + */ + const DACConfig *config; +#if DAC_USE_WAIT || defined(__DOXYGEN__) + /** + * @brief Waiting thread. + */ + Thread *thread; +#endif /* DAC_USE_WAIT */ +#if DAC_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) +#if CH_USE_MUTEXES || defined(__DOXYGEN__) + /** + * @brief Mutex protecting the bus. + */ + Mutex mutex; +#elif CH_USE_SEMAPHORES + Semaphore semaphore; +#endif +#endif /* DAC_USE_MUTUAL_EXCLUSION */ +#if defined(DAC_DRIVER_EXT_FIELDS) + DAC_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Half buffer indicator. + */ + bool_t half_buffer; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +extern DACDriver DACD1; + +#ifdef __cplusplus +extern "C" { +#endif + void dac_lld_init(void); + void dac_lld_start(DACDriver *dacp); + void dac_lld_stop(DACDriver *dacp); + void dac_lld_start_conversion(DACDriver *dacp); + void dac_lld_stop_conversion(DACDriver *dacp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_DAC */ + +#endif /* _DAC_LLD_H_ */ + +/** @} */ diff --git a/os/hal/platforms/LPC17xx/lpc17xx_dma.h b/os/hal/platforms/LPC17xx/lpc17xx_dma.h index e581265a5..952c24a17 100644 --- a/os/hal/platforms/LPC17xx/lpc17xx_dma.h +++ b/os/hal/platforms/LPC17xx/lpc17xx_dma.h @@ -217,6 +217,13 @@ typedef struct { volatile uint32_t config; /**< @brief Configuration. */ } lpc17xx_dma_channel_config_t; +typedef struct { + volatile uint32_t srcaddr; /**< @brief Source address. */ + volatile uint32_t dstaddr; /**< @brief Destination address. */ + volatile uint32_t lli; /**< @brief Linked List Item. */ + volatile uint32_t control; /**< @brief Control. */ +} lpc17xx_dma_lli_config_t; + /** * @brief DMA channel number. */ @@ -312,7 +319,7 @@ typedef void (*lpc17xx_dmaisr_t)(void *p, uint32_t flags); * @special */ #define dmaChannelLinkedList(dmach, addr) \ - _lpc17xx_dma_channel_config_t[dmach]->CLLI = (((uint32_t)(addr)) << 2) + _lpc17xx_dma_channel_config_t[dmach]->CLLI = ((uint32_t)(addr)) /** * @brief Set control configuration to a DMA channel. diff --git a/os/hal/platforms/LPC17xx/platform.mk b/os/hal/platforms/LPC17xx/platform.mk index b3e3f8eed..1cc18db5b 100644 --- a/os/hal/platforms/LPC17xx/platform.mk +++ b/os/hal/platforms/LPC17xx/platform.mk @@ -7,7 +7,8 @@ PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/LPC17xx/hal_lld.c \ ${CHIBIOS}/os/hal/platforms/LPC17xx/serial_lld.c \ ${CHIBIOS}/os/hal/platforms/LPC17xx/rtc_lld.c \ ${CHIBIOS}/os/hal/platforms/LPC17xx/i2c_lld.c \ - ${CHIBIOS}/os/hal/platforms/LPC17xx/spi_lld.c + ${CHIBIOS}/os/hal/platforms/LPC17xx/spi_lld.c \ + ${CHIBIOS}/os/hal/platforms/LPC17xx/dac_lld.c # Required include directories diff --git a/os/hal/src/hal.c b/os/hal/src/hal.c index 974a8854b..d7a088ec9 100644 --- a/os/hal/src/hal.c +++ b/os/hal/src/hal.c @@ -74,6 +74,9 @@ void halInit(void) { #if HAL_USE_CAN || defined(__DOXYGEN__)
canInit();
#endif
+#if HAL_USE_DAC || defined(__DOXYGEN__)
+ dacInit();
+#endif
#if HAL_USE_EXT || defined(__DOXYGEN__)
extInit();
#endif
|