Skip to content

Commit 36379d6

Browse files
jakezhu9luojia65
authored andcommitted
hal: uart and serial support
TODO: test if the code works on uarts and pads other than those in the example Signed-off-by: zhujunxing <zjx1319@hust.edu.cn>
1 parent 0a24042 commit 36379d6

File tree

8 files changed

+529
-24
lines changed

8 files changed

+529
-24
lines changed

Cargo.lock

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

examples/hello-world/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ repository.workspace = true
1111
[dependencies]
1212
sophgo-rom-rt = { version = "0.0.0", path = "../../sophgo-rom-rt" }
1313
panic-halt = "0.2.0"
14+
riscv = "0.11.0"
15+
embedded-io = "0.6.1"
16+
embedded-hal = "1.0.0"
1417

1518
[[bin]]
1619
name = "hello-world"

examples/hello-world/src/main.rs

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

7+
use embedded_io::Write;
78
use panic_halt as _;
89
use sophgo_rom_rt::{entry, Peripherals};
910

1011
#[entry]
1112
fn main(p: Peripherals) -> ! {
13+
let uart0_tx = p.pads.uart0_tx.into_function(&p.pinmux);
14+
let uart0_rx = p.pads.uart0_rx.into_function(&p.pinmux);
15+
16+
let mut serial = p.uart0.serial(Default::default(), (uart0_tx, uart0_rx));
17+
1218
loop {
13-
p.uart0.write(b"Hello World from Rust!\n");
14-
// TODO fix Uart16550 crate bug; it doesn't block when UART FIFO is not empty
19+
writeln!(serial, "Hello World from Rust!").ok();
20+
riscv::asm::delay(10_000_000);
1521
}
1622
}

sophgo-hal/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ repository.workspace = true
1010

1111
[dependencies]
1212
base-address = "0.0.0"
13-
uart16550 = "0.0.1"
1413
volatile-register = "0.2.1"
1514
embedded-hal = "1.0.0"
15+
embedded-io = "0.6.1"
1616

1717
[dev-dependencies]
1818
memoffset = "0.9.0"

sophgo-hal/src/lib.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,19 @@
22

33
pub mod gpio;
44
pub mod pad;
5+
pub mod uart;
56

67
use core::ops;
78

89
use base_address::BaseAddress;
910

