内核子系统运用---sysfs控制GPIO

命令行界面控制GPIO方法

配置

Linux 4.9在终端下查看是否有/sys/class/gpio 目录
没有打开内核选项
Device Drivers-》GPIO Support -》/sys/class/gpio/… (sysfs interface)  ==CONFIG_GPIO_SYSFS

操作

1 echo “166” > /sys/class/gpio/export
2 echo “out” > /sys/class/gpio/gpio166/direction
3 echo “1” > /sys/class/gpio/gpio166/value

  1. 将166编号的GPIO 导出
  2. 将166编号的GPIO方向设置成out
  3. 设置166编号的GPIO电平

166 编号的由来

不同平台编号计算方式不一样
以hisi 3559为例 166 对应 SHUB_GPIO1_6
hisi3559 平台一共GPIO0----GPIO18 SHUB0—SHUB4 《SHUB(Senosr Hub)》
按编号模拟SHUB0 -》GPIO19,SHUB_GPIO1-》GPIO20 以此类推。。。
(设备树文件中可以查看到)
hisi 每组GPIO最多含8个脚,所以编号166==20 * 8 +6
有的平台可能就是20 * 32 ,不同平台计算方式不一样

注意

1.GPIO的第二功能寄存器记得配置成GPIO模式
2.hisiGPIO 数据寄存器的地址包含读写寄存器屏蔽位,熟读并背诵数据手册
若地址为为0x3FC(0b11_1111_1100),则对GPIO_DATA[7:0]这8bit操作全部有
效。
若地址为0x200(0b10_0000_0000),则仅对GPIO_DATA[7]的操作有效。

如何得知gpio的编号

由上面得知每一个编号对应一个gpio,这个编号其实是没有意义的,只是认为的将gpio管脚人为的定义一个号码来对应,简化操作。那么我们最终操作的是gpio,那么如何得知gpio他的编号是多少。这种管脚对应编号的编码方式每个公司厂家的芯片可能都不一样,最重要的是找到这个关系,才能知道编号

比如novatek平台

找到arch中描述gpio的文件
arch\arm\plat-novatek\include\plat-na51089\nvt-gpio.h

/* GPIO pin number translation  */
#define C_GPIO(pin)                     (pin)
#define P_GPIO(pin)                     (pin + 0x20)
#define S_GPIO(pin)                     (pin + 0x40)
#define L_GPIO(pin)                     (pin + 0x60)
#define D_GPIO(pin)                     (pin + 0x80)
#define H_GPIO(pin)                     (pin + 0xA0)
#define A_GPIO(pin)                     (pin + 0xC0)
#define DSI_GPIO(pin)                   (pin + 0xE0)

#define C_GPIO_NUM                      23
#define P_GPIO_NUM                      26
#define S_GPIO_NUM                      9
#define L_GPIO_NUM                      10
#define H_GPIO_NUM                      12
#define D_GPIO_NUM                      8
#define A_GPIO_NUM                      3
#define DSI_GPIO_NUM                    11
nt平台不像hisi有顺序的1 2 3 4 组,他分组C P S L D H A ,,
A_GPIO 3 那么他的编号就是 0xC0 + 3 ,这样计算而来。
他这个排序的规则也是按照数据手册寄存器的递增的规则定义的

hisi平台

hisi平台的pinctl采用的是gpio-pl061驱动,而每组的GPIO都有编号
比如GPIO1_2,GPIO14_7等。

设备树中每块chip都有描述
在这里插入图片描述
在这里插入图片描述
从pl061的驱动来看,获取gpio的alias
并将gpio的每组第一个管脚编号即每个gpio chip的base为序号*8

比如GPIO12,那么他的gpio chip 的base 就是12*8;

static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
{
....
		if (dev->of_node) {
			i = of_alias_get_id(dev->of_node, "gpio");
			chip->gc.base = i * PL061_GPIO_NR;//#define PL061_GPIO_NR	8
		}
...
ret = gpiochip_add_data(&chip->gc, chip);
...
}

然后在gpiochip_add_data中会对这个chip申请PL061_GPIO_NR 个gpio的desc,
用来表示各个管脚,因为每个chip有8个管脚,所以前面GPIO20_6,为什么他的编号为166,是驱动定义导致的。


static int pl061_get_value(struct gpio_chip *gc, unsigned offset)
{
	struct pl061_gpio *chip = gpiochip_get_data(gc);

	return !!readb(chip->base + (BIT(offset + 2)));
}

在pl061中get value有+2的操作,是因为这个GPIO口的data寄存器硬件设计原因。
他的BIT[9:2]才描述GPIOX_0----7的管脚状态
GPIO_DATA 寄存器利用 PADDR[9:2] 实现了读写寄存器比特的屏蔽操作。

最后我们可以整一个脚本来操作

#!/bin/sh

GPIO_DIR=$1
GPIO_NUM=$2
GPIO_VAL=$3

if [[ "${GPIO_DIR}" != "out" ]] && [[ "${GPIO_DIR}" != 'in' ]] && [[ $# != 3 ]];
then
	echo "para error!"
	echo "example: ./gpio out/in XXX 1"
	exit 1
fi

if [[ ${GPIO_VAL} != 0 ]] ;then
	GPIO_VAL=1;
fi

if [ ! -d "/sys/class/gpio/gpio${GPIO_NUM}" ] ;then
	echo ${GPIO_NUM} > /sys/class/gpio/export
fi

echo ${GPIO_DIR} > /sys/class/gpio/gpio${GPIO_NUM}/direction
if [ "${GPIO_DIR}" == 'out' ] ;then
	echo ${GPIO_VAL} > /sys/class/gpio/gpio${GPIO_NUM}/value
else
	echo "gpio${GPIO_NUM}:	`cat /sys/class/gpio/gpio${GPIO_NUM}/value`"
fi
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值