diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2020-11-18 21:11:01 -0700 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2020-11-18 21:16:12 -0700 |
commit | c1405b06d98b9b227fa7ff53c158f31d745eb505 (patch) | |
tree | 77397453c2b0e20bbb4136aa52836fe3eb0e41e6 /02-usart/include/core | |
parent | 44c2d2d5e5ce43563a4912b2967cdb6b2039b6dd (diff) | |
download | stm32l4-c1405b06d98b9b227fa7ff53c158f31d745eb505.tar.gz stm32l4-c1405b06d98b9b227fa7ff53c158f31d745eb505.tar.bz2 stm32l4-c1405b06d98b9b227fa7ff53c158f31d745eb505.zip |
Reorganize some file. Put thte core register libraries in a core/
subdirectory.
Diffstat (limited to '02-usart/include/core')
-rw-r--r-- | 02-usart/include/core/apb.h | 4 | ||||
-rw-r--r-- | 02-usart/include/core/clock.h | 126 | ||||
-rw-r--r-- | 02-usart/include/core/dma.h | 172 | ||||
-rw-r--r-- | 02-usart/include/core/flash.h | 20 | ||||
-rw-r--r-- | 02-usart/include/core/gpio.h | 146 | ||||
-rw-r--r-- | 02-usart/include/core/isr_vector.h | 24 | ||||
-rw-r--r-- | 02-usart/include/core/isrs.i | 112 | ||||
-rw-r--r-- | 02-usart/include/core/rcc.h | 109 | ||||
-rw-r--r-- | 02-usart/include/core/system.h | 84 | ||||
-rw-r--r-- | 02-usart/include/core/usart.h | 223 |
10 files changed, 1020 insertions, 0 deletions
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 <stdint.h> +#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 <arch.h> +#include <stdint.h> + +#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 <stdint.h> + +/* + * 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 <stdint.h> + +/* + * 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 <stdint.h> + +#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 <stdint.h> +#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 <arch.h> +#include <stdint.h> + +#include "common.h" +#include "rcc.h" +#include <assert.h> + +#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_ */ |