当前位置: 首页 > news >正文

[实战]zynq7000设备树自动导出GPIO

目录

  • zynq7000设备树自动导出GPIO
    • 添加设备树节点
    • 验证实验
  • 结论

zynq7000设备树自动导出GPIO

今天无聊,掏出我82年产的microzed玩一玩。玩啥好呢,要不点个灯吧。于是,三下五除二,通过linux sys接口以及echo,很快就点亮了。无聊按了一下复位按键,发现系统重新先加载后,灯又不亮了。这不能忍,于是继续深入,发现导出的gpio都没了。

linux sys 接口,对GPIO实行的export操作,是临时性质的,因此每次重启系统,都需要重新进行export。通常可以通过制作脚本,在系统加载后或者用户登录后自动export,但今天,我想借这个事情,聊一条怎么用linux设备树解决这个问题。

添加设备树节点

相关的基础知识,可以参考我的博客
[Linux实战] Linux设备树原理与应用详解
[实战]Zynq设备树详细教程
[实战] 深入解析Petalinux下Zynq7000设备树开发:从理论到实战

zynq的用户自定义设备树,在{petalinux工程}/project-spec/meta-user/recipes-bsp/device-tree/files/ 下,那个叫 system-user.dtsi 就是, 用文本编辑工具打开它,会发现它是这样的:

/include/ "system-conf.dtsi"
/ {
};

这是一个空文件,里面没有任何节点,用户自定义的节点,只需要添加在这里面就行。

对于gpio自动导出,只需要新建一个gpio-export节点,并设置好必要属性,具体内容如下

