stm32: sync stm32h7 and Kconfig updates from Klipper

Signed-off-by:  Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
Eric Callahan 2025-05-31 05:37:31 -04:00
parent fcb2f84553
commit 94e4255d32
No known key found for this signature in database
GPG Key ID: 5A1EB336DFB4C71B
2 changed files with 69 additions and 87 deletions

View File

@ -375,7 +375,7 @@ choice
select CANSERIAL
config STM32_CANBUS_PA11_PA12_REMAP
bool "CAN bus (on PA9/PA10)" if LOW_LEVEL_OPTIONS
depends on HAVE_STM32_CANBUS && MACH_STM32F042
depends on MACH_STM32F042
select CANSERIAL
config STM32_CANBUS_PA11_PB9
bool "CAN bus (on PA11/PB9)"
@ -387,15 +387,15 @@ choice
select CANSERIAL
config STM32_MMENU_CANBUS_PI9_PH13
bool "CAN bus (on PI9/PH13)" if LOW_LEVEL_OPTIONS
depends on HAVE_STM32_CANBUS && MACH_STM32F4
depends on (MACH_STM32F4 && HAVE_STM32_CANBUS)
select CANSERIAL
config STM32_MMENU_CANBUS_PB5_PB6
bool "CAN bus (on PB5/PB6)" if LOW_LEVEL_OPTIONS
depends on (HAVE_STM32_CANBUS && MACH_STM32F4) || (HAVE_STM32_FDCANBUS && MACH_STM32G0B1)
depends on (MACH_STM32F4 && HAVE_STM32_CANBUS) || (HAVE_STM32_FDCANBUS && MACH_STM32G0B1)
select CANSERIAL
config STM32_MMENU_CANBUS_PB12_PB13
bool "CAN bus (on PB12/PB13)" if LOW_LEVEL_OPTIONS
depends on (HAVE_STM32_CANBUS && MACH_STM32F4) || HAVE_STM32_FDCANBUS
depends on (MACH_STM32F4 && HAVE_STM32_CANBUS) || HAVE_STM32_FDCANBUS
select CANSERIAL
config STM32_MMENU_CANBUS_PD0_PD1
bool "CAN bus (on PD0/PD1)" if LOW_LEVEL_OPTIONS
@ -428,13 +428,13 @@ choice
bool "CAN bus (on PB8/PB9)"
config STM32_CMENU_CANBUS_PI9_PH13
bool "CAN bus (on PI9/PH13)"
depends on HAVE_STM32_CANBUS && MACH_STM32F4
depends on (MACH_STM32F4 && HAVE_STM32_CANBUS)
config STM32_CMENU_CANBUS_PB5_PB6
bool "CAN bus (on PB5/PB6)"
depends on (HAVE_STM32_CANBUS && MACH_STM32F4) || (HAVE_STM32_FDCANBUS && MACH_STM32G0B1)
depends on (MACH_STM32F4 && HAVE_STM32_CANBUS) || (HAVE_STM32_FDCANBUS && MACH_STM32G0B1)
config STM32_CMENU_CANBUS_PB12_PB13
bool "CAN bus (on PB12/PB13)"
depends on (HAVE_STM32_CANBUS && MACH_STM32F4) || HAVE_STM32_FDCANBUS
depends on (MACH_STM32F4 && HAVE_STM32_CANBUS) || HAVE_STM32_FDCANBUS
config STM32_CMENU_CANBUS_PD0_PD1
bool "CAN bus (on PD0/PD1)"
depends on HAVE_STM32_CANBUS || HAVE_STM32_FDCANBUS

View File

