From e9a6bad751ef732f37d18e30955aa38d2a908e86 Mon Sep 17 00:00:00 2001 From: Sergey Lyubka Date: Sun, 17 Dec 2023 19:37:00 +0000 Subject: [PATCH] Move clock_init() to hal.h --- .../hal.h | 56 ++++++++++++++++- .../main.c | 2 + .../sysinit.c | 63 +++---------------- 3 files changed, 64 insertions(+), 57 deletions(-) diff --git a/examples/stm32/nucleo-h743zi-make-baremetal-builtin/hal.h b/examples/stm32/nucleo-h743zi-make-baremetal-builtin/hal.h index 69c80b04a4..368c1ce5e3 100644 --- a/examples/stm32/nucleo-h743zi-make-baremetal-builtin/hal.h +++ b/examples/stm32/nucleo-h743zi-make-baremetal-builtin/hal.h @@ -24,7 +24,7 @@ #define LED2 PIN('E', 1) // On-board LED pin (yellow) #define LED3 PIN('B', 14) // On-board LED pin (red) -#define LED LED2 // Use yellow LED for blinking +#define LED LED2 // Use yellow LED for blinking // System clock (2.1, Figure 1; 8.5, Figure 45; 8.5.5, Figure 47; 8.5.6, Figure // 49) CPU_FREQUENCY <= 480 MHz; hclk = CPU_FREQUENCY / HPRE ; hclk <= 240 MHz; @@ -61,7 +61,9 @@ enum { GPIO_PULL_NONE, GPIO_PULL_UP, GPIO_PULL_DOWN }; #define GPIO(N) ((GPIO_TypeDef *) (0x40000000 + 0x18020000UL + 0x400 * (N))) -static GPIO_TypeDef *gpio_bank(uint16_t pin) { return GPIO(PINBANK(pin)); } +static GPIO_TypeDef *gpio_bank(uint16_t pin) { + return GPIO(PINBANK(pin)); +} static inline void gpio_toggle(uint16_t pin) { GPIO_TypeDef *gpio = gpio_bank(pin); uint32_t mask = BIT(PINNO(pin)); @@ -159,6 +161,53 @@ static inline char chiprev(void) { return '?'; } +static inline unsigned int div2prescval(unsigned int div) { + // 0 --> /1; 8 --> /2 ... 11 --> /16; 12 --> /64 ... 15 --> /512 + if (div == 1) return 0; + if (div > 16) div /= 2; + unsigned int val = 7; + while (div >>= 1) ++val; + return val; +} + +static inline unsigned int pllrge(unsigned int f) { + unsigned int val = 0; + while (f >>= 1) ++val; + return val - 1; +} + +static inline void clock_init(void) { + SCB->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); // Enable FPU + __DSB(); + __ISB(); + PWR->CR3 |= BIT(1); // select LDO (reset value) + while ((PWR->CSR1 & BIT(13)) == 0) spin(1); // ACTVOSRDY + PWR->D3CR |= BIT(15) | BIT(14); // Select VOS1 + uint32_t f = PWR->D3CR; // fake read to wait for bus clocking + while ((PWR->CSR1 & BIT(13)) == 0) spin(1); // ACTVOSRDY + SYSCFG->PWRCR |= BIT(0); // ODEN + f = SYSCFG->PWRCR; + while ((PWR->CSR1 & BIT(13)) == 0) spin(1); // ACTVOSRDY + (void) f; + SETBITS( + RCC->D1CFGR, (0x0F << 8) | (7 << 4) | (0x0F << 0), + (div2prescval(D1CPRE) << 8) | (D1PPRE << 4) | (div2prescval(HPRE) << 0)); + RCC->D2CFGR = (D2PPRE2 << 8) | (D2PPRE1 << 4); + RCC->D3CFGR = (D3PPRE << 4); + SETBITS(RCC->PLLCFGR, 3 << 2, + pllrge(PLL1_HSI / PLL1_M) + << 2); // keep reset config (DIVP1EN, !PLL1VCOSEL), PLL1RGE + SETBITS(RCC->PLL1DIVR, (0x7F << 9) | (0x1FF << 0), + ((PLL1_P - 1) << 9) | ((PLL1_N - 1) << 0)); // Set PLL1_P PLL1_N + SETBITS(RCC->PLLCKSELR, 0x3F << 4, + PLL1_M << 4); // Set PLL1_M (source defaults to HSI) + RCC->CR |= BIT(24); // Enable PLL1 + while ((RCC->CR & BIT(25)) == 0) spin(1); // Wait until done + RCC->CFGR |= (3 << 0); // Set clock source to PLL1 + while ((RCC->CFGR & (7 << 3)) != (3 << 3)) spin(1); // Wait until done + FLASH->ACR = FLASH_LATENCY; // default is larger +} + static inline void ethernet_init(void) { // Initialise Ethernet. Enable MAC GPIO pins, see // https://www.st.com/resource/en/user_manual/um2407-stm32h7-nucleo144-boards-mb1364-stmicroelectronics.pdf @@ -169,9 +218,10 @@ static inline void ethernet_init(void) { gpio_init(pins[i], GPIO_MODE_AF, GPIO_OTYPE_PUSH_PULL, GPIO_SPEED_INSANE, GPIO_PULL_NONE, 11); // 11 is the Ethernet function } - NVIC_EnableIRQ(ETH_IRQn); // Setup Ethernet IRQ handler + RCC->APB4ENR |= RCC_APB4ENR_SYSCFGEN; // Enable SYSCFG SETBITS(SYSCFG->PMCR, 7 << 21, 4 << 21); // Use RMII (12.3.1) RCC->AHB1ENR |= BIT(15) | BIT(16) | BIT(17); // Enable Ethernet clocks + NVIC_EnableIRQ(ETH_IRQn); // Setup Ethernet IRQ handler } #define UUID ((uint8_t *) UID_BASE) // Unique 96-bit chip ID. TRM 61.1 diff --git a/examples/stm32/nucleo-h743zi-make-baremetal-builtin/main.c b/examples/stm32/nucleo-h743zi-make-baremetal-builtin/main.c index 2f008f4cc8..cd6a30a3bc 100644 --- a/examples/stm32/nucleo-h743zi-make-baremetal-builtin/main.c +++ b/examples/stm32/nucleo-h743zi-make-baremetal-builtin/main.c @@ -32,6 +32,8 @@ static void timer_fn(void *arg) { ifp->ndrop, ifp->nerr)); } +// Device initialisation flow is in startup_XXX.s, provided by device vendor. +// It inits data/bss, IRQ table, then calls SystemInit(), then calls main() int main(void) { gpio_output(LED); // Setup green LED uart_init(UART_DEBUG, 115200); // Initialise debug printf diff --git a/examples/stm32/nucleo-h743zi-make-baremetal-builtin/sysinit.c b/examples/stm32/nucleo-h743zi-make-baremetal-builtin/sysinit.c index 2d3c124e45..341ddc676a 100644 --- a/examples/stm32/nucleo-h743zi-make-baremetal-builtin/sysinit.c +++ b/examples/stm32/nucleo-h743zi-make-baremetal-builtin/sysinit.c @@ -4,62 +4,17 @@ // This file contains essentials required by the CMSIS: // uint32_t SystemCoreClock - holds the system core clock value // SystemInit() - initialises the system, e.g. sets up clocks +// +// Vendor CMSIS usually contain system_XXXX.c file with SystemInit() +// We don't use it - instead, we provide our own SystemInit(). #include "hal.h" -uint32_t SystemCoreClock = CPU_FREQUENCY; - -static inline unsigned int div2prescval(unsigned int div) { - // 0 --> /1; 8 --> /2 ... 11 --> /16; 12 --> /64 ... 15 --> /512 - if (div == 1) return 0; - if (div > 16) div /= 2; - unsigned int val = 7; - while (div >>= 1) ++val; - return val; -} - -static inline unsigned int pllrge(unsigned int f) { - unsigned int val = 0; - while (f >>= 1) ++val; - return val - 1; -} - -void SystemInit(void) { // Called automatically by startup code - SCB->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); // Enable FPU - asm("DSB"); - asm("ISB"); - PWR->CR3 |= BIT(1); // select LDO (reset value) - while ((PWR->CSR1 & BIT(13)) == 0) spin(1); // ACTVOSRDY - PWR->D3CR |= BIT(15) | BIT(14); // Select VOS1 - uint32_t f = PWR->D3CR; // fake read to wait for bus clocking - while ((PWR->CSR1 & BIT(13)) == 0) spin(1); // ACTVOSRDY - SYSCFG->PWRCR |= BIT(0); // ODEN - f = SYSCFG->PWRCR; - while ((PWR->CSR1 & BIT(13)) == 0) spin(1); // ACTVOSRDY - (void) f; - SETBITS( - RCC->D1CFGR, (0x0F << 8) | (7 << 4) | (0x0F << 0), - (div2prescval(D1CPRE) << 8) | (D1PPRE << 4) | (div2prescval(HPRE) << 0)); - RCC->D2CFGR = (D2PPRE2 << 8) | (D2PPRE1 << 4); - RCC->D3CFGR = (D3PPRE << 4); - SETBITS(RCC->PLLCFGR, 3 << 2, - pllrge(PLL1_HSI / PLL1_M) - << 2); // keep reset config (DIVP1EN, !PLL1VCOSEL), PLL1RGE - SETBITS(RCC->PLL1DIVR, (0x7F << 9) | (0x1FF << 0), - ((PLL1_P - 1) << 9) | ((PLL1_N - 1) << 0)); // Set PLL1_P PLL1_N - SETBITS(RCC->PLLCKSELR, 0x3F << 4, - PLL1_M << 4); // Set PLL1_M (source defaults to HSI) - RCC->CR |= BIT(24); // Enable PLL1 - while ((RCC->CR & BIT(25)) == 0) spin(1); // Wait until done - RCC->CFGR |= (3 << 0); // Set clock source to PLL1 - while ((RCC->CFGR & (7 << 3)) != (3 << 3)) spin(1); // Wait until done - FLASH->ACR = FLASH_LATENCY; // default is larger -#if 0 - // Enable SRAM block if you want to use it for ETH buffer (needs proper attributes in driver code) - // RCC->AHB2ENR |= BIT(29) | BIT(30) | BIT(31); -#endif +uint32_t SystemCoreClock; // Holds system core clock in Hz. Required by CMSIS - RCC->APB4ENR |= RCC_APB4ENR_SYSCFGEN; // Enable SYSCFG - rng_init(); // Initialise random number generator - SysTick_Config(CPU_FREQUENCY / 1000); // Sys tick every 1ms +void SystemInit(void) { // Called automatically by startup code + clock_init(); // Core clock to 480 MHz + rng_init(); // Initialise random number generator + SystemCoreClock = CPU_FREQUENCY; // defined in hal.h + SysTick_Config(SystemCoreClock / 1000); // Sys tick every 1ms }