最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

【深度】韋東山:GPIO和Pinctrl子系統(tǒng)的使用 (附免費(fèi)視頻)

2020-03-17 19:12 作者:韋東山  | 我要投稿

作者:韋東山

GPIO和Pinctrl子系統(tǒng)的使用

參考文檔:

a. 內(nèi)核 Documentation\devicetree\bindings\Pinctrl\ 目錄下:

Pinctrl-bindings.txt


b. 內(nèi)核 Documentation\gpio 目錄下:

Pinctrl-bindings.txt


c. 內(nèi)核 Documentation\devicetree\bindings\gpio 目錄下:

gpio.txt


注意:本章的重點(diǎn)在于“使用”,深入講解放在“驅(qū)動大全”的視頻里。

前面的視頻,我們使用直接操作寄存器的方法編寫驅(qū)動。這只是為了讓大家掌握驅(qū)動程序的本質(zhì),在實(shí)際開發(fā)過程中我們可不這樣做,太低效了!如果驅(qū)動開發(fā)都是這樣去查找寄存器,那我們就變成“寄存器工程師”了,即使是做單片機(jī)的都不執(zhí)著于裸寫寄存器了。

Linux下針對引腳有2個重要的子系統(tǒng):GPIO、Pinctrl。


1 Pinctrl子系統(tǒng)重要概念

1.1 引入

無論是哪種芯片,都有類似下圖的結(jié)構(gòu):



要想讓pinA、B用于GPIO,需要設(shè)置IOMUX讓它們連接到GPIO模塊;

要想讓pinA、B用于I2C,需要設(shè)置IOMUX讓它們連接到I2C模塊。

所以GPIO、I2C應(yīng)該是并列的關(guān)系,它們能夠使用之前,需要設(shè)置IOMUX。有時候并不僅僅是設(shè)置IOMUX,還要配置引腳,比如上拉、下拉、開漏等等。


現(xiàn)在的芯片動輒幾百個引腳,在使用到GPIO功能時,讓你一個引腳一個引腳去找對應(yīng)的寄存器,這要瘋掉。術(shù)業(yè)有專攻,這些累活就讓芯片廠家做吧──他們是BSP工程師。我們在他們的基礎(chǔ)上開發(fā),我們是驅(qū)動工程師。開玩笑的,BSP工程師是更懂他自家的芯片,但是如果驅(qū)動工程師看不懂他們的代碼,那你的進(jìn)步也有限啊。


所以,要把引腳的復(fù)用、配置抽出來,做成Pinctrl子系統(tǒng),給GPIO、I2C等模塊使用。

BSP工程師要做什么?看下圖:



等BSP工程師在GPIO子系統(tǒng)、Pinctrl子系統(tǒng)中把自家芯片的支持加進(jìn)去后,我們就可以非常方便地使用這些引腳了:點(diǎn)燈簡直太簡單了。


等等,GPIO模塊在圖中跟I2C不是并列的嗎?干嘛在講Pinctrl時還把GPIO子系統(tǒng)拉進(jìn)來?

大多數(shù)的芯片,沒有單獨(dú)的IOMUX模塊,引腳的復(fù)用、配置等等,就是在GPIO模塊內(nèi)部實(shí)現(xiàn)的。

在硬件上GPIO和Pinctrl是如此密切相關(guān),在軟件上它們的關(guān)系也非常密切。

所以這2個子系統(tǒng)我們一起講解。


1.2 重要概念

從設(shè)備樹開始學(xué)習(xí)Pintrl會比較容易。

主要參考文檔是:內(nèi)核Documentation\devicetree\bindings\pinctrl\pinctrl-bindings.txt


這會涉及2個對象:pin controller、client device。

前者提供服務(wù):可以用它來復(fù)用引腳、配置引腳。

后者使用服務(wù):聲明自己要使用哪些引腳的哪些功能,怎么配置它們。


a. pin controller:

在芯片手冊里你找不到pin controller,它是一個軟件上的概念,你可以認(rèn)為它對應(yīng)IOMUX──用來復(fù)用引腳,還可以配置引腳(比如上下拉電阻等)。

注意,pin controller和GPIO Controller不是一回事,前者控制的引腳可用于GPIO功能、I2C功能;后者只是把引腳配置為輸出、輸出等簡單的功能。


b. client device

“客戶設(shè)備”,誰的客戶?Pinctrl系統(tǒng)的客戶,那就是使用Pinctrl系統(tǒng)的設(shè)備,使用引腳的設(shè)備。它在設(shè)備樹里會被定義為一個節(jié)點(diǎn),在節(jié)點(diǎn)里聲明要用哪些引腳。

