From 2478a549b9f64c50310da41c861b8f86fdea2861 Mon Sep 17 00:00:00 2001 From: Josh Rahm Date: Tue, 24 Nov 2020 00:38:09 -0700 Subject: Add new system for startup. Now instead of init() and main() being responsible for all initialization, individual modules can link in their own initialization routines. There are 7 levels for these initializiation routines. So far these are how the levels are defined level 0 - Here the world is dark. Nothing is initialized. This level is responsible for initializing the system clock. level 1 - The system clock has been configured, but nothing else. Not even global variables. This level is responsible for loading the data sections from flash and clearing the .bss section. level 2 - USART2 is enabled and set to be the main kernel logging vehicle. From this point on klogf(...) can be used. level 3 - The NVIC is reset to point to the flash. From this point on interrupts can be received. I expect this is where most core initialization routines will take place levels 4 to 7 - User initializiation levels. main - main() is called after all 8 initialization levels have executed, so in a sense main() is like a 9th initialization level, except that there is can be only one main() routine whereas there can be multiple initalization routines per level. --- 02-usart/src/arch/stm32l4xxx/peripherals/clock.c | 11 +++ 02-usart/src/arch/stm32l4xxx/peripherals/init.c | 49 ---------- 02-usart/src/arch/stm32l4xxx/peripherals/usart.c | 13 ++- 02-usart/src/kern/init.c | 82 +++++++++++++++++ 02-usart/src/kern/log.c | 55 ++++++++++++ 02-usart/src/kern/main.c | 109 ++--------------------- 6 files changed, 164 insertions(+), 155 deletions(-) delete mode 100644 02-usart/src/arch/stm32l4xxx/peripherals/init.c create mode 100644 02-usart/src/kern/init.c create mode 100644 02-usart/src/kern/log.c (limited to '02-usart/src') diff --git a/02-usart/src/arch/stm32l4xxx/peripherals/clock.c b/02-usart/src/arch/stm32l4xxx/peripherals/clock.c index 1029d39..9051572 100644 --- a/02-usart/src/arch/stm32l4xxx/peripherals/clock.c +++ b/02-usart/src/arch/stm32l4xxx/peripherals/clock.c @@ -5,10 +5,13 @@ #include "arch/stm32l4xxx/peripherals/clock.h" #include "arch/stm32l4xxx/peripherals/flash.h" +#include "kern/init.h" + #include #define TIMEOUT 10000 + int pll_off() { uint32_t c; @@ -66,8 +69,16 @@ int configure_pll( return 0; } +static _no_init uint8_t clock_mHz; +uint8_t get_clock_mhz() +{ + return clock_mHz; +} + int set_system_clock_MHz(uint8_t mhz) { + clock_mHz = mhz; + /* Set the source of the system colck to MSI temporarily. */ set_system_clock_src(SYSTEM_CLOCK_SRC_MSI); diff --git a/02-usart/src/arch/stm32l4xxx/peripherals/init.c b/02-usart/src/arch/stm32l4xxx/peripherals/init.c deleted file mode 100644 index 47bfaa5..0000000 --- a/02-usart/src/arch/stm32l4xxx/peripherals/init.c +++ /dev/null @@ -1,49 +0,0 @@ -#include "arch.h" -#include "arch/stm32l4xxx/peripherals/system.h" - -/* Forward-declare the main function. This is implemented in main.c. */ -void main(); - -/* These are defined in the linker script. */ - -#ifdef ARCH_STM32L4 -extern uint32_t INIT_DATA_VALUES; -extern uint32_t DATA_SEGMENT_START; -extern uint32_t DATA_SEGMENT_STOP; -extern uint32_t BSS_START; -extern uint32_t BSS_END; - -/* - * Runs before main. Initializes the data and bss segments by loading them - * into memory. - */ -_Noreturn void on_reset() -{ - uint32_t* src; - uint32_t* dest; - - src = &INIT_DATA_VALUES; - dest = &DATA_SEGMENT_START; - - /* Copy the values from flash into the data segment. */ - while (dest != &DATA_SEGMENT_STOP) { - *(dest++) = *(src++); - } - - /* Everything in the BSS segment is set to zero. */ - dest = &BSS_START; - while (dest != &BSS_END) { - *(dest++) = 0; - } - - /* Set the vector offset table to be at the start - * of FLASH memory. */ - SCB.vto_r = 0x08000000; - - /* Jump to main. */ - main(); - - for(;;); -} - -#endif /* ARCH_STM32L4 */ diff --git a/02-usart/src/arch/stm32l4xxx/peripherals/usart.c b/02-usart/src/arch/stm32l4xxx/peripherals/usart.c index d37eee2..7309b48 100644 --- a/02-usart/src/arch/stm32l4xxx/peripherals/usart.c +++ b/02-usart/src/arch/stm32l4xxx/peripherals/usart.c @@ -97,9 +97,8 @@ void usart_enable_dma(__IO usart_t* usart, usart_enable_t enabled) }; } -void usart_printf(__IO usart_t* usart, const char* fmt, ...) +void usart_vprintf(__IO usart_t* usart, const char* fmt, va_list l) { - va_list l; union { void* ptr; char* str; @@ -107,8 +106,6 @@ void usart_printf(__IO usart_t* usart, const char* fmt, ...) } b; char buf[128]; - va_start(l, fmt); - while (*fmt != 0) { if (*fmt == '%') { switch (*(++fmt)) { @@ -145,3 +142,11 @@ void usart_printf(__IO usart_t* usart, const char* fmt, ...) end: va_end(l); } + +void usart_printf(__IO usart_t* usart, const char* fmt, ...) +{ + va_list l; + va_start(l, fmt); + + usart_vprintf(usart, fmt, l); +} diff --git a/02-usart/src/kern/init.c b/02-usart/src/kern/init.c new file mode 100644 index 0000000..2531ca9 --- /dev/null +++ b/02-usart/src/kern/init.c @@ -0,0 +1,82 @@ +#include "kern/init.h" + +#include "arch.h" +#include "arch/stm32l4xxx/peripherals/system.h" +#include "arch/stm32l4xxx/peripherals/clock.h" + +#include "kern/log.h" + +/* Forward-declare the main function. This is implemented in main.c. */ +int main(); + +/* These are defined in the linker script. */ + +#ifdef ARCH_STM32L4 +extern uint32_t INIT_DATA_VALUES; +extern uint32_t DATA_SEGMENT_START; +extern uint32_t DATA_SEGMENT_STOP; +extern uint32_t BSS_START; +extern uint32_t BSS_END; + +extern void(*INIT_ROUTINES_FLASH_START)(); +extern void(*INIT_ROUTINES_FLASH_STOP)(); + +init0() +{ + /* Enable a higher clock speed. This is the first thing we do + * beacuse it will boost the boot up time. */ + set_system_clock_MHz(80); +} + +init1() +{ + /* Next, we'll copy the data sections from flash to ram. */ + uint32_t* src; + uint32_t* dest; + + src = &INIT_DATA_VALUES; + dest = &DATA_SEGMENT_START; + + /* Copy the values from flash into the data segment. */ + while (dest != &DATA_SEGMENT_STOP) { + *(dest++) = *(src++); + } + + /* Everything in the BSS segment is set to zero. */ + dest = &BSS_START; + while (dest != &BSS_END) { + *(dest++) = 0; + } +} + +init3() +{ + klogf("--- System Restart ---\n"); + klogf("Setting the vector offset table to point to the start of flash.\n"); + + /* Set the vector offset table to be at the start + * of FLASH memory. */ + SCB.vto_r = 0x08000000; +} + +/* + * Runs before main. Initializes the data and bss segments by loading them + * into memory. + */ +_Noreturn void on_reset() +{ + void (**initfn)(); + for(initfn = &INIT_ROUTINES_FLASH_START; + initfn < &INIT_ROUTINES_FLASH_STOP; + ++ initfn) { + + (*initfn)(); + } + + /* Jump to main. */ + main(); + + for(;;); +} + +#endif /* ARCH_STM32L4 */ diff --git a/02-usart/src/kern/log.c b/02-usart/src/kern/log.c new file mode 100644 index 0000000..a217183 --- /dev/null +++ b/02-usart/src/kern/log.c @@ -0,0 +1,55 @@ +#include "arch/stm32l4xxx/peripherals/usart.h" +#include "arch/stm32l4xxx/peripherals/clock.h" + +#include "kern/log.h" +#include "kern/init.h" +#include "kern/gpio/gpio_manager.h" + +#include "kern/common.h" + +void setup_usart2(uint32_t baud_rate); + +/** This module requires an initialization routine. This is a level2 routine, + * so anything running at level3 or lower is guaranteed to have access + * to the klong. */ +init2() +{ + setup_usart2(115200); + regset(USART2.c_r1, usart_txeie, 1); + regset(USART2.c_r1, usart_rxneie, 1); + usart_set_enabled(&USART2, USART_ENABLE_TX | USART_ENABLE_RX); + + klogf("klog() enabled on USART2\n"); +} + +void klogf(const char* fmt, ...) +{ + va_list l; + va_start(l, fmt); + + usart_vprintf(&USART2, fmt, l); +} + +void setup_usart2(uint32_t baud_rate) +{ + enable_hsi(&RCC, true); + + int ec = 0; + gpio_enable_alternate_function( + GPIO_ALTERNATE_FUNCTION_USART2_TX, GPIO_PIN_PA2, &ec); + + gpio_enable_alternate_function( + GPIO_ALTERNATE_FUNCTION_USART2_RX, GPIO_PIN_PA15, &ec); + + set_usart2_clock_src(&RCC, USART_CLK_SRC_HSI16); + set_usart2_clock_enabled(&RCC, USART_CLK_SRC_HSI16); + + /* De-assert reset of USART2 */ + regset(RCC.apb1rst1_r, rcc_usart2rst, 0); + + USART2.c_r1 = 0; + USART2.c_r2 = 0; + USART2.c_r3 = 0; + + usart_set_divisor(&USART2, 16000000 / baud_rate); +} diff --git a/02-usart/src/kern/main.c b/02-usart/src/kern/main.c index 32166bc..ebb2164 100644 --- a/02-usart/src/kern/main.c +++ b/02-usart/src/kern/main.c @@ -1,67 +1,12 @@ - #include "arch.h" +#include "kern/log.h" -#include "arch/stm32l4xxx/peripherals/clock.h" -#include "arch/stm32l4xxx/peripherals/dma.h" -#include "arch/stm32l4xxx/peripherals/gpio.h" #include "arch/stm32l4xxx/peripherals/system.h" -#include "arch/stm32l4xxx/peripherals/usart.h" -#include "arch/stm32l4xxx/peripherals/nvic.h" -#include "arch/stm32l4xxx/peripherals/irq.h" - -#include "kern/dma/dma_manager.h" -#include "kern/gpio/gpio_manager.h" -#include "kern/gpio/sysled.h" - -#include "kern/delay.h" -#include "kern/mem.h" -#include "kern/string.h" - -/** Overrides the default systick irq handler. */ -void on_systick() -{ - static int is_on = 0; - gpio_reserved_pin_t sysled = get_sysled(); - - if (is_on) { - set_gpio_pin_low(sysled); - } else { - set_gpio_pin_high(sysled); - } - - is_on = ! is_on; -} +#include "arch/stm32l4xxx/peripherals/clock.h" -void setup_usart2(uint32_t baud_rate) +void on_systick() /* Overrides weak-symbol on_systick. */ { - enable_hsi(&RCC, true); - - int ec = 0; - gpio_enable_alternate_function( - GPIO_ALTERNATE_FUNCTION_USART2_TX, GPIO_PIN_PA2, &ec); - - if (ec) { - unhandled_isr(ec & 0xff); - } - - gpio_enable_alternate_function( - GPIO_ALTERNATE_FUNCTION_USART2_RX, GPIO_PIN_PA15, &ec); - - if (ec) { - unhandled_isr(ec & 0xff); - } - - set_usart2_clock_src(&RCC, USART_CLK_SRC_HSI16); - set_usart2_clock_enabled(&RCC, USART_CLK_SRC_HSI16); - - /* De-assert reset of USART2 */ - regset(RCC.apb1rst1_r, rcc_usart2rst, 0); - - USART2.c_r1 = 0; - USART2.c_r2 = 0; - USART2.c_r3 = 0; - - usart_set_divisor(&USART2, 16000000 / baud_rate); + klogf("Systick\n"); } #ifdef ARCH_STM32L4 @@ -69,56 +14,16 @@ void setup_usart2(uint32_t baud_rate) /* Main function. This gets executed from the interrupt vector defined above. */ int main() { - /* Enable a higher clock frequency. */ - set_system_clock_MHz(80); - - setup_usart2(115200); - regset(USART2.c_r1, usart_txeie, 1); - regset(USART2.c_r1, usart_rxneie, 1); - usart_enable_dma(&USART2, USART_ENABLE_TX); - usart_set_enabled(&USART2, USART_ENABLE_TX | USART_ENABLE_RX); - - - dma_opts_t opts = DEFAULT_DMA_OPTS; - opts.transfer_complete_interrupt_enable = 1; - int ec = 0; - dma_mem2p_channel_t dma_chan = - select_dma_channel_mem2p(DMA1_PERIPH_USART2_TX, &opts, &ec); - enable_interrupt(dma_channel_get_interrupt(dma_chan.c_)); + klogf("Hello, World! Clock Mhz: %d\n", (uint32_t) get_clock_mhz()); - if (ec) { - usart_printf(&USART2, "Select DMA channel failed :( %d\n", ec); - for (;;); - } - - // const char* thing = "Good Thing This Works!"; - - char* str = halloc(128); - kstrcpy(str, "Hello, Heap!"); - - usart_printf(&USART2, "DATA_SEGMENT_START %p\n", &DATA_SEGMENT_START); - usart_printf(&USART2, "DATA_SEGMENT_STOP: %p\n", &DATA_SEGMENT_STOP); - usart_printf(&USART2, "str at: %p\n", str); - usart_printf(&USART2, "str: %s\n", str); - // usart_printf(&USART2, "%s\n", thing); - // regset(USART2.ic_r, usart_tccf, 1); - // dma_mem2p_initiate_transfer(dma_chan, thing, strlen(thing)); - - gpio_reserved_pin_t sysled = get_sysled(); - set_gpio_pin_high(sysled); - - // usart_printf(&USART2, "Start Configuring Countdown!\n"); - - /* Set the countdown to start from 1,000,0000. */ - SCB.strv_r = 1000000; + /* Set the countdown to start from 10,000,0000. */ + SCB.strv_r = 10000000; /* Enable interrupts. */ regset(SCB.stcs_r, scb_tickint, 1); /* Start the systick. */ regset(SCB.stcs_r, scb_enable, 1); - - // usart_printf(&USART2, "Start Countdown Started!\n"); } #endif -- cgit