diff options
| author | 1-rafael-1 <[email protected]> | 2025-05-05 22:55:09 +0200 |
|---|---|---|
| committer | 1-rafael-1 <[email protected]> | 2025-05-05 22:55:09 +0200 |
| commit | 0d03aa0bec01fb0289915861d997bf7f2cf8d232 (patch) | |
| tree | 344cdec55443d4506cd288872c9812b964e84644 | |
| parent | 3d9cac361ed6bd0cd00cab7bf924608c89de9108 (diff) | |
rework init()
| -rw-r--r-- | embassy-rp/src/clocks.rs | 256 |
1 files changed, 103 insertions, 153 deletions
diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs index 107e499b7..a4cc129ab 100644 --- a/embassy-rp/src/clocks.rs +++ b/embassy-rp/src/clocks.rs | |||
| @@ -168,20 +168,20 @@ pub enum CoreVoltage { | |||
| 168 | #[cfg(feature = "rp2040")] | 168 | #[cfg(feature = "rp2040")] |
| 169 | impl CoreVoltage { | 169 | impl CoreVoltage { |
| 170 | /// Get the recommended Brown-Out Detection (BOD) setting for this voltage. | 170 | /// Get the recommended Brown-Out Detection (BOD) setting for this voltage. |
| 171 | /// Sets the BOD threshold to approximately 90% of the core voltage. | 171 | /// Sets the BOD threshold to approximately 80% of the core voltage. |
| 172 | fn recommended_bod(self) -> u8 { | 172 | fn recommended_bod(self) -> u8 { |
| 173 | match self { | 173 | match self { |
| 174 | CoreVoltage::V0_80 => 0b0110, // 0.720V (~90% of 0.80V) | 174 | CoreVoltage::V0_80 => 0b0100, // 0.645V (~81% of 0.80V) |
| 175 | CoreVoltage::V0_85 => 0b0111, // 0.774V (~91% of 0.85V) | 175 | CoreVoltage::V0_85 => 0b0101, // 0.688V (~81% of 0.85V) |
| 176 | CoreVoltage::V0_90 => 0b1000, // 0.817V (~91% of 0.90V) | 176 | CoreVoltage::V0_90 => 0b0110, // 0.731V (~81% of 0.90V) |
| 177 | CoreVoltage::V0_95 => 0b1001, // 0.860V (~91% of 0.95V) | 177 | CoreVoltage::V0_95 => 0b0111, // 0.774V (~81% of 0.95V) |
| 178 | CoreVoltage::V1_00 => 0b1010, // 0.903V (~90% of 1.00V) | 178 | CoreVoltage::V1_00 => 0b1000, // 0.817V (~82% of 1.00V) |
| 179 | CoreVoltage::V1_05 => 0b1011, // 0.946V (~90% of 1.05V) | 179 | CoreVoltage::V1_05 => 0b1000, // 0.817V (~78% of 1.05V) |
| 180 | CoreVoltage::V1_10 => 0b1100, // 0.989V (~90% of 1.10V) | 180 | CoreVoltage::V1_10 => 0b1001, // 0.860V (~78% of 1.10V) |
| 181 | CoreVoltage::V1_15 => 0b1101, // 1.032V (~90% of 1.15V) | 181 | CoreVoltage::V1_15 => 0b1010, // 0.903V (~79% of 1.15V) |
| 182 | CoreVoltage::V1_20 => 0b1110, // 1.075V (~90% of 1.20V) | 182 | CoreVoltage::V1_20 => 0b1011, // 0.946V (~79% of 1.20V) |
| 183 | CoreVoltage::V1_25 => 0b1111, // 1.118V (~89% of 1.25V) | 183 | CoreVoltage::V1_25 => 0b1100, // 0.989V (~79% of 1.25V) |
| 184 | CoreVoltage::V1_30 => 0b1111, // 1.118V (~86% of 1.30V) - using max available threshold | 184 | CoreVoltage::V1_30 => 0b1101, // 1.032V (~79% of 1.30V) |
| 185 | } | 185 | } |
| 186 | } | 186 | } |
| 187 | } | 187 | } |
| @@ -459,11 +459,6 @@ impl ClockConfig { | |||
| 459 | /// ``` | 459 | /// ``` |
| 460 | #[cfg(feature = "rp2040")] | 460 | #[cfg(feature = "rp2040")] |
| 461 | pub fn manual_pll(xosc_hz: u32, pll_config: PllConfig, core_voltage: CoreVoltage) -> Self { | 461 | pub fn manual_pll(xosc_hz: u32, pll_config: PllConfig, core_voltage: CoreVoltage) -> Self { |
| 462 | // Calculate the actual output frequency for documentation | ||
| 463 | // let ref_freq = xosc_hz / pll_config.refdiv as u32; | ||
| 464 | // let vco_freq = ref_freq * pll_config.fbdiv as u32; | ||
| 465 | // let sys_freq = vco_freq / ((pll_config.post_div1 * pll_config.post_div2) as u32); | ||
| 466 | |||
| 467 | // Validate PLL parameters | 462 | // Validate PLL parameters |
| 468 | assert!(pll_config.is_valid(xosc_hz), "Invalid PLL parameters"); | 463 | assert!(pll_config.is_valid(xosc_hz), "Invalid PLL parameters"); |
| 469 | 464 | ||
| @@ -893,6 +888,30 @@ pub(crate) unsafe fn init(config: ClockConfig) { | |||
| 893 | #[cfg(feature = "_rp235x")] | 888 | #[cfg(feature = "_rp235x")] |
| 894 | while c.clk_ref_selected().read() != pac::clocks::regs::ClkRefSelected(1) {} | 889 | while c.clk_ref_selected().read() != pac::clocks::regs::ClkRefSelected(1) {} |
| 895 | 890 | ||
| 891 | // Reset the PLLs | ||
| 892 | let mut peris = reset::Peripherals(0); | ||
| 893 | peris.set_pll_sys(true); | ||
| 894 | peris.set_pll_usb(true); | ||
| 895 | reset::reset(peris); | ||
| 896 | reset::unreset_wait(peris); | ||
| 897 | |||
| 898 | // let gpin0_freq = config.gpin0.map_or(0, |p| { | ||
| 899 | // core::mem::forget(p.1); | ||
| 900 | // p.0 | ||
| 901 | // }); | ||
| 902 | // CLOCKS.gpin0.store(gpin0_freq, Ordering::Relaxed); | ||
| 903 | // let gpin1_freq = config.gpin1.map_or(0, |p| { | ||
| 904 | // core::mem::forget(p.1); | ||
| 905 | // p.0 | ||
| 906 | // }); | ||
| 907 | // CLOCKS.gpin1.store(gpin1_freq, Ordering::Relaxed); | ||
| 908 | |||
| 909 | let rosc_freq = match config.rosc { | ||
| 910 | Some(config) => configure_rosc(config), | ||
| 911 | None => 0, | ||
| 912 | }; | ||
| 913 | CLOCKS.rosc.store(rosc_freq, Ordering::Relaxed); | ||
| 914 | |||
| 896 | // Set Core Voltage (RP2040 only), if we have config for it and we're not using the default | 915 | // Set Core Voltage (RP2040 only), if we have config for it and we're not using the default |
| 897 | #[cfg(feature = "rp2040")] | 916 | #[cfg(feature = "rp2040")] |
| 898 | { | 917 | { |
| @@ -901,8 +920,9 @@ pub(crate) unsafe fn init(config: ClockConfig) { | |||
| 901 | let current_vsel = vreg.vreg().read().vsel(); | 920 | let current_vsel = vreg.vreg().read().vsel(); |
| 902 | let target_vsel = voltage as u8; | 921 | let target_vsel = voltage as u8; |
| 903 | 922 | ||
| 923 | // If the target voltage is different from the current one, we need to change it | ||
| 904 | if target_vsel != current_vsel { | 924 | if target_vsel != current_vsel { |
| 905 | // Use modify() instead of write() to preserve the HIZ and EN bits - otherwise we will disable the regulator when changing voltage | 925 | // Use modify() to preserve the HIZ and EN bits - otherwise we will disable the regulator when changing voltage |
| 906 | vreg.vreg().modify(|w| w.set_vsel(target_vsel)); | 926 | vreg.vreg().modify(|w| w.set_vsel(target_vsel)); |
| 907 | 927 | ||
| 908 | // Wait for the voltage to stabilize. Use the provided delay or default based on voltage | 928 | // Wait for the voltage to stabilize. Use the provided delay or default based on voltage |
| @@ -914,16 +934,14 @@ pub(crate) unsafe fn init(config: ClockConfig) { | |||
| 914 | } | 934 | } |
| 915 | }); | 935 | }); |
| 916 | 936 | ||
| 917 | // We need a clock that's guaranteed to be running at this point | 937 | if settling_time_us != 0 { |
| 918 | // Use ROSC which should be configured by now | 938 | // Delay in microseconds, using the ROSC frequency to calculate cycles |
| 919 | let rosc_freq_rough = 6_000_000; // Rough ROSC frequency estimate | 939 | let cycles_per_us = rosc_freq / 1_000_000; |
| 920 | let cycles_per_us = rosc_freq_rough / 1_000_000; | 940 | let delay_cycles = settling_time_us * cycles_per_us; |
| 921 | let delay_cycles = settling_time_us * cycles_per_us; | 941 | cortex_m::asm::delay(delay_cycles); |
| 922 | 942 | } | |
| 923 | // Wait for voltage to stabilize | ||
| 924 | cortex_m::asm::delay(delay_cycles); | ||
| 925 | 943 | ||
| 926 | // Only now set the BOD level after voltage has stabilized | 944 | // Only now set the BOD level. At htis point the voltage is considered stable. |
| 927 | vreg.bod().write(|w| { | 945 | vreg.bod().write(|w| { |
| 928 | w.set_vsel(voltage.recommended_bod()); | 946 | w.set_vsel(voltage.recommended_bod()); |
| 929 | w.set_en(true); // Enable brownout detection | 947 | w.set_en(true); // Enable brownout detection |
| @@ -931,108 +949,64 @@ pub(crate) unsafe fn init(config: ClockConfig) { | |||
| 931 | } | 949 | } |
| 932 | } | 950 | } |
| 933 | 951 | ||
| 934 | // Configure ROSC first if present | 952 | let (xosc_freq, pll_sys_freq, pll_usb_freq) = match config.xosc { |
| 935 | let rosc_freq = match config.rosc { | ||
| 936 | Some(config) => configure_rosc(config), | ||
| 937 | None => 0, | ||
| 938 | }; | ||
| 939 | CLOCKS.rosc.store(rosc_freq, Ordering::Relaxed); | ||
| 940 | |||
| 941 | // Configure XOSC - we'll need this for our temporary stable clock | ||
| 942 | let xosc_freq = match &config.xosc { | ||
| 943 | Some(config) => { | 953 | Some(config) => { |
| 954 | // start XOSC | ||
| 955 | // datasheet mentions support for clock inputs into XIN, but doesn't go into | ||
| 956 | // how this is achieved. pico-sdk doesn't support this at all. | ||
| 944 | start_xosc(config.hz, config.delay_multiplier); | 957 | start_xosc(config.hz, config.delay_multiplier); |
| 945 | config.hz | ||
| 946 | } | ||
| 947 | None => 0, | ||
| 948 | }; | ||
| 949 | CLOCKS.xosc.store(xosc_freq, Ordering::Relaxed); | ||
| 950 | 958 | ||
| 951 | // Setup temporary stable clocks first | 959 | let pll_sys_freq = match config.sys_pll { |
| 952 | // Configure USB PLL for our stable temporary clock | 960 | Some(sys_pll_config) => match configure_pll(pac::PLL_SYS, config.hz, sys_pll_config) { |
| 953 | let pll_usb_freq = match &config.xosc { | ||
| 954 | Some(config) => match &config.usb_pll { | ||
| 955 | Some(pll_usb_config) => { | ||
| 956 | // Reset USB PLL | ||
| 957 | let mut peris = reset::Peripherals(0); | ||
| 958 | peris.set_pll_usb(true); | ||
| 959 | reset::reset(peris); | ||
| 960 | reset::unreset_wait(peris); | ||
| 961 | |||
| 962 | // Configure the USB PLL - this should give us 48MHz | ||
| 963 | let usb_pll_freq = match configure_pll(pac::PLL_USB, xosc_freq, *pll_usb_config) { | ||
| 964 | Ok(freq) => freq, | 961 | Ok(freq) => freq, |
| 965 | Err(_) => { | 962 | Err(e) => panic!("Failed to configure PLL_SYS: {}", e), |
| 966 | panic!("Failed to configure USB PLL"); | 963 | }, |
| 967 | } | 964 | None => 0, |
| 968 | }; | 965 | }; |
| 966 | let pll_usb_freq = match config.usb_pll { | ||
| 967 | Some(usb_pll_config) => match configure_pll(pac::PLL_USB, config.hz, usb_pll_config) { | ||
| 968 | Ok(freq) => freq, | ||
| 969 | Err(e) => panic!("Failed to configure PLL_USB: {}", e), | ||
| 970 | }, | ||
| 971 | None => 0, | ||
| 972 | }; | ||
| 969 | 973 | ||
| 970 | CLOCKS.pll_usb.store(usb_pll_freq, Ordering::Relaxed); | 974 | (config.hz, pll_sys_freq, pll_usb_freq) |
| 971 | usb_pll_freq | 975 | } |
| 972 | } | 976 | None => (0, 0, 0), |
| 973 | None => 0, | ||
| 974 | }, | ||
| 975 | None => 0, | ||
| 976 | }; | 977 | }; |
| 977 | 978 | ||
| 978 | // Configure REF clock to use XOSC | 979 | CLOCKS.xosc.store(xosc_freq, Ordering::Relaxed); |
| 980 | CLOCKS.pll_sys.store(pll_sys_freq, Ordering::Relaxed); | ||
| 981 | CLOCKS.pll_usb.store(pll_usb_freq, Ordering::Relaxed); | ||
| 982 | |||
| 983 | let (ref_src, ref_aux, clk_ref_freq) = { | ||
| 984 | use {ClkRefCtrlAuxsrc as Aux, ClkRefCtrlSrc as Src}; | ||
| 985 | let div = config.ref_clk.div as u32; | ||
| 986 | assert!(div >= 1 && div <= 4); | ||
| 987 | match config.ref_clk.src { | ||
| 988 | RefClkSrc::Xosc => (Src::XOSC_CLKSRC, Aux::CLKSRC_PLL_USB, xosc_freq / div), | ||
| 989 | RefClkSrc::Rosc => (Src::ROSC_CLKSRC_PH, Aux::CLKSRC_PLL_USB, rosc_freq / div), | ||
| 990 | RefClkSrc::PllUsb => (Src::CLKSRC_CLK_REF_AUX, Aux::CLKSRC_PLL_USB, pll_usb_freq / div), | ||
| 991 | // RefClkSrc::Gpin0 => (Src::CLKSRC_CLK_REF_AUX, Aux::CLKSRC_GPIN0, gpin0_freq / div), | ||
| 992 | // RefClkSrc::Gpin1 => (Src::CLKSRC_CLK_REF_AUX, Aux::CLKSRC_GPIN1, gpin1_freq / div), | ||
| 993 | } | ||
| 994 | }; | ||
| 995 | assert!(clk_ref_freq != 0); | ||
| 996 | CLOCKS.reference.store(clk_ref_freq, Ordering::Relaxed); | ||
| 979 | c.clk_ref_ctrl().write(|w| { | 997 | c.clk_ref_ctrl().write(|w| { |
| 980 | w.set_src(ClkRefCtrlSrc::XOSC_CLKSRC); | 998 | w.set_src(ref_src); |
| 999 | w.set_auxsrc(ref_aux); | ||
| 981 | }); | 1000 | }); |
| 982 | #[cfg(feature = "rp2040")] | 1001 | #[cfg(feature = "rp2040")] |
| 983 | while c.clk_ref_selected().read() != (1 << ClkRefCtrlSrc::XOSC_CLKSRC as u32) {} | 1002 | while c.clk_ref_selected().read() != (1 << ref_src as u32) {} |
| 984 | #[cfg(feature = "_rp235x")] | 1003 | #[cfg(feature = "_rp235x")] |
| 985 | while c.clk_ref_selected().read() != pac::clocks::regs::ClkRefSelected(1 << ClkRefCtrlSrc::XOSC_CLKSRC as u32) {} | 1004 | while c.clk_ref_selected().read() != pac::clocks::regs::ClkRefSelected(1 << ref_src as u32) {} |
| 986 | 1005 | c.clk_ref_div().write(|w| { | |
| 987 | // First switch the system clock to a stable source (USB PLL at 48MHz) | 1006 | w.set_int(config.ref_clk.div); |
| 988 | // This follows the official Pico SDK's approach to ensure stability during reconfiguration | ||
| 989 | c.clk_sys_ctrl().write(|w| { | ||
| 990 | w.set_auxsrc(ClkSysCtrlAuxsrc::CLKSRC_PLL_USB); | ||
| 991 | w.set_src(ClkSysCtrlSrc::CLKSRC_CLK_SYS_AUX); | ||
| 992 | }); | 1007 | }); |
| 993 | 1008 | ||
| 994 | #[cfg(feature = "rp2040")] | 1009 | // Configure tick generation on the 2040. |
| 995 | while c.clk_sys_selected().read() != (1 << ClkSysCtrlSrc::CLKSRC_CLK_SYS_AUX as u32) {} | ||
| 996 | #[cfg(feature = "_rp235x")] | ||
| 997 | while c.clk_sys_selected().read() | ||
| 998 | != pac::clocks::regs::ClkSysSelected(1 << ClkSysCtrlSrc::CLKSRC_CLK_SYS_AUX as u32) | ||
| 999 | {} | ||
| 1000 | |||
| 1001 | // Short delay after switching to USB PLL to ensure stability | ||
| 1002 | cortex_m::asm::delay(100); | ||
| 1003 | |||
| 1004 | // NOW CONFIGURE THE SYSTEM PLL (safely, since we're running from the USB PLL) | ||
| 1005 | let pll_sys_freq = match &config.xosc { | ||
| 1006 | Some(config) => match &config.sys_pll { | ||
| 1007 | Some(sys_pll_config) => { | ||
| 1008 | // Reset SYS PLL | ||
| 1009 | let mut peris = reset::Peripherals(0); | ||
| 1010 | peris.set_pll_sys(true); | ||
| 1011 | reset::reset(peris); | ||
| 1012 | reset::unreset_wait(peris); | ||
| 1013 | |||
| 1014 | // Configure the SYS PLL | ||
| 1015 | let pll_sys_freq = match configure_pll(pac::PLL_SYS, xosc_freq, *sys_pll_config) { | ||
| 1016 | Ok(freq) => freq, | ||
| 1017 | Err(_) => { | ||
| 1018 | panic!("Failed to configure system PLL"); | ||
| 1019 | } | ||
| 1020 | }; | ||
| 1021 | |||
| 1022 | // Ensure PLL is locked and stable | ||
| 1023 | cortex_m::asm::delay(100); | ||
| 1024 | |||
| 1025 | CLOCKS.pll_sys.store(pll_sys_freq, Ordering::Relaxed); | ||
| 1026 | pll_sys_freq | ||
| 1027 | } | ||
| 1028 | None => 0, | ||
| 1029 | }, | ||
| 1030 | None => 0, | ||
| 1031 | }; | ||
| 1032 | |||
| 1033 | // Configure tick generation using REF clock | ||
| 1034 | let clk_ref_freq = xosc_freq; // REF clock is now XOSC | ||
| 1035 | CLOCKS.reference.store(clk_ref_freq, Ordering::Relaxed); | ||
| 1036 | #[cfg(feature = "rp2040")] | 1010 | #[cfg(feature = "rp2040")] |
| 1037 | pac::WATCHDOG.tick().write(|w| { | 1011 | pac::WATCHDOG.tick().write(|w| { |
| 1038 | w.set_cycles((clk_ref_freq / 1_000_000) as u16); | 1012 | w.set_cycles((clk_ref_freq / 1_000_000) as u16); |
| @@ -1050,8 +1024,6 @@ pub(crate) unsafe fn init(config: ClockConfig) { | |||
| 1050 | pac::TICKS.watchdog_ctrl().write(|w| w.set_enable(true)); | 1024 | pac::TICKS.watchdog_ctrl().write(|w| w.set_enable(true)); |
| 1051 | } | 1025 | } |
| 1052 | 1026 | ||
| 1053 | // NOW SWITCH THE SYSTEM CLOCK TO THE CONFIGURED SOURCE | ||
| 1054 | // The SYS PLL is now stable and we can safely switch to it | ||
| 1055 | let (sys_src, sys_aux, clk_sys_freq) = { | 1027 | let (sys_src, sys_aux, clk_sys_freq) = { |
| 1056 | use {ClkSysCtrlAuxsrc as Aux, ClkSysCtrlSrc as Src}; | 1028 | use {ClkSysCtrlAuxsrc as Aux, ClkSysCtrlSrc as Src}; |
| 1057 | let (src, aux, freq) = match config.sys_clk.src { | 1029 | let (src, aux, freq) = match config.sys_clk.src { |
| @@ -1068,48 +1040,28 @@ pub(crate) unsafe fn init(config: ClockConfig) { | |||
| 1068 | }; | 1040 | }; |
| 1069 | assert!(clk_sys_freq != 0); | 1041 | assert!(clk_sys_freq != 0); |
| 1070 | CLOCKS.sys.store(clk_sys_freq, Ordering::Relaxed); | 1042 | CLOCKS.sys.store(clk_sys_freq, Ordering::Relaxed); |
| 1071 | 1043 | if sys_src != ClkSysCtrlSrc::CLK_REF { | |
| 1072 | // Set the divider before changing the source if it's increasing | 1044 | c.clk_sys_ctrl().write(|w| w.set_src(ClkSysCtrlSrc::CLK_REF)); |
| 1073 | if config.sys_clk.div_int > 1 || config.sys_clk.div_frac > 0 { | 1045 | #[cfg(feature = "rp2040")] |
| 1074 | c.clk_sys_div().write(|w| { | 1046 | while c.clk_sys_selected().read() != (1 << ClkSysCtrlSrc::CLK_REF as u32) {} |
| 1075 | w.set_int(config.sys_clk.div_int); | 1047 | #[cfg(feature = "_rp235x")] |
| 1076 | w.set_frac(config.sys_clk.div_frac); | 1048 | while c.clk_sys_selected().read() != pac::clocks::regs::ClkSysSelected(1 << ClkSysCtrlSrc::CLK_REF as u32) {} |
| 1077 | }); | ||
| 1078 | } | ||
| 1079 | |||
| 1080 | // Configure aux source first if needed | ||
| 1081 | if sys_src == ClkSysCtrlSrc::CLKSRC_CLK_SYS_AUX { | ||
| 1082 | c.clk_sys_ctrl().modify(|w| { | ||
| 1083 | w.set_auxsrc(sys_aux); | ||
| 1084 | }); | ||
| 1085 | } | 1049 | } |
| 1086 | |||
| 1087 | // Now set the source | ||
| 1088 | c.clk_sys_ctrl().write(|w| { | 1050 | c.clk_sys_ctrl().write(|w| { |
| 1089 | if sys_src == ClkSysCtrlSrc::CLKSRC_CLK_SYS_AUX { | 1051 | w.set_auxsrc(sys_aux); |
| 1090 | w.set_auxsrc(sys_aux); | ||
| 1091 | } | ||
| 1092 | w.set_src(sys_src); | 1052 | w.set_src(sys_src); |
| 1093 | }); | 1053 | }); |
| 1094 | 1054 | ||
| 1095 | // Wait for the clock to be selected | ||
| 1096 | #[cfg(feature = "rp2040")] | 1055 | #[cfg(feature = "rp2040")] |
| 1097 | while c.clk_sys_selected().read() != (1 << sys_src as u32) {} | 1056 | while c.clk_sys_selected().read() != (1 << sys_src as u32) {} |
| 1098 | #[cfg(feature = "_rp235x")] | 1057 | #[cfg(feature = "_rp235x")] |
| 1099 | while c.clk_sys_selected().read() != pac::clocks::regs::ClkSysSelected(1 << sys_src as u32) {} | 1058 | while c.clk_sys_selected().read() != pac::clocks::regs::ClkSysSelected(1 << sys_src as u32) {} |
| 1100 | 1059 | ||
| 1101 | // Short delay after final clock switch to ensure stability | 1060 | c.clk_sys_div().write(|w| { |
| 1102 | cortex_m::asm::delay(100); | 1061 | w.set_int(config.sys_clk.div_int); |
| 1103 | 1062 | w.set_frac(config.sys_clk.div_frac); | |
| 1104 | // Set the divider after changing the source if it's decreasing | 1063 | }); |
| 1105 | if config.sys_clk.div_int == 1 && config.sys_clk.div_frac == 0 { | ||
| 1106 | c.clk_sys_div().write(|w| { | ||
| 1107 | w.set_int(config.sys_clk.div_int); | ||
| 1108 | w.set_frac(config.sys_clk.div_frac); | ||
| 1109 | }); | ||
| 1110 | } | ||
| 1111 | 1064 | ||
| 1112 | // CONFIGURE PERIPHERAL CLOCK | ||
| 1113 | let mut peris = reset::ALL_PERIPHERALS; | 1065 | let mut peris = reset::ALL_PERIPHERALS; |
| 1114 | 1066 | ||
| 1115 | if let Some(src) = config.peri_clk_src { | 1067 | if let Some(src) = config.peri_clk_src { |
| @@ -1136,7 +1088,6 @@ pub(crate) unsafe fn init(config: ClockConfig) { | |||
| 1136 | CLOCKS.peri.store(0, Ordering::Relaxed); | 1088 | CLOCKS.peri.store(0, Ordering::Relaxed); |
| 1137 | } | 1089 | } |
| 1138 | 1090 | ||
| 1139 | // CONFIGURE USB CLOCK | ||
| 1140 | if let Some(conf) = config.usb_clk { | 1091 | if let Some(conf) = config.usb_clk { |
| 1141 | c.clk_usb_div().write(|w| w.set_int(conf.div)); | 1092 | c.clk_usb_div().write(|w| w.set_int(conf.div)); |
| 1142 | c.clk_usb_ctrl().write(|w| { | 1093 | c.clk_usb_ctrl().write(|w| { |
| @@ -1160,7 +1111,6 @@ pub(crate) unsafe fn init(config: ClockConfig) { | |||
| 1160 | CLOCKS.usb.store(0, Ordering::Relaxed); | 1111 | CLOCKS.usb.store(0, Ordering::Relaxed); |
| 1161 | } | 1112 | } |
| 1162 | 1113 | ||
| 1163 | // CONFIGURE ADC CLOCK | ||
| 1164 | if let Some(conf) = config.adc_clk { | 1114 | if let Some(conf) = config.adc_clk { |
| 1165 | c.clk_adc_div().write(|w| w.set_int(conf.div)); | 1115 | c.clk_adc_div().write(|w| w.set_int(conf.div)); |
| 1166 | c.clk_adc_ctrl().write(|w| { | 1116 | c.clk_adc_ctrl().write(|w| { |
| @@ -1184,7 +1134,7 @@ pub(crate) unsafe fn init(config: ClockConfig) { | |||
| 1184 | CLOCKS.adc.store(0, Ordering::Relaxed); | 1134 | CLOCKS.adc.store(0, Ordering::Relaxed); |
| 1185 | } | 1135 | } |
| 1186 | 1136 | ||
| 1187 | // CONFIGURE RTC CLOCK | 1137 | // rp2040 specific clocks |
| 1188 | #[cfg(feature = "rp2040")] | 1138 | #[cfg(feature = "rp2040")] |
| 1189 | if let Some(conf) = config.rtc_clk { | 1139 | if let Some(conf) = config.rtc_clk { |
| 1190 | c.clk_rtc_div().write(|w| { | 1140 | c.clk_rtc_div().write(|w| { |
| @@ -1393,7 +1343,7 @@ fn configure_pll(p: pac::pll::Pll, input_freq: u32, config: PllConfig) -> Result | |||
| 1393 | }); | 1343 | }); |
| 1394 | 1344 | ||
| 1395 | // 5. Wait for PLL to lock with a timeout | 1345 | // 5. Wait for PLL to lock with a timeout |
| 1396 | let mut timeout = 1_000_000; // Reasonable timeout value | 1346 | let mut timeout = 1_000_000; |
| 1397 | while !p.cs().read().lock() { | 1347 | while !p.cs().read().lock() { |
| 1398 | timeout -= 1; | 1348 | timeout -= 1; |
| 1399 | if timeout == 0 { | 1349 | if timeout == 0 { |