下面這個圖就可以把幾個重要概念理清楚:



上圖中,左邊是pincontroller節(jié)點(diǎn),右邊是client device節(jié)點(diǎn):

a. pin state:

對于一個“client device”來說,比如對于一個UART設(shè)備,它有多個“狀態(tài)”:default、sleep等,那對應(yīng)的引腳也有這些狀態(tài)。

怎么理解?

比如默認(rèn)狀態(tài)下,UART設(shè)備是工作的,那么所用的引腳就要復(fù)用為UART功能。

在休眠狀態(tài)下,為了省電,可以把這些引腳復(fù)用為GPIO功能;或者直接把它們配置輸出高電平。

上圖中,pinctrl-names里定義了2種狀態(tài):default、sleep。

第0種狀態(tài)用到的引腳在pinctrl-0中定義,它是state_0_node_a,位于pincontroller節(jié)點(diǎn)中。

第1種狀態(tài)用到的引腳在pinctrl-1中定義,它是state_1_node_a,位于pincontroller節(jié)點(diǎn)中。

當(dāng)這個設(shè)備處于default狀態(tài)時,pinctrl子系統(tǒng)會自動根據(jù)上述信息把所用引腳復(fù)用為uart0功能。

當(dāng)這這個設(shè)備處于sleep狀態(tài)時,pinctrl子系統(tǒng)會自動根據(jù)上述信息把所用引腳配置為高電平。


b. groups和function:

一個設(shè)備會用到一個或多個引腳,這些引腳就可以歸為一組(group);

這些引腳可以復(fù)用為某個功能:function。

當(dāng)然:一個設(shè)備可以用到多能引腳,比如A1、A2兩組引腳,A1組復(fù)用為F1功能,A2組復(fù)用為F2功能。


c. Generic pin multiplexing node和Generic pin configuration node

在上圖左邊的pin controller節(jié)點(diǎn)中,有子節(jié)點(diǎn)或?qū)O節(jié)點(diǎn),它們是給client device使用的。

可以用來描述復(fù)用信息:哪組(group)引腳復(fù)用為哪個功能(function);

可以用來描述配置信息:哪組(group)引腳配置為哪個設(shè)置功能(setting),比如上拉、下拉等。


注意:pin controller節(jié)點(diǎn)的格式,沒有統(tǒng)一的標(biāo)準(zhǔn)?。。。∶考倚酒疾灰粯?。

甚至上面的group、function關(guān)鍵字也不一定有,但是概念是有的。

1.3 示例



1.4 代碼中怎么引用pinctrl

這是透明的,我們的驅(qū)動基本不用管。當(dāng)設(shè)備切換狀態(tài)時,對應(yīng)的pinctrl就會被調(diào)用。

比如在platform_device和platform_driver的枚舉過程中,流程如下:



當(dāng)系統(tǒng)休眠時,也會去設(shè)置該設(shè)備sleep狀態(tài)對應(yīng)的引腳,不需要我們自己去調(diào)用代碼。


非要自己調(diào)用,也有函數(shù):

devm_pinctrl_get_select_default(struct device *dev);??? ??// 使用"default"狀態(tài)的引腳

pinctrl_get_select(struct device *dev, const char *name); // 根據(jù)name選擇某種狀態(tài)的引腳

pinctrl_put(struct pinctrl *p);?? // 不再使用, 退出時調(diào)用


2.GPIO子系統(tǒng)重要概念

2.1 引入

要操作GPIO引腳,先把所用引腳配置為GPIO功能,這通過Pinctrl子系統(tǒng)來實(shí)現(xiàn)。

然后就可以根據(jù)設(shè)置引腳方向(輸入還是輸出)、讀值──獲得電平狀態(tài),寫值──輸出高低電平。

以前我們通過寄存器來操作GPIO引腳,即使LED驅(qū)動程序,對于不同的板子它的代碼也完全不同。

當(dāng)BSP工程師實(shí)現(xiàn)了GPIO子系統(tǒng)后,我們就可以:

a. 在設(shè)備樹里指定GPIO引腳

b. 在驅(qū)動代碼中:

使用GPIO子系統(tǒng)的標(biāo)準(zhǔn)函數(shù)獲得GPIO、設(shè)置GPIO方向、讀取/設(shè)置GPIO值。

這樣的驅(qū)動代碼,將是單板無關(guān)的。


