ch32v103_hal/
clocks.rs

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        // if let Err(e) = self.validate_freq() {
132        //     return Err(e);
133        // }
134
135        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        // let sysclk = self.sysclk();
149
150        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}