嵌入式學(xué)習(xí)(四)——嵌入式Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)(一)

姓名:李萌怡? 學(xué)號(hào):19020100103? 學(xué)院:電子工程學(xué)院

轉(zhuǎn)自:https://blog.csdn.net/light_in_dark/article/details/73321105

【嵌牛導(dǎo)讀】:對(duì)于嵌入式系統(tǒng)的學(xué)習(xí)來(lái)說(shuō)捉兴,學(xué)習(xí)嵌入式Linux驅(qū)動(dòng)開(kāi)發(fā)是十分重要的環(huán)節(jié)拆檬。本文對(duì)嵌入式linux設(shè)備系統(tǒng)開(kāi)發(fā)作以簡(jiǎn)要總結(jié)袜爪。

【嵌牛鼻子】:寄存器? 結(jié)構(gòu)體

【嵌牛提問(wèn)】:字符設(shè)備驅(qū)動(dòng)開(kāi)發(fā)流程有哪些映琳?

【嵌牛正文】

一、Linux設(shè)備的分類(lèi)

字符設(shè)備、塊設(shè)備寥假、網(wǎng)絡(luò)設(shè)備,三種設(shè)備之間的區(qū)別是數(shù)據(jù)的交互模式霞扬,分別為:

字節(jié)流糕韧、數(shù)據(jù)塊、數(shù)據(jù)包喻圃。

二萤彩、VFS核心結(jié)構(gòu)體

VFS核心結(jié)構(gòu)體定義在”linux/fs.h”頭文件中。

1斧拍、struct inode結(jié)構(gòu)體

記錄文件的屬主乒疏、訪(fǎng)問(wèn)時(shí)間等信息。當(dāng)?shù)谝淮未蜷_(kāi)文件的時(shí)候由VFS創(chuàng)建并初始化饮焦。當(dāng)文件的所有引用都退出后,釋放inode; 如果用戶(hù)態(tài)有多個(gè)人同時(shí)打開(kāi)一個(gè)文件窍侧,則VFS只需要分配一個(gè)inode县踢。

2、struct file結(jié)構(gòu)體

對(duì)應(yīng)用戶(hù)態(tài)的open操作伟件。如果多次打開(kāi)同一個(gè)文件硼啤,內(nèi)核會(huì)生成多個(gè)file。file中記錄文件的打開(kāi)方式斧账,文件內(nèi)部指針等谴返。當(dāng)文件徹底關(guān)閉時(shí),釋放file咧织。

3嗓袱、struct file_operations結(jié)構(gòu)體

該結(jié)構(gòu)體包含若干函數(shù)指針,這些函數(shù)由驅(qū)動(dòng)來(lái)實(shí)現(xiàn)习绢,并集中到file_operations中渠抹,注冊(cè)到VFS。

驅(qū)動(dòng)一般要實(shí)現(xiàn)的函數(shù)有:

open

release

read

write

unlocked_ioctl

驅(qū)動(dòng)可能會(huì)實(shí)現(xiàn)的有:

poll

mmap

fasync

flush

llseek

三闪萄、字符設(shè)備驅(qū)動(dòng)開(kāi)發(fā)流程

(1)確定硬件信息

要確定硬件的數(shù)量梧却,物理地址,中斷號(hào)等信息败去;

(2)為要支持的設(shè)備準(zhǔn)備一個(gè)私有結(jié)構(gòu)體

內(nèi)核并不要求必須有私有結(jié)構(gòu)體放航,但如果驅(qū)動(dòng)支持多個(gè)設(shè)備,最好設(shè)計(jì)一個(gè)圆裕。私有結(jié)構(gòu)體完全由驅(qū)動(dòng)人員自行設(shè)計(jì)广鳍,一般來(lái)說(shuō)荆几,會(huì)把和設(shè)備相關(guān)的信息寫(xiě)入該結(jié)構(gòu)體,比如設(shè)備的地址等搜锰。

(3)為要支持的每個(gè)設(shè)備分配對(duì)應(yīng)的設(shè)備號(hào)

設(shè)備號(hào)由char驅(qū)動(dòng)分配伴郁,要求唯一。一般來(lái)說(shuō)蛋叼,如果char驅(qū)動(dòng)可支持多個(gè)類(lèi)似的設(shè)備焊傅,則應(yīng)該為這些設(shè)備選擇一個(gè)主設(shè)備號(hào),然后為每個(gè)設(shè)備選擇一個(gè)特定的次設(shè)備號(hào)狈涮。盡量挑選和其他驅(qū)動(dòng)不一樣的主設(shè)備號(hào)狐胎。可以看/proc/devices歌馍,文件中記錄了其他驅(qū)動(dòng)選擇的主設(shè)備號(hào)握巢;也可以向內(nèi)核申請(qǐng),由內(nèi)核分配一個(gè)主設(shè)備號(hào)松却。

