diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2020-11-24 13:46:41 -0700 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2020-11-24 13:46:41 -0700 |
commit | 93b063fedfcf7409a67df035170ea5670cad22e1 (patch) | |
tree | a23321a7465d966b1ccf196ca00e65a70c9f9110 /include | |
parent | b040195d31df6ad759f16ea3456471897f55daa1 (diff) | |
download | stm32l4-93b063fedfcf7409a67df035170ea5670cad22e1.tar.gz stm32l4-93b063fedfcf7409a67df035170ea5670cad22e1.tar.bz2 stm32l4-93b063fedfcf7409a67df035170ea5670cad22e1.zip |
Moved action to top level.
Removed old iterations of the project and moved the files from 02-usart
to the root directory since that's the sole place where the action is
and that subproject has outgrown its initial title.
Diffstat (limited to 'include')
26 files changed, 2000 insertions, 0 deletions
diff --git a/include/arch/arm/arch.h b/include/arch/arm/arch.h new file mode 100644 index 0000000..22d0987 --- /dev/null +++ b/include/arch/arm/arch.h @@ -0,0 +1,43 @@ +#ifndef ARCH_H_ +#define ARCH_H_ + +#ifndef ARCH_STM32L4 +#define ARCH_STM32L4 +#endif + +#define CORTEX_M4 + +#define enable_all_interrupts() \ + asm volatile(" cpsie i ") + + +#define DMA1_BASE (0x40020000) +#define DMA2_BASE (0x40020400) + +#define USART1_BASE (0x40013800) +#define USART2_BASE (0x40004400) + +#define GPIOA_BASE (0x48000000) +#define GPIOB_BASE (0x48000400) +#define GPIOC_BASE (0x48000800) +#define GPIOH_BASE (0x48001C00) + +#define SRAM1_BASE (0x20000000) +#define SRAM2_BASE (0x2000C000) + +#define SYSTEM_CONFIG_BLOCK_BASE (0xE000E008) +#define NVIC_BASE (0xE000E004) +#define RCC_BASE (0x40021000) + +#define SPI1_BASE (0x40013000) +#define SPI3_BASE (0x40003C00) + +#include <stdint.h> +#ifndef DRY_RUN +_Static_assert(sizeof(void*) == sizeof(uint32_t), "Pointers must be 32 bits"); +#endif + +extern uint32_t DATA_SEGMENT_START; +extern uint32_t DATA_SEGMENT_STOP; + +#endif /* ARCH_H_ */ diff --git a/include/arch/stm32l4xxx/peripherals/apb.h b/include/arch/stm32l4xxx/peripherals/apb.h new file mode 100644 index 0000000..11fa7ab --- /dev/null +++ b/include/arch/stm32l4xxx/peripherals/apb.h @@ -0,0 +1,4 @@ +#ifndef H__APB_ +#define H__APB_ + +#endif /* H__APB_ */ diff --git a/include/arch/stm32l4xxx/peripherals/clock.h b/include/arch/stm32l4xxx/peripherals/clock.h new file mode 100644 index 0000000..6f628fd --- /dev/null +++ b/include/arch/stm32l4xxx/peripherals/clock.h @@ -0,0 +1,128 @@ +#ifndef CORE_CLOCK_H__ +#define CORE_CLOCK_H__ + +#include <stdint.h> +#include "arch/stm32l4xxx/peripherals/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 */); + +uint8_t get_clock_mhz(); + +#endif /* CORE_CLOCK_H__ */ diff --git a/include/arch/stm32l4xxx/peripherals/dma.h b/include/arch/stm32l4xxx/peripherals/dma.h new file mode 100644 index 0000000..f62a92b --- /dev/null +++ b/include/arch/stm32l4xxx/peripherals/dma.h @@ -0,0 +1,149 @@ +#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 "kern/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_t; + +typedef enum { + READ_FROM_PERIPHERAL = 0, + READ_FROM_MEMORY = 1, +} dma_dir_t; + +typedef struct { + +#define dma_cc_en (1 << 0) // channel enable +#define dma_cc_tcie (1 << 1) // transfer complete interrupt enable +#define dma_cc_htie (1 << 2) // half transfer interrupt enable +#define dma_cc_teie (1 << 3) // transfer error interrupt enable +#define dma_cc_dir (1 << 4) // data transfer direction +#define dma_cc_circ (1 << 5) // circular mode +#define dma_cc_pinc (1 << 6) // peripheral increment mode +#define dma_cc_minc (1 << 7) // memory increment mode +#define dma_cc_psize (3 << 8) // Peripheral size +#define dma_cc_msize (3 << 10) // Memory size +#define dma_cc_pl (3 << 12) // Priority level +#define dma_cc_mem2mem (1 << 14) // Memory to memory mode + + __IO uint32_t cc_r; + + /* Number of data to transfer. Can only store a short. */ + __IO uint32_t cndt_r; + + /* DMA channel peripheral address register. + * Defines a memory address if mem2mem is set. */ + __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. +#define dma_gif1 (1 << 0) // global interrupt flag for channel 1 +#define dma_tcif1 (1 << 1) // transfer complete (TC) flag for channel 1 +#define dma_htif1 (1 << 2) // half transfer (HT) flag for channel 1 +#define dma_teif1 (1 << 3) // transfer error (TE) flag for channel 1 +#define dma_gif2 (1 << 4) // global interrupt flag for channel 2 +#define dma_tcif2 (1 << 5) // transfer complete (TC) flag for channel 2 +#define dma_htif2 (1 << 6) // half transfer (HT) flag for channel 2 +#define dma_teif2 (1 << 7) // transfer error (TE) flag for channel 2 +#define dma_gif3 (1 << 8) // global interrupt flag for channel 3 +#define dma_tcif3 (1 << 9) // transfer complete (TC) flag for channel 3 +#define dma_htif3 (1 << 10) // half transfer (HT) flag for channel 3 +#define dma_teif3 (1 << 11) // transfer error (TE) flag for channel 3 +#define dma_gif4 (1 << 12) // global interrupt flag for channel 4 +#define dma_tcif4 (1 << 13) // transfer complete (TC) flag for channel 4 +#define dma_htif4 (1 << 14) // half transfer (HT) flag for channel 4 +#define dma_teif4 (1 << 15) // transfer error (TE) flag for channel 4 +#define dma_gif5 (1 << 16) // global interrupt flag for channel 5 +#define dma_tcif5 (1 << 17) // transfer complete (TC) flag for channel 5 +#define dma_htif5 (1 << 18) // half transfer (HT) flag for channel 5 +#define dma_teif5 (1 << 19) // transfer error (TE) flag for channel 5 +#define dma_gif6 (1 << 20) // global interrupt flag for channel 6 +#define dma_tcif6 (1 << 21) // transfer complete (TC) flag for channel 6 +#define dma_htif6 (1 << 22) // half transfer (HT) flag for channel 6 +#define dma_teif6 (1 << 23) // transfer error (TE) flag for channel 6 +#define dma_gif7 (1 << 24) // global interrupt flag for channel 7 +#define dma_tcif7 (1 << 25) // transfer complete (TC) flag for channel 7 +#define dma_htif7 (1 << 26) // half transfer (HT) flag for channel 7 +#define dma_teif7 (1 << 27) // transfer error (TE) flag for channel 7 + __IO uint32_t is_r; + + // DMA Interrupt flag clear register +#define dma_cgif1 (1 << 0) // global interrupt flag clear for channel 1 +#define dma_ctcif1 (1 << 1) // transfer complete flag clear for channel 1 +#define dma_chtif1 (1 << 2) // half transfer flag clear for channel 1 +#define dma_cteif1 (1 << 3) // transfer error flag clear for channel 1 +#define dma_cgif2 (1 << 4) // global interrupt flag clear for channel 2 +#define dma_ctcif2 (1 << 5) // transfer complete flag clear for channel 2 +#define dma_chtif2 (1 << 6) // half transfer flag clear for channel 2 +#define dma_cteif2 (1 << 7) // transfer error flag clear for channel 2 +#define dma_cgif3 (1 << 8) // global interrupt flag clear for channel 3 +#define dma_ctcif3 (1 << 9) // transfer complete flag clear for channel 3 +#define dma_chtif3 (1 << 10) // half transfer flag clear for channel 3 +#define dma_cteif3 (1 << 11) // transfer error flag clear for channel 3 +#define dma_cgif4 (1 << 12) // global interrupt flag clear for channel 4 +#define dma_ctcif4 (1 << 13) // transfer complete flag clear for channel 4 +#define dma_chtif4 (1 << 14) // half transfer flag clear for channel 4 +#define dma_cteif4 (1 << 15) // transfer error flag clear for channel 4 +#define dma_cgif5 (1 << 16) // global interrupt flag clear for channel 5 +#define dma_ctcif5 (1 << 17) // transfer complete flag clear for channel 5 +#define dma_chtif5 (1 << 18) // half transfer flag clear for channel 5 +#define dma_cteif5 (1 << 19) // transfer error flag clear for channel 5 +#define dma_cgif6 (1 << 20) // global interrupt flag clear for channel 6 +#define dma_ctcif6 (1 << 21) // transfer complete flag clear for channel 6 +#define dma_chtif6 (1 << 22) // half transfer flag clear for channel 6 +#define dma_cteif6 (1 << 23) // transfer error flag clear for channel 6 +#define dma_cgif7 (1 << 24) // global interrupt flag clear for channel 7 +#define dma_ctcif7 (1 << 25) // transfer complete flag clear for channel 7 +#define dma_chtif7 (1 << 26) // half transfer flag clear for channel 7 +#define dma_cteif7 (1 << 27) // transfer error flag clear for channel 7 + __IO uint32_t ifc_r; + + dma_channel_config_t channel_config[7]; + + __IO uint32_t reserved[5]; + + /* DMA channel selection register. */ +#define dma_c1s (0xF << 0) // DMA channel 1 selection. +#define dma_c2s (0xF << 4) // DMA channel 2 selection. +#define dma_c3s (0xF << 8) // DMA channel 3 selection. +#define dma_c4s (0xF << 12) // DMA channel 4 selection. +#define dma_c5s (0xF << 16) // DMA channel 5 selection. +#define dma_c6s (0xF << 20) // DMA channel 6 selection. +#define dma_c7s (0xF << 24) // DMA channel 7 selection. + __IO uint32_t csel_r; +} dma_t; + +static_assert(offsetof(dma_t, csel_r) == 0xA8, "Offset check failed."); + +#endif /* CORE_DMA_H_ */ diff --git a/include/arch/stm32l4xxx/peripherals/flash.h b/include/arch/stm32l4xxx/peripherals/flash.h new file mode 100644 index 0000000..28a3d6c --- /dev/null +++ b/include/arch/stm32l4xxx/peripherals/flash.h @@ -0,0 +1,20 @@ +#ifndef H__FLASH_ +#define H__FLASH_ + +#include "kern/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/include/arch/stm32l4xxx/peripherals/gpio.h b/include/arch/stm32l4xxx/peripherals/gpio.h new file mode 100644 index 0000000..944d725 --- /dev/null +++ b/include/arch/stm32l4xxx/peripherals/gpio.h @@ -0,0 +1,66 @@ +#ifndef CORE_GPIO_H__ +#define CORE_GPIO_H__ + +#include "kern/common.h" +#include "arch/stm32l4xxx/peripherals/rcc.h" + +#include <stdint.h> + +/* + * Structure defining the layout of the layout of the GPIO registers on the + * stm32l432 development board. + */ +typedef struct GPIO_PORT_STR { + /* Mode of each GPIO pin for this GPIO port. */ +#define gpio_mode_n(off) (3 << ((off) * 2)) + __IO uint32_t mode_r; /* Mode register */ + + /* Output type for each gpio pin in this port. */ +#define gpio_otype_n(off) (1 << (off)) + __IO uint32_t otype_r; + + /* GPIO port output speed. */ +#define gpio_ospeed_n(off) (3 << ((off) * 2)) + __IO uint32_t ospeed_r; + + /* GPIO port pull-up/pull-down register */ +#define gpio_pupd_n(off) (3 << ((off) * 2)) + __IO uint32_t pupd_r; + + /* GPIO port input data register. */ +#define gpio_idr_n(off) (1 << (off)) + __IO uint32_t id_r; + + /* GPIO port output data register. */ +#define gpio_odr_n(off) (1 << (off)) + __IO uint32_t od_r; + + /* GPIO port bit set/reset register. */ +#define gpio_bs_n(off) (1 << (off)) +#define gpio_br_n(off) (1 << (off)) + __IO uint32_t bsr_r; + + /* GPIO port configuration lock register. */ +#define gpio_lck_n(off) (1 << (off)) +#define gpio_lckk (1 << 16) + __IO uint32_t lck_r; + + /* Alternate function low-register. */ +#define gpio_afsel_n(off) (0xf << ((off) * 4)) + __IO uint32_t af_rl; + /* Alternate function high-register. */ + __IO uint32_t af_rh; + + /* GPIO port bit register. */ +#define gpio_br_n(off) (1 << (off)) + __IO uint32_t br_r; + + /* Analog switch control register. */ +#define gpio_asc_n(off) (1 << (off)) + __IO uint32_t asc_r; +} PACKED gpio_port_config_t; + +static_assert( + offsetof(gpio_port_config_t, asc_r) == 0x2C, "Offset check failed"); + +#endif diff --git a/include/arch/stm32l4xxx/peripherals/irq.h b/include/arch/stm32l4xxx/peripherals/irq.h new file mode 100644 index 0000000..52878ca --- /dev/null +++ b/include/arch/stm32l4xxx/peripherals/irq.h @@ -0,0 +1,89 @@ +#ifndef CORE_IRQ_H__ +#define CORE_IRQ_H__ + +#include <stdint.h> + +/* + * Include file for interrupt service routines. + */ + +typedef enum { +#define IRQ_RESERVED(n) +#define IRQ(name_, uname, num) \ + IRQ_##uname = num, +#include "arch/stm32l4xxx/peripherals//isrs.inc" +#undef IRQ +#undef IRQ_RESERVED +} interrupt_t; + +/* Defines a set of interrupts so they may be enabled all at once. */ +typedef struct { + uint32_t sysirqs; /* System iterrupts. */ + uint32_t irqs[8]; +} interrupt_set_t; + +inline static void interrupt_set_add( + interrupt_set_t* interrupt_set, interrupt_t interrupt) +{ + if (interrupt < 16) { + interrupt_set->sysirqs |= 1 << interrupt; + return; + } + + interrupt -= 16; + int loc = interrupt / 32; + int off = interrupt % 32; + + interrupt_set->irqs[loc] |= 1 << off; +} + +inline static void interrupt_set_remove( + interrupt_set_t* interrupt_set, interrupt_t interrupt) +{ + if (interrupt < 16) { + interrupt_set->sysirqs &= ~(1 << interrupt); + return; + } + + interrupt -= 16; + int loc = interrupt / 32; + int off = interrupt % 32; + + interrupt_set->irqs[loc] &= ~(1 << off); +} + +/* + * 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); + +#define enable_interrupt(val) \ + {interrupt_set_t itrset = { 0 }; \ + interrupt_set_add(&itrset, val); \ + enable_interrupts(&itrset);} + +#define disable_interrupt(val) \ + {interrupt_set_t itrset = { 0 }; \ + interrupt_set_add(&itrset, val); \ + disable_interrupts(&itrset);} + +/* + * Enables the provided interrupt. Note that if the interrupt is one of the + * system interrupts (first 16) this function has no effect because those + * interrupts are always enabled. + */ +void enable_interrupts(interrupt_set_t* interrupts); + +/* + * Enables the provided interrupt + */ +void disable_interrupts(interrupt_set_t* interrupts); + +#endif /* CORE_IRQ_H_ */ diff --git a/include/arch/stm32l4xxx/peripherals/isrs.inc b/include/arch/stm32l4xxx/peripherals/isrs.inc new file mode 100644 index 0000000..0682238 --- /dev/null +++ b/include/arch/stm32l4xxx/peripherals/isrs.inc @@ -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, RESET, 1) +IRQ(on_nmi, NMI, 2) +IRQ(on_hard_fault, HARD_FAULT, 3) +IRQ(on_mem_manage, MEM_MANAGE, 4) +IRQ(on_bus_fault, BUS_FAULT, 5) +IRQ(on_usage_fault, USAGE_FAULT, 6) +IRQ_RESERVED(7) +IRQ_RESERVED(8) +IRQ_RESERVED(9) +IRQ_RESERVED(10) +IRQ(on_svc, SVC, 11) +IRQ(on_debug_mon, DEBUG_MON, 12) +IRQ_RESERVED(13) +IRQ(on_pendsv, PENDSV, 14) +IRQ(on_systick, SYSTICK, 15) +IRQ(on_wwdg_irq, WWDG_IRQ, 16) +IRQ(on_pvd_irq, PVD_IRQ, 17) +IRQ(on_tamper_stamp_irq, TAMPER_STAMP_IRQ, 18) +IRQ(on_rtc_wkup_irq, RTC_WKUP_IRQ, 19) +IRQ(on_flash_irq, FLASH_IRQ, 20) +IRQ(on_rcc_irq, RCC_IRQ, 21) +IRQ(on_exti0_irq, EXTI0_IRQ, 22) +IRQ(on_exti1_irq, EXTI1_IRQ, 23) +IRQ(on_exti2_irq, EXTI2_IRQ, 24) +IRQ(on_exti3_irq, EXTI3_IRQ, 25) +IRQ(on_exti4_irq, EXTI4_IRQ, 26) +IRQ(on_dma1_channel1_irq, DMA1_CHANNEL1_IRQ, 27) +IRQ(on_dma1_channel2_irq, DMA1_CHANNEL2_IRQ, 28) +IRQ(on_dma1_channel3_irq, DMA1_CHANNEL3_IRQ, 29) +IRQ(on_dma1_channel4_irq, DMA1_CHANNEL4_IRQ, 30) +IRQ(on_dma1_channel5_irq, DMA1_CHANNEL5_IRQ, 31) +IRQ(on_dma1_channel6_irq, DMA1_CHANNEL6_IRQ, 32) +IRQ(on_dma1_channel7_irq, DMA1_CHANNEL7_IRQ, 33) +IRQ(on_adc1_irq, ADC1_IRQ, 34) +IRQ(on_can1_tx, CAN1_TX, 35) +IRQ(on_can1_rx0, CAN1_RX0, 36) +IRQ(on_can1_rx1, CAN1_RX1, 37) +IRQ(on_can1_sce, CAN1_SCE, 38) +IRQ(on_exti9_5, EXTI9_5, 39) +IRQ(on_tim1_brk, TIM1_BRK, 40) +IRQ(on_tim1_up, TIM1_UP, 41) +IRQ(on_tim1_trg_com, TIM1_TRG_COM, 42) +IRQ(on_tim1_cc, TIM1_CC, 43) +IRQ(on_tim2, TIM2, 44) +IRQ(on_tim3, TIM3, 45) +IRQ(on_tim4, TIM4, 46) +IRQ(on_i2c1_ev, I2C1_EV, 47) +IRQ(on_i2c1_er, I2C1_ER, 48) +IRQ(on_i2c2_ev, I2C2_EV, 49) +IRQ(on_i2c2_er, I2C2_ER, 50) +IRQ(on_spi1, SPI1, 51) +IRQ(on_spi2, SPI2, 52) +IRQ(on_usart1, USART1, 53) +IRQ(on_usart2, USART2, 54) +IRQ(on_usart3, USART3, 55) +IRQ(on_exti15_10, EXTI15_10, 56) +IRQ(on_rtc_alarm, RTC_ALARM, 57) +IRQ(on_dfsdm1_flt3, DFSDM1_FLT3, 58) +IRQ(on_tim8_brk, TIM8_BRK, 59) +IRQ(on_tim8_up, TIM8_UP, 60) +IRQ(on_tim8_trg_com, TIM8_TRG_COM, 61) +IRQ(on_tim8_cc, TIM8_CC, 62) +IRQ(on_adc3, ADC3, 63) +IRQ(on_fmc, FMC, 64) +IRQ(on_sdmmc1, SDMMC1, 65) +IRQ(on_tim5, TIM5, 66) +IRQ(on_spi3, SPI3, 67) +IRQ(on_uart4, UART4, 68) +IRQ(on_uart5, UART5, 69) +IRQ(on_tim6_dacunder, TIM6_DACUNDER, 70) +IRQ(on_tim7, TIM7, 71) +IRQ(on_dma2_channel1, DMA2_CHANNEL1_IRQ, 72) +IRQ(on_dma2_channel2, DMA2_CHANNEL2_IRQ, 73) +IRQ(on_dma2_channel3, DMA2_CHANNEL3_IRQ, 74) +IRQ(on_dma2_channel4, DMA2_CHANNEL4_IRQ, 75) +IRQ(on_dma2_channel5, DMA2_CHANNEL5_IRQ, 76) +IRQ(on_dfsdm1_flt0, DFSDM1_FLT0, 77) +IRQ(on_dfsdm1_flt1, DFSDM1_FLT1, 78) +IRQ(on_dfsdm1_flt2, DFSDM1_FLT2, 79) +IRQ(on_comp, COMP, 80) +IRQ(on_lptim1, LPTIM1, 81) +IRQ(on_lptim2, LPTIM2, 82) +IRQ(on_otg_fs, OTG_FS, 83) +IRQ(on_dma2_channel6, DMA2_CHANNEL6, 84) +IRQ(on_dma2_channel7, DMA2_CHANNEL7, 85) +IRQ(on_lpuart1, LPUART1, 86) +IRQ(on_quadspi, QUADSPI, 87) +IRQ(on_i2c3_ev, I2C3_EV, 88) +IRQ(on_i2c3_er, I2C3_ER, 89) +IRQ(on_sai1, SAI1, 90) +IRQ(on_sai2, SAI2, 91) +IRQ(on_swpmi1, SWPMI1, 92) +IRQ(on_tsc, TSC, 93) +IRQ(on_lcd, LCD, 94) +IRQ(on_aes, AES, 95) +IRQ(on_rng, RNG, 96) +IRQ(on_fpu, FPU, 97) +IRQ(on_hash, HASH, 98) +IRQ(on_i2c4_ev, I2C4_EV, 99) +IRQ(on_i2c4_er, I2C4_ER, 100) +IRQ(on_dcmi, DCMI, 101) +IRQ(on_can2_tx, CAN2_TX, 102) +IRQ(on_can2_rx0, CAN2_RX0, 103) +IRQ(on_can2_rx1, CAN2_RX1, 104) +IRQ(on_can2_sce, CAN2_SCE, 105) +IRQ(on_dma2d, DMA2D, 106) diff --git a/include/arch/stm32l4xxx/peripherals/nvic.h b/include/arch/stm32l4xxx/peripherals/nvic.h new file mode 100644 index 0000000..1645a2d --- /dev/null +++ b/include/arch/stm32l4xxx/peripherals/nvic.h @@ -0,0 +1,46 @@ +#ifndef NVIC_H_ +#define NVIC_H_ + +#include "arch.h" +#include "kern/common.h" + +typedef __IO struct { +#define nvic_intlinesnum (0x0F << 0) + uint32_t ict_r; /* Interrupt control type register. */ + + uint8_t reserved0[0xF8]; + + uint32_t ise_r[8]; + + uint8_t reserved1[0x60]; + + uint32_t ice_r[8]; + + uint8_t reserved2[0x60]; + + uint32_t isp_r[8]; + + uint8_t reserved3[0x60]; + + uint32_t icp_r[8]; + + uint8_t reserved4[0x60]; + + uint32_t iab_r[8]; + + uint8_t reserved5[0xE0]; + + uint32_t ip_r[60]; +} nvic_t; + +static_assert(offsetof(nvic_t, ise_r) == 0x00FC, "Offset check failed"); +static_assert(offsetof(nvic_t, ice_r) == 0x017C, "Offset check failed"); +static_assert(offsetof(nvic_t, isp_r) == 0x01FC, "Offset check failed"); +static_assert(offsetof(nvic_t, icp_r) == 0x027C, "Offset check failed"); +static_assert(offsetof(nvic_t, iab_r) == 0x02FC, "Offset check failed"); +static_assert(offsetof(nvic_t, ip_r) == 0x03FC, "Offset check failed"); + +#define NVIC (* (nvic_t*) NVIC_BASE) + + +#endif /* NVIC_H_ */ diff --git a/include/arch/stm32l4xxx/peripherals/rcc.h b/include/arch/stm32l4xxx/peripherals/rcc.h new file mode 100644 index 0000000..de7b568 --- /dev/null +++ b/include/arch/stm32l4xxx/peripherals/rcc.h @@ -0,0 +1,132 @@ +#ifndef H__RCC_ +#define H__RCC_ + +#include "arch.h" +#include "kern/common.h" +#include <stdint.h> + +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. */ + +#define rcc_lptim1rst (1 << 31) // Low Power Timer 1 reset +#define rcc_opamprst (1 << 30) // OPAMP interface reset +#define rcc_dac1rst (1 << 29) // DAC1 interface reset +#define rcc_pwrrst (1 << 28) // Power interface reset +#define rcc_can2rst (1 << 26) // CAN2 reset (this bit is reserved for STM32L47x/L48x devices) +#define rcc_can1rst (1 << 25) // CAN1 reset +#define rcc_crsrst (1 << 24) // CRS reset (this bit is reserved for STM32L47x/L48x devices) +#define rcc_i2c3rst (1 << 23) // I2C3 reset +#define rcc_i2c2rst (1 << 22) // I2C2 reset +#define rcc_i2c1rst (1 << 21) // I2C1 reset +#define rcc_uart5rst (1 << 20) // UART5 reset +#define rcc_uart4rst (1 << 19) // UART4 reset +#define rcc_usart3rst (1 << 18) // USART3 reset +#define rcc_usart2rst (1 << 17) // USART2 reset +#define rcc_reserved (1 << 16) // must be kept at reset value. +#define rcc_spi3rst (1 << 15) // SPI3 reset +#define rcc_spi2rst (1 << 14) // SPI2 reset +#define rcc_lcdrst (1 << 9) // interface reset (this bit is reserved for STM32L471/L4x5 devices) +#define rcc_tim7rst (1 << 5) // timer reset +#define rcc_tim6rst (1 << 4) // timer reset +#define rcc_tim5rst (1 << 3) // timer reset +#define rcc_tim4rst (1 << 2) // timer reset +#define rcc_tim3rst (1 << 1) // timer reset +#define rcc_tim2rst (1 << 0) // timer reset + __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. */ + +#define rcc_dma1en (1 << 0) /* DMA1 clock enable. */ +#define rcc_dma2en (1 << 1) /* DMA2 clock enable. */ +#define rcc_flashen (1 << 8) /* Flash memory interface clock enable. */ +#define rcc_crcen (1 << 12) /* CRC clock enable. */ +#define rcc_tscen (1 << 16) /* Touch sensing controller clock enable. */ +#define rcc_dmad2en (1 << 17) /* DMA2D clock enabled. */ + __IO uint32_t ahb1en_r; /* AHB1 Peripheral enable register. 0x48 */ + +#define rcc_gpioen(port) (1 << (port)) +#define rcc_otgfsen (1 << 12) +#define rcc_adcen (1 << 13) +#define rcc_dcmien (1 << 14) +#define rcc_assen (1 << 16) +#define rcc_hashen (1 << 17) +#define rcc_rngen (1 << 18) + __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/include/arch/stm32l4xxx/peripherals/spi.h b/include/arch/stm32l4xxx/peripherals/spi.h new file mode 100644 index 0000000..a39a0bb --- /dev/null +++ b/include/arch/stm32l4xxx/peripherals/spi.h @@ -0,0 +1,102 @@ +#ifndef CORE_SPI_H_ +#define CORE_SPI_H_ + +#include "kern/common.h" +#include "arch.h" + +#define SPI1 (*((spi_t*)(SPI1_BASE))) +#define SPI3 (*((spi_t*)(SPI3_BASE))) + +typedef enum { + SPI_BAUD_FPCLK_DIV_2 = 0, + SPI_BAUD_FPCLK_DIV_4 = 1, + SPI_BAUD_FPCLK_DIV_8 = 2, + SPI_BAUD_FPCLK_DIV_16 = 3, + SPI_BAUD_FPCLK_DIV_32 = 4, + SPI_BAUD_FPCLK_DIV_64 = 5, + SPI_BAUD_FPCLK_DIV_128 = 6, + SPI_BAUD_FPCLK_DIV_256 = 7, +} spi_baud_rate_t; + +typedef enum { + SPI_DATA_SIZE_NOT_USED_0 = 0, + SPI_DATA_SIZE_NOT_USED_1 = 1, + SPI_DATA_SIZE_NOT_USED_2 = 2, + SPI_DATA_SIZE_4_BITS = 3, + SPI_DATA_SIZE_5_BITS = 4, + SPI_DATA_SIZE_6_BITS = 5, + SPI_DATA_SIZE_7_BITS = 6, + SPI_DATA_SIZE_8_BITS = 7, + SPI_DATA_SIZE_9_BITS = 8, + SPI_DATA_SIZE_10_BITS = 9, + SPI_DATA_SIZE_11_BITS = 10, + SPI_DATA_SIZE_12_BITS = 11, + SPI_DATA_SIZE_13_BITS = 12, + SPI_DATA_SIZE_14_BITS = 13, + SPI_DATA_SIZE_15_BITS = 14, + SPI_DATA_SIZE_16_BITS = 15, +} spi_data_size_t; + +typedef __IO struct { + /* spi control register. */ +#define spi_bidimode (1 << 15) /* Bidirectional data mode enable. */ +#define spi_bidioe (1 << 14) /* Output enable in bidirectional mode */ +#define spi_crcen (1 << 13) /* Hardware CRC calculation enable */ +#define spi_crcnext (1 << 12) /* Transmit CRC next */ +#define spi_crcl (1 << 11) /* CRC length */ +#define spi_rxonly (1 << 10) /* Receive only mode enabled. */ +#define spi_ssm (1 << 9) /* Software slave management */ +#define spi_ssi (1 << 8) /* Internal slave select */ +#define spi_lsbfirst (1 << 7) /* Frame format */ +#define spi_spe (1 << 6) /* SPI enable */ +#define spi_br (7 << 3) /* SPI enable */ +#define spi_mstr (1 << 2) /* Master selection */ +#define spi_cpol (1 << 1) /* Clock polarity */ +#define spi_cpha (1 << 0) /* Clock phase */ + uint32_t c_r1; + + /* spi control register #2 */ +#define spi_ldma_tx (1 << 14) /* Last DMA transfer for transmission */ +#define spi_ldma_rx (1 << 13) /* Last DMA transfer for reception */ +#define spi_frxth (1 << 12) /* FIFO reception threshold */ +#define spi_ds (0xF << 8) /* Data size */ +#define spi_txeie (1 << 7) /* Tx buffer empty interrupt enable */ +#define spi_rxneie (1 << 6) /* RX buffer not empty interrupt enable */ +#define spi_errie (1 << 5) /* Error interrupt enable */ +#define spi_frf (1 << 4) /* Frame format */ +#define spi_nssp (1 << 3) /*: NSS pulse management */ +#define spi_ssoe (1 << 2) /* SS output enable */ +#define spi_txdmaen (1 << 1) /* Tx buffer DMA enable */ +#define spi_rxdmaen (1 << 0) /* Rx buffer DMA enable */ + uint32_t c_r2; + + /* spi status register. */ +#define spi_ftlvl (3 << 11) /* Transmisison level */ +#define spi_frlvl (3 << 9) /* Reception level */ +#define spi_fre (1 << 8) /* Frame format error */ +#define spi_bsy (1 << 7) /* Busy flag */ +#define spi_ovr (1 << 6) /* Overrun flag */ +#define spi_modf (1 << 5) /* Mode fault */ +#define spi_crcerr (1 << 4) /* CRC error flag */ +#define spi_txe (1 << 1) /* Transmit buffer empty */ +#define spi_rxne (1 << 0) /* Receive buffer not empty */ + uint32_t s_r; + + /* spi data register. Really only the least-significant 16 bits are used. + * reading from this register reads from the Rx FIFO while writing to it + * writes to the Tx FIFO. */ + __IO uint32_t d_r; + + /* spi CRC polynomial register. */ + uint32_t crcp_r; + + /* spi rx CRC register. */ + uint32_t rxcrc_r; + + /* spi tx CRC register. */ + uint32_t txcrc_r; +} spi_t; + +static_assert(offsetof(spi_t, txcrc_r) == 0x18, "Offset check failed."); + +#endif /* CORE_SPI_H_ */ diff --git a/include/arch/stm32l4xxx/peripherals/system.h b/include/arch/stm32l4xxx/peripherals/system.h new file mode 100644 index 0000000..b6ff0a6 --- /dev/null +++ b/include/arch/stm32l4xxx/peripherals/system.h @@ -0,0 +1,76 @@ +#ifndef CORE_SYSTEM_H_ +#define CORE_SYSTEM_H_ + +#include <stdint.h> +#include "kern/common.h" + +typedef __IO struct { + uint32_t actl_r; /* Auxiliary Control Register, ACTLR on page 4-5 */ + + uint32_t reserved0; + +#define scb_enable (1 << 0) +#define scb_tickint (1 << 1) +#define scb_clksource (1 << 2) +#define scb_countflag (1 << 16) + uint32_t stcs_r; /* SysTick Control and Status Register */ + + 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/include/arch/stm32l4xxx/peripherals/tables/stm32l432xx/gpio/afn_table.inc b/include/arch/stm32l4xxx/peripherals/tables/stm32l432xx/gpio/afn_table.inc new file mode 100644 index 0000000..66d347c --- /dev/null +++ b/include/arch/stm32l4xxx/peripherals/tables/stm32l432xx/gpio/afn_table.inc @@ -0,0 +1,100 @@ +AFN(CAN1_RX, 9, PA11) +AFN(CAN1_TX, 9, PA12) +AFN(COMP1_OUT, 12, PA0, 12, PB0, 6, PA11, 6, PA6) +AFN(COMP2_OUT, 12, PA2, 12, PA7, 12, PB5) +AFN(I2C1_SCL, 4, PA9, 4, PB6) +AFN(I2C1_SDA, 4, PA10, 4, PB7) +AFN(I2C1_SMBA, 4, PA14, 4, PA1, 4, PB5) +AFN(I2C3_SCL, 4, PA7) +AFN(I2C3_SDA, 4, PB4) +AFN(IR_OUT, 1, PA13) +AFN(JTCK_SWCLK, 0, PA14) +AFN(JTDI, 0, PA15) +AFN(JTDO_TRACESWO, 0, PB3) +AFN(JTMS_SWDIO, 0, PA13) +AFN(LPTIM1_ETR, 1, PB6) +AFN(LPTIM1_IN1, 1, PB5) +AFN(LPTIM1_IN2, 1, PB7) +AFN(LPTIM1_OUT, 1, PA14) +AFN(LPTIM2_ETR, 14, PA5) +AFN(LPTIM2_IN1, 14, PB1) +AFN(LPTIM2_OUT, 14, PA4, 14, PA8) +AFN(LPUART1_CTS, 8, PA6) +AFN(LPUART1_RTS_DE, 8, PB1) +AFN(LPUART1_RX, 8, PA3) +AFN(LPUART1_TX, 8, PA2) +AFN(MCO, 0, PA8) +AFN(NJTRST, 0, PB4) +AFN(QUADSPI_BK1_IO0, 10, PB1) +AFN(QUADSPI_BK1_IO1, 10, PB0) +AFN(QUADSPI_BK1_IO2, 10, PA7) +AFN(QUADSPI_BK1_IO3, 10, PA6) +AFN(QUADSPI_BK1_NCS, 10, PA2) +AFN(QUADSPI_CLK, 10, PA3) +AFN(SAI1_EXTCLK, 13, PA0, 13, PB0) +AFN(SAI1_FS_A, 13, PA9) +AFN(SAI1_FS_B, 13, PA14, 13, PA4, 13, PB6) +AFN(SAI1_MCLK_A, 13, PA3) +AFN(SAI1_MCLK_B, 13, PB4) +AFN(SAI1_SCK_A, 13, PA8) +AFN(SAI1_SCK_B, 13, PB3) +AFN(SAI1_SD_A, 13, PA10) +AFN(SAI1_SD_B, 13, PA13, 13, PB5) +AFN(SPI1_MISO, 5, PA11, 5, PA6, 5, PB4) +AFN(SPI1_MOSI, 5, PA12, 5, PA7, 5, PB5) +AFN(SPI1_NSS, 5, PA15, 5, PA4, 5, PB0) +AFN(SPI1_SCK, 5, PA1, 5, PA5, 5, PB3) +AFN(SPI3_MISO, 6, PB4) +AFN(SPI3_MOSI, 6, PB5) +AFN(SPI3_NSS, 6, PA15, 6, PA4) +AFN(SPI3_SCK, 6, PB3) +AFN(SWPMI1_IO, 12, PA8) +AFN(SWPMI1_RX, 12, PA14) +AFN(SWPMI1_SUSPEND, 12, PA15) +AFN(SWPMI1_TX, 12, PA13) +AFN(TIM15_BKIN, 14, PA9) +AFN(TIM15_CH1, 14, PA2) +AFN(TIM15_CH1N, 14, PA1) +AFN(TIM15_CH2, 14, PA3) +AFN(TIM16_BKIN, 14, PB5) +AFN(TIM16_CH1, 14, PA6) +AFN(TIM16_CH1N, 14, PB6) +AFN(TIM1_BKIN, 1, PA6) +AFN(TIM1_BKIN2, 2, PA11) +AFN(TIM1_BKIN2_COMP1, 12, PA11) +AFN(TIM1_BKIN_COMP2, 12, PA6) +AFN(TIM1_CH1, 1, PA8) +AFN(TIM1_CH1N, 1, PA7) +AFN(TIM1_CH2, 1, PA9) +AFN(TIM1_CH2N, 1, PB0) +AFN(TIM1_CH3, 1, PA10) +AFN(TIM1_CH3N, 1, PB1) +AFN(TIM1_CH4, 1, PA11) +AFN(TIM1_ETR, 1, PA12) +AFN(TIM2_CH1, 1, PA0, 1, PA15, 1, PA5) +AFN(TIM2_CH2, 1, PA1, 1, PB3) +AFN(TIM2_CH3, 1, PA2) +AFN(TIM2_CH4, 1, PA3) +AFN(TIM2_ETR, 14, PA0, 2, PA15, 2, PA5) +AFN(TSC_G2_IO1, 9, PB4) +AFN(TSC_G2_IO2, 9, PB5) +AFN(TSC_G2_IO3, 9, PB6) +AFN(TSC_G2_IO4, 9, PB7) +AFN(TSC_G3_IO1, 9, PA15) +AFN(USART1_CK, 7, PA8, 7, PB5) +AFN(USART1_CTS, 7, PA11, 7, PB4) +AFN(USART1_RTS_DE, 7, PA12, 7, PB3) +AFN(USART1_RX, 7, PA10, 7, PB7) +AFN(USART1_TX, 7, PA9, 7, PB6) +AFN(USART2_CK, 7, PA4) +AFN(USART2_CTS, 7, PA0) +AFN(USART2_RTS_DE, 7, PA1) +AFN(USART2_RX, 3, PA15, 7, PA3) +AFN(USART2_TX, 7, PA2) +AFN(USART3_CK, 7, PB0) +AFN(USART3_CTS, 7, PA6) +AFN(USART3_RTS_DE, 7, PA15, 7, PB1) +AFN(USB_CRS_SYNC, 10, PA10) +AFN(USB_DM, 10, PA11) +AFN(USB_DP, 10, PA12) +AFN(USB_NOE, 10, PA13) diff --git a/include/arch/stm32l4xxx/peripherals/tables/stm32l432xx/gpio/port_table.inc b/include/arch/stm32l4xxx/peripherals/tables/stm32l432xx/gpio/port_table.inc new file mode 100644 index 0000000..21c7234 --- /dev/null +++ b/include/arch/stm32l4xxx/peripherals/tables/stm32l432xx/gpio/port_table.inc @@ -0,0 +1,26 @@ +PORT(A, 0) +PORT(A, 1) +PORT(A, 2) +PORT(A, 3) +PORT(A, 4) +PORT(A, 5) +PORT(A, 6) +PORT(A, 7) +PORT(A, 8) +PORT(A, 9) +PORT(A, 10) +PORT(A, 11) +PORT(A, 12) +PORT(A, 13) +PORT(A, 14) +PORT(A, 15) +PORT(B, 0) +PORT(B, 1) +PORT(B, 3) +PORT(B, 4) +PORT(B, 5) +PORT(B, 6) +PORT(B, 7) +PORT(C, 14) +PORT(C, 15) +PORT(H, 3) diff --git a/include/arch/stm32l4xxx/peripherals/usart.h b/include/arch/stm32l4xxx/peripherals/usart.h new file mode 100644 index 0000000..a1542f4 --- /dev/null +++ b/include/arch/stm32l4xxx/peripherals/usart.h @@ -0,0 +1,204 @@ +#ifndef H__USART_ +#define H__USART_ + +#include <arch.h> +#include <stdint.h> +#include <stdarg.h> + +#include "kern/common.h" +#include "arch/stm32l4xxx/peripherals/rcc.h" +#include <assert.h> + +#define USART1 (* (usart_t*) USART1_BASE) +#define USART2 (* (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. */ +#define usart_ue (1 << 0) /* UART enable */ +#define usart_uesm (1 << 1) /* UART enabled in stop mode. */ +#define usart_re (1 << 2) /* reciever enabled. */ +#define usart_te (1 << 3) /* transmitter enabled. */ +#define usart_idleie (1 << 4) /* Idle interrupt enabled. */ +#define usart_rxneie (1 << 5) /* RXNEIE RXNE interrupt enable. */ +#define usart_tcie (1 << 6) +#define usart_txeie (1 << 7) +#define usart_peie (1 << 8) +#define usart_ps (1 << 9) +#define usart_pce (1 << 10) +#define usart_wake (1 << 11) +#define usart_m0 (1 << 12) +#define usart_mme (1 << 13) +#define usart_cmie (1 << 14) +#define usart_over8 (1 << 15) +#define usart_dedt (0xF << 16) +#define usart_deat (0xF << 21) +#define usart_rtoie (1 << 26) +#define usart_eobie (1 << 27) +#define usart_m1 (1 << 28) + __IO uint32_t c_r1; + __IO uint32_t c_r2; + + +#define usart_eie (1 << 0) // Error interrupt enable. +#define usart_iren (1 << 1) // IrDA mode enabled +#define usart_irlp (1 << 2) // IrDA low power +#define usart_hdsel (1 << 3) // Half duplex selection +#define usart_nack (1 << 4) // Smartcard NACK enable +#define usart_scen (1 << 5) // Smartocard mode enable +#define usart_dmar (1 << 6) // DMA enable reciever +#define usart_dmat (1 << 7) // DMA enable transmitter +#define usart_rtse (1 << 8) // RTS enable +#define usart_ctse (1 << 9) // CTS enable +#define usart_ctsie (1 << 10) // CTS interrupt enable +#define usart_onebit (1 << 11) // One sample bit method enable +#define usart_ovrdis (1 << 12) // Overrun disable +#define usart_ddre (1 << 13) // DMA Disable on reception error +#define usart_dem (1 << 14) // Driver enable mode +#define usart_dep (1 << 15) // Driver enable polarity selection +#define usart_scarcnt0 (1 << 17) +#define usart_scarcnt1 (1 << 18) +#define usart_scarcnt2 (1 << 19) +#define usart_wus0 (1 << 20) // Wakeup from STOP mode interrept flag selection +#define usart_wus1 (1 << 21) // Wakeup from STOP mode interrept flag selection +#define usart_wufie (1 << 22) // Wakeup from STOP mode interrup enable +#define usart_ucesm (1 << 23) // USART clock enable in STOP mode. +#define usart_tcbgtie (1 << 24) // Transmission complete before guard time interrupt + __IO uint32_t c_r3; + + /* 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*/ +#define usart_pe (1 << 0) // Parity error +#define usart_fe (1 << 1) // Framing error +#define usart_nf (1 << 2) // START bit noise detection flag. +#define usart_ore (1 << 3) // Overrun error +#define usart_dlie (1 << 4) // Idle line detected +#define usart_rxne (1 << 5) // Read data register not empty +#define usart_tc (1 << 6) // Transmission complete +#define usart_txe (1 << 7) // Transmit data register empty +#define usart_lbdf (1 << 8) // LIN break detection flag +#define usart_ctsif (1 << 9) // CTS interrupt flag +#define usart_cts (1 << 10) // CTS flag. +#define usart_rtof (1 << 11) // Receiever timeout +#define usart_eobf (1 << 12) // End of block flag +#define usart_abre (1 << 14) // Auto baud rate error +#define usart_abrf (1 << 15) // Auto baud rate flag +#define usart_busy (1 << 16) // Busy flag +#define usart_cmf (1 << 17) // Character match flag +#define usart_sbkf (1 << 18) // send break flag +#define usart_rwu (1 << 19) // receiver wakeup frlom mute mode. +#define usart_wuf (1 << 20) // Wakeup from stop mode flag +#define usart_teack (1 << 21) // Transmit enable acknowledge flag. +#define usart_reack (1 << 22) // Receieve enable acknowledge flag. +#define usart_tcbgt (1 << 25) // Transmission completer before guard time completion. + __IO uint32_t is_r; /* Interrupt service register. */ + +#define usart_pecf (1 << 0) // Parity error clear flag +#define usart_fecf (1 << 1) // Framing error clear flag +#define usart_ncf (1 << 2) // Noise detected clear flag +#define usart_orecf (1 << 3) // Overrun error clear flag +#define usart_idlecf (1 << 4) // Idle line detected clear flag +#define usart_tccf (1 << 6) // Transmission complete clear flag +#define usart_tcbgtcf (1 << 7) // Transmission completed before guard time clear flag +#define usart_lbdcf (1 << 8) // LIN break detection clear flag +#define usart_ctscf (1 << 9) // CTS clear flag +#define usart_rtocf (1 << 11) // Receiver timeout clear flag +#define usart_eobcf (1 << 12) // End of block clear flag +#define usart_cmcf (1 << 17) // Character match clear flag +#define usart_wucf (1 << 20) // Wakeup from Stop mode clear flag. + __IO uint32_t ic_r; + 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, ...); + +void usart_vprintf(__IO usart_t* usart, const char* fmt, va_list l); + + +#endif /* H__USART_ */ diff --git a/include/arch/x86_64/arch.h b/include/arch/x86_64/arch.h new file mode 100644 index 0000000..c17721d --- /dev/null +++ b/include/arch/x86_64/arch.h @@ -0,0 +1,37 @@ +#ifndef ARCH_H_ +#define ARCH_H_ + +#include "fake_env.h" + +#define ARCH_PC +#define enable_all_interrupts() do {} while(0) + +#define RCC_BASE (load_fake_rcc__()) + +#define DMA1_BASE (load_fake_ahb1__() + 0x0) +#define DMA2_BASE (load_fake_ahb1__() + 0x400) + +#define USART1_BASE (load_fake_apb2__() + 0x3800) +#define USART2_BASE (load_fake_apb1__() + 0x4400) + +#define GPIOA_BASE (load_fake_ahb2__() + 0x0) +#define GPIOB_BASE (load_fake_ahb2__() + 0x400) +#define GPIOC_BASE (load_fake_ahb2__() + 0x800) +#define GPIOH_BASE (load_fake_ahb2__() + 0x1C00) + +#define SRAM1_BASE (load_fake_sram1__() + 0x0) +#define SRAM2_BASE (load_fake_sram2__() + 0x0) + +#define SYSTEM_CONFIG_BLOCK_BASE (load_fake_scb__()) +#define NVIC_BASE (load_fake_nvic__()) + +#define SPI1_BASE (load_fake_spi1__()) +#define SPI3_BASE (load_fake_spi3__()) + +// Pretend there's a data segement at the start of SRAM1 for more accurate +// testing. +#define GHOST_DATA_SEGMENT_SIZE 1234 +#define DATA_SEGMENT_START (*((uint8_t*)SRAM1_BASE)) +#define DATA_SEGMENT_STOP (*(((uint8_t*)SRAM1_BASE) + GHOST_DATA_SEGMENT_SIZE)) + +#endif /* ARCH_H_ */ diff --git a/include/kern/common.h b/include/kern/common.h new file mode 100644 index 0000000..653279e --- /dev/null +++ b/include/kern/common.h @@ -0,0 +1,50 @@ +#ifndef COMMON__H +#define COMMON__H + +#include <stdint.h> +#include <stddef.h> +#include <assert.h> + +#define WEAK __attribute__((weak)) +#define NORETURN __attribute__((noreturn)) + +#ifndef static_assert +#define static_assert(a, b) +#endif + +/* Define __IO to be volatile if it's not already. */ +#ifndef __IO +#define __IO volatile +#endif + +#define CTZ(n) __builtin_ctz(n) + +#define bool int +#ifndef __cplusplus +#define true 1 +#define false 0 +#endif + +#define PACKED __attribute__((packed)) +#define BIT(n) (1 << (n)) + +#define RESERVED_CONCAT_IMPL(x, y) x ## y +#define RESERVED_MACRO_CONCAT(x, y) RESERVED_CONCAT_IMPL(x, y) +#define RESERVED(n) \ + bits_t RESERVED_MACRO_CONCAT(_r, __COUNTER__) :n + +#define RESERVE(type) \ + __IO type RESERVED_MACRO_CONCAT(_r, __COUNTER__) + +#define ptr2reg(ptr) \ + ((uint32_t) (ptrdiff_t) (ptr)) + +typedef __IO uint32_t bits_t; + +#define regset(reg, mask, val) \ + ((reg) = ((reg) & ~mask) | (val << CTZ(mask))) + +#define regget(reg, mask) \ + (((reg) & mask) >> (CTZ(mask))) + +#endif /* COMMON_H */ diff --git a/include/kern/delay.h b/include/kern/delay.h new file mode 100644 index 0000000..65a26d6 --- /dev/null +++ b/include/kern/delay.h @@ -0,0 +1,12 @@ +#ifndef H__DELAY__ +#define H__DELAY__ + +#include <stdint.h> + +/* + * Loops and count-downs the delay, the time this takes depends on the speed + * of the clock. + */ +void delay(uint32_t delay); + +#endif /* H__DELAY__ */ diff --git a/include/kern/dma/dma_manager.h b/include/kern/dma/dma_manager.h new file mode 100644 index 0000000..0d17bd5 --- /dev/null +++ b/include/kern/dma/dma_manager.h @@ -0,0 +1,279 @@ +#ifndef PERI_DMA_H_ +#define PERI_DMA_H_ + +#include "kern/common.h" +#include "arch/stm32l4xxx/peripherals/dma.h" /* Access to the DMA registers. */ +#include "arch/stm32l4xxx/peripherals/irq.h" + +#define DMA_ERROR_CHANNEL_IN_USE 1 + +#define CAT2(x, y) x ## y +#define CAT1(v, c) CAT2(v, c) +#define DMA_RESERVED(dma) CAT1(dma ## _PERIPH_RESERVED, __COUNTER__) + +#define ALTERNATE0 0x0000 +#define ALTERNATE1 0x0100 +#define ALTERNATE2 0x0200 +#define ALTERNATE3 0x0300 + +#define DMA_N_CHANNELS 7 +typedef enum { + DMA1_PERIPH_ADC1 = 0, + DMA1_PERIPH_ADC2 = 1, + DMA1_PERIPH_ADC3 = 2, + DMA1_PERIPH_DFSDM1_FLT0 = 3, + DMA1_PERIPH_DFSDM1_FLT1 = 4, + DMA1_PERIPH_DFSDM1_FLT2 = 5, + DMA1_PERIPH_DFSDM1_FLT3 = 6, + + DMA_RESERVED(DMA1) = 7, + DMA1_PERIPH_SPI1_RX = 8, + DMA1_PERIPH_SPI1_TX = 9, + DMA1_PERIPH_SPI2_RX = 10, + DMA1_PERIPH_SPI2_TX = 11, + DMA1_PERIPH_SAI2_A = 12, + DMA1_PERIPH_SAI2_B = 13, + + DMA_RESERVED(DMA1) = 14, + DMA1_PERIPH_USART3_TX = 15, + DMA1_PERIPH_USART3_RX = 16, + DMA1_PERIPH_USART1_TX = 17, + DMA1_PERIPH_USART1_RX = 18, + DMA1_PERIPH_USART2_RX = 19, + DMA1_PERIPH_USART2_TX = 20, + + DMA_RESERVED(DMA1) = 21, + DMA1_PERIPH_I2C3_TX = 22, + DMA1_PERIPH_I2C3_RX = 23, + DMA1_PERIPH_I2C2_TX = 24, + DMA1_PERIPH_I2C2_RX = 25, + DMA1_PERIPH_I2C1_TX = 26, + DMA1_PERIPH_I2C1_RX = 27, + + DMA1_PERIPH_TIM2_CH3 = 28, + DMA1_PERIPH_TIM2_UP = 29, + DMA1_PERIPH_TIM16_CH1_1 = 30 | ALTERNATE0, + DMA1_PERIPH_TIM16_UP_1 = 30 | ALTERNATE1, /* Same as TIM16_CH1. */ + DMA_RESERVED(DMA1) = 31, + DMA1_PERIPH_TIM2_CH1 = 32, + DMA1_PERIPH_TIM16_CH1_2 = 33, + DMA1_PERIPH_TIM16_UP_2 = 33 | ALTERNATE1, /* Same as TIM16_CH1. */ + DMA1_PERIPH_TIM2_CH2 = 34, + DMA1_PERIPH_TIM2_CH4 = 34 | ALTERNATE1, /* Same as TIM2_CH2. */ + + + DMA1_PERIPH_TIM17_CH1_1 = 35, + DMA1_PERIPH_TIM17_UP_1 = 35 | ALTERNATE1, /* Same as TIM17_CH1 */ + DMA1_PERIPH_TIM3_CH3 = 36, + DMA1_PERIPH_TIM3_CH4 = 37, + DMA1_PERIPH_TIM3_UP = 37 | ALTERNATE1, /* Same as TIM3_CH4 */ + DMA1_PERIPH_TIM7_UP = 38, + DMA1_PERIPH_DAC_CH2 = 38 | ALTERNATE1, /* Same as TIM7_UP */ + DMA1_PERIPH_QUADSPI = 39, + DMA1_PERIPH_TIM3_CH1 = 40, + DMA1_PERIPH_TIM3_TRIG = 40 | ALTERNATE1, /* Same as TIM3_CH1 */ + DMA1_PERIPH_TIM17_CH1_2 = 41, + DMA1_PERIPH_TIM17_UP_2 = 41 | ALTERNATE1, /* Same as TIM17_CH1 */ + + DMA1_PERIPH_TIM4_CH1 = 42, + DMA_RESERVED(DMA1) = 43, + DMA1_PERIPH_TIM6_UP = 44, + DMA1_PERIPH_DAC_CH1 = 44 | ALTERNATE1, /* Same as TIM6_UP */ + DMA1_PERIPH_TIM4_CH2 = 45, + DMA1_PERIPH_TIM4_CH3 = 46, + DMA_RESERVED(DMA1) = 47, + DMA1_PERIPH_TIM4_UP = 48, + + DMA_DMA1_PERIHP_RESERVED5 = 49, + DMA1_PERIPH_TIM1_CH1 = 50, + DMA1_PERIPH_TIM1_CH2 = 51, + DMA1_PERIPH_TIM1_CH4 = 52, + DMA1_PERIPH_TIM1_TRIG = 52 | ALTERNATE1, /* Same as TIM1_TRIG */ + DMA1_PERIPH_TIM1_COM = 52 | ALTERNATE2, /* Same as TIM1_TRIG */ + DMA1_PERIPH_TIM15_CH1 = 53, + DMA1_PERIPH_TIM15_UP = 53 | ALTERNATE1, /* Same as TIM15_CH1 */ + DMA1_PERIPH_TIM15_TRIG = 53 | ALTERNATE2, /* Same as TIM15_CH1 */ + DMA1_PERIPH_TIM15_COM = 53 | ALTERNATE3, /* Same as TIM15_CH1 */ + DMA1_PERIPH_TIM1_UP = 54, + DMA1_PERIPH_TIM1_CH3 = 55, + + DMA2_DMA1_SWITCH__ = 56, + + DMA2_PERIPH_I2C4_RX = 56, + DMA2_PERIPH_I2C4_TX = 57, + DMA2_PERIPH_ADC1 = 58, + DMA2_PERIPH_ADC2 = 59, + DMA2_PERIPH_ADC3 = 60, + DMA2_PERIPH_DCMI_1 = 61, + DMA_RESERVED(DMA2) = 62, + + DMA2_PERIPH_SAI1_A_1 = 63, + DMA2_PERIPH_SAI1_B_1 = 64, + DMA2_PERIPH_SAI2_A = 65, + DMA2_PERIPH_SAI2_B = 66, + DMA_RESERVED(DMA2) = 67, + DMA2_PERIPH_SAI1_A_2 = 68, + DMA2_PERIPH_SAI1_B_2 = 69, + + DMA2_PERIPH_UART5_TX = 70, + DMA2_PERIPH_UART5_RX = 71, + DMA2_PERIPH_UART4_TX = 72, + DMA_RESERVED(DMA2) = 73, + DMA2_PERIPH_UART4_RX = 74, + DMA2_PERIPH_USART1_TX = 75, + DMA2_PERIPH_USART1_RX = 76, + + DMA2_PERIPH_SPI3_RX = 77, + DMA2_PERIPH_SPI3_TX = 78, + DMA_RESERVED(DMA2) = 79, + DMA2_PERIPH_TIM6_UP = 80, + DMA2_PERIPH_DAC_CH1 = 80 | ALTERNATE1, /* Same as TIM6_UP */ + DMA2_PERIPH_TIM7_UP = 81, + DMA2_PERIPH_DAC_CH2 = 81 | ALTERNATE1, /* Same as TIM7_UP */ + DMA_RESERVED(DMA2) = 82, + DMA2_PERIPH_QUADSPI = 83, + + DMA2_PERIPH_SWPMI1_RX = 84, + DMA2_PERIPH_SWPMI1_TX = 85, + DMA2_PERIPH_SPI1_RX = 86, + DMA2_PERIPH_SPI1_TX = 87, + DMA2_PERIPH_DCMI_2 = 88, + DMA2_PERIPH_LPUART1_TX = 89, + DMA2_PERIPH_LPUART1_RX = 90, + + + DMA2_PERIPH_TIM5_CH4 = 91, + DMA2_PERIPH_TIM5_TRIG = 91 | ALTERNATE1, /* Same as TIM5_CH4 */ + DMA2_PERIPH_TIM5_CH3 = 92, + DMA2_PERIPH_TIM5_UP = 92 | ALTERNATE1, /* Same as TIM5_CH3 */ + DMA_RESERVED(DMA2) = 93, + DMA2_PERIPH_TIM5_CH2 = 94, + DMA2_PERIPH_TIM5_CH1 = 95, + DMA2_PERIPH_I2C1_RX = 96, + DMA2_PERIPH_I2C1_TX = 97, + + DMA2_PERIPH_AES_IN_1 = 98, + DMA2_PERIPH_AES_OUT_1 = 99, + DMA2_PERIPH_AES_OUT_2 = 100, + DMA_RESERVED(DMA2) = 101, + DMA2_PERIPH_AES_IN_2 = 102, + DMA_RESERVED(DMA2) = 103, + DMA2_PERIPH_HASH_IN = 104, + + DMA2_PERIPH_TIM8_CH3 = 105, + DMA2_PERIPH_TIM8_UP = 105 | ALTERNATE1, /* Same as TIM8_CH3 */ + DMA2_PERIPH_TIM8_CH4 = 106, + DMA2_PERIPH_TIM8_TRIG = 106 | ALTERNATE1, /* Same as TIM8_CH4 */ + DMA2_PERIPH_TIM8_COM = 106 | ALTERNATE2, /* Same as TIM8_CH4 */ + DMA_RESERVED(DMA2) = 107, + DMA2_PERIPH_SDMMC1_1 = 108, + DMA2_PERIPH_SDMMC1_2 = 109, + DMA2_PERIPH_TIM8_CH1 = 110, + DMA2_PERIPH_TIM8_CH2 = 111, + + + DMA_PERIPH_SENTINEL, +} dma_peripheral_t; + + +/* Defines a DMA channel. */ +typedef struct { + uint8_t dma; /* 0 = DMA1, 1 = DMA2 */ + uint8_t chan; /* 0 - 6 */ +} dma_channel_t; + + +/* + * Defines a DMA channel allocated for memory-to-peripheral transfers. This + * structure is only nominally different from dma_channel_t in order to provide + * rudimentary type-checking. + */ +typedef struct { + dma_channel_t c_; +} dma_mem2p_channel_t; + +/* + * Defines a DMA channel allocated for peripheral-to-memory transfers. This + * structure is only nominally different from dma_channel_t in order to provide + * rudimentary type-checking. + */ +typedef struct { + dma_channel_t c_; +} dma_p2mem_channel_t; + +/* Defines a DMA channel allocated for mem2mem transfers. + * This structure is only nominally different from dma_channel_t + * in order to provide rudimentary type-checking. + */ +typedef struct { + dma_channel_t c_; +} dma_mem2mem_channel_t; + +#define DMA_CHAN_ERROR ((dma_channel_t) { .dma = 0xff, .chan = 0xff }) + +typedef struct { + bool transfer_complete_interrupt_enable; + bool half_transfer_interrupt_enable; + bool transfer_error_interrupt_enable; + + bool circular_mode; + bool peripheral_increment; + bool memory_increment; + + dma_size_t peripheral_block_size; + dma_size_t memory_block_size; + + dma_priority_level_t priority; +} dma_opts_t; + +#define DEFAULT_DMA_OPTS \ + ((dma_opts_t) { .memory_increment = 1, \ + .peripheral_increment = 0, \ + .transfer_complete_interrupt_enable = 0, \ + .half_transfer_interrupt_enable = 0, \ + .transfer_error_interrupt_enable = 0, \ + .circular_mode = 0, \ + .peripheral_block_size = DMA_SIZE_8_BITS, \ + .memory_block_size = DMA_SIZE_8_BITS, \ + .priority = DMA_PRIORITY_LEVEL_MEDIUM }) + +dma_p2mem_channel_t select_dma_channel_p2mem( + dma_peripheral_t peripheral, + dma_opts_t* opts_in, + int* error); + +dma_mem2p_channel_t select_dma_channel_mem2p( + dma_peripheral_t peripheral, + dma_opts_t* opts_in, + int* error); + +/* Returns a dma channel used for memory-to-memory transfers. + * + * channel - the channel this dma should use. The channel should + * be on the range [0-13]. The channels [0-6] refer to the 7 channels + * on DMA1, where channels [7-13] refer to the 7 channels on DMA2. + * + * If `channel` is -1, then the highest unused dma channel is selected. + */ +dma_mem2mem_channel_t select_dma_channel_mem2mem( + int channel, + dma_opts_t* opts, + int* error_out); + +void dma_mem2p_initiate_transfer( + dma_mem2p_channel_t chan, const void* from_loc, uint16_t nblocks); + +void dma_p2mem_initiate_transfer( + dma_p2mem_channel_t chan, void* to_loc, uint16_t nblocks); + +void dma_mem2mem_initiate_transfer( + dma_mem2mem_channel_t chan, + void* to_loc, + const void* from_loc, + uint16_t nblocks); + +void release_dma_channel(dma_channel_t chan); + +interrupt_t dma_channel_get_interrupt(dma_channel_t chan); + +#endif diff --git a/include/kern/gpio/gpio_manager.h b/include/kern/gpio/gpio_manager.h new file mode 100644 index 0000000..922a423 --- /dev/null +++ b/include/kern/gpio/gpio_manager.h @@ -0,0 +1,187 @@ +#ifndef KERN_GPIO_GPIO_MANAGE_H_ +#define KERN_GPIO_GPIO_MANAGE_H_ + +#include "kern/common.h" +#include "arch/stm32l4xxx/peripherals/gpio.h" + +#define GPIO_ERROR_IN_USE 1 +#define GPIO_ERROR_INVALID_PIN_FOR_ALTERNATE_FUNCTION 2 +#define GPIO_ERROR_INVALID_PIN 3 + +typedef enum { +/* Creates vaules GPIO_PIN_<port><num> i.e. GPIO_PIN_A0 */ +#define PORT(p, pn) \ + GPIO_PIN_P ## p ## pn, +#include "arch/stm32l4xxx/peripherals/tables/stm32l432xx/gpio/port_table.inc" +#undef PORT + + N_GPIO_PINS +} gpio_pin_t; + +/* Alternate functions. */ +typedef enum { +#define AFN(fn, ...) \ + GPIO_ALTERNATE_FUNCTION_ ## fn, +#include "arch/stm32l4xxx/peripherals/tables/stm32l432xx/gpio/afn_table.inc" +#undef AFN + GPIO_ALTERNATE_FUNCTION_EVENTOUT, +} gpio_alternate_function_t; + +#define gpio_pin_for_alternate_function(af) ((af) / 16) +#define gpio_pin_out_of_range(pin) \ + ((pin) < 0 || (pin) >= N_GPIO_PINS) + +typedef enum { + GPIO_PORT_A, + GPIO_PORT_B, + GPIO_PORT_C, + GPIO_PORT_D, + GPIO_PORT_E, + GPIO_PORT_F, + GPIO_PORT_G, + GPIO_PORT_H, + GPIO_PORT_I, + + N_GPIO_PORTS, +} gpio_port_t; + +typedef enum { + GPIO_MODE_INPUT, + GPIO_MODE_OUTPUT, + GPIO_MODE_ALTERNATE, + GPIO_MODE_ANALOG +} gpio_mode_t; + +/* + * Enum defining the pin speeds that are possible. + */ +typedef enum { + SPEED_2MHZ = 0, + SPEED_10MHZ = 1, + SPEED_50MHZ = 3, +} gpio_speed_t; + +typedef enum { + GPIO_OUTPUT_TYPE_PUSH_PULL, + GPIO_OUTPUT_TYPE_OPEN_DRAIN +} gpio_output_type_t; + +typedef enum { + GPIO_OUTPUT_SPEED_LOW, + GPIO_OUTPUT_SPEED_MEDIUM, + GPIO_OUTPUT_SPEED_HIGH, + GPIO_OUTPUT_SPEED_VERY_HIGH, +} gpio_output_speed_t; + +typedef enum { + GPIO_PULL_DIR_NONE, + GPIO_PULL_DIR_UP, + GPIO_PULL_DIR_DOWN, +} gpio_pull_dir_t; + +/* Returns the appropriate gpio_port for the provided pin. */ +inline static gpio_port_t get_port_for_pin(gpio_pin_t pin) +{ + switch (pin) { +#define PORT(p, pn) \ + case GPIO_PIN_P ## p ## pn: return GPIO_PORT_ ## p; +#include "arch/stm32l4xxx/peripherals/tables/stm32l432xx/gpio/port_table.inc" +#undef PORT + case N_GPIO_PINS: return N_GPIO_PORTS; + } + + /* Should be unreachable. */ +} + +#define DEFAULT_GPIO_OPTS_OUTPUT \ + (gpio_pin_opts_t) { \ + .mode = GPIO_MODE_OUTPUT, \ + .pull_dir = GPIO_PULL_DIR_DOWN, \ + .output_opts.speed = GPIO_OUTPUT_SPEED_MEDIUM, \ + .output_opts.type = GPIO_OUTPUT_TYPE_PUSH_PULL, \ + } + +#define DEFAULT_GPIO_OPTS_INPUT \ + (gpio_pin_opts_t) { \ + .mode = GPIO_MODE_OUTPUT, \ + .pull_dir = GPIO_PULL_DIR_DOWN, \ + } + +typedef struct { + gpio_mode_t mode; + gpio_pull_dir_t pull_dir; + + union { + struct { + } input_opts; + + struct { + gpio_output_speed_t speed; + gpio_output_type_t type; + } output_opts; + + struct { + uint8_t function; + } alternate_opts; + + struct { + } analog_opts; + }; +} gpio_pin_opts_t; + +/* Differentiates at compile-time from the a gpio_pin_t enum value and a pin + * that's been reserved. */ +typedef struct { + gpio_pin_t v_; +} gpio_reserved_pin_t; + +/* Returns a pointer to the GPIO pin bus and offset. This is useful for when + * raw access to the values are needed. I.e. time critical applications. */ +void get_gpio_pin_port_off( + gpio_pin_t pin, gpio_port_config_t** out_cfg, int* out_off); + +/* Sets the given GPIO pin to high. */ +void set_gpio_pin_high(gpio_reserved_pin_t pin); + +/* Sets the given GPIO pin to low. */ +void set_gpio_pin_low(gpio_reserved_pin_t pin); + +/** returns true if a GPIO pin is in use. */ +bool gpio_pin_in_use(gpio_pin_t pin); + +/* + * Reserve the provided GPIO pin using the opts provided. + * + * sets error_out to GPIO_ERROR_IN_USE if the GPIO pin could not be reserved + * because it already has been reserved. + * + * The function will automatically enable the correct GPIO port bus. + */ +gpio_reserved_pin_t reserve_gpio_pin( + gpio_pin_t pin, gpio_pin_opts_t* opts, int* error_out); + +/* Enables and returns the pin reserved for the alternate function. + * + * If the `hint` parameter is defined (non -1) the manager will try + * to reserve that pin for the alternate function and fail if it can't. + * + * If `hint` is -1 then the first available pin for that alternate function + * will be reserved and returned. + * + * + */ +gpio_reserved_pin_t gpio_enable_alternate_function( + gpio_alternate_function_t fn, + gpio_pin_t hint, + int* error_out); + +/* + * Releases the GPIO pin so it can be reserved again in the future. + * + * The pin is reset during this process and if there are no more reserved pins + * on the corresponding port this function will disable the port. (last one out + * gets the lights.). + */ +void release_gpio_pin(gpio_reserved_pin_t gpio_pin); + +#endif /* KERN_GPIO_GPIO_MANAGE_H_ */ diff --git a/include/kern/gpio/sysled.h b/include/kern/gpio/sysled.h new file mode 100644 index 0000000..b2c9056 --- /dev/null +++ b/include/kern/gpio/sysled.h @@ -0,0 +1,11 @@ +/* + * Headers for interacting and managing the system LED. + */ +#ifndef SYSLED_H_ +#define SYSLED_H_ + +#include "kern/gpio/gpio_manager.h" + +gpio_reserved_pin_t get_sysled(); + +#endif diff --git a/include/kern/init.h b/include/kern/init.h new file mode 100644 index 0000000..737b85f --- /dev/null +++ b/include/kern/init.h @@ -0,0 +1,67 @@ +#ifndef INIT_H_ +#define INIT_H_ + +/** Globals annotated with _no_init will not be set during init1 bootup + * where the data segement is loaded from flash and the bss segment is + * cleared. + * + * This is useful for routines that run in the init0 boot procedure + * that need persistent globals. + * + * Note that initializing a global annotated with _no_init will have + * no effect as the variable will remain uninitialized until explicitly + * set by by the program. + */ +#define _no_init \ + __attribute((__section__(".noinit"))) + +#define init0 \ + static void init0fn(); \ + static __attribute((__section__(".init0"))) \ + __attribute((__used__)) \ + void(*init0_ptr)() = init0fn; \ + static void init0fn +#define init1 \ + static void init1fn(); \ + static __attribute((__section__(".init1"))) \ + __attribute((__used__)) \ + void(*init1_ptr)() = init1fn; \ + static void init1fn +#define init2 \ + static void init2fn(); \ + static __attribute((__section__(".init2"))) \ + __attribute((__used__)) \ + void(*init2_ptr)() = init2fn; \ + static void init2fn +#define init3 \ + static void init3fn(); \ + static __attribute((__section__(".init3"))) \ + __attribute((__used__)) \ + void(*init3_ptr)() = init3fn; \ + static void init3fn +#define init4 \ + static void init4fn(); \ + static __attribute((__section__(".init4"))) \ + __attribute((__used__)) \ + void(*init4_ptr)() = init4fn; \ + static void init4fn +#define init5 \ + static void init5fn(); \ + static __attribute((__section__(".init5"))) \ + __attribute((__used__)) \ + void(*init5_ptr)() = init5fn; \ + static void init5fn +#define init6 \ + static void init6fn(); \ + static __attribute((__section__(".init6"))) \ + __attribute((__used__)) \ + void(*init6_ptr)() = init6fn; \ + static void init6fn +#define init7 \ + static void init7fn(); \ + static __attribute((__section__(".init7"))) \ + __attribute((__used__)) \ + void(*init7_ptr)() = init7fn; \ + static void init7fn + +#endif /* INIT_H_ */ diff --git a/include/kern/lib.h b/include/kern/lib.h new file mode 100644 index 0000000..be0e8e9 --- /dev/null +++ b/include/kern/lib.h @@ -0,0 +1,10 @@ +#ifndef LIB_H_ +#define LIB_H_ + +#include <stdint.h> + +void hexify(uint32_t v, char* into); + +void decimalify(int v, char* into); + +#endif diff --git a/include/kern/log.h b/include/kern/log.h new file mode 100644 index 0000000..5e49def --- /dev/null +++ b/include/kern/log.h @@ -0,0 +1,12 @@ +#ifndef LOG_H_ +#define LOG_H_ + +/* + * Defines logging capabilities. This logging unit will enable logging on + * the systems main USART output. + */ + +/** Similar to fprintf, but with a stripped-down format-string DSL. */ +void klogf(const char* fmt, ...); + +#endif diff --git a/include/kern/mem.h b/include/kern/mem.h new file mode 100644 index 0000000..c0999f5 --- /dev/null +++ b/include/kern/mem.h @@ -0,0 +1,32 @@ +#ifndef MEM_H_ +#define MEM_H_ + +#include "arch.h" +#include <stddef.h> + +#define DATA_SEGMENT_STOP_ADDR ((uint8_t*) &DATA_SEGMENT_STOP) +#define DATA_SEGMENT_START_ADDR ((uint8_t*) &DATA_SEGMENT_START) + +#define MAX_HEAP_SIZE \ + ((16384 - (DATA_SEGMENT_STOP_ADDR - DATA_SEGMENT_START_ADDR)) / 4 * 4) + +/* allocates memory on the head, which is stored in sram2 */ +void* halloc(size_t n); + +/* Frees the memory allocated by halloc. */ +void hfree(void* mem); + +#ifdef FOR_TESTING + +void* debug_halloc_get_next_ptr(void* ptr); + +void* debug_halloc_get_prev_ptr(void* ptr); + +int debug_halloc_assert_consistency(char* error, size_t len); + +void debug_print_blocks(); + +#endif + + +#endif diff --git a/include/kern/string.h b/include/kern/string.h new file mode 100644 index 0000000..3c9f0b4 --- /dev/null +++ b/include/kern/string.h @@ -0,0 +1,6 @@ +#ifndef STRING_H_ +#define STRING_H_ + +void kstrcpy(char* into, const char* from); + +#endif /* STRING_H_ */ |