-
Notifications
You must be signed in to change notification settings - Fork 627
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
STM32H7 Power Configuration issues leading to general unreliability to start-up #2806
Comments
I had this issue for a while on the H747xi but managed to resolve it after much testing. Let me dig up the config I'm using. I have a spare NUCLEO-H743ZI2 which I can test for you if you like. |
This is the code I have configured for my custom board, which to be fair has an external oscillator, but I have equivalent C code which I can use t- get it running reliably. so i am trying to work out the difference. This is the config I have: let mut config = Config::default();
{
use embassy_stm32::rcc::*;
// config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.hsi = None; // Since we're using HSE
config.rcc.hse = Some(Hse { freq: mhz(20), mode: HseMode::Bypass});
config.rcc.csi = false;
config.rcc.pll1 = Some(Pll {
source: PllSource::HSE,
prediv: PllPreDiv::DIV2,
mul: PllMul::MUL32,
divp: Some(PllDiv::DIV2),
divq: Some(PllDiv::DIV8),
divr: Some(PllDiv::DIV2),
});
config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb3_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb4_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.voltage_scale = VoltageScale::Scale3;
config.rcc.supply_config = SupplyConfig::DirectSMPS;
}
let p = embassy_stm32::init(config); And this is the equivalent config generated from STMCube: void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Supply configuration update enable
*/
HAL_PWREx_ConfigSupply(PWR_DIRECT_SMPS_SUPPLY);
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);
while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
/** Macro to configure the PLL clock source
*/
__HAL_RCC_PLL_PLLSOURCE_CONFIG(RCC_PLLSOURCE_HSE);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 2;
RCC_OscInitStruct.PLL.PLLN = 32;
RCC_OscInitStruct.PLL.PLLP = 2;
RCC_OscInitStruct.PLL.PLLQ = 8;
RCC_OscInitStruct.PLL.PLLR = 2;
RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;
RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
RCC_OscInitStruct.PLL.PLLFRACN = 0;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
|RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
Error_Handler();
}
} |
When I read out the PWR.CR3 register just before waiting for VOSRDY, the configuration from STMCube sets the register up as I can only assume that the STMCube HAL is adding bloat and enabling those even though they arent specifically being used |
Also tested on both STM32h7hxi Arduino Portenta H7 & GIGA R1 WiFi and hits the full 480MHz and 1.21 giga-watts!! 0.000000 TRACE BDCR configured: 00008113
└─ embassy_stm32::rcc::bd::{impl#3}::init::{closure#4} @ /Users/mdesilva/.cargo/git/checkouts/embassy-9312dcb0ed774b29/49807c0/embassy-stm32/src/fmt.rs:117
0.000000 DEBUG rcc: Clocks { csi: Some(Hertz(4000000)), hclk1: Some(Hertz(240000000)), hclk2: Some(Hertz(240000000)), hclk3: Some(Hertz(240000000)), hclk4: Some(Hertz(240000000)), hse: None, hsi: Some(Hertz(64000000)), hsi48: Some(Hertz(48000000)), i2s_ckin: None, lse: None, lsi: None, pclk1: Some(Hertz(120000000)), pclk1_tim: Some(Hertz(240000000)), pclk2: Some(Hertz(120000000)), pclk2_tim: Some(Hertz(240000000)), pclk3: Some(Hertz(120000000)), pclk4: Some(Hertz(120000000)), pll1_q: Some(Hertz(120000000)), pll2_p: Some(Hertz(100000000)), pll2_q: None, pll2_r: None, pll3_p: None, pll3_q: None, pll3_r: None, rtc: Some(Hertz(32768)), sys: Some(Hertz(480000000)) } Use the following config: pub fn init() -> (embassy_stm32::Peripherals, cortex_m::Peripherals) {
let mut config = Config::default();
{
use embassy_stm32::rcc::*;
config.rcc.supply_config = SupplyConfig::LDO;
config.rcc.hsi = Some(HSIPrescaler::DIV1); // // 64MHz
config.rcc.csi = true;
config.rcc.hsi48 = Some(Hsi48Config {
sync_from_usb: true,
}); // needed for USB
#[cfg(feature = "stm32h747_400")]
{
config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50,
divp: Some(PllDiv::DIV2), // ((64/4)*50)/2 = 400MHz
divq: Some(PllDiv::DIV8), // ((64/4)*50)/8 = 100MHz / SPI1 cksel defaults to pll1_q
divr: None,
});
config.rcc.pll2 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV8,
mul: PllMul::MUL50,
divp: Some(PllDiv::DIV4), // ((64/8)*50)/4 = 100MHz
divq: None,
divr: None,
});
}
#[cfg(feature = "stm32h747_480")]
{
config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV8,
mul: PllMul::MUL120,
divp: Some(PllDiv::DIV2), // ((64/8)*120)/2 = 480MHz
divq: Some(PllDiv::DIV8), // ((64/8)*120)/8 = 120MHz / SPI1 cksel defaults to pll1_q
divr: None,
});
config.rcc.pll2 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV8,
mul: PllMul::MUL50,
divp: Some(PllDiv::DIV4), // ((64/8)*50)/4 = 100MHz
divq: None,
divr: None,
});
}
config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb3_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb4_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.voltage_scale = VoltageScale::Scale0;
let mut mux = rcc::mux::ClockMux::default();
mux.adcsel = rcc::mux::Adcsel::PLL2_P;
config.rcc.mux = mux;
// RTC
config.rcc.ls = LsConfig::default_lse();
trace!("Voltage::Scale{=i32}", config.rcc.voltage_scale as i32);
}
let p: embassy_stm32::Peripherals = embassy_stm32::init(config);
let core_peri = cortex_m::Peripherals::take().unwrap();
(p, core_peri)
} This is my config, I don't think I had much luck with |
Also, this works on the STM32h7hxi Arduino Portenta H7 |
I've found some instability in my power configuration for the STM32h7hxi and have shared https://github.com/bsodmike/stm32h747xi-embassy-uart-troubleshoot which can be flashed onto an Arduino Portenta H7. See REDME for details. If anyone has a working config for UART with |
I have tested the same This zephyr PR has some interesting comments and seems to have a working RCC config to get to 400 MHz. |
|
This is a placeholder issue to track the knowledge we have on why STM32H7's are so unreliable to start-up. all of my testing has been done on three different STM32H745 boards: a Nucleo, a Discovery board, and a custom in-house board. This is what I have found so far, and will update as I discover more:
!PWR.csr1().read().actvosrdy() {}
in thercc::init
function.The text was updated successfully, but these errors were encountered: