Linux內核驅動之GPIO子系統(一)GPIO的使用

一?概述

??Linux內核中gpio是最簡單,最常用的資源(和?interrupt?,dma,timer一樣)驅動程序,應用程序都能夠通過相應的接口使用gpiogpio使用0MAX_INT之間的整數標識,不能使用負數,gpio硬件體系密切相關的,不過linux有一個框架處理gpio,能夠使用統一的接口來操作gpio.在講gpio核心(gpiolib.c)之前先來看看gpio是怎么使用的

二?內核中gpio的使用

?????1?測試gpio端口是否合法?int?gpio_is_valid(int?number);?

?????

?????2?申請某個gpio端口當然在申請之前需要顯示的配置該gpio端口的pinmux

????????int?gpio_request(unsigned?gpio,?const?char?*label)

?????

?????3?標記gpio的使用方向包括輸入還是輸出

???????/*成功返回零失敗返回負的錯誤值*/?

???????int?gpio_direction_input(unsigned?gpio);?

???????int?gpio_direction_output(unsigned?gpio,?int?value);?

?????

?????4?獲得gpio引腳的值和設置gpio引腳的值(對于輸出)

????????int?gpio_get_value(unsigned?gpio);

????????void?gpio_set_value(unsigned?gpio,?int?value);?

?????

?????5?gpio當作中斷口使用

??????? int?gpio_to_irq(unsigned?gpio);?

?????? ?返回的值即中斷編號可以傳給request_irq()free_irq()

??????? 內核通過調用該函數將gpio端口轉換為中斷,在用戶空間也有類似方法

??

?????6?導出gpio端口到用戶空間

?????? ?int?gpio_export(unsigned?gpio,?bool?direction_may_change);?

??????? 內核可以對已經被gpio_request()申請的gpio端口的導出進行明確的管理,

??????? 參數direction_may_change表示用戶程序是否允許修改gpio的方向,假如可以

??????? 則參數direction_may_change為真

????????/*?撤銷GPIO的導出?*/?

??????? void?gpio_unexport();?

?

三?用戶空間gpio的調用?

??????????用戶空間訪問gpio,即通過sysfs接口訪問gpio,下面是/sys/class/gpio目錄下的三種文件:?

????????????--export/unexport文件

????????????--gpioN指代具體的gpio引腳

????????????--gpio_chipN指代gpio控制器

????????????必須知道以上接口沒有標準device文件和它們的鏈接。?

?(1)?export/unexport文件接口:

??????????? ???/sys/class/gpio/export,該接口只能寫不能讀

???????????????用戶程序通過寫入gpio的編號來向內核申請將某個gpio的控制權導出到用戶空間當然前提是沒有內核代碼申請這個gpio端口

???????????????比如??echo?19?>?export?

?????????????? 上述操作會為19gpio創建一個節點gpio19,此時/sys/class/gpio目錄下邊生成一個gpio19的目錄

???????????????/sys/class/gpio/unexport和導出的效果相反。?

???????????????比如?echo?19?>?unexport

?????????????? 上述操作將會移除gpio19這個節點。?

?(2) /sys/class/gpio/gpioN

???????指代某個具體的gpio端口,里邊有如下屬性文件

??????direction?表示gpio端口的方向,讀取結果是inout。該文件也可以寫,寫入out?時該gpio設為輸出同時電平默認為低。寫入lowhigh則不僅可以

????????????????????? 設置為輸出?還可以設置輸出的電平。?當然如果內核不支持或者內核代碼不愿意,將不會存在這個屬性,比如內核調用了gpio_export(N,0)就

?????????????????????? 表示內核不愿意修改gpio端口方向屬性?

??????

??????value??????表示gpio引腳的電平,0(低電平)1(高電平),如果gpio被配置為輸出,這個值是可寫的,記住任何非零的值都將輸出高電平,?如果某個引腳

????????????????????? 能并且已經被配置為中斷,則可以調用poll(2)函數監聽該中斷,中斷觸發后poll(2)函數就會返回。

???????????????????????????????????

??????edge??????表示中斷的觸發方式,edge文件有如下四個值"none",?"rising",?"falling","both"

?????????? none表示引腳為輸入,不是中斷引腳

?????????? rising表示引腳為中斷輸入,上升沿觸發

?????????? falling表示引腳為中斷輸入,下降沿觸發

?????????? both表示引腳為中斷輸入,邊沿觸發

????????????????????? 這個文件節點只有在引腳被配置為輸入引腳的時候才存在。?當值是none時可以通過如下方法將變為中斷引腳

????????????????????? echo "both" > edge;對于是both,falling還是rising依賴具體硬件的中斷的觸發方式。此方法即用戶態gpio轉換為中斷引腳的方式

????????????????