2.2 在設(shè)備樹中指定引腳

在幾乎所有ARM芯片中,GPIO都分為幾組,每組中有若干個引腳。所以在使用GPIO子系統(tǒng)之前,就要先確定:它是哪組的?組里的哪一個?

在設(shè)備樹中,“GPIO組”就是一個GPIO Controller,這通常都由芯片廠家設(shè)置好。我們要做的是找到它名字,比如“gpio1”,然后指定要用它里面的哪個引腳,比如<&gpio1 0>。

有代碼更直觀,下圖是一些芯片的GPIO控制器節(jié)點(diǎn),它們一般都是廠家定義好,在xxx.dtsi文件中:



我們暫時只需要關(guān)心里面的這2個屬性:

gpio-controller;

#gpio-cells = <2>;

“gpio-controller”表示這個節(jié)點(diǎn)是一個GPIO Controller,它下面有很多引腳。

“#gpio-cells = <2>”表示這個控制器下每一個引腳要用2個32位的數(shù)(cell)來描述。

為什么要用2個數(shù)?其實(shí)使用多個cell來描述一個引腳,這是GPIO Controller自己決定的。比如可以用其中一個cell來表示那是哪一個引腳,用另一個cell來表示它是高電平有效還是低電平有效,甚至還可以用更多的cell來示其他特性。

普遍的用法是,用第1個cell來表示哪一個引腳,用第2個cell來表示有效電平:

GPIO_ACTIVE_HIGH : 高電平有效

GPIO_ACTIVE_LOW : 低電平有效


定義GPIO Controller是芯片廠家的事,我們怎么引用某個引腳呢?在自己的設(shè)備節(jié)點(diǎn)中使用屬性"[<name>-]gpios",示例如下:



上圖中,可以使用gpios屬性,也可以使用name-gpios屬性。


2.3 在驅(qū)動代碼中調(diào)用GPIO子系統(tǒng)

在設(shè)備樹中指定了GPIO引腳,在驅(qū)動代碼中如何使用?

也就是GPIO子系統(tǒng)的接口函數(shù)是什么?

GPIO子系統(tǒng)有兩套接口:基于描述符的(descriptor-based)、老的(legacy)。前者的函數(shù)都有前綴“gpiod_”,它使用gpio_desc結(jié)構(gòu)體來表示一個引腳;后者的函數(shù)都有前綴“gpio_”,它使用一個整數(shù)來表示一個引腳。


要操作一個引腳,首先要get引腳,然后設(shè)置方向,讀值、寫值。


驅(qū)動程序中要包含頭文件,

#include <linux/gpio/consumer.h>?? // descriptor-based

#include <linux/gpio.h>??????????? // legacy


下表列出常用的函數(shù):


有前綴“devm_”的含義是“設(shè)備資源管理”(Managed Device Resource),這是一種自動釋放資源的機(jī)制。它的思想是“資源是屬于設(shè)備的,設(shè)備不存在時資源就可以自動釋放”。

比如在Linux開發(fā)過程中,先申請了GPIO,再申請內(nèi)存;如果內(nèi)存申請失敗,那么在返回之前就需要先釋放GPIO資源。如果使用devm的相關(guān)函數(shù),在內(nèi)存申請失敗時可以直接返回:設(shè)備的銷毀函數(shù)會自動地釋放已經(jīng)申請了的GPIO資源。

建議使用“devm_”版本的相關(guān)函數(shù)。

舉例,假設(shè)備在設(shè)備樹中有如下節(jié)點(diǎn):

foo_device {

????????????? compatible = "acme,foo";

????????????? ...

????????????? led-gpios = <&gpio 15 GPIO_ACTIVE_HIGH>, /* red */

???????????????????? ??? <&gpio 16 GPIO_ACTIVE_HIGH>, /* green */

???????????????????? ??? <&gpio 17 GPIO_ACTIVE_HIGH>; /* blue */

?

????????????? power-gpios = <&gpio 1 GPIO_ACTIVE_LOW>;

?????? };

那么可以使用下面的函數(shù)獲得引腳:

struct gpio_desc *red, *green, *blue, *power;

?

red = gpiod_get_index(dev, "led", 0, GPIOD_OUT_HIGH);

green = gpiod_get_index(dev, "led", 1, GPIOD_OUT_HIGH);

blue = gpiod_get_index(dev, "led", 2, GPIOD_OUT_HIGH);

power = gpiod_get(dev, "power", GPIOD_OUT_HIGH);


