diff options
Diffstat (limited to 'src/kern/dma/dma_manager.c')
-rw-r--r-- | src/kern/dma/dma_manager.c | 55 |
1 files changed, 54 insertions, 1 deletions
diff --git a/src/kern/dma/dma_manager.c b/src/kern/dma/dma_manager.c index 9ffa795..39ae9a3 100644 --- a/src/kern/dma/dma_manager.c +++ b/src/kern/dma/dma_manager.c @@ -2,10 +2,38 @@ #include "arch/stm32l4xxx/peripherals/dma.h" #include "arch/stm32l4xxx/peripherals/rcc.h" +#include "arch/stm32l4xxx/peripherals/spi.h" #include "arch/stm32l4xxx/peripherals/usart.h" /* Bitmask of DMA2 channels in use. */ -static uint8_t dma_inuse[2]; +uint8_t dma_inuse[2]; + +void (*dma_channel_callbacks[14])(void*); +void* callback_args[14]; + +#define ON_DMA(dma, chan) \ + void on_dma##dma##_channel##chan() \ + { \ + if (dma_channel_callbacks[(dma - 1) * 7 + (chan - 1)]) { \ + dma_channel_callbacks[(dma - 1) * 7 + (chan - 1)]( \ + callback_args[(dma - 1) * 7 + (chan - 1)]); \ + } \ + } + +ON_DMA(1, 1); +ON_DMA(1, 2); +ON_DMA(1, 3); +ON_DMA(1, 4); +ON_DMA(1, 5); +ON_DMA(1, 6); +ON_DMA(1, 7); +ON_DMA(2, 1); +ON_DMA(2, 2); +ON_DMA(2, 3); +ON_DMA(2, 4); +ON_DMA(2, 5); +ON_DMA(2, 6); +ON_DMA(2, 7); static inline dma_t* get_dma(int dma) { @@ -37,6 +65,12 @@ static uint32_t get_periph_location(dma_peripheral_t operipheral) CASE(DMA1_PERIPH_USART1_TX, &USART1.td_r) CASE(DMA1_PERIPH_USART2_RX, &USART2.rd_r) CASE(DMA1_PERIPH_USART2_TX, &USART2.td_r) + CASE(DMA2_PERIPH_SPI1_RX, &SPI1.d_r) + CASE(DMA2_PERIPH_SPI1_TX, &SPI1.d_r) + CASE(DMA1_PERIPH_SPI1_RX, &SPI1.d_r) + CASE(DMA1_PERIPH_SPI1_TX, &SPI1.d_r) + CASE(DMA2_PERIPH_SPI3_RX, &SPI3.d_r) + CASE(DMA2_PERIPH_SPI3_TX, &SPI3.d_r) default: return 0; @@ -280,6 +314,25 @@ void dma_p2mem_initiate_transfer( regset(config->cc_r, dma_cc_en, 1); } +void dma_chan_set_callback( + dma_channel_t chan, void (*callback)(void*), void* arg) +{ + dma_channel_callbacks[chan.dma * 7 + chan.chan] = callback; + callback_args[chan.dma * 7 + chan.chan] = arg; + enable_interrupt(dma_channel_get_interrupt(chan)); +} + +void dma_channel_interrupt_enable(dma_channel_t chan, bool enabled) +{ + dma_channel_config_t* config = get_raw_channel_config(chan); + regset(config->cc_r, dma_cc_tcie, !!enabled); + if (enabled) { + enable_interrupt(dma_channel_get_interrupt(chan)); + } else { + disable_interrupt(dma_channel_get_interrupt(chan)); + } +} + interrupt_t dma_channel_get_interrupt(dma_channel_t chan) { if (chan.dma == 0) { |