FreeBSD 中文社区 2025 第二季度问卷调查
FreeBSD 中文社区(CFC)
VitePress 镜像站QQ 群 787969044视频教程Ⅰ视频教程Ⅱ
  • FreeBSD 从入门到追忆
  • 中文期刊
  • 状态报告
  • 发行说明
  • 手册
  • 网络文章集锦
  • 笔记本支持报告
  • Port 开发者手册
  • 架构手册
  • 开发者手册
  • 中文 man 手册
  • 文章
  • 书籍
  • FreeBSD 中文期刊
  • 编辑日志
  • 2025-123 下游项目
    • FreeBSD 发布工程:新主管上任
    • GhostBSD:从易用到挣扎与重生
    • BSD Now 与将来
    • 字符设备驱动教程(第三部分)
    • 学会走路——连接 GPIO 系统
    • FreeBSD 中对 SYN 段的处理
    • FreeBSD 2024 年秋季峰会
  • 2024-1112 虚拟化
    • 字符设备驱动程序教程(第二部分)
    • 面向 Linux 和 Windows 用户的 bhyve
    • Xen 与 FreeBSD
    • Wifibox:一种嵌入式虚拟化无线路由器
    • 嵌入式 FreeBSD:Fabric——起步阶段
    • DGP:一种新的数据包控制方法
    • 会议报告:我在都柏林的 EuroBSDCon 体验
  • 2024-0910 内核开发
    • 字符设备驱动程序教程
    • VPP 移植到了 FreeBSD:基础用法
    • 利用 Kyua 的 Jail 功能提升 FreeBSD 测试套件的并行效率
    • FreeBSD 上的 Valgrind
    • 嵌入式 FreeBSD:探索 bhyve
    • TCP/IP 历险记:FreeBSD TCP 协议栈中的 Pacing
    • 实用软件:实现无纸化(Paperless)
  • 2024-0708 存储与文件系统
    • FreeBSD 中的 NVMe-oF
    • FreeBSD iSCSI 入门
    • 使用 ZFS 原生加密保护数据
    • 嵌入式 FreeBSD:打造自己的镜像
    • TCP LRO 简介
    • 基于 Samba 的时间机器备份
  • 2024-0506 配置管理对决
    • 基本系统中的 mfsBSD
    • rdist
    • Hashicorp Vault
    • 在 GitHub 上向 FreeBSD 提交 PR
    • 悼念 Mike Karels
    • 2024 年 5-6 月来信
    • 嵌入式 FreeBSD 面包板
    • TCP/IP 历险记:TCP BBLog
    • 实用软件:开发定制 Ansible 模块
  • 2024-0304 开发工作流与集成
    • FreeBSD 内核开发工作流程
    • FreeBSD 与 KDE 持续集成(CI)
    • 更现代的内核调试工具
    • 从零开始的 ZFS 镜像及 makefs -t zfs
    • 提升 Git 使用体验
  • 2024-0102 网络(十周年)
    • FreeBSD 中的 RACK 栈和替代 TCP 栈
    • FreeBSD 14 中有关 TCP 的更新
    • if_ovpn 还是 OpenVPN
    • SR-IOV 已成为 FreeBSD 的重要功能
    • FreeBSD 接口 API(IfAPI)
    • BATMAN:更优的可移动热点网络方式
    • 配置自己的 VPN——基于 FreeBSD、Wireguard、IPv6 和广告拦截
    • 实用软件:使用 Zabbix 监控主机
  • 2023-1112 FreeBSD 14.0
    • LinuxBoot:从 Linux 启动 FreeBSD
    • FreeBSD 容器镜像
    • 现在用 Webhook 触发我
    • 新的 Ports 提交者:oel Bodenmann (jbo@freebsd.org)
  • 2023-0910 Port 与软件包
    • 回忆录:与 Warner Losh(@imp)的访谈
    • 在你自己的仓库中定制 Poudriere 源
    • Wazuh 和 MITRE Caldera 在 FreeBSD Jail 中的使用
    • PEP 517
    • CCCamp 2023 旅行报告
  • 2023-0708 容器与云
    • 在 Firecracker 上的 FreeBSD
    • 使用 pot 和 nomad 管理 Jail
    • 会议报告:C 与 BSD 正如拉丁语与我们——一位神学家的旅程
    • 抒怀之旅:与 Doug Rabson 的访谈
    • 基于 Jail 的广告拦截教程
    • 我们收到的来信
  • 2023-0506 FreeBSD 三十周年纪念特刊
    • CheriBSD 近十多年的历程
    • AArch64:成为 FreeBSD 新的一级架构
    • 岁月如梭:我个人的时间线
    • 安装 FreeBSD 1.0:回顾 30 年前
    • ZFS 是如何进入 FreeBSD 的呢?
    • 我不是来自约克郡的,我保证!
    • 回忆录:采访 David Greenman Lawrence
    • FreeBSD 和早期的 Unix 社区
    • 早期的 FreeBSD 移植
    • FreeBSD 30 周年:成功的秘诀
    • FreeBSD 在日本:回忆之旅与今日之实
  • 2023-0304 嵌入式
    • CheriBSD port 和软件包
    • 让我们来试试 ChatGPT
    • GPU 直通
  • 2023-0102 构建 FreEBSD Web 服务器
    • ZFS 的原子 I/O 与 PostgreSQL
    • 虚拟实验室——BSD 编程研讨会
    • ZFS 简介
    • 会议报告:落基山庆祝女性计算机科学家
    • 进行中的工作/征求反馈:数据包批处理
    • 基金会与 FreeBSD 桌面
  • 2022-1112 可观测性和衡量标准
    • 在 FreeBSD 的 DDB 内核调试器中编写自定义命令
    • DTrace:老式跟踪系统的新扩展
    • 基于证书的 Icinga 监控
    • 活动监控脚本(activitymonitor.sh)
    • 实用 IPv6(第四部分)
    • EuroBSDCon 会议报道
    • 实用 Port:Prometheus 的安装与配置
    • 书评:《用火解决问题:管理老化的计算机系统(并为现代系统保驾护航)》Kill It with Fire: Manage Aging Computer Systems (and Future Proof Modern Ones)
  • 2022-0910 安全性
    • CARP 简介
    • 重构内核加密服务框架
    • PAM 小窍门
    • SSH 小窍门
    • 实用 IPv6(第三部分)
    • 书评:Understanding Software Dynamics(深入理解软件性能——一种动态视角)—— Richard L. Sites 著
    • 访谈:保障 FreeBSD 安全性
    • MCH 2022 会议报告
  • 2022-0708 科研、系统与 FreeBSD
    • 在 FreeBSD 上构建 Loom 框架
    • 教授本科生 Unix 课程
    • FreeBSD 入门研讨会
    • 实用 IPv6(第二部分)
    • 在 2022 年及以后推广 FreeBSD
    • 进行中的工作/征求反馈:Socket 缓冲区
    • FreeBSD 开发者峰会报告
    • 支持 Electromagnetic Field 2022
  • 2022-0506 灾难恢复
    • 使用 FreeBSD 构建高弹性的私有云
    • LLDB 14 —— FreeBSD 新调试器
    • 实用 IPv6(第一部分)
    • 利用 netdump(4) 进行事后内核调试
    • 进行中的工作/征求反馈:FreeBSD 启动性能
    • 实用 Port:在 OpenZFS 上设置 NFSv4 文件服务器
  • 2022-0304 ARM64 是一级架构
    • FreeBSD/ARM64 上的数据科学
    • Pinebook Pro 上的 FreeBSD
    • 嵌入式控制器的 ACPI 支持
    • 进行中的工作/征求反馈:Lumina 桌面征集开发人员
    • 实用 Port:如何设置 Apple 时间机器
  • 2022-0102 软件与系统管理
    • 为 FreeBSD Ports 做贡献
    • 使用 Git 贡献到 FreeBSD Ports
    • CBSD:第一部分——生产环境
    • 将 OpenBSD 的 pf syncookie 代码移植到 FreeBSD 的 pf
    • 进行中的工作/征求反馈:mkjail
    • 《编程智慧:编程鬼才的经验和思考》(The Kollected Kode Vicious)书评
    • 会议报告:EuroBSDCon 2021 我的第一次 EuroBSDCon:一位新组织者的视角
  • 2021-1112 存储
    • 开放通道 SSD
    • 构建 FreeBSD 社区
    • 与完美操作系统同行 27 年
    • 进行中的工作/征求反馈:OccamBSD
    • 通过 iSCSI 导入 ZFS ZIL——不要在工作中这样做——就像我做的那样
  • 2021-0910 FreeBSD 开发
    • FreeBSD 代码审查与 git-arc
    • 如何为 FreeBSD 实现简单的 USB 驱动程序
    • 内核开发技巧
    • 程序员编程杂谈
  • 2021-0708 桌面/无线网
    • 通往 FreeBSD 桌面的直线路径
    • FreeBSD 13 中的人机接口设备 (HID) 支持
    • Panfrost 驱动程序
    • 用 Git 更新 FreeBSD
    • FreeBSD 的新面孔
    • 想给你的桌面加点佐料?
  • 2021-0506 安全
    • 七种提升新安装 FreeBSD 安全性的方法
    • copyinout 框架
    • 使用 TLS 改善 NFS 安全性
    • Capsicum 案例研究:Got
    • 对 Jail 进行安全扫描
  • 2021-0304 FreeBSD 13.0
    • 展望未来
    • FreeBSD 13.0 工具链
    • FreeBSD 13.0 中有新加载器吗?
    • TCP Cubic 准备起飞
    • OpenZFS 中的 Zstandard 压缩
    • 会议报告:FreeBSD 供应商峰会
    • Git 不够吗?
  • 2021-0102 案例研究
    • Tarsnap 的 FreeBSD 集群
    • BALLY WULFF
    • Netflix Open Connect
    • FreeBSD 的新面孔
    • 写作学者的 FreeBSD
    • 在世界之巅
  • 2020-1112 工作流/持续集成(CI)
    • FreeBSD Git 快速入门
    • 使用 syzkaller 进行内核 Fuzzing
    • Mastering Vim Quickly 书评
    • 线上会议实用技巧
    • 在控制台上进行网络监控
  • 2020-0910 贡献与入门
    • 采访:Warner Losh,第 2 部分
    • 代码审查
    • 撰写良好的提交消息
    • 如何在不是程序员的情况下做出贡献——成为 FreeBSD 译者
    • 如何成为文档提交者
    • 谷歌编程之夏
    • 为 FreeBSD 期刊撰写文章
    • 你为什么使用 FreeBSD
    • FreeBSD 的新面孔
  • 2020-0708 基准测试/调优
    • FreeBSD Friday
    • 采访:Warner Losh,第 1 部分
    • 构建和运行开源社区
    • 在 FreeBSD 上轻松搭建我的世界(Minecraft)服务器
    • FreeBSD 的新面孔
  • 2020-0506 网络性能
    • 内核中的 TLS 卸载
    • 访谈:Michael W Lucas
    • FreeBSD 桌面发行版
    • 使用 Poudriere 进行 Port 批量管理
    • FreeBSD 的新面孔