要注意的是,gpiod_set_value設(shè)置的值是“邏輯值”,不一定等于物理值。

什么意思?




舊的“gpio_”函數(shù)沒辦法根據(jù)設(shè)備樹信息獲得引腳,它需要先知道引腳號。

引腳號怎么確定?

在GPIO子系統(tǒng)中,每注冊一個GPIO Controller時會確定它的“base number”,那么這個控制器里的第n號引腳的號碼就是:base number + n。

但是如果硬件有變化、設(shè)備樹有變化,這個base number并不能保證是固定的,應(yīng)該查看sysfs來確定base number。

2.4 sysfs中的訪問方法

在sysfs中訪問GPIO,實(shí)際上用的就是引腳號,老的方法。

a. 先確定某個GPIO Controller的基準(zhǔn)引腳號(base number),再計(jì)算出某個引腳的號碼。

方法如下:

① 先在開發(fā)板的/sys/class/gpio目錄下,找到各個gpiochipXXX目錄:



② 然后進(jìn)入某個gpiochip目錄,查看文件label的內(nèi)容

③ 根據(jù)label的內(nèi)容對比設(shè)備樹

label內(nèi)容來自設(shè)備樹,比如它的寄存器基地址。用來跟設(shè)備樹(dtsi文件)比較,就可以知道這對應(yīng)哪一個GPIO Controller。

下圖是在100asK_imx6ull上運(yùn)行的結(jié)果,通過對比設(shè)備樹可知gpiochip96對應(yīng)gpio4:



所以gpio4這組引腳的基準(zhǔn)引腳號就是96,這也可以“cat base”來再次確認(rèn)。


b. 基于sysfs操作引腳:

以100ask_imx6ull為例,它有一個按鍵,原理圖如下:



那么GPIO4_14的號碼是96+14=110,可以如下操作讀取按鍵值:

echo ?110 > /sys/class/gpio/export?

echo in > /sys/class/gpio/gpio110/direction?

cat /sys/class/gpio/gpio110/value?

echo ?110 > /sys/class/gpio/unexport


注意:如果驅(qū)動程序已經(jīng)使用了該引腳,那么將會export失敗,會提示下面的錯誤:



對于輸出引腳,假設(shè)引腳號為N,可以用下面的方法設(shè)置它的值為1:

echo ?N > /sys/class/gpio/export?

echo out > /sys/class/gpio/gpioN/direction?

echo 1 > /sys/class/gpio/gpioN/value?

echo ?N > /sys/class/gpio/unexport


3.基于GPIO子系統(tǒng)的LED驅(qū)動程序

3.1 編寫思路

GPIO的地位跟其他模塊,比如I2C、UART的地方是一樣的,要使用某個引腳,需要先把引腳配置為GPIO功能,這要使用Pinctrl子系統(tǒng),只需要在設(shè)備樹里指定就可以。在驅(qū)動代碼上不需要我們做任何事情。

GPIO本身需要確定引腳,這也需要在設(shè)備樹里指定。

設(shè)備樹節(jié)點(diǎn)會被內(nèi)核轉(zhuǎn)換為platform_device。

對應(yīng)的,驅(qū)動代碼中要注冊一個platform_driver,在probe函數(shù)中:獲得引腳、注冊file_operations。

在file_operations中:設(shè)置方向、讀值/寫值。



下圖就是一個設(shè)備樹的例子:



3.2 在設(shè)備樹中添加Pinctrl信息

有些芯片提供了設(shè)備樹生成工具,在GUI界面中選擇引腳功能和配置信息,就可以自動生成Pinctrl子結(jié)點(diǎn)。把它復(fù)制到你的設(shè)備樹文件中,再在client device結(jié)點(diǎn)中引用就可以。

有些芯片只提供文檔,那就去閱讀文檔,一般在內(nèi)核源碼目錄Documentation\devicetree\bindings\pinctrl下面,保存有該廠家的文檔。

如果連文檔都沒有,那只能參考內(nèi)核源碼中的設(shè)備樹文件,在內(nèi)核源碼目錄arch/arm/boot/dts目錄下。

最后一步,網(wǎng)絡(luò)搜索。

Pinctrl子節(jié)點(diǎn)的樣式如下:



3.3 在設(shè)備樹中添加GPIO信息

先查看電路原理圖確定所用引腳,再在設(shè)備樹中指定:添加”[name]-gpios”屬性,指定使用的是哪一個GPIO Controller里的哪一個引腳,還有其他Flag信息,比如GPIO_ACTIVE_LOW等。具體需要多少個cell來描述一個引腳,需要查看設(shè)備樹中這個GPIO Controller節(jié)點(diǎn)里的“#gpio-cells”屬性值,也可以查看內(nèi)核文檔。

