杜比 发表于 2024-7-11 09:03:10

LoongOS的gpio操作

本帖最后由 杜比 于 2024-7-11 15:14 编辑

LoongOS的gpio操作

LoongOS是龙芯嵌入式操作系统,遵循Linux系统原理,它的GPIO(通用输入输出)的操作可以通过多种方法实现,包括


[*]使用Sysfs接口GPIO库
[*]设备树
[*]直接访问寄存器等方法。

在了解GPIO操作之前,有必要了解下龙芯的2K0300这个SOC处理器GPIO的一些背景支持:


[*]2K0300有一百多个GPIO端口,每个端口对应一个引脚
[*]GPIO的功能是可以自定义的,也就是复用机制,有主功能(默认配置),复用1,复用2和软件可操作的GPIO
[*]定义GPIO功能,主要是通过设备树来完成,比如久久派max的双网口,第二个网口是通过复用进行配置的
[*]GPIO口可做为输入,也可以做为输出,有些GPIO口也可以定义为中断输入,甚至可以做一些进一步的配置
[*]当定义为GPIO时,可以通过读写这个GPIO口,实现输入和输出等功能

关于设备树的定义,可以参看内核代码如下文件:
src/arch/loongarch/boot/dts/loongson目录下

loongson_2k0300_pai_99.dts
loongson_2k0300.dtsi   
2k0300-pinctrl.dtsi   //GPIO引脚控制




使用Sysfs接口:Sysfs是Linux内核提供的一种文件系统接口,用于与设备驱动程序进行交互。通过/sys/class/gpio目录下的文件,可以访问和控制GPIO引脚。你可以使用Shell命令或编程语言来读取或写入这些文件,以控制GPIO的状态。

GPIO库:有一些开源的GPIO库可以简化GPIO的控制,例如WiringPi,RPi.GPIO和libgpiod等库提供了函数和接口,使得在Linux系统上编程控制GPIO更加方便。你可以根据自己的需求选择适合的库,并按照其文档进行安装和使用。

设备树(Device Tree):对于一些嵌入式系统,GPIO的映射和配置信息通常存储在设备树中。你可以编辑设备树文件,定义GPIO的属性和功能,并在系统启动时加载设备树,使得GPIO能够被正确地初始化和使用。

直接访问寄存器:在一些特定的嵌入式平台上,你可以直接访问GPIO相关的物理寄存器(用户手册里面有描述)来进行控制。这需要对硬件和底层系统有更深入的了解,因此需要谨慎操作。

在linux环境下,可以通过命令来简单的了解GPIO的测试步骤:

    1、导出GPIO引脚:通过向/sys/class/gpio/export文件写入引脚编号来导出引脚。
    2、设置方向:通过写入direction文件来设置引脚的方向为输入或输出。
    3、读写值:通过读取或写入value文件来读取或设置引脚的值。

具体的操作演示:

// 先看下gpio的使用状况
root@LoongOS:gpio# pwd
/sys/class/gpio

root@LoongOS:gpio# ls -la
total 0
drwxr-xr-x2 root root   0 Jun9 10:06 .
drwxr-xr-x 51 root root   0 Jun9 10:06 ..
--w-------1 root root 16384 Jun9 10:17 export
lrwxrwxrwx1 root root   0 Jun9 10:06 gpiochip0 -> ../../devices/platform/soc/16000490.pinctrl/gpio/gpiochip0
lrwxrwxrwx1 root root   0 Jun9 10:06 gpiochip16 -> ../../devices/platform/soc/16000490.pinctrl/gpio/gpiochip16
lrwxrwxrwx1 root root   0 Jun9 10:06 gpiochip32 -> ../../devices/platform/soc/16000490.pinctrl/gpio/gpiochip32
lrwxrwxrwx1 root root   0 Jun9 10:06 gpiochip48 -> ../../devices/platform/soc/16000490.pinctrl/gpio/gpiochip48
lrwxrwxrwx1 root root   0 Jun9 10:06 gpiochip64 -> ../../devices/platform/soc/16000490.pinctrl/gpio/gpiochip64
lrwxrwxrwx1 root root   0 Jun9 10:06 gpiochip80 -> ../../devices/platform/soc/16000490.pinctrl/gpio/gpiochip80
lrwxrwxrwx1 root root   0 Jun9 10:06 gpiochip96 -> ../../devices/platform/soc/16000490.pinctrl/gpio/gpiochip96
--w-------1 root root 16384 Jun9 10:20 unexport

