Skip to content

Commit bc67c12

Browse files
committed
hal: GPIO support (register level)
Signed-off-by: zhujunxing <zjx1319@hust.edu.cn>
1 parent 4d5e4f5 commit bc67c12

File tree

5 files changed

+179
-0
lines changed

5 files changed

+179
-0
lines changed

Cargo.lock

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

sophgo-hal/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,7 @@ repository.workspace = true
1111
[dependencies]
1212
base-address = "0.0.0"
1313
uart16550 = "0.0.1"
14+
volatile-register = "0.2.1"
15+
16+
[dev-dependencies]
17+
memoffset = "0.9.0"

sophgo-hal/src/gpio.rs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
//! General Purpose Input/Output.
2+
3+
use volatile_register::{RO, RW, WO};
4+
5+
/// GPIO registers.
6+
#[repr(C)]
7+
pub struct RegisterBlock {
8+
/// Port A data register.
9+
pub data: RW<u32>,
10+
/// Port A data direction register.
11+
pub direction: RW<Direction>,
12+
_reserved0: [u8; 0x28],
13+
/// Interrupt enable register.
14+
pub interrupt_enable: RW<u32>,
15+
/// Interrupt mask register.
16+
pub interrupt_mask: RW<u32>,
17+
/// Interrupt level register.
18+
pub interrupt_level: RW<u32>,
19+
/// Interrupt polarity register.
20+
pub interrupt_polarity: RW<u32>,
21+
/// Interrupt status register.
22+
pub interrupt_status: RO<u32>,
23+
/// Raw interrupt status register.
24+
pub raw_interrupt_status: RO<u32>,
25+
/// Debounce enable register.
26+
pub debounce: RW<u32>,
27+
/// Port A clear interrupt register.
28+
pub interrupt_clear: WO<u32>,
29+
/// Port A external port register.
30+
pub external_port: RW<u32>,
31+
_reserved1: [u8; 0xC],
32+
/// Level-sensitive synchronization enable register.
33+
pub sync_level: RW<u32>,
34+
}
35+
36+
/// GPIO direction.
37+
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
38+
#[repr(transparent)]
39+
pub struct Direction(u32);
40+
41+
impl Direction {
42+
/// Set GPIO direction to input.
43+
#[inline]
44+
pub fn set_input(self, n: u8) -> Self {
45+
Self(self.0 & !(1 << n))
46+
}
47+
/// Set GPIO direction to output.
48+
#[inline]
49+
pub fn set_output(self, n: u8) -> Self {
50+
Self(self.0 | (1 << n))
51+
}
52+
/// Check if GPIO direction is input.
53+
#[inline]
54+
pub fn is_input(self, n: u8) -> bool {
55+
self.0 & (1 << n) == 0
56+
}
57+
/// Check if GPIO direction is output.
58+
#[inline]
59+
pub fn is_output(self, n: u8) -> bool {
60+
self.0 & (1 << n) != 0
61+
}
62+
}
63+
64+
#[cfg(test)]
65+
mod tests {
66+
use super::RegisterBlock;
67+
use memoffset::offset_of;
68+
69+
#[test]
70+
fn struct_register_block_offset() {
71+
assert_eq!(offset_of!(RegisterBlock, data), 0x00);
72+
assert_eq!(offset_of!(RegisterBlock, direction), 0x04);
73+
assert_eq!(offset_of!(RegisterBlock, interrupt_enable), 0x30);
74+
assert_eq!(offset_of!(RegisterBlock, interrupt_mask), 0x34);
75+
assert_eq!(offset_of!(RegisterBlock, interrupt_level), 0x38);
76+
assert_eq!(offset_of!(RegisterBlock, interrupt_polarity), 0x3C);
77+
assert_eq!(offset_of!(RegisterBlock, interrupt_status), 0x40);
78+
assert_eq!(offset_of!(RegisterBlock, raw_interrupt_status), 0x44);
79+
assert_eq!(offset_of!(RegisterBlock, debounce), 0x48);
80+
assert_eq!(offset_of!(RegisterBlock, interrupt_clear), 0x4C);
81+
assert_eq!(offset_of!(RegisterBlock, external_port), 0x50);
82+
assert_eq!(offset_of!(RegisterBlock, sync_level), 0x60);
83+
}
84+
}

sophgo-hal/src/lib.rs

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

3+
pub mod gpio;
4+
35
use core::ops;
46

