diff options
author | Marti Bolivar <mbolivar@leaflabs.com> | 2011-02-15 22:29:45 -0500 |
---|---|---|
committer | Marti Bolivar <mbolivar@leaflabs.com> | 2011-02-16 01:17:21 -0500 |
commit | 2764748208816043a3149eae3a433d02325a1a36 (patch) | |
tree | cc5afb0af0c6f1d2282db08d3dad1dae9b4d33e6 /libmaple/dma.c | |
parent | 1fb0e0d727089e23d4b30e1efba5410dc4b4da14 (diff) | |
parent | 620740bf1986311041a40bd2992d1b549f84b2ba (diff) | |
download | librambutan-2764748208816043a3149eae3a433d02325a1a36.tar.gz librambutan-2764748208816043a3149eae3a433d02325a1a36.zip |
Merge branch 'nzmichaelh-master' into master.
This provides DMA, IWDG, PWR, and BKP support, and fixes several bugs.
Conflicts:
libmaple/adc.h
libmaple/libmaple.h
libmaple/ring_buffer.h
Diffstat (limited to 'libmaple/dma.c')
-rw-r--r-- | libmaple/dma.c | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/libmaple/dma.c b/libmaple/dma.c new file mode 100644 index 0000000..15c96e1 --- /dev/null +++ b/libmaple/dma.c @@ -0,0 +1,148 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Michael Hope. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + *****************************************************************************/ + +/** + * @file dma.c + * + * @brief Direct Memory Access peripheral support + */ + +#include "libmaple.h" +#include "dma.h" +#include "rcc.h" +#include "nvic.h" + +#define DMA_EN BIT(0) + +typedef struct dma_regs { + uint32 CCR; + uint32 CNDTR; + uint32 CPAR; + uint32 CMAR; +} dma_regs; + +typedef struct DMAChannel { + void (*handler)(void); + uint32 irq_line; +} DMAChannel; + +volatile static DMAChannel dma_channels[] = { + { .handler = NULL, .irq_line = NVIC_DMA_CH1 }, + { .handler = NULL, .irq_line = NVIC_DMA_CH2 }, + { .handler = NULL, .irq_line = NVIC_DMA_CH3 }, + { .handler = NULL, .irq_line = NVIC_DMA_CH4 }, + { .handler = NULL, .irq_line = NVIC_DMA_CH5 }, + { .handler = NULL, .irq_line = NVIC_DMA_CH6 }, + { .handler = NULL, .irq_line = NVIC_DMA_CH7 } +}; + +/** Get the base address of the given channel, asserting and returning + * NULL on illegal + */ +static dma_regs *dma_get_regs(uint8 channel) { + if (channel >= 1 && channel <= 7) { + return (dma_regs *)(DMA1_CCR1 + DMA_CHANNEL_STRIDE * (channel-1)); + } else { + ASSERT(0); + return NULL; + } +} + +/* Zero-based indexing */ +static inline void dispatch_handler(uint8 channel_idx) { + ASSERT(dma_channels[channel_idx].handler); + if (dma_channels[channel_idx].handler) { + (dma_channels[channel_idx].handler)(); + } +} + +void DMAChannel1_IRQHandler(void) { + dispatch_handler(0); +} + +void DMAChannel2_IRQHandler(void) { + dispatch_handler(1); +} + +void DMAChannel3_IRQHandler(void) { + dispatch_handler(2); +} + +void DMAChannel4_IRQHandler(void) { + dispatch_handler(3); +} + +void DMAChannel5_IRQHandler(void) { + dispatch_handler(4); +} + +void DMAChannel6_IRQHandler(void) { + dispatch_handler(5); +} + +void DMAChannel7_IRQHandler(void) { + dispatch_handler(6); +} + +void dma_init(uint8 channel, volatile void *paddr, + dma_transfer_size psize, dma_transfer_size msize, + int mode) { + volatile dma_regs *regs = dma_get_regs(channel); + + if (regs != NULL) { + rcc_clk_enable(RCC_DMA1); + + regs->CCR = ((0 << 12) /* Low priority */ + | (msize << 10) + | (psize << 8) + | (0 << 0) /* Disabled (until started) */ + | mode); + + regs->CPAR = (uint32)paddr; + } +} + +void dma_start(uint8 channel, volatile void *buffer, uint16 count) { + volatile dma_regs *regs = dma_get_regs(channel); + + if (regs != NULL) { + regs->CCR &= ~DMA_EN; /* CMAR may not be written with EN set */ + regs->CMAR = (uint32)buffer; + regs->CNDTR = count; + + regs->CCR |= DMA_EN; + } +} + +void dma_attach_interrupt(uint8 channel, voidFuncPtr handler) { + channel--; /* 1-based -> 0-based indexing */ + dma_channels[channel].handler = handler; + nvic_irq_enable(dma_channels[channel].irq_line); +} + +void dma_detach_interrupt(uint8 channel) { + channel--; + nvic_irq_disable(dma_channels[channel].irq_line); + dma_channels[channel].handler = NULL; +} |