溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Linux driver怎么配置使用

發(fā)布時間:2021-12-20 10:42:22 來源:億速云 閱讀:133 作者:iii 欄目:互聯(lián)網(wǎng)科技

本篇內(nèi)容主要講解“Linux driver怎么配置使用”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學(xué)習(xí)“Linux driver怎么配置使用”吧!

綜述

AM335x觸摸屏控制器支持如下四種工作模式:

? 8路通用的ADC

? 4路作為4線觸摸屏連接,4路作為通用ADC

? 5路作為5線觸摸屏連接,3路作為通用ADC

? 8路作為8線觸摸屏連接

ADC采用的是12位SAR ADC, 采樣速率為每秒200k次. AD采樣模擬信號是從start of conversion為高時開始并在下降沿后的1個時鐘周期內(nèi)繼續(xù)采樣. 它在采樣周期結(jié)束時捕獲模擬信號并啟動轉(zhuǎn)換. 它在12個時鐘周期內(nèi)將采樣數(shù)據(jù)數(shù)字化,當(dāng)end of conversion信號被使能為高時, 表明數(shù)據(jù)ADCOUT<11:0>已可讀. 當(dāng)以前的數(shù)據(jù)被讀取后一個新的轉(zhuǎn)換周期就可以開始了。 請注意,ADC輸出的是加權(quán)的二進制數(shù)據(jù)

一 硬件連接:

4線觸摸屏的連接

5線觸摸屏連接

8線觸摸屏連接

二 Linux driver

2.1 配置使用
Device Drivers  --->
         [*]  Staging drivers  --->
                  [*]  Industrial I/O support  ---> 
                  [*]  Enable buffer support within IIO
                  <*>     Industrial I/O lock free software ring                                                              
                  < >     Industrial I/O buffering based on kfifo
                  -*-  Enable triggered sampling support                                                                     
                  (2)     Maximum number of consumers per trigger
                       Analog to digital converters  --->
                                <*>   TI's ADC driver

這里<*> TI's ADC driver 是直接編譯進內(nèi)核, 如果只是想編譯為模塊則可以點擊空格更改為<M>

2.2 設(shè)置驅(qū)動的平臺數(shù)據(jù)(platform_data)

在arch/arm/mach-omap2/board-am335xevm.c(我的板子是board-com335x.c)里添加如下代碼:

#include <linux/platform_data/ti_adc.h>
static struct adc_data am335x_adc_data = {
        .adc_channels = 4,
};

static struct mfd_tscadc_board tscadc = {
        .tsc_init = &am335x_touchscreen_data,
        .adc_init = &am335x_adc_data,
};

如果你要同時使用adc和觸摸屏的話照上邊這樣設(shè)置即可.

如果只使用adc則要移除觸摸屏的平臺數(shù)據(jù)(platform data),如下所示:

static struct adc_data am335x_adc_data = {
        .adc_channels = 8,
};

/*     
static struct tsc_data am335x_touchscreen_data  = {
        .wires  = 4,
        .x_plate_resistance = 200,
        .steps_to_configure = 5,
};  
*/

static struct mfd_tscadc_board tscadc = {
        /*   .tsc_init = &am335x_touchscreen_data, */
        .adc_init = &am335x_adc_data,
};

三 測試

將直流電壓連接到AIN0到AIN7的引腳上(你使用了哪個就接在哪個引腳),千萬注意測試電壓只能在0~1.8v之間

3.1 查看IIO設(shè)備

root@arago-armv7:~# ls -al /sys/bus/iio/devices/iio\:device0/
drwxr-xr-x    5 root     root            0 Jan  1 00:00 .
drwxr-xr-x    4 root     root            0 Jan  1 00:00 ..
drwxr-xr-x    2 root     root            0 Jan  1 00:00 buffer
-r--r--r--    1 root     root         4096 Jan  1 00:00 dev
-r--r--r--    1 root     root         4096 Jan  1 00:00 in_voltage0_raw
-r--r--r--    1 root     root         4096 Jan  1 00:00 in_voltage1_raw
-r--r--r--    1 root     root         4096 Jan  1 00:00 in_voltage2_raw
-r--r--r--    1 root     root         4096 Jan  1 00:00 in_voltage3_raw
-r--r--r--    1 root     root         4096 Jan  1 00:00 in_voltage4_raw
-r--r--r--    1 root     root         4096 Jan  1 00:00 in_voltage5_raw
-r--r--r--    1 root     root         4096 Jan  1 00:00 in_voltage6_raw
-r--r--r--    1 root     root         4096 Jan  1 00:00 in_voltage7_raw
-rw-r--r--    1 root     root         4096 Jan  1 00:00 mode
-r--r--r--    1 root     root         4096 Jan  1 00:00 name
drwxr-xr-x    2 root     root            0 Jan  1 00:00 power
drwxr-xr-x    2 root     root            0 Jan  1 00:00 scan_elements
lrwxrwxrwx    1 root     root            0 Jan  1 00:00 subsystem -> ../../../../../../bus/iio
-rw-r--r--    1 root     root         4096 Jan  1 00:00 uevent

