diff options
-rw-r--r-- | 02-usart/include/common.h | 5 | ||||
-rw-r--r-- | 02-usart/include/core/dma.h | 191 | ||||
-rw-r--r-- | 02-usart/src/core/init.c | 4 | ||||
-rw-r--r-- | 02-usart/tests/test_dma.c | 15 |
4 files changed, 106 insertions, 109 deletions
diff --git a/02-usart/include/common.h b/02-usart/include/common.h index f9cbe06..394dc62 100644 --- a/02-usart/include/common.h +++ b/02-usart/include/common.h @@ -17,6 +17,8 @@ #define __IO volatile #endif +#define CTZ(n) __builtin_ctz(n) + #define bool int #ifndef __cplusplus #define true 1 @@ -39,4 +41,7 @@ typedef __IO uint32_t bits_t; +#define regset(reg, mask, val) \ + (reg = (reg & ~mask) | (val << CTZ(mask))) + #endif /* COMMON_H */ diff --git a/02-usart/include/core/dma.h b/02-usart/include/core/dma.h index 1ae41a0..73bca76 100644 --- a/02-usart/include/core/dma.h +++ b/02-usart/include/core/dma.h @@ -36,33 +36,24 @@ typedef enum { } dma_dir_t; typedef struct { - union { - __IO uint32_t cc_r; - struct { - bits_t en:1; // channel enable - bits_t tcie:1; // transfer complete interrupt enable - bits_t htie:1; // half transfer interrupt enable - bits_t teie:1; // transfer error interrupt enable - bits_t dir:1; // data transfer direction - bits_t circ:1; // circular mode - bits_t pinc:1; // peripheral increment mode - bits_t minc:1; // memory increment mode - bits_t psize:2; // Peripheral size - bits_t msize:2; // Memory size - bits_t pl:2; // Priority level - bits_t mem2mem:1; // Memory to memory mode - bits_t reserved:17; - } PACKED cc_bf; - }; - - /* Number of data to transfer. */ - union { - __IO uint32_t cndt_r; - struct { - bits_t ndt:16; // Number of data to transfer. - bits_t reserved:16; - } cndt_bf; - }; + +#define dma_cc_en (1 << 0) // channel enable +#define dma_cc_tcie (1 << 1) // transfer complete interrupt enable +#define dma_cc_htie (1 << 2) // half transfer interrupt enable +#define dma_cc_teie (1 << 3) // transfer error interrupt enable +#define dma_cc_dir (1 << 4) // data transfer direction +#define dma_cc_circ (1 << 5) // circular mode +#define dma_cc_pinc (1 << 6) // peripheral increment mode +#define dma_cc_minc (1 << 7) // memory increment mode +#define dma_cc_psize (3 << 8) // Peripheral size +#define dma_cc_msize (3 << 10) // Memory size +#define dma_cc_pl (3 << 12) // Priority level +#define dma_cc_mem2mem (1 << 13) // Memory to memory mode + + __IO uint32_t cc_r; + + /* Number of data to transfer. Can only store a short. */ + __IO uint32_t cndt_r; /* DMA channel peripheral address register. * Defines a memory address if mem2mem is set. */ @@ -77,94 +68,80 @@ typedef struct { typedef struct { // DMA Interrupt status register. - union { - __IO uint32_t is_r; - struct { - bits_t gif1:1; // global interrupt flag for channel 1 - bits_t tcif1:1; // transfer complete (TC) flag for channel 1 - bits_t htif1:1; // half transfer (HT) flag for channel 1 - bits_t teif1:1; // transfer error (TE) flag for channel 1 - bits_t gif2:1; // global interrupt flag for channel 2 - bits_t tcif2:1; // transfer complete (TC) flag for channel 2 - bits_t htif2:1; // half transfer (HT) flag for channel 2 - bits_t teif2:1; // transfer error (TE) flag for channel 2 - bits_t gif3:1; // global interrupt flag for channel 3 - bits_t tcif3:1; // transfer complete (TC) flag for channel 3 - bits_t htif3:1; // half transfer (HT) flag for channel 3 - bits_t teif3:1; // transfer error (TE) flag for channel 3 - bits_t gif4:1; // global interrupt flag for channel 4 - bits_t tcif4:1; // transfer complete (TC) flag for channel 4 - bits_t htif4:1; // half transfer (HT) flag for channel 4 - bits_t teif4:1; // transfer error (TE) flag for channel 4 - bits_t gif5:1; // global interrupt flag for channel 5 - bits_t tcif5:1; // transfer complete (TC) flag for channel 5 - bits_t htif5:1; // half transfer (HT) flag for channel 5 - bits_t teif5:1; // transfer error (TE) flag for channel 5 - bits_t gif6:1; // global interrupt flag for channel 6 - bits_t tcif6:1; // transfer complete (TC) flag for channel 6 - bits_t htif6:1; // half transfer (HT) flag for channel 6 - bits_t teif6:1; // transfer error (TE) flag for channel 6 - bits_t gif7:1; // global interrupt flag for channel 7 - bits_t tcif7:1; // transfer complete (TC) flag for channel 7 - bits_t htif7:1; // half transfer (HT) flag for channel 7 - bits_t teif7:1; // transfer error (TE) flag for channel 7 - bits_t reserved:4; - } PACKED is_bf; - }; +#define dma_gif1 (1 << 0) // global interrupt flag for channel 1 +#define dma_tcif1 (1 << 1) // transfer complete (TC) flag for channel 1 +#define dma_htif1 (1 << 2) // half transfer (HT) flag for channel 1 +#define dma_teif1 (1 << 3) // transfer error (TE) flag for channel 1 +#define dma_gif2 (1 << 4) // global interrupt flag for channel 2 +#define dma_tcif2 (1 << 5) // transfer complete (TC) flag for channel 2 +#define dma_htif2 (1 << 6) // half transfer (HT) flag for channel 2 +#define dma_teif2 (1 << 7) // transfer error (TE) flag for channel 2 +#define dma_gif3 (1 << 8) // global interrupt flag for channel 3 +#define dma_tcif3 (1 << 9) // transfer complete (TC) flag for channel 3 +#define dma_htif3 (1 << 10) // half transfer (HT) flag for channel 3 +#define dma_teif3 (1 << 11) // transfer error (TE) flag for channel 3 +#define dma_gif4 (1 << 12) // global interrupt flag for channel 4 +#define dma_tcif4 (1 << 13) // transfer complete (TC) flag for channel 4 +#define dma_htif4 (1 << 14) // half transfer (HT) flag for channel 4 +#define dma_teif4 (1 << 15) // transfer error (TE) flag for channel 4 +#define dma_gif5 (1 << 16) // global interrupt flag for channel 5 +#define dma_tcif5 (1 << 17) // transfer complete (TC) flag for channel 5 +#define dma_htif5 (1 << 18) // half transfer (HT) flag for channel 5 +#define dma_teif5 (1 << 19) // transfer error (TE) flag for channel 5 +#define dma_gif6 (1 << 20) // global interrupt flag for channel 6 +#define dma_tcif6 (1 << 21) // transfer complete (TC) flag for channel 6 +#define dma_htif6 (1 << 22) // half transfer (HT) flag for channel 6 +#define dma_teif6 (1 << 23) // transfer error (TE) flag for channel 6 +#define dma_gif7 (1 << 24) // global interrupt flag for channel 7 +#define dma_tcif7 (1 << 25) // transfer complete (TC) flag for channel 7 +#define dma_htif7 (1 << 26) // half transfer (HT) flag for channel 7 +#define dma_teif7 (1 << 27) // transfer error (TE) flag for channel 7 + __IO uint32_t is_r; // DMA Interrupt flag clear register - union { - __IO uint32_t ifc_r; - struct { - bits_t cgif1:1; // global interrupt flag clear for channel 1 - bits_t ctcif1:1; // transfer complete flag clear for channel 1 - bits_t chtif1:1; // half transfer flag clear for channel 1 - bits_t cteif1:1; // transfer error flag clear for channel 1 - bits_t cgif2:1; // global interrupt flag clear for channel 2 - bits_t ctcif2:1; // transfer complete flag clear for channel 2 - bits_t chtif2:1; // half transfer flag clear for channel 2 - bits_t cteif2:1; // transfer error flag clear for channel 2 - bits_t cgif3:1; // global interrupt flag clear for channel 3 - bits_t ctcif3:1; // transfer complete flag clear for channel 3 - bits_t chtif3:1; // half transfer flag clear for channel 3 - bits_t cteif3:1; // transfer error flag clear for channel 3 - bits_t cgif4:1; // global interrupt flag clear for channel 4 - bits_t ctcif4:1; // transfer complete flag clear for channel 4 - bits_t chtif4:1; // half transfer flag clear for channel 4 - bits_t cteif4:1; // transfer error flag clear for channel 4 - bits_t cgif5:1; // global interrupt flag clear for channel 5 - bits_t ctcif5:1; // transfer complete flag clear for channel 5 - bits_t chtif5:1; // half transfer flag clear for channel 5 - bits_t cteif5:1; // transfer error flag clear for channel 5 - bits_t cgif6:1; // global interrupt flag clear for channel 6 - bits_t ctcif6:1; // transfer complete flag clear for channel 6 - bits_t chtif6:1; // half transfer flag clear for channel 6 - bits_t cteif6:1; // transfer error flag clear for channel 6 - bits_t cgif7:1; // global interrupt flag clear for channel 7 - bits_t ctcif7:1; // transfer complete flag clear for channel 7 - bits_t chtif7:1; // half transfer flag clear for channel 7 - bits_t cteif7:1; // transfer error flag clear for channel 7 - } PACKED ifc_bf; - }; +#define dma_cgif1 (1 << 0) // global interrupt flag clear for channel 1 +#define dma_ctcif1 (1 << 1) // transfer complete flag clear for channel 1 +#define dma_chtif1 (1 << 2) // half transfer flag clear for channel 1 +#define dma_cteif1 (1 << 3) // transfer error flag clear for channel 1 +#define dma_cgif2 (1 << 4) // global interrupt flag clear for channel 2 +#define dma_ctcif2 (1 << 5) // transfer complete flag clear for channel 2 +#define dma_chtif2 (1 << 6) // half transfer flag clear for channel 2 +#define dma_cteif2 (1 << 7) // transfer error flag clear for channel 2 +#define dma_cgif3 (1 << 8) // global interrupt flag clear for channel 3 +#define dma_ctcif3 (1 << 9) // transfer complete flag clear for channel 3 +#define dma_chtif3 (1 << 10) // half transfer flag clear for channel 3 +#define dma_cteif3 (1 << 11) // transfer error flag clear for channel 3 +#define dma_cgif4 (1 << 12) // global interrupt flag clear for channel 4 +#define dma_ctcif4 (1 << 13) // transfer complete flag clear for channel 4 +#define dma_chtif4 (1 << 14) // half transfer flag clear for channel 4 +#define dma_cteif4 (1 << 15) // transfer error flag clear for channel 4 +#define dma_cgif5 (1 << 16) // global interrupt flag clear for channel 5 +#define dma_ctcif5 (1 << 17) // transfer complete flag clear for channel 5 +#define dma_chtif5 (1 << 18) // half transfer flag clear for channel 5 +#define dma_cteif5 (1 << 19) // transfer error flag clear for channel 5 +#define dma_cgif6 (1 << 20) // global interrupt flag clear for channel 6 +#define dma_ctcif6 (1 << 21) // transfer complete flag clear for channel 6 +#define dma_chtif6 (1 << 22) // half transfer flag clear for channel 6 +#define dma_cteif6 (1 << 23) // transfer error flag clear for channel 6 +#define dma_cgif7 (1 << 24) // global interrupt flag clear for channel 7 +#define dma_ctcif7 (1 << 25) // transfer complete flag clear for channel 7 +#define dma_chtif7 (1 << 26) // half transfer flag clear for channel 7 +#define dma_cteif7 (1 << 27) // transfer error flag clear for channel 7 + __IO uint32_t ifc_r; dma_channel_config_t channel_config[7]; __IO uint32_t reserved[5]; /* DMA channel selection register. */ - union { - __IO uint32_t csel_r; - struct { - bits_t c1s:4; // DMA channel 1 selection. - bits_t c2s:4; // DMA channel 2 selection. - bits_t c3s:4; // DMA channel 3 selection. - bits_t c4s:4; // DMA channel 4 selection. - bits_t c5s:4; // DMA channel 5 selection. - bits_t c6s:4; // DMA channel 6 selection. - bits_t c7s:4; // DMA channel 7 selection. - bits_t reserved:4; - } PACKED csel_bf; - }; +#define c1s (0xF << 0) // DMA channel 1 selection. +#define c2s (0xF << 4) // DMA channel 2 selection. +#define c3s (0xF << 8) // DMA channel 3 selection. +#define c4s (0xF << 12) // DMA channel 4 selection. +#define c5s (0xF << 16) // DMA channel 5 selection. +#define c6s (0xF << 20) // DMA channel 6 selection. +#define c7s (0xF << 24) // DMA channel 7 selection. + __IO uint32_t csel_r; } dma_t; static_assert(offsetof(dma_t, csel_r) == 0xA8, "Offset check failed."); diff --git a/02-usart/src/core/init.c b/02-usart/src/core/init.c index e127006..0a7cb7f 100644 --- a/02-usart/src/core/init.c +++ b/02-usart/src/core/init.c @@ -5,6 +5,8 @@ void main(); /* These are defined in the linker script. */ + +#ifdef ARCH_STM32L4 extern uint32_t INIT_DATA_VALUES; extern uint32_t DATA_SEGMENT_START; extern uint32_t DATA_SEGMENT_STOP; @@ -43,3 +45,5 @@ _Noreturn void on_reset() for(;;); } + +#endif /* ARCH_STM32L4 */ diff --git a/02-usart/tests/test_dma.c b/02-usart/tests/test_dma.c index ae34a69..27ec022 100644 --- a/02-usart/tests/test_dma.c +++ b/02-usart/tests/test_dma.c @@ -10,13 +10,24 @@ TEST(dma, smoke) dma_t* dma = &DMA1; memset(dma, sizeof(dma), 0); - dma->is_bf.tcif1 = 1; + regset(dma->is_r, dma_tcif1, 1); ASSERT_EQ(dma->is_r, 2); - dma->is_bf.htif7 = 1; + regset(dma->is_r, dma_htif7, 1); ASSERT_EQ(dma->is_r, 67108866); } +TEST(dma, cc_regset) +{ + dma_t* dma = &DMA1; + memset(dma, sizeof(dma), 0); + + dma_channel_config_t* channel_config = &dma->channel_config[2]; + regset(channel_config->cc_r, dma_cc_msize, DMA_SIZE_32_BITS); + + ASSERT_EQ(channel_config->cc_r, 1 << 11); +} + TEST(dma, correct_align) { dma_t dma; |