Skip to content

Commit bb35cb5

Browse files
committed
STM32H753 Clock tree running at 400Mhz
What's Wrong: * CLock tree was incorrect in order and some values in BoardContext.cpp were incorrect. How Was it Fixed (if not obvious): * Human asking AI questions about hardware * Claude and Copolit getting hardware wrong * Human correcting AI from datasheet * AI and Human find the answer. What side effects does this have (could be none): * H7 boards boot but may be unstable when debugging gets such a huge change Which builds did you run to make sure they build? [ ] arm-none-eabi-gcc Cortex M4 [X] arm-none-eabi-gcc Cortex M7 [ ] (Apple) Native Clang [ ] (Apple) Homebrew GCC [ ] (Apple) Homebrew LLVM How Do We Know and Can Show It's Fixed: * Boots to main() Which Unittest Series did you Check? [ ] (Apple) Native Clang [ ] (Apple) Homebrew GCC [ ] (Apple) Homebrew LLVM Did this affect any on-target builds? If so which were tested? [ ] STM32F407VE board [X] STM32H753ZI board
1 parent dfc4357 commit bb35cb5

15 files changed

Lines changed: 215 additions & 98 deletions

File tree

boards/netduinoplus2/scripts/template.jdebug

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ void OnProjectLoad(void) {
22
//
33
// Dialog-generated settings
44
//
5-
Project.ConfigSemihosting("ModeBKPT=2");
65
Debug.SetResetMode(RM_RESET_HALT);
76
Project.SetTraceSource("SWO");
87
Project.SetDevice("STM32F405RG");

boards/nucleo_h753zi/scripts/template.jdebug

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ void OnProjectLoad(void) {
22
//
33
// Dialog-generated settings
44
//
5-
Project.ConfigSemihosting("ModeBKPT=2");
65
Debug.SetResetMode(RM_RESET_HALT);
76
Project.SetTraceSource("SWO");
87
Project.SetDevice("STM32H753ZI");

boards/nucleo_h753zi/source/BoardContext.cpp

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "lps35hw.hpp"
88
#include "lsm9ds1.hpp"
99
#include "segger/rtt.hpp"
10+
#include "stm32/h7xx/ResetAndClockControl.hpp"
1011
#include "strings.hpp"
1112

1213
namespace stm32 {
@@ -27,10 +28,10 @@ ClockConfiguration const default_clock_configuration = {
2728
/* .low_speed_external_oscillator_frequency = */ low_speed_external_oscillator_frequency,
2829
/* .voltage_scaling = */ 0b11, // VOS1 (up to 400 MHz without VOS0 boost)
2930
/* .d1_core_prescaler = */ 0b0000, // /1 (cpu_ck = sys_ck)
30-
/* .ahb_divider = */ 0b0000, // /1 (hclk = sys_ck)
31+
/* .ahb_divider = */ 0b1000, // /2 (hclk3 = sys_ck/2)
3132
/* .apb1_low_speed_divider = */ 0b101, // /4
3233
/* .apb2_high_speed_divider = */ 0b100, // /2
33-
/* .apb3_divider = */ 0b100, // /2
34+
/* .apb3_divider = */ 0b100, // /2 (apb3 = hclk3/2)
3435
/* .apb4_divider = */ 0b100, // /2
3536
/* .mcu_clock1_divider = */ 0b111, // /5
3637
/* .mcu_clock2_divider = */ 0b111, // /5
@@ -206,23 +207,33 @@ core::Status BoardContext::Initialize(void) {
206207
.SetOutputType(stm32::gpio::OutputType::PushPull);
207208

208209
stm32::h7xx::ResetAndClockControl::AHB1PeripheralClockEnable ahb1_enable;
210+
stm32::h7xx::ResetAndClockControl::AHB1PeripheralReset ahb1_reset;
209211
stm32::h7xx::ResetAndClockControl::AHB2PeripheralClockEnable ahb2_enable;
212+
stm32::h7xx::ResetAndClockControl::AHB2PeripheralReset ahb2_reset;
210213
stm32::h7xx::ResetAndClockControl::APB1LowClockEnable apb1_enable;
211214
stm32::h7xx::ResetAndClockControl::APB2PeripheralClockEnable apb2_enable;
212215

216+
// Reset the AHB1 peripherals
217+
ahb1_reset = stm32::h7xx::reset_and_clock_control.ahb1_peripheral_reset; // read
218+
ahb1_reset.bits.dma1_reset = 1U;
219+
ahb1_reset.bits.dma2_reset = 1U;
220+
stm32::h7xx::reset_and_clock_control.ahb1_peripheral_reset = ahb1_reset; // write
221+
ahb1_reset.bits.dma1_reset = 0U;
222+
ahb1_reset.bits.dma2_reset = 0U;
223+
stm32::h7xx::reset_and_clock_control.ahb1_peripheral_reset = ahb1_reset; // write
224+
225+
// Reset the AHB2 peripherals
226+
ahb2_reset = stm32::h7xx::reset_and_clock_control.ahb2_peripheral_reset; // read
227+
ahb2_reset.bits.random_number_generator_reset = 1U;
228+
stm32::h7xx::reset_and_clock_control.ahb2_peripheral_reset = ahb2_reset; // write
229+
ahb2_reset.bits.random_number_generator_reset = 0U;
230+
stm32::h7xx::reset_and_clock_control.ahb2_peripheral_reset = ahb2_reset; // write
231+
213232
// Enable the RNG in the AHB2 Periperhals
214233
ahb2_enable = stm32::h7xx::reset_and_clock_control.ahb2_peripheral_clock_enable; // read
215234
ahb2_enable.bits.random_number_generator_enable = 1U;
216235
stm32::h7xx::reset_and_clock_control.ahb2_peripheral_clock_enable = ahb2_enable; // write
217236

218-
// Reset the RNG
219-
stm32::h7xx::ResetAndClockControl::AHB2PeripheralReset reset;
220-
reset = stm32::h7xx::reset_and_clock_control.ahb2_peripheral_reset; // read
221-
reset.bits.random_number_generator_reset = 1U;
222-
stm32::h7xx::reset_and_clock_control.ahb2_peripheral_reset = reset; // write
223-
reset.bits.random_number_generator_reset = 0U;
224-
stm32::h7xx::reset_and_clock_control.ahb2_peripheral_reset = reset; // write
225-
226237
// enable the APB1 peripherals in the Reset and Clock Control register
227238
apb1_enable = stm32::h7xx::reset_and_clock_control.apb1_low_clock_enable; // read
228239
apb1_enable.bits.timer2_enable = 1U; // modify
@@ -242,22 +253,16 @@ core::Status BoardContext::Initialize(void) {
242253
apb2_enable.bits.spi1_enable = 1; // modify
243254
stm32::h7xx::reset_and_clock_control.apb2_peripheral_clock_enable = apb2_enable; // write
244255

245-
jarnax::print(
246-
"Feature Clock is %" PRIu32
247-
"\r\n"
248-
"APB1 Timer Clock is %" PRIu32
249-
"\r\n"
250-
"APB2 Timer Clock is %" PRIu32
251-
"\r\n"
252-
"APB1 Clock is %" PRIu32
253-
"\r\n"
254-
"APB2 Clock is %" PRIu32 "\r\n",
255-
stm32::GetClockTree().fclk.value(),
256-
stm32::GetClockTree().apb1_timer_clk.value(),
257-
stm32::GetClockTree().apb2_timer_clk.value(),
258-
stm32::GetClockTree().apb1_peripheral.value(),
259-
stm32::GetClockTree().apb2_peripheral.value()
260-
);
256+
jarnax::print("Feature Clock is %" PRIu32 "\r\n", stm32::GetClockTree().fclk.value());
257+
jarnax::print("APB1 Timer Clock is %" PRIu32 "\r\n", stm32::GetClockTree().apb1_timer_clk.value());
258+
jarnax::print("APB2 Timer Clock is %" PRIu32 "\r\n", stm32::GetClockTree().apb2_timer_clk.value());
259+
jarnax::print("APB1 Clock is %" PRIu32 "\r\n", stm32::GetClockTree().apb1_peripheral.value());
260+
jarnax::print("APB2 Clock is %" PRIu32 "\r\n", stm32::GetClockTree().apb2_peripheral.value());
261+
jarnax::print("APB3 Clock is %" PRIu32 "\r\n", stm32::GetClockTree().apb3_peripheral.value());
262+
jarnax::print("APB4 Clock is %" PRIu32 "\r\n", stm32::GetClockTree().apb4_peripheral.value());
263+
jarnax::print("AHB1 Clock is %" PRIu32 "\r\n", stm32::GetClockTree().ahb1_peripheral.value());
264+
jarnax::print("AHB2 Clock is %" PRIu32 "\r\n", stm32::GetClockTree().ahb2_peripheral.value());
265+
261266
do {
262267
// RNG
263268
status = random_number_generator_.Initialize();
@@ -281,7 +286,7 @@ core::Status BoardContext::Initialize(void) {
281286
// I2C2
282287
status = i2c2_driver_.Initialize(stm32::GetClockTree().apb1_peripheral, ::stm32::i2c2_bus_frequency);
283288
if (not status.IsSuccess()) {
284-
jarnax::print("I2C1 failed to initialize\r\n");
289+
jarnax::print("I2C2 failed to initialize\r\n");
285290
break;
286291
}
287292

boards/stm32_f4ve_v2/scripts/template.jdebug

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ void OnProjectLoad(void) {
22
//
33
// Dialog-generated settings
44
//
5-
Project.ConfigSemihosting("ModeBKPT=2");
65
Debug.SetResetMode(RM_RESET_HALT);
76
Project.SetTraceSource("SWO");
87
Project.SetDevice("STM32F407VE");
Binary file not shown.

modules/jarnax/source/configure.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ void ATTRIBUTE((used)) configure(void) {
2424

2525
jarnax::print("Vector Table @ %p\r\n", static_cast<void const *>(&cortex::vector_table));
2626
if constexpr (cortex::initialize_system_clocks) {
27+
// @FIXME this should work since the clock tree works, but doesn't link.
28+
// jarnax::print("Initializing Early Power\r\n");
29+
// vendor::initialize::early_power();
2730
jarnax::print("Initializing System Clocks\r\n");
2831
// each vendors clock tree is a unique and confusing flower, let them deal with it!
2932
vendor::initialize::clocks();

modules/stm32/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
add_module(NAME stm32
22
SOURCES
33
${CMAKE_CURRENT_SOURCE_DIR}/source/stm32f4xx/vectors.cpp
4+
${CMAKE_CURRENT_SOURCE_DIR}/source/stm32f4xx/power.cpp
45
${CMAKE_CURRENT_SOURCE_DIR}/source/stm32f4xx/clocks.cpp
56
${CMAKE_CURRENT_SOURCE_DIR}/source/gpio/Pin.cpp
67
${CMAKE_CURRENT_SOURCE_DIR}/source/Conversions.cpp
@@ -30,6 +31,7 @@ add_module(NAME stm32
3031
add_module(NAME stm32
3132
SOURCES
3233
${CMAKE_CURRENT_SOURCE_DIR}/source/stm32h7xx/vectors.cpp
34+
${CMAKE_CURRENT_SOURCE_DIR}/source/stm32h7xx/power.cpp
3335
${CMAKE_CURRENT_SOURCE_DIR}/source/stm32h7xx/clocks.cpp
3436
${CMAKE_CURRENT_SOURCE_DIR}/source/gpio/Pin.cpp
3537
${CMAKE_CURRENT_SOURCE_DIR}/source/Conversions.cpp

modules/stm32/include/stm32/Initialize.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ namespace stm32 {
1010
/// Used to initialize chip specific drivers which need to be brought up very early.
1111
namespace initialize {
1212

13+
/// @brief Initializes any Power needed to start the clock tree (e.g. enabling the voltage regulator)
14+
void early_power(void);
15+
1316
/// @brief The required Clock initialization for all STM32 chips
1417
void clocks(void);
1518

modules/stm32/include/stm32/h7xx/ResetAndClockControl.hpp

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,13 @@ struct ResetAndClockControl final {
307307
static_assert(sizeof(ClockRecoveryCalibrationControl) == 4UL, "Must be this exact size");
308308
/// RCC Clock Configuration Register (CFGR)
309309
struct Configuration final {
310+
/// System clock switch (SW)
311+
enum class SystemClockSwitch : uint32_t {
312+
HighSpeedInternalClock = 0b00, ///< (HSI_CLOCK)
313+
CalibratedSiliconInternalClock = 0b01, ///< (CSI_CLOCK)
314+
HighSpeedExternalClock = 0b10, ///< (HSE_CLOCK)
315+
PhaseLockLoopClock = 0b11, ///< (PLL_CLOCK)
316+
};
310317
/// Default Constructor
311318
Configuration()
312319
: whole{0u} {}
@@ -330,29 +337,29 @@ struct ResetAndClockControl final {
330337
/// The internal bitfield for the register
331338
struct Fields final {
332339
/// System clock switch (SW)
333-
uint32_t system_clock_switch : 3; // bits 0:2
340+
SystemClockSwitch system_clock_switch : 3; // bits 0:2
334341
/// System clock switch status (SWS)
335-
uint32_t system_clock_switch_status : 3; // bits 3:5
342+
SystemClockSwitch system_clock_switch_status : 3; // bits 3:5
336343
/// System clock selection after a wake up from system Stop (STOPWUCK)
337-
uint32_t stop_wakeup_clock : 1; // bit 6
344+
uint32_t stop_wakeup_clock : 1; // bit 6
338345
/// Kernel clock selection after a wake up from system Stop (STOPKERWUCK)
339-
uint32_t stop_kernel_wakeup_clock : 1; // bit 7
346+
uint32_t stop_kernel_wakeup_clock : 1; // bit 7
340347
/// HSE division factor for RTC clock (RTCPRE)
341-
uint32_t real_time_clock_prescaler : 6; // bits 8:13
348+
uint32_t real_time_clock_prescaler : 6; // bits 8:13
342349
/// High Resolution Timer clock prescaler selection (HRTIMSEL)
343-
uint32_t high_resolution_timer_select : 1; // bit 14
350+
uint32_t high_resolution_timer_select : 1; // bit 14
344351
/// Timers clocks prescaler selection (TIMPRE)
345-
uint32_t timers_clock_prescaler : 1; // bit 15
352+
uint32_t timers_clock_prescaler : 1; // bit 15
346353
/// (reserved)
347-
uint32_t : 2; // bits 16:17
354+
uint32_t : 2; // bits 16:17
348355
/// MCO1 prescaler (MCO1PRE)
349-
uint32_t mco1_prescaler : 4; // bits 18:21
356+
uint32_t mco1_prescaler : 4; // bits 18:21
350357
/// Micro-controller clock output 1 (MCO1SEL)
351-
uint32_t mco1_selection : 3; // bits 22:24
358+
uint32_t mco1_selection : 3; // bits 22:24
352359
/// MCO2 prescaler (MCO2PRE)
353-
uint32_t mco2_prescaler : 4; // bits 25:28
360+
uint32_t mco2_prescaler : 4; // bits 25:28
354361
/// Micro-controller clock output 2 (MCO2SEL)
355-
uint32_t mco2_selection : 3; // bits 29:31
362+
uint32_t mco2_selection : 3; // bits 29:31
356363
};
357364
//+=MEMORY======================================+
358365
union {
@@ -5970,11 +5977,11 @@ struct ResetAndClockControl final {
59705977

59715978
//+=MEMORY======================================+
59725979
/// clock control register (CR)
5973-
Control control; // offset 0x0UL
5980+
Control control; // offset 0x0UL
59745981
#if defined(STM32H7_REV_Y)
5975-
InternalClockSourcesCalibration internalclocksourcescalibration; // offset 0x4UL
5982+
InternalClockSourcesCalibration internal_clock_sources_calibration; // offset 0x4UL
59765983
#elif defined(STM32H7_REV_V)
5977-
HighSpeedInternalConfiguration highspeedinternalconfiguration; // offset 0x4UL
5984+
HighSpeedInternalConfiguration high_speed_internal_configuration; // offset 0x4UL
59785985
#endif
59795986
/// RCC Clock Recovery RC Register (CRRCR)
59805987
ClockRecoveryCalibrationControl clock_recovery_calibration_control; // offset 0x8UL
@@ -6016,12 +6023,12 @@ struct ResetAndClockControl final {
60166023
Domain3PeripheralClockSelection domain3_peripheral_clock_selection; // offset 0x58UL
60176024
uint32_t : 32; // offset 0x5cUL
60186025
/// RCC Clock Source Interrupt Enable Register (CIER)
6019-
ClockInterruptEnable clockinterruptenable; // offset 0x60UL
6026+
ClockInterruptEnable clock_interrupt_enable; // offset 0x60UL
60206027
/// RCC Clock Source Interrupt Flag Register (CIFR)
6021-
ClockInterruptFlags clockinterruptflags; // offset 0x64UL
6028+
ClockInterruptFlags clock_interrupt_flags; // offset 0x64UL
60226029
/// RCC Clock Source Interrupt Clear Register (CICR)
6023-
ClockInterruptClear clockinterruptclear; // offset 0x68UL
6024-
uint32_t : 32; // offset 0x6cUL
6030+
ClockInterruptClear clock_interrupt_clear; // offset 0x68UL
6031+
uint32_t : 32; // offset 0x6cUL
60256032
/// RCC Backup Domain Control Register (BDCR)
60266033
BackupDomainControl backup_domain_control; // offset 0x70UL
60276034
/// RCC Clock Control and Status Register (CSR)
@@ -6324,9 +6331,9 @@ static_assert(offsetof(ResetAndClockControl, domain1_peripheral_clock_selection)
63246331
static_assert(offsetof(ResetAndClockControl, domain2_peripheral_clock_selection1) == 0x50UL, "Must be located at this offset");
63256332
static_assert(offsetof(ResetAndClockControl, domain2_peripheral_clock_selection2) == 0x54UL, "Must be located at this offset");
63266333
static_assert(offsetof(ResetAndClockControl, domain3_peripheral_clock_selection) == 0x58UL, "Must be located at this offset");
6327-
static_assert(offsetof(ResetAndClockControl, clockinterruptenable) == 0x60UL, "Must be located at this offset");
6328-
static_assert(offsetof(ResetAndClockControl, clockinterruptflags) == 0x64UL, "Must be located at this offset");
6329-
static_assert(offsetof(ResetAndClockControl, clockinterruptclear) == 0x68UL, "Must be located at this offset");
6334+
static_assert(offsetof(ResetAndClockControl, clock_interrupt_enable) == 0x60UL, "Must be located at this offset");
6335+
static_assert(offsetof(ResetAndClockControl, clock_interrupt_flags) == 0x64UL, "Must be located at this offset");
6336+
static_assert(offsetof(ResetAndClockControl, clock_interrupt_clear) == 0x68UL, "Must be located at this offset");
63306337
static_assert(offsetof(ResetAndClockControl, backup_domain_control) == 0x70UL, "Must be located at this offset");
63316338
static_assert(offsetof(ResetAndClockControl, clock_control_status) == 0x74UL, "Must be located at this offset");
63326339
static_assert(offsetof(ResetAndClockControl, ahb3_peripheral_reset) == 0x7cUL, "Must be located at this offset");

modules/stm32/include/stm32/stm32h7xx.hpp

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ constexpr Hertz high_speed_internal_oscillator_frequency = 64_MHz;
3131
/// @brief The speed of the HSE oscillator on most STM32 parts
3232
constexpr Hertz low_speed_internal_oscillator_frequency = 32_KHz;
3333

34+
/// @brief The speed of the CSI oscillator on STM32H7 parts
35+
constexpr Hertz calibrated_silicon_internal_oscillator_frequency = 4_MHz;
36+
3437
/// The clock speed of the STM32H7xxxx
3538
constexpr Hertz top_clock_frequency = 480_MHz;
3639

@@ -328,23 +331,31 @@ struct ClockTree {
328331
Hertz low_speed_external;
329332
Hertz high_speed_internal;
330333
Hertz high_speed_external;
331-
Hertz pll_input; ///< The frequency of the input to the PLL
332-
Hertz pll_vco; ///< The frequency of the VCO
333-
Hertz pll_output; ///< The frequency of the PLL output
334-
Hertz sysclk; ///< the clock before the AHB/APB divider
335-
Hertz eth_ptp; ///< The frequency of the Ethernet PTP clock
336-
Hertz fclk; ///< The frequency of the cortex free running clock
337-
Hertz hclk; ///< The frequency of the AHB bus, DMA and Core Memory (HCLK)
338-
Hertz system_timer; ///< The frequency of the Cortex SYSTICK
339-
Hertz apb1_peripheral; ///< The frequency of the APB1 bus (low speed)
340-
Hertz apb2_peripheral; ///< The frequency of the APB2 bus (high speed)
334+
Hertz pll_input; ///< The frequency of the input to the PLL
335+
Hertz pll_vco; ///< The frequency of the VCO
336+
Hertz pll_output; ///< The frequency of the PLL output
337+
Hertz sysclk; ///< the clock before the D1CPRE dividers
338+
Hertz fclk; ///< The frequency of the cortex free running clock
339+
Hertz hclk; ///< The frequency of the AHB bus (HCLK in D1, HCLK1 in D2, HCLK3 in D3, and HCLK in D1)
340+
Hertz system_timer; ///< The frequency of the Cortex SYSTICK is the CPU clock divided by 8 (HCLK/8)
341+
Hertz apb1_peripheral; ///< The frequency of the APB1 bus (low speed in D2)
342+
Hertz apb2_peripheral; ///< The frequency of the APB2 bus (high speed in D2)
343+
Hertz apb3_peripheral; ///< The frequency of the APB3 bus (in D1)
344+
Hertz apb4_peripheral; ///< The frequency of the APB4 bus (in D3)
345+
Hertz ahb1_peripheral; ///< The frequency of the AHB1 peripheral clock (HCLK1 in D2)
346+
Hertz ahb2_peripheral; ///< The frequency of the AHB2 peripheral clock (HCLK2 == HCLK1 in D2)
347+
Hertz ahb3_peripheral; ///< The frequency of the HCLK3 peripheral clock (HCLK3 in D1)
348+
Hertz ahb4_peripheral; ///< The frequency of the HCLK4 peripheral clock (HCLK4 in D3)
349+
Hertz apb1_timer_clk; ///< The frequency of the TIMx clocks (TIMxCLK)
350+
Hertz apb2_timer_clk; ///< The frequency of the TIMx clocks (TIMxCLK)
351+
Hertz high_resolution_timer_clk; ///< The frequency of the HRTIMx clocks (HRTIMxCLK)
352+
// Specific Peripheral Clocks
353+
Hertz eth_ptp; ///< The frequency of the Ethernet PTP clock
341354
Hertz pll_i2s;
342355
Hertz pll_48ck;
343356
Hertz rtc;
344357
Hertz rng;
345358
Hertz usbotg;
346-
Hertz apb1_timer_clk; ///< The frequency of the TIMx clocks (TIMxCLK)
347-
Hertz apb2_timer_clk; ///< The frequency of the TIMx clocks (TIMxCLK)
348359
};
349360

350361
/// @brief The STM32H7xxx clock configuration.

0 commit comments

Comments
 (0)