aboutsummaryrefslogtreecommitdiff
path: root/02-usart/include/kern/dma/dma_manager.h
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2020-11-22 01:06:30 -0700
committerJosh Rahm <joshuarahm@gmail.com>2020-11-22 01:06:30 -0700
commit9f28e53c71d28d04e2775c59944d2887a99f1e86 (patch)
treec0ecb2872c6d27acf08aa73919d709f949200de5 /02-usart/include/kern/dma/dma_manager.h
parentebb9123c00d1e9629376b6f0a2f1f4e7e550c2af (diff)
downloadstm32l4-9f28e53c71d28d04e2775c59944d2887a99f1e86.tar.gz
stm32l4-9f28e53c71d28d04e2775c59944d2887a99f1e86.tar.bz2
stm32l4-9f28e53c71d28d04e2775c59944d2887a99f1e86.zip
Large reorganization.
What was in core/ is now moved to arch/stm34l4xxx/peripherals. This new directory is *supposed to* to contain raw header files defining just the pertinent register structures for the various peripherals. Peripheral management belongs somewhere in the new `kern/..` directories. This is not completely the case at the moment, so more refactoring needs to be done. What was sitting in the root has now been moved into the kern/ directory. The kern/ directory is to contain everything else other than raw device register definitions. The root of the kern/ tree is reserved for standard library-esque headers. The kern/<peripheral> directory contains management systems for that peripheral. (At the moment DMA is the only peripheral with a decent management system.) Preferably these peripheral systems should only include their correlating header in arch/stm34l4xxx/peripherals, and use other management systems for handling other peripherals rather than manipulating their raw registers directly. (Though this ideal will require much more critical mass of management systems.)
Diffstat (limited to '02-usart/include/kern/dma/dma_manager.h')
-rw-r--r--02-usart/include/kern/dma/dma_manager.h279
1 files changed, 279 insertions, 0 deletions
diff --git a/02-usart/include/kern/dma/dma_manager.h b/02-usart/include/kern/dma/dma_manager.h
new file mode 100644
index 0000000..0d17bd5
--- /dev/null
+++ b/02-usart/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