57
use base_address::BaseAddress;
@@ -17,3 +19,17 @@ impl<A: BaseAddress> ops::Deref for UART<A> {
1719
unsafe { &*(self.base.ptr() as *const _) }
1820
}
1921
}
22+
23+
/// General Purpose Input/Output.
24+
pub struct GPIO<A: BaseAddress> {
25+
base: A,
26+
}
27+
28+
impl<A: BaseAddress> ops::Deref for GPIO<A> {
29+
type Target = gpio::RegisterBlock;
30+
31+
#[inline(always)]
32+
fn deref(&self) -> &Self::Target {
33+
unsafe { &*(self.base.ptr() as *const _) }
34+
}
35+
}

sophgo-rom-rt/src/lib.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,51 @@ use base_address::Static;
77

88
/// Peripherals available on ROM start.
99
pub struct Peripherals {
10+
// TODO pub pin_mux: sophgo_hal::PinMux<Static<0x03001000>>,
11+
/// General Purpose Input/Output 0.
12+
pub gpio0: sophgo_hal::GPIO<Static<0x03020000>>,
13+
/// General Purpose Input/Output 1.
14+
pub gpio1: sophgo_hal::GPIO<Static<0x03021000>>,
15+
/// General Purpose Input/Output 2.
16+
pub gpio2: sophgo_hal::GPIO<Static<0x03022000>>,
17+
/// General Purpose Input/Output 3.
18+
pub gpio3: sophgo_hal::GPIO<Static<0x03023000>>,
19+
20+
// TODO pub pwm0: sophgo_hal::PWM<Static<0x03060000>>,
21+
// TODO pub pwm1: sophgo_hal::PWM<Static<0x03061000>>,
22+
// TODO pub pwm2: sophgo_hal::PWM<Static<0x03062000>>,
23+
// TODO pub pwm3: sophgo_hal::PWM<Static<0x03063000>>,
24+
// TODO pub timer: sophgo_hal::Timer<Static<0x030A0000>>,
25+
// TODO pub i2c0: sophgo_hal::I2C<Static<0x04000000>>,
26+
// TODO pub i2c1: sophgo_hal::I2C<Static<0x04010000>>,
27+
// TODO pub i2c2: sophgo_hal::I2C<Static<0x04020000>>,
28+
// TODO pub i2c3: sophgo_hal::I2C<Static<0x04030000>>,
29+
// TODO pub i2c4: sophgo_hal::I2C<Static<0x04040000>>,
30+
// TODO pub spi_nand: sophgo_hal::SPINand<Static<0x04060000>>,
31+
// TODO pub i2s0: sophgo_hal::I2S<Static<0x04100000>>,
32+
// TODO pub i2s1: sophgo_hal::I2S<Static<0x04110000>>,
33+
// TODO pub i2s2: sophgo_hal::I2S<Static<0x04120000>>,
34+
// TODO pub i2s3: sophgo_hal::I2S<Static<0x04130000>>,
1035
/// Universal Asynchronous Receiver/Transmitter 0.
1136
pub uart0: sophgo_hal::UART<Static<0x04140000>>,
37+
/// Universal Asynchronous Receiver/Transmitter 1.
38+
pub uart1: sophgo_hal::UART<Static<0x04150000>>,
39+
/// Universal Asynchronous Receiver/Transmitter 2.
40+
pub uart2: sophgo_hal::UART<Static<0x04160000>>,
41+
/// Universal Asynchronous Receiver/Transmitter 3.
42+
pub uart3: sophgo_hal::UART<Static<0x04170000>>,
43+
44+
// TODO spi0: sophgo_hal::SPI<Static<0x04180000>>,
45+
// TODO spi1: sophgo_hal::SPI<Static<0x04190000>>,
46+
// TODO spi2: sophgo_hal::SPI<Static<0x041A0000>>,
47+
// TODO spi3: sophgo_hal::SPI<Static<0x041B0000>>,
48+
/// Universal Asynchronous Receiver/Transmitter 4.
49+
pub uart4: sophgo_hal::UART<Static<0x041C0000>>,
50+
// TODO sd0: sophgo_hal::SD<Static<0x04310000>>,
51+
// TODO sd1: sophgo_hal::SD<Static<0x04320000>>,
52+
// TODO usb: sophgo_hal::USB<Static<0x04340000>>,
53+
// TODO documents
54+
pub rtc_gpio: sophgo_hal::GPIO<Static<0x05021000>>,
1255
}
1356

1457
#[cfg(target_arch = "riscv64")]

0 commit comments

Comments
 (0)