aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--02-usart/include/arch/arm/arch.h7
-rw-r--r--02-usart/include/arch/x86_64/arch.h3
-rw-r--r--02-usart/include/common.h5
-rw-r--r--02-usart/include/dma.h27
-rw-r--r--02-usart/include/mem.h12
-rw-r--r--02-usart/include/rcc.h18
-rw-r--r--02-usart/include/usart.h38
-rw-r--r--02-usart/src/main.c34
-rw-r--r--02-usart/src/mem.c11
-rw-r--r--02-usart/src/usart.c18
-rw-r--r--02-usart/tests/test_dma.c3
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);