3.2 單次模式

檢查ADC模式, 如下所示即為單次模式

cat /sys/bus/iio/devices/iio\:device0/mode
oneshot

如果不是單次模式可以使用如下命令更改

Echo onesht > /sys/bus/iio/devices/iio\:device0/mode

從某一端口讀取ADC輸出數(shù)據(jù):

in_voltageX_raw: raw value of the channel X of the ADC

從以下命令可知in_voltageX_raw里保存的就是ADC的原始數(shù)據(jù), 4095即滿量程數(shù)據(jù)

root@arago:~# cat /sys/bus/iio/devices/iio\:device0/in_voltage0_raw
4095

四 計算結(jié)果

D = Vin * (2^n - 1) / Vref

比如讀取回來ADC的數(shù)據(jù)是2298那么輸入電壓就是

Vin = D / ((2^n - 1) / Vref)

Vin = 2298 / ((2^12 – 1) / 1.8)

Vin = 1.01V

相關(guān)資料:

1 AM335x ADC Driver's Guide http://www.deyisupport.com/question_answer/w/faq/469.am335x-linux.aspx

2 AM335X 觸摸屏的硬件連接及Linux驅(qū)動

http://ti.eetop.cn/viewnews-4453

3 Using resistive touch screens for human/machine interface

http://www.ti.com/lit/an/slyt209a/slyt209a.pdf

input子系統(tǒng)

因為觸摸屏使用的是input子系統(tǒng)所以要講解觸摸屏之前首先要講解一下input子系統(tǒng), 它的核心文件是input.c

Input子系統(tǒng)結(jié)構(gòu)與功能實現(xiàn)

1 Input子系統(tǒng)是分層結(jié)構(gòu)的,總共分為三層: 硬件驅(qū)動層,子系統(tǒng)核心層,事件處理層。 

(1)其中硬件驅(qū)動層負(fù)責(zé)操作具體的硬件設(shè)備,這層的代碼是針對具體的驅(qū)動程序的,需要驅(qū)動程序的作者來編寫

(2)子系統(tǒng)核心層是鏈接其他兩個層之間的紐帶與橋梁,向下提供驅(qū)動層的接口,向上提供事件處理層的接口

(3)事件處理層負(fù)責(zé)與用戶程序打交道,將硬件驅(qū)動層傳來的事件報告給用戶程序

2各層之間通信的基本單位就是事件,任何一個輸入設(shè)備的動作都可以抽象成一種事件,如鍵盤的按下,觸摸屏的按下,鼠標(biāo)的移動等。事件有三種屬性:類型(type),編碼(code),值(value),Input子系統(tǒng)支持的所有事件都定義在input.h中,包括所有支持的類型,所屬類型支持的編碼等。事件傳送的方向是 硬件驅(qū)動層-->子系統(tǒng)核心-->事件處理層-->用戶空間

3 以觸摸屏為例說明輸入子系統(tǒng)的工作流程:

     注:am335x sdk6的觸摸屏驅(qū)動所用驅(qū)動層對應(yīng)的模塊文件為:ti_tsc.c,事件處理層對應(yīng)的模塊文件為 evdev.c

    (1)ti_tsc模塊初始化函數(shù)中將觸摸屏注冊到了輸入子系統(tǒng)中,于此同時,注冊函數(shù)在事件處理層鏈表中尋找事件處理器,這里找到的是evdev,并且將驅(qū)動與事件處理器掛載。并且在/dev/input中生成設(shè)備文件event0,以后我們訪問這個文件就會找的我們的觸摸屏驅(qū)動程序。

    (2)應(yīng)用程序打開設(shè)備文件/dev/input/event0,讀取設(shè)備文件,調(diào)用evdev模塊中read,如果沒有事件,進程就會睡眠。  

    (3)當(dāng)觸摸屏按下,驅(qū)動層通過input子系統(tǒng)核心層將事件(就是X,Y坐標(biāo), 壓感, 按下/松開)傳給事件處理層也就是evdev,evdev喚醒睡眠的進程,將事件傳給進程處理。

下邊看下代碼流程:

input_init()
         class_register
