日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 人文社科 > 生活经验 >内容正文

生活经验

嵌入式Linux设备驱动程序:用户空间中的设备驱动程序

發(fā)布時(shí)間:2023/11/28 生活经验 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 嵌入式Linux设备驱动程序:用户空间中的设备驱动程序 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

嵌入式Linux設(shè)備驅(qū)動(dòng)程序:用戶空間中的設(shè)備驅(qū)動(dòng)程序

Embedded Linux
device drivers: Device drivers in user space

Interfacing with Device Drivers

Device drivers in user space

用戶空間中的設(shè)備驅(qū)動(dòng)程序

在開(kāi)始編寫設(shè)備驅(qū)動(dòng)程序之前,請(qǐng)暫停片刻,考慮是否確實(shí)有必要。對(duì)于許多常見(jiàn)類型的設(shè)備,有通用的設(shè)備驅(qū)動(dòng)程序,允許您直接從用戶空間與硬件交互,而不必編寫一行內(nèi)核代碼。用戶空間代碼當(dāng)然更容易編寫和調(diào)試。它也不包括在GPL中,盡管我覺(jué)得這本身并不是一個(gè)很好的理由來(lái)這樣做。

這些驅(qū)動(dòng)程序分為兩大類:通過(guò)sysfs中的文件(包括GPIO和led)進(jìn)行控制的驅(qū)動(dòng)程序,以及通過(guò)設(shè)備節(jié)點(diǎn)(如I2C)公開(kāi)通用接口的串行總線。

GPIO

通用輸入/輸出(GPIO)是最簡(jiǎn)單的數(shù)字接口形式,因?yàn)樗梢灾苯釉L問(wèn)各個(gè)硬件引腳,每個(gè)引腳可以處于兩種狀態(tài)之一:高或低。在大多數(shù)情況下,您可以將GPIO管腳配置為輸入或輸出。你甚至可以使用一組GPIO管腳,通過(guò)操作軟件中的每個(gè)位來(lái)創(chuàng)建更高級(jí)的接口,比如I2C或SPI,這種技術(shù)被稱為位碰撞。主要的限制是軟件循環(huán)的速度和精度,以及您希望專用于它們的CPU周期數(shù)。一般來(lái)說(shuō),除非配置一個(gè)實(shí)時(shí)內(nèi)核,否則很難達(dá)到比毫秒更好的計(jì)時(shí)器精度。GPIO更常見(jiàn)的用例是讀取按鈕和數(shù)字傳感器以及控制led、電機(jī)和繼電器。

大多數(shù)soc有很多GPIO位,這些位被組合在GPIO寄存器中,通常每個(gè)寄存器32位。片上GPIO位通過(guò)多路復(fù)用器(稱為pinmux)路由到芯片封裝上的GPIO管腳。在電源管理芯片和專用的GPIO擴(kuò)展器中,可能有額外的GPIO引腳,通過(guò)I2C或SPI總線連接。所有這些多樣性都由一個(gè)名為gpiolib的內(nèi)核子系統(tǒng)來(lái)處理,它實(shí)際上不是一個(gè)庫(kù),而是GPIO驅(qū)動(dòng)程序用來(lái)以一致的方式公開(kāi)I/O的基礎(chǔ)設(shè)施。在Documentation/gpio的內(nèi)核源代碼中有關(guān)于gpiolib實(shí)現(xiàn)的詳細(xì)信息,驅(qū)動(dòng)程序本身的代碼在drivers/gpio中。

應(yīng)用程序可以通過(guò)/sys/class/gpio目錄中的文件與gpiolib交互。下面是一個(gè)典型的嵌入式板(BeagleBone Black)的示例:

ls /sys/class/gpio

export
gpiochip0 gpiochip32 gpiochip64 gpiochip96
unexport

名為gpiochip0到gpiochip96的目錄代表四個(gè)GPIO寄存器,每個(gè)寄存器有32個(gè)GPIO位。如果您查看其中一個(gè)gpiochip目錄,您將看到以下內(nèi)容:

ls

/sys/class/gpio/gpiochip96

base
label ngpio power subsystem uevent

名為base的文件包含寄存器中第一個(gè)GPIO引腳的編號(hào),ngpio包含寄存器中的位數(shù)。在本例中,gpiochip96/base是96,gpiochip96/ngpio是32,這說(shuō)明它包含GPIO位96到127。在一個(gè)寄存器中的最后一個(gè)GPIO和下一個(gè)寄存器中的第一個(gè)GPIO之間可能存在間隙。 要從用戶空間控制GPIO位,首先必須從內(nèi)核空間導(dǎo)出它,這是通過(guò)將GPIO編號(hào)寫入/sys/class/GPIO/export來(lái)完成的。此示例顯示GPIO 53的處理過(guò)程,它連接到BeagleBone Black上的用戶LED 0:

echo 53 >

/sys/class/gpio/export

ls

/sys/class/gpio

export gpio53 gpiochip0
gpiochip32 gpiochip64 gpiochip96 unexport

現(xiàn)在,有一個(gè)新的目錄gpio53,其中包含控制pin所需的文件。

如果GPIO位已經(jīng)被內(nèi)核聲明,您將無(wú)法以這種方式導(dǎo)出它。

目錄gpio53包含以下文件:

ls

/sys/class/gpio/gpio53

active_low direction
power uevent

device
edge subsystem value

管腳從輸入開(kāi)始。若要將其更改為輸出,請(qǐng)寫入方向文件。文件值包含管腳的當(dāng)前狀態(tài),0表示低,1表示高。如果是輸出,則可以通過(guò)將0或1寫入值來(lái)更改狀態(tài)。有時(shí),在硬件中,低和高的含義是相反的(硬件工程師喜歡做這種事情),所以寫1到active_low會(huì)顛倒值的含義,這樣低電壓報(bào)告為1,高電壓報(bào)告為0。

通過(guò)將GPIO編號(hào)寫入到/sys/class/gpio/unexport,可以從用戶空間控件中刪除GPIO。

處理來(lái)自GPIO的中斷

在許多情況下,可以將GPIO輸入配置為在狀態(tài)改變時(shí)生成中斷,這允許您等待中斷,而不是在效率低下的軟件循環(huán)中輪詢。如果GPIO位可以生成中斷,則存在名為edge的文件。最初,它的值稱為none,這意味著它不會(huì)生成中斷。要啟用中斷,可以將其設(shè)置為以下值之一:

上升:上升沿中斷

下降:下降沿中斷

兩個(gè):在上升和下降邊緣都中斷

無(wú):無(wú)中斷(默認(rèn))

可以使用poll()函數(shù)和POLLPRI作為事件等待中斷。如果要等待GPIO 48上的上升沿,請(qǐng)首先啟用中斷:

echo 48 >

/sys/class/gpio/export

echo falling

/sys/class/gpio/gpio48/edge

然后,使用poll(2)等待更改,如下面的代碼示例所示,您可以在 MELP/chapter_09/gpio-int/gpio-int.c中的代碼存檔一書中看到

#include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <poll.h> int main(int argc, char *argv[]) { int f; struct pollfd poll_fds[1]; int ret; char value[4]; int n; f = open("/sys/class/gpio/gpio48/value", O_RDONLY); if (f == -1) { perror(“Can’t open gpio48”); return 1; } n = read(f, &value, sizeof(value)); if (n > 0) { printf(“Initial value=%cn”, value[0]); lseek(f, 0, SEEK_SET); } poll_fds[0].fd = f; poll_fds[0].events = POLLPRI | POLLERR; while (1) { printf(“Waitingn”); ret = poll(poll_fds, 1, -1); if (ret > 0) { n = read(f, &value, sizeof(value)); printf(“Button pressed: value=%cn”, value[0]); lseek(f, 0, SEEK_SET); } } return 0; }

發(fā)光二極管

led通常通過(guò)GPIO管腳進(jìn)行控制,但是還有另一個(gè)內(nèi)核子系統(tǒng)提供了更專門的控制。LED內(nèi)核子系統(tǒng)增加了設(shè)置亮度的功能,如果LED有這種能力,它可以處理以其他方式連接的LED,而不是簡(jiǎn)單的GPIO管腳。它可以配置為觸發(fā)事件,如阻止設(shè)備訪問(wèn)或只是一個(gè)心跳信號(hào),以顯示設(shè)備正在工作。您必須使用選項(xiàng)CONFIG_LEDS_CLASS和適合您的LED觸發(fā)器操作來(lái)配置內(nèi)核。有關(guān)文檔/led/的詳細(xì)信息,驅(qū)動(dòng)程序位于drivers/led/中。

與GPIOs一樣,led是通過(guò)sysfs中目錄為/sys/class/led的接口控制的。在BeagleBone Black的情況下,led的名稱以d的形式編碼在設(shè)備樹(shù)中設(shè)備名稱:顏色:函數(shù)devicename:colour:function,如下所示:

ls /sys/class/leds

beaglebone:green:heartbeat beaglebone:green:usr2

beaglebone:green:mmc0
beaglebone:green:usr3

現(xiàn)在,我們可以查看其中一個(gè)指示燈的屬性,注意shell要求路徑名中的冒號(hào)字符“:”前面必須有一個(gè)反斜杠轉(zhuǎn)義符“”:

cd

/sys/class/leds/beaglebone:green:usr2

ls

brightness max_brightness
subsystem uevent

device power trigger

