1.5.3 司机

03-司机 — Comprehensive Rust

译文 · 基于 Comprehensive Rust

原文链接: https://google.github.io/comprehensive-rust/bare-metal/aps/better-uart/driver.html

1.5.3 司机

现在让我们使用新的Registers我们的驱动程序中的结构体。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
/// PL011 UART 的驱动程序。
#[derive(Debug)]
pub struct Uart {
    registers: *mut Registers,
}

impl Uart {
    /// 为 PL011 设备构建 UART 驱动程序的新实例
    /// 给定的一组寄存器。
    ///
    /// # 安全
    ///
    /// 给定的指针必须指向PL011的8个MMIO控制寄存器
    ///device,必须映射到进程的地址空间
    ///设备内存并且没有任何其他别名。
    pub unsafe fn new(registers: *mut Registers) -> Self {
        Self { registers }
    }

    /// 将单个字节写入 UART。
    pub fn write_byte(&mut self, byte: u8) {
        // 等待,直到 TX 缓冲区中有空间。
        while self.read_flag_register().contains(Flags::TXFF) {}

        // 安全:我们知道 self.registers 指向控制寄存器
        // 已正确映射的 PL011 设备的。
        unsafe {
            // 写入 TX 缓冲区。
            (&raw mut (*self.registers).dr).write_volatile(byte.into());
        }

        // 等待 UART 不再繁忙。
        while self.read_flag_register().contains(Flags::BUSY) {}
    }

    /// 读取并返回一个待处理字节,或者`None`如果什么都没有
    /// 已收到。
    pub fn read_byte(&mut self) -> Option<u8> {
        if self.read_flag_register().contains(Flags::RXFE) {
            None
        } else {
            // 安全:我们知道 self.registers 指向控件
            // 正确映射的 PL011 设备的寄存器。
            let data = unsafe { (&raw const (*self.registers).dr).read_volatile() };
            // TODO:检查位 8-11 中的错误情况。
            Some(data as u8)
        }
    }

    fn read_flag_register(&self) -> Flags {
        // 安全:我们知道 self.registers 指向控制寄存器
        // 已正确映射的 PL011 设备的。
        unsafe { (&raw const (*self.registers).fr).read_volatile() }
    }
}
  • 注意使用&raw const / &raw mut获取指向各个字段的指针 而不创建中间引用,这是不合理的。
  • 该示例未包含在幻灯片中,因为它与 safe-mmio接下来的例子。您可以在 QEMU 中运行它make qemu在下面src/bare-metal/aps/examples如果你需要的话。
最后修改 August 11, 2026: 更新 (70a5af133)