Skip to main content

tinyboot_ch32_hal/gpio/
v0.rs

1use core::convert::Infallible;
2
3use crate::Pin;
4
5#[derive(Copy, Clone)]
6pub enum Pull {
7    None,
8    Up,
9    Down,
10}
11
12#[derive(Copy, Clone, PartialEq)]
13pub enum Level {
14    Low,
15    High,
16}
17
18/// GPIO pin configuration.
19///
20/// Encodes the 4-bit CFGLR field `[MODE(2) | CNF(2)]` directly.
21/// Bit 7 = set ODR high, bit 6 = set ODR low, bits 3:0 = CFGLR nibble.
22#[derive(Copy, Clone)]
23pub struct PinMode(u8);
24
25// MODE bits: INPUT=0b00, OUTPUT_10MHZ=0b01
26// CNF bits (shifted <<2): ANALOG/PP=0b0000, FLOAT/OD=0b0100, PULL/AF_PP=0b1000, AF_OD=0b1100
27impl PinMode {
28    pub const INPUT_FLOATING: Self = Self(0b0100); // MODE=00 CNF=01
29    pub const INPUT_PULL_UP: Self = Self(0b1000 | 0x80); // MODE=00 CNF=10, ODR=1
30    pub const INPUT_PULL_DOWN: Self = Self(0b1000 | 0x40); // MODE=00 CNF=10, ODR=0
31    pub const OUTPUT_PUSH_PULL: Self = Self(0b0001); // MODE=01 CNF=00
32    pub const OUTPUT_OPEN_DRAIN: Self = Self(0b0101); // MODE=01 CNF=01
33    pub const AF_PUSH_PULL: Self = Self(0b1001); // MODE=01 CNF=10
34    pub const AF_OPEN_DRAIN: Self = Self(0b1101); // MODE=01 CNF=11
35
36    pub fn input_pull(pull: Pull) -> Self {
37        match pull {
38            Pull::Up => Self::INPUT_PULL_UP,
39            Pull::Down => Self::INPUT_PULL_DOWN,
40            Pull::None => Self::INPUT_FLOATING,
41        }
42    }
43}
44
45#[inline(always)]
46pub fn configure(pin: Pin, mode: PinMode) {
47    let regs = pin.gpio_regs();
48    let n = pin.pin_number();
49
50    let shift = n * 4;
51    let mask = !(0xFu32 << shift);
52    let bits = ((mode.0 & 0x0F) as u32) << shift;
53    let prev = regs.cfglr().read().0;
54    regs.cfglr()
55        .write_value(ch32_metapac::gpio::regs::Cfglr(prev & mask | bits));
56
57    if mode.0 & 0xC0 != 0 {
58        let mut outdr = regs.outdr().read();
59        outdr.set_odr(n, mode.0 & 0x80 != 0);
60        regs.outdr().write_value(outdr);
61    }
62}
63
64pub fn set_level(pin: Pin, level: Level) {
65    if level == Level::High {
66        pin.gpio_regs()
67            .bshr()
68            .write(|w| w.0 = 1 << pin.pin_number());
69    } else {
70        pin.gpio_regs().bcr().write(|w| w.0 = 1 << pin.pin_number());
71    }
72}
73
74impl embedded_hal::digital::ErrorType for Pin {
75    type Error = Infallible;
76}
77
78impl embedded_hal::digital::OutputPin for Pin {
79    fn set_high(&mut self) -> Result<(), Self::Error> {
80        set_level(*self, Level::High);
81        Ok(())
82    }
83
84    fn set_low(&mut self) -> Result<(), Self::Error> {
85        set_level(*self, Level::Low);
86        Ok(())
87    }
88}