aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaleb Jamison <[email protected]>2023-05-09 17:45:24 -0400
committerCaleb Jamison <[email protected]>2023-05-09 17:45:24 -0400
commit5cfe1a1fb40470dfaf256fc87989fd67884113f1 (patch)
tree25f36348ebb5826b0e314a9e8f01fb25508aef3d
parent6bea07848717857659c737a3bb3eab7c2cd8abdb (diff)
Dirbaio comments round 2
-rw-r--r--embassy-rp/src/clocks.rs191
-rw-r--r--examples/rp/src/bin/gpout.rs10
2 files changed, 107 insertions, 94 deletions
diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs
index b919b98a9..1354ccd27 100644
--- a/embassy-rp/src/clocks.rs
+++ b/embassy-rp/src/clocks.rs
@@ -6,15 +6,22 @@ use crate::{pac, reset, Peripheral};
6// TODO fix terrible use of global here 6// TODO fix terrible use of global here
7static mut XIN_HZ: u32 = 0; 7static mut XIN_HZ: u32 = 0;
8 8
9pub use rp_pac::clocks::vals::{
10 ClkAdcCtrlAuxsrc as AdcAuxsrc, ClkGpoutCtrlAuxsrc as GpoutSrc, ClkPeriCtrlAuxsrc as PeriClkAuxsrc,
11 ClkRefCtrlAuxsrc as RefAuxsrc, ClkRtcCtrlAuxsrc as RtcAuxsrc, ClkSysCtrlAuxsrc as SysAuxsrc,
12 ClkUsbCtrlAuxsrc as UsbAuxsrc,
13};
14
15#[non_exhaustive]
9pub struct ClockConfig { 16pub struct ClockConfig {
10 rosc: Option<RoscConfig>, 17 pub rosc: Option<RoscConfig>,
11 xosc: Option<XoscConfig>, 18 pub xosc: Option<XoscConfig>,
12 ref_clk: RefClkConfig, 19 pub ref_clk: RefClkConfig,
13 sys_clk: SysClkConfig, 20 pub sys_clk: SysClkConfig,
14 peri_clk_src: Option<ClkPeriCtrlAuxsrc>, 21 pub peri_clk_src: Option<ClkPeriCtrlAuxsrc>,
15 usb_clk: Option<UsbClkConfig>, 22 pub usb_clk: Option<UsbClkConfig>,
16 adc_clk: Option<AdcClkConfig>, 23 pub adc_clk: Option<AdcClkConfig>,
17 rtc_clk: Option<RtcClkConfig>, 24 pub rtc_clk: Option<RtcClkConfig>,
18} 25}
19 26
20impl ClockConfig { 27impl ClockConfig {
@@ -54,15 +61,18 @@ impl ClockConfig {
54 usb_clk: Some(UsbClkConfig { 61 usb_clk: Some(UsbClkConfig {
55 src: ClkUsbCtrlAuxsrc::CLKSRC_PLL_USB, 62 src: ClkUsbCtrlAuxsrc::CLKSRC_PLL_USB,
56 div: 1, 63 div: 1,
64 phase: 0,
57 }), 65 }),
58 adc_clk: Some(AdcClkConfig { 66 adc_clk: Some(AdcClkConfig {
59 src: ClkAdcCtrlAuxsrc::CLKSRC_PLL_USB, 67 src: ClkAdcCtrlAuxsrc::CLKSRC_PLL_USB,
60 div: 1, 68 div: 1,
69 phase: 0,
61 }), 70 }),
62 rtc_clk: Some(RtcClkConfig { 71 rtc_clk: Some(RtcClkConfig {
63 src: ClkRtcCtrlAuxsrc::CLKSRC_PLL_USB, 72 src: ClkRtcCtrlAuxsrc::CLKSRC_PLL_USB,
64 div_int: 1024, 73 div_int: 1024,
65 div_frac: 0, 74 div_frac: 0,
75 phase: 0,
66 }), 76 }),
67 } 77 }
68 } 78 }
@@ -89,27 +99,29 @@ impl ClockConfig {
89 adc_clk: Some(AdcClkConfig { 99 adc_clk: Some(AdcClkConfig {
90 src: ClkAdcCtrlAuxsrc::ROSC_CLKSRC_PH, 100 src: ClkAdcCtrlAuxsrc::ROSC_CLKSRC_PH,
91 div: 1, 101 div: 1,
102 phase: 0,
92 }), 103 }),
93 rtc_clk: Some(RtcClkConfig { 104 rtc_clk: Some(RtcClkConfig {
94 src: ClkRtcCtrlAuxsrc::ROSC_CLKSRC_PH, 105 src: ClkRtcCtrlAuxsrc::ROSC_CLKSRC_PH,
95 div_int: 1024, 106 div_int: 1024,
96 div_frac: 0, 107 div_frac: 0,
108 phase: 0,
97 }), 109 }),
98 } 110 }
99 } 111 }
100} 112}
101 113
102pub struct RoscConfig { 114pub struct RoscConfig {
103 range: pac::rosc::vals::FreqRange, 115 pub range: pac::rosc::vals::FreqRange,
104 drive_strength: [u8; 8], 116 pub drive_strength: [u8; 8],
105 div: u16, 117 pub div: u16,
106} 118}
107 119
108pub struct XoscConfig { 120pub struct XoscConfig {
109 hz: u32, 121 pub hz: u32,
110 clock_type: ExternalClock, 122 pub clock_type: ExternalClock,
111 sys_pll: Option<PllConfig>, 123 pub sys_pll: Option<PllConfig>,
112 usb_pll: Option<PllConfig>, 124 pub usb_pll: Option<PllConfig>,
113} 125}
114 126
115pub struct PllConfig { 127pub struct PllConfig {
@@ -124,8 +136,8 @@ pub enum ExternalClock {
124 Clock, 136 Clock,
125} 137}
126pub struct RefClkConfig { 138pub struct RefClkConfig {
127 src: RefClkSrc, 139 pub src: RefClkSrc,
128 div: u8, 140 pub div: u8,
129} 141}
130 142
131pub enum RefClkSrc { 143pub enum RefClkSrc {
@@ -140,25 +152,28 @@ pub enum SysClkSrc {
140} 152}
141 153
142pub struct SysClkConfig { 154pub struct SysClkConfig {
143 src: SysClkSrc, 155 pub src: SysClkSrc,
144 div_int: u32, 156 pub div_int: u32,
145 div_frac: u8, 157 pub div_frac: u8,
146} 158}
147 159
148pub struct UsbClkConfig { 160pub struct UsbClkConfig {
149 src: ClkUsbCtrlAuxsrc, 161 pub src: ClkUsbCtrlAuxsrc,
150 div: u8, 162 pub div: u8,
163 pub phase: u8,
151} 164}
152 165
153pub struct AdcClkConfig { 166pub struct AdcClkConfig {
154 src: ClkAdcCtrlAuxsrc, 167 pub src: ClkAdcCtrlAuxsrc,
155 div: u8, 168 pub div: u8,
169 pub phase: u8,
156} 170}
157 171
158pub struct RtcClkConfig { 172pub struct RtcClkConfig {
159 src: ClkRtcCtrlAuxsrc, 173 pub src: ClkRtcCtrlAuxsrc,
160 div_int: u32, 174 pub div_int: u32,
161 div_frac: u8, 175 pub div_frac: u8,
176 pub phase: u8,
162} 177}
163 178
164/// safety: must be called exactly once at bootup 179/// safety: must be called exactly once at bootup
@@ -289,6 +304,7 @@ pub(crate) unsafe fn init(config: ClockConfig) {
289 // CLK USB = PLL USB (48MHz) / 1 = 48MHz 304 // CLK USB = PLL USB (48MHz) / 1 = 48MHz
290 c.clk_usb_div().write(|w| w.set_int(conf.div)); 305 c.clk_usb_div().write(|w| w.set_int(conf.div));
291 c.clk_usb_ctrl().write(|w| { 306 c.clk_usb_ctrl().write(|w| {
307 w.set_phase(conf.phase);
292 w.set_enable(true); 308 w.set_enable(true);
293 w.set_auxsrc(conf.src); 309 w.set_auxsrc(conf.src);
294 }); 310 });
@@ -300,6 +316,7 @@ pub(crate) unsafe fn init(config: ClockConfig) {
300 // CLK ADC = PLL USB (48MHZ) / 1 = 48MHz 316 // CLK ADC = PLL USB (48MHZ) / 1 = 48MHz
301 c.clk_adc_div().write(|w| w.set_int(conf.div)); 317 c.clk_adc_div().write(|w| w.set_int(conf.div));
302 c.clk_adc_ctrl().write(|w| { 318 c.clk_adc_ctrl().write(|w| {
319 w.set_phase(conf.phase);
303 w.set_enable(true); 320 w.set_enable(true);
304 w.set_auxsrc(conf.src); 321 w.set_auxsrc(conf.src);
305 }); 322 });
@@ -317,6 +334,7 @@ pub(crate) unsafe fn init(config: ClockConfig) {
317 w.set_frac(conf.div_frac); 334 w.set_frac(conf.div_frac);
318 }); 335 });
319 c.clk_rtc_ctrl().write(|w| { 336 c.clk_rtc_ctrl().write(|w| {
337 w.set_phase(conf.phase);
320 w.set_enable(true); 338 w.set_enable(true);
321 w.set_auxsrc(conf.src); 339 w.set_auxsrc(conf.src);
322 }); 340 });
@@ -544,33 +562,6 @@ pub fn clk_rtc_freq() -> u32 {
544 base / int 562 base / int
545} 563}
546 564
547pub fn clk_gpout_freq<T: GpoutPin>(gpout: &Gpout<T>) -> u32 {
548 let c = pac::CLOCKS;
549 let src = unsafe { c.clk_gpout_ctrl(gpout.gpout.gpout_number()).read().auxsrc() };
550
551 let base = match src {
552 ClkGpoutCtrlAuxsrc::CLKSRC_PLL_SYS => pll_sys_freq(),
553 ClkGpoutCtrlAuxsrc::CLKSRC_GPIN0 => gpin0_freq(),
554 ClkGpoutCtrlAuxsrc::CLKSRC_GPIN1 => gpin1_freq(),
555 ClkGpoutCtrlAuxsrc::CLKSRC_PLL_USB => pll_usb_freq(),
556 ClkGpoutCtrlAuxsrc::ROSC_CLKSRC => estimate_rosc_freq(),
557 ClkGpoutCtrlAuxsrc::XOSC_CLKSRC => xosc_freq(),
558 ClkGpoutCtrlAuxsrc::CLK_SYS => clk_sys_freq(),
559 ClkGpoutCtrlAuxsrc::CLK_USB => clk_usb_freq(),
560 ClkGpoutCtrlAuxsrc::CLK_ADC => clk_adc_freq(),
561 ClkGpoutCtrlAuxsrc::CLK_RTC => clk_rtc_freq(),
562 ClkGpoutCtrlAuxsrc::CLK_REF => clk_ref_freq(),
563 _ => unreachable!(),
564 };
565
566 let div = unsafe { c.clk_gpout_div(gpout.gpout.gpout_number()).read() };
567 let int = if div.int() == 0 { 65536 } else { div.int() };
568 // TODO handle fractional clock div
569 let _frac = div.frac();
570
571 base / int
572}
573
574unsafe fn start_xosc(crystal_hz: u32) { 565unsafe fn start_xosc(crystal_hz: u32) {
575 pac::XOSC 566 pac::XOSC
576 .ctrl() 567 .ctrl()
@@ -641,20 +632,16 @@ unsafe fn configure_pll(p: pac::pll::Pll, input_freq: u32, config: PllConfig) {
641 p.pwr().modify(|w| w.set_postdivpd(false)); 632 p.pwr().modify(|w| w.set_postdivpd(false));
642} 633}
643 634
644pub trait GpinPin { 635pub trait GpinPin: crate::gpio::Pin {
645 fn gpin_number(&self) -> usize; 636 fn number(&self) -> usize;
646 fn pin_number(&self) -> usize;
647} 637}
648 638
649macro_rules! impl_gpinpin { 639macro_rules! impl_gpinpin {
650 ($name:ident, $pin_num:expr, $gpin_num:expr) => { 640 ($name:ident, $pin_num:expr, $gpin_num:expr) => {
651 impl GpinPin for crate::peripherals::$name { 641 impl GpinPin for crate::peripherals::$name {
652 fn gpin_number(&self) -> usize { 642 fn number(&self) -> usize {
653 $gpin_num 643 $gpin_num
654 } 644 }
655 fn pin_number(&self) -> usize {
656 $pin_num
657 }
658 } 645 }
659 }; 646 };
660} 647}
@@ -663,53 +650,50 @@ impl_gpinpin!(PIN_20, 20, 0);
663impl_gpinpin!(PIN_22, 22, 1); 650impl_gpinpin!(PIN_22, 22, 1);
664 651
665pub struct Gpin<'d, T: GpinPin> { 652pub struct Gpin<'d, T: GpinPin> {
666 gpout: PeripheralRef<'d, T>, 653 gpin: PeripheralRef<'d, T>,
667} 654}
668 655
669impl<'d, T: GpinPin> Gpin<'d, T> { 656impl<'d, T: GpinPin> Gpin<'d, T> {
670 pub fn new(gpout: impl Peripheral<P = T> + 'd) -> Self { 657 pub fn new(gpin: impl Peripheral<P = T> + 'd) -> Self {
671 into_ref!(gpout); 658 into_ref!(gpin);
672 659
673 unsafe { 660 unsafe {
674 let p = pac::IO_BANK0.gpio(gpout.pin_number()).ctrl(); 661 gpin.io().ctrl().write(|w| w.set_funcsel(0x08));
675 p.write(|w| w.set_funcsel(0x08));
676 } 662 }
677 663
678 Self { gpout } 664 Self { gpin }
679 } 665 }
680} 666}
681 667
682impl<'d, T: GpinPin> Drop for Gpin<'d, T> { 668impl<'d, T: GpinPin> Drop for Gpin<'d, T> {
683 fn drop(&mut self) { 669 fn drop(&mut self) {
684 unsafe { 670 unsafe {
685 let p = pac::IO_BANK0.gpio(self.gpout.pin_number()).ctrl(); 671 self.gpin
686 p.write(|w| w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::NULL.0)); 672 .io()
673 .ctrl()
674 .write(|w| w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::NULL.0));
687 } 675 }
688 } 676 }
689} 677}
690 678
691pub trait GpoutPin { 679pub trait GpoutPin: crate::gpio::Pin {
692 fn gpout_number(&self) -> usize; 680 fn number(&self) -> usize;
693 fn pin_number(&self) -> usize;
694} 681}
695 682
696macro_rules! impl_gpoutpin { 683macro_rules! impl_gpoutpin {
697 ($name:ident, $pin_num:expr, $gpout_num:expr) => { 684 ($name:ident, $gpout_num:expr) => {
698 impl GpoutPin for crate::peripherals::$name { 685 impl GpoutPin for crate::peripherals::$name {
699 fn gpout_number(&self) -> usize { 686 fn number(&self) -> usize {
700 $gpout_num 687 $gpout_num
701 } 688 }
702 fn pin_number(&self) -> usize {
703 $pin_num
704 }
705 } 689 }
706 }; 690 };
707} 691}
708 692
709impl_gpoutpin!(PIN_21, 21, 0); 693impl_gpoutpin!(PIN_21, 0);
710impl_gpoutpin!(PIN_23, 23, 1); 694impl_gpoutpin!(PIN_23, 1);
711impl_gpoutpin!(PIN_24, 24, 2); 695impl_gpoutpin!(PIN_24, 2);
712impl_gpoutpin!(PIN_25, 25, 3); 696impl_gpoutpin!(PIN_25, 3);
713 697
714pub struct Gpout<'d, T: GpoutPin> { 698pub struct Gpout<'d, T: GpoutPin> {
715 gpout: PeripheralRef<'d, T>, 699 gpout: PeripheralRef<'d, T>,
@@ -720,8 +704,7 @@ impl<'d, T: GpoutPin> Gpout<'d, T> {
720 into_ref!(gpout); 704 into_ref!(gpout);
721 705
722 unsafe { 706 unsafe {
723 let p = pac::IO_BANK0.gpio(gpout.pin_number()).ctrl(); 707 gpout.io().ctrl().write(|w| w.set_funcsel(0x08));
724 p.write(|w| w.set_funcsel(0x08));
725 } 708 }
726 709
727 Self { gpout } 710 Self { gpout }
@@ -730,7 +713,7 @@ impl<'d, T: GpoutPin> Gpout<'d, T> {
730 pub fn set_div(&self, int: u32, frac: u8) { 713 pub fn set_div(&self, int: u32, frac: u8) {
731 unsafe { 714 unsafe {
732 let c = pac::CLOCKS; 715 let c = pac::CLOCKS;
733 c.clk_gpout_div(self.gpout.gpout_number()).write(|w| { 716 c.clk_gpout_div(self.gpout.number()).write(|w| {
734 w.set_int(int); 717 w.set_int(int);
735 w.set_frac(frac); 718 w.set_frac(frac);
736 }); 719 });
@@ -740,7 +723,7 @@ impl<'d, T: GpoutPin> Gpout<'d, T> {
740 pub fn set_src(&self, src: ClkGpoutCtrlAuxsrc) { 723 pub fn set_src(&self, src: ClkGpoutCtrlAuxsrc) {
741 unsafe { 724 unsafe {
742 let c = pac::CLOCKS; 725 let c = pac::CLOCKS;
743 c.clk_gpout_ctrl(self.gpout.gpout_number()).modify(|w| { 726 c.clk_gpout_ctrl(self.gpout.number()).modify(|w| {
744 w.set_auxsrc(src); 727 w.set_auxsrc(src);
745 }); 728 });
746 } 729 }
@@ -749,7 +732,7 @@ impl<'d, T: GpoutPin> Gpout<'d, T> {
749 pub fn enable(&self) { 732 pub fn enable(&self) {
750 unsafe { 733 unsafe {
751 let c = pac::CLOCKS; 734 let c = pac::CLOCKS;
752 c.clk_gpout_ctrl(self.gpout.gpout_number()).modify(|w| { 735 c.clk_gpout_ctrl(self.gpout.number()).modify(|w| {
753 w.set_enable(true); 736 w.set_enable(true);
754 }); 737 });
755 } 738 }
@@ -758,18 +741,48 @@ impl<'d, T: GpoutPin> Gpout<'d, T> {
758 pub fn disable(&self) { 741 pub fn disable(&self) {
759 unsafe { 742 unsafe {
760 let c = pac::CLOCKS; 743 let c = pac::CLOCKS;
761 c.clk_gpout_ctrl(self.gpout.gpout_number()).modify(|w| { 744 c.clk_gpout_ctrl(self.gpout.number()).modify(|w| {
762 w.set_enable(false); 745 w.set_enable(false);
763 }); 746 });
764 } 747 }
765 } 748 }
749
750 pub fn get_freq(&self) -> u32 {
751 let c = pac::CLOCKS;
752 let src = unsafe { c.clk_gpout_ctrl(self.gpout.number()).read().auxsrc() };
753
754 let base = match src {
755 ClkGpoutCtrlAuxsrc::CLKSRC_PLL_SYS => pll_sys_freq(),
756 ClkGpoutCtrlAuxsrc::CLKSRC_GPIN0 => gpin0_freq(),
757 ClkGpoutCtrlAuxsrc::CLKSRC_GPIN1 => gpin1_freq(),
758 ClkGpoutCtrlAuxsrc::CLKSRC_PLL_USB => pll_usb_freq(),
759 ClkGpoutCtrlAuxsrc::ROSC_CLKSRC => estimate_rosc_freq(),
760 ClkGpoutCtrlAuxsrc::XOSC_CLKSRC => xosc_freq(),
761 ClkGpoutCtrlAuxsrc::CLK_SYS => clk_sys_freq(),
762 ClkGpoutCtrlAuxsrc::CLK_USB => clk_usb_freq(),
763 ClkGpoutCtrlAuxsrc::CLK_ADC => clk_adc_freq(),
764 ClkGpoutCtrlAuxsrc::CLK_RTC => clk_rtc_freq(),
765 ClkGpoutCtrlAuxsrc::CLK_REF => clk_ref_freq(),
766 _ => unreachable!(),
767 };
768
769 let div = unsafe { c.clk_gpout_div(self.gpout.number()).read() };
770 let int = if div.int() == 0 { 65536 } else { div.int() };
771 // TODO handle fractional clock div
772 let _frac = div.frac();
773
774 base / int
775 }
766} 776}
767 777
768impl<'d, T: GpoutPin> Drop for Gpout<'d, T> { 778impl<'d, T: GpoutPin> Drop for Gpout<'d, T> {
769 fn drop(&mut self) { 779 fn drop(&mut self) {
780 self.disable();
770 unsafe { 781 unsafe {
771 let p = pac::IO_BANK0.gpio(self.gpout.pin_number()).ctrl(); 782 self.gpout
772 p.write(|w| w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::NULL.0)); 783 .io()
784 .ctrl()
785 .write(|w| w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::NULL.0));
773 } 786 }
774 } 787 }
775} 788}
diff --git a/examples/rp/src/bin/gpout.rs b/examples/rp/src/bin/gpout.rs
index ea0efb859..236a653ac 100644
--- a/examples/rp/src/bin/gpout.rs
+++ b/examples/rp/src/bin/gpout.rs
@@ -4,7 +4,7 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_rp::{clocks, pac}; 7use embassy_rp::clocks;
8use embassy_time::{Duration, Timer}; 8use embassy_time::{Duration, Timer};
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
@@ -17,17 +17,17 @@ async fn main(_spawner: Spawner) {
17 gpout3.enable(); 17 gpout3.enable();
18 18
19 loop { 19 loop {
20 gpout3.set_src(pac::clocks::vals::ClkGpoutCtrlAuxsrc::CLK_SYS); 20 gpout3.set_src(clocks::GpoutSrc::CLK_SYS);
21 info!( 21 info!(
22 "Pin 25 is now outputing CLK_SYS/1000, should be toggling at {}", 22 "Pin 25 is now outputing CLK_SYS/1000, should be toggling at {}",
23 clocks::clk_gpout_freq(&gpout3) 23 gpout3.get_freq()
24 ); 24 );
25 Timer::after(Duration::from_secs(2)).await; 25 Timer::after(Duration::from_secs(2)).await;
26 26
27 gpout3.set_src(pac::clocks::vals::ClkGpoutCtrlAuxsrc::CLK_REF); 27 gpout3.set_src(clocks::GpoutSrc::CLK_REF);
28 info!( 28 info!(
29 "Pin 25 is now outputing CLK_REF/1000, should be toggling at {}", 29 "Pin 25 is now outputing CLK_REF/1000, should be toggling at {}",
30 clocks::clk_gpout_freq(&gpout3) 30 gpout3.get_freq()
31 ); 31 );
32 Timer::after(Duration::from_secs(2)).await; 32 Timer::after(Duration::from_secs(2)).await;
33 } 33 }