register_chrdev(INPUT_MAJOR, "input", &input_fops);
可以看到input子系統(tǒng)幫我們寫了以上兩個函數(shù), 那么這個input_fops是不是就是我們要填充的file_operations呢?
static const struct file_operations input_fops = {
         .owner = THIS_MODULE,
         .open = input_open_file,
         .llseek = noop_llseek,
};

這個file_operations并沒有read/write等接口, 由此我們可知該結(jié)構(gòu)體只是一個連接上下層的作用, 這是一種分層的思想. 那么他就是通過open成員來連接上下層, 我們來看下open成員做了什么事情:

input_open_file
        handler = input_table[iminor(inode) >> 5];//使用此設(shè)備號拿到handler結(jié)構(gòu)體
        new_fops = fops_get(handler->fops);      //獲取新的file_operations
        file->f_op = new_fops;                             //使用handler的fops成員來作為新的file_operations
        new_fops->open(inode, file);                   //handler->fops->open(indoe, file)

由此可知: 通過次設(shè)備號拿到數(shù)組中的handler成員, 就完成了上層的input_fops到底層的真實handler->fops的轉(zhuǎn)換,

底層的handler->fops->open(indoe, file) 就是真實的open, 對應(yīng)的read/write也是

現(xiàn)在最關(guān)鍵的就是input_table[]數(shù)組是怎么來的呢?  

通過查找代碼發(fā)現(xiàn)在 input_register_handler里使用了它, 那么誰調(diào)用了這個函數(shù)呢? 在input子系統(tǒng)的下邊有很多驅(qū)動都用到了這個函數(shù), 他們首先查找有沒有能匹配的硬件,如果有就調(diào)用這個函數(shù)將input_handler放入數(shù)組里邊.

這些驅(qū)動在以下的軟件部分可以看到:

軟件部分

Evdev.c  Joydev.c Keyboard.c Mousedev.c等這些就是input子系統(tǒng)向上注冊input_handler

input_register_handler
         input_attach_handler  判斷硬件的id_table能否與自己的id_table匹配, 如果匹配這建立連接

硬件部分:

input_register_device
         input_attach_handler   判斷軟件的id_table能否與自己的id_table匹配, 如果匹配這建立連接

device和handler在注冊的時候都會查找對方是否有可以與自己匹配的, 如果有就調(diào)用connect函數(shù)來連接彼此.

下邊以evdev.c為例來說明軟硬件兩部分是如何建立連接的:

evdev_connect()
         evdev->handle.dev = input_get_device(dev);
         evdev->handle.handler = handler;

在evdev.c中又創(chuàng)建了一個handle結(jié)構(gòu)體他分別指向device和handler, 這樣軟硬件兩邊通過這個結(jié)構(gòu)體找到對方.

Am335x的sdk6中觸摸屏的驅(qū)動文件

一 arch/arm/mach-omap2/board-com335x.c        板級初始化

static struct tsc_data am335x_touchscreen_data  = {
         .wires  = 4,                            //4線觸摸屏
         .x_plate_resistance = 200,     //阻抗200歐姆
         .steps_to_configure = 5,        //在產(chǎn)生中斷之前在fifo中的樣本個數(shù), 最大16
};

二 drivers/input/touchscreen/ti_tsc.c         驅(qū)動文件

ti_tsc_init
         platform_driver_register (&ti_tsc_driver);
tscadc_probe
         input_allocate_device  //分配

request_irq
         input_dev->name = "ti-tsc";  //設(shè)置
         input_dev->dev.parent = &pdev->dev;
         input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);//可以產(chǎn)生按鍵類事件/絕對位移類事件
         input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);//觸摸屏觸摸屏事件
         input_register_device//注冊

中斷處理函數(shù)

tscadc_interrupt
         tscadc_readl 讀取中斷狀態(tài)寄存器, adc與tsc共用一個中斷源
         判斷中斷原因然后上報事件
         input_report_abs(input_dev, ABS_X, val_x);//x坐標(biāo)
         input_report_abs(input_dev, ABS_Y, val_y);//y坐標(biāo)
         input_report_abs(input_dev, ABS_PRESSURE, z);//壓感
         input_report_key(input_dev, BTN_TOUCH, 1);//按下/松開
         input_sync(input_dev);

         檢查是否是抬起中斷
         status = tscadc_readl(ts_dev, TSCADC_REG_RAWIRQSTATUS);
         if (status & TSCADC_IRQENB_PENUP)
             input_report_key(input_dev, BTN_TOUCH, 0);
             input_report_abs(input_dev, ABS_PRESSURE, 0);
             input_sync(input_dev);

到此,相信大家對“Linux driver怎么配置使用”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進入相關(guān)頻道進行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI