1use fugit::HertzU32 as Hertz;
2use qingke::riscv;
3
4use crate::pac::Sys;
5use crate::with_safe_access;
6
7const HSE_FREQUENCY: Hertz = Hertz::from_raw(32_000_000);
9const PLL_FREQUENCY: Hertz = Hertz::from_raw(480_000_000);
10
11static mut CLOCK: Clocks = Clocks {
12 hclk: Hertz::from_raw(6_400_000),
14};
15
16#[derive(Copy, Clone, Eq, PartialEq, Debug)]
17pub struct Clocks {
18 pub hclk: Hertz,
19}
20
21#[inline]
22pub fn clocks() -> &'static Clocks {
23 unsafe { &CLOCK }
24}
25
26#[derive(Clone, Copy, Debug, PartialEq, Default)]
28pub enum Clock32KSrc {
29 #[default]
30 LSI,
31 LSE,
32}
33
34#[derive(Clone, Copy, Debug, PartialEq)]
35#[repr(u8)]
36pub enum ClockSrc {
37 Clock32K,
39 HSE(u8),
41 PLL(u8),
43}
44
45impl Default for ClockSrc {
46 fn default() -> Self {
47 Self::PLL(8)
48 }
49}
50
51#[derive(Clone, Copy, Debug, PartialEq, Default)]
52pub struct Config {
53 pub clock32ksrc: Clock32KSrc,
54 pub mux: ClockSrc,
55}
56
57impl Config {
58 pub fn use_lsi_32k(&mut self) -> &mut Self {
59 self.clock32ksrc = Clock32KSrc::LSI;
60 self.mux = ClockSrc::Clock32K;
61 self
62 }
63
64 pub fn use_lse_32k(&mut self) -> &mut Self {
65 self.clock32ksrc = Clock32KSrc::LSE;
66 self.mux = ClockSrc::Clock32K;
67 self
68 }
69
70 pub fn use_pll_60mhz(&mut self) -> &mut Self {
71 self.mux = ClockSrc::PLL(8);
72 self
73 }
74
75 pub fn use_pll_80mhz(&mut self) -> &mut Self {
76 self.mux = ClockSrc::PLL(6);
77 self
78 }
79
80 pub fn use_pll_48mhz(&mut self) -> &mut Self {
81 self.mux = ClockSrc::PLL(10);
82 self
83 }
84
85 pub fn use_pll_32mhz(&mut self) -> &mut Self {
86 self.mux = ClockSrc::PLL(15);
87 self
88 }
89
90 pub fn use_pll_24mhz(&mut self) -> &mut Self {
91 self.mux = ClockSrc::PLL(20);
92 self
93 }
94
95 pub fn use_pll_20mhz(&mut self) -> &mut Self {
96 self.mux = ClockSrc::PLL(24);
97 self
98 }
99
100 pub fn enable_lse(&mut self) -> &mut Self {
101 self.clock32ksrc = Clock32KSrc::LSE;
102 self
103 }
104
105 pub fn freeze(self) {
106 let sys = unsafe { &*Sys::PTR };
107
108 match self.clock32ksrc {
110 Clock32KSrc::LSE => {
111 with_safe_access(|| {
112 sys.r8_ck32k_config().modify(|_, w| w.rb_clk_xt32k_pon().set_bit());
113 });
114 riscv::asm::delay(clocks().hclk.to_Hz() / 10 / 4);
115 with_safe_access(|| {
119 sys.r8_ck32k_config().modify(|_, w| w.rb_clk_osc32k_xt().set_bit());
120 });
121 riscv::asm::delay(clocks().hclk.to_Hz() / 1000);
122 }
123 Clock32KSrc::LSI => {
124 with_safe_access(|| {
125 sys.r8_ck32k_config()
126 .modify(|_, w| w.rb_clk_osc32k_xt().clear_bit().rb_clk_int32k_pon().set_bit());
127 });
128 }
129 }
130
131 with_safe_access(|| unsafe {
132 sys.r8_pll_config().modify(|r, w| w.bits(r.bits() & !(1 << 5)));
133 });
134 let hclk = match self.mux {
135 ClockSrc::HSE(div) => {
136 assert!(div != 1, "1 means close HCLK");
137 if sys.r8_hfck_pwr_ctrl().read().rb_clk_xt32m_pon().bit_is_clear() {
138 with_safe_access(|| sys.r8_hfck_pwr_ctrl().modify(|_, w| w.rb_clk_xt32m_pon().set_bit()));
140 unsafe {
141 riscv::asm::delay(2400);
142 }
143 }
144 with_safe_access(|| {
145 sys.r16_clk_sys_cfg()
146 .write(|w| unsafe { w.rb_clk_sys_mod().bits(0b00).rb_clk_pll_div().bits(div & 0x1f) });
147 riscv::asm::nop();
148 riscv::asm::nop();
149 riscv::asm::nop();
150 riscv::asm::nop();
151 });
152 riscv::asm::nop();
153 riscv::asm::nop();
154 with_safe_access(|| {
155 sys.r8_adc_cfg().write(|w| unsafe { w.bits(0x51) });
156 });
157 Hertz::from_raw(HSE_FREQUENCY.to_Hz() / (div as u32))
158 }
159 ClockSrc::PLL(div) => {
160 assert!(div != 1, "1 means close HCLK");
161 if sys.r8_hfck_pwr_ctrl().read().rb_clk_pll_pon().bit_is_clear() {
162 with_safe_access(|| sys.r8_hfck_pwr_ctrl().modify(|_, w| w.rb_clk_pll_pon().set_bit()));
164 riscv::asm::delay(4000);
165 }
166 with_safe_access(|| {
167 sys.r16_clk_sys_cfg()
168 .write(|w| unsafe { w.rb_clk_sys_mod().bits(0b01).rb_clk_pll_div().bits(div & 0x1f) });
169 riscv::asm::nop();
170 riscv::asm::nop();
171 riscv::asm::nop();
172 riscv::asm::nop();
173 });
174 if div == 6 {
175 with_safe_access(|| unsafe {
177 sys.r8_adc_cfg().modify(|_, w| w.bits(0x02));
178 });
179 } else {
180 with_safe_access(|| unsafe {
181 sys.r8_adc_cfg().modify(|_, w| w.bits(0x52));
182 });
183 }
184 Hertz::from_raw(PLL_FREQUENCY.to_Hz() / (div as u32))
185 }
186 _ => {
187 with_safe_access(|| unsafe {
189 sys.r16_clk_sys_cfg().modify(|r, w| w.bits(r.bits() | 0xC0));
190 });
191 Hertz::from_raw(32_768)
192 }
193 };
194 with_safe_access(|| unsafe {
195 sys.r8_pll_config().modify(|r, w| w.bits(r.bits() | (1 << 7)));
196 });
197
198 unsafe {
199 CLOCK = Clocks { hclk };
200 }
201 }
202}
203
204pub unsafe fn calibrate_lsi() {}