aboutsummaryrefslogtreecommitdiff
path: root/include/kern/dma/dma_manager.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/kern/dma/dma_manager.h')
-rw-r--r--include/kern/dma/dma_manager.h279
1 files changed, 279 insertions, 0 deletions
diff --git a/include/kern/dma/dma_manager.h b/include/kern/dma/dma_manager.h
new file mode 100644
index 0000000..0d17bd5
--- /dev/null
+++ b/include/kern/dma/dma_manager.h
@@ -0,0 +1,279 @@
+#ifndef PERI_DMA_H_
+#define PERI_DMA_H_
+
+#include "kern/common.h"
+#include "arch/stm32l4xxx/peripherals/dma.h" /* Access to the DMA registers. */
+#include "arch/stm32l4xxx/peripherals/irq.h"
+
+#define DMA_ERROR_CHANNEL_IN_USE 1
+
+#define CAT2(x, y) x ## y
+#define CAT1(v, c) CAT2(v, c)
+#define DMA_RESERVED(dma) CAT1(dma ## _PERIPH_RESERVED, __COUNTER__)
+
+#define ALTERNATE0 0x0000
+#define ALTERNATE1 0x0100
+#define ALTERNATE2 0x0200
+#define ALTERNATE3 0x0300
+
+#define DMA_N_CHANNELS 7
+typedef enum {
+ DMA1_PERIPH_ADC1 = 0,
+ DMA1_PERIPH_ADC2 = 1,
+ DMA1_PERIPH_ADC3 = 2,
+ DMA1_PERIPH_DFSDM1_FLT0 = 3,
+ DMA1_PERIPH_DFSDM1_FLT1 = 4,
+ DMA1_PERIPH_DFSDM1_FLT2 = 5,
+ DMA1_PERIPH_DFSDM1_FLT3 = 6,
+
+ DMA_RESERVED(DMA1) = 7,
+ DMA1_PERIPH_SPI1_RX = 8,
+ DMA1_PERIPH_SPI1_TX = 9,
+ DMA1_PERIPH_SPI2_RX = 10,
+ DMA1_PERIPH_SPI2_TX = 11,
+ DMA1_PERIPH_SAI2_A = 12,
+ DMA1_PERIPH_SAI2_B = 13,
+
+ DMA_RESERVED(DMA1) = 14,
+ DMA1_PERIPH_USART3_TX = 15,
+ DMA1_PERIPH_USART3_RX = 16,
+ DMA1_PERIPH_USART1_TX = 17,
+ DMA1_PERIPH_USART1_RX = 18,
+ DMA1_PERIPH_USART2_RX = 19,
+ DMA1_PERIPH_USART2_TX = 20,
+
+ DMA_RESERVED(DMA1) = 21,
+ DMA1_PERIPH_I2C3_TX = 22,
+ DMA1_PERIPH_I2C3_RX = 23,
+ DMA1_PERIPH_I2C2_TX = 24,
+ DMA1_PERIPH_I2C2_RX = 25,
+ DMA1_PERIPH_I2C1_TX = 26,
+ DMA1_PERIPH_I2C1_RX = 27,
+
+ DMA1_PERIPH_TIM2_CH3 = 28,
+ DMA1_PERIPH_TIM2_UP = 29,
+ DMA1_PERIPH_TIM16_CH1_1 = 30 | ALTERNATE0,
+ DMA1_PERIPH_TIM16_UP_1 = 30 | ALTERNATE1, /* Same as TIM16_CH1. */
+ DMA_RESERVED(DMA1) = 31,
+ DMA1_PERIPH_TIM2_CH1 = 32,
+ DMA1_PERIPH_TIM16_CH1_2 = 33,
+ DMA1_PERIPH_TIM16_UP_2 = 33 | ALTERNATE1, /* Same as TIM16_CH1. */
+ DMA1_PERIPH_TIM2_CH2 = 34,
+ DMA1_PERIPH_TIM2_CH4 = 34 | ALTERNATE1, /* Same as TIM2_CH2. */
+
+
+ DMA1_PERIPH_TIM17_CH1_1 = 35,
+ DMA1_PERIPH_TIM17_UP_1 = 35 | ALTERNATE1, /* Same as TIM17_CH1 */
+ DMA1_PERIPH_TIM3_CH3 = 36,
+ DMA1_PERIPH_TIM3_CH4 = 37,
+ DMA1_PERIPH_TIM3_UP = 37 | ALTERNATE1, /* Same as TIM3_CH4 */
+ DMA1_PERIPH_TIM7_UP = 38,
+ DMA1_PERIPH_DAC_CH2 = 38 | ALTERNATE1, /* Same as TIM7_UP */
+ DMA1_PERIPH_QUADSPI = 39,
+ DMA1_PERIPH_TIM3_CH1 = 40,
+ DMA1_PERIPH_TIM3_TRIG = 40 | ALTERNATE1, /* Same as TIM3_CH1 */
+ DMA1_PERIPH_TIM17_CH1_2 = 41,
+ DMA1_PERIPH_TIM17_UP_2 = 41 | ALTERNATE1, /* Same as TIM17_CH1 */
+
+ DMA1_PERIPH_TIM4_CH1 = 42,
+ DMA_RESERVED(DMA1) = 43,
+ DMA1_PERIPH_TIM6_UP = 44,
+ DMA1_PERIPH_DAC_CH1 = 44 | ALTERNATE1, /* Same as TIM6_UP */
+ DMA1_PERIPH_TIM4_CH2 = 45,
+ DMA1_PERIPH_TIM4_CH3 = 46,
+ DMA_RESERVED(DMA1) = 47,
+ DMA1_PERIPH_TIM4_UP = 48,
+
+ DMA_DMA1_PERIHP_RESERVED5 = 49,
+ DMA1_PERIPH_TIM1_CH1 = 50,
+ DMA1_PERIPH_TIM1_CH2 = 51,
+ DMA1_PERIPH_TIM1_CH4 = 52,
+ DMA1_PERIPH_TIM1_TRIG = 52 | ALTERNATE1, /* Same as TIM1_TRIG */
+ DMA1_PERIPH_TIM1_COM = 52 | ALTERNATE2, /* Same as TIM1_TRIG */
+ DMA1_PERIPH_TIM15_CH1 = 53,
+ DMA1_PERIPH_TIM15_UP = 53 | ALTERNATE1, /* Same as TIM15_CH1 */
+ DMA1_PERIPH_TIM15_TRIG = 53 | ALTERNATE2, /* Same as TIM15_CH1 */
+ DMA1_PERIPH_TIM15_COM = 53 | ALTERNATE3, /* Same as TIM15_CH1 */
+ DMA1_PERIPH_TIM1_UP = 54,
+ DMA1_PERIPH_TIM1_CH3 = 55,
+
+ DMA2_DMA1_SWITCH__ = 56,
+
+ DMA2_PERIPH_I2C4_RX = 56,
+ DMA2_PERIPH_I2C4_TX = 57,
+ DMA2_PERIPH_ADC1 = 58,
+ DMA2_PERIPH_ADC2 = 59,
+ DMA2_PERIPH_ADC3 = 60,
+ DMA2_PERIPH_DCMI_1 = 61,
+ DMA_RESERVED(DMA2) = 62,
+
+ DMA2_PERIPH_SAI1_A_1 = 63,
+ DMA2_PERIPH_SAI1_B_1 = 64,
+ DMA2_PERIPH_SAI2_A = 65,
+ DMA2_PERIPH_SAI2_B = 66,
+ DMA_RESERVED(DMA2) = 67,
+ DMA2_PERIPH_SAI1_A_2 = 68,
+ DMA2_PERIPH_SAI1_B_2 = 69,
+
+ DMA2_PERIPH_UART5_TX = 70,
+ DMA2_PERIPH_UART5_RX = 71,
+ DMA2_PERIPH_UART4_TX = 72,
+ DMA_RESERVED(DMA2) = 73,
+ DMA2_PERIPH_UART4_RX = 74,
+ DMA2_PERIPH_USART1_TX = 75,
+ DMA2_PERIPH_USART1_RX = 76,
+
+ DMA2_PERIPH_SPI3_RX = 77,
+ DMA2_PERIPH_SPI3_TX = 78,
+ DMA_RESERVED(DMA2) = 79,
+ DMA2_PERIPH_TIM6_UP = 80,
+ DMA2_PERIPH_DAC_CH1 = 80 | ALTERNATE1, /* Same as TIM6_UP */
+ DMA2_PERIPH_TIM7_UP = 81,
+ DMA2_PERIPH_DAC_CH2 = 81 | ALTERNATE1, /* Same as TIM7_UP */
+ DMA_RESERVED(DMA2) = 82,
+ DMA2_PERIPH_QUADSPI = 83,
+
+ DMA2_PERIPH_SWPMI1_RX = 84,
+ DMA2_PERIPH_SWPMI1_TX = 85,
+ DMA2_PERIPH_SPI1_RX = 86,
+ DMA2_PERIPH_SPI1_TX = 87,
+ DMA2_PERIPH_DCMI_2 = 88,
+ DMA2_PERIPH_LPUART1_TX = 89,
+ DMA2_PERIPH_LPUART1_RX = 90,
+
+
+ DMA2_PERIPH_TIM5_CH4 = 91,
+ DMA2_PERIPH_TIM5_TRIG = 91 | ALTERNATE1, /* Same as TIM5_CH4 */
+ DMA2_PERIPH_TIM5_CH3 = 92,
+ DMA2_PERIPH_TIM5_UP = 92 | ALTERNATE1, /* Same as TIM5_CH3 */
+ DMA_RESERVED(DMA2) = 93,
+ DMA2_PERIPH_TIM5_CH2 = 94,
+ DMA2_PERIPH_TIM5_CH1 = 95,
+ DMA2_PERIPH_I2C1_RX = 96,
+ DMA2_PERIPH_I2C1_TX = 97,
+
+ DMA2_PERIPH_AES_IN_1 = 98,
+ DMA2_PERIPH_AES_OUT_1 = 99,
+ DMA2_PERIPH_AES_OUT_2 = 100,
+ DMA_RESERVED(DMA2) = 101,
+ DMA2_PERIPH_AES_IN_2 = 102,
+ DMA_RESERVED(DMA2) = 103,
+ DMA2_PERIPH_HASH_IN = 104,
+
+ DMA2_PERIPH_TIM8_CH3 = 105,
+ DMA2_PERIPH_TIM8_UP = 105 | ALTERNATE1, /* Same as TIM8_CH3 */
+ DMA2_PERIPH_TIM8_CH4 = 106,
+ DMA2_PERIPH_TIM8_TRIG = 106 | ALTERNATE1, /* Same as TIM8_CH4 */
+ DMA2_PERIPH_TIM8_COM = 106 | ALTERNATE2, /* Same as TIM8_CH4 */
+ DMA_RESERVED(DMA2) = 107,
+ DMA2_PERIPH_SDMMC1_1 = 108,
+ DMA2_PERIPH_SDMMC1_2 = 109,
+ DMA2_PERIPH_TIM8_CH1 = 110,
+ DMA2_PERIPH_TIM8_CH2 = 111,
+
+
+ DMA_PERIPH_SENTINEL,
+} dma_peripheral_t;
+
+
+/* Defines a DMA channel. */
+typedef struct {
+ uint8_t dma; /* 0 = DMA1, 1 = DMA2 */
+ uint8_t chan; /* 0 - 6 */
+} dma_channel_t;
+
+
+/*
+ * Defines a DMA channel allocated for memory-to-peripheral transfers. This
+ * structure is only nominally different from dma_channel_t in order to provide
+ * rudimentary type-checking.
+ */
+typedef struct {
+ dma_channel_t c_;
+} dma_mem2p_channel_t;
+
+/*
+ * Defines a DMA channel allocated for peripheral-to-memory transfers. This
+ * structure is only nominally different from dma_channel_t in order to provide
+ * rudimentary type-checking.
+ */
+typedef struct {
+ dma_channel_t c_;
+} dma_p2mem_channel_t;
+
+/* Defines a DMA channel allocated for mem2mem transfers.
+ * This structure is only nominally different from dma_channel_t
+ * in order to provide rudimentary type-checking.
+ */
+typedef struct {
+ dma_channel_t c_;
+} dma_mem2mem_channel_t;
+
+#define DMA_CHAN_ERROR ((dma_channel_t) { .dma = 0xff, .chan = 0xff })
+
+typedef struct {
+ bool transfer_complete_interrupt_enable;
+ bool half_transfer_interrupt_enable;
+ bool transfer_error_interrupt_enable;
+
+ bool circular_mode;
+ bool peripheral_increment;
+ bool memory_increment;
+
+ dma_size_t peripheral_block_size;
+ dma_size_t memory_block_size;
+
+ dma_priority_level_t priority;
+} dma_opts_t;
+
+#define DEFAULT_DMA_OPTS \
+ ((dma_opts_t) { .memory_increment = 1, \
+ .peripheral_increment = 0, \
+ .transfer_complete_interrupt_enable = 0, \
+ .half_transfer_interrupt_enable = 0, \
+ .transfer_error_interrupt_enable = 0, \
+ .circular_mode = 0, \
+ .peripheral_block_size = DMA_SIZE_8_BITS, \
+ .memory_block_size = DMA_SIZE_8_BITS, \
+ .priority = DMA_PRIORITY_LEVEL_MEDIUM })
+
+dma_p2mem_channel_t select_dma_channel_p2mem(
+ dma_peripheral_t peripheral,
+ dma_opts_t* opts_in,
+ int* error);
+
+dma_mem2p_channel_t select_dma_channel_mem2p(
+ dma_peripheral_t peripheral,
+ dma_opts_t* opts_in,
+ int* error);
+
+/* Returns a dma channel used for memory-to-memory transfers.
+ *
+ * channel - the channel this dma should use. The channel should
+ * be on the range [0-13]. The channels [0-6] refer to the 7 channels
+ * on DMA1, where channels [7-13] refer to the 7 channels on DMA2.
+ *
+ * If `channel` is -1, then the highest unused dma channel is selected.
+ */
+dma_mem2mem_channel_t select_dma_channel_mem2mem(
+ int channel,
+ dma_opts_t* opts,
+ int* error_out);
+
+void dma_mem2p_initiate_transfer(
+ dma_mem2p_channel_t chan, const void* from_loc, uint16_t nblocks);
+
+void dma_p2mem_initiate_transfer(
+ dma_p2mem_channel_t chan, void* to_loc, uint16_t nblocks);
+
+void dma_mem2mem_initiate_transfer(
+ dma_mem2mem_channel_t chan,
+ void* to_loc,
+ const void* from_loc,
+ uint16_t nblocks);
+
+void release_dma_channel(dma_channel_t chan);
+
+interrupt_t dma_channel_get_interrupt(dma_channel_t chan);
+
+#endif