diff options
| -rw-r--r-- | embassy-rp/src/clocks.rs | 329 | ||||
| -rw-r--r-- | examples/rp/src/bin/overclock.rs | 8 | ||||
| -rw-r--r-- | examples/rp/src/bin/overclock_manual.rs | 10 | ||||
| -rw-r--r-- | examples/rp235x/src/bin/overclock.rs | 74 | ||||
| -rw-r--r-- | tests/rp/src/bin/overclock.rs | 49 |
5 files changed, 405 insertions, 65 deletions
diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs index 6694aab66..ea5e9362b 100644 --- a/embassy-rp/src/clocks.rs +++ b/embassy-rp/src/clocks.rs | |||
| @@ -38,7 +38,7 @@ | |||
| 38 | //! | 38 | //! |
| 39 | //! ## Examples | 39 | //! ## Examples |
| 40 | //! | 40 | //! |
| 41 | //! ### Standard 125MHz configuration | 41 | //! ### Standard 125MHz (rp2040) or 150Mhz (rp235x) configuration |
| 42 | //! ```rust,ignore | 42 | //! ```rust,ignore |
| 43 | //! let config = ClockConfig::crystal(12_000_000); | 43 | //! let config = ClockConfig::crystal(12_000_000); |
| 44 | //! ``` | 44 | //! ``` |
| @@ -136,43 +136,152 @@ pub enum PeriClkSrc { | |||
| 136 | // Gpin1 = ClkPeriCtrlAuxsrc::CLKSRC_GPIN1 as _ , | 136 | // Gpin1 = ClkPeriCtrlAuxsrc::CLKSRC_GPIN1 as _ , |
| 137 | } | 137 | } |
| 138 | 138 | ||
| 139 | /// Core voltage regulator settings for RP2040. | 139 | /// Core voltage regulator settings. |
| 140 | /// | 140 | /// |
| 141 | /// The RP2040 voltage regulator can be configured for different output voltages. | 141 | /// The voltage regulator can be configured for different output voltages. |
| 142 | /// Higher voltages allow for higher clock frequencies but increase power consumption and heat. | 142 | /// Higher voltages allow for higher clock frequencies but increase power consumption and heat. |
| 143 | #[cfg(feature = "rp2040")] | ||
| 144 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] | 143 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] |
| 145 | #[repr(u8)] | 144 | #[repr(u8)] |
| 146 | pub enum CoreVoltage { | 145 | pub enum CoreVoltage { |
| 147 | /// 0.80V - Suitable for lower frequencies | 146 | // RP2040 voltage levels |
| 147 | #[cfg(feature = "rp2040")] | ||
| 148 | /// RP2040: 0.80V | ||
| 148 | V0_80 = 0b0000, | 149 | V0_80 = 0b0000, |
| 149 | /// 0.85V | 150 | #[cfg(feature = "rp2040")] |
| 151 | /// RP2040: 0.85V | ||
| 150 | V0_85 = 0b0110, | 152 | V0_85 = 0b0110, |
| 151 | /// 0.90V | 153 | #[cfg(feature = "rp2040")] |
| 154 | /// RP2040: 0.90V | ||
| 152 | V0_90 = 0b0111, | 155 | V0_90 = 0b0111, |
| 153 | /// 0.95V | 156 | #[cfg(feature = "rp2040")] |
| 157 | /// RP2040: 0.95V | ||
| 154 | V0_95 = 0b1000, | 158 | V0_95 = 0b1000, |
| 155 | /// 1.00V | 159 | #[cfg(feature = "rp2040")] |
| 160 | /// RP2040: 1.00V | ||
| 156 | V1_00 = 0b1001, | 161 | V1_00 = 0b1001, |
| 157 | /// 1.05V | 162 | #[cfg(feature = "rp2040")] |
| 163 | /// RP2040: 1.05V | ||
| 158 | V1_05 = 0b1010, | 164 | V1_05 = 0b1010, |
| 159 | /// 1.10V - Default voltage level | 165 | #[cfg(feature = "rp2040")] |
| 166 | /// RP2040: 1.10V - Default voltage level | ||
| 160 | V1_10 = 0b1011, | 167 | V1_10 = 0b1011, |
| 161 | /// 1.15V - Required for overclocking to 133-200MHz | 168 | #[cfg(feature = "rp2040")] |
| 169 | /// RP2040: 1.15V - Required for overclocking to 133-200MHz | ||
| 162 | V1_15 = 0b1100, | 170 | V1_15 = 0b1100, |
| 163 | /// 1.20V | 171 | #[cfg(feature = "rp2040")] |
| 172 | /// RP2040: 1.20V | ||
| 164 | V1_20 = 0b1101, | 173 | V1_20 = 0b1101, |
| 165 | /// 1.25V | 174 | #[cfg(feature = "rp2040")] |
| 175 | /// RP2040: 1.25V | ||
| 166 | V1_25 = 0b1110, | 176 | V1_25 = 0b1110, |
| 167 | /// 1.30V | 177 | #[cfg(feature = "rp2040")] |
| 178 | /// RP2040: 1.30V | ||
| 168 | V1_30 = 0b1111, | 179 | V1_30 = 0b1111, |
| 180 | |||
| 181 | // RP235x voltage levels | ||
| 182 | #[cfg(feature = "_rp235x")] | ||
| 183 | /// RP235x: 0.55V | ||
| 184 | V0_55 = 0b00000, | ||
| 185 | #[cfg(feature = "_rp235x")] | ||
| 186 | /// RP235x: 0.60V | ||
| 187 | V0_60 = 0b00001, | ||
| 188 | #[cfg(feature = "_rp235x")] | ||
| 189 | /// RP235x: 0.65V | ||
| 190 | V0_65 = 0b00010, | ||
| 191 | #[cfg(feature = "_rp235x")] | ||
| 192 | /// RP235x: 0.70V | ||
| 193 | V0_70 = 0b00011, | ||
| 194 | #[cfg(feature = "_rp235x")] | ||
| 195 | /// RP235x: 0.75V | ||
| 196 | V0_75 = 0b00100, | ||
| 197 | #[cfg(feature = "_rp235x")] | ||
| 198 | /// RP235x: 0.80V | ||
| 199 | V0_80 = 0b00101, | ||
| 200 | #[cfg(feature = "_rp235x")] | ||
| 201 | /// RP235x: 0.85V | ||
| 202 | V0_85 = 0b00110, | ||
| 203 | #[cfg(feature = "_rp235x")] | ||
| 204 | /// RP235x: 0.90V | ||
| 205 | V0_90 = 0b00111, | ||
| 206 | #[cfg(feature = "_rp235x")] | ||
| 207 | /// RP235x: 0.95V | ||
| 208 | V0_95 = 0b01000, | ||
| 209 | #[cfg(feature = "_rp235x")] | ||
| 210 | /// RP235x: 1.00V | ||
| 211 | V1_00 = 0b01001, | ||
| 212 | #[cfg(feature = "_rp235x")] | ||
| 213 | /// RP235x: 1.05V | ||
| 214 | V1_05 = 0b01010, | ||
| 215 | #[cfg(feature = "_rp235x")] | ||
| 216 | /// RP235x: 1.10V - Default voltage level | ||
| 217 | V1_10 = 0b01011, | ||
| 218 | #[cfg(feature = "_rp235x")] | ||
| 219 | /// RP235x: 1.15V | ||
| 220 | V1_15 = 0b01100, | ||
| 221 | #[cfg(feature = "_rp235x")] | ||
| 222 | /// RP235x: 1.20V | ||
| 223 | V1_20 = 0b01101, | ||
| 224 | #[cfg(feature = "_rp235x")] | ||
| 225 | /// RP235x: 1.25V | ||
| 226 | V1_25 = 0b01110, | ||
| 227 | #[cfg(feature = "_rp235x")] | ||
| 228 | /// RP235x: 1.30V | ||
| 229 | V1_30 = 0b01111, | ||
| 230 | #[cfg(feature = "_rp235x")] | ||
| 231 | /// RP235x: 1.35V | ||
| 232 | V1_35 = 0b10000, | ||
| 233 | #[cfg(feature = "_rp235x")] | ||
| 234 | /// RP235x: 1.40V | ||
| 235 | V1_40 = 0b10001, | ||
| 236 | #[cfg(feature = "_rp235x")] | ||
| 237 | /// RP235x: 1.50V | ||
| 238 | V1_50 = 0b10010, | ||
| 239 | #[cfg(feature = "_rp235x")] | ||
| 240 | /// RP235x: 1.60V | ||
| 241 | V1_60 = 0b10011, | ||
| 242 | #[cfg(feature = "_rp235x")] | ||
| 243 | /// RP235x: 1.65V | ||
| 244 | V1_65 = 0b10100, | ||
| 245 | #[cfg(feature = "_rp235x")] | ||
| 246 | /// RP235x: 1.70V | ||
| 247 | V1_70 = 0b10101, | ||
| 248 | #[cfg(feature = "_rp235x")] | ||
| 249 | /// RP235x: 1.80V | ||
| 250 | V1_80 = 0b10110, | ||
| 251 | #[cfg(feature = "_rp235x")] | ||
| 252 | /// RP235x: 1.90V | ||
| 253 | V1_90 = 0b10111, | ||
| 254 | #[cfg(feature = "_rp235x")] | ||
| 255 | /// RP235x: 2.00V | ||
| 256 | V2_00 = 0b11000, | ||
| 257 | #[cfg(feature = "_rp235x")] | ||
| 258 | /// RP235x: 2.35V | ||
| 259 | V2_35 = 0b11001, | ||
| 260 | #[cfg(feature = "_rp235x")] | ||
| 261 | /// RP235x: 2.50V | ||
| 262 | V2_50 = 0b11010, | ||
| 263 | #[cfg(feature = "_rp235x")] | ||
| 264 | /// RP235x: 2.65V | ||
| 265 | V2_65 = 0b11011, | ||
| 266 | #[cfg(feature = "_rp235x")] | ||
| 267 | /// RP235x: 2.80V | ||
| 268 | V2_80 = 0b11100, | ||
| 269 | #[cfg(feature = "_rp235x")] | ||
| 270 | /// RP235x: 3.00V | ||
| 271 | V3_00 = 0b11101, | ||
| 272 | #[cfg(feature = "_rp235x")] | ||
| 273 | /// RP235x: 3.15V | ||
| 274 | V3_15 = 0b11110, | ||
| 275 | #[cfg(feature = "_rp235x")] | ||
| 276 | /// RP235x: 3.30V | ||
| 277 | V3_30 = 0b11111, | ||
| 169 | } | 278 | } |
| 170 | 279 | ||
| 171 | #[cfg(feature = "rp2040")] | ||
| 172 | impl CoreVoltage { | 280 | impl CoreVoltage { |
| 173 | /// Get the recommended Brown-Out Detection (BOD) setting for this voltage. | 281 | /// Get the recommended Brown-Out Detection (BOD) setting for this voltage. |
| 174 | /// Sets the BOD threshold to approximately 80% of the core voltage. | 282 | /// Sets the BOD threshold to approximately 80% of the core voltage. |
| 175 | fn recommended_bod(self) -> u8 { | 283 | fn recommended_bod(self) -> u8 { |
| 284 | #[cfg(feature = "rp2040")] | ||
| 176 | match self { | 285 | match self { |
| 177 | CoreVoltage::V0_80 => 0b0100, // 0.645V (~81% of 0.80V) | 286 | CoreVoltage::V0_80 => 0b0100, // 0.645V (~81% of 0.80V) |
| 178 | CoreVoltage::V0_85 => 0b0101, // 0.688V (~81% of 0.85V) | 287 | CoreVoltage::V0_85 => 0b0101, // 0.688V (~81% of 0.85V) |
| @@ -180,12 +289,38 @@ impl CoreVoltage { | |||
| 180 | CoreVoltage::V0_95 => 0b0111, // 0.774V (~81% of 0.95V) | 289 | CoreVoltage::V0_95 => 0b0111, // 0.774V (~81% of 0.95V) |
| 181 | CoreVoltage::V1_00 => 0b1000, // 0.817V (~82% of 1.00V) | 290 | CoreVoltage::V1_00 => 0b1000, // 0.817V (~82% of 1.00V) |
| 182 | CoreVoltage::V1_05 => 0b1000, // 0.817V (~78% of 1.05V) | 291 | CoreVoltage::V1_05 => 0b1000, // 0.817V (~78% of 1.05V) |
| 183 | CoreVoltage::V1_10 => 0b1001, // 0.860V (~78% of 1.10V) | 292 | CoreVoltage::V1_10 => 0b1001, // 0.860V (~78% of 1.10V), the default |
| 184 | CoreVoltage::V1_15 => 0b1010, // 0.903V (~79% of 1.15V) | 293 | CoreVoltage::V1_15 => 0b1010, // 0.903V (~79% of 1.15V) |
| 185 | CoreVoltage::V1_20 => 0b1011, // 0.946V (~79% of 1.20V) | 294 | CoreVoltage::V1_20 => 0b1011, // 0.946V (~79% of 1.20V) |
| 186 | CoreVoltage::V1_25 => 0b1100, // 0.989V (~79% of 1.25V) | 295 | CoreVoltage::V1_25 => 0b1100, // 0.989V (~79% of 1.25V) |
| 187 | CoreVoltage::V1_30 => 0b1101, // 1.032V (~79% of 1.30V) | 296 | CoreVoltage::V1_30 => 0b1101, // 1.032V (~79% of 1.30V) |
| 188 | } | 297 | } |
| 298 | #[cfg(feature = "_rp235x")] | ||
| 299 | match self { | ||
| 300 | CoreVoltage::V0_55 => 0b00001, // 0.516V (~94% of 0.55V) | ||
| 301 | CoreVoltage::V0_60 => 0b00010, // 0.559V (~93% of 0.60V) | ||
| 302 | CoreVoltage::V0_65 => 0b00011, // 0.602V (~93% of 0.65V) | ||
| 303 | CoreVoltage::V0_70 => 0b00011, // 0.602V (~86% of 0.70V) | ||
| 304 | CoreVoltage::V0_75 => 0b00100, // 0.645V (~86% of 0.75V) | ||
| 305 | CoreVoltage::V0_80 => 0b00101, // 0.688V (~86% of 0.80V) | ||
| 306 | CoreVoltage::V0_85 => 0b00110, // 0.731V (~86% of 0.85V) | ||
| 307 | CoreVoltage::V0_90 => 0b00110, // 0.731V (~81% of 0.90V) | ||
| 308 | CoreVoltage::V0_95 => 0b00111, // 0.774V (~81% of 0.95V) | ||
| 309 | CoreVoltage::V1_00 => 0b01000, // 0.817V (~82% of 1.00V) | ||
| 310 | CoreVoltage::V1_05 => 0b01000, // 0.817V (~78% of 1.05V) | ||
| 311 | CoreVoltage::V1_10 => 0b01001, // 0.860V (~78% of 1.10V), the default | ||
| 312 | CoreVoltage::V1_15 => 0b01001, // 0.860V (~75% of 1.15V) | ||
| 313 | CoreVoltage::V1_20 => 0b01010, // 0.903V (~75% of 1.20V) | ||
| 314 | CoreVoltage::V1_25 => 0b01010, // 0.903V (~72% of 1.25V) | ||
| 315 | CoreVoltage::V1_30 => 0b01011, // 0.946V (~73% of 1.30V) | ||
| 316 | CoreVoltage::V1_35 => 0b01011, // 0.946V (~70% of 1.35V) | ||
| 317 | CoreVoltage::V1_40 => 0b01100, // 0.989V (~71% of 1.40V) | ||
| 318 | CoreVoltage::V1_50 => 0b01101, // 1.032V (~69% of 1.50V) | ||
| 319 | CoreVoltage::V1_60 => 0b01110, // 1.075V (~67% of 1.60V) | ||
| 320 | CoreVoltage::V1_65 => 0b01110, // 1.075V (~65% of 1.65V) | ||
| 321 | CoreVoltage::V1_70 => 0b01111, // 1.118V (~66% of 1.70V) | ||
| 322 | _ => 0b10000, // the rp2350 datasheet repeats this value for all other core voltages | ||
| 323 | } | ||
| 189 | } | 324 | } |
| 190 | } | 325 | } |
| 191 | 326 | ||
| @@ -209,12 +344,10 @@ pub struct ClockConfig { | |||
| 209 | /// RTC clock configuration. | 344 | /// RTC clock configuration. |
| 210 | #[cfg(feature = "rp2040")] | 345 | #[cfg(feature = "rp2040")] |
| 211 | pub rtc_clk: Option<RtcClkConfig>, | 346 | pub rtc_clk: Option<RtcClkConfig>, |
| 212 | /// Core voltage scaling (RP2040 only). Defaults to 1.10V. | 347 | /// Core voltage scaling. Defaults to 1.10V. |
| 213 | #[cfg(feature = "rp2040")] | ||
| 214 | pub core_voltage: CoreVoltage, | 348 | pub core_voltage: CoreVoltage, |
| 215 | /// Voltage stabilization delay in microseconds. | 349 | /// Voltage stabilization delay in microseconds. |
| 216 | /// If not set, defaults will be used based on voltage level. | 350 | /// If not set, defaults will be used based on voltage level. |
| 217 | #[cfg(feature = "rp2040")] | ||
| 218 | pub voltage_stabilization_delay_us: Option<u32>, | 351 | pub voltage_stabilization_delay_us: Option<u32>, |
| 219 | // See above re gpin handling being commented out | 352 | // See above re gpin handling being commented out |
| 220 | // gpin0: Option<(u32, Gpin<'static, AnyPin>)>, | 353 | // gpin0: Option<(u32, Gpin<'static, AnyPin>)>, |
| @@ -250,9 +383,7 @@ impl Default for ClockConfig { | |||
| 250 | adc_clk: None, | 383 | adc_clk: None, |
| 251 | #[cfg(feature = "rp2040")] | 384 | #[cfg(feature = "rp2040")] |
| 252 | rtc_clk: None, | 385 | rtc_clk: None, |
| 253 | #[cfg(feature = "rp2040")] | ||
| 254 | core_voltage: CoreVoltage::V1_10, | 386 | core_voltage: CoreVoltage::V1_10, |
| 255 | #[cfg(feature = "rp2040")] | ||
| 256 | voltage_stabilization_delay_us: None, | 387 | voltage_stabilization_delay_us: None, |
| 257 | // See above re gpin handling being commented out | 388 | // See above re gpin handling being commented out |
| 258 | // gpin0: None, | 389 | // gpin0: None, |
| @@ -323,9 +454,7 @@ impl ClockConfig { | |||
| 323 | div_frac: 0, | 454 | div_frac: 0, |
| 324 | phase: 0, | 455 | phase: 0, |
| 325 | }), | 456 | }), |
| 326 | #[cfg(feature = "rp2040")] | ||
| 327 | core_voltage: CoreVoltage::V1_10, // Use hardware default (1.10V) | 457 | core_voltage: CoreVoltage::V1_10, // Use hardware default (1.10V) |
| 328 | #[cfg(feature = "rp2040")] | ||
| 329 | voltage_stabilization_delay_us: None, | 458 | voltage_stabilization_delay_us: None, |
| 330 | // See above re gpin handling being commented out | 459 | // See above re gpin handling being commented out |
| 331 | // gpin0: None, | 460 | // gpin0: None, |
| @@ -368,9 +497,7 @@ impl ClockConfig { | |||
| 368 | div_frac: 171, | 497 | div_frac: 171, |
| 369 | phase: 0, | 498 | phase: 0, |
| 370 | }), | 499 | }), |
| 371 | #[cfg(feature = "rp2040")] | ||
| 372 | core_voltage: CoreVoltage::V1_10, // Use hardware default (1.10V) | 500 | core_voltage: CoreVoltage::V1_10, // Use hardware default (1.10V) |
| 373 | #[cfg(feature = "rp2040")] | ||
| 374 | voltage_stabilization_delay_us: None, | 501 | voltage_stabilization_delay_us: None, |
| 375 | // See above re gpin handling being commented out | 502 | // See above re gpin handling being commented out |
| 376 | // gpin0: None, | 503 | // gpin0: None, |
| @@ -394,12 +521,17 @@ impl ClockConfig { | |||
| 394 | /// the usual 12Mhz crystal, or panic if no valid parameters can be found. | 521 | /// the usual 12Mhz crystal, or panic if no valid parameters can be found. |
| 395 | /// | 522 | /// |
| 396 | /// # Note on core voltage: | 523 | /// # Note on core voltage: |
| 524 | /// | ||
| 525 | /// **For RP2040**: | ||
| 397 | /// To date the only officially documented core voltages (see Datasheet section 2.15.3.1. Instances) are: | 526 | /// To date the only officially documented core voltages (see Datasheet section 2.15.3.1. Instances) are: |
| 398 | /// - Up to 133MHz: V1_10 (default) | 527 | /// - Up to 133MHz: V1_10 (default) |
| 399 | /// - Above 133MHz: V1_15, but in the context of the datasheet covering reaching up to 200Mhz | 528 | /// - Above 133MHz: V1_15, but in the context of the datasheet covering reaching up to 200Mhz |
| 400 | /// That way all other frequencies below 133MHz or above 200MHz are not explicitly documented and not covered here. | 529 | /// That way all other frequencies below 133MHz or above 200MHz are not explicitly documented and not covered here. |
| 401 | /// In case You want to go below 133MHz or above 200MHz and want a different voltage, You will have to set that manually and with caution. | 530 | /// In case You want to go below 133MHz or above 200MHz and want a different voltage, You will have to set that manually and with caution. |
| 402 | #[cfg(feature = "rp2040")] | 531 | /// |
| 532 | /// **For RP235x**: | ||
| 533 | /// At this point in time there is no official manufacturer endorsement for running the chip on other core voltages and/or other clock speeds than the defaults. | ||
| 534 | /// Using this function is experimental and may not work as expected or even damage the chip. | ||
| 403 | pub fn system_freq(hz: u32) -> Self { | 535 | pub fn system_freq(hz: u32) -> Self { |
| 404 | // Start with the standard configuration from crystal() | 536 | // Start with the standard configuration from crystal() |
| 405 | const DEFAULT_CRYSTAL_HZ: u32 = 12_000_000; | 537 | const DEFAULT_CRYSTAL_HZ: u32 = 12_000_000; |
| @@ -407,9 +539,14 @@ impl ClockConfig { | |||
| 407 | 539 | ||
| 408 | // No need to modify anything if target frequency is already 125MHz | 540 | // No need to modify anything if target frequency is already 125MHz |
| 409 | // (which is what crystal() configures by default) | 541 | // (which is what crystal() configures by default) |
| 542 | #[cfg(feature = "rp2040")] | ||
| 410 | if hz == 125_000_000 { | 543 | if hz == 125_000_000 { |
| 411 | return config; | 544 | return config; |
| 412 | } | 545 | } |
| 546 | #[cfg(feature = "_rp235x")] | ||
| 547 | if hz == 150_000_000 { | ||
| 548 | return config; | ||
| 549 | } | ||
| 413 | 550 | ||
| 414 | // Find optimal PLL parameters for the requested frequency | 551 | // Find optimal PLL parameters for the requested frequency |
| 415 | let sys_pll_params = find_pll_params(DEFAULT_CRYSTAL_HZ, hz) | 552 | let sys_pll_params = find_pll_params(DEFAULT_CRYSTAL_HZ, hz) |
| @@ -429,6 +566,14 @@ impl ClockConfig { | |||
| 429 | _ => CoreVoltage::V1_10, // Use default voltage (V1_10) | 566 | _ => CoreVoltage::V1_10, // Use default voltage (V1_10) |
| 430 | }; | 567 | }; |
| 431 | } | 568 | } |
| 569 | #[cfg(feature = "_rp235x")] | ||
| 570 | { | ||
| 571 | config.core_voltage = match hz { | ||
| 572 | // There is no official support for running the chip on other core voltages and/or other clock speeds than the defaults. | ||
| 573 | // So for now we have not way of knowing what the voltage should be. Change this if the manufacturer provides more information. | ||
| 574 | _ => CoreVoltage::V1_10, // Use default voltage (V1_10) | ||
| 575 | }; | ||
| 576 | } | ||
| 432 | 577 | ||
| 433 | config | 578 | config |
| 434 | } | 579 | } |
| @@ -791,7 +936,6 @@ pub struct RtcClkConfig { | |||
| 791 | /// // Find parameters for 133MHz system clock from 12MHz crystal | 936 | /// // Find parameters for 133MHz system clock from 12MHz crystal |
| 792 | /// let pll_params = find_pll_params(12_000_000, 133_000_000).unwrap(); | 937 | /// let pll_params = find_pll_params(12_000_000, 133_000_000).unwrap(); |
| 793 | /// ``` | 938 | /// ``` |
| 794 | #[cfg(feature = "rp2040")] | ||
| 795 | fn find_pll_params(input_hz: u32, target_hz: u32) -> Option<PllConfig> { | 939 | fn find_pll_params(input_hz: u32, target_hz: u32) -> Option<PllConfig> { |
| 796 | // Fixed reference divider for system PLL | 940 | // Fixed reference divider for system PLL |
| 797 | const PLL_SYS_REFDIV: u8 = 1; | 941 | const PLL_SYS_REFDIV: u8 = 1; |
| @@ -925,18 +1069,59 @@ pub(crate) unsafe fn init(config: ClockConfig) { | |||
| 925 | }; | 1069 | }; |
| 926 | CLOCKS.rosc.store(rosc_freq, Ordering::Relaxed); | 1070 | CLOCKS.rosc.store(rosc_freq, Ordering::Relaxed); |
| 927 | 1071 | ||
| 928 | // Set Core Voltage (RP2040 only), if we have config for it and we're not using the default | 1072 | // Set Core Voltage, if we have config for it and we're not using the default |
| 929 | #[cfg(feature = "rp2040")] | ||
| 930 | { | 1073 | { |
| 931 | let voltage = config.core_voltage; | 1074 | let voltage = config.core_voltage; |
| 1075 | |||
| 1076 | #[cfg(feature = "rp2040")] | ||
| 932 | let vreg = pac::VREG_AND_CHIP_RESET; | 1077 | let vreg = pac::VREG_AND_CHIP_RESET; |
| 1078 | #[cfg(feature = "_rp235x")] | ||
| 1079 | let vreg = pac::POWMAN; | ||
| 1080 | |||
| 933 | let current_vsel = vreg.vreg().read().vsel(); | 1081 | let current_vsel = vreg.vreg().read().vsel(); |
| 934 | let target_vsel = voltage as u8; | 1082 | let target_vsel = voltage as u8; |
| 935 | 1083 | ||
| 936 | // If the target voltage is different from the current one, we need to change it | 1084 | // If the target voltage is different from the current one, we need to change it |
| 937 | if target_vsel != current_vsel { | 1085 | if target_vsel != current_vsel { |
| 938 | // Use modify() to preserve the HIZ and EN bits - otherwise we will disable the regulator when changing voltage | 1086 | #[cfg(feature = "rp2040")] |
| 939 | vreg.vreg().modify(|w| w.set_vsel(target_vsel)); | 1087 | { |
| 1088 | // Use modify() to preserve the HIZ and EN bits - otherwise we will disable the regulator when changing voltage | ||
| 1089 | vreg.vreg().modify(|w| w.set_vsel(target_vsel)); | ||
| 1090 | } | ||
| 1091 | #[cfg(feature = "_rp235x")] | ||
| 1092 | { | ||
| 1093 | // The rp235x has a different way of controlling the voltage regulator | ||
| 1094 | // Changes to the voltage regulator are protected by a password, see datasheet section 6.4 | ||
| 1095 | // The password is "5AFE" (0x5AFE), it must be set in the top 16 bits of the register | ||
| 1096 | |||
| 1097 | // The rp235x by default locks the voltage regulator control, so we need to unlock it first | ||
| 1098 | // See datasheet section 6.3.2. Software Control | ||
| 1099 | vreg.vreg_ctrl().modify(|w| { | ||
| 1100 | // Add password to top 16 bits, preserving the rest, repeat below for other registers | ||
| 1101 | w.0 = (w.0 & 0x0000FFFF) | (0x5AFE << 16); | ||
| 1102 | w.set_unlock(true); | ||
| 1103 | *w | ||
| 1104 | }); | ||
| 1105 | |||
| 1106 | // Set the voltage | ||
| 1107 | vreg.vreg().modify(|w| { | ||
| 1108 | w.0 = (w.0 & 0x0000FFFF) | (0x5AFE << 16); | ||
| 1109 | w.set_vsel(target_vsel); | ||
| 1110 | *w | ||
| 1111 | }); | ||
| 1112 | |||
| 1113 | // The rp235x has two more registers to set the voltage for low power mode | ||
| 1114 | vreg.vreg_lp_entry().modify(|w| { | ||
| 1115 | w.0 = (w.0 & 0x0000FFFF) | (0x5AFE << 16); | ||
| 1116 | w.set_vsel(target_vsel); | ||
| 1117 | *w | ||
| 1118 | }); | ||
| 1119 | vreg.vreg_lp_exit().modify(|w| { | ||
| 1120 | w.0 = (w.0 & 0x0000FFFF) | (0x5AFE << 16); | ||
| 1121 | w.set_vsel(target_vsel); | ||
| 1122 | *w | ||
| 1123 | }); | ||
| 1124 | } | ||
| 940 | 1125 | ||
| 941 | // Wait for the voltage to stabilize. Use the provided delay or default based on voltage | 1126 | // Wait for the voltage to stabilize. Use the provided delay or default based on voltage |
| 942 | let settling_time_us = config.voltage_stabilization_delay_us.unwrap_or_else(|| { | 1127 | let settling_time_us = config.voltage_stabilization_delay_us.unwrap_or_else(|| { |
| @@ -959,6 +1144,19 @@ pub(crate) unsafe fn init(config: ClockConfig) { | |||
| 959 | w.set_vsel(voltage.recommended_bod()); | 1144 | w.set_vsel(voltage.recommended_bod()); |
| 960 | w.set_en(true); // Enable brownout detection | 1145 | w.set_en(true); // Enable brownout detection |
| 961 | }); | 1146 | }); |
| 1147 | |||
| 1148 | #[cfg(feature = "_rp235x")] | ||
| 1149 | { | ||
| 1150 | // The rp235x has a separate register for the BOD level in low power mode | ||
| 1151 | vreg.bod_lp_entry().write(|w| { | ||
| 1152 | w.set_vsel(voltage.recommended_bod()); | ||
| 1153 | w.set_en(true); // Enable brownout detection | ||
| 1154 | }); | ||
| 1155 | vreg.bod_lp_exit().write(|w| { | ||
| 1156 | w.set_vsel(voltage.recommended_bod()); | ||
| 1157 | w.set_en(true); // Enable brownout detection | ||
| 1158 | }); | ||
| 1159 | } | ||
| 962 | } | 1160 | } |
| 963 | } | 1161 | } |
| 964 | 1162 | ||
| @@ -1283,6 +1481,73 @@ pub fn clk_rtc_freq() -> u16 { | |||
| 1283 | CLOCKS.rtc.load(Ordering::Relaxed) | 1481 | CLOCKS.rtc.load(Ordering::Relaxed) |
| 1284 | } | 1482 | } |
| 1285 | 1483 | ||
| 1484 | /// The core voltage of the chip. | ||
| 1485 | /// | ||
| 1486 | /// Returns the current core voltage or an error if the voltage register | ||
| 1487 | /// contains an unknown value. | ||
| 1488 | pub fn core_voltage() -> Result<CoreVoltage, &'static str> { | ||
| 1489 | #[cfg(feature = "rp2040")] | ||
| 1490 | { | ||
| 1491 | let vreg = pac::VREG_AND_CHIP_RESET; | ||
| 1492 | let vsel = vreg.vreg().read().vsel(); | ||
| 1493 | match vsel { | ||
| 1494 | 0b0000 => Ok(CoreVoltage::V0_80), | ||
| 1495 | 0b0110 => Ok(CoreVoltage::V0_85), | ||
| 1496 | 0b0111 => Ok(CoreVoltage::V0_90), | ||
| 1497 | 0b1000 => Ok(CoreVoltage::V0_95), | ||
| 1498 | 0b1001 => Ok(CoreVoltage::V1_00), | ||
| 1499 | 0b1010 => Ok(CoreVoltage::V1_05), | ||
| 1500 | 0b1011 => Ok(CoreVoltage::V1_10), | ||
| 1501 | 0b1100 => Ok(CoreVoltage::V1_15), | ||
| 1502 | 0b1101 => Ok(CoreVoltage::V1_20), | ||
| 1503 | 0b1110 => Ok(CoreVoltage::V1_25), | ||
| 1504 | 0b1111 => Ok(CoreVoltage::V1_30), | ||
| 1505 | _ => Err("Unexpected value in register"), | ||
| 1506 | } | ||
| 1507 | } | ||
| 1508 | |||
| 1509 | #[cfg(feature = "_rp235x")] | ||
| 1510 | { | ||
| 1511 | let vreg = pac::POWMAN; | ||
| 1512 | let vsel = vreg.vreg().read().vsel(); | ||
| 1513 | match vsel { | ||
| 1514 | 0b00000 => Ok(CoreVoltage::V0_55), | ||
| 1515 | 0b00001 => Ok(CoreVoltage::V0_60), | ||
| 1516 | 0b00010 => Ok(CoreVoltage::V0_65), | ||
| 1517 | 0b00011 => Ok(CoreVoltage::V0_70), | ||
| 1518 | 0b00100 => Ok(CoreVoltage::V0_75), | ||
| 1519 | 0b00101 => Ok(CoreVoltage::V0_80), | ||
| 1520 | 0b00110 => Ok(CoreVoltage::V0_85), | ||
| 1521 | 0b00111 => Ok(CoreVoltage::V0_90), | ||
| 1522 | 0b01000 => Ok(CoreVoltage::V0_95), | ||
| 1523 | 0b01001 => Ok(CoreVoltage::V1_00), | ||
| 1524 | 0b01010 => Ok(CoreVoltage::V1_05), | ||
| 1525 | 0b01011 => Ok(CoreVoltage::V1_10), | ||
| 1526 | 0b01100 => Ok(CoreVoltage::V1_15), | ||
| 1527 | 0b01101 => Ok(CoreVoltage::V1_20), | ||
| 1528 | 0b01110 => Ok(CoreVoltage::V1_25), | ||
| 1529 | 0b01111 => Ok(CoreVoltage::V1_30), | ||
| 1530 | 0b10000 => Ok(CoreVoltage::V1_35), | ||
| 1531 | 0b10001 => Ok(CoreVoltage::V1_40), | ||
| 1532 | 0b10010 => Ok(CoreVoltage::V1_50), | ||
| 1533 | 0b10011 => Ok(CoreVoltage::V1_60), | ||
| 1534 | 0b10100 => Ok(CoreVoltage::V1_65), | ||
| 1535 | 0b10101 => Ok(CoreVoltage::V1_70), | ||
| 1536 | 0b10110 => Ok(CoreVoltage::V1_80), | ||
| 1537 | 0b10111 => Ok(CoreVoltage::V1_90), | ||
| 1538 | 0b11000 => Ok(CoreVoltage::V2_00), | ||
| 1539 | 0b11001 => Ok(CoreVoltage::V2_35), | ||
| 1540 | 0b11010 => Ok(CoreVoltage::V2_50), | ||
| 1541 | 0b11011 => Ok(CoreVoltage::V2_65), | ||
| 1542 | 0b11100 => Ok(CoreVoltage::V2_80), | ||
| 1543 | 0b11101 => Ok(CoreVoltage::V3_00), | ||
| 1544 | 0b11110 => Ok(CoreVoltage::V3_15), | ||
| 1545 | 0b11111 => Ok(CoreVoltage::V3_30), | ||
| 1546 | _ => Err("Unexpected value in register"), | ||
| 1547 | } | ||
| 1548 | } | ||
| 1549 | } | ||
| 1550 | |||
| 1286 | fn start_xosc(crystal_hz: u32, delay_multiplier: u32) { | 1551 | fn start_xosc(crystal_hz: u32, delay_multiplier: u32) { |
| 1287 | let startup_delay = (((crystal_hz / 1000) * delay_multiplier) + 128) / 256; | 1552 | let startup_delay = (((crystal_hz / 1000) * delay_multiplier) + 128) / 256; |
| 1288 | pac::XOSC.startup().write(|w| w.set_delay(startup_delay as u16)); | 1553 | pac::XOSC.startup().write(|w| w.set_delay(startup_delay as u16)); |
diff --git a/examples/rp/src/bin/overclock.rs b/examples/rp/src/bin/overclock.rs index 9c78e0c9d..89147ba42 100644 --- a/examples/rp/src/bin/overclock.rs +++ b/examples/rp/src/bin/overclock.rs | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | 7 | ||
| 8 | use defmt::*; | 8 | use defmt::*; |
| 9 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 10 | use embassy_rp::clocks::{clk_sys_freq, ClockConfig}; | 10 | use embassy_rp::clocks::{clk_sys_freq, core_voltage, ClockConfig}; |
| 11 | use embassy_rp::config::Config; | 11 | use embassy_rp::config::Config; |
| 12 | use embassy_rp::gpio::{Level, Output}; | 12 | use embassy_rp::gpio::{Level, Output}; |
| 13 | use embassy_time::{Duration, Instant, Timer}; | 13 | use embassy_time::{Duration, Instant, Timer}; |
| @@ -20,15 +20,15 @@ async fn main(_spawner: Spawner) -> ! { | |||
| 20 | // Set up for clock frequency of 200 MHz, setting all necessary defaults. | 20 | // Set up for clock frequency of 200 MHz, setting all necessary defaults. |
| 21 | let config = Config::new(ClockConfig::system_freq(200_000_000)); | 21 | let config = Config::new(ClockConfig::system_freq(200_000_000)); |
| 22 | 22 | ||
| 23 | // Show the voltage scale for verification | ||
| 24 | info!("System core voltage: {}", Debug2Format(&config.clocks.core_voltage)); | ||
| 25 | |||
| 26 | // Initialize the peripherals | 23 | // Initialize the peripherals |
| 27 | let p = embassy_rp::init(config); | 24 | let p = embassy_rp::init(config); |
| 28 | 25 | ||
| 29 | // Show CPU frequency for verification | 26 | // Show CPU frequency for verification |
| 30 | let sys_freq = clk_sys_freq(); | 27 | let sys_freq = clk_sys_freq(); |
| 31 | info!("System clock frequency: {} MHz", sys_freq / 1_000_000); | 28 | info!("System clock frequency: {} MHz", sys_freq / 1_000_000); |
| 29 | // Show core voltage for verification | ||
| 30 | let core_voltage = core_voltage().unwrap(); | ||
| 31 | info!("Core voltage: {}", Debug2Format(&core_voltage)); | ||
| 32 | 32 | ||
| 33 | // LED to indicate the system is running | 33 | // LED to indicate the system is running |
| 34 | let mut led = Output::new(p.PIN_25, Level::Low); | 34 | let mut led = Output::new(p.PIN_25, Level::Low); |
diff --git a/examples/rp/src/bin/overclock_manual.rs b/examples/rp/src/bin/overclock_manual.rs index 35160b250..88ef26a7a 100644 --- a/examples/rp/src/bin/overclock_manual.rs +++ b/examples/rp/src/bin/overclock_manual.rs | |||
| @@ -7,8 +7,7 @@ | |||
| 7 | 7 | ||
| 8 | use defmt::*; | 8 | use defmt::*; |
| 9 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 10 | use embassy_rp::clocks; | 10 | use embassy_rp::clocks::{clk_sys_freq, core_voltage, ClockConfig, CoreVoltage, PllConfig}; |
| 11 | use embassy_rp::clocks::{ClockConfig, CoreVoltage, PllConfig}; | ||
| 12 | use embassy_rp::config::Config; | 11 | use embassy_rp::config::Config; |
| 13 | use embassy_rp::gpio::{Level, Output}; | 12 | use embassy_rp::gpio::{Level, Output}; |
| 14 | use embassy_time::{Duration, Instant, Timer}; | 13 | use embassy_time::{Duration, Instant, Timer}; |
| @@ -41,9 +40,12 @@ async fn main(_spawner: Spawner) -> ! { | |||
| 41 | // Initialize with our manual overclock configuration | 40 | // Initialize with our manual overclock configuration |
| 42 | let p = embassy_rp::init(configure_manual_overclock()); | 41 | let p = embassy_rp::init(configure_manual_overclock()); |
| 43 | 42 | ||
| 44 | // Verify the actual system clock frequency | 43 | // Show CPU frequency for verification |
| 45 | let sys_freq = clocks::clk_sys_freq(); | 44 | let sys_freq = clk_sys_freq(); |
| 46 | info!("System clock frequency: {} MHz", sys_freq / 1_000_000); | 45 | info!("System clock frequency: {} MHz", sys_freq / 1_000_000); |
| 46 | // Show core voltage for verification | ||
| 47 | let core_voltage = core_voltage().unwrap(); | ||
| 48 | info!("Core voltage: {}", Debug2Format(&core_voltage)); | ||
| 47 | 49 | ||
| 48 | // LED to indicate the system is running | 50 | // LED to indicate the system is running |
| 49 | let mut led = Output::new(p.PIN_25, Level::Low); | 51 | let mut led = Output::new(p.PIN_25, Level::Low); |
diff --git a/examples/rp235x/src/bin/overclock.rs b/examples/rp235x/src/bin/overclock.rs new file mode 100644 index 000000000..8713df688 --- /dev/null +++ b/examples/rp235x/src/bin/overclock.rs | |||
| @@ -0,0 +1,74 @@ | |||
| 1 | //! # Overclocking the RP2350 to 200 MHz | ||
| 2 | //! | ||
| 3 | //! This example demonstrates how to configure the RP2350 to run at 200 MHz instead of the default 150 MHz. | ||
| 4 | //! | ||
| 5 | //! ## Note | ||
| 6 | //! | ||
| 7 | //! As of yet there is no official support for running the RP235x at higher clock frequencies and/or other core voltages than the default. | ||
| 8 | //! Doing so may cause unexpected behavior and/or damage the chip. | ||
| 9 | |||
| 10 | #![no_std] | ||
| 11 | #![no_main] | ||
| 12 | |||
| 13 | use defmt::*; | ||
| 14 | use embassy_executor::Spawner; | ||
| 15 | use embassy_rp::clocks::{clk_sys_freq, core_voltage, ClockConfig, CoreVoltage}; | ||
| 16 | use embassy_rp::config::Config; | ||
| 17 | use embassy_rp::gpio::{Level, Output}; | ||
| 18 | use embassy_time::{Duration, Instant, Timer}; | ||
| 19 | use {defmt_rtt as _, panic_probe as _}; | ||
| 20 | |||
| 21 | const COUNT_TO: i64 = 10_000_000; | ||
| 22 | |||
| 23 | #[embassy_executor::main] | ||
| 24 | async fn main(_spawner: Spawner) -> ! { | ||
| 25 | // Set up for clock frequency of 200 MHz, setting all necessary defaults. | ||
| 26 | let mut config = Config::new(ClockConfig::system_freq(200_000_000)); | ||
| 27 | |||
| 28 | // since for the rp235x there is no official support for higher clock frequencies, `system_freq()` will not set a voltage for us. | ||
| 29 | // We need to guess the core voltage, that is needed for the higher clock frequency. Going with a small increase from the default 1.1V here, based on | ||
| 30 | // what we know about the RP2040. This is not guaranteed to be correct. | ||
| 31 | config.clocks.core_voltage = CoreVoltage::V1_15; | ||
| 32 | |||
| 33 | // Initialize the peripherals | ||
| 34 | let p = embassy_rp::init(config); | ||
| 35 | |||
| 36 | // Show CPU frequency for verification | ||
| 37 | let sys_freq = clk_sys_freq(); | ||
| 38 | info!("System clock frequency: {} MHz", sys_freq / 1_000_000); | ||
| 39 | // Show core voltage for verification | ||
| 40 | let core_voltage = core_voltage().unwrap(); | ||
| 41 | info!("Core voltage: {}", Debug2Format(&core_voltage)); | ||
| 42 | |||
| 43 | // LED to indicate the system is running | ||
| 44 | let mut led = Output::new(p.PIN_25, Level::Low); | ||
| 45 | |||
| 46 | loop { | ||
| 47 | // Reset the counter at the start of measurement period | ||
| 48 | let mut counter = 0; | ||
| 49 | |||
| 50 | // Turn LED on while counting | ||
| 51 | led.set_high(); | ||
| 52 | |||
| 53 | let start = Instant::now(); | ||
| 54 | |||
| 55 | // This is a busy loop that will take some time to complete | ||
| 56 | while counter < COUNT_TO { | ||
| 57 | counter += 1; | ||
| 58 | } | ||
| 59 | |||
| 60 | let elapsed = Instant::now() - start; | ||
| 61 | |||
| 62 | // Report the elapsed time | ||
| 63 | led.set_low(); | ||
| 64 | info!( | ||
| 65 | "At {}Mhz: Elapsed time to count to {}: {}ms", | ||
| 66 | sys_freq / 1_000_000, | ||
| 67 | counter, | ||
| 68 | elapsed.as_millis() | ||
| 69 | ); | ||
| 70 | |||
| 71 | // Wait 2 seconds before starting the next measurement | ||
| 72 | Timer::after(Duration::from_secs(2)).await; | ||
| 73 | } | ||
| 74 | } | ||
diff --git a/tests/rp/src/bin/overclock.rs b/tests/rp/src/bin/overclock.rs index be8e85a3f..a568d7fed 100644 --- a/tests/rp/src/bin/overclock.rs +++ b/tests/rp/src/bin/overclock.rs | |||
| @@ -7,14 +7,8 @@ teleprobe_meta::target!(b"rpi-pico"); | |||
| 7 | teleprobe_meta::target!(b"pimoroni-pico-plus-2"); | 7 | teleprobe_meta::target!(b"pimoroni-pico-plus-2"); |
| 8 | 8 | ||
| 9 | use defmt::info; | 9 | use defmt::info; |
| 10 | #[cfg(feature = "rp2040")] | ||
| 11 | use defmt::{assert, assert_eq}; | ||
| 12 | use embassy_executor::Spawner; | 10 | use embassy_executor::Spawner; |
| 13 | use embassy_rp::clocks; | 11 | use embassy_rp::clocks::{clk_sys_freq, core_voltage, ClockConfig, CoreVoltage}; |
| 14 | #[cfg(feature = "rp2040")] | ||
| 15 | use embassy_rp::clocks::ClockConfig; | ||
| 16 | #[cfg(feature = "rp2040")] | ||
| 17 | use embassy_rp::clocks::CoreVoltage; | ||
| 18 | use embassy_rp::config::Config; | 12 | use embassy_rp::config::Config; |
| 19 | use embassy_time::Instant; | 13 | use embassy_time::Instant; |
| 20 | use {defmt_rtt as _, panic_probe as _}; | 14 | use {defmt_rtt as _, panic_probe as _}; |
| @@ -23,23 +17,26 @@ const COUNT_TO: i64 = 10_000_000; | |||
| 23 | 17 | ||
| 24 | #[embassy_executor::main] | 18 | #[embassy_executor::main] |
| 25 | async fn main(_spawner: Spawner) { | 19 | async fn main(_spawner: Spawner) { |
| 26 | #[cfg(feature = "rp2040")] | ||
| 27 | let mut config = Config::default(); | 20 | let mut config = Config::default(); |
| 28 | #[cfg(not(feature = "rp2040"))] | ||
| 29 | let config = Config::default(); | ||
| 30 | 21 | ||
| 31 | // Initialize with 200MHz clock configuration for RP2040, other chips will use default clock | 22 | // Initialize with 200MHz clock configuration |
| 32 | #[cfg(feature = "rp2040")] | 23 | config.clocks = ClockConfig::system_freq(200_000_000); |
| 24 | |||
| 25 | // if we are rp235x, we need to manually set the core voltage. rp2040 should do this automatically | ||
| 26 | #[cfg(feature = "rp235xb")] | ||
| 33 | { | 27 | { |
| 34 | config.clocks = ClockConfig::system_freq(200_000_000); | 28 | config.clocks.core_voltage = CoreVoltage::V1_15; |
| 35 | let voltage = config.clocks.core_voltage; | ||
| 36 | assert!(matches!(voltage, CoreVoltage::V1_15), "Expected voltage scale V1_15"); | ||
| 37 | } | 29 | } |
| 38 | 30 | ||
| 39 | let _p = embassy_rp::init(config); | 31 | let _p = embassy_rp::init(config); |
| 40 | 32 | ||
| 33 | // We should be at core voltage of 1.15V | ||
| 34 | assert_eq!(core_voltage().unwrap(), CoreVoltage::V1_15, "Core voltage is not 1.15V"); | ||
| 35 | // We should be at 200MHz | ||
| 36 | assert_eq!(clk_sys_freq(), 200_000_000, "System clock frequency is not 200MHz"); | ||
| 37 | |||
| 41 | // Test the system speed | 38 | // Test the system speed |
| 42 | let (time_elapsed, clk_sys_freq) = { | 39 | let time_elapsed = { |
| 43 | let mut counter = 0; | 40 | let mut counter = 0; |
| 44 | let start = Instant::now(); | 41 | let start = Instant::now(); |
| 45 | while counter < COUNT_TO { | 42 | while counter < COUNT_TO { |
| @@ -47,24 +44,26 @@ async fn main(_spawner: Spawner) { | |||
| 47 | } | 44 | } |
| 48 | let elapsed = Instant::now() - start; | 45 | let elapsed = Instant::now() - start; |
| 49 | 46 | ||
| 50 | (elapsed.as_millis(), clocks::clk_sys_freq()) | 47 | elapsed.as_millis() |
| 51 | }; | 48 | }; |
| 52 | 49 | ||
| 53 | // Report the elapsed time, so that the compiler doesn't optimize it away for chips other than RP2040 | 50 | // Tests will fail if unused variables are detected: |
| 51 | // Report the elapsed time, so that the compiler doesn't optimize it away for the chip not on test | ||
| 54 | info!( | 52 | info!( |
| 55 | "At {}Mhz: Elapsed time to count to {}: {}ms", | 53 | "At {}Mhz: Elapsed time to count to {}: {}ms", |
| 56 | clk_sys_freq / 1_000_000, | 54 | clk_sys_freq() / 1_000_000, |
| 57 | COUNT_TO, | 55 | COUNT_TO, |
| 58 | time_elapsed | 56 | time_elapsed |
| 59 | ); | 57 | ); |
| 60 | 58 | ||
| 59 | // Check if the elapsed time is within expected limits | ||
| 60 | // for rp2040 we expect about 600ms | ||
| 61 | #[cfg(feature = "rp2040")] | 61 | #[cfg(feature = "rp2040")] |
| 62 | { | 62 | // allow 1% error |
| 63 | // we should be at 200MHz | 63 | assert!(time_elapsed < 606, "Elapsed time is too long"); |
| 64 | assert_eq!(clk_sys_freq, 200_000_000, "System clock frequency is not 200MHz"); | 64 | // for rp235x we expect about 450ms |
| 65 | // At 200MHz, the time to count to 10_000_000 should be at 600ms, testing with 1% margin | 65 | #[cfg(feature = "rp235xb")] |
| 66 | assert!(time_elapsed <= 606, "Elapsed time is too long"); | 66 | assert!(time_elapsed < 455, "Elapsed time is too long"); |
| 67 | } | ||
| 68 | 67 | ||
| 69 | cortex_m::asm::bkpt(); | 68 | cortex_m::asm::bkpt(); |
| 70 | } | 69 | } |
