1use ch32v1::ch32v103::{FLASH, RCC};
2use riscv::interrupt::free;
3
4const MAX_CLK_FREQ: u32 = 72_000_000;
5
6#[derive(Clone, Copy, PartialEq, Eq, Debug)]
7pub enum PllSrc {
8 Hsi,
9 Hse(u32),
10 HseDiv2(u32),
11}
12
13impl PllSrc {
14 pub fn bits(&self) -> bool {
15 match self {
16 Self::Hsi => false,
17 _ => true,
18 }
19 }
20}
21
22#[derive(Clone, Copy, PartialEq, Eq, Debug)]
23pub enum InputSrc {
24 Hsi,
25 Hse(u8),
26 Pll(PllSrc),
27 Unavailable,
28}
29
30impl InputSrc {
31 pub fn bits(&self) -> u8 {
32 match self {
33 InputSrc::Hsi => 0,
34 InputSrc::Hse(_) => 1,
35 InputSrc::Pll(_) => 2,
36 InputSrc::Unavailable => 3,
37 }
38 }
39}
40
41#[derive(Clone, Copy, PartialEq, Eq, Debug)]
42pub enum PllMul {
43 Mul2 = 0b0000,
44 Mul3 = 0b0001,
45 Mul4 = 0b0010,
46 Mul5 = 0b0011,
47 Mul6 = 0b0100,
48 Mul7 = 0b0101,
49 Mul8 = 0b0110,
50 Mul9 = 0b0111,
51 Mul10 = 0b1000,
52 Mul11 = 0b1001,
53 Mul12 = 0b1010,
54 Mul13 = 0b1011,
55 Mul14 = 0b1100,
56 Mul15 = 0b1101,
57 Mul16 = 0b1110,
58}
59
60impl PllMul {
61 pub fn val(&self) -> u32 {
62 *self as u32 + 2
63 }
64}
65
66#[derive(Clone, Copy, PartialEq, Eq, Debug)]
67pub enum AHBPreDiv {
68 NoDiv = 0b0000,
69 Div2 = 0b1000,
70 Div4 = 0b1001,
71 Div8 = 0b1010,
72 Div16 = 0b1011,
73 Div64 = 0b1100,
74 Div128 = 0b1101,
75 Div256 = 0b1110,
76 Div512 = 0b1111,
77}
78
79#[derive(Clone, Copy, PartialEq, Eq, Debug)]
80pub enum APB1PreDiv {
81 NoDiv = 0b000,
82 Div2 = 0b100,
83 Div4 = 0b101,
84 Div8 = 0b110,
85 Div16 = 0b111,
86}
87
88#[derive(Clone, Copy, PartialEq, Eq, Debug)]
89pub enum APB2PreDiv {
90 NoDiv = 0b000,
91 Div2 = 0b100,
92 Div4 = 0b101,
93 Div8 = 0b110,
94 Div16 = 0b111,
95}
96
97#[derive(Clone, Copy, PartialEq, Eq, Debug)]
98pub enum ADCPreDiv {
99 Div2 = 0b00,
100 Div4 = 0b01,
101 Div6 = 0b10,
102 Div8 = 0b11,
103}
104
105#[derive(Clone, Copy, PartialEq, Eq, Debug)]
106pub enum USBPreDiv {
107 NoDiv = 0b01,
108 Div1_5 = 0b00,
109}
110
111#[derive(Clone, Copy, PartialEq, Eq, Debug)]
112pub enum RccError {
113 Speed,
114 Hardware,
115}
116
117pub struct Clocks {
118 pub input_src: InputSrc,
119 pub sysclk_state: InputSrc,
120 pub pllmul: PllMul,
121 pub ahb_prediv: AHBPreDiv,
122 pub apb1_prediv: APB1PreDiv,
123 pub apb2_prediv: APB2PreDiv,
124 pub adc_prediv: ADCPreDiv,
125 pub css: bool,
126 pub hse_bypass: bool,
127}
128
129impl Clocks {
130 pub fn setup(&self) -> Result<(), RccError> {
131 let rcc = unsafe { &(*(RCC::ptr())) };
136
137 let flash = unsafe { &(*(FLASH::ptr())) };
138
139 flash.actlr.modify(|_, w| {
140 w.prftbe().bit(true);
141 if self.sysclk() < 48_000_000 {
142 w.latency().one()
143 } else {
144 w.latency().two()
145 }
146 });
147
148 free(|| unsafe {
151 match self.input_src {
152 InputSrc::Hsi => {
153 rcc.ctlr.modify(|_, w| w.hsion().on());
154 while rcc.ctlr.read().hsirdy().is_not_ready() {}
155 }
156 InputSrc::Hse(_) => {
157 rcc.ctlr.modify(|_, w| w.hseon().on());
158 while rcc.ctlr.read().hserdy().is_not_ready() {}
159 }
160 InputSrc::Pll(src) => match src {
161 PllSrc::Hse(_) => {
162 rcc.ctlr.modify(|_, w| w.hseon().bit(true));
163 while rcc.ctlr.read().hserdy().is_not_ready() {}
164 }
165 PllSrc::HseDiv2(_) => {
166 rcc.ctlr.modify(|_, w| w.hseon().on());
167 while rcc.ctlr.read().hserdy().is_not_ready() {}
168 }
169 _ => {
170 rcc.ctlr.modify(|_, w| w.hsion().on());
171 while rcc.ctlr.read().hsirdy().is_not_ready() {}
172 }
173 },
174 InputSrc::Unavailable => {}
175 }
176
177 rcc.ctlr.modify(|_, w| w.hsebyp().bit(self.hse_bypass));
178
179 if let InputSrc::Pll(src) = self.input_src {
180 rcc.ctlr.modify(|_, w| w.pllon().bit(false));
181
182 while rcc.ctlr.read().pllrdy().is_ready() {}
183
184 rcc.cfgr0
185 .modify(|_, w| w.pllsrc().bit(src.bits()).pllmul().bits(self.pllmul as u8));
186
187 rcc.ctlr.modify(|_, w| w.pllon().bit(true));
188
189 while rcc.ctlr.read().pllrdy().is_not_ready() {}
190 }
191
192 rcc.cfgr0.modify(|_, w| {
193 w.sw().bits(self.input_src.bits());
194 w.hpre().bits(self.ahb_prediv as u8);
195 w.ppre1().bits(self.apb1_prediv as u8);
196 w.ppre2().bits(self.apb2_prediv as u8)
197 });
198
199 rcc.ctlr.modify(|_, w| w.csson().bit(self.css));
200 });
201 Ok(())
202 }
203
204 pub fn sysclk(&self) -> u32 {
205 match self.input_src {
206 InputSrc::Hsi => 8_000_000,
207 InputSrc::Hse(f) => f as u32 * 1_000_000,
208 InputSrc::Pll(src) => match src {
209 PllSrc::Hse(v) => v * self.pllmul.val() * 1_000_000,
210 PllSrc::HseDiv2(v) => v / 2 * self.pllmul.val() * 1_000_000,
211 PllSrc::Hsi => 8_000_000 * self.pllmul.val(),
212 },
213 InputSrc::Unavailable => 0,
214 }
215 }
216
217 pub fn hclk(&self) -> u32 {
218 self.sysclk() / self.ahb_prediv as u32
219 }
220
221 pub fn pclk1(&self) -> u32 {
222 self.hclk() / self.apb1_prediv as u32
223 }
224
225 pub fn pclk2(&self) -> u32 {
226 self.hclk() / self.apb2_prediv as u32
227 }
228
229 pub fn adc_clk(&self) -> u32 {
230 self.pclk2() / self.adc_prediv as u32
231 }
232
233 pub fn input_src(&self) -> InputSrc {
234 let rcc = unsafe { &(*(RCC::ptr())) };
235 free(|| {
236 let bits = rcc.cfgr0.read().sws().bits();
237 if bits == 0b00 {
238 InputSrc::Hsi
239 } else if bits == 0b01 || bits == 0b10 {
240 self.input_src
241 } else {
242 InputSrc::Unavailable
243 }
244 })
245 }
246
247 pub fn validate_freq(&self) -> Result<(), RccError> {
248 if self.sysclk() > MAX_CLK_FREQ {
249 return Err(RccError::Speed);
250 }
251
252 if self.hclk() > MAX_CLK_FREQ {
253 return Err(RccError::Speed);
254 }
255
256 if self.pclk1() > MAX_CLK_FREQ {
257 return Err(RccError::Speed);
258 }
259
260 if self.pclk2() > MAX_CLK_FREQ {
261 return Err(RccError::Speed);
262 }
263
264 if self.adc_clk() > 14_000_000 {
265 return Err(RccError::Speed);
266 }
267
268 Ok(())
269 }
270}
271
272impl Default for Clocks {
273 fn default() -> Self {
274 Self {
275 input_src: InputSrc::Hsi,
276 sysclk_state: InputSrc::Hsi,
277 pllmul: PllMul::Mul2,
278 ahb_prediv: AHBPreDiv::NoDiv,
279 apb1_prediv: APB1PreDiv::NoDiv,
280 apb2_prediv: APB2PreDiv::NoDiv,
281 adc_prediv: ADCPreDiv::Div2,
282 css: false,
283 hse_bypass: false,
284 }
285 }
286}