// 导出GPIO88

root@LoongOS:gpio# pwd
/sys/class/gpio

root@LoongOS:gpio# echo 88 > export         
// 这其实是个重定向写入到export文件,export文件是内核gpio驱动的一个映射,gpio驱动会根据写入的值调用相应的功能
// 目录下还有个unexport文件,重定向写入这个文件,会释放对应gpio口

root@LoongOS:gpio# ls -la
total 0
drwxr-xr-x2 root root   0 Jun9 10:06 .
drwxr-xr-x 51 root root   0 Jun9 10:06 ..
--w-------1 root root 16384 Jun9 10:30 export
lrwxrwxrwx1 root root   0 Jun9 10:30 gpio88 -> ../../devices/platform/soc/16000490.pinctrl/gpiochip5/gpio/gpio88
lrwxrwxrwx1 root root   0 Jun9 10:06 gpiochip0 -> ../../devices/platform/soc/16000490.pinctrl/gpio/gpiochip0
lrwxrwxrwx1 root root   0 Jun9 10:06 gpiochip16 -> ../../devices/platform/soc/16000490.pinctrl/gpio/gpiochip16
lrwxrwxrwx1 root root   0 Jun9 10:06 gpiochip32 -> ../../devices/platform/soc/16000490.pinctrl/gpio/gpiochip32
lrwxrwxrwx1 root root   0 Jun9 10:06 gpiochip48 -> ../../devices/platform/soc/16000490.pinctrl/gpio/gpiochip48
lrwxrwxrwx1 root root   0 Jun9 10:06 gpiochip64 -> ../../devices/platform/soc/16000490.pinctrl/gpio/gpiochip64
lrwxrwxrwx1 root root   0 Jun9 10:06 gpiochip80 -> ../../devices/platform/soc/16000490.pinctrl/gpio/gpiochip80
lrwxrwxrwx1 root root   0 Jun9 10:06 gpiochip96 -> ../../devices/platform/soc/16000490.pinctrl/gpio/gpiochip96
--w-------1 root root 16384 Jun9 10:20 unexport

可以看出,新增了一个gpio88目录,说明导出成功
gpio88目录的软连接信息里,加粗的信息对应着设备树的结构
gpiochip5 的信息和gpio分组配置有关,16个gpio为一组,每个gpio占2位,对应4种复用关系,一组占32个位,也就是一个word
所以GPIO88的组是88/16 = 5 余 8,除数就是组号
如果导出GPIO66,看看会发生什么!

root@LoongOS:gpio# echo 66 > export
loongson_gpio_request: GPA64used_pins_bitmap: 0X0000FF6F      
current gpio request pin: chip->name gpa4, gpio: 0X00000004      // 第4组
CPU: 0 PID: 1609 Comm: sh Tainted: G         O      4.19.190 #22
Stack : 900000000113afd8 9000000000d7afa8 900000009da0c000 900000009da0fb50
         0000000000000000 900000009da0fb50 900000000148eac8 ffffffffffffffff
         0000000000000000 ffffffffffffffff 0000000000000007 0000000000000000
         9000000000d7afa8 0000000000000007 0000000000000006 0000000000000007
         9000000005500848 0000000000aaaaaa 00000000000002a1 0000000000000001
         0000000000000001 0000000004110000 0000007ffba733e4 ffffff8000000000
         90000000012c9bc8 0000000000000004 0000000000000000 900000000108caf8
         900000009c2eb720 0000005555a66418 0000000000000000 0000007ffba733e0
         900000000020a074 0000005555aafc50 00000000000000b0 0000000000000004
         0000000000000000 0000000000071fff 0000000000000800 90000000012c9bc8
         ...
