嵌入式驱动自学者的亲身感受,有什么建议?
點(diǎn)擊下方卡片,關(guān)注公眾號
ID:技術(shù)讓夢想更偉大
整理:李肖遙
嵌入式驅(qū)動(dòng)自學(xué)者的感受
?
學(xué)習(xí)嵌入式,或者說學(xué)習(xí)現(xiàn)代的計(jì)算機(jī)編程,如果你想學(xué)好,有一個(gè)比較要求,那就是你能接受它的設(shè)定、它的模式。反過來說,當(dāng)你真正接受它的設(shè)定、它的模式,并記住它們時(shí),我認(rèn)為,你已經(jīng)學(xué)好了。
?
昨天,我又置之死地而后生了一次。最近一直在搞驅(qū)動(dòng),一個(gè)LCD驅(qū)動(dòng)搞得我?guī)缀跻艞壚^續(xù)走嵌入式這條路。昨夜,睡不覺,打開嵌入學(xué)習(xí)視頻,躺在已關(guān)燈很久的房間的床上,大概凌晨3,4點(diǎn)吧。之前我一直都是學(xué)習(xí)著驅(qū)動(dòng)自編源碼的教學(xué),是那種幾乎和裸板程序沒多大區(qū)別的編程方式,只是多使用了一些向內(nèi)核注冊的接口函數(shù)。
?
而最近我想換一下,因?yàn)楹芏嘣O(shè)備驅(qū)動(dòng),內(nèi)核都是自帶的,而且是各種平臺的設(shè)備驅(qū)動(dòng)都有,我想如果能熟悉掌握內(nèi)核自帶驅(qū)動(dòng)的編程,那以后要做某個(gè)設(shè)備的驅(qū)動(dòng)時(shí),我只需要在自帶驅(qū)動(dòng)中修改一下便好了,通過學(xué)習(xí)LCD平臺設(shè)備的驅(qū)動(dòng),我了解了其編程想法,同時(shí)也認(rèn)同這種想法,甚至讓我疑惑,學(xué)習(xí)資料中教自編驅(qū)動(dòng)的意義,為何不直接教如果修改內(nèi)核源碼驅(qū)動(dòng)?
?
于是,繼續(xù)按著書去修改內(nèi)核驅(qū)動(dòng)源碼,但問題是,書中說他們這種修改,代碼成功運(yùn)行了,但我這,無論怎么調(diào)試都失敗,我反復(fù)檢測,我的修改是否與書中一致,檢測了很多遍依然沒發(fā)現(xiàn)哪一步不同,不過,有一點(diǎn)發(fā)現(xiàn)是,書中的內(nèi)核源碼和我內(nèi)核使用的源碼有一點(diǎn)點(diǎn)區(qū)別(當(dāng)然書里并沒有把所有的源碼都貼上,只是修改部分附近會聯(lián)帶著一些,這就是發(fā)現(xiàn),這些聯(lián)帶的沒需要修改的源碼和我的源碼有點(diǎn)區(qū)別,比如,我的源碼中多了一些設(shè)置(看似無關(guān)緊要的設(shè)置))。
?
與書核對無誤但失敗后,我又與成功運(yùn)行的自編驅(qū)動(dòng)核對,我陸續(xù)發(fā)現(xiàn)我修改的內(nèi)涵源碼中,沒有去啟動(dòng)設(shè)備,也更沒有去點(diǎn)亮背光,而在顯存分配后的寄存器設(shè)置似乎也有問題,因?yàn)檫@里的地址使用各種宏定義不同的累加或計(jì)算,最后算得地址和我的寄存器地址也不知是否吻合,因?yàn)轵?qū)動(dòng)源碼中最后計(jì)算得到的是虛擬地址。于是我對比自編驅(qū)動(dòng),一點(diǎn)點(diǎn)修改嘗試,到睡覺前都沒成功。
?
我是想學(xué)得理直氣壯一點(diǎn)的,最后是能一眼就能找到問題,并迅速輕松解決問題的,我也承認(rèn)自己確實(shí)是有些浮躁。但是經(jīng)過了昨晚床上的一點(diǎn)絕望的思考掙扎后,我好像想通了:為什么嵌入式學(xué)習(xí)視頻老師要教自編驅(qū)動(dòng)。
?
下面我說下自編驅(qū)動(dòng)與內(nèi)核驅(qū)動(dòng)源碼各自的問題:
自便驅(qū)動(dòng):
程序簡單簡潔,它只能驅(qū)動(dòng)特定的某個(gè)設(shè)備。如果設(shè)備換了需要支持另一款設(shè)備,那么你需要重新修改該驅(qū)動(dòng);如果需要系統(tǒng)同時(shí)支持兩種LCD,那么它就會變成復(fù)雜并且對于內(nèi)核驅(qū)動(dòng)的簡潔優(yōu)勢會削弱不少;如果你想驅(qū)動(dòng)支持多種設(shè)備,那自編驅(qū)動(dòng),相對了內(nèi)核驅(qū)動(dòng)源碼的簡潔優(yōu)勢會變成了劣勢,因?yàn)榫幊趟枷氲倪m用范圍不同而產(chǎn)生的結(jié)果。
內(nèi)核自帶驅(qū)動(dòng)源碼:
?
①從系統(tǒng)層次去考量,變量、宏定義使用多,甚至有些宏定義的值為了方便能讓各種在不同的階段需要不同的值調(diào)用,把簡單的一個(gè)賦值調(diào)用變成了需要進(jìn)行多次運(yùn)算才能檢測到該值是否滿足使用要求,因?yàn)槲覀儾皇窃擈?qū)動(dòng)的編碼者,不清楚這樣做的好處,也或許是內(nèi)核驅(qū)動(dòng)源碼的開發(fā)者從整個(gè)系統(tǒng)的編程簡潔性去考量,這樣做或許也是為了讓整個(gè)系統(tǒng)代碼更少,簡潔的一種做法,因?yàn)槊總€(gè)設(shè)備你都給它賦具體的值的話,整個(gè)系統(tǒng)中有幾百種驅(qū)動(dòng)設(shè)備源碼,給所有設(shè)備的這個(gè)位置參數(shù)都賦一個(gè)值的話,那各設(shè)備關(guān)于這個(gè)值的代碼就要多了幾百行了,所以還不如,讓各設(shè)備根據(jù)各種平臺去對某個(gè)宏進(jìn)行各自的計(jì)算來得到合適的值,但某些計(jì)算中相同的算法的也整合在一起,這樣就減少了系統(tǒng)不少行代碼。所以系統(tǒng)中驅(qū)動(dòng)源碼是系統(tǒng)開發(fā)者對系統(tǒng)源碼的整合,是基于系統(tǒng)層的整合。所以,對于我這種對單個(gè)設(shè)備驅(qū)動(dòng)編碼的人,就會覺得系統(tǒng)源碼有好多不人性化的地方,會覺得簡單的地方也被弄得很復(fù)雜。
?
②內(nèi)核自帶驅(qū)動(dòng)還有一些代碼是為了兼容以前的版本而添加了,比如以前硬件內(nèi)存資源稀少,需要使用調(diào)色板的方法來減少程序運(yùn)行時(shí)的內(nèi)存使用量,這也會真假代碼的復(fù)雜性,這一步雖不是必要的,但如果沒弄好,那LCD驅(qū)動(dòng)也不能正常使用。
?
③程序復(fù)雜,為了適用在多種設(shè)備型號,更簡單地添加不同型號的設(shè)備驅(qū)動(dòng),內(nèi)核對驅(qū)動(dòng)抽象分離,把驅(qū)動(dòng)分為平臺管理部分,驅(qū)動(dòng)代碼部分(與硬件無關(guān)碼),和設(shè)備代碼部分(硬件相關(guān)代碼)。用戶添加新型號設(shè)備驅(qū)動(dòng)時(shí),只需要在平臺管理部分檢查添加設(shè)備的匹配信息,和提供一個(gè)硬件設(shè)備相關(guān)的代碼(有格式)文件即可。
?
現(xiàn)在,站在驅(qū)動(dòng)開發(fā)者而非系統(tǒng)開發(fā)者的角度去衡量。
?
①自編的驅(qū)動(dòng),簡潔,要點(diǎn)明確。這個(gè)對于驅(qū)動(dòng)開發(fā)者的用處就是:無論你使用的是哪個(gè)版本的內(nèi)核,哪個(gè)芯片平臺,你可以通過自編碼比較簡單方便地就可以確認(rèn)硬件設(shè)備的情況,是否正常。如果自編碼通過,那可以試用自編碼上使用的參數(shù)去與內(nèi)核進(jìn)行核對、修改,然后再去測試。如果不成功,對于內(nèi)核中多余的設(shè)置(這些大多可能是提供內(nèi)核用做基本判斷的變量)可以先屏蔽,編譯出錯(cuò)了,根據(jù)提示,找到出錯(cuò)的位置修改添加。因?yàn)檫@些多余的設(shè)置,設(shè)置對了還行,設(shè)置錯(cuò)了,你又不好去定位錯(cuò)在哪。
?
自編的驅(qū)動(dòng)在此處的用處,調(diào)試時(shí),可以讓你排除多余的失敗可能性問題,在較少的代碼去查出錯(cuò)誤位置,如果你確定你的設(shè)置滿足了該設(shè)備的必需設(shè)置,還是失敗,你可以比較放心地去懷疑是硬件問題了。如果自編碼成功,那個(gè)又可以當(dāng)做你修改內(nèi)核驅(qū)動(dòng)的一個(gè)標(biāo)準(zhǔn)。
?
②內(nèi)核驅(qū)動(dòng)源碼支持管理多種型號的設(shè)備的優(yōu)勢是我用使用它的原因。先了解本版本本平臺的設(shè)備驅(qū)動(dòng)結(jié)構(gòu),如果是添加型號支持,那就根據(jù)自編驅(qū)動(dòng)的參數(shù)與設(shè)置即可,如果是第一次啟動(dòng)這類設(shè)備,你就還需要檢測結(jié)構(gòu)是完整性,如果結(jié)構(gòu)完整,參數(shù)無誤依舊錯(cuò)誤,那就把內(nèi)核驅(qū)動(dòng)源碼精簡到自編碼的簡單粗暴設(shè)置吧。最終就變成了在基于內(nèi)核驅(qū)動(dòng)架構(gòu)下的自編驅(qū)動(dòng)。如果還不行,那無疑是結(jié)構(gòu)性問題了。
?
所以自編驅(qū)動(dòng),還是有其存在價(jià)值的。內(nèi)核驅(qū)動(dòng)源碼內(nèi)容會變,平臺會變,但自編驅(qū)動(dòng)是變得最小的一個(gè),也是最容易實(shí)現(xiàn)驅(qū)動(dòng)目的的一個(gè)。是一碼打天下不可缺少的重要組成部分。
對于嵌入式驅(qū)動(dòng)開發(fā)的建議
1)?為了今后的發(fā)展,你除了考慮廣度以外,更重要的是注意知識的深度。
譬如,做過網(wǎng)絡(luò)驅(qū)動(dòng),那么是不是只停留在會寫驅(qū)動(dòng)的表層上,有沒有對Linux內(nèi)核的網(wǎng)絡(luò)結(jié)構(gòu),TCP/IP協(xié)議作過深入的了解。
2)?在Linux下開發(fā)很多時(shí)候都要利用現(xiàn)成的東西,沒必要什么都自己搞。關(guān)鍵是變成自己的驅(qū)動(dòng)后是否了解原作者編寫時(shí)背后的一些東西。你應(yīng)該不止是簡單的讓它工作。寫驅(qū)動(dòng)的時(shí)候就要考慮它的性能問題,并給出測試的方法(當(dāng)然可以利用現(xiàn)成的許多工具,譬如測試網(wǎng)絡(luò)性能的netperf等)。
當(dāng)你寫過Flash驅(qū)動(dòng),可能會知道Flash的性能有時(shí)候有多重要。
3)?C程序的自我修煉,是否考慮到軟件工程方面的一些東西,程序的可維護(hù)性和擴(kuò)展性,譬如LCD驅(qū)動(dòng),是不是從Sharp到NEC的只需要集中修改很少的幾個(gè)地方?
對于不同品牌的Flash,如果使得Flash的驅(qū)動(dòng)做的更具有靈活性。
4)?如果有時(shí)間結(jié)余,可以關(guān)注Linux內(nèi)核的發(fā)展。譬如LCD的驅(qū)動(dòng)有沒有考慮到V4L2通用架構(gòu),譬如網(wǎng)絡(luò)驅(qū)動(dòng)用到了NAPI了嗎?當(dāng)然在此之前,假設(shè)已經(jīng)對LDD3, ULK2理解的比較熟了。
5)?現(xiàn)在所作的這些驅(qū)動(dòng)還算不得非常核心的東西。如果你想有更好的發(fā)展,可以考慮往audio,video,net方面發(fā)展,你應(yīng)該多注意真?zhèn)€行業(yè)需要什么樣的人才,上述每一項(xiàng)都需要很厚的底蘊(yùn),譬如video,需要了解MPEG4, H264等,怎么也要個(gè)1到2年才能算個(gè)入行阿,所以我建議不要只顧悶頭做東西,要適當(dāng)關(guān)注目前的一些應(yīng)用。
6)?對硬件知識的補(bǔ)給,做嵌入式Linux這一行不可能不讀硬件的Spec,如果你對硬件的工作機(jī)制理解的比較透,會有助你寫出性能好的驅(qū)動(dòng)程序。
順便提一點(diǎn),適時(shí)的提高你的英語水平,對你的職業(yè)生涯絕對有幫助。(不要等需要的時(shí)候再補(bǔ),來不及)
7)?如果有時(shí)間,平時(shí)注意對Linux應(yīng)用程序編寫的了解/積累,也將有助于你寫出很好功能很好的驅(qū)動(dòng)程序。
8)?永遠(yuǎn)不能以為自己做了很多東西,就驅(qū)動(dòng)而言,像TVIN/TVOUT, USB, SDIO等等,好多未知領(lǐng)域呢。在問題還沒有解決之前很難說清是哪里不對了。
有時(shí)候是datasheet里面的一句話沒有注意,還有好幾次調(diào)不出來最后查到是PCB的問題,所以有時(shí)候特別暈。
-END-
猜你喜歡(點(diǎn)擊下劃線閱讀)
春晚上的“拓荒牛”
芯片荒!2020年花3000億進(jìn)口芯片...
全球芯片IC設(shè)計(jì)Top10巨頭最新排名:美國包攬前三,華為跌出前十,英偉達(dá)增幅最大。
??最 后??
?若覺得文章不錯(cuò),轉(zhuǎn)發(fā)分享,也是我們繼續(xù)更新的動(dòng)力。
5T資源大放送!包括但不限于:C/C++,Linux,Python,Java,PHP,人工智能,PCB、FPGA、DSP、labview、單片機(jī)、等等!
點(diǎn)擊下方卡片,在公眾號內(nèi)回復(fù)「更多資源」,即可免費(fèi)獲取。
總結(jié)
以上是生活随笔為你收集整理的嵌入式驱动自学者的亲身感受,有什么建议?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 苹果又一最新专利公布 可利用穿戴设备进行
- 下一篇: 如何确定JTAG好坏?JTAG到底是什么