diff options
| author | 1-rafael-1 <[email protected]> | 2025-05-12 09:45:05 +0200 |
|---|---|---|
| committer | 1-rafael-1 <[email protected]> | 2025-05-12 09:45:05 +0200 |
| commit | 133500167ca53cfbc5e9268356753bc0e3f8c209 (patch) | |
| tree | 7f3c0837e557ec6739d723950c306f57b03895d5 /embassy-rp | |
| parent | 4567beda7b7773c8cb11f19f0f4f146c1243508d (diff) | |
limit CoreVoltage eum to values up to 1.30V, because we do not support unlocking higher voltages
Diffstat (limited to 'embassy-rp')
| -rw-r--r-- | embassy-rp/src/clocks.rs | 141 |
1 files changed, 21 insertions, 120 deletions
diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs index ea5e9362b..bcd08c204 100644 --- a/embassy-rp/src/clocks.rs +++ b/embassy-rp/src/clocks.rs | |||
| @@ -140,6 +140,10 @@ pub enum PeriClkSrc { | |||
| 140 | /// | 140 | /// |
| 141 | /// The 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 | /// | ||
| 144 | /// **Note**: For RP235x the maximum voltage is 1.30V, unless unlocked by setting unless the voltage limit | ||
| 145 | /// is disabled using the disable_voltage_limit field in the vreg_ctrl register. For lack of practical use at this | ||
| 146 | /// point in time, this is not implemented here. So the maximum voltage in this enum is 1.30V for now. | ||
| 143 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] | 147 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] |
| 144 | #[repr(u8)] | 148 | #[repr(u8)] |
| 145 | pub enum CoreVoltage { | 149 | pub enum CoreVoltage { |
| @@ -227,54 +231,6 @@ pub enum CoreVoltage { | |||
| 227 | #[cfg(feature = "_rp235x")] | 231 | #[cfg(feature = "_rp235x")] |
| 228 | /// RP235x: 1.30V | 232 | /// RP235x: 1.30V |
| 229 | V1_30 = 0b01111, | 233 | 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, | ||
| 278 | } | 234 | } |
| 279 | 235 | ||
| 280 | impl CoreVoltage { | 236 | impl CoreVoltage { |
| @@ -313,13 +269,7 @@ impl CoreVoltage { | |||
| 313 | CoreVoltage::V1_20 => 0b01010, // 0.903V (~75% of 1.20V) | 269 | CoreVoltage::V1_20 => 0b01010, // 0.903V (~75% of 1.20V) |
| 314 | CoreVoltage::V1_25 => 0b01010, // 0.903V (~72% of 1.25V) | 270 | CoreVoltage::V1_25 => 0b01010, // 0.903V (~72% of 1.25V) |
| 315 | CoreVoltage::V1_30 => 0b01011, // 0.946V (~73% of 1.30V) | 271 | CoreVoltage::V1_30 => 0b01011, // 0.946V (~73% of 1.30V) |
| 316 | CoreVoltage::V1_35 => 0b01011, // 0.946V (~70% of 1.35V) | 272 | // all others: 0.946V (see CoreVoltage: we do not support setting Voltages higher than 1.30V at this point) |
| 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 | } | 273 | } |
| 324 | } | 274 | } |
| 325 | } | 275 | } |
| @@ -1083,45 +1033,17 @@ pub(crate) unsafe fn init(config: ClockConfig) { | |||
| 1083 | 1033 | ||
| 1084 | // If the target voltage is different from the current one, we need to change it | 1034 | // If the target voltage is different from the current one, we need to change it |
| 1085 | if target_vsel != current_vsel { | 1035 | if target_vsel != current_vsel { |
| 1036 | // Set the voltage regulator to the target voltage | ||
| 1086 | #[cfg(feature = "rp2040")] | 1037 | #[cfg(feature = "rp2040")] |
| 1087 | { | 1038 | vreg.vreg().modify(|w| w.set_vsel(target_vsel)); |
| 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")] | 1039 | #[cfg(feature = "_rp235x")] |
| 1092 | { | 1040 | // For rp235x changes to the voltage regulator are protected by a password, see datasheet section 6.4 Power Management (POWMAN) Registers |
| 1093 | // The rp235x has a different way of controlling the voltage regulator | 1041 | // The password is "5AFE" (0x5AFE), it must be set in the top 16 bits of the register |
| 1094 | // Changes to the voltage regulator are protected by a password, see datasheet section 6.4 | 1042 | vreg.vreg().modify(|w| { |
| 1095 | // The password is "5AFE" (0x5AFE), it must be set in the top 16 bits of the register | 1043 | w.0 = (w.0 & 0x0000FFFF) | (0x5AFE << 16); // Set the password |
| 1096 | 1044 | w.set_vsel(target_vsel); | |
| 1097 | // The rp235x by default locks the voltage regulator control, so we need to unlock it first | 1045 | *w |
| 1098 | // See datasheet section 6.3.2. Software Control | 1046 | }); |
| 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 | } | ||
| 1125 | 1047 | ||
| 1126 | // Wait for the voltage to stabilize. Use the provided delay or default based on voltage | 1048 | // Wait for the voltage to stabilize. Use the provided delay or default based on voltage |
| 1127 | let settling_time_us = config.voltage_stabilization_delay_us.unwrap_or_else(|| { | 1049 | let settling_time_us = config.voltage_stabilization_delay_us.unwrap_or_else(|| { |
| @@ -1140,23 +1062,17 @@ pub(crate) unsafe fn init(config: ClockConfig) { | |||
| 1140 | } | 1062 | } |
| 1141 | 1063 | ||
| 1142 | // Only now set the BOD level. At this point the voltage is considered stable. | 1064 | // Only now set the BOD level. At this point the voltage is considered stable. |
| 1065 | #[cfg(feature = "rp2040")] | ||
| 1143 | vreg.bod().write(|w| { | 1066 | vreg.bod().write(|w| { |
| 1144 | w.set_vsel(voltage.recommended_bod()); | 1067 | w.set_vsel(voltage.recommended_bod()); |
| 1145 | w.set_en(true); // Enable brownout detection | 1068 | w.set_en(true); // Enable brownout detection |
| 1146 | }); | 1069 | }); |
| 1147 | |||
| 1148 | #[cfg(feature = "_rp235x")] | 1070 | #[cfg(feature = "_rp235x")] |
| 1149 | { | 1071 | vreg.bod().write(|w| { |
| 1150 | // The rp235x has a separate register for the BOD level in low power mode | 1072 | w.0 = (w.0 & 0x0000FFFF) | (0x5AFE << 16); // Set the password |
| 1151 | vreg.bod_lp_entry().write(|w| { | 1073 | w.set_vsel(voltage.recommended_bod()); |
| 1152 | w.set_vsel(voltage.recommended_bod()); | 1074 | w.set_en(true); // Enable brownout detection |
| 1153 | w.set_en(true); // Enable brownout detection | 1075 | }); |
| 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 | } | ||
| 1160 | } | 1076 | } |
| 1161 | } | 1077 | } |
| 1162 | 1078 | ||
| @@ -1527,23 +1443,8 @@ pub fn core_voltage() -> Result<CoreVoltage, &'static str> { | |||
| 1527 | 0b01101 => Ok(CoreVoltage::V1_20), | 1443 | 0b01101 => Ok(CoreVoltage::V1_20), |
| 1528 | 0b01110 => Ok(CoreVoltage::V1_25), | 1444 | 0b01110 => Ok(CoreVoltage::V1_25), |
| 1529 | 0b01111 => Ok(CoreVoltage::V1_30), | 1445 | 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"), | 1446 | _ => Err("Unexpected value in register"), |
| 1447 | // see CoreVoltage: we do not support setting Voltages higher than 1.30V at this point | ||
| 1547 | } | 1448 | } |
| 1548 | } | 1449 | } |
| 1549 | } | 1450 | } |