由 GitBook 提供支持
LogoLogo

FreeBSD 中文社区(CFC) 2025

在本页
在GitHub上编辑
导出为 PDF
  1. 2025-123 下游项目

学会走路——连接 GPIO 系统

上一页字符设备驱动教程(第三部分)下一页FreeBSD 中对 SYN 段的处理

最后更新于28天前

  • 作者:Christopher R. Bowman

在上篇文章中,我们创建了简单的电路,使主板上的 LED 灯闪烁,并且学习了两种不同方法来把电路加载到 FPGA。遗憾的是,当我们加载电路时,CPU 停止运行了。此外,尽管这有点有趣,但并没有与芯片上的 CPU 进行交互。在本篇中,我们将深入了解 Vivado,学习如何在加载电路时保持 CPU 运行,并探索 FreeBSD 中的 GPIO 系统。

之前,当我们使用 U-boot 或者 xbit2bin 和 FreeBSD 下的 /dev/devcfg 时,我们发现 FreeBSD 停止运行了。我认为发生的问题是处理器的系统停止了运行。原来,我们使用的 FPGA.bit 文件并未包含处理器系统的配置信息。在本期中,我们将修复这个问题。

在如何呈现本期的内容上,我犹豫了一下。从学习的角度来看,最自然的方式可能是使用 Vivado 的 GUI(图形化界面)。然而,GUI 并不适合自动化,原因显而易见——它需要人工运行 GUI。此外,描述 GUI 步骤也既困难又繁琐。幸运的是,Vivado 有两个特性使得我们可以相对轻松地绕过这些问题。在使用 GUI 时,Vivado 工具会生成一个 .jou 文件,这是 GUI 在后台执行的所有 TCL 命令的日志。Vivado 还提供了一个 TCL 命令 write_project_tcl,可以用来重新创建使用 GUI 时 Vivado 创建的项目文件。我通常倾向于使用 .jou 文件,因为我发现这些脚本更简洁、易于理解,而且如果我运行这些脚本,我可以直接启动 GUI,或者使用 write_project_tcl 来写一个项目脚本。脚本似乎也更适合像 git 这样的版本控制系统。