??????active_low?

gpioN目錄下有active_low節點,表示當前GPIO的有限電平,默認為0,其意義為,當輸入/輸出value為0時,GPIO為低電平,當輸入/輸出value為1時,GPIO為高電平。同樣的,當active_low為1時,當輸入/輸出value為0時,GPIO為高電平,當輸入/輸出value為1時,GPIO為低電平。 也就是說,GPIO的真實電平=value^active_low。

$ echo 0 > active_low       #value是0,表示低電平。value是1,表示高電平
$ echo 1 > active_low       #value是1,表示低電平。value是0,表示高電平? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

?(3)/sys/class/gpio/gpiochipN

??????gpiochipN表示的就是一個gpio_chip,用來管理和控制一組gpio端口的控制器,該目錄下存在一下屬性文件:?

??????

??????base???N相同,表示控制器管理的最小的端口編號。?

??????lable???診斷使用的標志(并不總是唯一的)?

??????ngpio??表示控制器管理的gpio端口數量(端口范圍是:N?~?N+ngpio-1)?

四?用戶態使用gpio監聽中斷??????

首先需要將該gpio配置為中斷

echo??"rising"?>?/sys/class/gpio/gpio12/edge???????

以下是偽代碼

int?gpio_id;

struct?pollfd?fds[1];

gpio_fd?=?open("/sys/class/gpio/gpio12/value",O_RDONLY);

if(?gpio_fd?==?-1?)

???err_print("gpio?open");

fds[0].fd?=?gpio_fd;

fds[0].events??=?POLLPRI;

ret?=?read(gpio_fd,buff,10);

if(?ret?==?-1?)

????err_print("read");

while(1){

?????ret?=?poll(fds,1,-1);

?????if(?ret?==?-1?)

?????????err_print("poll");

???????if(?fds[0].revents?&?POLLPRI){

???????????ret?=?lseek(gpio_fd,0,SEEK_SET);

???????????if(?ret?==?-1?)

???????????????err_print("lseek");

???????????ret?=?read(gpio_fd,buff,10);

???????????if(?ret?==?-1?)

???????????????err_print("read");

????????????/*此時表示已經監聽到中斷觸發了,該干事了*/

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

??? }

}

記住使用poll()函數,設置事件監聽類型為POLLPRI和POLLERR在poll()返回后,使用lseek()移動到文件開頭讀取新的值或者關閉它再重新打開讀取新值。必須這樣做否則poll函數會總是返回。

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/383440.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/383440.shtml
英文地址,請注明出處:http://en.pswp.cn/news/383440.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

gpio_direction_output 與 gpio_set_value

gpio_set_value(port_num,0/1) 一般只是在這個GPIO口的寄存器上寫上某個值,至于這個端口是否設置為輸出,它就管不了! 而gpio_direction_output (port_num,0/1),在某個GPIO口寫上某個值之后&…

內核ko模塊strip使用

編譯一個內核時,習慣性的在install目標下加了命令: $(STRIP) --strip-all --remove-section.note --remove-section.comment test.ko 結果在insmod test.ko時出現錯誤: test: module has no symbols (stripped?) .................. 上…

ubuntu下修復U盤只讀問題

1.通過mount指令查看u盤掛載的實際設備 /dev/sdb1 on /media/xuxuequan/0BEB-331A type vfat (rw,nosuid,nodev,uid1000,gid1000,shortnamemixed,dmask0077,utf81,showexec,flush,uhelperudisks2) 2.umount掛載點 umount /media/xuxuequan/0BEB-331A 3.fsck修復u盤設備 s…

mkfs.jffs2參數詳解

實例:mkfs.jffs2 -r rootfs -o rootfs.jffs2 -e 0x4000 --pad0x1000000 -s 0x200 -n mkfs.jffs2: Usage: mkfs.jffs2 [OPTIONS] Make a JFFS2 file system image from an existing directory tree Options: -p, --pad[SIZE] 用16進制來表示所要輸出檔案的大小&…

關于c語言字符串函數和一些內存函數的的簡介

