Skip to content

Commit 01f65c9

Browse files
committed
Implement ppp over uart
1 parent 6870b44 commit 01f65c9

File tree

8 files changed

+475
-5
lines changed

8 files changed

+475
-5
lines changed

.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
"rust-analyzer.linkedProjects": [
1111
"rust/mlogv32/Cargo.toml",
1212
"rust/demo_no_alloc/Cargo.toml",
13-
"rust/sortKB/Cargo.toml"
13+
"rust/sortKB/Cargo.toml",
14+
"rust/ppp/Cargo.toml"
1415
],
1516
"rust-analyzer.check.allTargets": false,
1617
"rust-analyzer.cargo.features": "all",

rust/mlogv32/src/io.rs

Lines changed: 103 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
use core::arch::asm;
1+
use core::{arch::asm, hint};
22

33
#[cfg(feature = "alloc")]
44
use alloc::string::ToString;
5-
use uart::{address::MmioAddress, Data, Uart};
5+
use uart::{address::MmioAddress, Data, FifoControl, LineStatus, Uart};
66

77
pub use uart;
88

@@ -56,16 +56,115 @@ pub fn print_flush() {
5656
const UART0_ADDRESS: usize = 0xf0000010;
5757
const UART1_ADDRESS: usize = 0xf0000030;
5858

59+
pub enum UartAddress {
60+
Uart0,
61+
Uart1,
62+
}
63+
64+
impl UartAddress {
65+
unsafe fn get_address(&self) -> MmioAddress {
66+
let base = match self {
67+
UartAddress::Uart0 => UART0_ADDRESS,
68+
UartAddress::Uart1 => UART1_ADDRESS,
69+
};
70+
MmioAddress::new(base as *mut u8, 4)
71+
}
72+
}
73+
5974
/// # Safety
6075
///
6176
/// This function is unsafe because the caller must ensure that only one instance exists at a time, as it represents a physical memory-mapped peripheral.
6277
pub unsafe fn get_uart0() -> Uart<MmioAddress, Data> {
63-
unsafe { Uart::new(MmioAddress::new(UART0_ADDRESS as *mut u8, 4)) }
78+
unsafe { Uart::new(UartAddress::Uart0.get_address()) }
6479
}
6580

6681
/// # Safety
6782
///
6883
/// This function is unsafe because the caller must ensure that only one instance exists at a time, as it represents a physical memory-mapped peripheral.
6984
pub unsafe fn get_uart1() -> Uart<MmioAddress, Data> {
70-
unsafe { Uart::new(MmioAddress::new(UART1_ADDRESS as *mut u8, 4)) }
85+
unsafe { Uart::new(UartAddress::Uart0.get_address()) }
86+
}
87+
88+
pub struct UartPort {
89+
uart: Uart<MmioAddress, Data>,
90+
fifo_capacity: usize,
91+
fifo_len: usize,
92+
}
93+
94+
impl UartPort {
95+
/// # Safety
96+
///
97+
/// This function is unsafe because the caller must ensure that only one instance of each device exists at a time, as it represents a physical memory-mapped peripheral.
98+
pub unsafe fn new(device: UartAddress) -> Self {
99+
Self {
100+
uart: Uart::new(device.get_address()),
101+
fifo_capacity: 1,
102+
fifo_len: 0,
103+
}
104+
}
105+
106+
/// # Safety
107+
///
108+
/// This function is unsafe because the caller must ensure that only one instance of each device exists at a time, as it represents a physical memory-mapped peripheral. The caller must also ensure that the fifo capacity is correct.
109+
pub unsafe fn new_with_fifo(device: UartAddress, fifo_capacity: usize) -> Self {
110+
Self {
111+
uart: Uart::new(device.get_address()),
112+
fifo_capacity,
113+
fifo_len: 0,
114+
}
115+
}
116+
117+
pub fn init(&mut self) {
118+
self.uart.write_fifo_control(
119+
FifoControl::ENABLE | FifoControl::CLEAR_RX | FifoControl::CLEAR_TX,
120+
);
121+
}
122+
123+
pub fn read(&mut self, buf: &mut [u8]) -> usize {
124+
for (i, item) in buf.iter_mut().enumerate() {
125+
if let Some(byte) = self.read_byte() {
126+
*item = byte;
127+
} else {
128+
return i;
129+
}
130+
}
131+
buf.len()
132+
}
133+
134+
pub fn read_byte(&mut self) -> Option<u8> {
135+
if self
136+
.uart
137+
.read_line_status()
138+
.contains(LineStatus::DATA_AVAILABLE)
139+
{
140+
Some(self.uart.read_byte())
141+
} else {
142+
None
143+
}
144+
}
145+
146+
pub fn write(&mut self, buf: &[u8]) {
147+
for &byte in buf {
148+
self.write_byte(byte);
149+
}
150+
}
151+
152+
pub fn write_byte(&mut self, byte: u8) {
153+
while !self.try_write_byte(byte) {
154+
hint::spin_loop();
155+
}
156+
}
157+
158+
pub fn try_write_byte(&mut self, byte: u8) -> bool {
159+
if self.uart.read_line_status().contains(LineStatus::THR_EMPTY) {
160+
self.fifo_len = 0
161+
}
162+
if self.fifo_len < self.fifo_capacity {
163+
self.uart.write_byte(byte);
164+
self.fifo_len += 1;
165+
true
166+
} else {
167+
false
168+
}
169+
}
71170
}

rust/ppp/.cargo/config.toml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
[build]
2+
target = "riscv32imac-unknown-none-elf"
3+
rustflags = [
4+
"-C", "link-arg=-Tlink.x",
5+
"-C", "target-feature=-c",
6+
]
7+
8+
[unstable]
9+
build-std = ["core", "compiler_builtins"]
10+
11+
[alias]
12+
rbuild = "build --release"
13+
rb = "rbuild"
14+
15+
rsize = "size --release"
16+
17+
robjdump = [
18+
"objdump",
19+
"--release",
20+
"--",
21+
"--disassemble",
22+
"--no-show-raw-insn",
23+
]
24+
rod = "robjdump"
25+
26+
robjcopy = [
27+
"objcopy",
28+
"--release",
29+
"--",
30+
"--output-target", "binary",
31+
]

rust/ppp/Cargo.lock

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

rust/ppp/Cargo.toml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[package]
2+
name = "ppp"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
mlogv32 = { path = "../mlogv32" }
8+
ppproto = "0.2.1"
9+
10+
[profile.dev]
11+
12+
[profile.release]
13+
panic = "abort"
14+
# values: 2, 3, s, z
15+
opt-level = 3
16+
overflow-checks = false
17+
lto = true

rust/ppp/README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# ppp
2+
3+
Based on the example in https://github.com/embassy-rs/ppproto/blob/bd16b3093fe2ededb4fd7662ed253d7bc6b39a9b/README.md.
4+
5+
Steps:
6+
7+
- Make sure UART_FIFO_CAPACITY in the CONFIG proc is set to 253.
8+
- Start the mlogv32-utils socket server.
9+
- Run each of the following commands in a separate terminal (replace `127.0.0.1` with your [host ip](https://superuser.com/a/1679774) if using WSL):
10+
11+
```sh
12+
# show log output from uart0
13+
echo '{"type":"serial","device":"uart0","stopOnHalt":false,"overrun":false}' | netcat -v 127.0.0.1 5000
14+
15+
# relay socket server to pty
16+
socat -v -x TCP4:127.0.0.1:5000 PTY,link=pty,rawer
17+
18+
# connect pppd to uart1
19+
sudo pppd $PWD/pty 9600 192.168.7.1:192.168.7.10 ms-dns 8.8.4.4 ms-dns 8.8.8.8 connect "echo '{\"type\":\"serial\",\"device\":\"uart1\",\"stopOnHalt\":false,\"overrun\":false}'" nodetach debug local persist silent noproxyarp noauth
20+
```
21+
22+
- Build and flash this program to mlogv32, then start the processor.
23+
- Run `ping 192.168.7.10` to ping the processor.

rust/ppp/rust-toolchain.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[toolchain]
2+
channel = "nightly-2025-06-10"
3+
components = ["rust-src"]
4+
targets = ["riscv32imac-unknown-none-elf"]

0 commit comments

Comments
 (0)