Skip to content

Commit 29941cb

Browse files
committed
hal: GPIO, pad multiplexer and configurations support
Signed-off-by: zhujunxing <zjx1319@hust.edu.cn>
1 parent c88c507 commit 29941cb

File tree

8 files changed

+421
-23
lines changed

8 files changed

+421
-23
lines changed

Cargo.lock

Lines changed: 26 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/blinky/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ repository.workspace = true
1010

1111
[dependencies]
1212
sophgo-rom-rt = { version = "0.0.0", path = "../../sophgo-rom-rt" }
13+
sophgo-hal = { version = "0.0.0", path = "../../sophgo-hal" }
1314
panic-halt = "0.2.0"
15+
riscv = "0.11.0"
16+
embedded-hal = "1.0.0"
1417

1518
[[bin]]
1619
name = "blinky"

examples/blinky/src/main.rs

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,19 @@
44
#![no_std]
55
#![no_main]
66

7-
use core::arch::asm;
8-
7+
use embedded_hal::digital::OutputPin;
98
use panic_halt as _;
109
use sophgo_rom_rt::{entry, Peripherals};
1110

1211
#[entry]
1312
fn main(p: Peripherals) -> ! {
14-
unsafe {
15-
p.rtc_gpio
16-
.direction
17-
.write(p.rtc_gpio.direction.read().set_output(2));
18-
}
13+
let pad_led = p.pwr_pads.gpio2.into_function(&p.pinmux);
14+
let mut led = p.pwr_gpio.a2.into_pull_up_output(pad_led);
15+
1916
loop {
20-
unsafe {
21-
p.rtc_gpio.data.write(p.rtc_gpio.data.read() | (1 << 2));
22-
}
23-
for _ in 0..=1_000_000 {
24-
unsafe { asm!("nop") };
25-
}
26-
unsafe {
27-
p.rtc_gpio.data.write(p.rtc_gpio.data.read() & !(1 << 2));
28-
}
29-
for _ in 0..=1_000_000 {
30-
unsafe { asm!("nop") };
31-
}
17+
led.set_high().unwrap();
18+
riscv::asm::delay(10_000_000);
19+
led.set_low().unwrap();
20+
riscv::asm::delay(10_000_000);
3221
}
3322
}

sophgo-hal/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ repository.workspace = true
1212
base-address = "0.0.0"
1313
uart16550 = "0.0.1"
1414
volatile-register = "0.2.1"
15+
embedded-hal = "1.0.0"
1516

1617
[dev-dependencies]
1718
memoffset = "0.9.0"

sophgo-hal/src/gpio.rs

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
//! General Purpose Input/Output.
22
3+
use crate::{
4+
pad::{GpioFunc, Pad, PullUp},
5+
GPIO,
6+
};
7+
use base_address::BaseAddress;
8+
use core::marker::PhantomData;
9+
use embedded_hal::digital::{ErrorType, OutputPin};
310
use volatile_register::{RO, RW, WO};
411

512
/// GPIO registers.
@@ -33,7 +40,7 @@ pub struct RegisterBlock {
3340
pub sync_level: RW<u32>,
3441
}
3542

36-
/// GPIO direction.
43+
/// GPIO direction register.
3744
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3845
#[repr(transparent)]
3946
pub struct Direction(u32);
@@ -61,6 +68,95 @@ impl Direction {
6168
}
6269
}
6370

