@@ 13,8 13,10 @@
inline void __attribute__((always_inline))
reg_write_bits_pos(volatile uint32_t *reg, uint32_t data, uint8_t pos,
uint32_t mask) {
- *reg &= ~(mask << pos);
- *reg |= (data & mask) << pos;
+ uint32_t val = *reg;
+ val &= ~(mask << pos);
+ val |= (data & mask) << pos;
+ *reg = val;
}
/**
@@ 25,8 27,10 @@ reg_write_bits_pos(volatile uint32_t *reg, uint32_t data, uint8_t pos,
*/
inline void __attribute__((always_inline)) reg_write_bits(volatile uint32_t *reg, uint32_t data,
uint32_t mask) {
- *reg &= ~(mask);
- *reg |= (data & mask);
+ uint32_t val = *reg;
+ val &= ~(mask);
+ val |= (data & mask);
+ *reg = val;
}
/**
@@ 275,11 275,54 @@ void main()
clocks_pll_enable(CLOCK_PLL2);
clocks_pll_wait_ready(CLOCK_PLL2, 300);
- /* clocks_pll_configure(CLOCK_PLL1, 1, 25, PLL_SOURCE_HSE, 200, 2, 2, 2); */
- /* clocks_pll_enable(CLOCK_PLL1); */
- /* clocks_pll_wait_ready(CLOCK_PLL1, 300); */
-
- /* clocks_system_clock_source(CLOCK_SOURCE_PLL_1_P_CK, 1, 1, 1, 300); */
+ // 1. Set pwr configuration
+ reg_write_bits(&PWR->CR3,
+ (1 << PWR_CR3_SMPSEN_Pos) | (0 << PWR_CR3_LDOEN_Msk) |
+ (0 << PWR_CR3_BYPASS_Msk),
+ PWR_CR3_LDOEN_Msk | PWR_CR3_SMPSEN_Msk | PWR_CR3_BYPASS_Msk);
+
+ // 2. Verify pwr configuration. If not working, stay here looping!
+ // NOTE: this probably means you need to power cycle the board. The
+ // configuration can be written only when the chip has just been connected.
+ while (!(PWR->CR3 & PWR_CR3_SMPSEN) || (PWR->CR3 & PWR_CR3_LDOEN) || (PWR->CR3 & PWR_CR3_BYPASS));
+
+ // 3. Change VOS
+ // 3.1. Check current configuration (VOS 3)
+ while (!(PWR->CSR1 & PWR_CSR1_ACTVOSRDY));
+
+ // 3.2. VOS 1 transition
+ reg_write_bits(&PWR->D3CR, (11 << PWR_D3CR_VOS_Pos), PWR_D3CR_VOS_Msk);
+ while (!(PWR->CSR1 & PWR_D3CR_VOSRDY));
+
+ // 3.3. VOS 0 transition
+ reg_set_bits(&SYSCFG->PWRCR, SYSCFG_PWRCR_ODEN);
+ while (!(PWR->CSR1 & PWR_D3CR_VOSRDY));
+
+ // 25 MHz / 10 -> 2.5 MHz * 384 = 960 MHz (FVCO)
+ // PLL1_P = 960 / 2 => 480 MHz
+ clocks_pll_configure(CLOCK_PLL1, 0, 10, PLL_SOURCE_HSE, 384, 2, 0, 0);
+ clocks_pll_enable(CLOCK_PLL1);
+ clocks_pll_wait_ready(CLOCK_PLL1, 300);
+
+ // Flash setup
+ /* uint32_t sysck_freq_hz = 480000000; // 480 MHz */
+ /* uint32_t d1cpre_freq_hz = sysck_freq_hz / 1; // 480 Mhz */
+ /* uint32_t rcc_hclk = d1cpre_freq_hz / 2; // 240 MHz */
+
+ // 240 MHz means wait states = 4, progr delay = 2
+ reg_write_bits(&FLASH->ACR,
+ (2 << FLASH_ACR_WRHIGHFREQ_Pos) | (4 << FLASH_ACR_LATENCY_Pos),
+ FLASH_ACR_WRHIGHFREQ_Msk | FLASH_ACR_LATENCY_Msk);
+ while (((FLASH->ACR & FLASH_ACR_LATENCY_Msk) >> FLASH_ACR_LATENCY_Pos) != 4);
+
+ // D1CPRE = sysck / 1 => 480 MHz, HPRE = sysck / 2 => 240 MHz
+ reg_write_bits(&RCC->D1CFGR,
+ (0 << RCC_D1CFGR_D1CPRE_Pos) | (1 << RCC_D1CFGR_HPRE_Pos) |
+ (0 << RCC_D1CFGR_D1CPRE_Pos),
+ RCC_D1CFGR_D1CPRE_Msk | RCC_D1CFGR_HPRE_Msk | RCC_D1CFGR_D1CPRE_Msk);
+
+ // Sysck = PLL1_P
+ clocks_system_clock_source(CLOCK_SOURCE_PLL_1_P_CK, 1, 1, 1, 300);
fmc_t fmc;
init_fmc(&fmc);