【移植驱动到Linux3.4.2内核之二】LCD,触摸屏,按键,USB等驱动程序的移植心得总结
學習交流加
- 個人qq:
1126137994 - 個人微信:
liu1126137994 - 學習交流資源分享qq群:
962535112
文章目錄
- 一移植驅動程序心得體會
- 二移植LCD驅動程序記錄
- 三移植按鍵輸入子系統驅動程序
- 四移植觸摸屏驅動程序
- 五移植USB驅動程序
今天移植了按鍵,LED,LCD,觸摸屏等驅動程序,移植驅動程序相對于寫驅動程序,就簡單得多,前提是得理解驅動程序。
現在來大體總結一下如何移植一個新的驅動程序(不是內核自帶的驅動程序)的大體思路以及流程。
一移植驅動程序心得體會
首先呢,我們拿到一個新的驅動程序,直接先拿過來編譯(先修改Makefile關于內核的路徑),編譯后,一般都會報錯,因為我們的驅動程序,一般不是針對我們這個內核來寫的,報錯了不要怕,我們一個一個解決。
錯誤一般不會太難解決,因為驅動程序關于硬件的操作,都是完全一樣的,除非你用的硬件都不一樣,那樣就得換驅動程序了。一般的錯誤不會涉及修改硬件的操作,一般都是因為新的內核里面某些函數的名字變了,或者某些函數的定義的形式變了,比如以前是一堆函數在定義,但是有可能在新內核中,這些函數有可能會統一放到一個結構體或者數組中被定義。也有可能這個函數的名字稍微有所變化,也或者是頭文件的名字變了,或者缺少了某些頭文件。總的來說,大概的錯誤就是以下幾種:
錯誤:
1.1 頭文件不對:去掉或改名
1.2 宏不對:改名使用新宏
1.3 有些函數沒有了:改名使用新函數
當我們遇到這樣的錯誤,如果不會解決,就去參考內核中類似的驅動程序,看看別人是怎么實現這些我們錯誤的功能的,,記住,參考內核源碼,是一個非常好的辦法,隨著經驗的提高,這個方法一定要越來越熟悉。然后大概的解決辦法,就是上面所說的幾種。
之前移植過LED驅動程序,按鍵等,下面給出一兩個移植的過程記錄,方便以后查閱復習
二移植LCD驅動程序記錄
1.直接編譯
首先把我們的LCD的驅動程序以及它的Makefile拿到Linux系統編譯,需要將Makefile里依賴的內核目錄的路徑修改為當前使用的內核路徑,然后直接make編譯,肯定會報錯:
2.一個個解決錯誤
首先解決前面的錯誤,前三個錯誤都說,沒有相關頭文件,那么我們就把這三個頭文件注釋掉:
然后重新編譯:
這里竟然直接編譯通過了,說明新的內核關于LCD的變化不大。
3.測試驅動程序
我們把驅動生成的.ko文件拷貝到網絡文件系統,然后還需要重新配置一下內核去掉它本身自帶的LCD的支持來驗證我們的新編譯的驅動是否可以驅動我們的LCD屏。
配置內核:
make menuconfig
依次選擇:
重新編譯內核。
編譯好內核映像后,還需要make modules,因為我們的LCD驅動程序還依賴于其他三個函數:
然后我把內核映像文件以及生成的三個依賴文件(cfb*ko)拷貝到網絡文件系統,燒寫內核重啟開發板:
設置環境參數:
set bootargs console=ttySAC0,115200 root=/dev/nfs nfsroot=192.168.1.101:/work/nfs_root/fs_mini_mdev_new ip=192.168.1.104:192.168.1.101:192.168.1.1:255.255.255.0::eth0:off
保存環境參數:
save
燒寫內核
nfs 30000000 192.168.1.101:/work/nfs_root/uImage_nolcd; bootm 30000000
啟動后,先裝載cfb*ko文件,然后裝載lcd.ko文件,然后用測試程序測試是否可以操作顯示屏。一切正常,移植完畢!!!
三移植按鍵輸入子系統驅動程序
1.直接編譯
同上lcd驅動的編譯先修改Makefile后直接編譯:
2.改錯誤
第一個錯誤:沒有某個頭文件,那就直接先注釋掉。
第二到五的錯誤:沒有定義那個宏,通過搜索內核相關類似驅動程序以及類似函數的用法,得知,應該將下面的結構體:
改為:
struct pin_desc pins_desc[4] = {{IRQ_EINT0, "S2", S3C2410_GPF(0), KEY_L},{IRQ_EINT2, "S3", S3C2410_GPF(2), KEY_S},{IRQ_EINT11, "S4", S3C2410_GPG(3), KEY_ENTER},{IRQ_EINT19, "S5", S3C2410_GPG(11), KEY_LEFTSHIFT}, };第六個錯誤:說是下面的IRQT_BOTHEDGE沒有定義,可能是新內核的這個標志有所變化(雙邊沿觸發):
request_irq(pins_desc[i].irq, buttons_irq, IRQT_BOTHEDGE, pins_desc[i].name, &pins_desc[i]);搜索內核中request_irq函數的相通用法(注意搜索范圍可以縮小到/drivers/char目錄),最終查到可以用下面的代替:
request_irq(pins_desc[i].irq, buttons_irq, (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING), pins_desc[i].name, &pins_desc[i]);先解決這上面的幾個錯誤,重新編譯:竟然編譯成功了!!!這說明后面沒有看的錯誤,其實是由前面的錯誤導致的。
3.測試驅動程序
我們把文件系統中/etc/inittab修改為(加一行:tty1::askfirst:-/bin/sh):
然后重啟系統:
那么開發板顯示屏也會出現跟串口顯示一樣的內容,按下按鍵,可以直接操作了。按鍵驅動程序移植成功。
四移植觸摸屏驅動程序
1.直接編譯:
2.改錯誤
這次我們的錯誤比較簡單,只需要把上面沒有的頭文件注釋掉就行,然后重新編譯。
3.tslib測試觸摸屏
我們用tslib這個應用程序庫來校準測試觸摸屏。
首先我們按照下面的步驟編譯tslib的庫:
編譯:
tar xzf tslib-1.4.tar.gz
cd tslib
./autogen.sh
mkdir tmp
echo “ac_cv_func_malloc_0_nonnull=yes” >arm-linux.cache
./configure --host=arm-linux --cache-file=arm-linux.cache --prefix=$(pwd)/tmp
make
make install
安裝tslib庫:
cd tmp
cp * -rf /work/nfs_root/fs_mini_mdev_new/
然后修改添加好的ts庫的文件系統的配置文件:
修改 /etc/ts.conf第1行(去掉#號和第一個空格):
然后設置環境變量:
export TSLIB_TSDEVICE=/dev/event1
export TSLIB_CALIBFILE=/etc/pointercal
export TSLIB_CONFFILE=/etc/ts.conf
export TSLIB_PLUGINDIR=/lib/ts
export TSLIB_CONSOLEDEVICE=none
export TSLIB_FBDEVICE=/dev/fb0
校準:
然后輸入:
ts_calibrate
然后顯示如下:
selected device is not a touchscreen I understand
看來是遇到了錯誤,去百度搜索關鍵字,最終得知:
原因非常簡單:tslib中的輸入系統和內核input系統版本不匹配,當然也有其他原因,不過這是最常見的情況,先分析一下tslib代碼,觀察這句話在什么情況下被打印就知道了。
將tslib庫中c和H文件加入Source Insight,跟蹤源碼發現,在 input-raw.c文件中有這么一段代碼:
其中關鍵的是version == EV_VERSION這個判斷語句(可以通過注釋法測試到底是哪個判斷語句導致的打印語句),如果這倆不等,那么就會打印出selected device is not a touchscreen I understand。
tslib中的input版本號是在交叉編譯的時候指定的,賦值給version,而EV_VERSION是在內核中定義,筆者做tslib時,用的2.6.39內核,這個EV_VERSION定義在include/linux/input.h中,值是0x010001,而tslib中的version是和交叉編譯器相同,查看編譯器,在/work/tools/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/include/linux/input.h中,值是0x010000,這倆明顯不相等,當然不會滿足version == EV_VERSION,所以導致錯誤。
解決辦法:
以下提供兩種解決方法
1.將內核源代碼里的include/linux/input.h中的
2.將arm交叉編譯工具中的頭文件庫中的
linux/input.h中的#define EV_VERSION 0x010000改為#define EV_VERSION 0x010001然后再編譯tslib庫我們選用第二種。
然后重新編譯tslib庫:
make clean
make
make install
然后將庫拷貝到網絡文件系統。
修改配置文件以及設置環境變量(如上同)
然后校準輸入:
ts_calibrate
可以正常校準觸摸屏了。
輸入:ts_test可以在屏幕上進行畫圓。
以上操作,說明觸摸屏驅動程序,以及校準程序,都可以正常使用。
五移植USB驅動程序
我們之前寫過簡單的USB鼠標驅動程序,實現鼠標左鍵輸出字符“l”,右鍵輸出字符“s”,中鍵輸出回車。
跟上面的一樣,直接編譯USB驅動程序,出現以下錯誤:
去源碼中看錯誤的行出現在:
usb_buf = usb_buffer_alloc(dev, len, GFP_ATOMIC, &usb_buf_phys);。。。。。。。。。。。。usb_buffer_free(dev, len, usb_buf, usb_buf_phys);錯誤說沒有定義usb_buffer_alloc和usb_buffer_free,通過查找,找到如下內容:
/* Compatible macros while we switch over */ static inline void *usb_buffer_alloc(struct usb_device *dev, size_t size,gfp_t mem_flags, dma_addr_t *dma) {return usb_alloc_coherent(dev, size, mem_flags, dma); }static inline void usb_buffer_free(struct usb_device *dev, size_t size,void *addr, dma_addr_t dma) {return usb_free_coherent(dev, size, addr, dma); }說明,新的內核中,沒有直接定義usb_buffer_alloc與usb_buffer_free,而是讓他們返回usb_alloc_coherent和usb_free_coherent,所以我們將usb_buffer_alloc與usb_buffer_free分別替換為:usb_alloc_coherent和usb_free_coherent,應該就可以了!!!!
重新編譯,成功!!!!
測試步驟較簡單,省略!!!
好了經過以上的分析過程,自己對這種非內核自帶的驅動程序的移植,有了一定的理解與掌握,相信以后隨著經驗的豐富,會更加熟練!!!
想一起探討以及獲得各種學習資源加我(有我博客中寫的代碼的原稿):
qq:1126137994
微信:liu1126137994
可以共同交流關于嵌入式,操作系統,C++語言,C語言,數據結構等技術問題。
總結
以上是生活随笔為你收集整理的【移植驱动到Linux3.4.2内核之二】LCD,触摸屏,按键,USB等驱动程序的移植心得总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【C语言进阶深度学习记录】三十七 C/
- 下一篇: linux _max_path,[apu