pic32_hal/clock/
refclock.rs1use core::marker::PhantomData;
4
5#[cfg(any(
6 feature = "pic32mx1xxfxxxb",
7 feature = "pic32mx2xxfxxxb",
8 feature = "pic32mx37x",
9 feature = "pic32mx47x",
10))]
11use crate::pac::{osc::RegisterBlock, OSC};
12
13#[cfg(feature = "pic32mx2x4fxxxb")]
14use crate::pac::{cru::RegisterBlock, CRU};
15
16use super::Error;
17
18#[derive(PartialEq, Eq, Clone, Copy, Debug)]
20#[repr(u8)]
21pub enum Source {
22 Sysclock = 0,
23 Pbclock = 1,
24 Posc = 2,
25 Frc = 3,
26 Lprc = 4,
27 Sosc = 5,
28 Usbpll = 6,
29 Syspll = 7,
30 Refclki = 8,
31}
32
33pub struct Refclock {
35 pub(super) _private: PhantomData<()>, }
37
38#[cfg(any(
39 feature = "pic32mx1xxfxxxb",
40 feature = "pic32mx2xxfxxxb",
41 feature = "pic32mx37x",
42 feature = "pic32mx47x",
43))]
44macro_rules! regs {
45 () => {
46 unsafe { &*OSC::ptr() as &RegisterBlock }
47 };
48}
49
50#[cfg(feature = "pic32mx2x4fxxxb")]
51macro_rules! regs {
52 () => {
53 unsafe { &*CRU::ptr() as &RegisterBlock }
54 };
55}
56
57impl Refclock {
58 pub fn enable(&self) {
60 regs!().refoconset.write(|w| w.on().bit(true));
61 while !regs!().refocon.read().active().bit() {}
63 }
64
65 pub fn disable(&self) {
67 regs!().refoconclr.write(|w| w.on().bit(true));
68 while regs!().refocon.read().active().bit() {}
70 }
71
72 pub fn output_enable(&self) {
74 regs!().refoconset.write(|w| w.oe().bit(true));
75 }
76
77 pub fn output_disable(&self) {
79 regs!().refoconclr.write(|w| w.oe().bit(true));
80 }
81
82 pub fn select_source(&self, s: Source) -> Result<(), Error> {
87 if regs!().refocon.read().active().bit() {
88 return Err(Error::InvalidState);
89 }
90 regs!()
91 .refocon
92 .write(|w| unsafe { w.rosel().bits(s as u8) });
93 Ok(())
94 }
95
96 pub fn set_divisor(&self, div_q8: u32) -> Result<(), Error> {
110 let m = div_q8 & 0x1ff; let n = div_q8 >> 9; if n == 0 || n > 32767 {
115 return Err(Error::InvalidArgument);
116 }
117 if self.set_divisor_ongoing() {
118 return Err(Error::InvalidState);
119 }
120 regs!()
121 .refotrim
122 .write(|w| unsafe { w.rotrim().bits(m as u16) });
123 regs!()
124 .refocon
125 .modify(|_, w| unsafe { w.rodiv().bits(n as u16).divswen().bit(true) });
126 Ok(())
127 }
128
129 pub fn set_divisor_ongoing(&self) -> bool {
134 regs!().refocon.read().active().bit() && regs!().refocon.read().divswen().bit()
135 }
136}