From c1405b06d98b9b227fa7ff53c158f31d745eb505 Mon Sep 17 00:00:00 2001 From: Josh Rahm Date: Wed, 18 Nov 2020 21:11:01 -0700 Subject: Reorganize some file. Put thte core register libraries in a core/ subdirectory. --- 02-usart/genmake.pl | 15 ++- 02-usart/include/apb.h | 4 - 02-usart/include/clock.h | 126 --------------------- 02-usart/include/core/apb.h | 4 + 02-usart/include/core/clock.h | 126 +++++++++++++++++++++ 02-usart/include/core/dma.h | 172 ++++++++++++++++++++++++++++ 02-usart/include/core/flash.h | 20 ++++ 02-usart/include/core/gpio.h | 146 ++++++++++++++++++++++++ 02-usart/include/core/isr_vector.h | 24 ++++ 02-usart/include/core/isrs.i | 112 +++++++++++++++++++ 02-usart/include/core/rcc.h | 109 ++++++++++++++++++ 02-usart/include/core/system.h | 84 ++++++++++++++ 02-usart/include/core/usart.h | 223 +++++++++++++++++++++++++++++++++++++ 02-usart/include/dma.h | 172 ---------------------------- 02-usart/include/flash.h | 20 ---- 02-usart/include/gpio.h | 146 ------------------------ 02-usart/include/isr_vector.h | 24 ---- 02-usart/include/isrs.i | 112 ------------------- 02-usart/include/mem.h | 8 -- 02-usart/include/rcc.h | 109 ------------------ 02-usart/include/system.h | 84 -------------- 02-usart/include/usart.h | 223 ------------------------------------- 02-usart/src/clock.c | 106 ------------------ 02-usart/src/core/clock.c | 106 ++++++++++++++++++ 02-usart/src/core/gpio.c | 52 +++++++++ 02-usart/src/core/init.c | 45 ++++++++ 02-usart/src/core/isr_vector.c | 107 ++++++++++++++++++ 02-usart/src/core/usart.c | 145 ++++++++++++++++++++++++ 02-usart/src/gpio.c | 52 --------- 02-usart/src/init.c | 45 -------- 02-usart/src/isr_vector.c | 107 ------------------ 02-usart/src/main.c | 19 ++-- 02-usart/src/mem.c | 16 +-- 02-usart/src/spin.c | 2 +- 02-usart/src/usart.c | 145 ------------------------ 02-usart/tests/test_dma.c | 2 +- 02-usart/tests/test_lib.c | 19 ++++ 02-usart/tests/test_memory.c | 12 ++ 02-usart/tests/test_usart.c | 20 ++++ 39 files changed, 1558 insertions(+), 1505 deletions(-) delete mode 100644 02-usart/include/apb.h delete mode 100644 02-usart/include/clock.h create mode 100644 02-usart/include/core/apb.h create mode 100644 02-usart/include/core/clock.h create mode 100644 02-usart/include/core/dma.h create mode 100644 02-usart/include/core/flash.h create mode 100644 02-usart/include/core/gpio.h create mode 100644 02-usart/include/core/isr_vector.h create mode 100644 02-usart/include/core/isrs.i create mode 100644 02-usart/include/core/rcc.h create mode 100644 02-usart/include/core/system.h create mode 100644 02-usart/include/core/usart.h delete mode 100644 02-usart/include/dma.h delete mode 100644 02-usart/include/flash.h delete mode 100644 02-usart/include/gpio.h delete mode 100644 02-usart/include/isr_vector.h delete mode 100644 02-usart/include/isrs.i delete mode 100644 02-usart/include/rcc.h delete mode 100644 02-usart/include/system.h delete mode 100644 02-usart/include/usart.h delete mode 100644 02-usart/src/clock.c create mode 100644 02-usart/src/core/clock.c create mode 100644 02-usart/src/core/gpio.c create mode 100644 02-usart/src/core/init.c create mode 100644 02-usart/src/core/isr_vector.c create mode 100644 02-usart/src/core/usart.c delete mode 100644 02-usart/src/gpio.c delete mode 100644 02-usart/src/init.c delete mode 100644 02-usart/src/isr_vector.c delete mode 100644 02-usart/src/usart.c create mode 100644 02-usart/tests/test_lib.c create mode 100644 02-usart/tests/test_memory.c create mode 100644 02-usart/tests/test_usart.c diff --git a/02-usart/genmake.pl b/02-usart/genmake.pl index 54b1f80..89403ce 100755 --- a/02-usart/genmake.pl +++ b/02-usart/genmake.pl @@ -23,13 +23,19 @@ sub header_deps { } my @files; -find(sub { push @files, "src/$_" if $_ =~ /.*\.c/ }, "src/"); +find(sub { + push @files, "$File::Find::name" if $_ =~ /.*\.c/ + }, "src/"); my @test_files; -find(sub { push @test_files, "tests/$_" if $_ =~ /.*\.c/ }, "tests/"); +find(sub { + push @test_files, "$File::Find::name" if $_ =~ /.*\.c/ + }, "tests/"); my @header_files; -find(sub { push @header_files, "include/$_" if $_ =~ /.*\.h/ }, "include/" ); +find(sub { + push @header_files, "$File::Find::name" if $_ =~ /.*\.h/; + }, "include/" ); my $idempotency_hash=sha1_hex("@files @test_files @header_files"); @@ -70,10 +76,12 @@ foreach $file (@files) { # Emit the rule to make the object file. print "$obj_file: $deps_as_join\n\t"; + print "\@mkdir -p " . dirname($obj_file) . "\n\t"; print '$(CC) -c ' . $c_file . ' -o ' . $obj_file . ' $(CFLAGS)' . "\n\n"; # Emit the rule to make the assembly file. print "$s_file: $deps_as_join\n\t"; + print "\@mkdir -p " . dirname($obj_file) . "\n\t"; print '$(CC) -S ' . $c_file . ' -o ' . $s_file . ' $(CFLAGS)' . "\n\n"; } @@ -91,6 +99,7 @@ foreach $file (@test_files) { my $deps_as_join = join(" ", @deps); print "${outbinary}: $deps_as_join $obj_files_deps test_harness/test_harness.a\n\t"; + print "mkdir -p " . dirname($outbinary) . "\n\t"; print '$(CC) $(CFLAGS) -o' . ${outbinary} . ' ' . $c_file . ' ' . $obj_files_deps . " test_harness/test_harness.a\n\n"; print "$directories$basename:\n\t"; diff --git a/02-usart/include/apb.h b/02-usart/include/apb.h deleted file mode 100644 index 11fa7ab..0000000 --- a/02-usart/include/apb.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef H__APB_ -#define H__APB_ - -#endif /* H__APB_ */ diff --git a/02-usart/include/clock.h b/02-usart/include/clock.h deleted file mode 100644 index 46ac6f2..0000000 --- a/02-usart/include/clock.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef CLOCK_H__ -#define CLOCK_H__ - -#include -#include "rcc.h" - -#define PERIPH_BASE ((uint32_t)0x40000000) -#define AHBPERIPH_BASE (PERIPH_BASE + 0x00020000) -#define FLASH_R_BASE (AHBPERIPH_BASE + 0x00003C00) -#define PWR_BASE (PERIPH_BASE + 0x7000) -#define PWR_CSR_VOSF ((uint16_t)0x0010) /*!< Voltage Scaling select flag */ - -#ifndef __IO -#define __IO volatile -#endif - -typedef struct { - __IO uint32_t cr; - __IO uint32_t csr; -} pwr_t; - -// typedef struct { -// __IO uint32_t acr; -// __IO uint32_t pecr; -// __IO uint32_t pdkeyr; -// __IO uint32_t pekeyr; -// __IO uint32_t prgkeyr; -// __IO uint32_t optkeyr; -// __IO uint32_t sr; -// __IO uint32_t obr; -// __IO uint32_t wrpr; -// } flash_t; - -// #define FLASH (*(flash_t*) (FLASH_R_BASE)) -#define PWR (*(pwr_t*)(PWR_BASE)) - -/* Valid values for the PLLR/PLLQ bits of the PLLCFG register. */ -typedef enum { - PLL_DIVISOR_2 = 1, - PLL_DIVISOR_4 = 3, - PLL_DIVISOR_6 = 5, - PLL_DIVISOR_8 = 7, - PLL_DIVISOR_OFF = 0, -} pll_divisor_t; - -/* Valid values for the PLLP bits off the PLLCFG register. */ -typedef enum { - PLLP_DIVISOR_7 = 1, - PLLP_DIVISOR_17 = 3, - PLLP_DIVISOR_OFF = 0, -} pllp_divisor_t; - -/* Valid values for the PLLM bits of the PLLCFG register. */ -typedef enum { - PLLM_DIVISOR_1 = 0, - PLLM_DIVISOR_2 = 1, - PLLM_DIVISOR_3 = 2, - PLLM_DIVISOR_4 = 3, - PLLM_DIVISOR_5 = 4, - PLLM_DIVISOR_6 = 5, - PLLM_DIVISOR_7 = 6, - PLLM_DIVISOR_8 = 7, -} pllm_divisor_t; - -/* Possible sources for the input clock. */ -typedef enum { - PLL_SRC_NONE = 0, - PLL_SRC_MSI = 1, - PLL_SRC_HSI = 2, - PLL_SRC_HSE = 3, -} pll_src_t; - -/* Valid sources for the system clock. */ -typedef enum { - SYSTEM_CLOCK_SRC_MSI = 0, - SYSTEM_CLOCK_SRC_HSI = 1, - SYSTEM_CLOCK_SRC_HSE = 2, - SYSTEM_CLOCK_SRC_PLL = 3, -} system_clock_src_t; - -#define E_BADPLLN (-2) -#define E_BADPLLP_DIV (-1) -#define E_TIMEOUT (-3) -#define E_NOT_OFF (-4) -#define E_BAD_ARG (-5) - -#define enable_hsi(rcc, enabled) do { \ - if (enabled) { \ - (rcc)->c_r |= BIT(8); \ - } else { \ - (rcc)->c_r &= ~BIT(8); \ - } \ -} while(0) - -/* - * Sets the system clock to a full 80Mhz. - */ -int set_system_clock_MHz(uint8_t mhz); - -/* - * Set the PLL on. - */ -int pll_on(); - -/* - * Set the PLL off. - */ -int pll_off(); - -/* - * Sets the source of the system clock. - */ -int set_system_clock_src(system_clock_src_t src); - -/* - * Configure the PLL. - */ -int configure_pll( - uint8_t pllp_div_factor, pll_divisor_t pllr, /* System clock divisor. */ - pll_divisor_t pllq, /* Divison factor for PLL48M1CLK. */ - pllp_divisor_t pllp, /* Divison factor for PLLSAI2CLK. */ - uint8_t plln, /* PLL numerator. */ - pllm_divisor_t pllm, /* PLL denominator. */ - pll_src_t pllsrc /* PLL source */); - -#endif /* CLOCK_H__ */ diff --git a/02-usart/include/core/apb.h b/02-usart/include/core/apb.h new file mode 100644 index 0000000..11fa7ab --- /dev/null +++ b/02-usart/include/core/apb.h @@ -0,0 +1,4 @@ +#ifndef H__APB_ +#define H__APB_ + +#endif /* H__APB_ */ diff --git a/02-usart/include/core/clock.h b/02-usart/include/core/clock.h new file mode 100644 index 0000000..c3c58d7 --- /dev/null +++ b/02-usart/include/core/clock.h @@ -0,0 +1,126 @@ +#ifndef CORE_CLOCK_H__ +#define CORE_CLOCK_H__ + +#include +#include "rcc.h" + +#define PERIPH_BASE ((uint32_t)0x40000000) +#define AHBPERIPH_BASE (PERIPH_BASE + 0x00020000) +#define FLASH_R_BASE (AHBPERIPH_BASE + 0x00003C00) +#define PWR_BASE (PERIPH_BASE + 0x7000) +#define PWR_CSR_VOSF ((uint16_t)0x0010) /*!< Voltage Scaling select flag */ + +#ifndef __IO +#define __IO volatile +#endif + +typedef struct { + __IO uint32_t cr; + __IO uint32_t csr; +} pwr_t; + +// typedef struct { +// __IO uint32_t acr; +// __IO uint32_t pecr; +// __IO uint32_t pdkeyr; +// __IO uint32_t pekeyr; +// __IO uint32_t prgkeyr; +// __IO uint32_t optkeyr; +// __IO uint32_t sr; +// __IO uint32_t obr; +// __IO uint32_t wrpr; +// } flash_t; + +// #define FLASH (*(flash_t*) (FLASH_R_BASE)) +#define PWR (*(pwr_t*)(PWR_BASE)) + +/* Valid values for the PLLR/PLLQ bits of the PLLCFG register. */ +typedef enum { + PLL_DIVISOR_2 = 1, + PLL_DIVISOR_4 = 3, + PLL_DIVISOR_6 = 5, + PLL_DIVISOR_8 = 7, + PLL_DIVISOR_OFF = 0, +} pll_divisor_t; + +/* Valid values for the PLLP bits off the PLLCFG register. */ +typedef enum { + PLLP_DIVISOR_7 = 1, + PLLP_DIVISOR_17 = 3, + PLLP_DIVISOR_OFF = 0, +} pllp_divisor_t; + +/* Valid values for the PLLM bits of the PLLCFG register. */ +typedef enum { + PLLM_DIVISOR_1 = 0, + PLLM_DIVISOR_2 = 1, + PLLM_DIVISOR_3 = 2, + PLLM_DIVISOR_4 = 3, + PLLM_DIVISOR_5 = 4, + PLLM_DIVISOR_6 = 5, + PLLM_DIVISOR_7 = 6, + PLLM_DIVISOR_8 = 7, +} pllm_divisor_t; + +/* Possible sources for the input clock. */ +typedef enum { + PLL_SRC_NONE = 0, + PLL_SRC_MSI = 1, + PLL_SRC_HSI = 2, + PLL_SRC_HSE = 3, +} pll_src_t; + +/* Valid sources for the system clock. */ +typedef enum { + SYSTEM_CLOCK_SRC_MSI = 0, + SYSTEM_CLOCK_SRC_HSI = 1, + SYSTEM_CLOCK_SRC_HSE = 2, + SYSTEM_CLOCK_SRC_PLL = 3, +} system_clock_src_t; + +#define E_BADPLLN (-2) +#define E_BADPLLP_DIV (-1) +#define E_TIMEOUT (-3) +#define E_NOT_OFF (-4) +#define E_BAD_ARG (-5) + +#define enable_hsi(rcc, enabled) do { \ + if (enabled) { \ + (rcc)->c_r |= BIT(8); \ + } else { \ + (rcc)->c_r &= ~BIT(8); \ + } \ +} while(0) + +/* + * Sets the system clock to a full 80Mhz. + */ +int set_system_clock_MHz(uint8_t mhz); + +/* + * Set the PLL on. + */ +int pll_on(); + +/* + * Set the PLL off. + */ +int pll_off(); + +/* + * Sets the source of the system clock. + */ +int set_system_clock_src(system_clock_src_t src); + +/* + * Configure the PLL. + */ +int configure_pll( + uint8_t pllp_div_factor, pll_divisor_t pllr, /* System clock divisor. */ + pll_divisor_t pllq, /* Divison factor for PLL48M1CLK. */ + pllp_divisor_t pllp, /* Divison factor for PLLSAI2CLK. */ + uint8_t plln, /* PLL numerator. */ + pllm_divisor_t pllm, /* PLL denominator. */ + pll_src_t pllsrc /* PLL source */); + +#endif /* CORE_CLOCK_H__ */ diff --git a/02-usart/include/core/dma.h b/02-usart/include/core/dma.h new file mode 100644 index 0000000..1ae41a0 --- /dev/null +++ b/02-usart/include/core/dma.h @@ -0,0 +1,172 @@ +#ifndef CORE_DMA_H_ +#define CORE_DMA_H_ + +/* + * Header file for definining the DMA (Direct Memory Access). + * + * A DMA is used to perform data transfers between segments of memory + * or between memory and peripherals. + * + * There are 2 DMA's on the chip. Each with 7 channels. + */ + +#include "common.h" +#include +#include + +#define DMA1 (* (dma_t*) DMA1_BASE) +#define DMA2 (* (dma_t*) DMA2_BASE) + +typedef enum { + DMA_SIZE_8_BITS = 0, + DMA_SIZE_16_BITS = 1, + DMA_SIZE_32_BITS = 2, +} dma_size_t; + +typedef enum { + DMA_PRIORITY_LEVEL_LOW = 0, + DMA_PRIORITY_LEVEL_MEDIUM = 1, + DMA_PRIORITY_LEVEL_HIGH = 2, + 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 { + __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; + }; + + /* DMA channel peripheral address register. + * Defines a memory address if mem2mem is set. */ + __IO uint32_t cpa_r; + + /* DMA channel memory address register. + * Defines another perpipheral address if peripheral-periphal mode is set. */ + __IO uint32_t cma_r; + + __IO uint32_t reserved; +} dma_channel_config_t; + +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; + }; + + // 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; + }; + + 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; + }; +} dma_t; + +static_assert(offsetof(dma_t, csel_r) == 0xA8, "Offset check failed."); + +#endif /* CORE_DMA_H_ */ diff --git a/02-usart/include/core/flash.h b/02-usart/include/core/flash.h new file mode 100644 index 0000000..a163a25 --- /dev/null +++ b/02-usart/include/core/flash.h @@ -0,0 +1,20 @@ +#ifndef H__FLASH_ +#define H__FLASH_ + +#include "common.h" + +/* + * Header file for dealing with flash. + */ + +#define FLASH_BASE 0x40022000 + +typedef struct { + __IO uint32_t ac_r; /* Flash access control register. */ + + /* TODO fill out the rest. */ +} PACKED flash_t; + +#define FLASH (*(__IO flash_t*)FLASH_BASE) + +#endif /* H__FLASH_ */ diff --git a/02-usart/include/core/gpio.h b/02-usart/include/core/gpio.h new file mode 100644 index 0000000..856a176 --- /dev/null +++ b/02-usart/include/core/gpio.h @@ -0,0 +1,146 @@ +#ifndef CORE_GPIO_H__ +#define CORE_GPIO_H__ + +#include "common.h" +#include "rcc.h" + +#include + +/* + * Possible GPIO ports. + */ +typedef enum { + GPIO_PORT_A = 0, + GPIO_PORT_B = 1, + GPIO_PORT_C = 2, + GPIO_PORT_D = 3 +} gpio_port_number_t; + +/* + * Structure defining the layout of the layout of the GPIO registers on the + * stm32l432 development board. + */ +typedef struct GPIO_PORT_STR { + __IO uint32_t mode_r; /* Mode register */ + __IO uint32_t otype_r; + __IO uint32_t ospeed_r; + __IO uint32_t pupd_r; + __IO uint32_t id_r; + __IO uint32_t output_r; + __IO uint32_t bsr_r; + __IO uint32_t lck_r; + __IO uint32_t af_rl; + __IO uint32_t af_rh; +} PACKED gpio_port_t; + +/* + * Enum defining the PINs in a GPIO port. Each port has 16 pins to use in + * the stm32l432. + */ +typedef enum GPIO_PIN_ENUM { + PIN_0 = 0, + PIN_1 = 1, + PIN_2 = 2, + PIN_3 = 3, + PIN_4 = 4, + PIN_5 = 5, + PIN_6 = 6, + PIN_7 = 7, + PIN_8 = 8, + PIN_9 = 9, + PIN_10 = 10, + PIN_11 = 11, + PIN_12 = 12, + PIN_13 = 13, + PIN_14 = 14, + PIN_15 = 15 +} gpio_pin_t; + +/* Alternate function number. */ +typedef enum { + AFN_0 = 0, + AFN_1 = 1, + AFN_2 = 2, + AFN_3 = 3, + AFN_4 = 4, + AFN_5 = 5, + AFN_6 = 6, + AFN_7 = 7, + AFN_8 = 8, + AFN_9 = 9, + AFN_10 = 10, + AFN_11 = 11, + AFN_12 = 12, + AFN_13 = 13, + AFN_14 = 14, + AFN_15 = 15 +} alternate_function_t; + +/* + * Enum defining the pin modes that are possible. + */ +typedef enum { + MODE_INPUT = 0, + MODE_OUTPUT = 1, + MODE_ALTERNATE = 2, + MODE_ANALOG = 3 +} gpio_pin_mode_t; + +/* + * Enum defining the pin speeds that are possible. + */ +typedef enum { + SPEED_2MHZ = 0, + SPEED_10MHZ = 1, + SPEED_50MHZ = 3, +} speed_t; + +/* + * Structure defining an OUTPUT pin. Structurally equivalent to the input pin, + * but can be used in a slightly type-safe manner. + */ +typedef struct { + __IO gpio_port_t* gpio_port; + gpio_pin_t pin; +} gpio_output_pin_t; + +/* + * Sets the mode on a GPIO pin. + * + * gpio_port: the gpio port to use. + * pin: the pin number to set. + * pin_mode: the mode to set the pin to. + */ +void set_gpio_pin_mode( + __IO gpio_port_t* gpio_port, gpio_pin_t pin, gpio_pin_mode_t pin_mode); + +/* + * Sets the given GPIO pin to be an output pin. Returns an output_pin struct + * corresponding to + */ +gpio_output_pin_t set_gpio_pin_output( + __IO gpio_port_t* gpio_port, gpio_pin_t pin); + +/* + * Sets an output pin on or off. + * + * pin: the pin to toggle. + * onoff: 0 for off, non-zero of on. + */ +void set_gpio_output_pin(gpio_output_pin_t pin, bool onoff); + +#define pin_on(p) set_gpio_output_pin(p, 1) + +#define pin_off(p) set_gpio_output_pin(p, 0) + +/* + * Enables a GPIO port and returns a reference to the register definition + * of that GPIO port. + */ +__IO gpio_port_t* enable_gpio(gpio_port_number_t number); + +/* Sets the alternate function for a GPIO pin. */ +void set_gpio_alternate_function( + __IO gpio_port_t* port, gpio_pin_t gpio_pin, alternate_function_t afn); + +#endif /* CORE_GPIO_H__ */ diff --git a/02-usart/include/core/isr_vector.h b/02-usart/include/core/isr_vector.h new file mode 100644 index 0000000..78763cd --- /dev/null +++ b/02-usart/include/core/isr_vector.h @@ -0,0 +1,24 @@ +#ifndef CORE_h__ISR_VECTOR_H__ +#define CORE_h__ISR_VECTOR_H__ + +#include + +/* + * Include file for interrupt service routines. + */ + +/* + * The interrupt service routines. These link in the function `main` as the + * main function. + */ +extern const void* vectors[]; + +/* + * Defines an error state. This loops forever and defines a distinct flashing + * pattern to let the user know an unhandled ISR happened. + */ +void unhandled_isr(uint8_t val); + +void isr_simple_pin_on(); + +#endif /* CORE_h___ISR_VECTOR_H__ */ diff --git a/02-usart/include/core/isrs.i b/02-usart/include/core/isrs.i new file mode 100644 index 0000000..cdb3889 --- /dev/null +++ b/02-usart/include/core/isrs.i @@ -0,0 +1,112 @@ +/* + * The following is a list of interrupts listed in a way + * that makes it easy to macro-process them by defining + * macro definitions for IRQ and IRQ_RESERVED alike followed + * by including this file. + */ +IRQ(on_reset, 1) +IRQ(on_nmi, 2) +IRQ(on_hard_fault, 3) +IRQ(on_mem_manage, 4) +IRQ(on_bus_fault, 5) +IRQ(on_usage_fault, 6) +IRQ_RESERVED(7) +IRQ_RESERVED(8) +IRQ_RESERVED(9) +IRQ_RESERVED(10) +IRQ(on_svc, 11) +IRQ(on_debug_mon, 12) +IRQ_RESERVED(13) +IRQ(on_pendsv, 14) +IRQ(on_systick, 15) +IRQ(on_wwdg_irq, 16) +IRQ(on_pvd_irq, 17) +IRQ(on_tamper_stamp_irq, 18) +IRQ(on_rtc_wkup_irq, 19) +IRQ(on_flash_irq, 20) +IRQ(on_rcc_irq, 21) +IRQ(on_exti0_irq, 22) +IRQ(on_exti1_irq, 23) +IRQ(on_exti2_irq, 24) +IRQ(on_exti3_irq, 25) +IRQ(on_exti4_irq, 26) +IRQ(on_dma1_channel1_irq, 27) +IRQ(on_dma1_channel2_irq, 28) +IRQ(on_dma1_channel3_irq, 29) +IRQ(on_dma1_channel4_irq, 30) +IRQ(on_dma1_channel5_irq, 31) +IRQ(on_dma1_channel6_irq, 32) +IRQ(on_dma1_channel7_irq, 33) +IRQ(on_adc1_irq, 34) +IRQ(on_can1_tx, 35) +IRQ(on_can1_rx0, 36) +IRQ(on_can1_rx1, 37) +IRQ(on_can1_sce, 38) +IRQ(on_exti9_5, 39) +IRQ(on_tim1_brk, 40) +IRQ(on_tim1_up, 41) +IRQ(on_tim1_trg_com, 42) +IRQ(on_tim1_cc, 43) +IRQ(on_tim2, 44) +IRQ(on_tim3, 45) +IRQ(on_tim4, 46) +IRQ(on_i2c1_ev, 47) +IRQ(on_i2c1_er, 48) +IRQ(on_i2c2_ev, 49) +IRQ(on_i2c2_er, 50) +IRQ(on_spi1, 51) +IRQ(on_spi2, 52) +IRQ(on_usart1, 53) +IRQ(on_usart2, 54) +IRQ(on_usart3, 55) +IRQ(on_exti15_10, 56) +IRQ(on_rtc_alarm, 57) +IRQ(on_dfsdm1_flt3, 58) +IRQ(on_tim8_brk, 59) +IRQ(on_tim8_up, 60) +IRQ(on_tim8_trg_com, 61) +IRQ(on_tim8_cc, 62) +IRQ(on_adc3, 63) +IRQ(on_fmc, 64) +IRQ(on_sdmmc1, 65) +IRQ(on_tim5, 66) +IRQ(on_spi3, 67) +IRQ(on_uart4, 68) +IRQ(on_uart5, 69) +IRQ(on_tim6_dacunder, 70) +IRQ(on_tim7, 71) +IRQ(on_dma2_channel1, 72) +IRQ(on_dma2_channel2, 73) +IRQ(on_dma2_channel3, 74) +IRQ(on_dma2_channel4, 75) +IRQ(on_dma2_channel5, 76) +IRQ(on_dfsdm1_flt0, 77) +IRQ(on_dfsdm1_flt1, 78) +IRQ(on_dfsdm1_flt2, 79) +IRQ(on_comp, 80) +IRQ(on_lptim1, 81) +IRQ(on_lptim2, 82) +IRQ(on_otg_fs, 83) +IRQ(on_dma2_channel6, 84) +IRQ(on_dma2_channel7, 85) +IRQ(on_lpuart1, 86) +IRQ(on_quadspi, 87) +IRQ(on_i2c3_ev, 88) +IRQ(on_i2c3_er, 89) +IRQ(on_sai1, 90) +IRQ(on_sai2, 91) +IRQ(on_swpmi1, 92) +IRQ(on_tsc, 93) +IRQ(on_lcd, 94) +IRQ(on_aes, 95) +IRQ(on_rng, 96) +IRQ(on_fpu, 97) +IRQ(on_hash, 98) +IRQ(on_i2c4_ev, 99) +IRQ(on_i2c4_er, 100) +IRQ(on_dcmi, 101) +IRQ(on_can2_tx, 102) +IRQ(on_can2_rx0, 103) +IRQ(on_can2_rx1, 104) +IRQ(on_can2_sce, 105) +IRQ(on_dma2d, 106) diff --git a/02-usart/include/core/rcc.h b/02-usart/include/core/rcc.h new file mode 100644 index 0000000..05f5e5f --- /dev/null +++ b/02-usart/include/core/rcc.h @@ -0,0 +1,109 @@ +#ifndef H__RCC_ +#define H__RCC_ + +#include "common.h" +#include + +#define RCC_BASE ((uint32_t)0x40021000) + +typedef struct { + __IO uint32_t c_r; /* Clock control register. 0x00 */ + __IO uint32_t icsc_r; /* Internal clock srcs calibration register. 0x04 */ + __IO uint32_t cfg_r; /* clock confguration register. 0x08 */ + __IO uint32_t pllcfg_r; /* PLL Configuration register. 0x0c */ + __IO uint32_t pllsai1cfg_r; /* PLLSAI1 configuration register. 0x10 */ + + __IO uint32_t reserved_1; /* Not used. offset 0x14. */ + + __IO uint32_t cie_r; /* Clock interrupt enable register. 0x18 */ + __IO uint32_t cif_r; /* Clock interrupt flag regiseter. 0x1c */ + __IO uint32_t cic_r; /* Clock interrupt clear register. 0x20 */ + + __IO uint32_t reserved_2; /* Not used. offset 0x24. */ + + __IO uint32_t ahb1rst_r; /* AHB Peripheral 1 reset register. 0x28 */ + __IO uint32_t ahb2rst_r; /* AHB Peripheral 2 reset register. 0x2c */ + __IO uint32_t ahb3rst_r; /* AHB Peripheral 3 reset register. 0x30 */ + + __IO uint32_t reserved_3; /* Not used. offset 0x34. */ + + __IO uint32_t apb1rst1_r; /* APB Peripheral reset register 1. 0x38 */ + __IO uint32_t apb1rst2_r; /* APB Peripheral reset register 2. 0x3C */ + __IO uint32_t apb2rst_r; /* APB Peripheral reset register. 0x40 */ + + __IO uint32_t reserved_4; /* Not used. offset 0x44. */ + + __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 */ + + __IO uint32_t reserved_5; /* Not used. offset 0x54. */ + + __IO uint32_t apb1en1_r; /* APB1 Peripheral enable register 1. 0x58 */ + __IO uint32_t apb1en2_r; /* APB1 Peripheral enable register 2. 0x5C */ + __IO uint32_t apb2en_r; /* APB2 Peripheral enable register. 0x60 */ + + __IO uint32_t reserved_6; /* Not used. offset 0x64. */ + + __IO uint32_t ahb1smen_r; /* 0x68 */ + __IO uint32_t ahb2smen_r; /* 0x6c */ + __IO uint32_t ahb3smen_r; /* 0x70 */ + + __IO uint32_t reserved_7; + + __IO uint32_t apb1smen_r1; /* 0x78 */ + __IO uint32_t apb1smen_r2; /* 0x7c */ + __IO uint32_t apb2smen_r; /* 0x80 */ + + __IO uint32_t reserved_8; + + __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. */ + +/* Sets the HSE. rcc is the RCC to use, e is zero for off, non-zero for on. */ +#define set_hse(rcc, e) \ + do { \ + if (e) { \ + (rcc).c_r |= 1 << 16; \ + } else { \ + (rcc).c_r &= ~(1 << 16); \ + } \ + } while (0) + +/* Sets the HSI. rcc is the RCC to use, e is zero for off, non-zero for on. */ +#define set_hsi(rcc, e) \ + do { \ + if (e) { \ + (rcc).c_r |= 1 << 8; \ + } else { \ + (rcc).c_r &= ~(1 << 8); \ + } \ + } while (0) + +/* Checks to see if the hse is ready. */ +#define hse_ready(rcc) ((rcc).c_r & (1 << 17)) + +/* Checks to see if the hse is ready. */ +#define hsi_ready(rcc) ((rcc).c_r & (1 << 10)) + +#endif diff --git a/02-usart/include/core/system.h b/02-usart/include/core/system.h new file mode 100644 index 0000000..c836edc --- /dev/null +++ b/02-usart/include/core/system.h @@ -0,0 +1,84 @@ +#ifndef CORE_SYSTEM_H_ +#define CORE_SYSTEM_H_ + +#include +#include "common.h" + +typedef __IO struct { + uint32_t actl_r; /* Auxiliary Control Register, ACTLR on page 4-5 */ + + uint32_t reserved0; + + union { + uint32_t stcs_r; /* SysTick Control and Status Register */ + struct { + bits_t enable:1; + bits_t tickint:1; + bits_t clksource:1; + + bits_t reserved0:13; + + bits_t countflag:1; + + bits_t reserved1:15; + } stcs_bf; + }; + uint32_t strv_r; /* SysTick Reload Value Register */ + uint32_t stcv_r; /* SysTick Current Value Register */ + uint32_t stc_r; /* SysTick Calibration Value Register */ + + uint8_t reserved1[3296]; + + uint32_t cpuid; /* CPUID Base Register, CPUID on page 4-5 */ + uint32_t ics_r; /* RO 0x00000000 Interrupt Control and State Register */ + uint32_t vto_r; /* Vector Table Offset Register */ + uint32_t airc_r; /* Application Interrupt and Reset Control Register */ + uint32_t sc_r; /* System Control Register */ + uint32_t cc_r; /* Configuration and Control Register. */ + uint32_t shp_r1; /* System Handler Priority Register 1 */ + uint32_t shp_r2; /* System Handler Priority Register 2 */ + uint32_t shp_r3; /* System Handler Priority Register 3 */ + uint32_t shcs_r; /* System Handler Control and State Register */ + uint32_t cfs_r; /* Configurable Fault Status Registers */ + uint32_t hfs_r; /* HardFault Status register */ + uint32_t dfs_r; /* Debug Fault Status Register */ + uint32_t mmfa_r; /* MemManage Address Registerb */ + uint32_t bfa_r; /* BusFault Address Registerb */ + uint32_t afs_r; /* Auxiliary Fault Status Register, AFSR on page 4-6 */ + uint32_t id_pf_r0; /* Processor Feature Register 0 */ + uint32_t id_pf_r1; /* Processor Feature Register 1 */ + uint32_t id_df_r0; /* Debug Features Register 0 */ + uint32_t id_af_r0; /* Auxiliary Features Register 0 */ + uint32_t id_mmf_r0; /* Memory Model Feature Register 0 */ + uint32_t id_mmf_r1; /* 0x00000000 Memory Model Feature Register 1 */ + uint32_t id_mmf_r2; /* Memory Model Feature Register 2 */ + uint32_t id_mmf_r3; /* Memory Model Feature Register 3 */ + uint32_t id_isa_r0; /* Instruction Set Attributes Register 0 */ + uint32_t id_isa_r1; /* Instruction Set Attributes Register 1 */ + uint32_t id_isa_r2; /* Instruction Set Attributes Register 2 */ + uint32_t id_isa_r3; /* Instruction Set Attributes Register 3 */ + uint32_t id_isa_r4; /* Instruction Set Attributes Register 4 */ + + uint8_t reserved2[20]; + + uint32_t cpac_r; /* Coprocessor Access Control Register */ + + uint8_t reserved3[372]; + + uint32_t sti_r; /* Software Triggered Interrupt Register */ +} system_control_block_t; + +#define ARM_SYSCFG_BASE 0xE000E008 +#define CHECK_OFFSET(member, expected) \ + static_assert(ARM_SYSCFG_BASE + offsetof(system_control_block_t, member) == expected, \ + "Offset check failed") + +CHECK_OFFSET(stcs_r, 0xE000E010); +CHECK_OFFSET(cpuid, 0xE000ED00); +CHECK_OFFSET(cpac_r, 0xE000ED88); +CHECK_OFFSET(id_mmf_r3, 0xE000ED5C); +CHECK_OFFSET(sti_r, 0xE000EF00); + +#define SCB (*(system_control_block_t*)SYSTEM_CONFIG_BLOCK_BASE) + +#endif diff --git a/02-usart/include/core/usart.h b/02-usart/include/core/usart.h new file mode 100644 index 0000000..9ed6dbb --- /dev/null +++ b/02-usart/include/core/usart.h @@ -0,0 +1,223 @@ +#ifndef H__USART_ +#define H__USART_ + +#include +#include + +#include "common.h" +#include "rcc.h" +#include + +#define USART1 (* (__IO usart_t*) USART1_BASE) +#define USART2 (* (__IO usart_t*) USART2_BASE) + +/* + * Possible USART clock sources. + */ +typedef enum { + USART_CLK_SRC_PLK = 0, /* Clock derived from the SysClk. */ + USART_CLK_SRC_SYSCLK = 1, /* System clock. */ + USART_CLK_SRC_HSI16 = 2, /* 16MHz oscillator. */ + USART_CLK_SRC_LSE = 3 /* Low power 32kHz clock. */ +} usart_clk_src_t; + +typedef struct { + /* USART configuration registers 0x04 - 0x0c. */ + union { + __IO uint32_t c_r1; + struct { + bits_t ue:1; /* UART enable */ + bits_t uesm:1; /* UART enabled in stop mode. */ + bits_t re:1; /* reciever enabled. */ + bits_t te:1; /* transmitter enabled. */ + bits_t idleie:1; /* Idle interrupt enabled. */ + bits_t rxneie:1; /* RXNEIE RXNE interrupt enable. */ + bits_t tcie:1; + bits_t txeie:1; + bits_t peie:1; + bits_t ps:1; + bits_t pce:1; + bits_t wake:1; + bits_t m0:1; + bits_t mme:1; + bits_t cmie:1; + bits_t over8:1; + bits_t dedt:4; + bits_t deat:4; + bits_t rtoie:1; + bits_t eobie:1; + bits_t m1:1; + bits_t reserved:3; + } PACKED c1_bf; /* c1_bf = c1 bit field */ + }; /* USART Control Register 1. */ + __IO uint32_t c_r2; + + union { + __IO uint32_t c_r3; + struct { + bits_t eie:1; // Error interrupt enable. + bits_t iren:1; // IrDA mode enabled + bits_t irlp:1; // IrDA low power + bits_t hdsel:1; // Half duplex selection + bits_t nack:1; // Smartcard NACK enable + bits_t scen:1; // Smartocard mode enable + bits_t dmar:1; // DMA enable reciever + bits_t dmat:1; // DMA enable transmitter + bits_t rtse:1; // RTS enable + bits_t ctse:1; // CTS enable + bits_t ctsie:1; // CTS interrupt enable + bits_t onebit:1; // One sample bit method enable + bits_t ovrdis:1; // Overrun disable + bits_t ddre:1; // DMA Disable on reception error + bits_t dem:1; // Driver enable mode + bits_t dep:1; // Driver enable polarity selection + bits_t reserved0:1; + bits_t scarcnt:3; // Smartcard auto-retry count. + bits_t wus:2; // Wakeup from STOP mode interrept flag selection + bits_t wufie:1; // Wakeup from STOP mode interrup enable + bits_t ucesm:1; // USART clock enable in STOP mode. + bits_t tcbgtie:1; // Transmission complete before guard time interrupt + bits_t reserved1:7; + } PACKED c3_bf; + }; + + /* USART baud rate register. */ + uint32_t br_r; + uint32_t gtp_r; + uint32_t rto_r; + uint32_t rq_r; + + /* USART ISR register. Offset = 0x1c*/ + union { + __IO uint32_t is_r; /* Interrupt service register. */ + struct { + bits_t pe:1; // Parity error + bits_t fe:1; // Framing error + bits_t nf:1; // START bit noise detection flag. + bits_t ore:1; // Overrun error + bits_t dlie:1; // Idle line detected + bits_t rxne:1; // Read data register not empty + bits_t tc:1; // Transmission complete + bits_t txe:1; // Transmit data register empty + bits_t lbdf:1; // LIN break detection flag + bits_t ctsif:1; // CTS interrupt flag + bits_t cts:1; // CTS flag. + bits_t rtof:1; // Receiever timeout + bits_t eobf:1; // End of block flag + bits_t reserved0:1; + bits_t abre:1; // Auto baud rate error + bits_t abrf:1; // Auto baud rate flag + bits_t busy:1; // Busy flag + bits_t cmf:1; // Character match flag + bits_t sbkf:1; // send break flag + bits_t rwu:1; // receiver wakeup frlom mute mode. + bits_t wuf:1; // Wakeup from stop mode flag + bits_t teack:1; // Transmit enable acknowledge flag. + bits_t reack:1; // Receieve enable acknowledge flag. + bits_t reserved1:2; + bits_t tcbgt:1; // Transmission completer before guard time completion. + bits_t reserved2:6; + } PACKED is_bf; /* Interrupt servite bit field. */ + }; + 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 +} oversampling_mode_t; + +static inline void usart_set_divisor( + __IO usart_t* usart, + uint32_t usartdiv) +{ + if (usart->c_r1 & (1 << 15)) { + /* OVER8 is set. */ + usart->br_r = + (usartdiv & ~7) | + ((usartdiv & 7) >> 1); + } else { + /* OVER8 is not set. */ + usart->br_r = usartdiv; + } +} + +static inline void usart_set_oversampling_mode( + __IO usart_t* usart, + oversampling_mode_t mode) +{ + if (mode == OVERSAMPLE_8) { + usart->c_r1 |= 1 << 15; + } else { + usart->c_r1 &= ~(1 << 15); + } +} + +typedef enum { + USART_PARITY_DISABLED = 0, + USART_PARITY_EVEN = 2 << 9, + USART_PARITY_ODD = 3 << 9, +} usart_parity_t; + +typedef enum { + USART_ENABLE_TX = 0x02, + USART_ENABLE_RX = 0x01, + USART_ENABLE_DISABLED = 0x00, +} usart_enable_t; + +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. + */ +void usart_transmit_byte_sync(__IO usart_t* usart, uint8_t byte); + +void set_usart1_clock_src(__IO rcc_t* rcc, usart_clk_src_t usart_clk_src); + +void set_usart1_clock_enabled(__IO rcc_t* rcc, bool enable); + +void set_usart2_clock_src(__IO rcc_t* rcc, usart_clk_src_t usart_clk_src); + +void set_usart2_clock_enabled(__IO rcc_t* rcc, bool enable); + +void usart_transmit_bytes_sync( + __IO usart_t* usart, const uint8_t* bytes, uint32_t n); + +void usart_transmit_str_sync(__IO usart_t* usart, const char* str); + +void usart_printf(__IO usart_t* usart, const char* fmt, ...); + + +#endif /* H__USART_ */ diff --git a/02-usart/include/dma.h b/02-usart/include/dma.h deleted file mode 100644 index 229b732..0000000 --- a/02-usart/include/dma.h +++ /dev/null @@ -1,172 +0,0 @@ -#ifndef DMA_H_ -#define DMA_H_ - -/* - * Header file for definining the DMA (Direct Memory Access). - * - * A DMA is used to perform data transfers between segments of memory - * or between memory and peripherals. - * - * There are 2 DMA's on the chip. Each with 7 channels. - */ - -#include "common.h" -#include -#include - -#define DMA1 (* (dma_t*) DMA1_BASE) -#define DMA2 (* (dma_t*) DMA2_BASE) - -typedef enum { - DMA_SIZE_8_BITS = 0, - DMA_SIZE_16_BITS = 1, - DMA_SIZE_32_BITS = 2, -} dma_size_t; - -typedef enum { - DMA_PRIORITY_LEVEL_LOW = 0, - DMA_PRIORITY_LEVEL_MEDIUM = 1, - DMA_PRIORITY_LEVEL_HIGH = 2, - 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 { - __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; - }; - - /* DMA channel peripheral address register. - * Defines a memory address if mem2mem is set. */ - __IO uint32_t cpa_r; - - /* DMA channel memory address register. - * Defines another perpipheral address if peripheral-periphal mode is set. */ - __IO uint32_t cma_r; - - __IO uint32_t reserved; -} dma_channel_config_t; - -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; - }; - - // 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; - }; - - 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; - }; -} dma_t; - -static_assert(offsetof(dma_t, csel_r) == 0xA8, "Offset check failed."); - -#endif /* DMA_H_ */ diff --git a/02-usart/include/flash.h b/02-usart/include/flash.h deleted file mode 100644 index a163a25..0000000 --- a/02-usart/include/flash.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef H__FLASH_ -#define H__FLASH_ - -#include "common.h" - -/* - * Header file for dealing with flash. - */ - -#define FLASH_BASE 0x40022000 - -typedef struct { - __IO uint32_t ac_r; /* Flash access control register. */ - - /* TODO fill out the rest. */ -} PACKED flash_t; - -#define FLASH (*(__IO flash_t*)FLASH_BASE) - -#endif /* H__FLASH_ */ diff --git a/02-usart/include/gpio.h b/02-usart/include/gpio.h deleted file mode 100644 index 62169c6..0000000 --- a/02-usart/include/gpio.h +++ /dev/null @@ -1,146 +0,0 @@ -#ifndef GPIO_H__ -#define GPIO_H__ - -#include "common.h" -#include "rcc.h" - -#include - -/* - * Possible GPIO ports. - */ -typedef enum { - GPIO_PORT_A = 0, - GPIO_PORT_B = 1, - GPIO_PORT_C = 2, - GPIO_PORT_D = 3 -} gpio_port_number_t; - -/* - * Structure defining the layout of the layout of the GPIO registers on the - * stm32l432 development board. - */ -typedef struct GPIO_PORT_STR { - __IO uint32_t mode_r; /* Mode register */ - __IO uint32_t otype_r; - __IO uint32_t ospeed_r; - __IO uint32_t pupd_r; - __IO uint32_t id_r; - __IO uint32_t output_r; - __IO uint32_t bsr_r; - __IO uint32_t lck_r; - __IO uint32_t af_rl; - __IO uint32_t af_rh; -} PACKED gpio_port_t; - -/* - * Enum defining the PINs in a GPIO port. Each port has 16 pins to use in - * the stm32l432. - */ -typedef enum GPIO_PIN_ENUM { - PIN_0 = 0, - PIN_1 = 1, - PIN_2 = 2, - PIN_3 = 3, - PIN_4 = 4, - PIN_5 = 5, - PIN_6 = 6, - PIN_7 = 7, - PIN_8 = 8, - PIN_9 = 9, - PIN_10 = 10, - PIN_11 = 11, - PIN_12 = 12, - PIN_13 = 13, - PIN_14 = 14, - PIN_15 = 15 -} gpio_pin_t; - -/* Alternate function number. */ -typedef enum { - AFN_0 = 0, - AFN_1 = 1, - AFN_2 = 2, - AFN_3 = 3, - AFN_4 = 4, - AFN_5 = 5, - AFN_6 = 6, - AFN_7 = 7, - AFN_8 = 8, - AFN_9 = 9, - AFN_10 = 10, - AFN_11 = 11, - AFN_12 = 12, - AFN_13 = 13, - AFN_14 = 14, - AFN_15 = 15 -} alternate_function_t; - -/* - * Enum defining the pin modes that are possible. - */ -typedef enum { - MODE_INPUT = 0, - MODE_OUTPUT = 1, - MODE_ALTERNATE = 2, - MODE_ANALOG = 3 -} gpio_pin_mode_t; - -/* - * Enum defining the pin speeds that are possible. - */ -typedef enum { - SPEED_2MHZ = 0, - SPEED_10MHZ = 1, - SPEED_50MHZ = 3, -} speed_t; - -/* - * Structure defining an OUTPUT pin. Structurally equivalent to the input pin, - * but can be used in a slightly type-safe manner. - */ -typedef struct { - __IO gpio_port_t* gpio_port; - gpio_pin_t pin; -} gpio_output_pin_t; - -/* - * Sets the mode on a GPIO pin. - * - * gpio_port: the gpio port to use. - * pin: the pin number to set. - * pin_mode: the mode to set the pin to. - */ -void set_gpio_pin_mode( - __IO gpio_port_t* gpio_port, gpio_pin_t pin, gpio_pin_mode_t pin_mode); - -/* - * Sets the given GPIO pin to be an output pin. Returns an output_pin struct - * corresponding to - */ -gpio_output_pin_t set_gpio_pin_output( - __IO gpio_port_t* gpio_port, gpio_pin_t pin); - -/* - * Sets an output pin on or off. - * - * pin: the pin to toggle. - * onoff: 0 for off, non-zero of on. - */ -void set_gpio_output_pin(gpio_output_pin_t pin, bool onoff); - -#define pin_on(p) set_gpio_output_pin(p, 1) - -#define pin_off(p) set_gpio_output_pin(p, 0) - -/* - * Enables a GPIO port and returns a reference to the register definition - * of that GPIO port. - */ -__IO gpio_port_t* enable_gpio(gpio_port_number_t number); - -/* Sets the alternate function for a GPIO pin. */ -void set_gpio_alternate_function( - __IO gpio_port_t* port, gpio_pin_t gpio_pin, alternate_function_t afn); - -#endif /* GPIO_H__ */ diff --git a/02-usart/include/isr_vector.h b/02-usart/include/isr_vector.h deleted file mode 100644 index 7cb4596..0000000 --- a/02-usart/include/isr_vector.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef h__ISR_VECTOR_H__ -#define h__ISR_VECTOR_H__ - -#include - -/* - * Include file for interrupt service routines. - */ - -/* - * The interrupt service routines. These link in the function `main` as the - * main function. - */ -extern const void* vectors[]; - -/* - * Defines an error state. This loops forever and defines a distinct flashing - * pattern to let the user know an unhandled ISR happened. - */ -void unhandled_isr(uint8_t val); - -void isr_simple_pin_on(); - -#endif /* h___ISR_VECTOR_H__ */ diff --git a/02-usart/include/isrs.i b/02-usart/include/isrs.i deleted file mode 100644 index cdb3889..0000000 --- a/02-usart/include/isrs.i +++ /dev/null @@ -1,112 +0,0 @@ -/* - * The following is a list of interrupts listed in a way - * that makes it easy to macro-process them by defining - * macro definitions for IRQ and IRQ_RESERVED alike followed - * by including this file. - */ -IRQ(on_reset, 1) -IRQ(on_nmi, 2) -IRQ(on_hard_fault, 3) -IRQ(on_mem_manage, 4) -IRQ(on_bus_fault, 5) -IRQ(on_usage_fault, 6) -IRQ_RESERVED(7) -IRQ_RESERVED(8) -IRQ_RESERVED(9) -IRQ_RESERVED(10) -IRQ(on_svc, 11) -IRQ(on_debug_mon, 12) -IRQ_RESERVED(13) -IRQ(on_pendsv, 14) -IRQ(on_systick, 15) -IRQ(on_wwdg_irq, 16) -IRQ(on_pvd_irq, 17) -IRQ(on_tamper_stamp_irq, 18) -IRQ(on_rtc_wkup_irq, 19) -IRQ(on_flash_irq, 20) -IRQ(on_rcc_irq, 21) -IRQ(on_exti0_irq, 22) -IRQ(on_exti1_irq, 23) -IRQ(on_exti2_irq, 24) -IRQ(on_exti3_irq, 25) -IRQ(on_exti4_irq, 26) -IRQ(on_dma1_channel1_irq, 27) -IRQ(on_dma1_channel2_irq, 28) -IRQ(on_dma1_channel3_irq, 29) -IRQ(on_dma1_channel4_irq, 30) -IRQ(on_dma1_channel5_irq, 31) -IRQ(on_dma1_channel6_irq, 32) -IRQ(on_dma1_channel7_irq, 33) -IRQ(on_adc1_irq, 34) -IRQ(on_can1_tx, 35) -IRQ(on_can1_rx0, 36) -IRQ(on_can1_rx1, 37) -IRQ(on_can1_sce, 38) -IRQ(on_exti9_5, 39) -IRQ(on_tim1_brk, 40) -IRQ(on_tim1_up, 41) -IRQ(on_tim1_trg_com, 42) -IRQ(on_tim1_cc, 43) -IRQ(on_tim2, 44) -IRQ(on_tim3, 45) -IRQ(on_tim4, 46) -IRQ(on_i2c1_ev, 47) -IRQ(on_i2c1_er, 48) -IRQ(on_i2c2_ev, 49) -IRQ(on_i2c2_er, 50) -IRQ(on_spi1, 51) -IRQ(on_spi2, 52) -IRQ(on_usart1, 53) -IRQ(on_usart2, 54) -IRQ(on_usart3, 55) -IRQ(on_exti15_10, 56) -IRQ(on_rtc_alarm, 57) -IRQ(on_dfsdm1_flt3, 58) -IRQ(on_tim8_brk, 59) -IRQ(on_tim8_up, 60) -IRQ(on_tim8_trg_com, 61) -IRQ(on_tim8_cc, 62) -IRQ(on_adc3, 63) -IRQ(on_fmc, 64) -IRQ(on_sdmmc1, 65) -IRQ(on_tim5, 66) -IRQ(on_spi3, 67) -IRQ(on_uart4, 68) -IRQ(on_uart5, 69) -IRQ(on_tim6_dacunder, 70) -IRQ(on_tim7, 71) -IRQ(on_dma2_channel1, 72) -IRQ(on_dma2_channel2, 73) -IRQ(on_dma2_channel3, 74) -IRQ(on_dma2_channel4, 75) -IRQ(on_dma2_channel5, 76) -IRQ(on_dfsdm1_flt0, 77) -IRQ(on_dfsdm1_flt1, 78) -IRQ(on_dfsdm1_flt2, 79) -IRQ(on_comp, 80) -IRQ(on_lptim1, 81) -IRQ(on_lptim2, 82) -IRQ(on_otg_fs, 83) -IRQ(on_dma2_channel6, 84) -IRQ(on_dma2_channel7, 85) -IRQ(on_lpuart1, 86) -IRQ(on_quadspi, 87) -IRQ(on_i2c3_ev, 88) -IRQ(on_i2c3_er, 89) -IRQ(on_sai1, 90) -IRQ(on_sai2, 91) -IRQ(on_swpmi1, 92) -IRQ(on_tsc, 93) -IRQ(on_lcd, 94) -IRQ(on_aes, 95) -IRQ(on_rng, 96) -IRQ(on_fpu, 97) -IRQ(on_hash, 98) -IRQ(on_i2c4_ev, 99) -IRQ(on_i2c4_er, 100) -IRQ(on_dcmi, 101) -IRQ(on_can2_tx, 102) -IRQ(on_can2_rx0, 103) -IRQ(on_can2_rx1, 104) -IRQ(on_can2_sce, 105) -IRQ(on_dma2d, 106) diff --git a/02-usart/include/mem.h b/02-usart/include/mem.h index fefe53d..aa4ce12 100644 --- a/02-usart/include/mem.h +++ b/02-usart/include/mem.h @@ -1,12 +1,4 @@ #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 deleted file mode 100644 index 05f5e5f..0000000 --- a/02-usart/include/rcc.h +++ /dev/null @@ -1,109 +0,0 @@ -#ifndef H__RCC_ -#define H__RCC_ - -#include "common.h" -#include - -#define RCC_BASE ((uint32_t)0x40021000) - -typedef struct { - __IO uint32_t c_r; /* Clock control register. 0x00 */ - __IO uint32_t icsc_r; /* Internal clock srcs calibration register. 0x04 */ - __IO uint32_t cfg_r; /* clock confguration register. 0x08 */ - __IO uint32_t pllcfg_r; /* PLL Configuration register. 0x0c */ - __IO uint32_t pllsai1cfg_r; /* PLLSAI1 configuration register. 0x10 */ - - __IO uint32_t reserved_1; /* Not used. offset 0x14. */ - - __IO uint32_t cie_r; /* Clock interrupt enable register. 0x18 */ - __IO uint32_t cif_r; /* Clock interrupt flag regiseter. 0x1c */ - __IO uint32_t cic_r; /* Clock interrupt clear register. 0x20 */ - - __IO uint32_t reserved_2; /* Not used. offset 0x24. */ - - __IO uint32_t ahb1rst_r; /* AHB Peripheral 1 reset register. 0x28 */ - __IO uint32_t ahb2rst_r; /* AHB Peripheral 2 reset register. 0x2c */ - __IO uint32_t ahb3rst_r; /* AHB Peripheral 3 reset register. 0x30 */ - - __IO uint32_t reserved_3; /* Not used. offset 0x34. */ - - __IO uint32_t apb1rst1_r; /* APB Peripheral reset register 1. 0x38 */ - __IO uint32_t apb1rst2_r; /* APB Peripheral reset register 2. 0x3C */ - __IO uint32_t apb2rst_r; /* APB Peripheral reset register. 0x40 */ - - __IO uint32_t reserved_4; /* Not used. offset 0x44. */ - - __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 */ - - __IO uint32_t reserved_5; /* Not used. offset 0x54. */ - - __IO uint32_t apb1en1_r; /* APB1 Peripheral enable register 1. 0x58 */ - __IO uint32_t apb1en2_r; /* APB1 Peripheral enable register 2. 0x5C */ - __IO uint32_t apb2en_r; /* APB2 Peripheral enable register. 0x60 */ - - __IO uint32_t reserved_6; /* Not used. offset 0x64. */ - - __IO uint32_t ahb1smen_r; /* 0x68 */ - __IO uint32_t ahb2smen_r; /* 0x6c */ - __IO uint32_t ahb3smen_r; /* 0x70 */ - - __IO uint32_t reserved_7; - - __IO uint32_t apb1smen_r1; /* 0x78 */ - __IO uint32_t apb1smen_r2; /* 0x7c */ - __IO uint32_t apb2smen_r; /* 0x80 */ - - __IO uint32_t reserved_8; - - __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. */ - -/* Sets the HSE. rcc is the RCC to use, e is zero for off, non-zero for on. */ -#define set_hse(rcc, e) \ - do { \ - if (e) { \ - (rcc).c_r |= 1 << 16; \ - } else { \ - (rcc).c_r &= ~(1 << 16); \ - } \ - } while (0) - -/* Sets the HSI. rcc is the RCC to use, e is zero for off, non-zero for on. */ -#define set_hsi(rcc, e) \ - do { \ - if (e) { \ - (rcc).c_r |= 1 << 8; \ - } else { \ - (rcc).c_r &= ~(1 << 8); \ - } \ - } while (0) - -/* Checks to see if the hse is ready. */ -#define hse_ready(rcc) ((rcc).c_r & (1 << 17)) - -/* Checks to see if the hse is ready. */ -#define hsi_ready(rcc) ((rcc).c_r & (1 << 10)) - -#endif diff --git a/02-usart/include/system.h b/02-usart/include/system.h deleted file mode 100644 index f2a4de9..0000000 --- a/02-usart/include/system.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef SYSTEM_H_ -#define SYSTEM_H_ - -#include -#include "common.h" - -typedef __IO struct { - uint32_t actl_r; /* Auxiliary Control Register, ACTLR on page 4-5 */ - - uint32_t reserved0; - - union { - uint32_t stcs_r; /* SysTick Control and Status Register */ - struct { - bits_t enable:1; - bits_t tickint:1; - bits_t clksource:1; - - bits_t reserved0:13; - - bits_t countflag:1; - - bits_t reserved1:15; - } stcs_bf; - }; - uint32_t strv_r; /* SysTick Reload Value Register */ - uint32_t stcv_r; /* SysTick Current Value Register */ - uint32_t stc_r; /* SysTick Calibration Value Register */ - - uint8_t reserved1[3296]; - - uint32_t cpuid; /* CPUID Base Register, CPUID on page 4-5 */ - uint32_t ics_r; /* RO 0x00000000 Interrupt Control and State Register */ - uint32_t vto_r; /* Vector Table Offset Register */ - uint32_t airc_r; /* Application Interrupt and Reset Control Register */ - uint32_t sc_r; /* System Control Register */ - uint32_t cc_r; /* Configuration and Control Register. */ - uint32_t shp_r1; /* System Handler Priority Register 1 */ - uint32_t shp_r2; /* System Handler Priority Register 2 */ - uint32_t shp_r3; /* System Handler Priority Register 3 */ - uint32_t shcs_r; /* System Handler Control and State Register */ - uint32_t cfs_r; /* Configurable Fault Status Registers */ - uint32_t hfs_r; /* HardFault Status register */ - uint32_t dfs_r; /* Debug Fault Status Register */ - uint32_t mmfa_r; /* MemManage Address Registerb */ - uint32_t bfa_r; /* BusFault Address Registerb */ - uint32_t afs_r; /* Auxiliary Fault Status Register, AFSR on page 4-6 */ - uint32_t id_pf_r0; /* Processor Feature Register 0 */ - uint32_t id_pf_r1; /* Processor Feature Register 1 */ - uint32_t id_df_r0; /* Debug Features Register 0 */ - uint32_t id_af_r0; /* Auxiliary Features Register 0 */ - uint32_t id_mmf_r0; /* Memory Model Feature Register 0 */ - uint32_t id_mmf_r1; /* 0x00000000 Memory Model Feature Register 1 */ - uint32_t id_mmf_r2; /* Memory Model Feature Register 2 */ - uint32_t id_mmf_r3; /* Memory Model Feature Register 3 */ - uint32_t id_isa_r0; /* Instruction Set Attributes Register 0 */ - uint32_t id_isa_r1; /* Instruction Set Attributes Register 1 */ - uint32_t id_isa_r2; /* Instruction Set Attributes Register 2 */ - uint32_t id_isa_r3; /* Instruction Set Attributes Register 3 */ - uint32_t id_isa_r4; /* Instruction Set Attributes Register 4 */ - - uint8_t reserved2[20]; - - uint32_t cpac_r; /* Coprocessor Access Control Register */ - - uint8_t reserved3[372]; - - uint32_t sti_r; /* Software Triggered Interrupt Register */ -} system_control_block_t; - -#define ARM_SYSCFG_BASE 0xE000E008 -#define CHECK_OFFSET(member, expected) \ - static_assert(ARM_SYSCFG_BASE + offsetof(system_control_block_t, member) == expected, \ - "Offset check failed") - -CHECK_OFFSET(stcs_r, 0xE000E010); -CHECK_OFFSET(cpuid, 0xE000ED00); -CHECK_OFFSET(cpac_r, 0xE000ED88); -CHECK_OFFSET(id_mmf_r3, 0xE000ED5C); -CHECK_OFFSET(sti_r, 0xE000EF00); - -#define SCB (*(system_control_block_t*)SYSTEM_CONFIG_BLOCK_BASE) - -#endif diff --git a/02-usart/include/usart.h b/02-usart/include/usart.h deleted file mode 100644 index 9ed6dbb..0000000 --- a/02-usart/include/usart.h +++ /dev/null @@ -1,223 +0,0 @@ -#ifndef H__USART_ -#define H__USART_ - -#include -#include - -#include "common.h" -#include "rcc.h" -#include - -#define USART1 (* (__IO usart_t*) USART1_BASE) -#define USART2 (* (__IO usart_t*) USART2_BASE) - -/* - * Possible USART clock sources. - */ -typedef enum { - USART_CLK_SRC_PLK = 0, /* Clock derived from the SysClk. */ - USART_CLK_SRC_SYSCLK = 1, /* System clock. */ - USART_CLK_SRC_HSI16 = 2, /* 16MHz oscillator. */ - USART_CLK_SRC_LSE = 3 /* Low power 32kHz clock. */ -} usart_clk_src_t; - -typedef struct { - /* USART configuration registers 0x04 - 0x0c. */ - union { - __IO uint32_t c_r1; - struct { - bits_t ue:1; /* UART enable */ - bits_t uesm:1; /* UART enabled in stop mode. */ - bits_t re:1; /* reciever enabled. */ - bits_t te:1; /* transmitter enabled. */ - bits_t idleie:1; /* Idle interrupt enabled. */ - bits_t rxneie:1; /* RXNEIE RXNE interrupt enable. */ - bits_t tcie:1; - bits_t txeie:1; - bits_t peie:1; - bits_t ps:1; - bits_t pce:1; - bits_t wake:1; - bits_t m0:1; - bits_t mme:1; - bits_t cmie:1; - bits_t over8:1; - bits_t dedt:4; - bits_t deat:4; - bits_t rtoie:1; - bits_t eobie:1; - bits_t m1:1; - bits_t reserved:3; - } PACKED c1_bf; /* c1_bf = c1 bit field */ - }; /* USART Control Register 1. */ - __IO uint32_t c_r2; - - union { - __IO uint32_t c_r3; - struct { - bits_t eie:1; // Error interrupt enable. - bits_t iren:1; // IrDA mode enabled - bits_t irlp:1; // IrDA low power - bits_t hdsel:1; // Half duplex selection - bits_t nack:1; // Smartcard NACK enable - bits_t scen:1; // Smartocard mode enable - bits_t dmar:1; // DMA enable reciever - bits_t dmat:1; // DMA enable transmitter - bits_t rtse:1; // RTS enable - bits_t ctse:1; // CTS enable - bits_t ctsie:1; // CTS interrupt enable - bits_t onebit:1; // One sample bit method enable - bits_t ovrdis:1; // Overrun disable - bits_t ddre:1; // DMA Disable on reception error - bits_t dem:1; // Driver enable mode - bits_t dep:1; // Driver enable polarity selection - bits_t reserved0:1; - bits_t scarcnt:3; // Smartcard auto-retry count. - bits_t wus:2; // Wakeup from STOP mode interrept flag selection - bits_t wufie:1; // Wakeup from STOP mode interrup enable - bits_t ucesm:1; // USART clock enable in STOP mode. - bits_t tcbgtie:1; // Transmission complete before guard time interrupt - bits_t reserved1:7; - } PACKED c3_bf; - }; - - /* USART baud rate register. */ - uint32_t br_r; - uint32_t gtp_r; - uint32_t rto_r; - uint32_t rq_r; - - /* USART ISR register. Offset = 0x1c*/ - union { - __IO uint32_t is_r; /* Interrupt service register. */ - struct { - bits_t pe:1; // Parity error - bits_t fe:1; // Framing error - bits_t nf:1; // START bit noise detection flag. - bits_t ore:1; // Overrun error - bits_t dlie:1; // Idle line detected - bits_t rxne:1; // Read data register not empty - bits_t tc:1; // Transmission complete - bits_t txe:1; // Transmit data register empty - bits_t lbdf:1; // LIN break detection flag - bits_t ctsif:1; // CTS interrupt flag - bits_t cts:1; // CTS flag. - bits_t rtof:1; // Receiever timeout - bits_t eobf:1; // End of block flag - bits_t reserved0:1; - bits_t abre:1; // Auto baud rate error - bits_t abrf:1; // Auto baud rate flag - bits_t busy:1; // Busy flag - bits_t cmf:1; // Character match flag - bits_t sbkf:1; // send break flag - bits_t rwu:1; // receiver wakeup frlom mute mode. - bits_t wuf:1; // Wakeup from stop mode flag - bits_t teack:1; // Transmit enable acknowledge flag. - bits_t reack:1; // Receieve enable acknowledge flag. - bits_t reserved1:2; - bits_t tcbgt:1; // Transmission completer before guard time completion. - bits_t reserved2:6; - } PACKED is_bf; /* Interrupt servite bit field. */ - }; - 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 -} oversampling_mode_t; - -static inline void usart_set_divisor( - __IO usart_t* usart, - uint32_t usartdiv) -{ - if (usart->c_r1 & (1 << 15)) { - /* OVER8 is set. */ - usart->br_r = - (usartdiv & ~7) | - ((usartdiv & 7) >> 1); - } else { - /* OVER8 is not set. */ - usart->br_r = usartdiv; - } -} - -static inline void usart_set_oversampling_mode( - __IO usart_t* usart, - oversampling_mode_t mode) -{ - if (mode == OVERSAMPLE_8) { - usart->c_r1 |= 1 << 15; - } else { - usart->c_r1 &= ~(1 << 15); - } -} - -typedef enum { - USART_PARITY_DISABLED = 0, - USART_PARITY_EVEN = 2 << 9, - USART_PARITY_ODD = 3 << 9, -} usart_parity_t; - -typedef enum { - USART_ENABLE_TX = 0x02, - USART_ENABLE_RX = 0x01, - USART_ENABLE_DISABLED = 0x00, -} usart_enable_t; - -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. - */ -void usart_transmit_byte_sync(__IO usart_t* usart, uint8_t byte); - -void set_usart1_clock_src(__IO rcc_t* rcc, usart_clk_src_t usart_clk_src); - -void set_usart1_clock_enabled(__IO rcc_t* rcc, bool enable); - -void set_usart2_clock_src(__IO rcc_t* rcc, usart_clk_src_t usart_clk_src); - -void set_usart2_clock_enabled(__IO rcc_t* rcc, bool enable); - -void usart_transmit_bytes_sync( - __IO usart_t* usart, const uint8_t* bytes, uint32_t n); - -void usart_transmit_str_sync(__IO usart_t* usart, const char* str); - -void usart_printf(__IO usart_t* usart, const char* fmt, ...); - - -#endif /* H__USART_ */ diff --git a/02-usart/src/clock.c b/02-usart/src/clock.c deleted file mode 100644 index 75bac97..0000000 --- a/02-usart/src/clock.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * This file sets the system clock to its full glory of 80Mhz - */ - -#include "clock.h" -#include -#include "flash.h" -#include "gpio.h" -#include "spin.h" - -#define TIMEOUT 10000 - -int pll_off() -{ - uint32_t c; - - RCC.c_r &= ~BIT(24); /* Turn off pll. */ - for (c = 0; c < TIMEOUT && RCC.c_r & BIT(25); ++c) - ; /* Wait for OFF. */ - - if (c == TIMEOUT) { - return E_TIMEOUT; - } - - return 0; -} - -int pll_on() -{ - uint32_t c; - - RCC.c_r |= BIT(24); /* Turn on PLL. */ - for (c = 0; c < TIMEOUT && !(RCC.c_r & BIT(25)); ++c) - ; /* Wait for RDY. */ - - if (c == TIMEOUT) { - return E_TIMEOUT; - } - - return 0; -} - -int configure_pll( - uint8_t pllp_div_factor, pll_divisor_t pllr, /* System clock divisor. */ - pll_divisor_t pllq, /* Divison factor for PLL48M1CLK. */ - pllp_divisor_t pllp, /* Divison factor for PLLSAI2CLK. */ - uint8_t plln, /* PLL numerator. */ - pllm_divisor_t pllm, /* PLL denominator. */ - pll_src_t pllsrc /* PLL source */) -{ - if (RCC.c_r & BIT(25)) { - /* PLL must be off to configure it. */ - return E_NOT_OFF; - } - - /* Make sure inputs are valid. */ - if (pllp_div_factor == 1 || pllp_div_factor > 31) { - return E_BADPLLP_DIV; - } - if (plln < 8 || plln > 86) { - return E_BADPLLN; - } - - RCC.pllcfg_r = (pllp_div_factor << 27) | (pllr << 24) | (pllq << 20) | - (pllp << 16) | (plln << 8) | (pllm << 4) | (pllsrc << 0); - - return 0; -} - -int set_system_clock_MHz(uint8_t mhz) -{ - /* Set the source of the system colck to MSI temporarily. */ - set_system_clock_src(SYSTEM_CLOCK_SRC_MSI); - - if (mhz <= 8 || mhz > 80) { - return E_BAD_ARG; - } - - pll_off(); - - configure_pll( - 0 /* pllp_div_factor */, PLL_DIVISOR_4 /* pllr: VCO / 4 = mhz MHz. */, - PLL_DIVISOR_4 /* pllq: VCO / 4 = mhz MHz */, PLLP_DIVISOR_7 /* pllp */, - - /* The following set the frequency of VCO to (mhz*4)MHz: mhz * 1 * 4MHz. - */ - mhz /* plln | mhz */, PLLM_DIVISOR_1 /* pllm | 01 */, - PLL_SRC_MSI /* pll src | 04 Mhz */); - - pll_on(); - - /* Configure the flash to have 4 wait states. This is required at - * 80 MHz. */ - FLASH.ac_r &= ~0x07; - FLASH.ac_r |= 0x04; - - /* Set the source of the system colck to PLL. */ - set_system_clock_src(SYSTEM_CLOCK_SRC_PLL); - return 0; -} - -int set_system_clock_src(system_clock_src_t src) -{ - uint8_t value = RCC.cfg_r & ~0x03; - RCC.cfg_r = value | src; -} diff --git a/02-usart/src/core/clock.c b/02-usart/src/core/clock.c new file mode 100644 index 0000000..d779140 --- /dev/null +++ b/02-usart/src/core/clock.c @@ -0,0 +1,106 @@ +/* + * This file sets the system clock to its full glory of 80Mhz + */ + +#include "core/clock.h" +#include "core/flash.h" + +#include +#include "spin.h" + +#define TIMEOUT 10000 + +int pll_off() +{ + uint32_t c; + + RCC.c_r &= ~BIT(24); /* Turn off pll. */ + for (c = 0; c < TIMEOUT && RCC.c_r & BIT(25); ++c) + ; /* Wait for OFF. */ + + if (c == TIMEOUT) { + return E_TIMEOUT; + } + + return 0; +} + +int pll_on() +{ + uint32_t c; + + RCC.c_r |= BIT(24); /* Turn on PLL. */ + for (c = 0; c < TIMEOUT && !(RCC.c_r & BIT(25)); ++c) + ; /* Wait for RDY. */ + + if (c == TIMEOUT) { + return E_TIMEOUT; + } + + return 0; +} + +int configure_pll( + uint8_t pllp_div_factor, pll_divisor_t pllr, /* System clock divisor. */ + pll_divisor_t pllq, /* Divison factor for PLL48M1CLK. */ + pllp_divisor_t pllp, /* Divison factor for PLLSAI2CLK. */ + uint8_t plln, /* PLL numerator. */ + pllm_divisor_t pllm, /* PLL denominator. */ + pll_src_t pllsrc /* PLL source */) +{ + if (RCC.c_r & BIT(25)) { + /* PLL must be off to configure it. */ + return E_NOT_OFF; + } + + /* Make sure inputs are valid. */ + if (pllp_div_factor == 1 || pllp_div_factor > 31) { + return E_BADPLLP_DIV; + } + if (plln < 8 || plln > 86) { + return E_BADPLLN; + } + + RCC.pllcfg_r = (pllp_div_factor << 27) | (pllr << 24) | (pllq << 20) | + (pllp << 16) | (plln << 8) | (pllm << 4) | (pllsrc << 0); + + return 0; +} + +int set_system_clock_MHz(uint8_t mhz) +{ + /* Set the source of the system colck to MSI temporarily. */ + set_system_clock_src(SYSTEM_CLOCK_SRC_MSI); + + if (mhz <= 8 || mhz > 80) { + return E_BAD_ARG; + } + + pll_off(); + + configure_pll( + 0 /* pllp_div_factor */, PLL_DIVISOR_4 /* pllr: VCO / 4 = mhz MHz. */, + PLL_DIVISOR_4 /* pllq: VCO / 4 = mhz MHz */, PLLP_DIVISOR_7 /* pllp */, + + /* The following set the frequency of VCO to (mhz*4)MHz: mhz * 1 * 4MHz. + */ + mhz /* plln | mhz */, PLLM_DIVISOR_1 /* pllm | 01 */, + PLL_SRC_MSI /* pll src | 04 Mhz */); + + pll_on(); + + /* Configure the flash to have 4 wait states. This is required at + * 80 MHz. */ + FLASH.ac_r &= ~0x07; + FLASH.ac_r |= 0x04; + + /* Set the source of the system colck to PLL. */ + set_system_clock_src(SYSTEM_CLOCK_SRC_PLL); + return 0; +} + +int set_system_clock_src(system_clock_src_t src) +{ + uint8_t value = RCC.cfg_r & ~0x03; + RCC.cfg_r = value | src; +} diff --git a/02-usart/src/core/gpio.c b/02-usart/src/core/gpio.c new file mode 100644 index 0000000..c46b1ff --- /dev/null +++ b/02-usart/src/core/gpio.c @@ -0,0 +1,52 @@ +#include "core/gpio.h" +#include "core/rcc.h" + +/* + * Sets the mode of a pin on a gpio por. + */ +void set_gpio_pin_mode( + __IO gpio_port_t* gpio_port, gpio_pin_t pin, gpio_pin_mode_t mode) +{ + /* Each pin has a 2-bit mode provided at bits pin#*2 and pin#*2+1 */ + gpio_port->mode_r &= ~(0x03 << pin * 2); + gpio_port->mode_r |= mode << pin * 2; +} + +gpio_output_pin_t set_gpio_pin_output( + __IO gpio_port_t* gpio_port, gpio_pin_t pin) +{ + set_gpio_pin_mode(gpio_port, pin, MODE_OUTPUT); + + return (gpio_output_pin_t){.gpio_port = gpio_port, .pin = pin}; +} + +void set_gpio_output_pin(gpio_output_pin_t pin, bool onoff) +{ + if (onoff) { + pin.gpio_port->output_r |= 1 << pin.pin; + } else { + pin.gpio_port->output_r &= ~(1 << pin.pin); + } +} + +void set_gpio_alternate_function( + __IO gpio_port_t* port, gpio_pin_t gpio_pin, alternate_function_t afn) +{ + __IO uint32_t* reg; + if (gpio_pin < 8) { + reg = &(port->af_rl); + } else { + reg = &(port->af_rh); + gpio_pin -= 8; + } + + uint32_t tmp = *reg & (~0x0f << gpio_pin * 4); + *reg = tmp | (afn << gpio_pin * 4); +} + +#define GPIO_PORTS_BASE_ADDR ((uint8_t*)0x48000000) +__IO gpio_port_t* enable_gpio(gpio_port_number_t gpio_port_number) +{ + RCC.ahb2en_r |= 1 << gpio_port_number; /* Enable the GPIO port. */ + return (__IO gpio_port_t*)(GPIO_PORTS_BASE_ADDR + (gpio_port_number * 0x400)); +} diff --git a/02-usart/src/core/init.c b/02-usart/src/core/init.c new file mode 100644 index 0000000..e127006 --- /dev/null +++ b/02-usart/src/core/init.c @@ -0,0 +1,45 @@ +#include "arch.h" +#include "core/system.h" + +/* Forward-declare the main function. This is implemented in main.c. */ +void main(); + +/* These are defined in the linker script. */ +extern uint32_t INIT_DATA_VALUES; +extern uint32_t DATA_SEGMENT_START; +extern uint32_t DATA_SEGMENT_STOP; +extern uint32_t BSS_START; +extern uint32_t BSS_END; + +/* + * Runs before main. Initializes the data and bss segments by loading them + * into memory. + */ +_Noreturn void on_reset() +{ + uint32_t* src; + uint32_t* dest; + + src = &INIT_DATA_VALUES; + dest = &DATA_SEGMENT_START; + + /* Copy the values from flash into the data segment. */ + while (dest != &DATA_SEGMENT_STOP) { + *(dest++) = *(src++); + } + + /* Everything in the BSS segment is set to zero. */ + dest = &BSS_START; + while (dest != &BSS_END) { + *(dest++) = 0; + } + + /* Set the vector offset table to be at the start + * of FLASH memory. */ + SCB.vto_r = 0x08000000; + + /* Jump to main. */ + main(); + + for(;;); +} diff --git a/02-usart/src/core/isr_vector.c b/02-usart/src/core/isr_vector.c new file mode 100644 index 0000000..9f3f560 --- /dev/null +++ b/02-usart/src/core/isr_vector.c @@ -0,0 +1,107 @@ +#include "core/isr_vector.h" +#include "core/gpio.h" + +#include "arch.h" +#include "delay.h" + +#ifdef ARCH_STM32L4 + +#define IRQ_RESERVED(n) +#define IRQ(name, n) \ + void WEAK name () { \ + unhandled_isr(n); \ + } +#include "core/isrs.i" +#undef IRQ_RESERVED +#undef IRQ + + +void isr_simple_pin_on() +{ + __IO gpio_port_t* port_b = enable_gpio(GPIO_PORT_B); + gpio_output_pin_t pin3 = set_gpio_pin_output(port_b, PIN_3); + + pin_on(pin3); +} + +#define DEFINE_UNHANDLED_ISR(n) \ + int unhandled_isr_##n() \ + { \ + unhandled_isr(n); \ + } + + +/* Flashes wildly. */ +void super_flash() +{ + static int pin_on = 0; + __IO gpio_port_t* port_b = enable_gpio(GPIO_PORT_B); + gpio_output_pin_t pin3 = set_gpio_pin_output(port_b, PIN_3); + + if (pin_on) { + pin_off(pin3); + } else { + pin_on(pin3); + } + + pin_on = !pin_on; +} + +#define IRQ_RESERVED(n) 0, +#define IRQ(name, n) name, +const void* vectors[] __attribute__((section(".vectors"))) = { + (void*)0x2000c000, /* Top of stack at top of sram1. 48k */ +#include "core/isrs.i" +}; +#undef IRQ_RESERVED +#undef IRQ + +/* Encodes the provided number as a series of flashes on the on-board + * LED. The flashes follow as such: + * + * Before the bits of the code are flashed, a rapid succession of 20 flashes + * followed by a pause will occur indicating that the next 8 flashes indicate + * the bits of the provided code. + * + * The next eight flashes are indicate either a 1 or 0 depending on the length + * of the light being on. The first flash is the least-significant bit, the next + * the second least, the third third least, etc. + * + * - A quick flash followed by a long pause indicates a 0 bit. + * - A "long" flash followed by a equally long pause indicates a 1 bit. + */ +void unhandled_isr(uint8_t number) +{ + __IO gpio_port_t* port_b = enable_gpio(GPIO_PORT_B); + gpio_output_pin_t pin3 = set_gpio_pin_output(port_b, PIN_3); + for (;;) { + for (int i = 0; i < 20; ++ i) { + pin_on(pin3); + delay(1000000); + pin_off(pin3); + delay(1000000); + } + delay(50000000); + + int n = number; + for (int i = 0; i < 8; ++ i) { + if (n & 1) { + // LSB is a 1 + pin_on(pin3); + delay(15000000); + pin_off(pin3); + delay(15000000); + } else { + // LSB is a 0 + pin_on(pin3); + delay(1000000); + pin_off(pin3); + delay(29000000); + } + + n >>= 1; + } + } +} + +#endif diff --git a/02-usart/src/core/usart.c b/02-usart/src/core/usart.c new file mode 100644 index 0000000..8f58d8b --- /dev/null +++ b/02-usart/src/core/usart.c @@ -0,0 +1,145 @@ +#include "core/usart.h" +#include "delay.h" +#include "lib.h" +#include + +void set_usart1_clock_src(__IO rcc_t* rcc, usart_clk_src_t usart_clk_src) +{ + rcc->ccip_r = rcc->ccip_r & (~0x03) | usart_clk_src; +} + +void set_usart2_clock_src(__IO rcc_t* rcc, usart_clk_src_t usart_clk_src) +{ + rcc->ccip_r = rcc->ccip_r & ~(0x03 << 2) | (usart_clk_src << 2); +} + +void set_usart2_clock_enabled(__IO rcc_t* rcc, bool enable) +{ + if (enable) { + rcc->apb1en1_r |= BIT(17); + } else { + rcc->apb1en1_r &= ~BIT(17); + } +} + +void set_usart1_clock_enabled(__IO rcc_t* rcc, bool enable) +{ + if (enable) { + rcc->apb2en_r |= BIT(14); + } else { + rcc->apb2en_r &= ~BIT(14); + } +} + +void usart_set_parity(__IO usart_t* usart, usart_parity_t parity) +{ + uint32_t c_r1 = usart->c_r1; + c_r1 &= ~(0x3 << 9); + c_r1 |= parity; + usart->c_r1 = c_r1; +} + +void usart_set_enabled(__IO usart_t* usart, usart_enable_t enabled) +{ + uint32_t c_r1 = usart->c_r1; + + if (!enabled) { + usart->c1_bf.ue = 0; + } else { + /* Set the rx enabled. */ + usart->c1_bf.re = !!(enabled & USART_ENABLE_RX); + usart->c1_bf.te = !!(enabled & USART_ENABLE_TX); + usart->c1_bf.ue = 1; + } +} + +void usart_transmit_byte_sync(__IO usart_t* usart, uint8_t byte) +{ + usart->td_r = byte; + /* Per the manual, when bit 7 of the IS register is set, then the usart + * data has been sent to the shift register. + * + * This bit is cleared by writing to the TD register. */ + while (!(usart->is_r & BIT(7))) + ; +} + +void usart_transmit_bytes_sync(__IO usart_t* usart, const uint8_t* bytes, uint32_t n) +{ + while (n --) { + usart_transmit_byte_sync(usart, *(bytes ++)); + } +} + +void usart_transmit_str_sync(__IO usart_t* usart, const char* str) +{ + while (*str) { + if (*str == '\n') { + usart_transmit_byte_sync(usart, '\r'); + } + 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; + }; +} + +void usart_printf(__IO usart_t* usart, const char* fmt, ...) +{ + va_list l; + union { + void* ptr; + int i; + } b; + char buf[128]; + + va_start(l, fmt); + + while (*fmt != 0) { + if (*fmt == '%') { + switch (*(++fmt)) { + case 0: + goto end; + case '%': + usart_transmit_byte_sync(usart, '%'); + break; + case 'p': + b.ptr = va_arg(l, void*); + hexify(ptr2reg(b.ptr), buf); + usart_transmit_str_sync(usart, "0x"); + usart_transmit_str_sync(usart, buf); + break; + case 'd': + case 'i': + b.i = va_arg(l, int); + decimalify(b.i, buf); + usart_transmit_str_sync(usart, buf); + break; + } + ++ fmt; + } else { + if (*fmt == '\n') { + usart_transmit_byte_sync(usart, '\r'); + } + usart_transmit_byte_sync(usart, *(fmt ++)); + } + } + +end: + va_end(l); +} diff --git a/02-usart/src/gpio.c b/02-usart/src/gpio.c deleted file mode 100644 index 02933b7..0000000 --- a/02-usart/src/gpio.c +++ /dev/null @@ -1,52 +0,0 @@ -#include "gpio.h" -#include "rcc.h" - -/* - * Sets the mode of a pin on a gpio por. - */ -void set_gpio_pin_mode( - __IO gpio_port_t* gpio_port, gpio_pin_t pin, gpio_pin_mode_t mode) -{ - /* Each pin has a 2-bit mode provided at bits pin#*2 and pin#*2+1 */ - gpio_port->mode_r &= ~(0x03 << pin * 2); - gpio_port->mode_r |= mode << pin * 2; -} - -gpio_output_pin_t set_gpio_pin_output( - __IO gpio_port_t* gpio_port, gpio_pin_t pin) -{ - set_gpio_pin_mode(gpio_port, pin, MODE_OUTPUT); - - return (gpio_output_pin_t){.gpio_port = gpio_port, .pin = pin}; -} - -void set_gpio_output_pin(gpio_output_pin_t pin, bool onoff) -{ - if (onoff) { - pin.gpio_port->output_r |= 1 << pin.pin; - } else { - pin.gpio_port->output_r &= ~(1 << pin.pin); - } -} - -void set_gpio_alternate_function( - __IO gpio_port_t* port, gpio_pin_t gpio_pin, alternate_function_t afn) -{ - __IO uint32_t* reg; - if (gpio_pin < 8) { - reg = &(port->af_rl); - } else { - reg = &(port->af_rh); - gpio_pin -= 8; - } - - uint32_t tmp = *reg & (~0x0f << gpio_pin * 4); - *reg = tmp | (afn << gpio_pin * 4); -} - -#define GPIO_PORTS_BASE_ADDR ((uint8_t*)0x48000000) -__IO gpio_port_t* enable_gpio(gpio_port_number_t gpio_port_number) -{ - RCC.ahb2en_r |= 1 << gpio_port_number; /* Enable the GPIO port. */ - return (__IO gpio_port_t*)(GPIO_PORTS_BASE_ADDR + (gpio_port_number * 0x400)); -} diff --git a/02-usart/src/init.c b/02-usart/src/init.c deleted file mode 100644 index 70703aa..0000000 --- a/02-usart/src/init.c +++ /dev/null @@ -1,45 +0,0 @@ -#include "arch.h" -#include "system.h" - -/* Forward-declare the main function. This is implemented in main.c. */ -void main(); - -/* These are defined in the linker script. */ -extern uint32_t INIT_DATA_VALUES; -extern uint32_t DATA_SEGMENT_START; -extern uint32_t DATA_SEGMENT_STOP; -extern uint32_t BSS_START; -extern uint32_t BSS_END; - -/* - * Runs before main. Initializes the data and bss segments by loading them - * into memory. - */ -_Noreturn void on_reset() -{ - uint32_t* src; - uint32_t* dest; - - src = &INIT_DATA_VALUES; - dest = &DATA_SEGMENT_START; - - /* Copy the values from flash into the data segment. */ - while (dest != &DATA_SEGMENT_STOP) { - *(dest++) = *(src++); - } - - /* Everything in the BSS segment is set to zero. */ - dest = &BSS_START; - while (dest != &BSS_END) { - *(dest++) = 0; - } - - /* Set the vector offset table to be at the start - * of FLASH memory. */ - SCB.vto_r = 0x08000000; - - /* Jump to main. */ - main(); - - for(;;); -} diff --git a/02-usart/src/isr_vector.c b/02-usart/src/isr_vector.c deleted file mode 100644 index 484f3c5..0000000 --- a/02-usart/src/isr_vector.c +++ /dev/null @@ -1,107 +0,0 @@ -#include "isr_vector.h" - -#include "arch.h" -#include "delay.h" -#include "gpio.h" - -#ifdef ARCH_STM32L4 - -#define IRQ_RESERVED(n) -#define IRQ(name, n) \ - void WEAK name () { \ - unhandled_isr(n); \ - } -#include "isrs.i" -#undef IRQ_RESERVED -#undef IRQ - - -void isr_simple_pin_on() -{ - __IO gpio_port_t* port_b = enable_gpio(GPIO_PORT_B); - gpio_output_pin_t pin3 = set_gpio_pin_output(port_b, PIN_3); - - pin_on(pin3); -} - -#define DEFINE_UNHANDLED_ISR(n) \ - int unhandled_isr_##n() \ - { \ - unhandled_isr(n); \ - } - - -/* Flashes wildly. */ -void super_flash() -{ - static int pin_on = 0; - __IO gpio_port_t* port_b = enable_gpio(GPIO_PORT_B); - gpio_output_pin_t pin3 = set_gpio_pin_output(port_b, PIN_3); - - if (pin_on) { - pin_off(pin3); - } else { - pin_on(pin3); - } - - pin_on = !pin_on; -} - -#define IRQ_RESERVED(n) 0, -#define IRQ(name, n) name, -const void* vectors[] __attribute__((section(".vectors"))) = { - (void*)0x2000c000, /* Top of stack at top of sram1. 48k */ -#include "isrs.i" -}; -#undef IRQ_RESERVED -#undef IRQ - -/* Encodes the provided number as a series of flashes on the on-board - * LED. The flashes follow as such: - * - * Before the bits of the code are flashed, a rapid succession of 20 flashes - * followed by a pause will occur indicating that the next 8 flashes indicate - * the bits of the provided code. - * - * The next eight flashes are indicate either a 1 or 0 depending on the length - * of the light being on. The first flash is the least-significant bit, the next - * the second least, the third third least, etc. - * - * - A quick flash followed by a long pause indicates a 0 bit. - * - A "long" flash followed by a equally long pause indicates a 1 bit. - */ -void unhandled_isr(uint8_t number) -{ - __IO gpio_port_t* port_b = enable_gpio(GPIO_PORT_B); - gpio_output_pin_t pin3 = set_gpio_pin_output(port_b, PIN_3); - for (;;) { - for (int i = 0; i < 20; ++ i) { - pin_on(pin3); - delay(1000000); - pin_off(pin3); - delay(1000000); - } - delay(50000000); - - int n = number; - for (int i = 0; i < 8; ++ i) { - if (n & 1) { - // LSB is a 1 - pin_on(pin3); - delay(15000000); - pin_off(pin3); - delay(15000000); - } else { - // LSB is a 0 - pin_on(pin3); - delay(1000000); - pin_off(pin3); - delay(29000000); - } - - n >>= 1; - } - } -} - -#endif diff --git a/02-usart/src/main.c b/02-usart/src/main.c index b293202..73ccb17 100644 --- a/02-usart/src/main.c +++ b/02-usart/src/main.c @@ -1,16 +1,17 @@ -#include "isr_vector.h" -#include "lib.h" -#include "string.h" -#include "mem.h" -#include "dma.h" #include "arch.h" -#include "clock.h" +#include "core/clock.h" +#include "core/dma.h" +#include "core/gpio.h" +#include "core/isr_vector.h" +#include "core/system.h" +#include "core/usart.h" + #include "delay.h" -#include "gpio.h" +#include "lib.h" +#include "mem.h" #include "spin.h" -#include "usart.h" -#include "system.h" +#include "string.h" #ifdef ARCH_STM32L4 diff --git a/02-usart/src/mem.c b/02-usart/src/mem.c index 5772bdc..9fef8bc 100644 --- a/02-usart/src/mem.c +++ b/02-usart/src/mem.c @@ -1,11 +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_ ++); -} +// 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/spin.c b/02-usart/src/spin.c index fbd16b6..4d1aede 100644 --- a/02-usart/src/spin.c +++ b/02-usart/src/spin.c @@ -1,6 +1,6 @@ #include "spin.h" #include "delay.h" -#include "gpio.h" +#include "core/gpio.h" #define SHORT_DELAY 200000 #define LONG_DELAY (SHORT_DELAY * 2) diff --git a/02-usart/src/usart.c b/02-usart/src/usart.c deleted file mode 100644 index 07bf90c..0000000 --- a/02-usart/src/usart.c +++ /dev/null @@ -1,145 +0,0 @@ -#include "usart.h" -#include "delay.h" -#include "lib.h" -#include - -void set_usart1_clock_src(__IO rcc_t* rcc, usart_clk_src_t usart_clk_src) -{ - rcc->ccip_r = rcc->ccip_r & (~0x03) | usart_clk_src; -} - -void set_usart2_clock_src(__IO rcc_t* rcc, usart_clk_src_t usart_clk_src) -{ - rcc->ccip_r = rcc->ccip_r & ~(0x03 << 2) | (usart_clk_src << 2); -} - -void set_usart2_clock_enabled(__IO rcc_t* rcc, bool enable) -{ - if (enable) { - rcc->apb1en1_r |= BIT(17); - } else { - rcc->apb1en1_r &= ~BIT(17); - } -} - -void set_usart1_clock_enabled(__IO rcc_t* rcc, bool enable) -{ - if (enable) { - rcc->apb2en_r |= BIT(14); - } else { - rcc->apb2en_r &= ~BIT(14); - } -} - -void usart_set_parity(__IO usart_t* usart, usart_parity_t parity) -{ - uint32_t c_r1 = usart->c_r1; - c_r1 &= ~(0x3 << 9); - c_r1 |= parity; - usart->c_r1 = c_r1; -} - -void usart_set_enabled(__IO usart_t* usart, usart_enable_t enabled) -{ - uint32_t c_r1 = usart->c_r1; - - if (!enabled) { - usart->c1_bf.ue = 0; - } else { - /* Set the rx enabled. */ - usart->c1_bf.re = !!(enabled & USART_ENABLE_RX); - usart->c1_bf.te = !!(enabled & USART_ENABLE_TX); - usart->c1_bf.ue = 1; - } -} - -void usart_transmit_byte_sync(__IO usart_t* usart, uint8_t byte) -{ - usart->td_r = byte; - /* Per the manual, when bit 7 of the IS register is set, then the usart - * data has been sent to the shift register. - * - * This bit is cleared by writing to the TD register. */ - while (!(usart->is_r & BIT(7))) - ; -} - -void usart_transmit_bytes_sync(__IO usart_t* usart, const uint8_t* bytes, uint32_t n) -{ - while (n --) { - usart_transmit_byte_sync(usart, *(bytes ++)); - } -} - -void usart_transmit_str_sync(__IO usart_t* usart, const char* str) -{ - while (*str) { - if (*str == '\n') { - usart_transmit_byte_sync(usart, '\r'); - } - 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; - }; -} - -void usart_printf(__IO usart_t* usart, const char* fmt, ...) -{ - va_list l; - union { - void* ptr; - int i; - } b; - char buf[128]; - - va_start(l, fmt); - - while (*fmt != 0) { - if (*fmt == '%') { - switch (*(++fmt)) { - case 0: - goto end; - case '%': - usart_transmit_byte_sync(usart, '%'); - break; - case 'p': - b.ptr = va_arg(l, void*); - hexify(ptr2reg(b.ptr), buf); - usart_transmit_str_sync(usart, "0x"); - usart_transmit_str_sync(usart, buf); - break; - case 'd': - case 'i': - b.i = va_arg(l, int); - decimalify(b.i, buf); - usart_transmit_str_sync(usart, buf); - break; - } - ++ fmt; - } else { - if (*fmt == '\n') { - usart_transmit_byte_sync(usart, '\r'); - } - usart_transmit_byte_sync(usart, *(fmt ++)); - } - } - -end: - va_end(l); -} diff --git a/02-usart/tests/test_dma.c b/02-usart/tests/test_dma.c index 7704590..ae34a69 100644 --- a/02-usart/tests/test_dma.c +++ b/02-usart/tests/test_dma.c @@ -1,5 +1,5 @@ #include "test_harness.h" -#include "dma.h" +#include "core/dma.h" #include #include diff --git a/02-usart/tests/test_lib.c b/02-usart/tests/test_lib.c new file mode 100644 index 0000000..8d63577 --- /dev/null +++ b/02-usart/tests/test_lib.c @@ -0,0 +1,19 @@ +#include "test_harness.h" +#include "lib.h" + +TEST(lib, hexify) +{ + char buf[10]; + + hexify(0xaaaaaaaa, buf); + ASSERT_EQ_STR(buf, "AAAAAAAA"); + + hexify(0xdddddddd, buf); + ASSERT_EQ_STR(buf, "DDDDDDDD"); + + hexify(0x02468ace, buf); + ASSERT_EQ_STR(buf, "02468ACE"); + + hexify(0xdeadbeef, buf); + ASSERT_EQ_STR(buf, "DEADBEEF"); +} diff --git a/02-usart/tests/test_memory.c b/02-usart/tests/test_memory.c new file mode 100644 index 0000000..e62877a --- /dev/null +++ b/02-usart/tests/test_memory.c @@ -0,0 +1,12 @@ +#include "test_harness.c" +#include "memory.h" + +TEST(memory, memcpy) +{ + const char* from = "Hello"; + char to[16]; + + memcpy(to, from, 6); + + ASSERT_EQ_STR(to, from); +} diff --git a/02-usart/tests/test_usart.c b/02-usart/tests/test_usart.c new file mode 100644 index 0000000..e2cfdf8 --- /dev/null +++ b/02-usart/tests/test_usart.c @@ -0,0 +1,20 @@ +#include "test_harness.h" +#include "core/usart.h" + +#include + +TEST(usart, enable_dma) +{ + __IO usart_t* usart = &USART1; + + usart->c_r3 = 0; + + usart_enable_dma(usart, USART_ENABLE_TX); + ASSERT_EQ(usart->c_r3, 128); + + usart_enable_dma(usart, USART_ENABLE_RX); + ASSERT_EQ(usart->c_r3, 192); + + usart_enable_dma(usart, USART_ENABLE_DISABLED); + ASSERT_EQ(usart->c_r3, 0); +} -- cgit