Call Trace:
[<900000000020a074>] show_stack+0x34/0x140
[<9000000000d7afa8>] dump_stack+0xa8/0xdc
[<9000000000759d48>] loongson_gpio_request+0x78/0xc0
[<900000000075cf7c>] gpiod_request_commit+0x10c/0x2d0
[<9000000000760138>] gpiod_request+0x58/0xc0
[<9000000000764b0c>] export_store+0x7c/0x150
[<9000000000469c08>] kernfs_fop_write+0xc8/0x1e0
[<90000000003db9b8>] __vfs_write+0x28/0x170
[<90000000003dbce4>] vfs_write+0xc4/0x1d0
[<90000000003dbfa4>] ksys_write+0x64/0x100
[<90000000002116f8>] syscall_common+0x24/0x34
<b>drivers/pinctrl/pinctrl-ls2k300.c:gpio functions has redefinition



接下来看一个更好玩的

// 输出系统当前的gpio复用表格,可以通过这种方式查看系统当前的GPIO口复用情况

root@LoongOS:device# cat    /sys/class/gpio/gpiochip0/device/dump_gpio
PA0-00:main   PA1-00:main   PA2-00:main   PA3-00:main   PA4-00:main   PA5-00:main   PA6-00:main
PA0-01:main   PA1-01:main   PA2-01:main   PA3-01:main   PA4-01:main   PA5-01:gpio   PA6-01:main
PA0-02:main   PA1-02:main   PA2-02:main   PA3-02:main   PA4-02:main   PA5-02:gpio   PA6-02:main
PA0-03:main   PA1-03:main   PA2-03:main   PA3-03:main   PA4-03:main   PA5-03:gpio   PA6-03:main
PA0-04:main   PA1-04:main   PA2-04:main   PA3-04:gpio   PA4-04:gpio   PA5-04:gpio   PA6-04:main
PA0-05:main   PA1-05:main   PA2-05:main   PA3-05:gpio   PA4-05:func1    PA5-05:gpio   PA6-05:main
PA0-06:main   PA1-06:main   PA2-06:main   PA3-06:gpio   PA4-06:func1    PA5-06:func2    PA6-06:main
PA0-07:main   PA1-07:main   PA2-07:main   PA3-07:gpio   PA4-07:gpio   PA5-07:gpio   PA6-07:main
PA0-08:main   PA1-08:main   PA2-08:main   PA3-08:main   PA4-08:main   PA5-08:gpio   PA6-08:main
PA0-09:main   PA1-09:main   PA2-09:main   PA3-09:main   PA4-09:main   PA5-09:gpio   PA6-09:main
PA0-10:main   PA1-10:main   PA2-10:main   PA3-10:main   PA4-10:main   PA5-10:main   PA6-10:gpio
PA0-11:main   PA1-11:main   PA2-11:main   PA3-11:main   PA4-11:main   PA5-11:main   PA6-11:gpio
PA0-12:main   PA1-12:main   PA2-12:main   PA3-12:main   PA4-12:main   PA5-12:main   PA6-12:gpio
PA0-13:main   PA1-13:main   PA2-13:main   PA3-13:main   PA4-13:main   PA5-13:main   PA6-13:gpio
PA0-14:main   PA1-14:main   PA2-14:main   PA3-14:main   PA4-14:main   PA5-14:main   PA6-14:gpio
PA0-15:main   PA1-15:main   PA2-15:main   PA3-15:main   PA4-15:main   PA5-15:main   PA6-15:gpio
root@LoongOS:device#
此外,对于需要更高性能的应用,可以通过内存映射的方式直接操作GPIO寄存器,这通常需要管理员权限,并且需要对硬件有深入的了解。

