I've been attempting to set the PLL clock frequency on a STM32H7B3 board, and I was able to do so by setting the DIVN multiplier (RCC_PLL1DIVR_N1) in the code below. The last time I was able to do this successfully was with the multiplier set to 1. When I tried downloading the code with multiplier set to 0x18F (= 399), I got the above error message. I now realize that the max I should have tried was probably DIVN = 280 due to the sys_ck specs, but nonetheless, the error happened upon downloading the code, not running it. I tried using the reset button, but to no avail. I now can't connect to the board and I don't know what else to try.
RCC -> CFGR &= 0; // Reset register
int32_t cfgr = RCC -> CFGR;
int32_t sws_pll1 = RCC_CFGR_SWS_PLL1;
int32_t status = cfgr & sws_pll1;
while (!status) {
cfgr = RCC -> CFGR;
sws_pll1 = RCC_CFGR_SWS_PLL1;
status = cfgr & sws_pll1;
} // System clock switch status: Wait until PLL1 is system clock; TODO: hangs*/
// RCC source control register
RCC->CR |= RCC_CR_HSION; // HSI clock enable
while (!(RCC->CR & RCC_CR_HSIRDY)); // Wait until HSI clock is ready
/* -------- PLL Config -------- */
// RCC PLLs clock source selection register
RCC -> PLLCKSELR |= RCC_PLLCKSELR_PLLSRC_HSI; // Select HSI as PLL clock source (hsi_ck)
// Note: Must have PLL1ON = 0 for modifying prescaler
RCC -> PLLCKSELR &= ~RCC_PLLCKSELR_DIVM1; // Reset prescaler for PLL1 to disabled
RCC -> PLLCKSELR |= RCC_PLLCKSELR_DIVM1_5; // Set prescaler for PLL1 to divsion by 32
// RCC PLL1 fractional divider register
RCC -> PLL1FRACR = 0; // Set FRACN to 0
// RCC PLLs configuration register
RCC -> PLLCFGR |= RCC_PLLCFGR_PLL1FRACEN; // PLL1 franctional latch enable
RCC -> PLLCFGR &= ~RCC_PLLCFGR_PLL1VCOSEL; // Select PLL1 output frequency range: wide VCO range from 128 to 560 MHz
RCC -> PLLCFGR |= RCC_PLLCFGR_PLL1RGE_3; // Select PLL1 input reference frequency range: between 8 and 16 MHz
// Note: Must have PLL1ON = 0 and PLL1RDY = 0 for enabling divider output
RCC -> PLLCFGR |= RCC_PLLCFGR_DIVP1EN; // PLL1 DIVP divider output enable
RCC -> PLLCFGR |= RCC_PLLCFGR_DIVQ1EN; // PLL1 DIVQ divider output enable
RCC -> PLLCFGR |= RCC_PLLCFGR_DIVR1EN; // PLL1 DIVR divider output enable
// RCC PLL1 dividers configuration register
// Note: Must have PLL1ON = 0 and PLL1RDY = 0 for writing bits
RCC -> PLL1DIVR &= 0; // Reset register
RCC -> PLL1DIVR |= (0x1 << RCC_PLL1DIVR_N1_Pos) & RCC_PLL1DIVR_N1; // DIVN = 0x18F = 399
RCC -> PLL1DIVR |= (0x1 << RCC_PLL1DIVR_P1_Pos) & RCC_PLL1DIVR_P1; // DIVP = 1
RCC -> PLL1DIVR |= (0x1 << RCC_PLL1DIVR_Q1_Pos) & RCC_PLL1DIVR_Q1; // DIVQ = 1
RCC -> PLL1DIVR |= (0x1 << RCC_PLL1DIVR_R1_Pos) & RCC_PLL1DIVR_R1; // DIVR = 1
// RCC source control register
RCC -> CR |= RCC_CR_PLL1ON; // PLL1 enable
//while((RCC -> CR & RCC_CR_PLL1RDY) == 0); // Wait until PLL1 clock is ready; TODO: hangs
Update: I ran JLinkSTM32, but it printed the following:
Connecting to J-Link via USB...O.K.
Using SWD as target interface.
Target interface speed: 1000 kHz.
VTarget = 3.299V
Reset target...O.K.
Reset option bytes to factory settings...
Option bytes reset to factory settings.
Resetting option bytes failed.
Press any key to exit.
Run the command line
JLinkSTM32.exe
utility (installed with the J-Flash tools), select option 9 (For STM32H7xxxx) and hope (takes a few nervous seconds).If successful, it may have bulk-erased the flash and will have reset the option bytes for the whole chip. It has got me out of a number of inexplicable lock-out situations not recoverable via the J-Flash GUI tool.