亮度文件控制LED的亮度,可以是0(關(guān)閉)和最大亮度(完全打開(kāi))之間的數(shù)字。如果LED不支持中等亮度,任何非零值都會(huì)將其打開(kāi)。名為trigger的文件列出了觸發(fā)LED亮起的事件。觸發(fā)器列表取決于實(shí)現(xiàn)。下面是一個(gè)例子:

cat trigger

none mmc0 mmc1 timer oneshot
heartbeat backlight gpio [cpu0]

default-on

當(dāng)前選定的觸發(fā)器顯示在方括號(hào)中。您可以通過(guò)將其他觸發(fā)器之一寫入文件來(lái)更改它。如果要完全通過(guò)亮度控制LED,請(qǐng)選擇“無(wú)”。如果將觸發(fā)器設(shè)置為計(jì)時(shí)器,則會(huì)出現(xiàn)兩個(gè)額外文件,允許您以毫秒為單位設(shè)置開(kāi)關(guān)時(shí)間:

echo timer > trigger

ls

brightness delay_on max_brightness
subsystem uevent

delay_off device power trigger

cat delay_on

500

cat

/sys/class/leds/beaglebone:green:heartbeat/delay_off

500

如果LED具有片上定時(shí)器硬件,則閃爍不會(huì)中斷CPU。

I2C

I2C是一種簡(jiǎn)單的低速2線總線,在嵌入式板上很常見(jiàn),通常用于訪問(wèn)不在SoC上的外圍設(shè)備,如顯示控制器、攝像頭傳感器、GPIO擴(kuò)展器等。在PCs上有一個(gè)稱為系統(tǒng)管理總線(SMBus)的相關(guān)標(biāo)準(zhǔn),用于訪問(wèn)溫度和電壓傳感器。SMBus是I2C的一個(gè)子集。

I2C是一種主從協(xié)議,主機(jī)是SoC上的一個(gè)或多個(gè)主機(jī)控制器。從機(jī)有一個(gè)由制造商分配的7位地址(請(qǐng)閱讀數(shù)據(jù)表),每個(gè)總線最多允許128個(gè)節(jié)點(diǎn),但保留了16個(gè)節(jié)點(diǎn),因此實(shí)際上只允許112個(gè)節(jié)點(diǎn)。主機(jī)可以與其中一個(gè)從機(jī)啟動(dòng)讀或?qū)懯聞?wù)。通常,第一個(gè)字節(jié)用于指定從機(jī)上的寄存器,其余字節(jié)是從該寄存器讀取或?qū)懭氲臄?shù)據(jù)。

每個(gè)主機(jī)控制器有一個(gè)設(shè)備節(jié)點(diǎn),例如,該SoC有四個(gè):

ls -l /dev/i2c*

crw-rw—- 1 root
i2c 89, 0 Jan 1 00:18 /dev/i2c-0

crw-rw—- 1 root i2c 89, 1 Jan 1 00:18 /dev/i2c-1

crw-rw—- 1 root i2c 89, 2 Jan 1 00:18 /dev/i2c-2

crw-rw—- 1 root i2c 89, 3 Jan 1 00:18 /dev/i2c-3

設(shè)備接口提供一系列ioctl命令,用于查詢主機(jī)控制器并將讀寫命令發(fā)送到I2C從機(jī)。有一個(gè)名為i2c-tools的包,它使用這個(gè)接口提供與i2c設(shè)備交互的基本命令行工具。工具如下:

· i2cdetect : This lists the I2C adapters, and probes the bus

· i2cdump : This dumps data from all the registers of an I2C
peripheral

· i2cget : This reads data from an I2C slave

· i2cset : This writes data to an I2C slave

i2c工具包可以在Buildroot和Yocto項(xiàng)目以及大多數(shù)主流發(fā)行版中獲得。所以,只要你知道從機(jī)的地址和協(xié)議,編寫一個(gè)用戶空間程序來(lái)與設(shè)備對(duì)話是很簡(jiǎn)單的。下面的示例顯示如何從安裝在I2C總線0上BeagleBone Black上的從機(jī)地址0x50上的AT24C512B EEPROM讀取前四個(gè)字節(jié)(代碼在MELP/章節(jié)U 09/I2C示例中):

#include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <sys/ioctl.h> #include <linux/i2c-dev.h> #define I2C_ADDRESS 0x50 int main(void) { int f; int n; char buf[10]; f = open("/dev/i2c-0", O_RDWR); /* Set the address of the i2c slave device / ioctl(f, I2C_SLAVE, I2C_ADDRESS); / Set the 16-bit address to read from to 0 / buf[0] = 0; / address byte 1 / buf[1] = 0; / address byte 2 / n = write(f, buf, 2); / Now read 4 bytes from that address */ n = read(f, buf, 4); printf(“0x%x 0x%x0 0x%x 0x%xn”, buf[0], buf[1], buf[2], buf[3]); close(f); return 0; }

