前文回顧
《Linux驅(qū)動(dòng)開發(fā)(一)—環(huán)境搭建與hello world》
《Linux驅(qū)動(dòng)開發(fā)(二)—驅(qū)動(dòng)與設(shè)備的分離設(shè)計(jì)》
《Linux驅(qū)動(dòng)開發(fā)(三)—設(shè)備樹》
《Linux驅(qū)動(dòng)開發(fā)(四)—樹莓派內(nèi)核編譯》
《Linux驅(qū)動(dòng)開發(fā)(五)—樹莓派設(shè)備樹配合驅(qū)動(dòng)開發(fā)》
《Linux驅(qū)動(dòng)開發(fā)(六)—樹莓派配合硬件進(jìn)行字符驅(qū)動(dòng)開發(fā)》
《Linux驅(qū)動(dòng)開發(fā)(七)—樹莓派按鍵驅(qū)動(dòng)開發(fā)》
《Linux驅(qū)動(dòng)開發(fā)(八)—樹莓派SR04驅(qū)動(dòng)開發(fā)》
《Linux驅(qū)動(dòng)開發(fā)(九)—樹莓派I2C設(shè)備驅(qū)動(dòng)開發(fā)(BME280)》
《Linux驅(qū)動(dòng)開發(fā)(十)—樹莓派輸入子系統(tǒng)學(xué)習(xí)(紅外接收)》
《Linux驅(qū)動(dòng)開發(fā)(十一)—樹莓派SPI驅(qū)動(dòng)學(xué)習(xí)(OLED)》
《Linux驅(qū)動(dòng)開發(fā)(十二)—樹莓派framebuffer學(xué)習(xí)(改造OLED)》
《Linux驅(qū)動(dòng)開發(fā)(十三)—USB驅(qū)動(dòng)HID開發(fā)學(xué)習(xí)(鼠標(biāo))》
《Linux驅(qū)動(dòng)開發(fā)(十四)—USB驅(qū)動(dòng)開發(fā)學(xué)習(xí)(鍵盤+鼠標(biāo))》
繼續(xù)宣傳一下韋老師的視頻