如果我们查看“图 1-1:Zynq-7000 SoC 概述”(来自《UG585:Zynq-7000 SoC 技术参考手册》),我们可以看到有多种外设模块(如 UART、I2C、SPI 等),这些模块可以通过多路复用器连接到外部引脚。该手册的“1.2.3 I/O 外设”部分详细描述了更多的功能。出于我们当下的需求,我们只需要注意到,我们可以相当灵活地将 GPIO 设备的信号路由到芯片上的引脚。如果我们再查看 的第 12 节“基本 I/O”,我们可以看到,板上的绿色 LED 与芯片引脚相连,这些引脚通过电流设置电阻接地。如果我们将这些引脚设为高电平,LED 灯就会亮起;反之,设为低电平时,LED 灯就会熄灭。

为了切换这些引脚,我们将使用 Vivado 软件将 GPIO 设备的输出路由到 LED 引脚,从而能让 GPIO 设备控制这些引脚。在开始这段旅程时我并不知道,但 FreeBSD 确实有一款 GPIO 子系统,且有人已经编写了驱动程序,使得这一切能从用户空间使用。

要开始,首先把 克隆到安装了 Vivado 工具的 Linux 主机上(在之前的文章中我展示了如何设置 bhyve),然后在仓库根目录下输入 make。如果工具 Vivado 已经正确配置,并且一切顺利,它应该会运行 Vivado,并拉取一个脚本,这个脚本会实例化处理器子系统,并将 GPIO 设备的前四个 EMIO 引脚连接到 LED 引脚。包含处理器子系统将解决我们之前在用 bit 流加载设备时处理器停止运行的问题。

