From: phfr24 Date: Sun, 12 Jul 2026 20:25:43 +0000 (-0300) Subject: organize X-Git-Url: https://git.wirehaze.ovh/stm32f411ceu6.git/commitdiff_plain/4bfee77ecbb19ef2143a1cd486cfa92bd3aceef4?ds=inline organize --- diff --git a/Makefile b/Makefile index f0ec81f..3c19779 100644 --- a/Makefile +++ b/Makefile @@ -32,6 +32,7 @@ CFLAGS := -march=armv7e-m+fp \ -Wextra \ -Wconversion \ -Wstrict-prototypes \ + -Wmissing-prototypes \ -Wshadow \ -Wundef \ -Wdouble-promotion \ @@ -46,7 +47,7 @@ OCFLAGS := --output-target=binary # --------------------------------------------------------------------------- # -objs := kernel.o kentry.o +objs := $(patsubst %.c, %.o, $(wildcard *.c)) lds := kernel.ld LDFLAGS += -T $(lds) diff --git a/exceptions.c b/exceptions.c new file mode 100644 index 0000000..b3afaaa --- /dev/null +++ b/exceptions.c @@ -0,0 +1,53 @@ +#include "link.h" +#include "led.h" +#include "sysclk.h" +#include "uart.h" + +/* Initialize just enough to be able to handle a fault. */ +__attribute__ ((noinline, used)) static void +sys_init (void) +{ + unsigned int *src, *dst; + + /* Relocate .data section to SRAM */ + src = &_data_lma_start; + dst = &_data_vma_start; + + while (dst < &_data_vma_end) + *(dst++) = *(src++); + + /* Initialize .bss */ + dst = &_bss_vma_start; + + while (dst < &_bss_vma_end) + *(dst++) = 0; + + led_init (); + sysclk_init (); + uart_init (); +} + +/* Startup */ +__attribute__ ((naked, noreturn)) static void +reset_handler (void) +{ + /* Set FAULTMASK */ + asm ("cpsid f"); + + /* This function is the core logic for reset_handler (). We just need it so + * that when we jump to kentry the stack is empty. */ + asm ("bl sys_init"); + + /* Clear FAULTMASK */ + asm ("cpsie f"); + + /* Jump to kernel entry code. When reset_handler () is called we are already + * running on Thread mode (Privileged), so we can just jump directly. */ + asm ("b kentry"); +} + +__attribute__ ((section (".vector_table"), used)) +static unsigned long const vector_table[] = { + (unsigned long) &_sram_end, + (unsigned long) reset_handler, +}; diff --git a/kentry.c b/kentry.c index 33b8295..e9eab94 100644 --- a/kentry.c +++ b/kentry.c @@ -1,4 +1,7 @@ -#include "stm32f411.h" +#include "uart.h" +#include "led.h" + +__attribute__ ((noreturn)) void kentry (void); static const char *text[] = { "hello, friend.\r\n", @@ -15,7 +18,7 @@ static const char *text[] = { void kentry (void) { - unsigned int line, off; + unsigned int line; /* Test UART and LED ---------------------------------------------------- */ @@ -23,24 +26,8 @@ kentry (void) { for (line = 0; line < sizeof text / sizeof *text; ++line) { - /* Print current line */ - off = 0; - while (text[line][off]) - { - /* TXE: Transmit data register empty */ - while (!(*USART1_SR & (1u << 7))); /* 0: Data is not transferred - to the shift register */ - - /* DR[8:0]: Data value */ - *USART1_DR = text[line][off++]; - } - - /* TC: Transmission complete */ - while (!(*USART1_SR & (1u << 6))); /* 0: Transmission is not - complete */ - - /* Blink LED */ - *GPIOC_ODR ^= (1u << 13); + kputs_busytc (text[line]); + led_toggle (); } } } diff --git a/kernel.c b/kernel.c deleted file mode 100644 index 1545c6e..0000000 --- a/kernel.c +++ /dev/null @@ -1,100 +0,0 @@ -#include "link.h" -#include "stm32f411.h" - -__attribute__ ((noreturn)) extern void kentry (void); - -static void -reset_handler (void) -{ - unsigned int *src, *dst; - - /* Set FAULTMASK */ - asm ("cpsid f"); - - /* Initialize .data and .bss in SRAM ------------------------------------ */ - - /* Relocate .data section */ - src = &_data_lma_start; - dst = &_data_vma_start; - - while (dst < &_data_vma_end) - *(dst++) = *(src++); - - /* Initialize .bss */ - dst = &_bss_vma_start; - - while (dst < &_bss_vma_end) - *(dst++) = 0; - - /* LED setup ------------------------------------------------------------ */ - - /* GPIOCEN: IO port C clock enable */ - *RCC_AHB1ENR |= (1u << 2); /* 1: IO port C clock enabled */ - /* MODERy[1:0]: Port x configuration bits (y = 0..15) */ - *GPIOC_MODER &= ~(0b11u << 26); /* Clear PC13 bits */ - *GPIOC_MODER |= (1u << 26); /* 01: General purpose output mode */ - - /* PC13: 0 = LED on - * 1 = LED off */ - - /* SYSCLK setup --------------------------------------------------------- */ - - /* HSEBYP: HSE clock bypass */ - *RCC_CR &= ~(1u << 18); /* 0: HSE oscillator not bypassed */ - /* HSEON: HSE clock enable */ - *RCC_CR |= (1u << 16); /* 1: HSE oscillator ON */ - /* HSERDY: HSE clock ready flag */ - while (!(*RCC_CR & (1u << 17))); /* 0: HSE oscillator not ready */ - /* SW: System clock switch */ - *RCC_CFGR &= ~(0b11u); /* Clear SW bits */ - *RCC_CFGR |= (0b01u); /* 01: HSE oscillator selected as system clock */ - /* SWS: System clock switch status */ - while ((*RCC_CFGR & (0b11u << 2)) != (0b01u << 2)); /* 01: HSE oscillator used - as the system clock */ - /* HSION: Internal high-speed clock enable */ - *RCC_CR &= ~(1u); /* 0: HSI oscillator OFF */ - - /* UART setup ----------------------------------------------------------- */ - - /* GPIOAEN: IO port A clock enable */ - *RCC_AHB1ENR |= (1u); /* 1: IO port A clock enabled */ - /* MODERy[1:0]: Port x configuration bits (y = 0..15) */ - *GPIOA_MODER &= ~(0b1111u << 18); /* Clear PA9 and PA10 bits */ - *GPIOA_MODER |= (0b1010u << 18); /* 10: Alternate function mode */ - /* AFRHy: Alternate function selection for port x bit y (y = 8..15) */ - *GPIOA_AFRH &= ~(0b11111111u << 4); /* Clear PA9 and PA10 bits */ - *GPIOA_AFRH |= (0b01110111u << 4); /* 0111: AF7 */ - - /* PA9: USART1_TX - * PA10: USART1_RX */ - - /* USART1EN: USART1 clock enable */ - *RCC_APB2ENR |= (1u << 4); /* 1: USART1 clock enabled */ - /* UE: USART enable */ - *USART1_CR1 |= (1u << 13); /* 1: USART enable */ - /* M: Word length */ - *USART1_CR1 &= ~(1u << 12); /* 0: 1 Start bit, 8 Data bits, n Stop bit */ - /* PCE: Parity control enable */ - *USART1_CR1 &= ~(1u << 10); /* 0: Parity control disabled */ - /* STOP: STOP bits */ - *USART1_CR2 &= ~(0b11u << 12); /* 00: 1 Stop bit */ - /* Clock frequency: 25MHz - * Desired baud rate: 1.2 KBps - * USARTDIV = 1302.0625 */ - *USART1_BRR = (1302u << 4) | 1u; /* mantissa and fraction (/16) */ - /* TE: Transmitter enable */ - *USART1_CR1 |= (1u << 3); /* 1: Transmitter is enabled */ - - /* Jump to kernel entry code -------------------------------------------- */ - - /* Clear FAULTMASK */ - asm ("cpsie f"); - - kentry (); -} - -__attribute__ ((section (".vector_table"), used)) -static unsigned long const vector_table[] = { - (unsigned long) &_sram_end, - (unsigned long) reset_handler, -}; diff --git a/led.c b/led.c new file mode 100644 index 0000000..6627535 --- /dev/null +++ b/led.c @@ -0,0 +1,33 @@ +#include "led.h" +#include "stm32f411.h" + +void +led_init (void) +{ + /* GPIOCEN: IO port C clock enable */ + *RCC_AHB1ENR |= (1u << 2); /* 1: IO port C clock enabled */ + /* MODERy[1:0]: Port x configuration bits (y = 0..15) */ + *GPIOC_MODER &= ~(0b11u << 26); /* Clear PC13 bits */ + *GPIOC_MODER |= (1u << 26); /* 01: General purpose output mode */ + + /* PC13: 0 = LED on + * 1 = LED off */ +} + +void +led_on (void) +{ + *GPIOC_ODR &= ~(1u << 13); +} + +void +led_off (void) +{ + *GPIOC_ODR |= (1u << 13); +} + +void +led_toggle (void) +{ + *GPIOC_ODR ^= (1u << 13); +} diff --git a/led.h b/led.h new file mode 100644 index 0000000..5f02ce7 --- /dev/null +++ b/led.h @@ -0,0 +1,9 @@ +#ifndef _LED_H_ +#define _LED_H_ + +void led_init (void); +void led_on (void); +void led_off (void); +void led_toggle (void); + +#endif /* _LED_H_ */ diff --git a/sysclk.c b/sysclk.c new file mode 100644 index 0000000..a106774 --- /dev/null +++ b/sysclk.c @@ -0,0 +1,25 @@ +#include "sysclk.h" +#include "stm32f411.h" + +void +sysclk_init (void) +{ + /* HSEBYP: HSE clock bypass */ + *RCC_CR &= ~(1u << 18); /* 0: HSE oscillator not bypassed */ + + /* HSEON: HSE clock enable */ + *RCC_CR |= (1u << 16); /* 1: HSE oscillator ON */ + + /* HSERDY: HSE clock ready flag */ + while (!(*RCC_CR & (1u << 17))); /* 0: HSE oscillator not ready */ + + /* SW: System clock switch */ + *RCC_CFGR &= ~(0b11u); /* Clear SW bits */ + *RCC_CFGR |= (0b01u); /* 01: HSE oscillator selected as system clock */ + + /* SWS: System clock switch status */ + while ((*RCC_CFGR & (0b11u << 2)) != (0b01u << 2)); /* 01: HSE oscillator used + as the system clock */ + /* HSION: Internal high-speed clock enable */ + *RCC_CR &= ~(1u); /* 0: HSI oscillator OFF */ +} diff --git a/sysclk.h b/sysclk.h new file mode 100644 index 0000000..b02ae6a --- /dev/null +++ b/sysclk.h @@ -0,0 +1,6 @@ +#ifndef _SYSCLK_H_ +#define _SYSCLK_H_ + +void sysclk_init (void); + +#endif /* _SYSCLK_H_ */ diff --git a/uart.c b/uart.c new file mode 100644 index 0000000..7174979 --- /dev/null +++ b/uart.c @@ -0,0 +1,80 @@ +#include "uart.h" +#include "stm32f411.h" + +/* Wait for data to be transferred into the shift register. */ +static void +busywait_txe (void) +{ + /* TXE: Transmit data register empty */ + while (!(*USART1_SR & (1u << 7))); /* 0: Data is not transferred to the shift + register */ +} + +/* Wait for transmission of the last frame. */ +static void +busywait_tc (void) +{ + /* TC: Transmission complete */ + while (!(*USART1_SR & (1u << 6))); /* 0: Transmission is not complete */ +} + +static void +tx (char c) +{ + /* DR[8:0]: Data value */ + *USART1_DR = c; +} + +void +uart_init (void) +{ + /* GPIOAEN: IO port A clock enable */ + *RCC_AHB1ENR |= (1u); /* 1: IO port A clock enabled */ + + /* MODERy[1:0]: Port x configuration bits (y = 0..15) */ + *GPIOA_MODER &= ~(0b1111u << 18); /* Clear PA9 and PA10 bits */ + *GPIOA_MODER |= (0b1010u << 18); /* 10: Alternate function mode */ + + /* AFRHy: Alternate function selection for port x bit y (y = 8..15) */ + *GPIOA_AFRH &= ~(0b11111111u << 4); /* Clear PA9 and PA10 bits */ + *GPIOA_AFRH |= (0b01110111u << 4); /* 0111: AF7 */ + + /* PA9: USART1_TX + * PA10: USART1_RX */ + + /* USART1EN: USART1 clock enable */ + *RCC_APB2ENR |= (1u << 4); /* 1: USART1 clock enabled */ + + /* UE: USART enable */ + *USART1_CR1 |= (1u << 13); /* 1: USART enable */ + + /* M: Word length */ + *USART1_CR1 &= ~(1u << 12); /* 0: 1 Start bit, 8 Data bits, n Stop bit */ + + /* PCE: Parity control enable */ + *USART1_CR1 &= ~(1u << 10); /* 0: Parity control disabled */ + + /* STOP: STOP bits */ + *USART1_CR2 &= ~(0b11u << 12); /* 00: 1 Stop bit */ + + /* Clock frequency: 25MHz + * Desired baud rate: 1.2 KBps */ + + /* Mantissa and fraction (/16) */ + *USART1_BRR = (1302u << 4) | 1u; /* USARTDIV = 1302.0625 */ + + /* TE: Transmitter enable */ + *USART1_CR1 |= (1u << 3); /* 1: Transmitter is enabled */ +} + +void +kputs_busytc (const char *str) +{ + while (*str) + { + busywait_txe (); + tx (*(str++)); + } + + busywait_tc (); +} diff --git a/uart.h b/uart.h new file mode 100644 index 0000000..ee16d4c --- /dev/null +++ b/uart.h @@ -0,0 +1,9 @@ +#ifndef _UART_H_ +#define _UART_H_ + +void uart_init (void); + +/* Busy waiting, wait for Transmission Complete (TC). */ +void kputs_busytc (const char *str); + +#endif /* _UART_H_ */