[实战]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是驱动做的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值