版權聲明 : 本文爲博主隨手筆記,歡迎評論和轉載。 http://www.javashuo.com/article/p-wdhdndze-u.html html
LED驅動程序node
第一步:看懂 PCB 原理圖和 芯片datasheetlinux
第二步:尋找對應 Pin 的寄存器地址shell
第三步:匹配有效的信息bash
下面以 iTOP4412 ARM9開發板爲例 :函數
找出對應的 LED 引腳this
經過 KP_COL0 和 VDD50_EN 匹配芯片上對應的 Pin :spa
從上圖可知 : KP_COL0 對應在 chip 上的 Pin :GPL2_0 ; VDD50_EN 對應在 chip 上的 Pin :GPK1_1 3d
而後經過 chip datasheet 去匹配對應的寄存器 : code
從上圖可知GPL2對應的個寄存器的功能。可知這些 datasheet 都是英文的,建議志同道合的夥伴們記得去提高一下本身的英語文化水平。
從匹配的信息來看,須要的是 GPL2_0
GPL_CON 寄存器 :
從上圖可知 GPL2CON 的 Base Address :0x1100_0000
地址對應的偏移爲:Base Address + 0x1000
重置值爲 : 0x0000_0000
LED, 那麼則須把 GPL2CON[0]設置成 : 0x1 = Output --->輸出模式
GPL_DAT 寄存器 :
Description 處要仔細讀, 裏面涉及了對應寄存器的用法。
GPK1_1 配信息的原理同上!!!!
綜述 :
GPL2_CON 地址爲 : 0x11000100
GPL_DAT 地址爲:0x11000104
GPK1_CON 地址爲 : 0x11000060
GPK_DAT 地址爲:0x11000064
驅動原理 :就是操做 open read write ioctl close 等函數,因此在 Linux驅動程序入門 二 時說過,學驅動很簡單!
用戶層 | open | read | write | ioctl | |
file_operation | || | || | || | || | |
驅動層 | led_open | led_read | led_write | led_ioctl |
用戶層有一個 open 函數,則驅動層有對應的 led_open 函數,二者經過 file_operation結構關聯起來!!!
led 的驅動程序爲 :
1 #include <linux/module.h> 2 #include <linux/kernel.h> 3 #include <linux/fs.h> 4 #include <linux/init.h> 5 #include <linux/delay.h> 6 #include <asm/uaccess.h> 7 #include <asm/io.h> 8 #include <linux/device.h> 9 10 int major; 11 12 volatile unsigned long *gpl2con = NULL; 13 volatile unsigned long *gpl2dat = NULL; 14 15 volatile unsigned long *gpk1con = NULL; 16 volatile unsigned long *gpk1dat = NULL; 17 18 static int led_open(struct inode *inode, struct file *file) 19 { 20 /*配置GPL2爲輸出,先清零,再配置*/ 21 *gpl2con &= ~0x03; 22 *gpl2con |= 0x01; 23 24 /*配置GPK1爲輸出,先清零,再配置*/ 25 *gpk1con &= ~(0x03<<4); 26 *gpk1con |= (0x01<<4); 27 return 0; 28 } 29 static int led_write(struct file *filp, 30 /const char __user *buf, size_t count, loff_t *ppos) 31 { 32 int val; 33 34 /*從用戶拷貝到內核///copy_to_user()從內核拷貝到用戶*/ 35 copy_from_user(&val, buf, count); 36 if(val == 1) 37 { 38 //點燈 39 *gpl2dat |= 1; 40 //點燈 41 *gpk1dat |= 0x02; 42 } 43 else 44 { 45 //滅燈 46 *gpl2dat &= ~1; 47 //滅燈 48 *gpk1dat &= ~0x02; 49 } 50 return 0; 51 } 52 static struct file_operations led_fops = { 53 /*這是一個宏,推向編譯環境時自動建立的__this_module*/ 54 .owner = THIS_MODULE, 55 .open = led_open, 56 .write = led_write, 57 }; 58 static int led_drv_init(void) 59 { 60 /*註冊驅動程序,告訴內核這個函數來被誰調用*/ 61 register_chrdev(0, "first_drv", &first_drv_fops); 62 63 gpl2con = (volatile unsigned long *)ioremap(0x11000100, 4); 64 gpl2dat = gpl2con + 1; 65 66 gpk1con = (volatile unsigned long *)ioremap(0x11000060, 4); 67 gpk1dat = gpk1con + 1; 68 69 return 0; 70 } 71 static void led_drv_exit(void) 72 { 73 unregister_chrdev(major, "first_drv"); 74 device_unregister(firstdrv_class_dev); 75 class_destroy(firstdrv_class); 76 iounmap(gpl2con); 77 iounmap(gpk1con); 78 } 79 80 module_init(led_drv_init); 81 module_exit(led_drv_exit); 82 83 MODULE_LICENSE("Dual BSD/GPL"); 84 MODULE_AUTHOR("stormeli"); 85 MODULE_DESCRIPTION("LEDdriver");
對應的Makefile,即編譯內核爲 :
#!/bin/bash obj-m += led_drv.o KDIR := /home/topeet/Android/Android4.0/iTop4412_Kernel_3.0 PWD ?= $(shell pwd) all: make -C $(KDIR) M=$(PWD) modules clean: rm -rf *.o
用戶層程序爲 :
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <string.h> /* *firstdrvtest on *firstdrvtest off */ int main(int argc, char **argv) { int fd; int val = 1; fd = open("/dev/led", O_RDWR); if(fd < 0) { printf("can't open!\n"); } if(argc != 2) { printf("Usage :\n"); printf("%s <on|off>\n", argv[0]); return 0; } if(strcmp(argv[1], "on") == 0) { val = 1; } else { val = 0; } write(fd, &val, 4); return 0; }
編譯過程爲:
1、編譯驅動程序 : 使用 make 指令,獲得 .ko 文件,即模塊驅動文件
2、編譯用戶程序 : 使用 arm-none-linux-guneabi- gcc -o led_device led_device.c -static 指令編譯
獲得可執行文件 led_device
把編譯獲得的 可執行文件 led_device 和 led_drv.ko 文件拷貝進 iTOP4412 板子裏(可以使用的方法有 U盤拷貝, nfs協議傳輸,tftp協議傳輸)
板子上的操做:
加載內核模塊的指令 : insmod xxx.ko
查看內核模塊的指令:lsmod
卸載內核模塊的指令:rmmod xxx
經過 insmod xxx.ko 加載內核模塊, 而後 lsmod 查詢,是否加載成功, 再使用 cat /proc/device 查看分配的 主設備號 跟 次設備號「此關於設備文件的建立」
「驅動匹配得有 設備文件『由用戶層可知建立 /dev/led 文件』跟驅動文件」
建立設備文件的指令爲 : mknod /dev/led c 主設備號 次設備號 c「表明是字符 character 設備驅動」
最後執行用戶可執行文件 ./led_device
可知 led_drv 主設備號爲 248, 次設備號爲 0
板子 LED 點亮