1011
/// Universal Asynchronous Receiver/Transmitter.
11-
pub struct UART<A: BaseAddress> {
12+
pub struct UART<A: BaseAddress, const I: usize> {
1213
base: A,
1314
}
1415

15-
impl<A: BaseAddress> ops::Deref for UART<A> {
16-
type Target = uart16550::Uart16550<u32>;
16+
impl<A: BaseAddress, const I: usize> ops::Deref for UART<A, I> {
17+
type Target = uart::RegisterBlock;
1718

1819
#[inline(always)]
1920
fn deref(&self) -> &Self::Target {

sophgo-hal/src/pad.rs

Lines changed: 108 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use core::marker::PhantomData;
55
use volatile_register::RW;
66

77
/// The `PINMUX` pad multiplexer peripheral.
8+
#[repr(C)]
89
pub struct PinMux {
910
/// Pad function multiplexer registers for all the pads.
1011
pub fmux: FMux,
@@ -21,32 +22,74 @@ impl AsRef<FMux> for PinMux {
2122
}
2223

2324
/// Pad function multiplexer registers for all the pads.
25+
#[repr(C)]
2426
pub struct FMux {
25-
_reserved0: [u8; 0xAC],
27+
_reserved0: [u8; 0x40],
28+
/// UART-0 TX pad function.
29+
pub uart0_tx: RW<u32>,
30+
/// UART-0 RX pad function.
31+
pub uart0_rx: RW<u32>,
32+
_reserved1: [u8; 0x28],
33+
/// I2C-0 Serial Clock (SCL) pad function.
34+
pub i2c0_scl: RW<u32>,
35+
/// I2C-0 Serial Data (SDA) pad function.
36+
pub i2c0_sda: RW<u32>,
37+
_reserved2: [u8; 0x34],
2638
/// Power (RTC) domain GPIO-2 pad function.
2739
pub pwr_gpio2: RW<u32>,
2840
// TODO other fields and padding
41+
_reserved3: [u8; 0x1750],
2942
}
3043

3144
impl FMux {
3245
/// Gets the pad function multiplexer register for the given pad number `N`.
3346
#[inline]
3447
pub fn fmux<const N: usize>(&self) -> &RW<u32> {
3548
match N {
49+
18 => &self.uart0_tx,
50+
19 => &self.uart0_rx,
51+
28 => &self.i2c0_scl,
52+
29 => &self.i2c0_sda,
3653
49 => &self.pwr_gpio2,
3754
_ => todo!(),
3855
}
3956
}
4057
}
4158

4259
/// Non-RTC domain pad configurations.
60+
#[repr(C)]
4361
pub struct PadConfigs {
44-
// TODO
62+
_reserved0: [u8; 0x10C],
63+
/// Non-RTC domain UART-0 TX pad configurations.
64+
pub uart0_tx: RW<PadConfig>,
65+
/// Non-RTC domain UART-0 RX pad configurations.
66+
pub uart0_rx: RW<PadConfig>,
67+
_reserved1: [u8; 0x28],
68+
/// Non-RTC domain i2c-0 SCL pad configurations.
69+
pub i2c0_scl: RW<PadConfig>,
70+
/// Non-RTC domain i2c-0 SDA pad configurations.
71+
pub i2c0_sda: RW<PadConfig>,
4572
}
4673

47-
// TODO fn pad_config in impl PadConfigs
74+
impl PadConfigs {
75+
/// Gets the pad configuration register for the given pad number `N`.
76+
///
77+
/// `N` must be number of a pad in the non-RTC domain.
78+
#[inline]
79+
const fn pad_config<const N: usize>(&self) -> &RW<PadConfig> {
80+
match N {
81+
18 => &self.uart0_tx,
82+
19 => &self.uart0_rx,
83+
28 => &self.i2c0_scl,
84+
29 => &self.i2c0_sda,
85+
// if not a non-RTC pad, return unimplemented!()
86+
_ => todo!(),
87+
}
88+
}
89+
}
4890

4991
/// Power (RTC) domain pad configurations.
92+
#[repr(C)]
5093
pub struct PwrPadConfigs {
5194
_reserved0: [u8; 0x34],
5295
/// Power (RTC) domain GPIO-2 pad configuration.
@@ -138,11 +181,14 @@ impl<A: BaseAddress, const N: usize, F> Pad<A, N, F> {
138181
}
139182
}
140183
#[inline]
141-
fn pad_config(&self) -> &RW<PadConfig> {
184+
pub fn pad_config(&self) -> &RW<PadConfig> {
142185
match N {
143186
// TODO in range of power pads ...
144187
49 => unsafe { &*(self.base.ptr() as *const PwrPadConfigs) }.pad_config::<N>(),
145188
// TODO in range of conventional pads ...
189+
18..=19 | 28..=29 => {
190+
unsafe { &*(self.base.ptr() as *const PadConfigs) }.pad_config::<N>()
191+
}
146192
// .. => { ... }
147193
_ => todo!(),
148194
}
@@ -174,6 +220,9 @@ pub struct PullUp;
174220
/// Floating as pull mode (type state).
175221
pub struct Floating;
176222

223+
/// UART function (type state).
224+
pub struct UartFunc<const I: usize>;
225+
177226
/// Trait for all valid pad functions.
178227
pub trait Function {
179228
/// Pull direction associated with this pad function.
@@ -214,6 +263,32 @@ const fn gpio_fmux<const N: usize>() -> u32 {
214263
}
215264
}
216265

266+
impl<const I: usize> Function for UartFunc<I> {
267+
const PULL: Pull = Pull::Up;
268+
#[inline]
269+
fn fmux<const N: usize>() -> u32 {
270+
uart_fmux::<N, I>()
271+
}
272+
}
273+
274+
const fn uart_fmux<const N: usize, const I: usize>() -> u32 {
275+
match I {
276+
0 => match N {
277+
18..=19 => 0,
278+
_ => unimplemented!(),
279+
},
280+
1 => match N {
281+
28..=29 => 1,
282+
_ => unimplemented!(),
283+
},
284+
2 => match N {
285+
28..=29 => 2,
286+
_ => unimplemented!(),
287+
},
288+
_ => unimplemented!(),
289+
}
290+
}
291+
217292
/// Pad internal pull direction values.
218293
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
219294
#[repr(u8)]
@@ -225,3 +300,32 @@ pub enum Pull {
225300
/// Internally pulled down.
226301
Down = 2,
227302
}
303+
304+
#[cfg(test)]
305+
mod tests {
306+
use super::{FMux, PadConfigs, PinMux};
307+
use memoffset::offset_of;
308+
309+
#[test]
310+
fn struct_pinmux_offset() {
311+
assert_eq!(offset_of!(PinMux, fmux), 0x00);
312+
assert_eq!(offset_of!(PinMux, config), 0x1800);
313+
}
314+
315+
#[test]
316+
fn struct_fmux_offset() {
317+
assert_eq!(offset_of!(FMux, uart0_tx), 0x40);
318+
assert_eq!(offset_of!(FMux, uart0_rx), 0x44);
319+
assert_eq!(offset_of!(FMux, i2c0_scl), 0x70);
320+
assert_eq!(offset_of!(FMux, i2c0_sda), 0x74);
321+
assert_eq!(offset_of!(FMux, pwr_gpio2), 0xAC);
322+
}
323+
324+
#[test]
325+
fn struct_pad_configs_offset() {
326+
assert_eq!(offset_of!(PadConfigs, uart0_tx), 0x190C - 0x1800);
327+
assert_eq!(offset_of!(PadConfigs, uart0_rx), 0x1910 - 0x1800);
328+
assert_eq!(offset_of!(PadConfigs, i2c0_scl), 0x193C - 0x1800);
329+
assert_eq!(offset_of!(PadConfigs, i2c0_sda), 0x1940 - 0x1800);
330+
}
331+
}

0 commit comments

Comments
 (0)