寫這些東西還真是花時間啊,繼續昨天的內容。
我寫驅動的時候總希望能找到乙個樣例參考一下,可惜網上的例子基本找不到。還好友善之臂的文件裡有些例子,但是說的很不詳細,要是直接輸入會有很多的編譯錯誤。我的這個例子是乙個控制led的例子,用linux就控制led,當然是相當的弱智的哈哈。我用的是s3c2410,led連線在gpb7~10上,灌電流方式驅動,io配置暫存器gpbcon的實體地址0x56000010,io資料暫存器gpbdat的實體地址0x56000014。程式中的幾個關鍵點,在我昨天的blog中有敘述。
首先編寫乙個叫做leds_test.c的檔案,內容如下:
#include
#include
#include
#include
#include
#include
//please configure your kernel first to use the following headers, because the directory "asm" is a short cut to your arch's "asm" directory.
//so do the headers in the "hardware" sub directory.
#include //this header is for ioremap(), iounmap().
#include //this header is for get_user(), put_user().
#define name "led_test"
module_author("lu xianzi <
[email protected]>"); //this line and the following 4 lines can be omitted.
module_description("led test driver");
module_license("gpl");
module_param(major, int, 0);
module_parm_desc(major, "major device number");
static int major = 231; //define device major
unsigned long * preg; //definition of register base.
static ssize_t led_test_write(struct file *file, const char __user *data, size_t len, loff_t *ppos)
static ssize_t led_test_read(struct file *file, char __user *buf, size_t len, loff_t *ppos)
static int led_test_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
return 1; }
static int led_test_open(struct inode *inode, struct file *file)
static int led_test_release(struct inode *inode, struct file *file)
static struct file_operations led_test_fops = ;
static int __init led_test_init(void)
preg = ioremap(0x56000010, 0x20);
printk("virtual addr base = 0x%lx/n", (unsigned long)preg);
tmp = * (volatile unsigned long *)preg;
printk("gpbcon = 0x%lx/n", tmp);
tmp = * (volatile unsigned long *)(preg + 1);
printk("gpbdat = 0x%lx/n", tmp);
printk("seting led test driver.../n");
* (volatile unsigned long *)preg = 0x155555;
* (volatile unsigned long *)(preg + 1) = 0xfff;
tmp = * (volatile unsigned long *)preg;
printk("gpbcon = 0x%lx/n", tmp);
tmp = * (volatile unsigned long *)(preg + 1);
printk("gpbdat = 0x%lx/n", tmp);
printk("led test driver initiated./n");
return 0; }
static void __exit led_test_cleanup(void)
module_init(led_test_init);
module_exit(led_test_cleanup);
在驅動程式的目錄下建立乙個名為「makefile」的檔案,其內容只有一行:
obj-m := leds_test.o
編譯之,我的linux核心存在/home/lxz/linux-2.6.11.7,所以編譯命令為
make -k -c /home/lxz/linux-2.6.11.7 subdirs=$pwd modules
編譯後生成幾個檔案,其中leds_test.ko是我們需要的驅動模組。
然後在另外乙個目錄中編寫乙個叫做leds.c的檔案,其內容如下
#include
#include
int main(int argc, char **argv) ;
unsigned long tmp;
if (argc != 3 || sscanf(argv[1], "%d", &led_no) != 1 || sscanf(argv[2], "%d", &on) != 1 || on < 0 || on > 1 || led_no < 0 || led_no >3)
fd = open("/dev/leds", o_rdwr);
if (fd < 0)
ioctl(fd, on, led_no);
write(fd, buf, 10);
read(fd, buf, 4);
tmp = buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[3] << 24);
printf("user program read: gpbdat = 0x%lx/n", tmp);
close(fd);
return 0;}
編譯之,輸入
arm-linux-gcc -o leds leds.c
然後把生成的leds_test.ko和leds這2個檔案拷貝到你的檔案系統中,如/home下,啟動linux。之後的過程如下:
/ # cd /home
/home # insmod leds_test.ko
lxz led test driver.
virtual addr base = 0xc485e010
gpbcon = 0x44555
gpbdat = 0x540
seting led test driver...
gpbcon = 0x155555
gpbdat = 0x7ff
led test driver initiated.
/home # mknod /dev/leds c 231 0
/home # ./leds 0 1
led test driver opened!
led test - ioctl: param 1 0
gpbcon = 0x155555
gpbdat = 0x77f
led test - write: user_data 1234567890
led test - read
user proled test driver released!
gram read: gpbdat = 0x77f
/home #
這裡有個非常有趣的事情,你會發現核心的printk函式比客戶程式的printf函式列印時出現一些混亂,我想應該是因為linux不是乙個實時系統,核心和使用者程式分時執行的結果。
如果要解除安裝驅動模組,如下:
/ # rmmod leds_test
led test driver unloaded!
/ #
Linux2 6塊裝置驅動程式
一 塊裝置的操作的處理體系結構 1.vfs 虛擬檔案系統 vfs位於塊裝置的處理體系結構的上層,提供乙個通用的檔案模型。vfs和塊裝置的關係見linux2.6裝置管理 系統呼叫的服務例程呼叫乙個合適的vfs函式,將檔案描述符和檔案內的偏移量傳遞給它。2.磁碟快取記憶體 vfs函式確定所請求的資料是否...
linux2 6字元裝置驅動開發模板
cpp view plain copy include include include include include 字元裝置驅動模板開始 define char dev device name char dev 是應當連線到這個編號範圍的裝置的名字,出現在 proc devices和sysfs中...
Linux裝置驅動程式學習(1) 字元裝置驅動程式
linux裝置驅動程式學習 1 字元裝置驅動程式 一 分配裝置號 1 對字元裝置的訪問是通過檔案系統內的裝置名稱進行的 dev ttys0 在核心中,include dev t 用來儲存裝置編號 包括主裝置號和次裝置號。由dev t獲得主次裝置號 major dev t dev minor dev ...