@ -49,6 +49,10 @@ lookup_clock_line(uint32_t periph_base)
uint32_t bit = 1 << ((periph_base - D2_APB2PERIPH_BASE) / 0x400);
return (struct cline){.en=&RCC->APB2ENR, .rst=&RCC->APB2RSTR, .bit=bit};
} else {
if (periph_base == FDCAN2_BASE)
// FDCAN1 and FDCAN2 share same clock enable
return (struct cline){.en=&RCC->APB1HENR, .rst=&RCC->APB1HRSTR,
.bit = RCC_APB1HENR_FDCANEN};
uint32_t offset = ((periph_base - D2_APB1PERIPH_BASE) / 0x400);
if (offset < 32) {
uint32_t bit = 1 << offset;
@ -86,123 +90,100 @@ DECL_CONSTANT_STR("RESERVE_PINS_crystal", "PH0,PH1");
static void
clock_setup(void)
{
#if !CONFIG_MACH_STM32H723
// Ensure USB OTG ULPI is not enabled
CLEAR_BIT(RCC->AHB1ENR, RCC_AHB1ENR_USB2OTGHSULPIEN);
CLEAR_BIT(RCC->AHB1LPENR, RCC_AHB1LPENR_USB2OTGHSULPILPEN);
#endif
// Set this despite correct defaults.
// "The software has to program the supply configuration in PWR control
// register 3" (pg. 259)
// Only a single write is allowed (pg. 304)
PWR->CR3 = (PWR->CR3 | PWR_CR3_LDOEN) & ~(PWR_CR3_BYPASS | PWR_CR3_SCUEN);
// Enable low dropout regulator
PWR->CR3 = PWR_CR3_LDOEN;
while (!(PWR->CSR1 & PWR_CSR1_ACTVOSRDY))
;
// (HSE 25mhz) /DIVM1(5) (pll_base 5Mhz) *DIVN1(192) (pll_freq 960Mhz)
// /DIVP1(2) (SYSCLK 480Mhz)
uint32_t pll_base = 5000000;
// Only even dividers (DIVP1) are allowed
uint32_t pll_freq = CONFIG_CLOCK_FREQ * 2;
// Setup pll1 frequency
uint32_t pll_base = CONFIG_STM32_CLOCK_REF_25M ? 5000000 : 4000000;
uint32_t pll_freq = CONFIG_CLOCK_FREQ * (CONFIG_MACH_STM32H723 ? 1 : 2);
uint32_t rcc_cr = RCC_CR_HSION;
if (!CONFIG_STM32_CLOCK_REF_INTERNAL) {
// Configure PLL from external crystal (HSE)
RCC->CR |= RCC_CR_HSEON;
RCC->CR = rcc_cr = rcc_cr | RCC_CR_HSEON;
while (!(RCC->CR & RCC_CR_HSERDY))
;
MODIFY_REG(RCC->PLLCKSELR, RCC_PLLCKSELR_PLLSRC_Msk,
RCC_PLLCKSELR_PLLSRC_HSE);
MODIFY_REG(RCC->PLLCKSELR, RCC_PLLCKSELR_DIVM1_Msk,
(CONFIG_CLOCK_REF_FREQ/pll_base) << RCC_PLLCKSELR_DIVM1_Pos);
RCC->PLLCKSELR = RCC_PLLCKSELR_PLLSRC_HSE
| ((CONFIG_CLOCK_REF_FREQ/pll_base) << RCC_PLLCKSELR_DIVM1_Pos);
} else {
// Configure PLL from internal 64Mhz oscillator (HSI)
// HSI frequency of 64Mhz is integer divisible with 4Mhz
pll_base = 4000000;
MODIFY_REG(RCC->PLLCKSELR, RCC_PLLCKSELR_PLLSRC_Msk,
RCC_PLLCKSELR_PLLSRC_HSI);
MODIFY_REG(RCC->PLLCKSELR, RCC_PLLCKSELR_DIVM1_Msk,
(64000000/pll_base) << RCC_PLLCKSELR_DIVM1_Pos);
RCC->PLLCKSELR = RCC_PLLCKSELR_PLLSRC_HSI
| ((64000000/pll_base) << RCC_PLLCKSELR_DIVM1_Pos);
}
// Set input frequency range of PLL1 according to pll_base
// 3 = 8-16Mhz, 2 = 4-8Mhz
MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLL1RGE_Msk, RCC_PLLCFGR_PLL1RGE_2);
// Disable unused PLL1 outputs
MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_DIVR1EN_Msk, 0);
// Enable PLL1Q and set to 100MHz for SPI 1,2,3
MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_DIVQ1EN, RCC_PLLCFGR_DIVQ1EN);
MODIFY_REG(RCC->PLL1DIVR, RCC_PLL1DIVR_Q1,
(pll_freq / FREQ_PERIPH - 1) << RCC_PLL1DIVR_Q1_Pos);
// This is necessary, default is not 1!
MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_DIVP1EN_Msk, RCC_PLLCFGR_DIVP1EN);
RCC->PLLCFGR = (2 << RCC_PLLCFGR_PLL1RGE_Pos)
// Enable PLL1Q (used by some peripherals)
| RCC_PLLCFGR_DIVQ1EN
// Enable PLL1P (for cpu clock)
| RCC_PLLCFGR_DIVP1EN;
// Set multiplier DIVN1 and post divider DIVP1
// 001 = /2, 010 = not allowed, 0011 = /4 ...
MODIFY_REG(RCC->PLL1DIVR, RCC_PLL1DIVR_N1_Msk,
(pll_freq/pll_base - 1) << RCC_PLL1DIVR_N1_Pos);
MODIFY_REG(RCC->PLL1DIVR, RCC_PLL1DIVR_P1_Msk,
(pll_freq/CONFIG_CLOCK_FREQ - 1) << RCC_PLL1DIVR_P1_Pos);
RCC->PLL1DIVR = ((pll_freq/pll_base - 1) << RCC_PLL1DIVR_N1_Pos)
// Set PLL1Q frequency (some peripherals directly use pll1_q_ck)
| ((pll_freq/FREQ_PERIPH - 1) << RCC_PLL1DIVR_Q1_Pos)
// Set PLL1P cpu clock frequency
| ((pll_freq/CONFIG_CLOCK_FREQ - 1) << RCC_PLL1DIVR_P1_Pos);
// Pwr
MODIFY_REG(PWR->D3CR, PWR_D3CR_VOS_Msk, PWR_D3CR_VOS);
// Enable VOS1 power mode (or VOS0 if freq>400Mhz)
if (CONFIG_MACH_STM32H723) {
PWR->D3CR = (CONFIG_CLOCK_FREQ > 400000000 ? 0 : 3) << PWR_D3CR_VOS_Pos;
while (!(PWR->D3CR & PWR_D3CR_VOSRDY))
;
} else {
PWR->D3CR = 3 << PWR_D3CR_VOS_Pos;
while (!(PWR->D3CR & PWR_D3CR_VOSRDY))
;
// Enable VOS0 (overdrive)
if (CONFIG_CLOCK_FREQ > 400000000) {
RCC->APB4ENR |= RCC_APB4ENR_SYSCFGEN;
#if !CONFIG_MACH_STM32H723
enable_pclock((uint32_t)SYSCFG);
#ifdef SYSCFG_PWRCR_ODEN
SYSCFG->PWRCR |= SYSCFG_PWRCR_ODEN;
#else
PWR->CR3 |= PWR_CR3_BYPASS;
#endif
while (!(PWR->D3CR & PWR_D3CR_VOSRDY))
;
}
}
SCB_EnableICache();
SCB_EnableDCache();
// Set flash latency according to clock frequency (pg.159)
// Set flash latency according to clock frequency
uint32_t flash_acr_latency = (CONFIG_CLOCK_FREQ > 450000000) ?
FLASH_ACR_LATENCY_4WS : FLASH_ACR_LATENCY_2WS;
MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY_Msk, flash_acr_latency);
MODIFY_REG(FLASH->ACR, FLASH_ACR_WRHIGHFREQ_Msk, FLASH_ACR_WRHIGHFREQ_1);
FLASH->ACR = flash_acr_latency | (2 << FLASH_ACR_WRHIGHFREQ_Pos);
while (!(FLASH->ACR & flash_acr_latency))
;
// Set HPRE, D1PPRE, D2PPRE, D2PPRE2, D3PPRE dividers
// 480MHz / 2 = 240MHz rcc_hclk3
MODIFY_REG(RCC->D1CFGR, RCC_D1CFGR_HPRE, RCC_D1CFGR_HPRE_3);
// 240MHz / 2 = 120MHz rcc_pclk3
MODIFY_REG(RCC->D1CFGR, RCC_D1CFGR_D1PPRE, RCC_D1CFGR_D1PPRE_DIV2);
// 240MHz / 2 = 120MHz rcc_pclk1
MODIFY_REG(RCC->D2CFGR, RCC_D2CFGR_D2PPRE1, RCC_D2CFGR_D2PPRE1_DIV2);
// 240MHz / 2 = 120MHz rcc_pclk2
MODIFY_REG(RCC->D2CFGR, RCC_D2CFGR_D2PPRE2, RCC_D2CFGR_D2PPRE2_DIV2);
// 240MHz / 2 = 120MHz rcc_pclk4
MODIFY_REG(RCC->D3CFGR, RCC_D3CFGR_D3PPRE, RCC_D3CFGR_D3PPRE_DIV2);
// Set HPRE clock to div 2 (CONFIG_CLOCK_FREQ/2) and set
// peripheral clocks another div 2 (CONFIG_CLOCK_FREQ/4)
RCC->D1CFGR = RCC_D1CFGR_HPRE_DIV2 | RCC_D1CFGR_D1PPRE_DIV2;
RCC->D2CFGR = RCC_D2CFGR_D2PPRE1_DIV2 | RCC_D2CFGR_D2PPRE2_DIV2;
RCC->D3CFGR = RCC_D3CFGR_D3PPRE_DIV2;
// Switch on PLL1
RCC->CR |= RCC_CR_PLL1ON;
RCC->CR = rcc_cr = rcc_cr | RCC_CR_PLL1ON;
while (!(RCC->CR & RCC_CR_PLL1RDY))
;
// Switch system clock source (SYSCLK) to PLL1
MODIFY_REG(RCC->CFGR, RCC_CFGR_SW_Msk, RCC_CFGR_SW_PLL1);
RCC->CFGR = RCC_CFGR_SW_PLL1;
while ((RCC->CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SWS_PLL1)
;
// Set the source of FDCAN clock
MODIFY_REG(RCC->D2CCIP1R, RCC_D2CCIP1R_FDCANSEL, RCC_D2CCIP1R_FDCANSEL_0);
// Set the source of FDCAN clock to pll1_q_ck
RCC->D2CCIP1R = 1 << RCC_D2CCIP1R_FDCANSEL_Pos;
// Configure HSI48 clock for USB
// Configure USB to use HSI48 clock
if (CONFIG_USB) {
SET_BIT(RCC->CR, RCC_CR_HSI48ON);
while((RCC->CR & RCC_CR_HSI48RDY) == 0);
SET_BIT(RCC->APB1HENR, RCC_APB1HENR_CRSEN);
SET_BIT(RCC->APB1HRSTR, RCC_APB1HRSTR_CRSRST);
CLEAR_BIT(RCC->APB1HRSTR, RCC_APB1HRSTR_CRSRST);
CLEAR_BIT(CRS->CFGR, CRS_CFGR_SYNCSRC);
SET_BIT(CRS->CR, CRS_CR_CEN | CRS_CR_AUTOTRIMEN);
CLEAR_BIT(RCC->D2CCIP2R, RCC_D2CCIP2R_USBSEL);
SET_BIT(RCC->D2CCIP2R, RCC_D2CCIP2R_USBSEL);
RCC->CR = rcc_cr = rcc_cr | RCC_CR_HSI48ON;
while ((RCC->CR & RCC_CR_HSI48RDY) == 0)
;
enable_pclock((uint32_t)CRS);
CRS->CFGR &= ~CRS_CFGR_SYNCSRC;
CRS->CR = (CRS->CR & CRS_CR_TRIM) | CRS_CR_CEN | CRS_CR_AUTOTRIMEN;
RCC->D2CCIP2R = RCC_D2CCIP2R_USBSEL;
}
}
@ -239,6 +220,7 @@ armcm_main(void)
RCC->APB2ENR = 0x00000000;
RCC->APB3ENR = 0x00000000;
RCC->APB4ENR = 0x00000000;
RCC->AHB1ENR = 0x00000000;
SCB->VTOR = (uint32_t)VectorTable;