示例如下:



3.4編程示例

在實(shí)際操作過程中也許會碰到意外的問題,現(xiàn)場演示如何解決。

a. 定義、注冊一個platform_driver

b. 在它的probe函數(shù)里:

b.1 根據(jù)platform_device的設(shè)備樹信息確定GPIO:gpiod_get

b.2 定義、注冊一個file_operations結(jié)構(gòu)體

b.3 在file_operarions中使用GPIO子系統(tǒng)的函數(shù)操作GPIO:

gpiod_direction_output、gpiod_set_value


好處:這些代碼對所有的代碼都是完全一樣的!

使用GIT命令載后,源碼leddrv.c位于這個目錄下:

01_all_series_quickstart\

04_快速入門_正式開始\

02_嵌入式Linux驅(qū)動開發(fā)基礎(chǔ)知識\source\

05_gpio_and_pinctrl\

01_led


摘錄重點(diǎn)內(nèi)容:

a. 注冊platform_driver

注意下面第122行的"100ask,leddrv",它會跟設(shè)備樹中節(jié)點(diǎn)的compatible對應(yīng):

121 static const struct of_device_id ask100_leds[] = {

122???? { .compatible = "100ask,leddrv" },

123???? { },

124 };

125

126 /* 1. 定義platform_driver */

127 static struct platform_driver chip_demo_gpio_driver = {

128???? .probe????? = chip_demo_gpio_probe,

129???? .remove???? = chip_demo_gpio_remove,

130???? .driver???? = {

131???????? .name?? = "100ask_led",

132???????? .of_match_table = ask100_leds,

133???? },

134 };

135

136 /* 2. 在入口函數(shù)注冊platform_driver */

137 static int __init led_init(void)

138 {

139???? int err;

140

141???? printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);

142

143???? err = platform_driver_register(&chip_demo_gpio_driver);

144

145???? return err;

146 }



b. 在probe函數(shù)中獲得GPIO

核心代碼是第87行,它從該設(shè)備(對應(yīng)設(shè)備樹中的設(shè)備節(jié)點(diǎn))獲取名為“l(fā)ed”的引腳。在設(shè)備樹中,必定有一屬性名為“l(fā)ed-gpios”或“l(fā)ed-gpio”。

77 /* 4. 從platform_device獲得GPIO

78? *??? 把file_operations結(jié)構(gòu)體告訴內(nèi)核:注冊驅(qū)動程序

79? */

80 static int chip_demo_gpio_probe(struct platform_device *pdev)

81 {

82????? //int err;

83

84????? printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);

85

86????? /* 4.1 設(shè)備樹中定義有: led-gpios=<...>; */

87???? led_gpio = gpiod_get(&pdev->dev, "led", 0);

88????? if (IS_ERR(led_gpio)) {

89????????????? dev_err(&pdev->dev, "Failed to get GPIO for led\n");

90????????????? return PTR_ERR(led_gpio);

91????? }

92



c. 注冊file_operations結(jié)構(gòu)體:

這是老套路了:

93????? /* 4.2 注冊file_operations????? */

94????? major = register_chrdev(0, "100ask_led", &led_drv);? /* /dev/led */

95

96????? led_class = class_create(THIS_MODULE, "100ask_led_class");

97????? if (IS_ERR(led_class)) {

98????????????? printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);

99????????????? unregister_chrdev(major, "led");

100???????????? gpiod_put(led_gpio);

101???????????? return PTR_ERR(led_class);

102???? }

103

104???? device_create(led_class, NULL, MKDEV(major, 0), NULL, "100ask_led%d", 0); /* /dev/100ask_led0 */

105



d. 在open函數(shù)中調(diào)用GPIO函數(shù)設(shè)置引腳方向:

51 static int led_drv_open (struct inode *node, struct file *file)

52 {

53????? //int minor = iminor(node);

54

55????? printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);

56????? /* 根據(jù)次設(shè)備號初始化LED */

57????? gpiod_direction_output(led_gpio, 0);

58

59????? return 0;

60 }



e. 在write函數(shù)中調(diào)用GPIO函數(shù)設(shè)置引腳值:

34 /* write(fd, &val, 1); */

35 static ssize_t led_drv_write (struct file *file, const char __user *buf, size_t size, loff_t *offset)

