本文通過(guò)對(duì)Linux下串口驅(qū)動(dòng)的分析。由最上層的C庫(kù)罪既。到操作系統(tǒng)系統(tǒng)調(diào)用層的封裝腹暖。再到tty子系統(tǒng)的核心汇在。再到一系列線路規(guī)程。再到最底層的硬件操作脏答。
對(duì)Linux中的tty子系統(tǒng)進(jìn)行簡(jiǎn)要的說(shuō)明糕殉。從理論到實(shí)踐。以便讀者能對(duì)OS原理有更深入的了解和更具體的掌握殖告。
在具體分析之前阿蝶。我們必須對(duì)串口。驅(qū)動(dòng)黄绩。和Linux操作系統(tǒng)有一定的了解羡洁。這一階段我們有三個(gè)問(wèn)題需要解決:
1.什么是Linux操作系統(tǒng)。
2.什么是Linux設(shè)備驅(qū)動(dòng)爽丹。
3.關(guān)于串口的種種筑煮。
要了解這些概念。如下我介紹了一點(diǎn)這方面的知識(shí)粤蝎。不過(guò)遺憾的是對(duì)一些概念有著不可避免的向前引用真仲。
這個(gè)過(guò)程中我會(huì)盡量忽略次要因素。以在本次調(diào)研中最主要目的為主線初澎。如果讀者您對(duì)這些概念已經(jīng)有很深入的理解秸应。可以直接閱讀后面的代碼分析:
1谤狡、什么是Linux操作系統(tǒng) 灸眼?
Linux是一套免費(fèi)使用和自由傳播的類Unix操作系統(tǒng),是一個(gè)基于POSIX和UNIX的多用戶墓懂、多任務(wù)焰宣、支持多線程和多CPU的操作系統(tǒng)。
它能運(yùn)行主要的UNIX工具軟件捕仔、應(yīng)用程序和網(wǎng)絡(luò)協(xié)議匕积。它支持32位和64位硬件盈罐。Linux繼承了Unix以網(wǎng)絡(luò)為核心的設(shè)計(jì)思想,是一個(gè)性能穩(wěn)定的多用戶網(wǎng)絡(luò)操作系統(tǒng)闪唆。
Linux操作系統(tǒng)誕生于1991 年10 月5 日(這是第一次正式向外公布時(shí)間)盅粪。Linux存在著許多不同的Linux版本悄蕾,但它們都使用了Linux內(nèi)核票顾。
Linux具備驚人的可移植性》鳎可安裝在各種計(jì)算機(jī)硬件設(shè)備中奠骄,比如手機(jī)、平板電腦番刊、路由器含鳞、視頻游戲控制臺(tái)、臺(tái)式計(jì)算機(jī)芹务、大型機(jī)和超級(jí)計(jì)算機(jī)蝉绷。
嚴(yán)格來(lái)講,Linux這個(gè)詞本身只表示Linux內(nèi)核枣抱,但實(shí)際上人們已經(jīng)習(xí)慣了用Linux來(lái)形容整個(gè)基于Linux內(nèi)核熔吗,并且使用GNU 工程各種工具和數(shù)據(jù)庫(kù)的操作系統(tǒng)。
在這幾個(gè)簡(jiǎn)要的段落中沃但。有不少新的名詞被引入了進(jìn)來(lái)磁滚。下面我對(duì)幾個(gè)重要的概念進(jìn)行描述。
A宵晚、關(guān)于類UNIX系統(tǒng)
類Unix系統(tǒng)(英文:Unix-like)指各種傳統(tǒng)的Unix系統(tǒng)(比如FreeBSD垂攘、OpenBSD、SUN公司的Solaris)以及各種與傳統(tǒng)Unix類似的系統(tǒng)(例如Minix淤刃、Linux晒他、QNX等)。
它們雖然有的是自由軟件逸贾,有的是商業(yè)軟件陨仅,但都相當(dāng)程度地繼承了原始UNIX的特性,有許多相似處铝侵,并且都在一定程度上遵守POSIX規(guī)范灼伤。
這個(gè)在一些經(jīng)典的操作系統(tǒng)教科書中已經(jīng)作了說(shuō)明。我們僅需知道咪鲜。它和我們熟知的Windows系列操作系統(tǒng)一樣狐赡。都是一種現(xiàn)代操作系統(tǒng)。對(duì)底層的計(jì)算機(jī)資源進(jìn)行抽象疟丙。對(duì)上層用戶提供調(diào)用接口颖侄。完成計(jì)算機(jī)應(yīng)該完成的功能鸟雏。
B、關(guān)于可移植性
可移植性指與軟件從某一環(huán)境轉(zhuǎn)移到另一環(huán)境下的難易程度览祖。為獲得較高的可移植性孝鹊,在設(shè)計(jì)過(guò)程中常采用通用的程序設(shè)計(jì)語(yǔ)言和運(yùn)行支撐環(huán)境。盡量不用與系統(tǒng)的底層相關(guān)性強(qiáng)的語(yǔ)言展蒂。
可移植性是軟件質(zhì)量之一又活,良好的可移植性可以提高軟件的生命周期。代碼的可移植性主題是軟件玄货;可移植性是軟件產(chǎn)品的一種能力屬性皇钞,其行為表現(xiàn)為一種程度悼泌,而表現(xiàn)出來(lái)的程度與環(huán)境密切相關(guān)松捉。
一個(gè)操作系統(tǒng)的可移植性往往表現(xiàn)在它能在運(yùn)行在不同的體系結(jié)構(gòu)上。感性的理解就是可以支持的設(shè)備有很多馆里。比如前文所說(shuō)的隘世,Linux可以運(yùn)行在大型服務(wù)器上。各種平板電腦上鸠踪。
前段時(shí)間有黑客成功的把Linux移植到一個(gè)佳能照相機(jī)上丙者。并且在這個(gè)照相機(jī)上運(yùn)行了一些主流的軟件∮埽可以說(shuō)械媒。只要有足夠可以利用的硬件資源。就可以把Linux移植到這個(gè)硬件平臺(tái)上去评汰。這個(gè)資源的最低要求往往很低纷捞。這可以與對(duì)硬件資源要求很高的Windows有一個(gè)鮮明的對(duì)比。舉個(gè)例子就是被去。當(dāng)Windows 10的升級(jí)提示從你計(jì)算機(jī)的右下角彈出時(shí)主儡。
你可以不假思索的點(diǎn)擊‘馬上升級(jí)’嗎?我想大多數(shù)人對(duì)這個(gè)問(wèn)題的答案是否定的惨缆。為什么糜值?因?yàn)榇蠖鄶?shù)情況下。升級(jí)之后就會(huì)變得更卡坯墨。延遲更大寂汇。一些無(wú)用而龐大的軟件瘋狂的占用你有限的計(jì)算機(jī)資源。而如果你選擇的是Linux捣染。你幾乎可以任意的在計(jì)算機(jī)上安裝軟件骄瓣。運(yùn)行程序(如果你的內(nèi)存不是太小。且硬盤交換分區(qū)足夠的話)液斜。
Linux核心已經(jīng)將有限的硬件資源發(fā)揮到了極致累贤。開(kāi)源軟件良好的模塊化設(shè)計(jì)在各個(gè)層次上充分利用了程序的局部性原理叠穆。(當(dāng)然這是在損失了一定易用性的前提下的。)臼膏。不好意思我扯遠(yuǎn)了硼被。這些不是本文的重點(diǎn)。渗磅。
由于筆者沒(méi)有土豪到有很多計(jì)算機(jī)嚷硫。所以選擇了一款比較便宜的ARM9開(kāi)發(fā)板作為開(kāi)發(fā)平臺(tái)。它的CPU是三星公司生產(chǎn)的S3C2440始鱼。核心是ARM920T仔掸。
C、關(guān)于Linux的基本思想
Linux的基本思想有兩點(diǎn):
第一. 一切都是文件医清。系統(tǒng)中的所有都?xì)w結(jié)為一個(gè)文件起暮,包括命令、硬件和軟件設(shè)備会烙、操作系統(tǒng)负懦、進(jìn)程等等對(duì)于操作系統(tǒng)內(nèi)核而言,都被視為擁有各自特性或類型的文件柏腻。至于說(shuō)Linux是基于Unix的纸厉,很大程度上也是因?yàn)檫@兩者的基本思想十分相近
第二. 每個(gè)軟件都有確定的用途。
D五嫂、關(guān)于Linux的特點(diǎn)
完全免費(fèi)
Linux是一款免費(fèi)的操作系統(tǒng)颗品,用戶可以通過(guò)網(wǎng)絡(luò)或其他途徑免費(fèi)獲得,并可以任意修改其源代碼沃缘。這是其他的操作系統(tǒng)所做不到的躯枢。
正是由于這一點(diǎn),來(lái)自全世界的無(wú)數(shù)程序員參與了Linux的修改孩灯、編寫工作闺金,程序員可以根據(jù)自己的興趣和靈感對(duì)其進(jìn)行改變,這讓Linux吸收了無(wú)數(shù)程序員的精華峰档,不斷壯大败匹。
完全兼容POSIX1.0標(biāo)準(zhǔn)
這使得可以在Linux下通過(guò)相應(yīng)的模擬器運(yùn)行常見(jiàn)的DOS、Windows的程序讥巡。這為用戶從Windows轉(zhuǎn)到Linux奠定了基礎(chǔ)掀亩。
許多用戶在考慮使用Linux時(shí),就想到以前在Windows下常見(jiàn)的程序是否能正常運(yùn)行欢顷,這一點(diǎn)就消除了他們的疑慮槽棍。
多用戶、多任務(wù)
Linux支持多用戶,各個(gè)用戶對(duì)于自己的文件設(shè)備有自己特殊的權(quán)利炼七,保證了各用戶之間互不影響缆巧。多任務(wù)則是現(xiàn)在電腦最主要的一個(gè)特點(diǎn),Linux可以使多個(gè)程序同時(shí)并獨(dú)立地運(yùn)行豌拙。
良好的界面
Linux同時(shí)具有字符界面和圖形界面陕悬。在字符界面用戶可以通過(guò)鍵盤輸入相應(yīng)的指令來(lái)進(jìn)行操作。它同時(shí)也提供了類似Windows圖形界面的X-Window系統(tǒng)按傅,用戶可以使用鼠標(biāo)對(duì)其進(jìn)行操作捉超。在X-Window環(huán)境中就和在Windows中相似,可以說(shuō)是一個(gè)Linux版的Windows唯绍。
支持多種平臺(tái)
Linux可以運(yùn)行在多種硬件平臺(tái)上拼岳,如具有x86、680x0况芒、SPARC惜纸、Alpha等處理器的平臺(tái)。此外Linux還是一種嵌入式操作系統(tǒng)牛柒,可以運(yùn)行在掌上電腦堪簿、機(jī)頂盒或游戲機(jī)上。2001年1月份發(fā)布的Linux 2.4版內(nèi)核已經(jīng)能夠完全支持Intel 64位芯片架構(gòu)皮壁。同時(shí)Linux也支持多處理器技術(shù)。多個(gè)處理器同時(shí)工作哪审,使系統(tǒng)性能大大提高蛾魄。
文件類型
普通文件(regular file):就是一般存取的文件,由ls-al顯示出來(lái)的屬性中湿滓,第一個(gè)屬性為 [-]滴须,例如 [-rwxrwxrwx]。另外叽奥,依照文件的內(nèi)容扔水,又大致可以分為:
1、純文本文件(ASCII):這是Unix系統(tǒng)中最多的一種文件類型朝氓,之所以稱為純文本文件魔市,是因?yàn)閮?nèi)容可以直接讀到的數(shù)據(jù),例如數(shù)字赵哲、字母等等待德。設(shè)置文件幾乎都屬于這種文件類型。舉例來(lái)說(shuō)枫夺,使用命令“cat ~/.bashrc”就可以看到該文件的內(nèi)容(cat是將文件內(nèi)容讀出來(lái))将宪。
2、二進(jìn)制文件(binary):系統(tǒng)其實(shí)僅認(rèn)識(shí)且可以執(zhí)行二進(jìn)制文件(binary file)。Linux中的可執(zhí)行文件(腳本较坛,文本方式的批處理文件不算)就是這種格式的印蔗。舉例來(lái)說(shuō),命令cat就是一個(gè)二進(jìn)制文件丑勤。
3喻鳄、數(shù)據(jù)格式的文件(data):有些程序在運(yùn)行過(guò)程中,會(huì)讀取某些特定格式的文件确封,那些特定格式的文件可以稱為數(shù)據(jù)文件(data file)香缺。舉例來(lái)說(shuō),Linux在用戶登入時(shí)股耽,都會(huì)將登錄數(shù)據(jù)記錄在 /var/log/wtmp文件內(nèi)泽示,該文件是一個(gè)數(shù)據(jù)文件,它能通過(guò)last命令讀出來(lái)秉剑。但使用cat時(shí)泛豪,會(huì)讀出亂碼。因?yàn)樗菍儆谝环N特殊格式的文件侦鹏。
4诡曙、目錄文件(directory):就是目錄,第一個(gè)屬性為[d]略水,例如 [drwxrwxrwx]价卤。
連接文件(link):類似Windows下面的快捷方式。第一個(gè)屬性為 [l]渊涝,例如 [lrwxrwxrwx]慎璧。
5、設(shè)備與設(shè)備文件(device):與系統(tǒng)外設(shè)及存儲(chǔ)等相關(guān)的一些文件跨释,通常都集中在 /dev目錄胸私。通常又分為兩種:
塊設(shè)備文件:就是存儲(chǔ)數(shù)據(jù)以供系統(tǒng)存取的接口設(shè)備,簡(jiǎn)單而言就是硬盤鳖谈。例如一號(hào)硬盤的代碼是 /dev/hda1等文件岁疼。第一個(gè)屬性為 [b]。
字符設(shè)備文件:即串行端口的接口設(shè)備缆娃,例如鍵盤捷绒、鼠標(biāo)等等。第一個(gè)屬性為 [c]龄恋。
6疙驾、套接字(sockets):這類文件通常用在網(wǎng)絡(luò)數(shù)據(jù)連接」希可以啟動(dòng)一個(gè)程序來(lái)監(jiān)聽(tīng)客戶端的要求它碎,客戶端就可以通過(guò)套接字來(lái)進(jìn)行數(shù)據(jù)通信。第一個(gè)屬性為 [s],最常在 /var/run目錄中看到這種文件類型扳肛。
7傻挂、管道(FIFO,pipe):FIFO也是一種特殊的文件類型,它主要的目的是挖息,解決多個(gè)程序同時(shí)存取一個(gè)文件所造成的錯(cuò)誤金拒。FIFO是first-in-first-out(先進(jìn)先出)的縮寫。第一個(gè)屬性為 [p]
文件結(jié)構(gòu)
/:根目錄套腹,所有的目錄绪抛、文件、設(shè)備都在/之下电禀,/就是Linux文件系統(tǒng)的組織者幢码,也是最上級(jí)的領(lǐng)導(dǎo)者。
/bin:bin 就是二進(jìn)制(binary)英文縮寫尖飞。在一般的系統(tǒng)當(dāng)中症副,都可以在這個(gè)目錄下找到linux常用的命令。系統(tǒng)所需要的那些命令位于此目錄政基。
/boot:Linux的內(nèi)核及引導(dǎo)系統(tǒng)程序所需要的文件目錄贞铣,比如 vmlinuz initrd.img 文件都位于這個(gè)目錄中。在一般情況下沮明,GRUB或LILO系統(tǒng)引導(dǎo)管理器也位于這個(gè)目錄辕坝。
/cdrom:這個(gè)目錄在剛剛安裝系統(tǒng)的時(shí)候是空的∩豪蓿可以將光驅(qū)文件系統(tǒng)掛在這個(gè)目錄下圣勒。例如:mount /dev/cdrom /cdrom
/dev:dev 是設(shè)備(device)的英文縮寫。這個(gè)目錄對(duì)所有的用戶都十分重要摧扇。因?yàn)樵谶@個(gè)目錄中包含了所有l(wèi)inux系統(tǒng)中使用的外部設(shè)備。但是這里并不是放的外部設(shè)備的驅(qū)動(dòng)程序挚歧。這一點(diǎn)和常用的windows,dos操作系統(tǒng)不一樣扛稽。它實(shí)際上是一個(gè)訪問(wèn)這些外部設(shè)備的端口』海可以非常方便地去訪問(wèn)這些外部設(shè)備在张,和訪問(wèn)一個(gè)文件,一個(gè)目錄沒(méi)有任何區(qū)別矮慕。
/etc:etc這個(gè)目錄是linux系統(tǒng)中最重要的目錄之一帮匾。在這個(gè)目錄下存放了系統(tǒng)管理時(shí)要用到的各種配置文件和子目錄。要用到的網(wǎng)絡(luò)配置文件痴鳄,文件系統(tǒng)瘟斜,x系統(tǒng)配置文件,設(shè)備配置信息,設(shè)置用戶信息等都在這個(gè)目錄下螺句。
/home:如果建立一個(gè)用戶虽惭,用戶名是"xx",那么在/home目錄下就有一個(gè)對(duì)應(yīng)的/home/xx路徑,用來(lái)存放用戶的主目錄蛇尚。
/lib:lib是庫(kù)(library)英文縮寫芽唇。這個(gè)目錄是用來(lái)存放系統(tǒng)動(dòng)態(tài)連接共享庫(kù)的。幾乎所有的應(yīng)用程序都會(huì)用到這個(gè)目錄下的共享庫(kù)取劫。因此匆笤,千萬(wàn)不要輕易對(duì)這個(gè)目錄進(jìn)行什么操作,一旦發(fā)生問(wèn)題谱邪,系統(tǒng)就不能工作了炮捧。
/lost+found:在ext2或ext3文件系統(tǒng)中,當(dāng)系統(tǒng)意外崩潰或機(jī)器意外關(guān)機(jī)虾标,而產(chǎn)生一些文件碎片放在這里寓盗。當(dāng)系統(tǒng)啟動(dòng)的過(guò)程中fsck工具會(huì)檢查這里,并修復(fù)已經(jīng)損壞的文件系統(tǒng)璧函。有時(shí)系統(tǒng)發(fā)生問(wèn)題傀蚌,有很多的文件被移到這個(gè)目錄中,可能會(huì)用手工的方式來(lái)修復(fù)蘸吓,或移到文件到原來(lái)的位置上善炫。
/mnt:這個(gè)目錄一般是用于存放掛載儲(chǔ)存設(shè)備的掛載目錄的,比如有cdrom等目錄库继÷嵋眨可以參看/etc/fstab的定義。
/media:有些linux的發(fā)行版使用這個(gè)目錄來(lái)掛載那些usb接口的移動(dòng)硬盤(包括U盤)宪萄、CD/DVD驅(qū)動(dòng)器等等艺谆。
/opt:這里主要存放那些可選的程序。
/proc:可以在這個(gè)目錄下獲取系統(tǒng)信息拜英。這些信息是在內(nèi)存中静汤,由系統(tǒng)自己產(chǎn)生的。
/root:Linux超級(jí)權(quán)限用戶root的家目錄居凶。
/sbin:這個(gè)目錄是用來(lái)存放系統(tǒng)管理員的系統(tǒng)管理程序虫给。大多是涉及系統(tǒng)管理的命令的存放,是超級(jí)權(quán)限用戶root的可執(zhí)行命令存放地侠碧,普通用戶無(wú)權(quán)限執(zhí)行這個(gè)目錄下的命令抹估,這個(gè)目錄和/usr/sbin; /usr/X11R6/sbin或/usr/local/sbin目錄是相似的,凡是目錄sbin中包含的都是root權(quán)限才能執(zhí)行的弄兜。
/selinux :對(duì)SElinux的一些配置文件目錄药蜻,SElinux可以讓linux更加安全瓷式。
/srv 服務(wù)啟動(dòng)后,所需訪問(wèn)的數(shù)據(jù)目錄谷暮,舉個(gè)例子來(lái)說(shuō)蒿往,www服務(wù)啟動(dòng)讀取的網(wǎng)頁(yè)數(shù)據(jù)就可以放在/srv/www中
/tmp:臨時(shí)文件目錄,用來(lái)存放不同程序執(zhí)行時(shí)產(chǎn)生的臨時(shí)文件湿弦。有時(shí)用戶運(yùn)行程序的時(shí)候瓤漏,會(huì)產(chǎn)生臨時(shí)文件。/tmp就用來(lái)存放臨時(shí)文件的颊埃。/var/tmp目錄和這個(gè)目錄相似蔬充。
/usr:這是linux系統(tǒng)中占用硬盤空間最大的目錄。用戶的很多應(yīng)用程序和文件都存放在這個(gè)目錄下班利。在這個(gè)目錄下饥漫,可以找到那些不適合放在/bin或/etc目錄下的額外的工具
/usr/local:這里主要存放那些手動(dòng)安裝的軟件,即不是通過(guò)“新立得”或apt-get安裝的軟件罗标。它和/usr目錄具有相類似的目錄結(jié)構(gòu)庸队。讓軟件包管理器來(lái)管理/usr目錄,而把自定義的腳本(scripts)放到/usr/local目錄下面闯割、彻消。
/usr/share :系統(tǒng)共用的東西存放地,比如/usr/share/fonts 是字體目錄宙拉,/usr/share/doc和/usr/share/man幫助文件宾尚。
/var:這個(gè)目錄的內(nèi)容是經(jīng)常變動(dòng)的,看名字就知道谢澈,可以理解為vary的縮寫煌贴,/var下有/var/log 這是用來(lái)存放系統(tǒng)日志的目錄。/var/ www目錄是定義Apache服務(wù)器站點(diǎn)存放目錄锥忿;/var/lib 用來(lái)存放一些庫(kù)文件牛郑,比如MySQL的,以及MySQL數(shù)據(jù)庫(kù)的的存放地敬鬓。
如上井濒。相信讀者已經(jīng)對(duì)Linux操作系統(tǒng)有了一個(gè)概觀。對(duì)于一些具體命令列林。筆者決定需要用到的時(shí)候再做說(shuō)明。現(xiàn)在我們來(lái)看看第二個(gè)概念:
2酪惭、什么是Linux設(shè)備驅(qū)動(dòng)
設(shè)備驅(qū)動(dòng)最通俗的解釋就是驅(qū)使硬件設(shè)備行動(dòng)希痴。驅(qū)動(dòng)與底層硬件直接打交道,按照硬件設(shè)備的具體工作方式春感,讀寫設(shè)備的寄存器砌创,完成設(shè)備的輪詢虏缸、中斷處理、DMA通信嫩实,進(jìn)行物理內(nèi)存向虛擬內(nèi)存的映射等刽辙,最終讓通信設(shè)備能收發(fā)數(shù)據(jù),讓顯示設(shè)備能顯示文字和畫面甲献,讓存儲(chǔ)設(shè)備能記錄文件和數(shù)據(jù)宰缤。
Linux設(shè)備驅(qū)動(dòng)是對(duì)底層硬件資源的抽象。對(duì)上層的操作系統(tǒng)其他服務(wù)提供一個(gè)良好的接口晃洒。讓其他服務(wù)可以把一個(gè)特定的硬件慨灭。或是一種機(jī)制當(dāng)做一個(gè)文件使用球及。使用通用的系統(tǒng)調(diào)用進(jìn)行調(diào)用氧骤。
3、關(guān)于串口的種種
眾所周知吃引。我們現(xiàn)在的計(jì)算機(jī)上面有很多接口筹陵。如USB。網(wǎng)口镊尺。并口等朦佩。串口總線是其中的一個(gè)。串行接口簡(jiǎn)稱串口鹅心,也稱串行通信接口或串行通訊接口(通常指COM接口)吕粗,是采用串行通信方式的擴(kuò)展接口。
串行接口 (Serial Interface) 是指數(shù)據(jù)一位一位地順序傳送旭愧,其特點(diǎn)是通信線路簡(jiǎn)單颅筋,只要一對(duì)傳輸線就可以實(shí)現(xiàn)雙向通信(可以直接利用電話線作為傳輸線),從而大大降低了成本输枯,特別適用于遠(yuǎn)距離通信议泵,但傳送速度較慢。一條信息的各位數(shù)據(jù)被逐位按順序傳送的通訊方式稱為串行通訊桃熄。
串行通訊的特點(diǎn)是:數(shù)據(jù)位的傳送先口,按位順序進(jìn)行,最少只需一根傳輸線即可完成瞳收;成本低但傳送速度慢碉京。串行通訊的距離可以從幾米到幾千米;根據(jù)信息的傳送方向螟深,串行通訊可以進(jìn)一步分為單工谐宙、半雙工和全雙工三種。
串口通信的兩種最基本的方式:同步串行通信方式和異步串行通信方式界弧。
同步串行是指SPI(SerialPeripheral interface)的縮寫凡蜻,顧名思義就是串行外圍設(shè)備接口搭综。SPI總線系統(tǒng)是一種同步串行外設(shè)接口,它可以使MCU與各種外圍設(shè)備以串行方式進(jìn)行通信以交換信息划栓,TRM450是SPI接口兑巾。
異步串行是指UART(UniversalAsynchronous Receiver/Transmitter),通用異步接收/發(fā)送忠荞。UART是一個(gè)并行輸入成為串行輸出的芯片蒋歌,通常集成在主板上。UART包含TTL電平的串口和RS232電平的串口钻洒。
TTL電平是3.3V的奋姿,而RS232是負(fù)邏輯電平,它定義+5+12V為低電平素标,而-12-5V為高電平称诗,MDS2710、MDS SD4头遭、EL805等是RS232接口寓免,EL806有TTL接口。
串行接口按電氣標(biāo)準(zhǔn)及協(xié)議來(lái)分包括RS-232-C计维、RS-422袜香、RS485等。
RS-232
也稱標(biāo)準(zhǔn)串口鲫惶,最常用的一種串行通訊接口蜈首。它是在1970年由美國(guó)電子工業(yè)協(xié)會(huì)(EIA)聯(lián)合貝爾系統(tǒng)、調(diào)制解調(diào)器廠家及計(jì)算機(jī)終端生產(chǎn)廠家共同制定的用于串行通訊的標(biāo)準(zhǔn)欠母。
它的全名是“數(shù)據(jù)終端設(shè)備(DTE)和數(shù)據(jù)通訊設(shè)備(DCE)之間串行二進(jìn)制數(shù)據(jù)交換接口技術(shù)標(biāo)準(zhǔn)”欢策。傳統(tǒng)的RS-232-C接口標(biāo)準(zhǔn)有22根線,采用標(biāo)準(zhǔn)25芯D型插頭座(DB25)赏淌,后來(lái)使用簡(jiǎn)化為9芯D型插座(DB9)踩寇,現(xiàn)在應(yīng)用中25芯插頭座已很少采用。
RS-232采取不平衡傳輸方式六水,即所謂單端通訊俺孙。由于其發(fā)送電平與接收電平的差僅為2V至3V左右,所以其共模抑制能力差掷贾,再加上雙絞線上的分布電容睛榄,其傳送距離最大為約15米,最高速率為20kb/s想帅。RS-232是為點(diǎn)對(duì)點(diǎn)(即只用一對(duì)收懈费、發(fā)設(shè)備)通訊而設(shè)計(jì)的,其驅(qū)動(dòng)器負(fù)載為3~7kΩ博脑。所以RS-232適合本地設(shè)備之間的通信憎乙。
RS-422
標(biāo)準(zhǔn)全稱是“平衡電壓數(shù)字接口電路的電氣特性”,它定義了接口電路的特性叉趣。典型的RS-422是四線接口泞边。實(shí)際上還有一根信號(hào)地線,共5根線疗杉。其DB9連接器引腳定義阵谚。由于接收器采用高輸入阻抗和發(fā)送驅(qū)動(dòng)器比RS232更強(qiáng)的驅(qū)動(dòng)能力,故允許在相同傳輸線上連接多個(gè)接收節(jié)點(diǎn)烟具,最多可接10個(gè)節(jié)點(diǎn)梢什。
即一個(gè)主設(shè)備(Master),其余為從設(shè)備(Slave)朝聋,從設(shè)備之間不能通信嗡午,所以RS-422支持點(diǎn)對(duì)多的雙向通信。接收器輸入阻抗為4k冀痕,故發(fā)端最大負(fù)載能力是10×4k+100Ω(終接電阻)荔睹。
RS-422四線接口由于采用單獨(dú)的發(fā)送和接收通道,因此不必控制數(shù)據(jù)方向言蛇,各裝置之間任何必須的信號(hào)交換均可以按軟件方式(XON/XOFF握手)或硬件方式(一對(duì)單獨(dú)的雙絞線)實(shí)現(xiàn)僻他。
RS-422的最大傳輸距離為1219米,最大傳輸速率為10Mb/s腊尚。其平衡雙絞線的長(zhǎng)度與傳輸速率成反比吨拗,在100kb/s速率以下,才可能達(dá)到最大傳輸距離婿斥。只有在很短的距離下才能獲得最高速率傳輸劝篷。一般100米長(zhǎng)的雙絞線上所能獲得的最大傳輸速率僅為1Mb/s。
RS-485
是從RS-422基礎(chǔ)上發(fā)展而來(lái)的受扳,所以RS-485許多電氣規(guī)定與RS-422相仿携龟。如都采用平衡傳輸方式、都需要在傳輸線上接終接電阻等勘高。RS-485可以采用二線與四線方式峡蟋,二線制可實(shí)現(xiàn)真正的多點(diǎn)雙向通信,而采用四線連接時(shí)华望,與RS-422一樣只能實(shí)現(xiàn)點(diǎn)對(duì)多的通信蕊蝗,即只能有一個(gè)主(Master)設(shè)備,其余為從設(shè)備赖舟,但它比RS-422有改進(jìn)蓬戚,無(wú)論四線還是二線連接方式總線上可多接到32個(gè)設(shè)備。
RS-485與RS-422的不同還在于其共模輸出電壓是不同的宾抓,RS-485是-7V至+12V之間子漩,而RS-422在-7V至+7V之間豫喧,RS-485接收器最小輸入阻抗為12kΩ、RS-422是4kΩ幢泼;由于RS-485滿足所有RS-422的規(guī)范紧显,所以RS-485的驅(qū)動(dòng)器可以在RS-422網(wǎng)絡(luò)中應(yīng)用。
RS-485與RS-422一樣缕棵,其最大傳輸距離約為1219米孵班,最大傳輸速率為10Mb/s。平衡雙絞線的長(zhǎng)度與傳輸速率成反比招驴,在100kb/s速率以下篙程,才可能使用規(guī)定最長(zhǎng)的電纜長(zhǎng)度。只有在很短的距離下才能獲得最高速率傳輸别厘。一般100米長(zhǎng)雙絞線最大傳輸速率僅為1Mb/s虱饿。
筆者采用的RS-232串口通信協(xié)議。下面對(duì)其通信接線方法做簡(jiǎn)要說(shuō)明丹允。目前較為常用的串口有9針串口(DB9)和25針串口(DB25)郭厌,通信距離較近時(shí)(<12m),可以用電纜線直接連接標(biāo)準(zhǔn)RS232端口(RS422,RS485較遠(yuǎn))雕蔽,若距離較遠(yuǎn)折柠,需附加調(diào)制解調(diào)器(MODEM)或其他相關(guān)設(shè)備。最為簡(jiǎn)單且常用的是三線制接法批狐,即地扇售、接收數(shù)據(jù)和發(fā)送數(shù)據(jù)三腳相連,這是最為基本的接法嚣艇,且直接用RS232相連承冰。
上面是對(duì)微機(jī)標(biāo)準(zhǔn)串行口而言的,還有許多非標(biāo)準(zhǔn)設(shè)備食零,不做說(shuō)明困乒。
好了。到此為止我們已經(jīng)解決了一開(kāi)始的三個(gè)問(wèn)題贰谣。讓我們進(jìn)入實(shí)際的代碼娜搂。實(shí)際的硬件來(lái)進(jìn)行分析。
在一個(gè)硬件平臺(tái)上吱抚。硬件是可用的百宇。我們必須要燒寫適當(dāng)?shù)能涹w到平臺(tái)的RAM中。這樣CPU才能跳轉(zhuǎn)到最先的指令秘豹。然后慢慢加載各種資源携御。才能完成系統(tǒng)的自舉。
一般我們采用BootLoader進(jìn)行硬件的初始化。并引導(dǎo)至操作系統(tǒng)核心啄刹。
筆者采用的BootLoader是u-Boot-1.1.16涮坐。Uboot是一個(gè)眾所周知的開(kāi)源軟件。讀者僅需了解它起到了BootLoader的作用即可鸵膏。這里不多做解釋膊升。僅對(duì)串口的連接和程序的下載作簡(jiǎn)要說(shuō)明:
將UBOOT目錄下的u-boot.bin下載到開(kāi)發(fā)平臺(tái)上。在Windows打開(kāi)設(shè)備管理器谭企。選擇端口。從而找到正確的com口號(hào)评肆。在此之前確保開(kāi)發(fā)板的串口與筆記本的USB口連接债查。(因?yàn)楝F(xiàn)在筆記本都沒(méi)有并口了。所以只能采用USB轉(zhuǎn)串口線瓜挽。搭配開(kāi)發(fā)板上的電平轉(zhuǎn)換芯片來(lái)完成串口連接目的盹廷。)
然后我們?cè)偈褂靡粋€(gè)工具。即SecureCRT久橙。找到對(duì)應(yīng)的com號(hào)俄占。完成快速鏈接。波特率選擇115200淆衷。取消流控缸榄。
如果一切順利。在筆記本上就可以看到串口的類似下面的輸出祝拯。這就是傳說(shuō)中的串口控制臺(tái)甚带。
這個(gè)串口的指令功能是由Uboot本身完成的。并不是linux下的串口驅(qū)動(dòng)佳头。
引入此圖旨在讓讀者感性的認(rèn)識(shí)到串口控制臺(tái)的功能是什么鹰贵。
下面正式開(kāi)始對(duì)串口打開(kāi)。發(fā)送康嘉。接收函數(shù)的分析碉输。這里向前引用一個(gè)函數(shù)。就是linux內(nèi)核中幾種2440芯片通用的串口發(fā)送函數(shù)s3c24xx_serial_start_tx亭珍。函數(shù)聲明為static voids3c24xx_serial_start_tx(struct uart_port *port):函數(shù)定義在./linux/driver/tty/serial/samsung.c中敷钾。
好了。我們從這個(gè)目錄結(jié)構(gòu)開(kāi)始块蚌。說(shuō)明大概的tty子系統(tǒng)驅(qū)動(dòng)模型闰非。
首先。最前面的linux是內(nèi)核代碼的根目錄峭范。如圖所示:
至此财松。我們面臨一個(gè)問(wèn)題。linux內(nèi)核是什么。
Linux內(nèi)核是什么辆毡?
Linux是一種開(kāi)源電腦操作系統(tǒng)內(nèi)核菜秦。它是一個(gè)用C語(yǔ)言寫成,符合POSIX標(biāo)準(zhǔn)的類Unix操作系統(tǒng)舶掖。
Linux最早是由芬蘭黑客Linus Torvalds為嘗試在英特爾x86架構(gòu)上提供自由免費(fèi)的類Unix操作系統(tǒng)而開(kāi)發(fā)的球昨。該計(jì)劃開(kāi)始于1991年,在計(jì)劃的早期有一些Minix 黑客提供了協(xié)助眨攘,而今天全球無(wú)數(shù)程序員正在為該計(jì)劃無(wú)償提供幫助主慰。
Linux是一個(gè)一體化內(nèi)核(monolithickernel)系統(tǒng)■晔郏“內(nèi)核”指的是一個(gè)提供硬件抽象層共螺、磁盤及文件系統(tǒng)控制、多任務(wù)等功能的系統(tǒng)軟件情竹。一個(gè)內(nèi)核不是一套完整的操作系統(tǒng)藐不。
一套基于Linux內(nèi)核的完整操作系統(tǒng)叫作Linux操作系統(tǒng),或是GNU/Linux秦效。設(shè)備驅(qū)動(dòng)程序可以完全訪問(wèn)硬件雏蛮。Linux內(nèi)的設(shè)備驅(qū)動(dòng)程序可以方便地以模塊化(modularize)的形式設(shè)置,并在系統(tǒng)運(yùn)行期間可直接裝載或卸載阱州。
操作系統(tǒng)是一個(gè)用來(lái)和硬件打交道并為用戶程序提供一個(gè)有限服務(wù)集的低級(jí)支撐軟件挑秉。一個(gè)計(jì)算機(jī)系統(tǒng)是一個(gè)硬件和軟件的共生體,它們互相依賴贡耽,不可分割衷模。計(jì)算機(jī)的硬件,含有外圍設(shè)備蒲赂、處理器阱冶、內(nèi)存、硬盤和其他的電子設(shè)備組成計(jì)算機(jī)的發(fā)動(dòng)機(jī)滥嘴。但是沒(méi)有軟件來(lái)操作和控制它木蹬,自身是不能工作的。
完成這個(gè)控制工作的軟件就稱為操作系統(tǒng)若皱,在Linux的術(shù)語(yǔ)中被稱為“內(nèi)核”镊叁,也可以稱為“核心”。Linux內(nèi)核的主要模塊(或組件)分以下幾個(gè)部分:存儲(chǔ)管理走触、CPU和進(jìn)程管理晦譬、文件系統(tǒng)、設(shè)備管理和驅(qū)動(dòng)互广、網(wǎng)絡(luò)通信敛腌,以及系統(tǒng)的初始化(引導(dǎo))卧土、系統(tǒng)調(diào)用等。
系統(tǒng)調(diào)用接口
SCI 層提供了某些機(jī)制執(zhí)行從用戶空間到內(nèi)核的函數(shù)調(diào)用像樊。正如前面討論的一樣尤莺,這個(gè)接口依賴于體系結(jié)構(gòu),甚至在相同的處理器家族內(nèi)也是如此生棍。SCI 實(shí)際上是一個(gè)非常有用的函數(shù)調(diào)用多路復(fù)用和多路分解服務(wù)颤霎。在 ./linux/kernel 中您可以找到 SCI 的實(shí)現(xiàn)窿撬,并在 ./linux/arch 中找到依賴于體系結(jié)構(gòu)的部分扒俯。
進(jìn)程管理
進(jìn)程管理的重點(diǎn)是進(jìn)程的執(zhí)行。在內(nèi)核中刑顺,這些進(jìn)程稱為線程柔纵,代表了單獨(dú)的處理器虛擬化(線程代碼粹污、數(shù)據(jù)、堆棧和 CPU寄存器)首量。在用戶空間,通常使用進(jìn)程這個(gè)術(shù)語(yǔ)进苍,不過(guò) Linux 實(shí)現(xiàn)并沒(méi)有區(qū)分這兩個(gè)概念(進(jìn)程和線程)加缘。
內(nèi)核通過(guò) SCI 提供了一個(gè)應(yīng)用程序編程接口(API)來(lái)創(chuàng)建一個(gè)新進(jìn)程(fork、exec 或 Portable Operating System Interface [POSⅨ] 函數(shù))觉啊,停止進(jìn)程(kill拣宏、exit),并在它們之間進(jìn)行通信和同步(signal 或者 POSⅨ機(jī)制)杠人。
進(jìn)程管理還包括處理活動(dòng)進(jìn)程之間共享 CPU的需求勋乾。內(nèi)核實(shí)現(xiàn)了一種新型的調(diào)度算法,不管有多少個(gè)線程在競(jìng)爭(zhēng) CPU嗡善,這種算法都可以在固定時(shí)間內(nèi)進(jìn)行操作辑莫。這種算法就稱為 O⑴調(diào)度程序,這個(gè)名字就表示它調(diào)度多個(gè)線程所使用的時(shí)間和調(diào)度一個(gè)線程所使用的時(shí)間是相同的罩引。
O⑴調(diào)度程序也可以支持多處理器(稱為對(duì)稱多處理器或 SMP)各吨。您可以在 ./linux/kernel 中找到進(jìn)程管理的源代碼,在 ./linux/arch 中可以找到依賴于體系結(jié)構(gòu)的源代碼袁铐。
內(nèi)存管理
內(nèi)核所管理的另外一個(gè)重要資源是內(nèi)存揭蜒。為了提高效率,如果由硬管理虛擬內(nèi)存剔桨,內(nèi)存是按照所謂的內(nèi)存頁(yè)方式進(jìn)行管理的(對(duì)于大部分體系結(jié)構(gòu)來(lái)說(shuō)都是 4KB)屉更。Linux 包括了管理可用內(nèi)存的方式,以及物理和虛擬映射所使用的硬件機(jī)制洒缀。
不過(guò)內(nèi)存管理要管理的可不止 4KB緩沖區(qū)瑰谜。Linux 提供了對(duì) 4KB緩沖區(qū)的抽象,例如 slab 分配器。這種內(nèi)存管理模式使用 4KB緩沖區(qū)為基數(shù)似舵,然后從中分配結(jié)構(gòu)脚猾,并跟蹤內(nèi)存頁(yè)使用情況,比如哪些內(nèi)存頁(yè)是滿的砚哗,哪些頁(yè)面沒(méi)有完全使用龙助,哪些頁(yè)面為空。這樣就允許該模式根據(jù)系統(tǒng)需要來(lái)動(dòng)態(tài)調(diào)整內(nèi)存使用蛛芥。
為了支持多個(gè)用戶使用內(nèi)存提鸟,有時(shí)會(huì)出現(xiàn)可用內(nèi)存被消耗光的情況。由于這個(gè)原因仅淑,頁(yè)面可以移出內(nèi)存并放入磁盤中称勋。這個(gè)過(guò)程稱為交換,因?yàn)轫?yè)面會(huì)被從內(nèi)存交換到硬盤上涯竟。內(nèi)存管理的源代碼可以在 ./linux/mm 中找到赡鲜。
虛擬文件系統(tǒng)
虛擬文件系統(tǒng)(VFS)是 Linux 內(nèi)核中非常有用的一個(gè)方面,因?yàn)樗鼮槲募到y(tǒng)提供了一個(gè)通用的接口抽象庐船。VFS 在 SCI 和內(nèi)核所支持的文件系統(tǒng)之間提供了一個(gè)交換層银酬。
VFS 在用戶和文件系統(tǒng)之間提供了一個(gè)交換層
在 VFS 上面,是對(duì)諸如 open筐钟、close揩瞪、read 和 write 之類的函數(shù)的一個(gè)通用 API 抽象。在 VFS 下面是文件系統(tǒng)抽象篓冲,它定義了上層函數(shù)的實(shí)現(xiàn)方式李破。它們是給定文件系統(tǒng)(超過(guò) 50 個(gè))的插件。文件系統(tǒng)的源代碼可以在 ./linux/fs 中找到壹将。
文件系統(tǒng)層之下是緩沖區(qū)緩存嗤攻,它為文件系統(tǒng)層提供了一個(gè)通用函數(shù)集(與具體文件系統(tǒng)無(wú)關(guān))。這個(gè)緩存層通過(guò)將數(shù)據(jù)保留一段時(shí)間(或者隨即預(yù)先讀取數(shù)據(jù)以便在需要是就可用)優(yōu)化了對(duì)物理設(shè)備的訪問(wèn)瞭恰。緩沖區(qū)緩存之下是設(shè)備驅(qū)動(dòng)程序屯曹,它實(shí)現(xiàn)了特定物理設(shè)備的接口。
好了惊畏。相信讀者已經(jīng)對(duì)linuxkernel 有了一個(gè)概觀恶耽。下面我們繼續(xù)分析這個(gè)路徑背后代表的模型結(jié)構(gòu)。(./linux/driver/tty/serial/samsung.c)
driver是驅(qū)動(dòng)程序的目錄颜启。如圖所示:
前文對(duì)linux設(shè)備驅(qū)動(dòng)程序有了一個(gè)大概的描述偷俭。下面我們具體看一下linux下的驅(qū)動(dòng)。
縱覽linux/drivers目錄缰盏,大概還有35個(gè)以上的子目錄涌萤,每個(gè)子目錄基本上就代表了一種設(shè)備驅(qū)動(dòng)淹遵,有atm、block负溪、char透揣、misc、input川抡、net辐真、usb、sound崖堤、video等侍咱。這里只描述在嵌入式系統(tǒng)里面用得最為廣泛的3種設(shè)備。
1.字符設(shè)備(char device)
字符設(shè)備是Linux最簡(jiǎn)單的設(shè)備密幔,可以像文件一樣訪問(wèn)楔脯。初始化字符設(shè)備時(shí),它的設(shè)備驅(qū)動(dòng)程序向Linux登記胯甩,并在字符設(shè)備向量表中增加一個(gè)device_struct數(shù)據(jù)結(jié)構(gòu)條目昧廷,這個(gè)設(shè)備的主設(shè)備標(biāo)識(shí)符用做這個(gè)向量表的索引。
一個(gè)設(shè)備的主設(shè)備標(biāo)識(shí)符是固定的偎箫。chrdevs向量表中的每一個(gè)條目麸粮,一個(gè)device_struct數(shù)據(jù)結(jié)構(gòu),包括兩個(gè)元素:一個(gè)登記設(shè)備驅(qū)動(dòng)程序名稱的指針和一個(gè)指向一組文件操作的指針镜廉。可以參考的代碼是include/linux/ major.h愚战。
一般來(lái)說(shuō)像鼠標(biāo)娇唯、串口、鍵盤等設(shè)備都屬于字符設(shè)備寂玲。
2.塊設(shè)備(block device)
塊設(shè)備是文件系統(tǒng)的物質(zhì)基礎(chǔ)塔插,它也可以像文件一樣被訪問(wèn)。Linux用blkdevs向量表維護(hù)已經(jīng)登記的塊設(shè)備文件拓哟。它像chrdevs向量表一樣想许,使用設(shè)備的主設(shè)備號(hào)作為索引。它的條目也是device_struct數(shù)據(jù)結(jié)構(gòu)断序。與字符設(shè)備不同的是流纹,塊設(shè)備分為SCSI類和IDE類。
向Linux內(nèi)核登記并向核心提供文件操作违诗。一種塊設(shè)備類的設(shè)備驅(qū)動(dòng)程序向這種類提供和類相關(guān)的接口漱凝。可以參考的代碼是fs/devices.c诸迟。
每一個(gè)塊設(shè)備驅(qū)動(dòng)程序必須提供普通的文件操作接口和對(duì)于buffer cache的接口茸炒。每一個(gè)塊設(shè)備驅(qū)動(dòng)程序填充blk_dev向量表中的blk_dev_struct數(shù)據(jù)結(jié)構(gòu)愕乎。此向量表的索引是設(shè)備的主設(shè)備號(hào)。其中blk_dev_struct數(shù)據(jù)結(jié)構(gòu)包括一個(gè)請(qǐng)求例程的地址和一個(gè)指針壁公,指向一個(gè)request數(shù)據(jù)結(jié)構(gòu)的列表感论,每一個(gè)都表達(dá)buffer cache向設(shè)備讀/寫一塊數(shù)據(jù)的一個(gè)請(qǐng)求。
可以參考的源代碼是drivers/block/ll_rw_blk.c和include/linux/blkdev.h紊册。
當(dāng)buffer cache從一個(gè)已登記的設(shè)備讀/寫一塊數(shù)據(jù)比肄,或者希望讀、寫一塊數(shù)據(jù)到其他位置時(shí)湿硝,就在blk_dev_struct中增加一個(gè)request數(shù)據(jù)結(jié)構(gòu)薪前。每個(gè)request數(shù)據(jù)結(jié)構(gòu)都有一個(gè)指向一個(gè)或多個(gè)buffer_head數(shù)據(jù)結(jié)構(gòu)的指針,每一個(gè)都是讀/寫一塊數(shù)據(jù)的請(qǐng)求关斜。
如果buffer_head數(shù)據(jù)結(jié)構(gòu)被鎖定(buffer_cache)示括,可能會(huì)有一個(gè)進(jìn)程在等待這個(gè)緩沖區(qū)的阻塞進(jìn)程完成。每一個(gè)request數(shù)據(jù)結(jié)構(gòu)都是從all_request表中分配的痢畜。如果request增加到空的request列表中垛膝,就調(diào)用驅(qū)動(dòng)程序的request函數(shù)處理這個(gè)request隊(duì)列,否則驅(qū)動(dòng)程序只是簡(jiǎn)單地處理request隊(duì)列中的每一個(gè)請(qǐng)求丁稀。
塊設(shè)備驅(qū)動(dòng)程序和字符設(shè)備驅(qū)動(dòng)程序的主要區(qū)別是:在對(duì)字符設(shè)備發(fā)出讀吼拥、寫請(qǐng)求時(shí),實(shí)際的硬件I/O一般緊接著就發(fā)生了线衫,塊設(shè)備則不然凿可,它利用一塊系統(tǒng)內(nèi)存作為緩沖區(qū),當(dāng)用戶進(jìn)程對(duì)設(shè)備請(qǐng)求能滿足用戶的要求時(shí)授账,就返回請(qǐng)求的數(shù)據(jù)枯跑,如果不能就調(diào)用請(qǐng)求函數(shù)來(lái)進(jìn)行實(shí)際的I/O操作。塊設(shè)備是主要針對(duì)磁盤等慢速設(shè)備的白热,以免耗費(fèi)過(guò)多的CPU時(shí)間來(lái)等待敛助。
塊設(shè)備主要有硬盤、光盤驅(qū)動(dòng)器等屋确∧苫鳎可以查看文件/proc/devices獲得。
3.網(wǎng)絡(luò)設(shè)備(net device)
網(wǎng)絡(luò)設(shè)備在系統(tǒng)中的作用類似于一個(gè)已掛載的塊設(shè)備攻臀。塊設(shè)備將自己注冊(cè)到blk_dev數(shù)據(jù)及其他內(nèi)核結(jié)構(gòu)中焕数,然后通過(guò)自己的request函數(shù)在發(fā)生請(qǐng)求時(shí)傳輸和接收數(shù)據(jù)塊,同樣網(wǎng)絡(luò)設(shè)備也必須在特定的數(shù)據(jù)結(jié)構(gòu)中注冊(cè)自己刨啸,以便與外界交換數(shù)據(jù)包時(shí)被調(diào)用百匆。網(wǎng)絡(luò)設(shè)備在Linux里做專門的處理。Linux的網(wǎng)絡(luò)系統(tǒng)主要是基于BSD UNIX的Socket機(jī)制呜投。在系統(tǒng)和驅(qū)動(dòng)程序之間定義有專門的數(shù)據(jù)結(jié)構(gòu)(sk_buff)進(jìn)行數(shù)據(jù)的傳遞加匈。系統(tǒng)里支持對(duì)發(fā)送數(shù)據(jù)和接收數(shù)據(jù)的緩存存璃,提供流量控制機(jī)制,提供對(duì)多協(xié)議的支持雕拼。
4.雜項(xiàng)設(shè)備(misc device)
雜項(xiàng)設(shè)備也是在嵌入式系統(tǒng)中用得比較多的一種設(shè)備驅(qū)動(dòng)纵东,在第11章里面介紹的sub LCD和弦芯片的驅(qū)動(dòng)等都是采用 misc device 的驅(qū)動(dòng)方式實(shí)現(xiàn)的。在 Linux 內(nèi)核的include\linux目錄下有Miscdevice.h文件啥寇,要把自己定義的misc device從設(shè)備定義在這里偎球。其實(shí)是因?yàn)檫@些字符設(shè)備不符合預(yù)先確定的字符設(shè)備范疇,所有這些設(shè)備采用主編號(hào)10辑甜,一起歸于misc device衰絮,其實(shí)misc_register就是用主標(biāo)號(hào)10調(diào)用register_chrdev()的。
這是driver目錄下的分類磷醋。我們主要調(diào)研的串口驅(qū)動(dòng)猫牡。屬于TTY子系統(tǒng)。所以我們cd到tty目錄下邓线。ls顯示里面的文件淌友。如圖所示:
下面對(duì)linux內(nèi)核tty設(shè)備做一點(diǎn)簡(jiǎn)要說(shuō)明。
tty一詞源于Teletypes骇陈,或Teletypewriters震庭,它是最早出現(xiàn)的一種終端設(shè)備,類似電傳打字機(jī)你雌,由Teletype公司生產(chǎn)器联。最初tty是指連接到Unix系統(tǒng)上的物理或者虛擬終端。終端是一種字符型設(shè)備婿崭,通常使用tty來(lái)統(tǒng)稱各種類型的終端設(shè)備主籍。隨著時(shí)間的推移,當(dāng)通過(guò)串行口能夠建立起終端連接后逛球,這個(gè)名字也用來(lái)指任何的串口設(shè)備。
它還有多種類苫昌,例如串口(ttySn颤绕、ttySACn、ttyOn)祟身、USB到串口的轉(zhuǎn)換器(ttyUSBn)奥务,還有需要特殊處理才能正常工作的調(diào)制解調(diào)器(比如傳統(tǒng)的WinModem類設(shè)備)等。tty虛擬設(shè)備支持虛擬控制臺(tái)袜硫,它能通過(guò)鍵盤及網(wǎng)絡(luò)連接或者通過(guò)xterm會(huì)話登錄到計(jì)算機(jī)上氯葬。
其實(shí)起初終端和控制臺(tái)都不是個(gè)人電腦的概念,而是多人共用的小型中型大型計(jì)算機(jī)上的概念婉陷。終端為主機(jī)提供了人機(jī)接口帚称,每個(gè)人都通過(guò)終端使用主機(jī)的資源。終端有字符終端和圖形終端兩種楼吃。一臺(tái)主機(jī)可以連很多終端】殉粒控制臺(tái)是一種特殊的人機(jī)接口, 是人控制主機(jī)的第一人機(jī)接口况既。
而主機(jī)對(duì)于控制臺(tái)的信任度高于其他終端耸三。對(duì)此還可以結(jié)合內(nèi)核啟動(dòng)代碼中init進(jìn)程打開(kāi)/dev/console和執(zhí)行兩次sys_dup(0)养盗,以及標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出、標(biāo)準(zhǔn)出錯(cuò)藏研,還有就是進(jìn)程fork后的標(biāo)準(zhǔn)輸入輸出的復(fù)制情況來(lái)一起理解敬矩。而個(gè)人計(jì)算機(jī)只有控制臺(tái),沒(méi)有終端。當(dāng)然愿意的話蠢挡,可以在串口上連一兩臺(tái)字符啞終端弧岳。
但是linux按POSIX標(biāo)準(zhǔn)把個(gè)人計(jì)算機(jī)當(dāng)成小型機(jī)來(lái)用,在控制臺(tái)上通過(guò)getty軟件虛擬了六個(gè)字符啞終端(或者叫虛擬控制臺(tái)終端tty1-tty6)(數(shù)量可以在/etc/inittab里自己調(diào)整)和一個(gè)圖型終端, 在虛擬圖形終端中又可以通過(guò)軟件(如rxvt)再虛擬無(wú)限多個(gè)偽終端(pts/0等)。
但這全是虛擬的,雖然用起來(lái)一樣,但實(shí)際上沒(méi)有物理實(shí)體业踏。所以在個(gè)人計(jì)算機(jī)上,只有一個(gè)實(shí)際的控制臺(tái),沒(méi)有終端,所有終端都是在控制臺(tái)上用軟件模擬的禽炬。要把個(gè)人計(jì)算機(jī)當(dāng)主機(jī)再通過(guò)串口或網(wǎng)卡外連真正的物理終端也可以,論成本,呵呵勤家。誰(shuí)會(huì)怎么做呢腹尖。
終端按照其自身能力分類,可以分為:
1伐脖、啞終端(瘦客戶端)
早期的計(jì)算機(jī)終端是通過(guò)串行RS-232通信的热幔,它只能解釋有限數(shù)量的控制碼(CR,LF等)晓殊,但沒(méi)有能力處理執(zhí)行特殊的轉(zhuǎn)義序列功能(如清行、清屏或控制光標(biāo)的位置)伤提。簡(jiǎn)單來(lái)說(shuō)就是處理能力有限的終端機(jī)巫俺,他們一般基本上只具有和機(jī)械電傳打字機(jī)類似的有限功能。這種類型的終端稱為啞終端肿男。
現(xiàn)在仍然在現(xiàn)代類Unix系統(tǒng)上得到支持介汹,通過(guò)設(shè)置環(huán)境變量TERM=dumb却嗡。啞終端有時(shí)用來(lái)指任何類型的通過(guò)RS-232連接的傳統(tǒng)計(jì)算機(jī)終端,不對(duì)數(shù)據(jù)進(jìn)行本地處理或本地執(zhí)行用戶程序的串行通信終端嘹承。啞終端有時(shí)也指功能有限窗价,只有單色文本處理能力或直接傳輸每一個(gè)鍵入的字符而不等待主機(jī)輪詢的公共計(jì)算機(jī)終端。
2叹卷、智能終端(胖客戶端)
智能終端就是有能力處理轉(zhuǎn)義序列撼港,也就是說(shuō)處理能力較強(qiáng)的終端機(jī)。
Linux系統(tǒng)的終端設(shè)備一般有以下幾種:
1骤竹、 控制臺(tái)
系統(tǒng)控制臺(tái)/dev/console
/dev/console是系統(tǒng)控制臺(tái)帝牡,是與操作系統(tǒng)交互的設(shè)備。系統(tǒng)所產(chǎn)生的信息會(huì)發(fā)送到該設(shè)備上蒙揣。平時(shí)我們看到的PC只有一個(gè)屏幕和鍵盤靶溜,它其實(shí)就是控制臺(tái)。目前只有在單用戶模式下懒震,才允許用戶登錄控制臺(tái)/dev/console罩息。(可以在單用戶模式下輸入tty命令進(jìn)行確認(rèn))。
console有緩沖的概念个扰,為內(nèi)核提供打印輸出瓷炮。內(nèi)核把要打印的內(nèi)容裝入緩沖區(qū)__log_buff,然后由console來(lái)決定打印到哪里(比如是tty0還是ttySn等)锨匆。console指向激活的終端崭别。歷史上,console指主機(jī)本身的屏幕和鍵盤恐锣,而tty指用電纜鏈接的其它位置的控制臺(tái)茅主。
某些情況下console和tty0是一致的,就是當(dāng)前所使用的是虛擬終端土榴,也是激活虛擬終端诀姚。所以有些資料中稱/dev/console是到/dev/tty0的符號(hào)鏈接,但是這樣說(shuō)現(xiàn)在看來(lái)是不對(duì)的:根據(jù)內(nèi)核文檔玷禽,在2.1.71之前赫段,/dev/console根據(jù)不同系統(tǒng)設(shè)定,符號(hào)鏈接到/dev/tty0或者其他tty*上矢赁,在2.1.71版本之后則完全由內(nèi)核代碼內(nèi)部控制它的映射糯笙。
如果一個(gè)終端設(shè)備要實(shí)現(xiàn)console功能,必須向內(nèi)核注冊(cè)一個(gè)struct console結(jié)構(gòu)撩银,一般的串口驅(qū)動(dòng)中都會(huì)有给涕。如果設(shè)備要實(shí)現(xiàn)tty功能,必須要內(nèi)核的tty子系統(tǒng)注冊(cè)一個(gè)struct tty_driver結(jié)構(gòu),注冊(cè)函數(shù)在drivers/tty/tty_io.c中够庙。一個(gè)設(shè)備可以同時(shí)實(shí)現(xiàn)console和tty_driver恭应,一般串口都這么做。
當(dāng)前控制臺(tái):/dev/tty
這是應(yīng)用程序中的概念耘眨,如果當(dāng)前進(jìn)程有控制終端(Controlling Terminal)昼榛,那么/dev/tty就是當(dāng)前進(jìn)程控制臺(tái)的設(shè)備文件。對(duì)于你登錄的shell剔难,/dev/tty就是你使用的控制臺(tái)胆屿,設(shè)備號(hào)是(5,0)。不過(guò)它并不指任何物理意義上的控制臺(tái)钥飞,/dev/tty會(huì)映射到當(dāng)前設(shè)備(使用命令“tty”可以查看它具體對(duì)應(yīng)哪個(gè)實(shí)際物理控制臺(tái)設(shè)備)莺掠。輸出到/dev/tty的內(nèi)容只會(huì)顯示在當(dāng)前工作終端上(無(wú)論是登錄在ttyn中還是pty中)。
你如果在控制臺(tái)界面下(即字符界面下)那么dev/tty就是映射到dev/tty1-6之間的一個(gè)(取決于你當(dāng)前的控制臺(tái)號(hào))读宙,但是如果你現(xiàn)在是在圖形界面(Xwindows)彻秆,那么你會(huì)發(fā)現(xiàn)現(xiàn)在的/dev/tty映射到的是/dev/pts的偽終端上。/dev/tty有些類似于到實(shí)際所使用終端設(shè)備的一個(gè)聯(lián)接结闸。
你可以輸入命令“tty"唇兑,將顯示當(dāng)前映射終端如:/dev/tty1或者/dev/pts/0等。也可以使用命令“ps -ax”來(lái)查看其他進(jìn)程與哪個(gè)控制終端相連桦锄。
在當(dāng)前終端中輸入 echo “tekkaman” > /dev/tty 扎附,都會(huì)直接顯示在當(dāng)前的終端中。
虛擬控制臺(tái) /dev/ttyn
/dev/ttyn是進(jìn)程虛擬控制臺(tái)结耀,他們共享同一個(gè)真實(shí)的物理控制臺(tái)留夜。如果在進(jìn)程里打開(kāi)一個(gè)這樣的文件且該文件不是其他進(jìn)程的控制臺(tái)時(shí),那該文件就是這個(gè)進(jìn)程的控制臺(tái)图甜。
進(jìn)程printf數(shù)據(jù)會(huì)輸出到這里碍粥。在PC上,用戶可以使用alt+Fn切換控制臺(tái)黑毅,現(xiàn)在不知道怎么回事我用Ctrl + Alt + Fn才能切換嚼摩。這沒(méi)具體看過(guò)為啥】笫荩可能是Linux沒(méi)有繼承UNIX這方面的傳統(tǒng)罷了枕面。看起來(lái)感覺(jué)存在多個(gè)屏幕缚去,這種虛擬控制臺(tái)對(duì)應(yīng)tty1~n潮秘,其中:
/dev/tty1等代表第一個(gè)虛擬控制臺(tái)
例如當(dāng)使用ALT+F2進(jìn)行切換時(shí),系統(tǒng)的虛擬控制臺(tái)為/dev/tty2 易结,當(dāng)前控制臺(tái)(/dev/tty)則指向/dev/tty2
在UNIX系統(tǒng)中枕荞,計(jì)算機(jī)顯示器通常被稱為控制臺(tái)(Console)稠通。它仿真了類型為L(zhǎng)inux的一種終端,并且有一些設(shè)備特殊文件與之相關(guān)聯(lián):tty0买猖、tty1、tty2等滋尉。當(dāng)你在控制臺(tái)上登錄時(shí)玉控,使用的是tty1。使用Alt+[F1—F6]組合鍵時(shí)狮惜,我們就可以切換到tty2高诺、tty3等上面去。
讀者可以登錄到不同的虛擬控制臺(tái)上去碾篡,因而可以讓系統(tǒng)同時(shí)有幾個(gè)不同的會(huì)話存在虱而。
而比較特殊的是/dev/tty0,他代表當(dāng)前虛擬控制臺(tái)开泽,其實(shí)就是當(dāng)前所使用虛擬控制臺(tái)的一個(gè)別名牡拇。因此不管當(dāng)前正在使用哪個(gè)虛擬控制臺(tái)(注意:這里是虛擬控制臺(tái),不包括偽終端)穆律,系統(tǒng)信息都會(huì)重定位到/dev/tty0上惠呼。
只有系統(tǒng)或超級(jí)用戶root可以向/dev/tty0進(jìn)行寫操作。tty0是系統(tǒng)自動(dòng)打開(kāi)的峦耘,但不用于用戶登錄剔蹋。在Framebuffer設(shè)備沒(méi)有啟用的系統(tǒng)中,可以使用/dev/tty0訪問(wèn)顯卡辅髓。
2泣崩、 偽終端pty(pseudo-tty)
偽終端(Pseudo Terminal)是終端的發(fā)展,為滿足現(xiàn)在需求(比如網(wǎng)絡(luò)登陸洛口、xwindow窗口的管理)矫付。它是成對(duì)出現(xiàn)的邏輯終端設(shè)備(即master和slave設(shè)備, 對(duì)master的操作會(huì)反映到slave上)。它多用于模擬終端程序绍弟,是遠(yuǎn)程登陸(telnet技即、ssh、xterm等)后創(chuàng)建的控制臺(tái)設(shè)備樟遣。
歷史上而叼,有兩套偽終端軟件接口:
BSD接口:較簡(jiǎn)單,master為/dev/pty [p-za-e] [0-9a-f];slave為 /dev/tty [p-za-e] [0-9a-f] 豹悬,它們都是配對(duì)的出現(xiàn)的葵陵。例如/dev/ptyp3和/dev/ttyp3。但由于在編程時(shí)要找到一個(gè)合適的終端需要逐個(gè)嘗試瞻佛,所以逐漸被放棄脱篙。
Unix 98接口:使用一個(gè)/dev/ptmx作為master設(shè)備娇钱,在每次打開(kāi)操作時(shí)會(huì)得到一個(gè)master設(shè)備fd,并在/dev/pts/目錄下得到一個(gè)slave設(shè)備(如 /dev/pts/3和/dev/ptmx)绊困,這樣就避免了逐個(gè)嘗試的麻煩文搂。
由于可能有好幾千個(gè)用戶登陸,所以/dev/pts/* 是動(dòng)態(tài)生成的秤朗,不象其他設(shè)備文件是構(gòu)建系統(tǒng)時(shí)就已經(jīng)產(chǎn)生的硬盤節(jié)點(diǎn)(如果未使用devfs煤蹭、udev、mdev等) 取视。第一個(gè)用戶登陸硝皂,設(shè)備文件為/dev/pts/0,第二個(gè)為/dev/pts/1作谭,以此類推稽物。它們并不與實(shí)際物理設(shè)備直接相關(guān)。現(xiàn)在大多數(shù)系統(tǒng)是通過(guò)此接口實(shí)現(xiàn)pty折欠。
我們?cè)赬 Window下打開(kāi)的終端或使用telnet或ssh等方式登錄Linux主機(jī)贝或,此時(shí)均通過(guò)pty設(shè)備。例如锐秦,如果某人在網(wǎng)上使用telnet程序連接到你的計(jì)算機(jī)上傀缩,則telnet程序就可能會(huì)打開(kāi)/dev/ptmx設(shè)備獲取一個(gè)fd。此時(shí)一個(gè)getty程序就應(yīng)該運(yùn)行在對(duì)應(yīng)的/dev/pts/* 上农猬。當(dāng)telnet從遠(yuǎn)端獲取了一個(gè)字符時(shí)赡艰,該字符就會(huì)通過(guò)ptmx、pts/* 傳遞給 getty程序斤葱,而getty程序就會(huì)通過(guò)pts/* 慷垮、ptmx和telnet程序往網(wǎng)絡(luò)上返回“l(fā)ogin:”字符串信息。這樣揍堕,登錄程序與telnet程序就通過(guò)“偽終端”進(jìn)行通信料身。
telnet<--->/dev/ptmx(master)<--->pts/*(slave)<--->getty
如果一個(gè)程序把 pts/* 看作是一個(gè)串行端口設(shè)備,則它對(duì)該端口的讀/寫操作會(huì)反映在該邏輯終端設(shè)備對(duì)的另一個(gè)/dev/ptmx上衩茸,而/dev/ptmx則是另一個(gè)程序用于讀寫操作的邏輯設(shè)備芹血。
這樣,兩個(gè)程序就可以通過(guò)這種邏輯設(shè)備進(jìn)行互相交流楞慈,這很象是邏輯設(shè)備對(duì)之間的管道操作幔烛。對(duì)于pts/* ,任何設(shè)計(jì)成使用一個(gè)串行端口設(shè)備的程序都可以使用該邏輯設(shè)備囊蓝。但對(duì)于使用/dev/ptmx的程序饿悬,則需要專門設(shè)計(jì)來(lái)使用/dev/ptmx邏輯設(shè)備。通過(guò)使用適當(dāng)?shù)能浖鬯涂梢园褍蓚€(gè)甚至多個(gè)偽終端設(shè)備連接到同一個(gè)物理串行端口上狡恬。
3珠叔、 串口終端(/dev/ttySn)
串行端口終端(Serial PortTerminal)是使用計(jì)算機(jī)串行端口連接的終端設(shè)備。計(jì)算機(jī)把每個(gè)串行端口都看作是一個(gè)字符設(shè)備弟劲。有段時(shí)間串行端口設(shè)備通常被稱為終端設(shè)備祷安,那時(shí)它的最大用途就是用來(lái)連接終端,所以這些串行端口所對(duì)應(yīng)的設(shè)備名稱是/dev/tts/0(或/dev/ttyS0)兔乞、/dev/tts/1(或/dev /ttyS1)等辆憔,設(shè)備號(hào)分別是(4,0)、(4,1)等(對(duì)應(yīng)于win系統(tǒng)下的COM1报嵌、COM2等)。若要向一個(gè)端口發(fā)送數(shù)據(jù)熊榛,可以在命令行上把標(biāo)準(zhǔn)輸出重定向到這些特殊文件名上即可锚国。
我們可以在命令行提示符下鍵入:echotekkaman> /dev/ttyS1會(huì)把“tekkaman”發(fā)送到連接在ttyS1(COM2)端口的設(shè)備上。
在2.6以后的內(nèi)核后玄坦、一些三星的芯片將串口終端設(shè)備節(jié)點(diǎn)命名為ttySACn血筑。TI的Omap系列芯片從2.6.37開(kāi)始芯片自帶的UART設(shè)備開(kāi)始使用專有的的omap-uart驅(qū)動(dòng),故設(shè)備節(jié)點(diǎn)命名為ttyOn煎楣,以區(qū)別于使用8250驅(qū)動(dòng)時(shí)的設(shè)備名“ttySn”豺总。這其中包括筆者用到的這個(gè)S3C2440。所以我們?cè)赨boot啟動(dòng)參數(shù)中要設(shè)置console = ttySAC0才可以择懂。這一句的意思其實(shí)就是把ttySAC0當(dāng)做我們的控制臺(tái)終端喻喳。
4、 其它類型終端
還針對(duì)很多不同的字符設(shè)備存在有很多其它種類的終端設(shè)備特殊文件困曙,例如針對(duì)ISDN設(shè)備的/dev/ttyIn終端設(shè)備等表伦。
好了。到此為止慷丽。相信讀者已經(jīng)對(duì)tty設(shè)備有了一個(gè)概觀蹦哼。
因?yàn)槲覀兒烷_(kāi)發(fā)板的人機(jī)交互的接口是Windows下的串口控制臺(tái)。這就是上面所說(shuō)的控制臺(tái)終端要糊。但是我們用了console = ttySAC0.即把串口終端當(dāng)做控制臺(tái)終端纲熏。所以我們要研究具體的代碼需要cd到serial子目錄下。即串口終端目錄锄俄。ls顯示serial下的文件結(jié)點(diǎn)局劲。如圖所示:
我們主要關(guān)心的是兩類文件。一類是與體系結(jié)構(gòu)和板載資源無(wú)關(guān)的通用串口操作文件奶赠。(samsung.c)一類是與體系結(jié)構(gòu)相關(guān)的硬件操作文件容握。(s3c2440.c s3c2410.c s5pv210.c等),我們?yōu)榱说玫骄唧w的調(diào)用鏈车柠。在具體的發(fā)送函數(shù)中加入回溯剔氏。如圖所示塑猖。
我們得到的函數(shù)調(diào)用鏈?zhǔn)沁@樣的(以發(fā)送函數(shù)。即文件的寫操作為例.
write->
sys_write->
vfs_write->
redirected_tty_write->
tty_write->
n_tty_write->
uart_write->
uart_start->
s3c24xx_serial_start_tx
從具體代碼上來(lái)看谈跛。這些函數(shù)基本上都是通過(guò)結(jié)構(gòu)體中的函數(shù)指針調(diào)用羊苟。我們可以把這個(gè)調(diào)用鏈分為三個(gè)部分。即tty子系統(tǒng)核心感憾。tty鏈路規(guī)程蜡励。tty驅(qū)動(dòng)
tty核心。是對(duì)整個(gè)tty設(shè)備的抽象阻桅。對(duì)用戶提供統(tǒng)一的接口凉倚。包括sys_write->vfs_write
tty線路規(guī)程。是對(duì)傳輸數(shù)據(jù)的格式化嫂沉。在tty_ldisc_N_TTY變量中描述稽寒。包括redirected_tty_write->tty_write->n_tty_write->
tty驅(qū)動(dòng)。是面向tty設(shè)備的硬件驅(qū)動(dòng)趟章。這里面真正的對(duì)硬件進(jìn)行操作杏糙。包括uart_write->uart_start->s3c24xx_serial_start_tx
這是從具體函數(shù)的角度來(lái)看的調(diào)用鏈。下面為了從數(shù)據(jù)結(jié)構(gòu)的角度來(lái)分析調(diào)用鏈蚓土。介紹linux內(nèi)核中針對(duì)于這一個(gè)串口硬件的主要數(shù)據(jù)結(jié)構(gòu)宏侍。對(duì)于具體的字段我們用到的時(shí)候再解釋。
uart_driver蜀漆。
就是uart驅(qū)動(dòng)程序結(jié)構(gòu)谅河。封裝了tty_driver,使得底層的UART驅(qū)動(dòng)無(wú)需關(guān)心tty_driver具體定義如下确丢。
uart_port
uart_port用于描述一個(gè)UART端口(直接對(duì)應(yīng)于一個(gè)串口)的I/O端口或者IO內(nèi)存地址等信息旧蛾。
uart_ops定義了針對(duì)UART的一系列操作。注意這里不要把uart_ops結(jié)構(gòu)和uart_ops變量混淆蠕嫁。uart_ops結(jié)構(gòu)是我們這里的數(shù)據(jù)結(jié)構(gòu)锨天。而uart_ops變量則是一個(gè)tty_operations的變量。
在serial_core.c中定義了tty_operations的實(shí)例剃毒。即uart_ops變量病袄,包含uart_open();uart_close()赘阀;uart_send_xchar()等成員函數(shù)涯捻,這些函數(shù)借助uart_ops結(jié)構(gòu)體中的成員函數(shù)來(lái)完成具體的操作:
uart_ops變量是tty_operations型的一個(gè)變量买决。如下圖所示:
uart_state是uart的狀態(tài)結(jié)構(gòu)。
uart_info是uart的信息結(jié)構(gòu)。在這個(gè)體系結(jié)構(gòu)下定義為s3c24xx_uart_info:
所以很顯然书幕。用數(shù)據(jù)結(jié)構(gòu)來(lái)描述函數(shù)調(diào)用鏈就是
uart_driver ->
uart_state->
uart_port->
uart_ops->
特定的函數(shù)指針仰美。
初始化過(guò)程比較復(fù)雜。不贅述。從函數(shù)指針的調(diào)用流程為主線齿诞。忽略一些入?yún)z查和內(nèi)核中的信號(hào)量代碼。大致的初始化流程如下圖所示:
打開(kāi)設(shè)備和初始化流程類似骂租。如圖所示:
同理數(shù)據(jù)的發(fā)送和接收如圖所示:
這里我們需要注意的是祷杈。使能發(fā)送并沒(méi)有真正的發(fā)送過(guò)程。而只是使能發(fā)送中斷
這一句:enable_irq(ourport->tx_irq);
這是因?yàn)锳RM9處理器上有一個(gè)循環(huán)緩沖渗饮。用戶從write系統(tǒng)調(diào)用傳下來(lái)的數(shù)據(jù)就會(huì)寫入這個(gè)UTXH0寄存器但汞。發(fā)送完事之后處理器會(huì)產(chǎn)生一個(gè)內(nèi)部中斷。我們通過(guò)這個(gè)內(nèi)部中斷就可以實(shí)現(xiàn)流控過(guò)程互站、我們打開(kāi)芯片手冊(cè)可以看到如下字樣(拿ARM11舉例也一樣私蕾,。這是ARM11的):
如下才是發(fā)送中斷的ISR(Interrupt Service Routine)中斷服務(wù)例程胡桃。一個(gè)irqreturn_t類型的handler踩叭。
這個(gè)wr_regb(port, S3C2410_UTXH, port->x_char);就是往特定寄存器寫的過(guò)程。
至此我們的分析已經(jīng)結(jié)束标捺。相信讀者對(duì)于Linux下的tty子系統(tǒng)已經(jīng)有一個(gè)概觀了。下面是這個(gè)uart驅(qū)動(dòng)的總圖揉抵。結(jié)合數(shù)據(jù)結(jié)構(gòu)的調(diào)用鏈亡容。Linux內(nèi)核完成了驅(qū)動(dòng)模型和特定硬件的分離:
串口驅(qū)動(dòng)數(shù)據(jù)結(jié)構(gòu)總圖:
-END-
直接來(lái)源 | 嵌入式大雜燴
原文:http://www.reibang.com/p/3a9013b9569c
作者:Linkerist
| *整理文章為傳播相關(guān)技術(shù),版權(quán)歸原作者所有* |
*| 如有侵權(quán)冤今,請(qǐng)聯(lián)系刪除* |