#define DEV_MAJOR? 50

...

dev_id = MKDEV(DEV_MAJOR, 0);

(4)準(zhǔn)備file_operations結(jié)構(gòu)體

函數(shù)集中包括open/release/read/write/unlocked_ioctl等函數(shù)暴浦,如果驅(qū)動(dòng)支持多個(gè)設(shè)備,在函數(shù)中必須能區(qū)分自己訪(fǎng)問(wèn)的是哪個(gè)設(shè)備晓锻。

static struct file_operations mem_fops = {

? ? .owner = THIS_MODULE,

? ? .open = mem_open,

? ? .release = mem_release,

? ? .read = mem_read,

? ? .write = mem_write,

? ? .unlocked_ioctl = mem_ioctl,

};

(5)注冊(cè)設(shè)備

方法一:

利用cdev結(jié)構(gòu)體歌焦,將設(shè)備號(hào)和file_operations注冊(cè)到VFS。一般來(lái)說(shuō)砚哆,將cdev結(jié)構(gòu)體包含到私有結(jié)構(gòu)體中独撇。采用cdev注冊(cè)的設(shè)備,不會(huì)自動(dòng)創(chuàng)建設(shè)備文件躁锁。

cdev_init(&mem_cdev, &mem_fops);

cdev_add(&mem_cdev, dev_id, 1);

cdev_del(&mem_cdev);? //注銷(xiāo)cdev?

方法二:

注冊(cè)miscdevice(用misc代替cdev注冊(cè)纷铣,可以自動(dòng)創(chuàng)建設(shè)備文件)

這種情況下不需要定義主設(shè)備號(hào),即省去#define DEV_MAJOR 50战转,同時(shí)需要用頭文件”linux/miscdevice.h”代替”linux/cdev.h”頭文件搜立。

static struct miscdevice mem_miscdev = {

? ? .minor? = MISC_DYNAMIC_MINOR,

? ? .name? = "mem",? ? //對(duì)應(yīng)/dev/mem設(shè)備文件

? ? .fops? = &mem_fops,

};

ret = misc_register(&mem_miscdev); //注冊(cè)miscdevice

misc_deregister(&mem_miscdev);? ? //注銷(xiāo)miscdevice

cdev和miscdevice比較:

(1)cdev可以實(shí)現(xiàn)同一個(gè)驅(qū)動(dòng)對(duì)應(yīng)多個(gè)設(shè)備,而miscdevice只能實(shí)現(xiàn)一個(gè)驅(qū)動(dòng)對(duì)應(yīng)一個(gè)設(shè)備匣吊;

(2)cdev不能實(shí)現(xiàn)設(shè)備文件的自動(dòng)創(chuàng)建儒拂,而miscdevice可以實(shí)現(xiàn)設(shè)備文件的自動(dòng)創(chuàng)建。

上述的過(guò)程比較適合較簡(jiǎn)單的設(shè)備色鸳,比如看門(mén)狗社痛,led燈,各種傳感器等命雀。較復(fù)雜設(shè)備的char驅(qū)動(dòng)蒜哀,常常要利用內(nèi)核提供的驅(qū)動(dòng)子系統(tǒng)代碼進(jìn)行設(shè)計(jì)。

四、如何在linux驅(qū)動(dòng)中訪(fǎng)問(wèn)寄存器(SFR)

1撵儿、片內(nèi)外設(shè)(pripheral)

(1)基于三總線(xiàn)訪(fǎng)問(wèn)

(2)用寄存器控制

(3)寄存器有物理地址乘客,可通過(guò)手冊(cè)查到,不可更改

2淀歇、片外外設(shè)

(1)很少通過(guò)三總線(xiàn)相連易核,一般是通過(guò)UART,CAN,I2C,USB,SPI,MIPI,I2S,AC97等總線(xiàn)相連。主芯片內(nèi)部必須提供對(duì)應(yīng)的控制器:內(nèi)部的控制器 <–> 外部的外設(shè)

(2)片外外設(shè)基本都是智能設(shè)備(不但有硬件浪默,還有軟件)

(3)有些片外外設(shè)通過(guò)寄存器控制牡直,有些則通過(guò)命令控制

(4)如果用寄存器控制,寄存器沒(méi)有物理地址纳决,只有偏移碰逸。

(5)要控制片外外設(shè),需要首先了解對(duì)應(yīng)的總線(xiàn)

3阔加、訪(fǎng)問(wèn)寄存器的流程