在LoongOS中提供了一个叫 devmem2 的工具软件

root@LoongOS:bin# devmem2

Usage:devmem2 { address } [ type [ data ] ]
      address : memory address to act upon
      type    : access operation type : yte, alfword, ord, ong
      data    : data to be written

使用方法: devmem2物理地址类型[数值]         数值 = 要写入的值,如果是读,不用提供数值

如:GPIO复用配置寄存器的地址是 16000490.pinctrl 中的 0x16000490,属于芯片配置寄存器,采用直接映射机制,它的地址是 0x8000000016000490

root@LoongOS:bin# devmem2 0x016000490 w 0000       // 对0x16000490 写一个字,值 = 0000,相当于把 gpio0 - gpio15 都设置成 00,也就是GPIO功能
/dev/mem opened.
Memory mapped at address 0x7ff458c000.
Read at address0x16000490 (0x7ff458c490): 0xFFFFFFFF
Write at address 0x16000490 (0x7ff458c490): 0x00000000, readback 0x00000000


root@LoongOS:bin# cat    /sys/class/gpio/gpiochip0/device/dump_gpio
PA0-00:gpio   PA1-00:main   PA2-00:main   PA3-00:main   PA4-00:main   PA5-00:main   PA6-00:main
PA0-01:gpio   PA1-01:main   PA2-01:main   PA3-01:main   PA4-01:main   PA5-01:gpio   PA6-01:main
PA0-02:gpio   PA1-02:main   PA2-02:main   PA3-02:main   PA4-02:main   PA5-02:gpio   PA6-02:main
PA0-03:gpio   PA1-03:main   PA2-03:main   PA3-03:main   PA4-03:main   PA5-03:gpio   PA6-03:main
PA0-04:gpio   PA1-04:main   PA2-04:main   PA3-04:gpio   PA4-04:gpio   PA5-04:gpio   PA6-04:main
PA0-05:gpio   PA1-05:main   PA2-05:main   PA3-05:gpio   PA4-05:func1    PA5-05:gpio   PA6-05:main
PA0-06:gpio   PA1-06:main   PA2-06:main   PA3-06:gpio   PA4-06:func1    PA5-06:func2    PA6-06:main
PA0-07:gpio   PA1-07:main   PA2-07:main   PA3-07:gpio   PA4-07:gpio   PA5-07:gpio   PA6-07:main
PA0-08:gpio   PA1-08:main   PA2-08:main   PA3-08:main   PA4-08:main   PA5-08:gpio   PA6-08:main
PA0-09:gpio   PA1-09:main   PA2-09:main   PA3-09:main   PA4-09:main   PA5-09:gpio   PA6-09:main
PA0-10:gpio   PA1-10:main   PA2-10:main   PA3-10:main   PA4-10:main   PA5-10:main   PA6-10:gpio
PA0-11:gpio   PA1-11:main   PA2-11:main   PA3-11:main   PA4-11:main   PA5-11:main   PA6-11:gpio
PA0-12:gpio   PA1-12:main   PA2-12:main   PA3-12:main   PA4-12:main   PA5-12:main   PA6-12:gpio
PA0-13:gpio   PA1-13:main   PA2-13:main   PA3-13:main   PA4-13:main   PA5-13:main   PA6-13:gpio
PA0-14:gpio   PA1-14:main   PA2-14:main   PA3-14:main   PA4-14:main   PA5-14:main   PA6-14:gpio
PA0-15:gpio   PA1-15:main   PA2-15:main   PA3-15:main   PA4-15:main   PA5-15:main   PA6-15:gpio

// 这种寄存器直接读写操作,不会有任何的提示和警告



zl2013 发表于 2024-7-11 09:14:10

:handshake
页: [1]
查看完整版本: LoongOS的gpio操作