關于c語言字符串函數和一些內存函數的的簡介 求字符串長度的函數 strlen函數介紹![在這里插入圖片描述](https://img-blog.csdnimg.cn/20190301142458376.jpg)注模擬實現 . [1 ]計數器方式 因為strlen 是求字符串長度的函數,所以不能改變字符串本身,所…

君正T20平臺生成jffs2格式rootfs

基于系統升級的考慮,這兩天在君正T20平臺上折騰如何生成jffs2 格式的rootfs。詳細的過程如下: 1.修改uboot中的分區參數: 修改為rootfs格式為jffs2的,且適當擴大rootfs分區大小。(因jffs2的壓縮比不如只讀的squashfs…

用結構體寫一個簡單的通訊錄

一個簡單的通訊錄 通訊錄應該具備簡單的一些功能 1 增添聯系人 2 刪除聯系人 3 查找聯系人 4 修改聯系人 5 按名字給聯系人排序 6 查看通訊錄 除此之外,應該在實現上還應該具備一些其他的功能函數 比如 初始化通訊錄 這些都是功能函數,而整個函數入口應…

jffs2 啟動的常見的問題

Q:在啟動過程中出現at91sam user.warn kernel: Empty flash at 0x00f0fffc ends at 0x00f10000問題 A:在mkfs.jffs2的時候,加上-e 0x20000指定擦除塊的大小。-e是指定擦除塊的大小,我們使用的nandflash的塊大小為128K字節&#xf…

c動態內存管理

動態內存管理 我們之前要開辟內存用的方法都是定義變量,比如 但是上述開辟內存的方法有兩個特點 1空間開辟大小是固定的 2數組在申明的時候,必須指定數組的長度,它所需要的內存在編譯時分配 malloc和free c中提供一個動態內存開辟函數 這…

JFFS2文件系統掛載過程優化的分析報告

一 問題描述 在上電啟動優化中發現Linux系統下掛載JFFS2文件系統耗時較長,以128M的NOR FLASH為例,用時接近20秒。后續單板的FLASH容量為256M,時間會更長。如此長的掛載時間,會大增加系統的上電啟動時間。希望能對mount功能或JFFS…

右移函數(字符串,數組)

右移函數 以上是數組右移,將int換成char 把數組內容改成字符串就行。

關于jffs2文件系統如何掉電保護

JFFS2 是將節點信息保存在內存中 Flash上日志型文件系統的資料,了解到傳統的基于閃存轉換層(FLT)的文件系統存在的主要問題: 1. 效率低。因為每次都要把要修改的數據所在擦寫塊放入內存,產生了許多不必要的讀操作&…

c中指針簡介

c中指針簡介 首先我們來看一下指針的一些基本概念 ![在這里插入圖片描述](https://img 而對于指針的應用,平常有一些形式,總結了一下大概有這幾種用法 對于以上的幾種用法,我依次給出詳盡的解釋 //這是一個普通的整型變量 1 //首先從P 處開…

判斷一個字符串是否另一個字符串的右移后的

首先我們把需要判斷的字符串傳進來,開辟一塊大小為兩個字符串的長度總和加1的動態的空間,然后后字符串拷貝函數將一個字符串拷貝到開辟空降中,再將這個字符串再次連接到這塊動態的空間中,等于就是將一個字符串拷貝了兩遍。然后比較…

登陸后保持環境變量導出

在嵌入式開發中,要保證在系統登錄后,導出的環境變量依然有效,需要修改如下文件: /etc/profile export PATH/bin:/sbin:/usr/bin:/usr/sbin export PATH/system/bin:$PATH export LD_LIBRARY_PATH/system/lib export LD_LIBRARY_P…

fasync驅動異步通知機制

fasync簡介 編輯異步通知fasync應用于系統調用signal和sigaction函數,簡單的說,signal函數就是讓一個信號與與一個函數對應,每當接收到這個信號就會調用相應的函數。[1]那么什么是異步通知?異步通知類似于中斷的機制,當…

Linux中最常見命令總結

Linux中最常見命令總結 基礎命令 命令使用格式 命令名【選項參數】 【操作對象】Ls -a workspace目錄命令 Ls 默認顯示瀏覽當前文件目錄 -a 顯示所有文件,不忽略以點開頭的文件 Linux下以.開頭的文件是隱藏文件 每個目錄下文件的兩個特殊目錄 . 表示目錄自身…

不帶頭結點的鏈表基礎操作(初始化,增刪改查)

鏈表是什么? **鏈表是一種物理存儲單元上非連續、非順序的存儲結構,數據元素的邏輯順序是通過鏈表中的指針鏈接次序實現的。鏈表由一系列結點(鏈表中每一個元素稱為結點)組成,結點可以在運行時動態生成。每個結點包括…

fcntl的使用

功能描述&#xff1a;根據文件描述詞來操作文件的特性。 #include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd); int fcntl(int fd, int cmd, long arg); int fcntl(int fd, int cmd, struct flock *lock); [描述] fcntl()針對(文件)描述符提供控…

鏈表面試題1:反轉單鏈表,不帶頭結點。

三個指針p1,p2,p3&#xff0c;p1指向頭結點的前一個結點&#xff0c;也就時指空&#xff0c;p2指向頭結點&#xff0c;p3指向頭結點下一個結點。 p3指向p2的下一個&#xff0c;讓p2指針域指向p1&#xff0c;讓p1挪到p2上&#xff0c;再讓p2指向p3.