在Documentation/I2C/dev interface中有關(guān)于I2C的Linux實(shí)現(xiàn)的更多信息。主控制器驅(qū)動(dòng)程序位于drivers/i2c/總線中。

串行外設(shè)接口(SPI)

SPI總線類似于I2C,但速度更快,最高可達(dá)數(shù)十兆赫。在雙工線路中使用四條獨(dú)立的雙工線路進(jìn)行操作??偩€上的每個(gè)芯片都通過(guò)專用芯片選擇線進(jìn)行選擇。它通常用于連接觸摸屏傳感器、顯示控制器和串行或閃存設(shè)備。

與I2C一樣,它是主從協(xié)議,大多數(shù)SOC實(shí)現(xiàn)一個(gè)或多個(gè)主主機(jī)控制器。有一個(gè)通用的SPI設(shè)備驅(qū)動(dòng)程序,您可以通過(guò)內(nèi)核配置CONFIG_SPI峎SPIDEV來(lái)啟用它。它為每個(gè)SPI控制器創(chuàng)建一個(gè)設(shè)備節(jié)點(diǎn),允許您從用戶空間訪問(wèn)SPI芯片。設(shè)備節(jié)點(diǎn)被命名為spidev[bus].[chip select]:

ls -l /dev/spi*

crw-rw—- 1 root root 153, 0 Jan 1 00:29 /dev/spidev1.0

有關(guān)使用spidev接口的示例,請(qǐng)參閱Documentation/spi中的示例代碼。

總結(jié)

以上是生活随笔為你收集整理的嵌入式Linux设备驱动程序:用户空间中的设备驱动程序的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日韩精品久久久久久久电影99爱 | 又色又爽又黄无遮挡的免费视频 | 草草在线观看视频 | 嫩模被强到高潮呻吟不断 | 伊人天天操 | 欧美成人一区二区三区四区 | 色哟哟视频在线 | 亚洲高清视频网站 | 日韩亚洲欧美一区二区三区 | 国产成人精品一二三区 | 国产成人亚洲综合a∨婷婷 台湾a级片 | 五月天国产精品 | se欧美 | 狐狸视频污 | 日本涩涩视频 | 色综合av综合无码综合网站 | 深夜福利一区二区三区 | 国产精品丝袜一区二区 | 精品人妻互换一区二区三区 | 操极品美女 | 精品国产91久久久久久久妲己 | 午夜精品福利一区二区蜜股av | 综合五月天 | 西西4444www大胆无视频 | 二区视频在线观看 | 18国产免费视频 | 一区二区不卡免费视频 | 五月婷婷天堂 | 成色网| 99精品影视| 强制憋尿play黄文尿奴 | 一乃葵在线 | 超碰激情 | www黄色在线观看 | 国产美女视频91 | 毛片网站在线看 | 欧美激情精品久久久久 | 色5566| 久久理论视频 | 午夜在线国产 | www..com色| 久久久久久伊人 | 涩涩一区| 91色蝌蚪| 久久久77 | 国产毛片一区二区三区va在线 | 国产一区二区在线观看免费 | 亚洲av无码国产精品久久久久 | 色一情一区二区三区四区 | 久久久久久久久影院 | 亚欧在线视频 | 一区黄色| 色哟哟中文字幕 | 男人的天堂国产 | 九色精品视频 | 自拍露脸高潮 | 免费在线观看高清影视网站 | 无套白嫩进入乌克兰美女 | 在线观看av片 | 国产伦精品一区二区三区视频黑人 | 美女野外找人搭讪啪啪 | 国产伦精品免费视频 | 欧美有码在线 | 亚洲男人网 | 欧美激情精品 | a在线免费观看 | 亚洲综合精品一区 | 艳妇臀荡乳欲伦交换电影 | 日本高清视频一区二区 | 欧美一级日韩 | av免费久久 | 欧美三级小视频 | 色播五月婷婷 | 香蕉视频传媒 | 久草中文在线 | 99热中文| 波多野结衣在线免费观看视频 | 日日影院 | 亚洲男人的天堂网 | 啪啪在线观看 | 黄色一级网| 亚洲不卡av一区二区 | 麻豆精品一区二区三区 | 免费看a网站| 亚洲在线观看一区二区 | 国产国拍精品亚洲 | 人人妻人人澡人人爽久久av | 麻豆做爰免费观看 | 亚洲av日韩av永久无码下载 | 无码内射中文字幕岛国片 | 一级做a爱片久久 | 欧美3p视频| 99久久网站| 亚洲精品久久久久久久久久吃药 | 亚洲精品一区二区三区不卡 | 香蕉久久久久久久av网站 | 日韩在线视频一区二区三区 | 国内自拍小视频 | 免费黄网在线看 |