You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

6.0 KiB

教程 05 - 驱动程序: GPIO和UART

tl;dr

  • 添加了用于真实UARTGPIO控制器的驱动程序。
  • 我们将首次能够在真实硬件上运行代码 (请向下滚动查看说明)。

简介

在上一篇教程中,我们启用了全局安全变量,为添加第一个真实设备驱动程序奠定了基础。 我们放弃了神奇的QEMU控制台并引入了一个驱动程序管理器,允许BSP将设备驱动程序注册到内核中。

驱动程序管理器

第一步是向内核添加一个driver subsystem。相应的代码将位于src/driver.rs中。 该子系统引入了interface::DeviceDriver,这是每个设备驱动程序都需要实现的通用特征,并为内核所知。 在同一文件中实例化的全局DRIVER_MANAGER实例(类型为DriverManager)作为一个中央实体,可以被调用来管理内核中的所有设备驱动程序。 例如,通过使用全局可访问的crate::driver::driver_manager().register_driver(...),任何代码都可以注册一个实现了interface::DeviceDriver特征的具有静态生命周期的对象。

在内核初始化期间,调用crate::driver::driver_manager().init_drivers(...)将使驱动程序管理器遍历所有已注册的驱动程序, 并启动它们的初始化,并执行可选的post-init callback,该回调可以与驱动程序一起注册。 例如,此机制用于在UART驱动程序初始化后将其切换为主系统控制台的驱动程序。

BSP驱动程序实现

src/bsp/raspberrypi/driver.rs中,函数init()负责注册UARTGPIO驱动程序。 因此,在内核初始化期间,按照以下来自main.rs的代码,正确的顺序是: i首先初始化BSP驱动程序子系统然后ii调用driver_manager()

unsafe fn kernel_init() -> ! {
    // Initialize the BSP driver subsystem.
    if let Err(x) = bsp::driver::init() {
        panic!("Error initializing BSP driver subsystem: {}", x);
    }

    // Initialize all device drivers.
    driver::driver_manager().init_drivers();
    // println! is usable from here on.

驱动程序本身存储在src/bsp/device_driver中,并且可以在不同的BSP之间重复使用 在这些教程中添加的第一个驱动程序是PL011Uart驱动程序:它实现了console::interface::*特征,并且从现在开始用作主系统控制台。 第二个驱动程序是GPIO驱动程序,它根据需要将RPii'sUART映射(即将来自SoC内部的信号路由到实际的硬件引脚)。 请注意,GPIO驱动程序区分RPi 3RPi 4。它们的硬件不同,因此我们必须在软件中进行适配。

现在,BSP还包含了一个内存映射表,位于src/bsp/raspberrypi/memory.rs中。它提供了树莓派的MMIO地址, BSP使用这些地址来实例化相应的设备驱动程序,以便驱动程序代码知道在内存中找到设备的寄存器的位置。

SD卡启动

由于我们现在有了真实的UART输出,我们可以在真实的硬件上运行代码。 由于前面提到的GPIO驱动程序的差异,构建过程在RPi 3RPi 4之间有所区别。 默认情况下,所有的Makefile目标都将为RPi 3构建。 为了RPi 4构建,需要在每个目标前加上BSP=rpi4。例如:

$ BSP=rpi4 make
$ BSP=rpi4 make doc

不幸的是QEMU目前还不支持RPi 4,因此BSP=rpi4 make qemu无法工作。

准备SD卡的一些步骤在RPi3和RPi4之间有所不同请在以下操作中小心。

通用步骤

  1. 创建一个名为bootFAT32分区。
  2. 在SD卡上生成一个名为config.txt的文件,并将以下内容写入其中:
arm_64bit=1
init_uart_clock=48000000

RPi 3

  1. Raspberry Pi firmware repo中将以下文件复制到SD卡上
  2. 运行make命令。

RPi 4

  1. Raspberry Pi firmware repo中将以下文件复制到SD卡上
  2. 运行BSP=rpi4 make命令。

注意: 如果在您的RPi4上无法正常工作请尝试将start4.elf重命名为start.elf (不带4) 并复制到SD卡上。

再次通用步骤

  1. kernel8.img复制到SD卡上并将SD卡插入RPi。
  2. 运行miniterm target在主机上打开UART设备
$ make miniterm

注意: Miniterm假设默认的串行设备名称为/dev/ttyUSB0。Depending on your 根据您的主机操作系统,设备名称可能会有所不同。例如,在macOS上,它可能是 /dev/tty.usbserial-0001之类的。在这种情况下,请明确提供设备名称:

$ DEV_SERIAL=/dev/tty.usbserial-0001 make miniterm
  1. 将USB串口连接到主机PC。
    • 请参考top-level README中的接线图。
    • 注意: TX发送线连接到RX接收引脚。
    • 确保您没有连接USB串口的电源引脚只连接RX/TX和GND引脚。
  2. 将RPi连接到USB电源线并观察输出。
Miniterm 1.0

[MT] ⏳ Waiting for /dev/ttyUSB0
[MT] ✅ Serial connected
[0] mingo version 0.5.0
[1] Booting on: Raspberry Pi 3
[2] Drivers loaded:
      1. BCM PL011 UART
      2. BCM GPIO
[3] Chars written: 117
[4] Echoing input now
  1. 通过按下ctrl-c退出。

相比之前的变化diff

请检查英文版本,这是最新的。