70天30節(jié)Linux驅(qū)動(dòng)開發(fā)快速入門系列課程【實(shí)戰(zhàn)教學(xué)、技術(shù)討論、直播答疑】
內(nèi)核中目前存在了大量的設(shè)備驅(qū)動(dòng),如何能夠快速利用起來,也是驅(qū)動(dòng)工程師需要掌握的,畢竟人家都寫好了,再從頭去寫,何苦呢?
本章目的
如果我們需要在自己的linux設(shè)備上增加一個(gè)外設(shè),例如一個(gè)屏幕,一個(gè)鍵盤,首先要想到的不是去寫驅(qū)動(dòng),而是看一下系統(tǒng)有沒有帶驅(qū)動(dòng)。例如這塊SPI的TFT屏幕,驅(qū)動(dòng)芯片是ili9341。
都是學(xué)習(xí)單片機(jī)遺留下來的東西,現(xiàn)在學(xué)驅(qū)動(dòng)又能玩一波了。
尋找驅(qū)動(dòng)
那么首先要在內(nèi)核中查詢是否有該芯片的屏幕驅(qū)動(dòng)。通過在menuconfig中搜索關(guān)鍵詞ili9341,我們就發(fā)現(xiàn)了它本身已經(jīng)動(dòng)態(tài)編譯了ili9341的fb驅(qū)動(dòng),并且是支持framebuffer的。
進(jìn)入開發(fā)板看一下,連我們之前開發(fā)的ssd1306的驅(qū)動(dòng)都存在了。
不過不要覺得寫驅(qū)動(dòng)就沒有意義了,寫驅(qū)動(dòng)一方面能夠?qū)纹瑱C(jī)的知識應(yīng)用到linux上,熟悉驅(qū)動(dòng)的邏輯架構(gòu),還能夠讓你更快速的了解一個(gè)別人寫好的驅(qū)動(dòng)。萬一遇到bug,也知道從哪里入手。
設(shè)備樹
既然驅(qū)動(dòng)已經(jīng)存在了。那么按照總線設(shè)備驅(qū)動(dòng)模型,要想正常工作,就需要增加設(shè)備信息,提供給驅(qū)動(dòng)使用,才能完成設(shè)備的驅(qū)動(dòng)。
那么這個(gè)設(shè)備樹如何編寫,兩個(gè)思路,
- 參考已有的設(shè)備樹中別人怎么寫的
- 查看內(nèi)核的設(shè)備樹文檔了。
來查找一下有沒有介紹文檔
root@ubuntu:/home/pgg/shumeipai/linux/Documentation# find ./ -name "*ili9341*"
./devicetree/bindings/display/ilitek,ili9341.txt
./devicetree/bindings/display/panel/ilitek,ili9341.yaml
發(fā)現(xiàn)了描述文檔《ilitek,ili9341.txt》,內(nèi)容如下,告訴了你它是一個(gè)SPI模式控制器,需要三個(gè)關(guān)鍵參數(shù),
compatile,dc-gpios和rest-gpios,還有一個(gè)例子。
多么的貼心
那么我們就按照這個(gè)來嘗試一下修改設(shè)備樹。
然后更新一下設(shè)備樹。結(jié)果發(fā)現(xiàn)屏幕亮,但是手動(dòng)加載驅(qū)動(dòng)沒有任何反應(yīng),打印信息中也沒有看到。
在/sys/bus/spi/devices/中沒有發(fā)現(xiàn)任何spi設(shè)備。
懷疑設(shè)備樹有問題。
于是發(fā)現(xiàn)了一個(gè)對于新手來說很重要的設(shè)備樹配置
status = "okay";
在增加了這條語句之后,重新編譯設(shè)備樹,發(fā)現(xiàn)了錯(cuò)誤提示,原來剛才根本就沒有編譯上這個(gè)設(shè)備
root@ubuntu:/home/pgg/shumeipai/linux# ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make dtbs
DTC arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dtb
arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts:222.13-231.4: ERROR (phandle_references): /soc/spi@7e204000/myili9341@0: Reference to non-existent node or label "gpio0"
arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts:222.13-231.4: ERROR (phandle_references): /soc/spi@7e204000/myili9341@0: Reference to non-existent node or label "gpio0"
arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts:222.13-231.4: ERROR (phandle_references): /soc/spi@7e204000/myili9341@0: Reference to non-existent node or label "backlight"
重新修改設(shè)備樹
再次更新設(shè)備樹。能夠看到spi設(shè)備了
root@raspberrypi:/home/pgg# ls /sys/bus/spi/devices/
spi0.0
連接硬件
然后按照引腳接好電路,和之前的oled小屏幕是一樣的。
重啟設(shè)備。驅(qū)動(dòng)會(huì)自動(dòng)根據(jù)設(shè)備樹里面的描述進(jìn)行加載。直接就能顯示桌面了!真是個(gè)小驚喜。
直接就啟動(dòng)了。然后插上usb鼠標(biāo),加載上自己的驅(qū)動(dòng)。走你!沒毛病
OLED同理
之前我們的OLED是SPI的oled,還有一部分相同芯片ssd1306采用的是iic通訊,那么我們同樣可以找到相關(guān)的驅(qū)動(dòng)
以及搜索到相關(guān)的設(shè)備樹范例:
Documentation\devicetree\bindings\display\ssd1307fb.txt
改天試一下這個(gè)驅(qū)動(dòng),感覺要比自己寫的,用起來更踏實(shí)呢。
學(xué)習(xí)源碼
在drivers\staging\fbtft路徑下,我們可以看到針對大量顯示屏的驅(qū)動(dòng)源碼,這里采用了一個(gè)框架,每一種屏幕驅(qū)動(dòng),有一個(gè)私有的文件例如fb_ili9341.c,中間圍繞這一個(gè)結(jié)構(gòu)體進(jìn)行特殊配置
static struct fbtft_display display = {
.regwidth = 8,
.width = WIDTH,
.height = HEIGHT,
.txbuflen = TXBUFLEN,
.gamma_num = 2,
.gamma_len = 15,
.gamma = DEFAULT_GAMMA,
.fbtftops = {
.init_display = init_display,
.set_addr_win = set_addr_win,
.set_var = set_var,
.set_gamma = set_gamma,
},
};
每個(gè)屏幕差異的操作,由fbtftops結(jié)構(gòu)中的函數(shù)來定義,結(jié)構(gòu)中的函數(shù)會(huì)有默認(rèn)操作。
struct fbtft_ops {
int (*write)(struct fbtft_par *par, void *buf, size_t len);
int (*read)(struct fbtft_par *par, void *buf, size_t len);
int (*write_vmem)(struct fbtft_par *par, size_t offset, size_t len);
void (*write_register)(struct fbtft_par *par, int len, ...);
void (*set_addr_win)(struct fbtft_par *par,
int xs, int ys, int xe, int ye);
void (*reset)(struct fbtft_par *par);
void (*mkdirty)(struct fb_info *info, int from, int to);
void (*update_display)(struct fbtft_par *par,
unsigned int start_line, unsigned int end_line);
int (*init_display)(struct fbtft_par *par);
int (*blank)(struct fbtft_par *par, bool on);
unsigned long (*request_gpios_match)(struct fbtft_par *par,
const struct fbtft_gpio *gpio);
int (*request_gpios)(struct fbtft_par *par);
int (*verify_gpios)(struct fbtft_par *par);
void (*register_backlight)(struct fbtft_par *par);
void (*unregister_backlight)(struct fbtft_par *par);
int (*set_var)(struct fbtft_par *par);
int (*set_gamma)(struct fbtft_par *par, u32 *curves);
};
函數(shù)意義
函數(shù) | 意義 |
---|---|
write | 寫入接口總線 |
read | 從接口總線讀取 |
write_vmem | 將視頻內(nèi)存寫入顯示 |
write_reg | 寫入控制器寄存器 |
set_addr_win | 設(shè)置GRAM更新窗口 |
reset | 重置LCD控制器 |
mkdirty | 標(biāo)記要更新的顯示行 |
update_display | 更新顯示 |
init_display | 初始化顯示 |
blank | 空白顯示(可選) |
request_gpios_match | Do pinname to gpio匹配 |
request_gpios | 從內(nèi)核請求gpios |
free_gpios | 釋放以前請求的gpios |
verify_gpios | 驗(yàn)證是否存在必要的gpios(可選) |
register_backlight | 用于注冊背光設(shè)備(可選) |
unregister_backlight | 取消注冊背光設(shè)備(可選) |
set_var | 使用諸如@rotate和@bgr的變量值配置LCD(可選) |
set_gamma | 設(shè)置gamma曲線(可選) |
框架有四個(gè)核心的文件
fbtft-core.c
fbtft-bus.c
fbtft-io.c
fbtft-sysfs.c
愿意了解的可以去解讀一下。
總結(jié)思路
使用第三方驅(qū)動(dòng)外設(shè)步驟:
- 查找關(guān)鍵驅(qū)動(dòng)并啟用
- 查找相關(guān)設(shè)備樹資料
- 修改設(shè)備樹
- 編譯更新設(shè)備樹和內(nèi)核
現(xiàn)在的內(nèi)核驅(qū)動(dòng)庫相當(dāng)豐富,大部分常用的外設(shè)都能找到相關(guān)的驅(qū)動(dòng)。文章來源:http://www.zghlxwxcb.cn/news/detail-608692.html
結(jié)束語
昨晚一夜沒睡好,其實(shí)大家心里都憋著一股火氣,各種抱怨的聲音充斥著微信群,朋友圈。正所謂是愛之深,責(zé)之切,不過有些事,并不是頭腦一熱,就能夠干的。處理這些危機(jī),靠的也得是冷靜的頭腦。
無論是什么統(tǒng),那都是內(nèi)部矛盾,最后容易受傷的還是普通人。
所以要深刻認(rèn)識到,誰才是真正的壞人。
不過壞人也干了一件好事,你能去,那我也能去咯,我離得近,還能天天去。日久天長,我就不走了。文章來源地址http://www.zghlxwxcb.cn/news/detail-608692.html
到了這里,關(guān)于Linux驅(qū)動(dòng)開發(fā)(十五)---如何使用內(nèi)核現(xiàn)有驅(qū)動(dòng)(顯示屏)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!