內(nèi)核里的gpiolib除了提供如gpio_request, gpio_direction_input/output, gpio_set_value等操作函數(shù)外,還提供了在終端上用直接操作gpio口的功能.
首先確認(rèn)內(nèi)核里是否已選擇上gpiolib的sysfs接口功能(默認(rèn)是已選擇上的)
make menuconfig ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
Device Drivers --->
*- GPIO Support --->
[*] /sys/class/gpio/... (sysfs interface)
然后確認(rèn)在linux內(nèi)核源碼里gpio口對應(yīng)的序號,這個是由芯片廠家自定義的,通常在”arch/arm/mach-xxx/include/mach/gpio.h”里.
h3的gpio口定義在”arch/arm/mach-sunxi/include/mach/gpio.h”
#define SUNXI_BANK_SIZE 32
#define SUNXI_PA_BASE 0
#define SUNXI_PB_BASE 32
#define SUNXI_PC_BASE 64
#define SUNXI_PD_BASE 96
#define SUNXI_PE_BASE 128
#define SUNXI_PF_BASE 160
#define SUNXI_PG_BASE 192
#define SUNXI_PH_BASE 224
#define SUNXI_PI_BASE 256
#define SUNXI_PJ_BASE 288
#define SUNXI_PK_BASE 320
#define SUNXI_PL_BASE 352
#define SUNXI_PM_BASE 384
#define SUNXI_PN_BASE 416
#define SUNXI_PO_BASE 448
#define AXP_PIN_BASE 1024
#define SUNXI_PIN_NAME_MAX_LEN 8
/* sunxi gpio name space */
#define GPIOA(n) (SUNXI_PA_BASE + (n))
#define GPIOB(n) (SUNXI_PB_BASE + (n))
#define GPIOC(n) (SUNXI_PC_BASE + (n))
#define GPIOD(n) (SUNXI_PD_BASE + (n))
#define GPIOE(n) (SUNXI_PE_BASE + (n))
#define GPIOF(n) (SUNXI_PF_BASE + (n))
#define GPIOG(n) (SUNXI_PG_BASE + (n))
#define GPIOH(n) (SUNXI_PH_BASE + (n))
#define GPIOI(n) (SUNXI_PI_BASE + (n))
#define GPIOJ(n) (SUNXI_PJ_BASE + (n))
#define GPIOK(n) (SUNXI_PK_BASE + (n))
#define GPIOL(n) (SUNXI_PL_BASE + (n))
#define GPIOM(n) (SUNXI_PM_BASE + (n))
#define GPION(n) (SUNXI_PN_BASE + (n))
#define GPIOO(n) (SUNXI_PO_BASE + (n))
#define GPIO_AXP(n) (AXP_PIN_BASE + (n))
gpio口的操作過程,如控制status-led(接在PA15)的亮滅.
1 讓gpiolib導(dǎo)出PA15的控制文件. 可根據(jù)上面檢出PA15引腳對應(yīng)的gpio口序號為15
echo 15 > /sys/class/gpio/export
操作完成后,應(yīng)會在/sys/class/gpio/目錄下生成一個gpio15的子目錄.
2 在/sys/class/gpio/gpio15目錄有文件:
/mnt/kernel_coding # ls /sys/class/gpio/gpio15/
active_low direction edge value
//通過direction文件可控制gpio口是作輸入或輸出功能
// echo "high" > /sys/class/gpio/gpio15/direction 是讓gpio口作輸出,并輸出高電平
// echo "out" > /sys/class/gpio/gpio15/direction 是作輸出功能,并輸出低電平
// echo "in" > /sys/class/gpio/gpio15/direction 是作輸入功能
//通過value文件可以獲取和控制gpio口的電平(當(dāng)gpio口作輸出時(shí),可以通過寫操作改變電平。當(dāng)作輸入時(shí),可以通過讀操作獲取電平)
// echo "1" > /sys/class/gpio/gpio15/value 讓gpio口輸出高電平
// echo "0" > /sys/class/gpio/gpio15/value 讓gpio口輸出低電平
//通過edge文件, 可以指定gpio作中斷功能,并指定它的觸發(fā)電平和獲取. 觸發(fā)電平方式有("none", "falling", "rising", "both")
//通過active_low文件,可以指定往value文件寫1時(shí)為有效電平.
如: echo "1" > /sys/calss/gpio/gpio15/value時(shí)是輸出高電平的
當(dāng)echo "1" > /sys/calss/gpio/gpio15/active_low后, 再往value寫1是就是輸出低電平了.
工作原理可參考https://blog.csdn.net/jklinux/article/details/73896459
702 static struct class_attribute gpio_class_attrs[] = {
703 __ATTR(export, 0200, NULL, export_store), // 當(dāng)對/sys/class/gpio/export進(jìn)行寫操作時(shí),會觸發(fā)調(diào)用export_store函數(shù)
704 __ATTR(unexport, 0200, NULL, unexport_store),
705 __ATTR_NULL,
706 };
707
708 static struct class gpio_class = {
709 .name = "gpio",
710 .owner = THIS_MODULE,
711
712 .class_attrs = gpio_class_attrs, //指定了屬性文件. (/sys/class/gpio/export, /sys/class/gpio/unexport)
713 };
997 static int __init gpiolib_sysfs_init(void)
998 {
...
1003 status = class_register(&gpio_class); //注冊class后就會生成/sys/class/gpio目錄,并在目錄下生成gpio_class的屬性文件
...
1029 }
1030 postcore_initcall(gpiolib_sysfs_init); //系統(tǒng)初始化時(shí)會調(diào)用
//當(dāng)對"echo gpio口對應(yīng)的序號 > /sys/class/gpio/export"進(jìn)行寫操作時(shí),會觸發(fā)調(diào)用export_store函數(shù)
637 static ssize_t export_store(struct class *class,
638 struct class_attribute *attr,
639 const char *buf, size_t len)
640 {
641 long gpio;
642 int status;
643
644 status = strict_strtol(buf, 0, &gpio); //把字符串buf里描述的gpio口序號轉(zhuǎn)成long類型變量gpio
...
653 status = gpio_request(gpio, "sysfs"); //請求gpio口
...
659 status = gpio_export(gpio, true); //再調(diào)用gpio_export函數(shù)來處理請求的gpio口
...
669 }
731 int gpio_export(unsigned gpio, bool direction_may_change)
732 {
...
774 dev = device_create_with_groups(&gpio_class, desc->chip->dev,
775 MKDEV(0, 0), desc, gpio_groups,
776 ioname ? ioname : "gpio%u", gpio); //會在/sys/class/gpio/目錄下生成一個名為"gpio"+gpio口序號的子目錄(請gpio口為15, 則子目錄名為"gpio15"), 并在子目錄生成"direction, edge,value, active_low"等屬性文件
...
790 }
791 EXPORT_SYMBOL_GPL(gpio_export);
571 static struct attribute *gpio_attrs[] = {
572 &dev_attr_direction.attr,
573 &dev_attr_edge.attr,
574 &dev_attr_value.attr,
575 &dev_attr_active_low.attr,
576 NULL,
577 };
578
579 static const struct attribute_group gpio_group = {
580 .attrs = gpio_attrs,
581 .is_visible = gpio_is_visible,
582 };
583
584 static const struct attribute_group *gpio_groups[] = {
585 &gpio_group,
586 NULL
587 };
///////////////////////////////////
242 static ssize_t gpio_direction_store(struct device *dev,
243 struct device_attribute *attr, const char *buf, size_t size)
244 {
245 const struct gpio_desc *desc = dev_get_drvdata(dev);
246 unsigned gpio = desc - gpio_desc;
247 ssize_t status;
248
249 mutex_lock(&sysfs_lock);
250
251 if (!test_bit(FLAG_EXPORT, &desc->flags))
252 status = -EIO;
253 else if (sysfs_streq(buf, "high"))
254 status = gpio_direction_output(gpio, 1);
255 else if (sysfs_streq(buf, "out") || sysfs_streq(buf, "low"))
256 status = gpio_direction_output(gpio, 0);
257 else if (sysfs_streq(buf, "in"))
258 status = gpio_direction_input(gpio);
259 else
260 status = -EINVAL;
261
262 mutex_unlock(&sysfs_lock);
263 return status ? : size;
264 }
265
266 static DEVICE_ATTR(direction, 0644,
267 gpio_direction_show, gpio_direction_store); // 當(dāng)對direction屬性文件寫操作時(shí),觸發(fā)調(diào)用gpio_direction_store. 如寫"out"則把gpio口作為輸出,并輸出低電平. 同樣的原理,可以通過value屬性文件操作gpio口的電平狀態(tài).
|