在运行 make 后,查找构建的 zynq_gpio_leds.bit 文件。使用之前介绍的 xbit2bin 程序将其编程到芯片中。

# xbit2bin zynq_gpio_leds.bit

你应该会看到什么也没有发生。虽然不是很激动人心,但至少处理器应该仍在运行。

现在,我们需要使用 FreeBSD 的 GPIO 子系统。输入 man gpioctl 会给出关于可用功能的简洁总结。

以 root 用户,我们可运行 gpioctl 程序来列出可用的引脚:

# gpioctl -f /dev/gpioc0 -l

没能成功吧?是的,我对此也有点惊讶。查看 /usr/src/sys/arm/xilinx/zy7_gpio.c 中的 GPIO 源代码,我看到驱动程序中有 probe 和 attach 函数,但查看我的 ARTYZ7 系统的 dmesg 输出,我没有看到任何表明设备已被发现的内容。仔细看一下 probe 函数:

static int
zy7_gpio_probe(device_t dev)
{

        if (!ofw_bus_status_okay(dev))
                return (ENXIO);

        if (!ofw_bus_is_compatible(dev, "xlnx,zy7_gpio"))
               return (ENXIO);

        device_set_desc(dev, "Zynq-7000 GPIO driver");
        return (0);
}

可以看到,找到设备所需的唯一条件就是 ofw_bus_is_compatible(dev, "xlnx,zy7_gpio") 函数返回 true。

