aboutsummaryrefslogtreecommitdiff
path: root/src/kern/dma/dma_manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kern/dma/dma_manager.c')
-rw-r--r--src/kern/dma/dma_manager.c55
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) {