diff options
| -rw-r--r-- | embassy-rp/src/clocks.rs | 241 |
1 files changed, 147 insertions, 94 deletions
diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs index 5d3444442..def34fc70 100644 --- a/embassy-rp/src/clocks.rs +++ b/embassy-rp/src/clocks.rs | |||
| @@ -6,32 +6,25 @@ use crate::{pac, reset}; | |||
| 6 | static mut XIN_HZ: u32 = 0; | 6 | static mut XIN_HZ: u32 = 0; |
| 7 | 7 | ||
| 8 | pub struct ClockConfig { | 8 | pub struct ClockConfig { |
| 9 | rosc_config: Option<RoscConfig>, | 9 | rosc: Option<RoscConfig>, |
| 10 | xosc_config: Option<XoscConfig>, | 10 | xosc: Option<XoscConfig>, |
| 11 | ref_clk_config: (RefClkSrc, u8), | 11 | ref_clk: RefClkConfig, |
| 12 | sys_clk_config: (SysClkSrc, u32), | 12 | sys_clk: SysClkConfig, |
| 13 | peri_clk_src: Option<ClkPeriCtrlAuxsrc>, | 13 | peri_clk_src: Option<ClkPeriCtrlAuxsrc>, |
| 14 | usb_clk_config: Option<(ClkUsbCtrlAuxsrc, u8)>, | 14 | usb_clk: Option<UsbClkConfig>, |
| 15 | adc_clk_config: Option<(ClkAdcCtrlAuxsrc, u8)>, | 15 | adc_clk: Option<AdcClkConfig>, |
| 16 | rtc_clk_config: Option<(ClkRtcCtrlAuxsrc, u32)>, | 16 | rtc_clk: Option<RtcClkConfig>, |
| 17 | } | 17 | } |
| 18 | 18 | ||
| 19 | impl ClockConfig { | 19 | impl ClockConfig { |
| 20 | pub fn crystal(crystal_hz: u32) -> Self { | 20 | pub fn crystal(crystal_hz: u32) -> Self { |
| 21 | Self { | 21 | Self { |
| 22 | rosc_config: Some(RoscConfig { | 22 | rosc: Some(RoscConfig { |
| 23 | range: pac::rosc::vals::FreqRange::MEDIUM, | 23 | range: pac::rosc::vals::FreqRange::MEDIUM, |
| 24 | drive_strength_0: 0, | 24 | drive_strength: [0; 8], |
| 25 | drive_strength_1: 0, | ||
| 26 | drive_strength_2: 0, | ||
| 27 | drive_strength_3: 0, | ||
| 28 | drive_strength_4: 0, | ||
| 29 | drive_strength_5: 0, | ||
| 30 | drive_strength_6: 0, | ||
| 31 | drive_strength_7: 0, | ||
| 32 | div: 16, | 25 | div: 16, |
| 33 | }), | 26 | }), |
| 34 | xosc_config: Some(XoscConfig { | 27 | xosc: Some(XoscConfig { |
| 35 | hz: crystal_hz, | 28 | hz: crystal_hz, |
| 36 | clock_type: ExternalClock::Crystal, | 29 | clock_type: ExternalClock::Crystal, |
| 37 | sys_pll: Some(PllConfig { | 30 | sys_pll: Some(PllConfig { |
| @@ -47,42 +40,68 @@ impl ClockConfig { | |||
| 47 | post_div2: 2, | 40 | post_div2: 2, |
| 48 | }), | 41 | }), |
| 49 | }), | 42 | }), |
| 50 | ref_clk_config: (RefClkSrc::Xosc, 1), | 43 | ref_clk: RefClkConfig { |
| 51 | sys_clk_config: (SysClkSrc::Aux(ClkSysCtrlAuxsrc::CLKSRC_PLL_SYS), 1), | 44 | src: RefClkSrc::Xosc, |
| 45 | div: 1, | ||
| 46 | }, | ||
| 47 | sys_clk: SysClkConfig { | ||
| 48 | src: SysClkSrc::Aux(ClkSysCtrlAuxsrc::CLKSRC_PLL_SYS), | ||
| 49 | div_int: 1, | ||
| 50 | div_frac: 0, | ||
| 51 | }, | ||
| 52 | peri_clk_src: Some(ClkPeriCtrlAuxsrc::CLK_SYS), | 52 | peri_clk_src: Some(ClkPeriCtrlAuxsrc::CLK_SYS), |
| 53 | usb_clk_config: Some((ClkUsbCtrlAuxsrc::CLKSRC_PLL_USB, 1)), | 53 | usb_clk: Some(UsbClkConfig { |
| 54 | adc_clk_config: Some((ClkAdcCtrlAuxsrc::CLKSRC_PLL_USB, 1)), | 54 | src: ClkUsbCtrlAuxsrc::CLKSRC_PLL_USB, |
| 55 | rtc_clk_config: Some((ClkRtcCtrlAuxsrc::CLKSRC_PLL_USB, 1024)), | 55 | div: 1, |
| 56 | }), | ||
| 57 | adc_clk: Some(AdcClkConfig { | ||
| 58 | src: ClkAdcCtrlAuxsrc::CLKSRC_PLL_USB, | ||
| 59 | div: 1, | ||
| 60 | }), | ||
| 61 | rtc_clk: Some(RtcClkConfig { | ||
| 62 | src: ClkRtcCtrlAuxsrc::CLKSRC_PLL_USB, | ||
| 63 | div_int: 1024, | ||
| 64 | div_frac: 0, | ||
| 65 | }), | ||
| 56 | } | 66 | } |
| 57 | } | 67 | } |
| 58 | 68 | ||
| 59 | pub fn rosc() -> Self { | 69 | pub fn rosc() -> Self { |
| 60 | Self { | 70 | Self { |
| 61 | rosc_config: Some(RoscConfig { | 71 | rosc: Some(RoscConfig { |
| 62 | range: pac::rosc::vals::FreqRange::HIGH, | 72 | range: pac::rosc::vals::FreqRange::HIGH, |
| 63 | drive_strength_0: 0, | 73 | drive_strength: [0; 8], |
| 64 | drive_strength_1: 0, | ||
| 65 | drive_strength_2: 0, | ||
| 66 | drive_strength_3: 0, | ||
| 67 | drive_strength_4: 0, | ||
| 68 | drive_strength_5: 0, | ||
| 69 | drive_strength_6: 0, | ||
| 70 | drive_strength_7: 0, | ||
| 71 | div: 1, | 74 | div: 1, |
| 72 | }), | 75 | }), |
| 73 | xosc_config: None, | 76 | xosc: None, |
| 74 | ref_clk_config: (RefClkSrc::Rosc, 4), | 77 | ref_clk: RefClkConfig { |
| 75 | sys_clk_config: (SysClkSrc::Aux(ClkSysCtrlAuxsrc::ROSC_CLKSRC), 1), | 78 | src: RefClkSrc::Rosc, |
| 79 | div: 1, | ||
| 80 | }, | ||
| 81 | sys_clk: SysClkConfig { | ||
| 82 | src: SysClkSrc::Aux(ClkSysCtrlAuxsrc::ROSC_CLKSRC), | ||
| 83 | div_int: 1, | ||
| 84 | div_frac: 0, | ||
| 85 | }, | ||
| 76 | peri_clk_src: Some(ClkPeriCtrlAuxsrc::ROSC_CLKSRC_PH), | 86 | peri_clk_src: Some(ClkPeriCtrlAuxsrc::ROSC_CLKSRC_PH), |
| 77 | usb_clk_config: None, | 87 | usb_clk: None, |
| 78 | adc_clk_config: Some((ClkAdcCtrlAuxsrc::ROSC_CLKSRC_PH, 1)), | 88 | adc_clk: Some(AdcClkConfig { |
| 79 | rtc_clk_config: Some((ClkRtcCtrlAuxsrc::ROSC_CLKSRC_PH, 1024)), | 89 | src: ClkAdcCtrlAuxsrc::ROSC_CLKSRC_PH, |
| 90 | div: 1, | ||
| 91 | }), | ||
| 92 | rtc_clk: Some(RtcClkConfig { | ||
| 93 | src: ClkRtcCtrlAuxsrc::ROSC_CLKSRC_PH, | ||
| 94 | div_int: 1024, | ||
| 95 | div_frac: 0, | ||
| 96 | }), | ||
| 80 | } | 97 | } |
| 81 | } | 98 | } |
| 82 | } | 99 | } |
| 83 | pub enum ExternalClock { | 100 | |
| 84 | Crystal, | 101 | pub struct RoscConfig { |
| 85 | Clock, | 102 | range: pac::rosc::vals::FreqRange, |
| 103 | drive_strength: [u8; 8], | ||
| 104 | div: u16, | ||
| 86 | } | 105 | } |
| 87 | 106 | ||
| 88 | pub struct XoscConfig { | 107 | pub struct XoscConfig { |
| @@ -92,19 +111,6 @@ pub struct XoscConfig { | |||
| 92 | usb_pll: Option<PllConfig>, | 111 | usb_pll: Option<PllConfig>, |
| 93 | } | 112 | } |
| 94 | 113 | ||
| 95 | pub struct RoscConfig { | ||
| 96 | range: pac::rosc::vals::FreqRange, | ||
| 97 | drive_strength_0: u8, | ||
| 98 | drive_strength_1: u8, | ||
| 99 | drive_strength_2: u8, | ||
| 100 | drive_strength_3: u8, | ||
| 101 | drive_strength_4: u8, | ||
| 102 | drive_strength_5: u8, | ||
| 103 | drive_strength_6: u8, | ||
| 104 | drive_strength_7: u8, | ||
| 105 | div: u16, | ||
| 106 | } | ||
| 107 | |||
| 108 | pub struct PllConfig { | 114 | pub struct PllConfig { |
| 109 | pub refdiv: u32, | 115 | pub refdiv: u32, |
| 110 | pub vco_freq: u32, | 116 | pub vco_freq: u32, |
| @@ -112,9 +118,13 @@ pub struct PllConfig { | |||
| 112 | pub post_div2: u8, | 118 | pub post_div2: u8, |
| 113 | } | 119 | } |
| 114 | 120 | ||
| 121 | pub enum ExternalClock { | ||
| 122 | Crystal, | ||
| 123 | Clock, | ||
| 124 | } | ||
| 115 | pub struct RefClkConfig { | 125 | pub struct RefClkConfig { |
| 116 | pub src: RefClkSrc, | 126 | src: RefClkSrc, |
| 117 | pub div: u8, | 127 | div: u8, |
| 118 | } | 128 | } |
| 119 | 129 | ||
| 120 | pub enum RefClkSrc { | 130 | pub enum RefClkSrc { |
| @@ -123,16 +133,33 @@ pub enum RefClkSrc { | |||
| 123 | Aux(ClkRefCtrlAuxsrc), | 133 | Aux(ClkRefCtrlAuxsrc), |
| 124 | } | 134 | } |
| 125 | 135 | ||
| 126 | pub struct SysClkConfig { | ||
| 127 | pub src: SysClkSrc, | ||
| 128 | pub div: u32, | ||
| 129 | } | ||
| 130 | |||
| 131 | pub enum SysClkSrc { | 136 | pub enum SysClkSrc { |
| 132 | Ref, | 137 | Ref, |
| 133 | Aux(ClkSysCtrlAuxsrc), | 138 | Aux(ClkSysCtrlAuxsrc), |
| 134 | } | 139 | } |
| 135 | 140 | ||
| 141 | pub struct SysClkConfig { | ||
| 142 | src: SysClkSrc, | ||
| 143 | div_int: u32, | ||
| 144 | div_frac: u8, | ||
| 145 | } | ||
| 146 | |||
| 147 | pub struct UsbClkConfig { | ||
| 148 | src: ClkUsbCtrlAuxsrc, | ||
| 149 | div: u8, | ||
| 150 | } | ||
| 151 | |||
| 152 | pub struct AdcClkConfig { | ||
| 153 | src: ClkAdcCtrlAuxsrc, | ||
| 154 | div: u8, | ||
| 155 | } | ||
| 156 | |||
| 157 | pub struct RtcClkConfig { | ||
| 158 | src: ClkRtcCtrlAuxsrc, | ||
| 159 | div_int: u32, | ||
| 160 | div_frac: u8, | ||
| 161 | } | ||
| 162 | |||
| 136 | /// safety: must be called exactly once at bootup | 163 | /// safety: must be called exactly once at bootup |
| 137 | pub(crate) unsafe fn init(config: ClockConfig) { | 164 | pub(crate) unsafe fn init(config: ClockConfig) { |
| 138 | // Reset everything except: | 165 | // Reset everything except: |
| @@ -160,11 +187,11 @@ pub(crate) unsafe fn init(config: ClockConfig) { | |||
| 160 | c.clk_ref_ctrl().modify(|w| w.set_src(ClkRefCtrlSrc::ROSC_CLKSRC_PH)); | 187 | c.clk_ref_ctrl().modify(|w| w.set_src(ClkRefCtrlSrc::ROSC_CLKSRC_PH)); |
| 161 | while c.clk_ref_selected().read() != 1 {} | 188 | while c.clk_ref_selected().read() != 1 {} |
| 162 | 189 | ||
| 163 | if let Some(config) = config.rosc_config { | 190 | if let Some(config) = config.rosc { |
| 164 | configure_rosc(config); | 191 | configure_rosc(config); |
| 165 | } | 192 | } |
| 166 | 193 | ||
| 167 | if let Some(config) = config.xosc_config { | 194 | if let Some(config) = config.xosc { |
| 168 | XIN_HZ = config.hz; | 195 | XIN_HZ = config.hz; |
| 169 | 196 | ||
| 170 | pac::WATCHDOG.tick().write(|w| { | 197 | pac::WATCHDOG.tick().write(|w| { |
| @@ -188,21 +215,18 @@ pub(crate) unsafe fn init(config: ClockConfig) { | |||
| 188 | } | 215 | } |
| 189 | } | 216 | } |
| 190 | 217 | ||
| 191 | let (src, div) = config.ref_clk_config; | 218 | match config.ref_clk.src { |
| 192 | match src { | ||
| 193 | RefClkSrc::Xosc => { | 219 | RefClkSrc::Xosc => { |
| 194 | c.clk_ref_ctrl().write(|w| { | 220 | c.clk_ref_ctrl().write(|w| { |
| 195 | w.set_src(ClkRefCtrlSrc::XOSC_CLKSRC); | 221 | w.set_src(ClkRefCtrlSrc::XOSC_CLKSRC); |
| 196 | }); | 222 | }); |
| 197 | while c.clk_ref_selected().read() != 1 << ClkRefCtrlSrc::XOSC_CLKSRC.0 {} | 223 | while c.clk_ref_selected().read() != 1 << ClkRefCtrlSrc::XOSC_CLKSRC.0 {} |
| 198 | c.clk_ref_div().write(|w| w.set_int(div)); | ||
| 199 | } | 224 | } |
| 200 | RefClkSrc::Rosc => { | 225 | RefClkSrc::Rosc => { |
| 201 | c.clk_ref_ctrl().write(|w| { | 226 | c.clk_ref_ctrl().write(|w| { |
| 202 | w.set_src(ClkRefCtrlSrc::ROSC_CLKSRC_PH); | 227 | w.set_src(ClkRefCtrlSrc::ROSC_CLKSRC_PH); |
| 203 | }); | 228 | }); |
| 204 | while c.clk_ref_selected().read() != 1 << ClkRefCtrlSrc::ROSC_CLKSRC_PH.0 {} | 229 | while c.clk_ref_selected().read() != 1 << ClkRefCtrlSrc::ROSC_CLKSRC_PH.0 {} |
| 205 | c.clk_ref_div().write(|w| w.set_int(div)); | ||
| 206 | } | 230 | } |
| 207 | RefClkSrc::Aux(src) => { | 231 | RefClkSrc::Aux(src) => { |
| 208 | c.clk_ref_ctrl().write(|w| { | 232 | c.clk_ref_ctrl().write(|w| { |
| @@ -210,23 +234,23 @@ pub(crate) unsafe fn init(config: ClockConfig) { | |||
| 210 | w.set_src(ClkRefCtrlSrc::CLKSRC_CLK_REF_AUX); | 234 | w.set_src(ClkRefCtrlSrc::CLKSRC_CLK_REF_AUX); |
| 211 | }); | 235 | }); |
| 212 | while c.clk_ref_selected().read() != 1 << ClkRefCtrlSrc::CLKSRC_CLK_REF_AUX.0 {} | 236 | while c.clk_ref_selected().read() != 1 << ClkRefCtrlSrc::CLKSRC_CLK_REF_AUX.0 {} |
| 213 | c.clk_ref_div().write(|w| w.set_int(div)); | ||
| 214 | } | 237 | } |
| 215 | } | 238 | } |
| 239 | c.clk_ref_div().write(|w| { | ||
| 240 | w.set_int(config.ref_clk.div); | ||
| 241 | }); | ||
| 216 | 242 | ||
| 217 | pac::WATCHDOG.tick().write(|w| { | 243 | pac::WATCHDOG.tick().write(|w| { |
| 218 | w.set_cycles((clk_ref_freq() / 1_000_000) as u16); | 244 | w.set_cycles((clk_ref_freq() / 1_000_000) as u16); |
| 219 | w.set_enable(true); | 245 | w.set_enable(true); |
| 220 | }); | 246 | }); |
| 221 | 247 | ||
| 222 | let (src, div) = config.sys_clk_config; | 248 | match config.sys_clk.src { |
| 223 | match src { | ||
| 224 | SysClkSrc::Ref => { | 249 | SysClkSrc::Ref => { |
| 225 | c.clk_sys_ctrl().write(|w| { | 250 | c.clk_sys_ctrl().write(|w| { |
| 226 | w.set_src(ClkSysCtrlSrc::CLK_REF); | 251 | w.set_src(ClkSysCtrlSrc::CLK_REF); |
| 227 | }); | 252 | }); |
| 228 | while c.clk_sys_selected().read() != 1 << ClkSysCtrlSrc::CLK_REF.0 {} | 253 | while c.clk_sys_selected().read() != 1 << ClkSysCtrlSrc::CLK_REF.0 {} |
| 229 | c.clk_sys_div().write(|w| w.set_int(div)); | ||
| 230 | } | 254 | } |
| 231 | SysClkSrc::Aux(src) => { | 255 | SysClkSrc::Aux(src) => { |
| 232 | c.clk_sys_ctrl().write(|w| { | 256 | c.clk_sys_ctrl().write(|w| { |
| @@ -234,7 +258,6 @@ pub(crate) unsafe fn init(config: ClockConfig) { | |||
| 234 | }); | 258 | }); |
| 235 | while c.clk_sys_selected().read() != 1 << ClkSysCtrlSrc::CLK_REF.0 {} | 259 | while c.clk_sys_selected().read() != 1 << ClkSysCtrlSrc::CLK_REF.0 {} |
| 236 | 260 | ||
| 237 | c.clk_sys_div().write(|w| w.set_int(div)); | ||
| 238 | c.clk_sys_ctrl().write(|w| { | 261 | c.clk_sys_ctrl().write(|w| { |
| 239 | w.set_auxsrc(src); | 262 | w.set_auxsrc(src); |
| 240 | w.set_src(ClkSysCtrlSrc::CLKSRC_CLK_SYS_AUX); | 263 | w.set_src(ClkSysCtrlSrc::CLKSRC_CLK_SYS_AUX); |
| @@ -242,6 +265,10 @@ pub(crate) unsafe fn init(config: ClockConfig) { | |||
| 242 | while c.clk_sys_selected().read() != 1 << ClkSysCtrlSrc::CLKSRC_CLK_SYS_AUX.0 {} | 265 | while c.clk_sys_selected().read() != 1 << ClkSysCtrlSrc::CLKSRC_CLK_SYS_AUX.0 {} |
| 243 | } | 266 | } |
| 244 | } | 267 | } |
| 268 | c.clk_sys_div().write(|w| { | ||
| 269 | w.set_int(config.sys_clk.div_int); | ||
| 270 | w.set_frac(config.sys_clk.div_frac); | ||
| 271 | }); | ||
| 245 | 272 | ||
| 246 | let mut peris = reset::ALL_PERIPHERALS; | 273 | let mut peris = reset::ALL_PERIPHERALS; |
| 247 | 274 | ||
| @@ -257,37 +284,40 @@ pub(crate) unsafe fn init(config: ClockConfig) { | |||
| 257 | peris.set_uart1(false); | 284 | peris.set_uart1(false); |
| 258 | } | 285 | } |
| 259 | 286 | ||
| 260 | if let Some((src, div)) = config.usb_clk_config { | 287 | if let Some(conf) = config.usb_clk { |
| 261 | // CLK USB = PLL USB (48MHz) / 1 = 48MHz | 288 | // CLK USB = PLL USB (48MHz) / 1 = 48MHz |
| 262 | c.clk_usb_div().write(|w| w.set_int(div)); | 289 | c.clk_usb_div().write(|w| w.set_int(conf.div)); |
| 263 | c.clk_usb_ctrl().write(|w| { | 290 | c.clk_usb_ctrl().write(|w| { |
| 264 | w.set_enable(true); | 291 | w.set_enable(true); |
| 265 | w.set_auxsrc(src); | 292 | w.set_auxsrc(conf.src); |
| 266 | }); | 293 | }); |
| 267 | } else { | 294 | } else { |
| 268 | peris.set_usbctrl(false); | 295 | peris.set_usbctrl(false); |
| 269 | } | 296 | } |
| 270 | 297 | ||
| 271 | if let Some((src, div)) = config.adc_clk_config { | 298 | if let Some(conf) = config.adc_clk { |
| 272 | // CLK ADC = PLL USB (48MHZ) / 1 = 48MHz | 299 | // CLK ADC = PLL USB (48MHZ) / 1 = 48MHz |
| 273 | c.clk_adc_div().write(|w| w.set_int(div)); | 300 | c.clk_adc_div().write(|w| w.set_int(conf.div)); |
| 274 | c.clk_adc_ctrl().write(|w| { | 301 | c.clk_adc_ctrl().write(|w| { |
| 275 | w.set_enable(true); | 302 | w.set_enable(true); |
| 276 | w.set_auxsrc(src); | 303 | w.set_auxsrc(conf.src); |
| 277 | }); | 304 | }); |
| 278 | } else { | 305 | } else { |
| 279 | peris.set_adc(false); | 306 | peris.set_adc(false); |
| 280 | } | 307 | } |
| 281 | 308 | ||
| 282 | if let Some((src, div)) = config.rtc_clk_config { | 309 | if let Some(conf) = config.rtc_clk { |
| 283 | // CLK RTC = PLL USB (48MHz) / 1024 = 46875Hz | 310 | // CLK RTC = PLL USB (48MHz) / 1024 = 46875Hz |
| 284 | c.clk_rtc_ctrl().modify(|w| { | 311 | c.clk_rtc_ctrl().modify(|w| { |
| 285 | w.set_enable(false); | 312 | w.set_enable(false); |
| 286 | }); | 313 | }); |
| 287 | c.clk_rtc_div().write(|w| w.set_int(div)); | 314 | c.clk_rtc_div().write(|w| { |
| 315 | w.set_int(conf.div_int); | ||
| 316 | w.set_frac(conf.div_frac); | ||
| 317 | }); | ||
| 288 | c.clk_rtc_ctrl().write(|w| { | 318 | c.clk_rtc_ctrl().write(|w| { |
| 289 | w.set_enable(true); | 319 | w.set_enable(true); |
| 290 | w.set_auxsrc(src); | 320 | w.set_auxsrc(conf.src); |
| 291 | }); | 321 | }); |
| 292 | } else { | 322 | } else { |
| 293 | peris.set_rtc(false); | 323 | peris.set_rtc(false); |
| @@ -302,18 +332,18 @@ unsafe fn configure_rosc(config: RoscConfig) { | |||
| 302 | 332 | ||
| 303 | p.freqa().write(|w| { | 333 | p.freqa().write(|w| { |
| 304 | w.set_passwd(pac::rosc::vals::Passwd::PASS); | 334 | w.set_passwd(pac::rosc::vals::Passwd::PASS); |
| 305 | w.set_ds0(config.drive_strength_0); | 335 | w.set_ds0(config.drive_strength[0]); |
| 306 | w.set_ds1(config.drive_strength_1); | 336 | w.set_ds1(config.drive_strength[1]); |
| 307 | w.set_ds2(config.drive_strength_2); | 337 | w.set_ds2(config.drive_strength[2]); |
| 308 | w.set_ds3(config.drive_strength_3); | 338 | w.set_ds3(config.drive_strength[3]); |
| 309 | }); | 339 | }); |
| 310 | 340 | ||
| 311 | p.freqb().write(|w| { | 341 | p.freqb().write(|w| { |
| 312 | w.set_passwd(pac::rosc::vals::Passwd::PASS); | 342 | w.set_passwd(pac::rosc::vals::Passwd::PASS); |
| 313 | w.set_ds4(config.drive_strength_4); | 343 | w.set_ds4(config.drive_strength[4]); |
| 314 | w.set_ds5(config.drive_strength_5); | 344 | w.set_ds5(config.drive_strength[5]); |
| 315 | w.set_ds6(config.drive_strength_6); | 345 | w.set_ds6(config.drive_strength[6]); |
| 316 | w.set_ds7(config.drive_strength_7); | 346 | w.set_ds7(config.drive_strength[7]); |
| 317 | }); | 347 | }); |
| 318 | 348 | ||
| 319 | p.div().write(|w| { | 349 | p.div().write(|w| { |
| @@ -637,17 +667,31 @@ unsafe fn configure_pll(p: pac::pll::Pll, input_freq: u32, config: PllConfig) { | |||
| 637 | p.pwr().modify(|w| w.set_postdivpd(false)); | 667 | p.pwr().modify(|w| w.set_postdivpd(false)); |
| 638 | } | 668 | } |
| 639 | 669 | ||
| 640 | pub struct Gpout0 { | 670 | pub trait GpoutPin {} |
| 641 | _pin: crate::peripherals::PIN_21, | 671 | |
| 672 | impl GpoutPin for crate::peripherals::PIN_21 {} | ||
| 673 | impl GpoutPin for crate::peripherals::PIN_23 {} | ||
| 674 | impl GpoutPin for crate::peripherals::PIN_24 {} | ||
| 675 | impl GpoutPin for crate::peripherals::PIN_25 {} | ||
| 676 | |||
| 677 | use embassy_hal_common::{into_ref, PeripheralRef}; | ||
| 678 | |||
| 679 | use crate::Peripheral; | ||
| 680 | |||
| 681 | pub struct Gpout<'d, T: GpoutPin> { | ||
| 682 | _pin: PeripheralRef<'d, T>, | ||
| 642 | } | 683 | } |
| 643 | 684 | ||
| 644 | impl Gpout0 { | 685 | impl<'d, T: GpoutPin> Gpout<'d, T> { |
| 645 | pub fn new(pin: crate::peripherals::PIN_21) -> Self { | 686 | pub fn new(_pin: impl Peripheral<P = T> + 'd) -> Self { |
| 687 | into_ref!(_pin); | ||
| 688 | |||
| 646 | unsafe { | 689 | unsafe { |
| 647 | let p = pac::IO_BANK0.gpio(21).ctrl(); | 690 | let p = pac::IO_BANK0.gpio(21).ctrl(); |
| 648 | p.write(|w| w.set_funcsel(pac::io::vals::Gpio21ctrlFuncsel::CLOCKS_GPOUT_0.0)) | 691 | p.write(|w| w.set_funcsel(pac::io::vals::Gpio21ctrlFuncsel::CLOCKS_GPOUT_0.0)); |
| 649 | } | 692 | } |
| 650 | Self { _pin: pin } | 693 | |
| 694 | Self { _pin } | ||
| 651 | } | 695 | } |
| 652 | 696 | ||
| 653 | pub fn set_div(&self, int: u32, frac: u8) { | 697 | pub fn set_div(&self, int: u32, frac: u8) { |
| @@ -677,6 +721,15 @@ impl Gpout0 { | |||
| 677 | }); | 721 | }); |
| 678 | } | 722 | } |
| 679 | } | 723 | } |
| 724 | |||
| 725 | pub fn disable(&self) { | ||
| 726 | unsafe { | ||
| 727 | let c = pac::CLOCKS; | ||
| 728 | c.clk_gpout0_ctrl().modify(|w| { | ||
| 729 | w.set_enable(true); | ||
| 730 | }); | ||
| 731 | } | ||
| 732 | } | ||
| 680 | } | 733 | } |
| 681 | 734 | ||
| 682 | /// Random number generator based on the ROSC RANDOMBIT register. | 735 | /// Random number generator based on the ROSC RANDOMBIT register. |