在嵌入式系统中,像大多数 ARM 系统一样,硬件通常不像现代 PCIe 总线那样是自识别的。软件无法自动识别硬件的存在以及其控制寄存器在内存地址空间中的位置。出于这个原因,许多操作系统使用 FDT(Flattened Device Trees,扁平设备树)来描述其设备内存映射。FDT 是文本文件,描述了嵌入式系统的信息,包括其他内容:如有哪些设备存在,以及它们在内存中的位置。这使得软件能够处理各种设备,而不需要硬编码信息。通过使用不同的 FDT,相同的内核通常可以与略有差异的设备兼容。FDT 是通过名为 dtc(设备树编译器)的工具将 DTS 文件(设备树源文件)编译成 DTB 文件(设备树二进制文件)。dtc 提供了选项,可以用来编译 DTS 或反编译 DTB。后者非常有用。例如,你可以请求内核返回它正在使用的 DTB,并使用 dtc 将其转换为文本:

# sysctl -b hw.fdt.dtb | dtc -I dtb -O dts

如果我们查找 gpio 部分,我们会看到(其中包括)以下内容:

             gpio@e000a000 {
                  compatible = "xlnx,zy7_gpio";
                };

DTB 中的兼容字符串不是驱动程序所期望的,因此它假设设备不存在。如果你查看 FreeBSD 的启动输出,你会发现内核正在使用 U-boot 提供的 EFI 固件模拟的 DTB。我们可以通过修复 U-boot 提供的内容来更改这一点,但那将需要补丁和重新编译 U-boot。相反,FreeBSD 提供了在内核加载器提示符或使用 loader.conf 变量加载 DTB 文件的功能。你可以使用以下 /boot/loader.conf 变量从加载器加载 DTB 文件:

# fdt_name="/boot/dtb/zynq-artyz7.dtb"
# fdt_type="dtb"
# fdt_load="YES"

这可以工作,但还有第三种方法。事实证明,你可以创建 FDT/DTS 叠加文件,这些文件是对 FDT/DTS/DTB 的补丁。我们只需要一个添加正确兼容字符串的 DTS 叠加文件,这样就可以了。以下是我在项目仓库的 dts 目录中包含的 DTS 叠加文件的核心部分,并附带一个 Makefile:

&{/axi/gpio@e000a000} { compatible = "xlnx,zy7_gpio"; };

我们可能会在后续的专栏中更详细地查看 FDT 文件,所以这里我不做解释。而是给你此文件的概况。构建完 DTB 叠加文件后,将生成的 DTB 文件放入 /boot/dtb/overlays,并将以下内容添加到 /boot/loader.conf:

fdt_overlays="artyz7_gpio_overlay.dtb"

重新启动并注意新的 dmesg 输出:

gpio0: <Zynq-7000 GPIO driver> mem 0xe000a000-0xe000afff irq 5 on simplebus0

现在我们再次尝试运行 gpioctl 命令,你应该能看到类似如下内容的一行:

pin 64: 0 EMIO_0<IN>

我们需要告诉 GPIO 子系统将引脚配置为输出,然后可以尝试切换它:

gpioctl -f /dev/gpioc0 -c EMIO_0 OUT
gpioctl -f /dev/gpioc0 -t EMIO_0

我会等着。灯光亮起时,请尽量保持坐姿,不要起身跳舞。看看你能否弄明白如何打开其他 LED,然后运行脚本 scripts/blink.sh,并传入参数 2。你应该会看到 LED 按照二进制计数闪烁。


在 1989 年,Christopher R. Bowman 首次在 VAX 11/785 上使用了 BSD,当时他在 Johns Hopkins University 应用物理实验室的地下二层工作。后来,在 90 年代中期,他在马里兰大学使用 FreeBSD 设计了他的第一款 2 微米 CMOS 芯片。从那时起,他一直是 FreeBSD 用户,并对硬件设计和驱动硬件的软件感兴趣。他在半导体设计自动化行业工作了 20 年。

如果你对此有什么问题、评论、反馈和批评,我很乐意听到你的声音。你可通过 联系我。

Learning to Walk–Interfacing to the GPIO System
Arty Z7 参考手册
git 仓库
articles@ChrisBowman.com