Skip to main content

gd32e2_hal/
syscfg.rs

1//! System configuration: the registers that wire peripherals to each other
2//! rather than to the outside world.
3//!
4//! Covers the boot mode, the interrupt latency, the SRAM parity error flag, the
5//! `PA11`/`PA12` remap of packages below 32 pins and `EXTISS`, the latter
6//! through [`ExtiLine::source`](crate::exti::ExtiLine::source).
7
8#[cfg(not(pads_ge_lqfp32))]
9use crate::gpio::{Active, Input, Pin};
10use crate::pac;
11use crate::rcu::Rcu;
12
13/// The memory the chip booted from (`BOOT_MODE`).
14#[derive(Clone, Copy, PartialEq, Eq)]
15#[cfg_attr(feature = "defmt", derive(defmt::Format))]
16pub enum BootMode {
17    /// Main flash: the application.
18    MainFlash,
19    /// System flash memory: the factory bootloader.
20    SystemFlash,
21    /// Embedded SRAM.
22    Sram,
23}
24
25/// Owns the SYSCFG registers.
26pub struct Syscfg {
27    syscfg: pac::Syscfg,
28}
29
30impl Syscfg {
31    /// Returns the peripheral. The clock stays on, since `CFGCMPEN` also feeds
32    /// the comparator.
33    pub fn release(self) -> pac::Syscfg {
34        self.syscfg
35    }
36
37    /// Returns the memory the chip booted from, as latched at the last reset.
38    pub fn boot_mode(&self) -> BootMode {
39        match self.syscfg.cfg0().read().boot_mode().bits() {
40            0b00 | 0b10 => BootMode::MainFlash,
41            0b01 => BootMode::SystemFlash,
42            0b11 => BootMode::Sram,
43            _ => unreachable!(),
44        }
45    }
46
47    /// Holds interrupt entry back to no sooner than `latency + 1` cycles of
48    /// `hclk` after the interrupt pends. A value above the worst natural latency
49    /// makes entry take the same time whatever the core was executing; `0`, the
50    /// reset value, enters as early as possible.
51    pub fn set_irq_latency(&mut self, latency: u8) {
52        // SAFETY: the field is eight bits wide, so every `u8` is a latency.
53        self.syscfg
54            .cpu_irq_lat()
55            .modify(|_, w| unsafe { w.irq_latency().bits(latency) });
56    }
57
58    /// Whether an SRAM parity error has been caught (`SRAM_PCEF`). Raised only
59    /// while the check is on, see
60    /// [`OptionBytes::sram_parity`](crate::fmc::OptionBytes::sram_parity).
61    pub fn sram_pcef(&self) -> bool {
62        self.syscfg.cfg2().read().sram_pcef().is_error()
63    }
64    /// Clears `SRAM_PCEF`.
65    pub fn clear_sram_pcef(&mut self) {
66        self.syscfg.cfg2().modify(|_, w| w.sram_pcef().clear());
67    }
68
69    /// Points EXTI line `line` at the port encoded by `code`.
70    ///
71    /// # Panics
72    ///
73    /// If `line` is above 15 — the lines above that have no source to select.
74    pub(crate) fn set_extiss(&mut self, line: u8, code: u8) {
75        match line {
76            // SAFETY: `code` is an `ExtiPin::SS_CODE`, one of the port codes this
77            // field takes.
78            l @ 0..=3 => self.syscfg.extiss0().modify(|_, w| unsafe {
79                match l {
80                    0 => w.exti0_ss().bits(code),
81                    1 => w.exti1_ss().bits(code),
82                    2 => w.exti2_ss().bits(code),
83                    _ => w.exti3_ss().bits(code),
84                }
85            }),
86            // SAFETY: as above.
87            l @ 4..=7 => self.syscfg.extiss1().modify(|_, w| unsafe {
88                match l {
89                    4 => w.exti4_ss().bits(code),
90                    5 => w.exti5_ss().bits(code),
91                    6 => w.exti6_ss().bits(code),
92                    _ => w.exti7_ss().bits(code),
93                }
94            }),
95            // SAFETY: as above.
96            l @ 8..=11 => self.syscfg.extiss2().modify(|_, w| unsafe {
97                match l {
98                    8 => w.exti8_ss().bits(code),
99                    9 => w.exti9_ss().bits(code),
100                    10 => w.exti10_ss().bits(code),
101                    _ => w.exti11_ss().bits(code),
102                }
103            }),
104            // SAFETY: as above.
105            l @ 12..=15 => self.syscfg.extiss3().modify(|_, w| unsafe {
106                match l {
107                    12 => w.exti12_ss().bits(code),
108                    13 => w.exti13_ss().bits(code),
109                    14 => w.exti14_ss().bits(code),
110                    _ => w.exti15_ss().bits(code),
111                }
112            }),
113            _ => unreachable!(),
114        }
115    }
116}
117
118#[cfg(not(pads_ge_lqfp32))]
119impl Syscfg {
120    /// Hands the `PA9`/`PA10` pads over to `PA11`/`PA12`, which come back as
121    /// inputs.
122    ///
123    /// Packages below 32 pins bond one pair or the other on the same two pads,
124    /// `PA9`/`PA10` after reset.
125    pub fn remap_pa11_pa12<M9: Active, M10: Active>(
126        &mut self,
127        _pa9: Pin<'A', 9, M9>,
128        _pa10: Pin<'A', 10, M10>,
129    ) -> (Pin<'A', 11, Input>, Pin<'A', 12, Input>) {
130        let pins = (Pin::take_as_input(), Pin::take_as_input());
131        self.syscfg
132            .cfg0()
133            .modify(|_, w| w.pa11_pa12_rmp().set_bit());
134        pins
135    }
136    /// Gives the pads back to `PA9`/`PA10`, which come back as inputs.
137    pub fn unmap_pa11_pa12<M11: Active, M12: Active>(
138        &mut self,
139        _pa11: Pin<'A', 11, M11>,
140        _pa12: Pin<'A', 12, M12>,
141    ) -> (Pin<'A', 9, Input>, Pin<'A', 10, Input>) {
142        let pins = (Pin::take_as_input(), Pin::take_as_input());
143        self.syscfg
144            .cfg0()
145            .modify(|_, w| w.pa11_pa12_rmp().clear_bit());
146        pins
147    }
148}
149
150/// Takes the raw peripheral into [`Syscfg`].
151pub trait SyscfgExt {
152    /// Switches the SYSCFG clock on and hands back the owning type.
153    ///
154    /// The clock bit is shared with the comparator, so CMP is clocked too; see
155    /// [`Rcu::enable_cfgcmp`].
156    fn constrain(self, rcu: &mut Rcu) -> Syscfg;
157}
158
159impl SyscfgExt for pac::Syscfg {
160    fn constrain(self, rcu: &mut Rcu) -> Syscfg {
161        rcu.enable_cfgcmp();
162        Syscfg { syscfg: self }
163    }
164}