一、 led驅動的實現原理:
通過GPC0_3和GPC0_4引腳的高低電平來控制三極管的導通性,從而控制LED燈亮滅。
盡管 Linux 驅動直接與硬件打交道,但并不是 Linux 驅動直接向硬件中的內存寫數據, 而是與本機的I0內存(I/O Memory,位于內核空間〉進行交互。所謂 1/0 內存是通過各種接口( PCI、 USB、藍牙、以太網口等〉連接到主機( PC、手機〉的硬件〈網卡、聲卡、攝像頭等〉在主機內存中的映射。
二、 編寫led驅動
1>首先我們需要感受一下led驅動的結果:
測試 LED 驅動之前需要用 USB 數據線連接 S3C 開發板,然后打開 S3C 開發板的電源開關。成功啟動后,執行 build.sh腳本文件編譯和安裝 LED 驅動。如果一切順利,build. sh腳本文件會自動將 s3c6410_leds.ko 文件上傳到 S3C 開發板并安裝.
可以用下面的命令控制開發板上的 LED:
adb shell ”echo ‘1’ > /dev/s3c6.410_leds' #打開第 1 個 LEO,其他的 LED 都關閉
adb shell ” echo’ 1010 ’> /dev/s3c6410_leds' #第 1 個和第 3 個 LED 打開,第2個和 第 4 個 LED 關閉
2>其次:創建 LED 驅動的設備文件,步驟如下:
第1步:使用 cdev_init 函數初始化 cdev:
描述設備文件需要一個 cdev 結構體.cdev 的大多數成員變量并不需要我們自己去初始化, 只要調用 cdev init 函數就可以初始化大 部分 cdev 的成員變量。
第 2 步:指定設備號
Linux 設備文件的設備號分為主設備號和次設備號。用 1 個 int類型(devt)表示。其中前 12 位表示主設備號,后 20 位表示次設備號。設備號有如下兩種指定方法:
1、直接在代碼中指定(硬編碼〉
2、動態分配。
i.nt alloc_c hrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name) 其中,dev 表示設備號指針〈就是個int 指針), .alloc_chrdev_region函數會隨機分配-個未使用的主設備號,并根據baseminor參數值分配次設備號。
如果直接指定設備號,需要使用register_chrdev_region函數注冊字符設備區域。
一般采用分別指定主設備號和次設備號的方式指定設備號,因此需要 MKDEV宏將主設備號和次設備號組合成設備號,代碼如下:
// major 表示主設備號, minor表示次設備號
int dev_number =MKDEV(m:ajor, minor) ;
可以分別使用 MAJOR和 MiNOR宏從設備號中獲取主設備號和次設備號,代碼如下:
// 獲取主設備號
int major=MAJOR(dev_number);
// 獲取次設備號
int minor= MAJOR(dev number);
第 3步:使用 cdev_add函數將字符設備添加到內核中的字符設備數組中
cdev_add函數用于將字符設備添加到 probes數組〈保存己建立的字符設備〉中。
第 4 步: 使用 class_create宏創建 struct class
struct class 包含了一些與設備文件有關的變量以及一些回調函數指針變量。
第 5 步:使用 device_create 函數創建設備文件
使用下面的代碼調甩device_create 函數創建設備文件。
device create(leds class, NULL, dev number, NULL, DEVICE NAME);
其中 leds class 表示 struct class, dev number表示設備號,DEVICE NAME 表示設備文件的名稱。
3>卸載 LED 驅動的設備文件
卸載 Linux 驅動的設備文件稍微簡單-些,需要依次調用 device_destroy、class_destroy 和 unregister_chrdev_region 方法。
4>設置寄存器與初始化 LED 驅動
ARM 處理器有多個寄存器,通過設置不同寄存器的值。可以設置 LED 引腳的狀態、打開或禁止上拉(pull-up)電路以及控制 LED 的亮和滅。
注意:
LED 有兩個引腳: GPBO 和 GPBI 。其中一個引腳連接到了 ARM 處理器的 GPIO 端口,另 一個引腳經過一個限流電阻連接到電源: VCC3 上。。當 GPIO 端口為低電平時, LED 兩端產生電壓差,這時 LED 有電流通過并發光;反之當 GPIO 端口為高電平時, LED 中沒有電流通過, LED 將 熄滅。
控制 LED 需要通過 3個寄存器來完成。這 3個寄存器是GPMCON (端口配置寄存器〉、 GPMDAT (端口數據寄存器)和 GPMPUD (端口上拉電路寄存器〉。
每一個寄存器可以使用 4個字節,也就是一個int型類型數據占用的空間。
使用 GPMCON 寄存器的低 16 位將 LED 的兩個端口( GPBO 和 GPB l )的屬性,設為 Output。
使用 GPMDAT 寄存器的低 4 位控制 4 個 LED 的亮、滅。
使用 GPMPUD 寄存糕的低 8 位分別打開 4 個 LED 的上拉( pull-up)電路。
一般需要在LED驅動加載時初始化以上3個寄存器。先編寫一個初始化函數--à在 leds_init 函數中調用leds_init_gpm 函數就可以完成寄存器的初始化。
5>控制 LED
LED 驅動可以使用如下兩種方式控制 LED:1、通過字符串控制 LE D; 2、通過 l/0命令控制 LED ;
其次:LED 驅動必須要接收相應的數據。 如果通過字符串控制 LED。需要使用. fif.e_operations.write函數。如果通過 I/0命令控制 LED, 需要使用 file__operations.iocdl函數。
6> LED 驅動的模塊參數
使用一個模塊參數:Linux 驅動指定一個模塊參數需要使用 module_param Cname, type, perm)宏。其中 name 表示參數名, type 表示參數類型, perm表示讀/寫權限。
module_param 支持的參數類型包括 byte、 short、 ushort (無符號 short)、 int、 uint (無符號 int〕、 long、 ulong (無符號 long)、 charp (字符指針)、 bool 和 invbool (布爾的反)。
因此:修改 LED 驅動的代碼,為 LED 驅動添加一個模塊參數:
首先要定義一個保存模塊參數值的變量(leds_state),--àmodule_param 宏指定模塊參數的相關信息--à修改 leds_init 函數的代碼;將leds_init_gpm 函數的參數值改成leds_state (因為模塊參數值和LED 驅動控制lED的規則正好相反)。
擴展:
使用下面的命令可以測試 LED 驅動的模塊參數:
# adb shell insmod /data/1ocal/s3c6410_leds.ko leds_state=3 點亮靠近電池的兩個 LED
使用下面的命令可以看到leds_state文件的內容為3 :
# adb shell cat /sys/module/s3c6410_leds/parameters/leds_state
使用下面的命令可以將 leds_state文件的內容改為 5
# adb shel l ’echo 5 > /sys/module/s3c6410_leds/parameters/leds_ state’修改 leds_state文件的內容后。在LED驅動代碼中的leds_state值會變成5.
使用模塊參數我們需要注意:
1. 通過module_param_array宏的第3個參數指定數組長度時使用指針類型的數據;
2. 如果linux驅動含有多個模塊參數,需要將這些參數用單引號或雙引號括起來;
3. 指定數組類型的參數值,逗號前后不能空格。
7>led燈完整代碼的編寫。
三、 測試led驅動
在本章學習過程中,前面已經提到過測試方法,此處為更復雜的方法:可以向 LED 設備文件發送字符串,還可以發送 I/0 控制命令。其測試方式包括可執行程序測試、 NDK 測試和 Java 測試。
1> 編寫測試 I/O 控制命令的通用程序
LED 驅動有兩種與設備文件交互的方式:
分別為:直接寫入字符串數據和I/O控制命令。
其中直接向設備文件寫入數據可以使用命令行方式來完成,也可以通過 write 函數來完成。但 I/0 控制命令只能通過 iocll 函數發出。
注意:編譯android源代碼有很多方法,例如:使用獨立的交叉編譯器、AndroidADK等。如果利用android源代碼編譯,要保證本機上有Android源代碼,并且在<Android混代碼>/development目錄為ioctl 目錄建立一個符號鏈接,符號鏈接名必須是ioctl。
1.在ioctl 目錄有一個 build_android.sh腳本文件,讀者可以直接運行這個腳本文件利用Adroid 源代碼編譯 ioctl【前提:按照build_android.sh文件中的路徑確定android源代碼的位置,或者修改build_android.sh文件中的Android源代碼路徑】-----à先編譯 test_ioctl文件----à將生成的ioctl文件上傳到開發板的“/data/local”目錄,最后執行ioctl命令。
注意:ioctl 的命令行參數必須至少有3 個 (多余的被忽略〉,如果命令行參數小于 3 個,會輸出ioctl 命令的用法提示。
2.在開發板上運行的可執行文件同樣可以在 eclipse集成環境中開發。由于ioctl是通用的,因此,應該為每一個需要測試的程序單獨建立1個 Eclipse 工程,當我們測試一個程序時,例如:led。我們需要建立一個eclipse目錄,用于存放eclipse工程的相關內容。另外,還需要為每一個測試程序單獨建立1個腳本文件,其最后一條命令為 ioctl命令傳遞了3個參數,該條命令如下:
adb shell ‘/data/loctal/ioctl /dev/s3c6410_leds 1 .2'//將第三個led點亮。
2> 使用 NDK 測試 LED 驅動
NDK 程序測試和可執行程序測試差不多。只不過 NDK Library 可以被 Java 程序調用,而在 Android 系統中的可執行程序在非 root 狀態下是無法直接被調用的。所以如果想在 Android 應用程序中測試 Linux 驅動, 最直接的方法就是使用 NDK。
3> 使用 Java 測試 LED 驅動
由于 JDK 未提供發送I/O命令的 API,因此使用 Java 只能通過發送控制字符串測試 LED 驅動。
四、 Led驅動移植
Android 系統能否正常運行,在很大程度上 取決于 Android 能否識別當前設備的硬件,例如,顯示屏、 Wi-Fi、 GPS、 GSM、藍牙、各種傳感器等,識別這些設備的工作主要由 Linux 驅動完成。而 Linux 驅動必須要在當前使用的 Linux 內核下編譯才可以安裝在當前的 Linux 或 Android 系統中。LED 驅動最簡單的移植就是將其在不同 Linux內核版本下進行編譯。
例如:以led驅動為例:
LED 驅動是通過設置 GPMDAT 寄存器來控制 LED 的亮滅的。 GPMDAT 寄存器的低 4位分別控制 4個 LED 。 0 表示打開 LED, 1 表示關閉 LED。這是在 OK64 1 0 開發板上的設置。如果要將 LED 驅動移植到另外基于 S3C6410 的開發版上,而這個目標開發板上恰好與 OK6410 開發板的 GPMDA1、寄存器的低 4 位表示的含義相反,也就是說, 1 表示打開 LED,0 表示關閉 LED, 那么 LED 驅動的代碼就要做相應的改變。首先要改變的就是 leds_init 函數。在 LED 驅動裝載后,會 用 OxE 設置 4個 LED 的默認狀態. 而在新的開發板上,就要將 OxE 變成 Oxl.
我們還需要修改控制 LED 的代碼,例如,下面的代碼用于發送控制字符串。需要將生成開關 LED 的代碼互換位置。
注意:移植linux有一條非常重要,就是在修改Liunx驅動的源代碼時應盡量不修改linux驅動接口。
上一篇:Android JNI用于驅動測試
下一篇:android休眠喚醒驅動流程分析
- 熱門資源推薦
- 熱門放大器推薦
設計資源 培訓 開發板 精華推薦
- RD-350,用于蜂窩電話的 5W、5V 交流轉直流單輸出電源的參考設計
- 使用 Microchip Technology 的 LM285EOA-1.2 的參考設計
- AKD5357-B,AK5357 24 位 Delta-Sigma ADC 評估板
- MAXREFDES220#:智能指尖式心率計及脈搏血氧儀,具備信號處理功能
- STEVAL-ISA069V1,使用 ST1S31 的演示板,3 A / 1.5 MHz 降壓同步開關穩壓器
- 老璇退坑鍵盤V2
- 【ART-Pi】RT-THREAD
- puzzle level 8(益智拼圖)
- LTC2208IUP 演示板,CMOS 輸出,130Msps,16 位 ADC,70MHz
- 使用 LT3045IMSE 并聯多個使用 ILIM(電流監視器)的器件以消除鎮流器電阻壓降的典型應用