/include/ "system-conf.dtsi"
/ {gpio-export {compatible = "gpio-export";#gpio-cells = <2>;gpio47 {gpio-export,name = "custom_gpio47";gpio-export,output = <0>;gpios = <&gpio0 47 0>;};};
};
  • gpio-export { … }‌

‌作用‌:创建一个名为gpio-export的子节点,用于管理GPIO导出功能。

  • compatible = “gpio-export”;‌

‌作用‌:绑定Linux内核的gpio-export驱动,该驱动负责将GPIO导出到用户空间。
‌验证‌:可通过内核源码查找COMPATIBLE_STR匹配(如drivers/gpio/gpio-export.c)。

  • #gpio-cells = <2>;‌

‌作用‌:声明每个GPIO描述需要2个参数(控制器、引脚号、激活电平)。
‌背景‌:与GPIO控制器的#gpio-cells定义一致,确保语法匹配。

  • gpio47 { … }‌

‌作用‌:定义GPIO 47的导出配置,子节点名称通常与GPIO编号对应。

  • ‌gpio-export,name = “custom_gpio47”;‌

‌作用‌:指定用户空间看到的GPIO名称(在/sys/class/gpio/下生成同名目录)。
‌用户空间路径‌:

/sys/class/gpio/custom_gpio47/
  • ‌‌gpio-export,output = <0>;‌

‌作用‌:初始化方向为输入(0=输入,1=输出)。
‌扩展‌:若需初始化为输出,需添加gpio-export,init = <0/1>;设置默认电平。

  • ‌‌gpios = <&gpio0 47 0>;‌

‌作用‌:关联硬件GPIO控制器和引脚,格式为:

<&控制器 引脚号 激活电平>

‌参数详解‌:

  • &gpio0:Zynq的MIO控制器(GPIO 0-53)。
  • 47:GPIO编号(需确认硬件未复用为其他功能)。
  • 0:低电平有效(若设为1,则active-high)。

改完之后保存,petalinux-build
在petalinux工程目录下运行

petalinux-build 
[INFO] Sourcing buildtools
[INFO] Building project
[INFO] Sourcing build environment
[INFO] Generating workspace directory
INFO: bitbake petalinux-image-minimal
NOTE: Started PRServer with DBfile: /D/study/zynq7010_project/build/cache/prserv.sqlite3, Address: 127.0.0.1:43583, PID: 73789
Loading cache: 100% |#############################################################| Time: 0:00:01
Loaded 6495 entries from dependency cache.
Parsing recipes: 100% |#############################################################| Time: 0:00:02
Parsing of 4461 .bb files complete (4459 cached, 2 parsed). 6497 targets, 627 skipped, 1 masked, 0 errors.
NOTE: Resolving any missing task queue dependencies
Initialising tasks: 100% |#############################################################| Time: 0:00:08
Checking sstate mirror object availability: 100% |#############################################################| Time: 0:00:11
Sstate summary: Wanted 478 Local 9 Network 304 Missed 165 Current 1106 (65% match, 89% complete)
Removing 19 stale sstate objects for arch zynq_generic: 100% |#############################################################| Time: 0:00:00
NOTE: Executing Tasks
NOTE: Tasks Summary: Attempted 4232 tasks of which 4178 didn't need to be rerun and all succeeded.
INFO: Successfully copied built images to tftp dir: 
/tftpboot/microZed
[INFO] Successfully built project

然后打包,在工程目录下运行

petalinux-package --boot --fsbl --fpga --u-boot --force

然后将boot.bin、image.ub、boot.csr三个文件拷贝到sd卡fat分区,把rootfs.tar.gz文件解压缩要sd卡ext分区。插入microzed,重启。

验证实验

首先启动之前的版本

zynq7010:~$ cd /sys/class/gpio/
zynq7010:/sys/class/gpio$ ls
export       gpiochip906  unexport

可见目录下没有任何导出的gpio,手动导出:
为了方便操作,先切换root:

zynq7010:/sys/class/gpio$ sudo -i
Password: 
root@zynq7010:~# 

再进行导出

root@zynq7010:~# cd /sys/class/gpio/
root@zynq7010:/sys/class/gpio# ls
export       gpiochip906  unexport
root@zynq7010:/sys/class/gpio# echo 953 > export 
root@zynq7010:/sys/class/gpio# ls
export       gpio953      gpiochip906  unexport

导出成功,进行属性配置和值操作,严重gpio操作成功

root@zynq7010:/sys/class/gpio# echo out > gpio953/direction 
root@zynq7010:/sys/class/gpio# 
root@zynq7010:/sys/class/gpio# 
root@zynq7010:/sys/class/gpio# echo 1 > gpio953/value 
root@zynq7010:/sys/class/gpio# cat  gpio953/value                                                                                                                                                                                                                                        
1
root@zynq7010:/sys/class/gpio# echo 0 > gpio953/value                                                                                                                                                                                                                                    
root@zynq7010:/sys/class/gpio# cat  gpio953/value 

修改属性为GPO,同时修改输出值,操作都成功了。

复位办卡,重新启动,再次查看GPIO情况

zynq7010:~$ cd /sys/class/gpio/
zynq7010:/sys/class/gpio$ ls
export       gpiochip906  unexport

上次导出的已经没有了,export是一个临时操作,每次重启后都会丢失,需要重新export。

好了,上修改了设备树后的版本,看看什么情况。

zynq7010:~$ cd /sys/class/gpio/
zynq7010:/sys/class/gpio$ ls
export       gpiochip906  unexport

哦和,还是一样的,没有被导出。是什么原因呢????
经过仔细研究linux设备操作,搞清楚了问题的根本原因,他在于设备树只是申明有这么一个设备,但是是不是会使用,取决于驱动,所以现在要想实现自动export还得自己写一段驱动才行。这个事情先留后面了。在这里借用linux本身就已经有驱动的Led设备。我们通过设备树,把这个设备定义成LED设备,这样linux加载时,就会自动export了。
设备树改动如下:

/include/ "system-conf.dtsi"
/ {my_gpios {compatible = "gpio-leds"; // 使用标准 gpio-leds 驱动(自动导出)status = "okay";my_gpio0 {label = "my-gpio0";gpios = <&gpio0 47 0>; // EMIO GPIO 0 (MIO 0-53, EMIO 54-117)default-state = "on"; // 初始状态};};
};

保存,编译,打包,拷贝到SD卡,启动开发版。进去一查看

zynq7010:~$ cd /sys/class/gpio/
zynq7010:/sys/class/gpio$ ls
export       gpiochip906  unexport

傻了,怎么还没有不应该阿。。。。
突然,灵光一线,设备树把它指定为led设备了,就算导出了,也不再这里了,因该会有一个led目录,于是仔细查看果然:

zynq7010:~$ ls /sys/class/leds/  
mmc0::    my-gpio0

这个my-gpio0不就是我在设备树中定义的标签吗?原来他躲在这里。正好我这个gpio就是用来控制板子上Led,我低头一看板子,果然多亮了一个灯,开心。
继续进到目录,看到

root@zynq7010:/sys/class/leds/my-gpio0# ls
brightness      device          max_brightness  power           subsystem       trigger         uevent
root@zynq7010:/sys/class/leds/my-gpio0# 

brightness 应该就是控制指令了,于是:

root@zynq7010:/sys/class/leds/my-gpio0# cat brightness 
1
root@zynq7010:/sys/class/leds/my-gpio0# 

现在灯亮它是1,改成0应该灭了,试一下:

root@zynq7010:/sys/class/leds/my-gpio0# echo 0 > brightness 
root@zynq7010:/sys/class/leds/my-gpio0# echo 1 > brightness                                                                           
root@zynq7010:/sys/class/leds/my-gpio0# echo 0 > brightness 

果然,灭-亮-灭,就是它了。

结论

通过本文,应该对设备树、驱动、linux硬件驱动框架,应该能有个感性的认知了。
本文的实验至少说明:

  • linux可以通过设备树实现设备的自动export
  • 但是能否export,除了设备树之外,还需要驱动配合,设备树只是定义设备,驱动才是用户,export是驱动做的。

相关文章:

  • 聊聊自动化用例的维护
  • Qt Creator中自定义应用程序的可执行文件图标
  • LM Studio模型下载慢怎么办
  • Java基础系列-HashMap源码解析2-AVL树
  • 从代码学习深度学习 - 自动并行 PyTorch 版
  • 57、Spring Boot 最佳实践
  • NLP高频面试题(五十三)——LLM中激活函数详解
  • 力扣hot100_链表(3)_python版本
  • 盈达科技:登顶GEO优化全球制高点,以AICC定义AI时代内容智能优化新标杆
  • TCP四大特性面试回答引导
  • 【无人机】无人机位置估计出现偏差的原因分析
  • ESP32-S3开发板麦克风录音到SD卡存储测试
  • 自主可控鸿道Intewell工业实时操作系统
  • Rust 语言使用场景分析
  • 【LangChain4j】AI 第一弹:LangChain4j 的理解
  • 图聚类中的亲和力传播
  • 数据库11(触发器)
  • 跨平台软件开发探讨
  • 三目云台转动性能稳定性
  • 动态显微镜数据分析及AI拓展
  • 过敏性鼻炎,不只是“打喷嚏”那么简单
  • 新东方:2025财年前三季度净利增29%,第四财季海外业务将承压
  • 预订假期酒店却被告知无法入住,去哪儿:对违规酒店予以处罚
  • 文旅部:今年一季度国内出游人次17.94亿,同比增长26.4%
  • 五一节,和人民照相馆一起找回“拍照”的仪式感
  • 朱守科已任西藏自治区政府党组成员、自治区公安厅党委书记