由于linux使能了MMU饵史,因此對(duì)于驅(qū)動(dòng)來(lái)說(shuō),不能直接使用寄存器的物理地址胜榔,必須將其映射為虛擬地址才可以使用胳喷。

(1)定義寄存器物理基地址以及寄存器的偏移

#define GPIO_BASE? 0x11000000

#define GPIO_SIZE? 0x1000? //0x8

#define GPM4CON? ? 0x2E0? //偏移地址

#define GPM4DAT? ? 0x2E4? //偏移地址

GPIO_SIZE為寄存器的范圍,可以按照使用的寄存器的總大小進(jìn)行計(jì)算夭织,比如用了兩個(gè)寄存器厌蔽,范圍是0x8;但由于地址映射的最小單位是4K摔癣,因此小于4K的值都是可以的。

(2)將寄存器物理地址映射到虛擬地址纬向,如果映射不成功择浊,則無(wú)法訪(fǎng)問(wèn)寄存器

static void __iomem *vir_base;

vir_base = ioremap(GPIO_BASE, GPIO_SIZE);

if (!vir_base) {

? ? printk("Cannot ioremap\n");

? ? return -EIO;

(3)訪(fǎng)問(wèn)寄存器,一般采用基地址加偏移的模式逾条,內(nèi)核根據(jù)寄存器的大小琢岩,提供了一系列函數(shù)

8位寄存器的訪(fǎng)問(wèn)

char value;

value = readb(vir_base + offset);

writeb(value, (vir_base + offset));

16位寄存器的訪(fǎng)問(wèn)

short value;

value = readw(vir_base + offset);

writew(value, (vir_base + offset));

32位寄存器的訪(fǎng)問(wèn)

int value;

value = readl(vir_base + offset);

writel(value, (vir_base + offset));

64位寄存器的訪(fǎng)問(wèn)

u64 value;

value = readq(vir_base + offset);

writeq(value, (vir_base + offset));

(4)取消寄存器的映射

iounmap(vir_base);

————————————————

版權(quán)聲明:本文為CSDN博主「light_in_dark」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議师脂,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明担孔。

原文鏈接:https://blog.csdn.net/light_in_dark/article/details/73321105

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市吃警,隨后出現(xiàn)的幾起案子糕篇,更是在濱河造成了極大的恐慌,老刑警劉巖酌心,帶你破解...
    沈念sama閱讀 216,997評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拌消,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡安券,警方通過(guò)查閱死者的電腦和手機(jī)墩崩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)氓英,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人鹦筹,你說(shuō)我怎么就攤上這事铝阐。” “怎么了铐拐?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,359評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵徘键,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我余舶,道長(zhǎng)啊鸭,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,309評(píng)論 1 292
  • 正文 為了忘掉前任匿值,我火速辦了婚禮赠制,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘挟憔。我一直安慰自己钟些,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,346評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布绊谭。 她就那樣靜靜地躺著政恍,像睡著了一般。 火紅的嫁衣襯著肌膚如雪达传。 梳的紋絲不亂的頭發(fā)上篙耗,一...
    開(kāi)封第一講書(shū)人閱讀 51,258評(píng)論 1 300
  • 那天,我揣著相機(jī)與錄音宪赶,去河邊找鬼宗弯。 笑死,一個(gè)胖子當(dāng)著我的面吹牛搂妻,可吹牛的內(nèi)容都是我干的蒙保。 我是一名探鬼主播,決...
    沈念sama閱讀 40,122評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼欲主,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼邓厕!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起扁瓢,我...
    開(kāi)封第一講書(shū)人閱讀 38,970評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤详恼,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后引几,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體单雾,經(jīng)...
    沈念sama閱讀 45,403評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,596評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了硅堆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片屿储。...
    茶點(diǎn)故事閱讀 39,769評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖渐逃,靈堂內(nèi)的尸體忽然破棺而出够掠,到底是詐尸還是另有隱情,我是刑警寧澤茄菊,帶...
    沈念sama閱讀 35,464評(píng)論 5 344
  • 正文 年R本政府宣布疯潭,位于F島的核電站,受9級(jí)特大地震影響面殖,放射性物質(zhì)發(fā)生泄漏竖哩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,075評(píng)論 3 327
  • 文/蒙蒙 一脊僚、第九天 我趴在偏房一處隱蔽的房頂上張望相叁。 院中可真熱鬧,春花似錦辽幌、人聲如沸增淹。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,705評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)虑润。三九已至,卻和暖如春加酵,著一層夾襖步出監(jiān)牢的瞬間拳喻,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,848評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工猪腕, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留舞蔽,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,831評(píng)論 2 370
  • 正文 我出身青樓码撰,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親个盆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子脖岛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,678評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容