diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2020-11-16 21:02:48 -0700 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2020-11-16 21:02:48 -0700 |
commit | c0e1b4cdf20c55f2cbbdf3a5889f447974135fd8 (patch) | |
tree | 003c27f4551f02de304da28cc60314a4516c40ed | |
parent | cd115ba47253ce8d2680178248116d251abacb23 (diff) | |
download | stm32l4-c0e1b4cdf20c55f2cbbdf3a5889f447974135fd8.tar.gz stm32l4-c0e1b4cdf20c55f2cbbdf3a5889f447974135fd8.tar.bz2 stm32l4-c0e1b4cdf20c55f2cbbdf3a5889f447974135fd8.zip |
Got the DMA to send a simple message through UART2.
-rw-r--r-- | 02-usart/include/arch/arm/arch.h | 7 | ||||
-rw-r--r-- | 02-usart/include/arch/x86_64/arch.h | 3 | ||||
-rw-r--r-- | 02-usart/include/common.h | 5 | ||||
-rw-r--r-- | 02-usart/include/dma.h | 27 | ||||
-rw-r--r-- | 02-usart/include/mem.h | 12 | ||||
-rw-r--r-- | 02-usart/include/rcc.h | 18 | ||||
-rw-r--r-- | 02-usart/include/usart.h | 38 | ||||
-rw-r--r-- | 02-usart/src/main.c | 34 | ||||
-rw-r--r-- | 02-usart/src/mem.c | 11 | ||||
-rw-r--r-- | 02-usart/src/usart.c | 18 | ||||
-rw-r--r-- | 02-usart/tests/test_dma.c | 3 |
11 files changed, 153 insertions, 23 deletions
diff --git a/02-usart/include/arch/arm/arch.h b/02-usart/include/arch/arm/arch.h index 904cbdb..6c10213 100644 --- a/02-usart/include/arch/arm/arch.h +++ b/02-usart/include/arch/arm/arch.h @@ -7,6 +7,7 @@ #define enable_interrupts() \ asm volatile(" cpsie i ") + #define DMA1_BASE (0x40020000) #define DMA2_BASE (0x40020400) @@ -17,4 +18,10 @@ #define GPIOB_BASE (0x48000400) #define GPIOC_BASE (0x48000800) +#define SRAM1_BASE (0x20000000) +#define SRAM2_BASE (0x2000C000) + +#include <stdint.h> +_Static_assert(sizeof(void*) == sizeof(uint32_t), "Pointers must be 32 bits"); + #endif /* ARCH_H_ */ diff --git a/02-usart/include/arch/x86_64/arch.h b/02-usart/include/arch/x86_64/arch.h index 43f6077..2b99239 100644 --- a/02-usart/include/arch/x86_64/arch.h +++ b/02-usart/include/arch/x86_64/arch.h @@ -16,4 +16,7 @@ #define GPIOB_BASE (load_fake_ahb2__() + 0x400) #define GPIOC_BASE (load_fake_ahb2__() + 0x800) +#define SRAM1_BASE (load_fake_sram1__() + 0x0) +#define SRAM2_BASE (load_fake_sram2__() + 0x0) + #endif /* ARCH_H_ */ diff --git a/02-usart/include/common.h b/02-usart/include/common.h index 01b6a47..8e0cb06 100644 --- a/02-usart/include/common.h +++ b/02-usart/include/common.h @@ -31,6 +31,9 @@ #define RESERVE(type) \ __IO type RESERVED_MACRO_CONCAT(_r, __COUNTER__) -typedef uint32_t bits_t; +#define ptr2reg(ptr) \ + ((uint32_t) (ptrdiff_t) (ptr)) + +typedef __IO uint32_t bits_t; #endif /* COMMON_H */ diff --git a/02-usart/include/dma.h b/02-usart/include/dma.h index 57462f9..229b732 100644 --- a/02-usart/include/dma.h +++ b/02-usart/include/dma.h @@ -30,9 +30,14 @@ typedef enum { DMA_PRIORITY_LEVEL_VERY_HIGH = 3 } dma_priority_level; +typedef enum { + READ_FROM_PERIPHERAL = 0, + READ_FROM_MEMORY = 1, +} dma_dir_t; + typedef struct { union { - uint32_t cc_r; + __IO uint32_t cc_r; struct { bits_t en:1; // channel enable bits_t tcie:1; // transfer complete interrupt enable @@ -52,28 +57,28 @@ typedef struct { /* Number of data to transfer. */ union { - uint32_t cndt_r; + __IO uint32_t cndt_r; struct { - uint16_t ndt; // Number of data to transfer. - uint16_t reserved; + bits_t ndt:16; // Number of data to transfer. + bits_t reserved:16; } cndt_bf; }; /* DMA channel peripheral address register. * Defines a memory address if mem2mem is set. */ - uint32_t cpa_r; + __IO uint32_t cpa_r; /* DMA channel memory address register. * Defines another perpipheral address if peripheral-periphal mode is set. */ - uint32_t cma_r; + __IO uint32_t cma_r; - uint32_t reserved; + __IO uint32_t reserved; } dma_channel_config_t; typedef struct { // DMA Interrupt status register. union { - uint32_t is_r; + __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 @@ -109,7 +114,7 @@ typedef struct { // DMA Interrupt flag clear register union { - uint32_t ifc_r; + __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 @@ -144,11 +149,11 @@ typedef struct { dma_channel_config_t channel_config[7]; - uint32_t reserved[5]; + __IO uint32_t reserved[5]; /* DMA channel selection register. */ union { - uint32_t csel_r; + __IO uint32_t csel_r; struct { bits_t c1s:4; // DMA channel 1 selection. bits_t c2s:4; // DMA channel 2 selection. diff --git a/02-usart/include/mem.h b/02-usart/include/mem.h new file mode 100644 index 0000000..fefe53d --- /dev/null +++ b/02-usart/include/mem.h @@ -0,0 +1,12 @@ +#ifndef MEM_H_ +#define MEM_H_ + +#include "common.h" + +void memcpy_(void* dest, const void* src, size_t len); + +#ifdef ARCH_STM32L4 +#define memcpy memcpy_ +#endif + +#endif diff --git a/02-usart/include/rcc.h b/02-usart/include/rcc.h index 7ed4dee..05f5e5f 100644 --- a/02-usart/include/rcc.h +++ b/02-usart/include/rcc.h @@ -33,7 +33,21 @@ typedef struct { __IO uint32_t reserved_4; /* Not used. offset 0x44. */ - __IO uint32_t ahb1en_r; /* AHB1 Peripheral enable register. 0x48 */ + __IO union { + __IO uint32_t ahb1en_r; /* AHB1 Peripheral enable register. 0x48 */ + struct { + bits_t dma1en:1; /* DMA1 clock enable. */ + bits_t dma2en:1; /* DMA2 clock enable. */ + bits_t reserved0:6; + bits_t flashen:1; /* Flash memory interface clock enable. */ + bits_t reserved1:3; + bits_t crcen:1; /* CRC clock enable. */ + bits_t reserved2:3; + bits_t tscen:1; /* Touch sensing controller clock enable. */ + bits_t dmad2en:1; /* DMA2D clock enabled. */ + bits_t reserved3:14; + } ahb1en_bf; + }; __IO uint32_t ahb2en_r; /* AHB2 Peripheral enable register. 0x4C */ __IO uint32_t ahb3en_r; /* AHB3 Peripheral enable register. 0x50 */ @@ -60,6 +74,8 @@ typedef struct { __IO uint32_t ccip_r; /* 0x88 */ } PACKED rcc_t; +static_assert(offsetof(rcc_t, ccip_r) == 0x88, "Offset check failed."); + #define RCC (*(__IO rcc_t*)RCC_BASE) /* Macros to operate on the RCC registers. */ diff --git a/02-usart/include/usart.h b/02-usart/include/usart.h index d806397..c645e92 100644 --- a/02-usart/include/usart.h +++ b/02-usart/include/usart.h @@ -6,6 +6,7 @@ #include "common.h" #include "rcc.h" +#include <assert.h> #define USART1 (* (__IO usart_t*) USART1_BASE) #define USART2 (* (__IO usart_t*) USART2_BASE) @@ -23,7 +24,7 @@ typedef enum { typedef struct { /* USART configuration registers 0x04 - 0x0c. */ union { - uint32_t c_r1; + __IO uint32_t c_r1; struct { bits_t ue:1; /* UART enable */ bits_t uesm:1; /* UART enabled in stop mode. */ @@ -49,10 +50,10 @@ typedef struct { bits_t reserved:3; } PACKED c1_bf; /* c1_bf = c1 bit field */ }; /* USART Control Register 1. */ - uint32_t c_r2; + __IO uint32_t c_r2; union { - uint32_t c_r3; + __IO uint32_t c_r3; struct { bits_t eie:1; // Error interrupt enable. bits_t iren:1; // IrDA mode enabled @@ -88,7 +89,7 @@ typedef struct { /* USART ISR register. Offset = 0x1c*/ union { - uint32_t is_r; /* Interrupt service register. */ + __IO uint32_t is_r; /* Interrupt service register. */ struct { bits_t pe:1; // Parity error bits_t fe:1; // Framing error @@ -118,11 +119,36 @@ typedef struct { bits_t reserved2:6; } PACKED is_bf; /* Interrupt servite bit field. */ }; - uint32_t ic_r; + union { + __IO uint32_t ic_r; + struct { + bits_t pecf:1; // Parity error clear flag + bits_t fecf:1; // Framing error clear flag + bits_t ncf:1; // Noise detected clear flag + bits_t orecf:1; // Overrun error clear flag + bits_t idlecf:1; // Idle line detected clear flag + bits_t reserved0:1; + bits_t tccf:1; // Transmission complete clear flag + bits_t tcbgtcf:1; // Transmission completed before guard time clear flag + bits_t lbdcf:1; // LIN break detection clear flag + bits_t ctscf:1; // CTS clear flag + bits_t reserved1:1; + bits_t rtocf:1; // Receiver timeout clear flag + bits_t eobcf:1; // End of block clear flag + bits_t reserved2:4; + bits_t cmcf:1; // Character match clear flag + bits_t reserved3:2; // Character match clear flag + bits_t wucf:1; // Wakeup from Stop mode clear flag. + bits_t reserved4:11; + } PACKED ic_bf; + }; uint32_t rd_r; uint32_t td_r; } usart_t; +static_assert(offsetof(usart_t, ic_r) == 0x20, "Offset assertion failed."); +static_assert(offsetof(usart_t, rd_r) == 0x24, "Offset assertion failed."); + typedef enum { OVERSAMPLE_8, OVERSAMPLE_16 @@ -170,6 +196,8 @@ void usart_set_parity(__IO usart_t* usart, usart_parity_t parity); void usart_set_enabled(__IO usart_t* usart, usart_enable_t enabled); +void usart_enable_dma(__IO usart_t* usart, usart_enable_t enabled); + /* * Send a byte on the usart, This command blocks until the data * is fully sent. diff --git a/02-usart/src/main.c b/02-usart/src/main.c index 5f45e0b..b4f7dd7 100644 --- a/02-usart/src/main.c +++ b/02-usart/src/main.c @@ -1,4 +1,7 @@ +#include "string.h" +#include "mem.h" +#include "dma.h" #include "arch.h" #include "clock.h" #include "delay.h" @@ -8,7 +11,7 @@ volatile uint32_t delay_amt = 20000000 / 4; -int enable_usart2(uint32_t baud_rate) +int setup_usart2(uint32_t baud_rate) { __IO gpio_port_t* port_a = enable_gpio(GPIO_PORT_A); enable_hsi(&RCC, true); @@ -36,7 +39,6 @@ int enable_usart2(uint32_t baud_rate) USART2.c_r3 = 0; usart_set_divisor(&USART2, 16000000 / baud_rate); - usart_set_enabled(&USART2, USART_ENABLE_TX | USART_ENABLE_RX); } int enable_usart1(uint32_t baud_rate) @@ -88,10 +90,34 @@ int main() /* Enable a higher clock frequency. */ set_system_clock_MHz(80); - enable_usart2(115200); + setup_usart2(115200); + + + char* into = (char*) (SRAM1_BASE + 50); + const char* hello = "Hello, Chester Cheeto!\r\n"; + int len = strlen(hello); + memcpy(into, hello, len + 1); + + usart_enable_dma(&USART2, USART_ENABLE_TX); + usart_set_enabled(&USART2, USART_ENABLE_TX | USART_ENABLE_RX); + + pin_on(pin3); + + RCC.ahb1en_bf.dma1en = 1; /* Enable DMA1 Clock. */ + DMA1.csel_bf.c7s = 0x2; /* Select USART2_TX for the sel. */ + DMA1.channel_config[6].cc_r = 0; + DMA1.channel_config[6].cc_bf.dir = READ_FROM_MEMORY; + DMA1.channel_config[6].cc_bf.minc = 1; + DMA1.channel_config[6].cc_bf.pl = DMA_PRIORITY_LEVEL_VERY_HIGH; + DMA1.channel_config[6].cndt_bf.ndt = len; + DMA1.channel_config[6].cpa_r = ptr2reg(&USART2.td_r); + DMA1.channel_config[6].cma_r = ptr2reg(into); + + USART2.ic_bf.tccf = 1; + DMA1.channel_config[6].cc_bf.en = 1; pin_on(pin3); - usart_transmit_str_sync(&USART2, "Hello, World\n"); + // usart_transmit_str_sync(&USART2, into); for(;;); } diff --git a/02-usart/src/mem.c b/02-usart/src/mem.c new file mode 100644 index 0000000..5772bdc --- /dev/null +++ b/02-usart/src/mem.c @@ -0,0 +1,11 @@ +#include "mem.h" +#include "common.h" + +void memcpy_(void* dest, const void* src, size_t len) +{ + uint8_t* dest_ = (uint8_t*) dest; + uint8_t* src_ = (uint8_t*) src; + + while ((len--) > 0) + *(dest_ ++) = *(src_ ++); +} diff --git a/02-usart/src/usart.c b/02-usart/src/usart.c index 42297a8..d4073d0 100644 --- a/02-usart/src/usart.c +++ b/02-usart/src/usart.c @@ -78,3 +78,21 @@ void usart_transmit_str_sync(__IO usart_t* usart, const char* str) usart_transmit_byte_sync(usart, *(str ++)); } } + +void usart_enable_dma(__IO usart_t* usart, usart_enable_t enabled) +{ + switch(enabled) { + case USART_ENABLE_DISABLED: + usart->c3_bf.dmar = 0; + usart->c3_bf.dmat = 0; + break; + + case USART_ENABLE_TX: + usart->c3_bf.dmat = 1; + break; + + case USART_ENABLE_RX: + usart->c3_bf.dmar = 1; + break; + }; +} diff --git a/02-usart/tests/test_dma.c b/02-usart/tests/test_dma.c index 7c2127a..7704590 100644 --- a/02-usart/tests/test_dma.c +++ b/02-usart/tests/test_dma.c @@ -5,7 +5,8 @@ #include <stdlib.h> #include <memory.h> -TEST(dma, smoke) { +TEST(dma, smoke) +{ dma_t* dma = &DMA1; memset(dma, sizeof(dma), 0); |