核心裡的gpiolib在終端上命令操作gpio口
阿新 • • 發佈:2019-02-11
核心裡的gpiolib除了提供如gpio_request, gpio_direction_input/output, gpio_set_value等操作函式外,還提供了在終端上用直接操作gpio口的功能.
首先確認核心裡是否已選擇上gpiolib的sysfs介面功能(預設是已選擇上的)
make menuconfig ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
Device Drivers --->
*- GPIO Support --->
[*] /sys/class/gpio/... (sysfs interface)
然後確認在linux核心原始碼裡gpio口對應的序號,這個是由晶片廠家自定義的,通常在”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匯出PA15的控制檔案. 可根據上面檢出PA15引腳對應的gpio口序號為15
echo 15 > /sys/class/gpio/export
操作完成後,應會在/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口的電平(當gpio口作輸出時,可以通過寫操作改變電平。當作輸入時,可以通過讀操作獲取電平)
// echo "1" > /sys/class/gpio/gpio15/value 讓gpio口輸出高電平
// echo "0" > /sys/class/gpio/gpio15/value 讓gpio口輸出低電平
//通過edge檔案, 可以指定gpio作中斷功能,並指定它的觸發電平和獲取. 觸發電平方式有("none", "falling", "rising", "both")
//通過active_low檔案,可以指定往value檔案寫1時為有效電平.
如: echo "1" > /sys/calss/gpio/gpio15/value時是輸出高電平的
當echo "1" > /sys/calss/gpio/gpio15/active_low後, 再往value寫1是就是輸出低電平了.
702 static struct class_attribute gpio_class_attrs[] = {
703 __ATTR(export, 0200, NULL, export_store), // 當對/sys/class/gpio/export進行寫操作時,會觸發呼叫export_store函式
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); //系統初始化時會呼叫
//當對"echo gpio口對應的序號 > /sys/class/gpio/export"進行寫操作時,會觸發呼叫export_store函式
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口序號轉成long型別變數gpio
...
653 status = gpio_request(gpio, "sysfs"); //請求gpio口
...
659 status = gpio_export(gpio, true); //再呼叫gpio_export函式來處理請求的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); // 當對direction屬性檔案寫操作時,觸發呼叫gpio_direction_store. 如寫"out"則把gpio口作為輸出,並輸出低電平. 同樣的原理,可以通過value屬性檔案操作gpio口的電平狀態.