71+
/// Owned GPIO peripheral signal with mode type state.
72+
pub struct Gpio<A: BaseAddress, const I: u8, M> {
73+
base: GPIO<A>,
74+
_mode: PhantomData<M>,
75+
}
76+
77+
/// Input mode (type state).
78+
pub struct Input;
79+
80+
/// Output mode (type state).
81+
pub struct Output;
82+
83+
impl<A: BaseAddress, const I: u8, M> Gpio<A, I, M> {
84+
/// Configures the GPIO signal as a `GpioPad` operating as a pull up output.
85+
///
86+
/// # Examples
87+
///
88+
/// Gets ownership of pad from `PwrPads`, configures it as a pull up output
89+
/// to drive an LED.
90+
///
91+
/// ```no_run
92+
/// let pad_led = p.pwr_pads.gpio2.into_function(&p.pinmux);
93+
/// let mut led = p.pwr_gpio.a2.into_pull_up_output(pad_led);
94+
/// ```
95+
#[inline]
96+
pub fn into_pull_up_output<A2: BaseAddress, const N: usize>(
97+
self,
98+
pad: Pad<A2, N, GpioFunc<PullUp>>,
99+
) -> GpioPad<Gpio<A, I, Output>, Pad<A2, N, GpioFunc<PullUp>>> {
100+
unsafe {
101+
self.base.direction.modify(|w| w.set_output(I));
102+
}
103+
GpioPad {
104+
gpio: Gpio {
105+
base: self.base,
106+
_mode: PhantomData,
107+
},
108+
pad,
109+
}
110+
}
111+
}
112+
113+
/// Ownership wrapper of a GPIO signal and a pad.
114+
pub struct GpioPad<T, U> {
115+
gpio: T,
116+
pad: U,
117+
}
118+
119+
impl<A: BaseAddress, A2: BaseAddress, const I: u8, const N: usize, M, T>
120+
GpioPad<Gpio<A, I, M>, Pad<A2, N, GpioFunc<T>>>
121+
{
122+
/// Reconfigures the `GpioPad` to operate as a pull up output.
123+
#[inline]
124+
pub fn into_pull_up_output(self) -> GpioPad<Gpio<A, I, Output>, Pad<A2, N, GpioFunc<PullUp>>> {
125+
let (gpio, pad) = self.into_inner();
126+
gpio.into_pull_up_output(pad.into_gpio_pull_up())
127+
}
128+
}
129+
130+
impl<T, U> GpioPad<T, U> {
131+
/// Unwraps the ownership structure, returning the GPIO signal and the pad.
132+
#[inline]
133+
pub fn into_inner(self) -> (T, U) {
134+
(self.gpio, self.pad)
135+
}
136+
}
137+
138+
impl<T, U> ErrorType for GpioPad<T, U> {
139+
type Error = core::convert::Infallible;
140+
}
141+
142+
impl<A: BaseAddress, const I: u8, U> OutputPin for GpioPad<Gpio<A, I, Output>, U> {
143+
#[inline]
144+
fn set_low(&mut self) -> Result<(), Self::Error> {
145+
unsafe {
146+
self.gpio.base.data.modify(|w| w & !(1 << I));
147+
}
148+
Ok(())
149+
}
150+
151+
#[inline]
152+
fn set_high(&mut self) -> Result<(), Self::Error> {
153+
unsafe {
154+
self.gpio.base.data.modify(|w| w | (1 << I));
155+
}
156+
Ok(())
157+
}
158+
}
159+
64160
#[cfg(test)]
65161
mod tests {
66162
use super::RegisterBlock;

sophgo-hal/src/lib.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![no_std]
22

33
pub mod gpio;
4+
pub mod pad;
45

56
use core::ops;
67

@@ -33,3 +34,24 @@ impl<A: BaseAddress> ops::Deref for GPIO<A> {
3334
unsafe { &*(self.base.ptr() as *const _) }
3435
}
3536
}
37+
38+
/// Pad function multiplexer peripheral.
39+
pub struct PINMUX<A: BaseAddress> {
40+
base: A,
41+
}
42+
43+
impl<A: BaseAddress> ops::Deref for PINMUX<A> {
44+
type Target = pad::PinMux;
45+
46+
#[inline(always)]
47+
fn deref(&self) -> &Self::Target {
48+
unsafe { &*(self.base.ptr() as *const _) }
49+
}
50+
}
51+
52+
impl<A: BaseAddress> AsRef<pad::FMux> for PINMUX<A> {
53+
#[inline(always)]
54+
fn as_ref(&self) -> &pad::FMux {
55+
&self.fmux
56+
}
57+
}

0 commit comments

Comments
 (0)