日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

【移植驱动到Linux3.4.2内核之二】LCD,触摸屏,按键,USB等驱动程序的移植心得总结

發布時間:2023/12/10 linux 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【移植驱动到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.一個個解決錯誤
    首先解決前面的錯誤,前三個錯誤都說,沒有相關頭文件,那么我們就把這三個頭文件注釋掉:

    //#include <asm/arch/regs-lcd.h> //#include <asm/arch/regs-gpio.h> //#include <asm/arch/fb.h>

    然后重新編譯:

    這里竟然直接編譯通過了,說明新的內核關于LCD的變化不大。

    3.測試驅動程序
    我們把驅動生成的.ko文件拷貝到網絡文件系統,然后還需要重新配置一下內核去掉它本身自帶的LCD的支持來驗證我們的新編譯的驅動是否可以驅動我們的LCD屏。
    配置內核:
    make menuconfig
    依次選擇:

    Device Drivers ---> Graphics support ---> <*> Support for frame buffer devices ---> <M> S3C2410 LCD framebuffer support //將這一項前面尖括號的*號改成m,這樣就去掉了內核自帶的LCD驅動

    重新編譯內核。
    編譯好內核映像后,還需要make modules,因為我們的LCD驅動程序還依賴于其他三個函數:

    static struct fb_ops s3c_lcdfb_ops = {.owner = THIS_MODULE,.fb_setcolreg = s3c_lcdfb_setcolreg,.fb_fillrect = cfb_fillrect, //下面這三個,這三個函數在三個不同的文件,我們需要把這三個文件編譯為.ko文件加載到內核才能.fb_copyarea = cfb_copyarea, //使用LCD驅動程序。.fb_imageblit = cfb_imageblit, };

    然后我把內核映像文件以及生成的三個依賴文件(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_GPF0, KEY_L},{IRQ_EINT2, "S3", S3C2410_GPF2, KEY_S},{IRQ_EINT11, "S4", S3C2410_GPG3, KEY_ENTER},{IRQ_EINT19, "S5", S3C2410_GPG11, KEY_LEFTSHIFT}, };

    改為:

    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):

    ::sysinit:/etc/init.d/rcS console::askfirst:-/bin/sh tty1::askfirst:-/bin/sh ::ctrlaltdel:/sbin/reboot ::shutdown:/bin/umount -a -r

    然后重啟系統:
    那么開發板顯示屏也會出現跟串口顯示一樣的內容,按下按鍵,可以直接操作了。按鍵驅動程序移植成功。


    四移植觸摸屏驅動程序

    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行(去掉#號和第一個空格):

    # module_raw input 改為: module_raw input

    然后設置環境變量:
    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文件中有這么一段代碼:

    static int check_fd(struct tslib_input *i) {struct tsdev *ts = i->module.dev;int version;u_int32_t bit;u_int64_t absbit;if (! ((ioctl(ts->fd, EVIOCGVERSION, &version) >= 0) &&(version == EV_VERSION) &&(ioctl(ts->fd, EVIOCGBIT(0, sizeof(bit) * 8), &bit) >= 0) &&(bit & (1 << EV_ABS)) &&(ioctl(ts->fd, EVIOCGBIT(EV_ABS, sizeof(absbit) * 8), &absbit) >= 0) &&(absbit & (1 << ABS_X)) &&(absbit & (1 << ABS_Y)) && (absbit & (1 << ABS_PRESSURE)))) {fprintf(stderr, "selected device is not a touchscreen I understand\n");return -1; } if (bit & (1 << EV_SYN))i->using_syn = 1;return 0;}

    其中關鍵的是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中的

    #define EV_VERSION 0x010001改為:#define EV_VERSION 0x010000

    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等驱动程序的移植心得总结的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。