|
26 | 26 |
|
27 | 27 | #include <nuttx/config.h> |
28 | 28 |
|
| 29 | +#include <assert.h> |
| 30 | + |
29 | 31 | #include <arch/board/board.h> |
30 | 32 |
|
31 | 33 | #include "arm_internal.h" |
|
34 | 36 | #include "hardware/stm32_flash.h" |
35 | 37 | #include "hardware/stm32u3xx_pwr.h" |
36 | 38 |
|
| 39 | +/**************************************************************************** |
| 40 | + * Pre-processor Definitions |
| 41 | + ****************************************************************************/ |
| 42 | + |
| 43 | +#ifndef CONFIG_ARCH_BOARD_STM32_CUSTOM_CLOCKCONFIG |
| 44 | + |
| 45 | +static_assert(CONFIG_BOARD_LOOPSPERMSEC != -1, |
| 46 | + "Configure BOARD_LOOPSPERMSEC to a non-default value"); |
| 47 | + |
| 48 | +/* Allow up to 100 milliseconds for each clock or regulator transition. */ |
| 49 | + |
| 50 | +#define CLOCK_READY_TIMEOUT (100 * CONFIG_BOARD_LOOPSPERMSEC) |
| 51 | + |
| 52 | +#ifndef STM32_BOARD_USEMSIS |
| 53 | +# error stm32_stdclockconfig() requires MSIS board configuration |
| 54 | +#endif |
| 55 | + |
| 56 | +#endif |
| 57 | + |
37 | 58 | /**************************************************************************** |
38 | 59 | * Public Functions |
39 | 60 | ****************************************************************************/ |
|
42 | 63 | * Name: stm32_stdclockconfig |
43 | 64 | * |
44 | 65 | * Description: |
45 | | - * Configure the STM32U3 system clock from MSIRC0 at 96 MHz. |
| 66 | + * Configure the STM32U3 system clock from the settings in board.h. |
46 | 67 | * |
47 | 68 | ****************************************************************************/ |
48 | 69 |
|
| 70 | +#ifndef CONFIG_ARCH_BOARD_STM32_CUSTOM_CLOCKCONFIG |
49 | 71 | void stm32_stdclockconfig(void) |
50 | 72 | { |
51 | 73 | uint32_t regval; |
| 74 | + volatile int32_t timeout; |
52 | 75 |
|
53 | 76 | /* The EPOD booster and voltage scaling control require the PWR clock. */ |
54 | 77 |
|
55 | 78 | modifyreg32(STM32_RCC_AHB1ENR2, 0, RCC_AHB1ENR2_PWREN); |
56 | 79 |
|
57 | | - /* Supply the EPOD booster from undivided MSIS. */ |
| 80 | + /* Select the board regulator and wait until the transition completes. */ |
| 81 | + |
| 82 | + modifyreg32(STM32_PWR_CR3, PWR_CR3_REGSEL, STM32_PWR_CR3_REGSEL); |
| 83 | + for (timeout = CLOCK_READY_TIMEOUT; timeout > 0; timeout--) |
| 84 | + { |
| 85 | + if ((getreg32(STM32_PWR_SVMSR) & PWR_SVMSR_REGS) == |
| 86 | + STM32_PWR_CR3_REGSEL) |
| 87 | + { |
| 88 | + break; |
| 89 | + } |
| 90 | + } |
| 91 | + |
| 92 | + if (timeout == 0) |
| 93 | + { |
| 94 | + return; |
| 95 | + } |
| 96 | + |
| 97 | + /* Configure and enable the EPOD booster. */ |
58 | 98 |
|
59 | 99 | regval = getreg32(STM32_RCC_CFGR4); |
60 | 100 | regval &= ~(RCC_CFGR4_BOOSTSEL_MASK | RCC_CFGR4_BOOSTDIV_MASK); |
61 | | - regval |= RCC_CFGR4_BOOSTSEL_MSIS; |
| 101 | + regval |= STM32_RCC_CFGR4_BOOSTSEL | STM32_RCC_CFGR4_BOOSTDIV; |
62 | 102 | putreg32(regval, STM32_RCC_CFGR4); |
63 | 103 |
|
64 | | - modifyreg32(STM32_PWR_VOSR, 0, PWR_VOSR_BOOSTEN); |
65 | | - while ((getreg32(STM32_PWR_VOSR) & PWR_VOSR_BOOSTRDY) == 0) |
| 104 | + modifyreg32(STM32_PWR_VOSR, 0, STM32_PWR_VOSR_BOOST); |
| 105 | + for (timeout = CLOCK_READY_TIMEOUT; timeout > 0; timeout--) |
| 106 | + { |
| 107 | + if ((getreg32(STM32_PWR_VOSR) & PWR_VOSR_BOOSTRDY) != 0) |
| 108 | + { |
| 109 | + break; |
| 110 | + } |
| 111 | + } |
| 112 | + |
| 113 | + if (timeout == 0) |
66 | 114 | { |
| 115 | + return; |
67 | 116 | } |
68 | 117 |
|
69 | | - /* Select voltage scale 1 and wait until it is active. */ |
| 118 | + /* Select the board voltage scale and wait until it is active. */ |
| 119 | + |
| 120 | + modifyreg32(STM32_PWR_VOSR, PWR_VOSR_R1EN | PWR_VOSR_R2EN, |
| 121 | + STM32_PWR_VOSR_RANGE); |
| 122 | + for (timeout = CLOCK_READY_TIMEOUT; timeout > 0; timeout--) |
| 123 | + { |
| 124 | + if ((getreg32(STM32_PWR_VOSR) & |
| 125 | + (PWR_VOSR_R1RDY | PWR_VOSR_R2RDY)) == |
| 126 | + STM32_PWR_VOSR_RANGERDY) |
| 127 | + { |
| 128 | + break; |
| 129 | + } |
| 130 | + } |
70 | 131 |
|
71 | | - modifyreg32(STM32_PWR_VOSR, PWR_VOSR_R2EN, PWR_VOSR_R1EN); |
72 | | - while ((getreg32(STM32_PWR_VOSR) & |
73 | | - (PWR_VOSR_R1RDY | PWR_VOSR_R2RDY)) != PWR_VOSR_R1RDY) |
| 132 | + if (timeout == 0) |
74 | 133 | { |
| 134 | + return; |
75 | 135 | } |
76 | 136 |
|
77 | | - /* Three wait states are required before raising HCLK to 96 MHz. */ |
| 137 | + /* Configure FLASH before raising HCLK. */ |
78 | 138 |
|
79 | 139 | modifyreg32(STM32_FLASH_ACR, FLASH_ACR_LATENCY_MASK, |
80 | | - FLASH_ACR_LATENCY(3)); |
| 140 | + STM32_FLASH_ACR_LATENCY); |
81 | 141 |
|
82 | | - /* Select MSIRC0 divided by one and use it as the 96 MHz system clock. */ |
| 142 | + /* Configure and start MSIS. */ |
83 | 143 |
|
84 | 144 | regval = getreg32(STM32_RCC_ICSCR1); |
85 | 145 | regval &= ~(RCC_ICSCR1_MSISSEL | RCC_ICSCR1_MSISDIV_MASK); |
86 | | - regval |= RCC_ICSCR1_MSIRGSEL; |
| 146 | + regval |= RCC_ICSCR1_MSIRGSEL | STM32_RCC_ICSCR1_MSISSEL | |
| 147 | + STM32_RCC_ICSCR1_MSISDIV; |
87 | 148 | putreg32(regval, STM32_RCC_ICSCR1); |
88 | 149 |
|
89 | 150 | modifyreg32(STM32_RCC_CR, 0, RCC_CR_MSISON); |
90 | | - while ((getreg32(STM32_RCC_CR) & RCC_CR_MSISRDY) == 0) |
| 151 | + for (timeout = CLOCK_READY_TIMEOUT; timeout > 0; timeout--) |
91 | 152 | { |
| 153 | + if ((getreg32(STM32_RCC_CR) & RCC_CR_MSISRDY) != 0) |
| 154 | + { |
| 155 | + break; |
| 156 | + } |
92 | 157 | } |
93 | 158 |
|
94 | | - modifyreg32(STM32_RCC_CFGR1, RCC_CFGR1_SW_MASK, RCC_CFGR1_SW_MSIS); |
95 | | - while ((getreg32(STM32_RCC_CFGR1) & RCC_CFGR1_SWS_MASK) != |
96 | | - RCC_CFGR1_SWS_MSIS) |
| 159 | + if (timeout == 0) |
97 | 160 | { |
| 161 | + return; |
98 | 162 | } |
99 | 163 |
|
100 | | - /* Keep all bus clocks undivided. */ |
| 164 | + /* Configure the AHB and APB prescalers. */ |
101 | 165 |
|
102 | 166 | modifyreg32(STM32_RCC_CFGR2, |
103 | 167 | RCC_CFGR2_HPRE_MASK | RCC_CFGR2_PPRE1_MASK | |
104 | | - RCC_CFGR2_PPRE2_MASK, 0); |
105 | | - modifyreg32(STM32_RCC_CFGR3, RCC_CFGR3_PPRE3_MASK, 0); |
| 168 | + RCC_CFGR2_PPRE2_MASK, |
| 169 | + STM32_RCC_CFGR2_HPRE | STM32_RCC_CFGR2_PPRE1 | |
| 170 | + STM32_RCC_CFGR2_PPRE2); |
| 171 | + modifyreg32(STM32_RCC_CFGR3, RCC_CFGR3_PPRE3_MASK, |
| 172 | + STM32_RCC_CFGR3_PPRE3); |
| 173 | + |
| 174 | + /* Use MSIS as the system clock and wait for the switch to complete. */ |
| 175 | + |
| 176 | + modifyreg32(STM32_RCC_CFGR1, RCC_CFGR1_SW_MASK, RCC_CFGR1_SW_MSIS); |
| 177 | + for (timeout = CLOCK_READY_TIMEOUT; timeout > 0; timeout--) |
| 178 | + { |
| 179 | + if ((getreg32(STM32_RCC_CFGR1) & RCC_CFGR1_SWS_MASK) == |
| 180 | + RCC_CFGR1_SWS_MSIS) |
| 181 | + { |
| 182 | + break; |
| 183 | + } |
| 184 | + } |
106 | 185 | } |
| 186 | +#endif |
107 | 187 |
|
108 | 188 | /**************************************************************************** |
109 | 189 | * Name: stm32_rcc_enableperipherals |
|
0 commit comments