diff options
author | Frederic Morin <frederic.morin.8@gmail.com> | 2023-03-05 19:15:43 -0500 |
---|---|---|
committer | KevinOConnor <kevin@koconnor.net> | 2023-05-07 11:15:05 -0400 |
commit | 33b18fd62ba73c90054a7b94b68c341bb3f40d9a (patch) | |
tree | 8a2b11edeaa52ffffa2891412a5f7d6978b8f959 /src/stm32/stm32f7.c | |
parent | a3eebab4f2b90822f76de91487ff3d4158b80494 (diff) | |
download | kutter-33b18fd62ba73c90054a7b94b68c341bb3f40d9a.tar.gz kutter-33b18fd62ba73c90054a7b94b68c341bb3f40d9a.tar.xz kutter-33b18fd62ba73c90054a7b94b68c341bb3f40d9a.zip |
stm32f7: add support for stm32f7 and remram board
Signed-off-by: Frederic Morin <frederic.morin.8@gmail.com>
Diffstat (limited to 'src/stm32/stm32f7.c')
-rw-r--r-- | src/stm32/stm32f7.c | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/src/stm32/stm32f7.c b/src/stm32/stm32f7.c new file mode 100644 index 00000000..f6f27618 --- /dev/null +++ b/src/stm32/stm32f7.c @@ -0,0 +1,168 @@ +// Code to setup clocks on stm32f7 +// +// Copyright (C) 2023 Frederic Morin <frederic.morin.8@gmail.com> +// +// This file may be distributed under the terms of the GNU GPLv3 license. + +#include "autoconf.h" // CONFIG_CLOCK_REF_FREQ +#include "board/armcm_boot.h" // VectorTable +#include "board/armcm_reset.h" // try_request_canboot +#include "board/irq.h" // irq_disable +#include "board/misc.h" // bootloader_request +#include "command.h" // DECL_CONSTANT_STR +#include "internal.h" // enable_pclock +#include "sched.h" // sched_main + + +/**************************************************************** + * Clock setup + ****************************************************************/ + +#define FREQ_PERIPH_DIV 4 +#define FREQ_PERIPH (CONFIG_CLOCK_FREQ / FREQ_PERIPH_DIV) +#define FREQ_USB 48000000 + +// Map a peripheral address to its enable bits +struct cline +lookup_clock_line(uint32_t periph_base) +{ + if (periph_base >= AHB1PERIPH_BASE) { + uint32_t bit = 1 << ((periph_base - AHB1PERIPH_BASE) / 0x400); + return (struct cline){.en=&RCC->AHB1ENR, .rst=&RCC->AHB1RSTR, .bit=bit}; + } else if (periph_base >= APB2PERIPH_BASE) { + uint32_t bit = 1 << ((periph_base - APB2PERIPH_BASE) / 0x400); + if (bit & 0x700) + // Skip ADC peripheral reset as they share a bit + return (struct cline){.en=&RCC->APB2ENR, .bit=bit}; + return (struct cline){.en=&RCC->APB2ENR, .rst=&RCC->APB2RSTR, .bit=bit}; + } else { + uint32_t bit = 1 << ((periph_base - APB1PERIPH_BASE) / 0x400); + return (struct cline){.en=&RCC->APB1ENR, .rst=&RCC->APB1RSTR, .bit=bit}; + } +} + +// Return the frequency of the given peripheral clock +uint32_t +get_pclock_frequency(uint32_t periph_base) +{ + return FREQ_PERIPH; +} + +// Enable a GPIO peripheral clock +void +gpio_clock_enable(GPIO_TypeDef *regs) +{ + uint32_t rcc_pos = ((uint32_t)regs - AHB1PERIPH_BASE) / 0x400; + RCC->AHB1ENR |= 1 << rcc_pos; + RCC->AHB1ENR; +} + +#if !CONFIG_STM32_CLOCK_REF_INTERNAL +DECL_CONSTANT_STR("RESERVE_PINS_crystal", "PH0,PH1"); +#endif + +// Main clock setup called at chip startup +static void +clock_setup(void) +{ + // Configure and enable PLL + const uint32_t pll_base = 2000000, pll_freq = CONFIG_CLOCK_FREQ * 2; + uint32_t pllcfgr; + if (!CONFIG_STM32_CLOCK_REF_INTERNAL) { + // Configure 216Mhz PLL from external crystal (HSE) + const uint32_t div = CONFIG_CLOCK_REF_FREQ / pll_base; + RCC->CR |= RCC_CR_HSEON; + pllcfgr = RCC_PLLCFGR_PLLSRC_HSE | (div << RCC_PLLCFGR_PLLM_Pos); + } else { + // Configure 216Mhz PLL from internal 16Mhz oscillator (HSI) + const uint32_t div = 16000000 / pll_base; + pllcfgr = RCC_PLLCFGR_PLLSRC_HSI | (div << RCC_PLLCFGR_PLLM_Pos); + } + RCC->PLLCFGR = (pllcfgr | ((pll_freq/pll_base) << RCC_PLLCFGR_PLLN_Pos) + | (0 << RCC_PLLCFGR_PLLP_Pos) // /2 + | ((pll_freq/FREQ_USB) << RCC_PLLCFGR_PLLQ_Pos) + | (2 << RCC_PLLCFGR_PLLR_Pos)); + RCC->CR |= RCC_CR_PLLON; + + // Enable "over drive" + enable_pclock(PWR_BASE); + PWR->CR1 = (3 << PWR_CR1_VOS_Pos) | PWR_CR1_ODEN; + while (!(PWR->CSR1 & PWR_CSR1_ODRDY)) + ; + PWR->CR1 = (3 << PWR_CR1_VOS_Pos) | PWR_CR1_ODEN | PWR_CR1_ODSWEN; + while (!(PWR->CSR1 & PWR_CSR1_ODSWRDY)) + ; + + // Enable 48Mhz USB clock + if (CONFIG_USB) { + // setup PLLSAI + const uint32_t plls_base = 2000000, plls_freq = FREQ_USB * 4; + RCC->PLLSAICFGR = ( + ((plls_freq/plls_base) << RCC_PLLSAICFGR_PLLSAIN_Pos) // *96 + | (((plls_freq/FREQ_USB)/2 - 1) << RCC_PLLSAICFGR_PLLSAIP_Pos)// /4 + | ((plls_freq/FREQ_USB) << RCC_PLLSAICFGR_PLLSAIQ_Pos)); + // enable PLLSAI and wait for PLLSAI lock + RCC->CR |= RCC_CR_PLLSAION; + while (!(RCC->CR & RCC_CR_PLLSAIRDY)) + ; + // set CLK48 source to PLLSAI + RCC->DCKCFGR2 = RCC_DCKCFGR2_CK48MSEL; // RCC_CLK48SOURCE_PLLSAIP + } + + // Set flash latency + MODIFY_REG( + FLASH->ACR, FLASH_ACR_LATENCY, (uint32_t)(FLASH_ACR_LATENCY_7WS)); + + // Wait for PLL lock + while (!(RCC->CR & RCC_CR_PLLRDY)) + ; + + // Switch system clock to PLL + RCC->CFGR = RCC_CFGR_PPRE1_DIV4 | RCC_CFGR_PPRE2_DIV4 | RCC_CFGR_SW_PLL; + while ((RCC->CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SWS_PLL) + ; +} + + +/**************************************************************** + * Bootloader + ****************************************************************/ + +// Handle reboot requests +void +bootloader_request(void) +{ + try_request_canboot(); + dfu_reboot(); +} + + +/**************************************************************** + * Startup + ****************************************************************/ + +// Main entry point - called from armcm_boot.c:ResetHandler() +void +armcm_main(void) +{ + // Run SystemInit() and then restore VTOR + SystemInit(); + SCB->VTOR = (uint32_t)VectorTable; + + // Reset peripheral clocks (for some bootloaders that don't) + RCC->AHB1ENR = 0x00100000; + RCC->AHB2ENR = 0x00000000; + RCC->AHB3ENR = 0x00000000; + RCC->APB1ENR = 0x00000400; + RCC->APB2ENR = 0x00000000; + + dfu_reboot_check(); + + // STM32F7 specific DWT unlock required prior to timer_init() DWT setup. + CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; + DWT->LAR = 0xC5ACCE55; + + clock_setup(); + + sched_main(); +} |