36 {

37????? int err;

38????? char status;

39????? //struct inode *inode = file_inode(file);

40????? //int minor = iminor(inode);

41

42????? printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);

43????? err = copy_from_user(&status, buf, 1);

44

45????? /* 根據(jù)次設(shè)備號和status控制LED */

46????? gpiod_set_value(led_gpio, status);

47

48????? return 1;

49 }

?



f. 釋放GPIO:

gpiod_put(led_gpio);


4.在100ASK_IMX6ULL上機(jī)實(shí)驗(yàn)

4.1 確定引腳并生成設(shè)備樹節(jié)點(diǎn)

NXP公司對于IMX6ULL芯片,有設(shè)備樹生成工具。我們也把它上傳到GIT去了,使用GIT命令載后,在這個目錄下:

01_all_series_quickstart\

04_快速入門_正式開始\

02_嵌入式Linux驅(qū)動開發(fā)基礎(chǔ)知識\source\

05_gpio_and_pinctrl\

tools\

imx\

安裝“Pins_Tool_for_i.MX_Processors_v6_x64.exe”后運(yùn)行,打開IMX6ULL的配置文件“MCIMX6Y2xxx08.mex”,就可以在GUI界面中選擇引腳,配置它的功能,這就可以自動生成Pinctrl的子節(jié)點(diǎn)信息。

100ASK_IMX6ULL使用的LED原理圖如下,可知引腳是GPIO5_3:



在設(shè)備樹工具中,如下圖操作:




把自動生成的設(shè)備樹信息,放到內(nèi)核源碼arch/arm/boot/dts/100ask_imx6ull-14x14.dts中,代碼如下:

a. Pinctrl信息:

&iomuxc_snvs {

……

??????? myled_for_gpio_subsys: myled_for_gpio_subsys{

??????????? fsl,pins = <

??????????????? MX6ULL_PAD_SNVS_TAMPER3__GPIO5_IO03??????? 0x000110A0

??????????? >;

??????? };

?



b. 設(shè)備節(jié)點(diǎn)信息(放在根節(jié)點(diǎn)下):

myled {

??????????? compatible = "100ask,leddrv";

??????????? pinctrl-names = "default";

??????????? pinctrl-0 = <&myled_for_gpio_subsys>;

??????????? led-gpios = <&gpio5 3 GPIO_ACTIVE_LOW>;

??????? };


4.2 編譯程序

編譯設(shè)備樹后,要更新設(shè)備樹。

編譯驅(qū)動程序時,“l(fā)eddrv_未測試的原始版本.c”是有錯誤信息的,“l(fā)eddrv.c”是修改過的。

測試方法,在板子上執(zhí)行命令:

# insmod? leddrv.ko

# ls /dev/100ask_led0

# ./ledtest /dev/100ask_led0 on

# ./ledtest /dev/100ask_led0 off

?

我是韋東山,專注研究嵌入式linux+ARM 10多年,歡迎大家訂閱我的付費(fèi)視頻:100ask.taobao.com


本文已錄成視頻,學(xué)習(xí)起來更形象直觀。學(xué)起來更容易。

pinctrl子系統(tǒng)重要概念:

https://www.bilibili.com/video/av65976587?p=69

gpio子系統(tǒng)重要概念:

https://www.bilibili.com/video/av65976587?p=70

基于GPIO子系統(tǒng)的LED驅(qū)動程序:

https://www.bilibili.com/video/av65976587?p=71

在100ASK_IMX6ULL上機(jī)實(shí)驗(yàn):

https://www.bilibili.com/video/av65976587?p=72

還沒搞懂的同學(xué)可以加我同事微信13163769879加入交流群討論學(xué)習(xí),


【深度】韋東山:GPIO和Pinctrl子系統(tǒng)的使用 (附免費(fèi)視頻)的評論 (共 條)

分享到微博請遵守國家法律
呼伦贝尔市| 五常市| 嘉兴市| 蚌埠市| 桃源县| 贡觉县| 耒阳市| 湟源县| 中方县| 潼南县| 哈巴河县| 平南县| 得荣县| 运城市| 惠水县| 丰原市| 兴和县| 托克托县| 鹿邑县| 嘉祥县| 铜鼓县| 康平县| 循化| 错那县| 衡南县| 揭东县| 科技| 米泉市| 洞口县| 无极县| 永济市| 宣恩县| 瑞丽市| 保靖县| 邵阳市| 柳河县| 柘城县| 德庆县| 佛坪县| 长垣县| 青田县|