开发板:TQ210
OS:Android 4.0.3
以下所有内容都是在TQ210开发板上实现,并且很多内容也是天嵌公司提供,我将一些内容进行了删减、替换,然后加入了一些自己的理解,同时也是记录自己学习的旅程。
废话不多说 先看硬件电路图 很简单 通过NPN三极管控制LED的阴极 NPN三极管的基极给高电平 则三级管导通 则LED等点亮 反之则熄灭
LED驱动源码
led_unders.c
#include <linux/miscdevice.h> //包含miscdevice misc_register... #include <linux/init.h> //包含__init __exit... #include <linux/fs.h> //包含file_operations... #include <linux/err.h> //包含EINVAL.. #include <mach/gpio.h> //包含S5PV210_GPC0() ... #include <plat/gpio-cfg.h> //包含S3C_GPIO_SFN() s3c_gpio_cfgpin() gpio_direction_output().. #define DEVICE_NAME "led_unders" //设备名 #define GPIO_CTIOL_ON 1 //控制LED亮 #define GPIO_CTIOL_OFF 0 //控制LED 灭 static unsigned int gpio_table[]= //引用I/O引脚 { S5PV210_GPC0(3), //开发板的手册上是GPC1 ,是错的 S5PV210_GPC0(4), }; static unsigned int gpio_cfg_table[]= //设置IO为输出 { S3C_GPIO_SFN(1), //设置引脚为输出 S3C_GPIO_SFN(1), }; static int gpio_led_under_open(struct inode *inode,struct file *file) //打开led_unders设备 { int ret=0,i; for(i=0;i<sizeof(gpio_table)/sizeof(gpio_table[0]);i++) { s3c_gpio_cfgpin(gpio_table[i], gpio_cfg_table[i]); //设置引脚为输出 ret=gpio_direction_output(gpio_table[i],GPIO_CTIOL_OFF); //设置引脚为0 } if(ret==0) printk("led_open success.\n"); else {ret=-1; printk("led_open failed.\n");} return ret; } static int gpio_led_under_close(struct inode *inode,struct file *file) { printk(KERN_INFO "led_close success.\n"); return 0; } static long gpio_led_under_ioctl(struct file *file,unsigned int cmd,unsigned long arg) //控制哪个led灯亮或者灭 { int ret=0; printk(KERN_INFO "led ioctl.\n"); arg=arg-1; if(arg>sizeof(gpio_table)/sizeof(gpio_table[0])) return -EINVAL; //判断传递的参数是否合法 switch(cmd) { case GPIO_CTIOL_ON: gpio_direction_output(gpio_table[arg],GPIO_CTIOL_ON); //点亮LED break; case GPIO_CTIOL_OFF: gpio_direction_output(gpio_table[arg],GPIO_CTIOL_OFF); //熄灭LED break; default: ret=-1; printk(KERN_INFO "led ioctl error"); } return ret; } static struct file_operations dev_fops= { .owner=THIS_MODULE, .unlocked_ioctl=gpio_led_under_ioctl, .open=gpio_led_under_open, .release=gpio_led_under_close, }; static struct miscdevice misc_led= { //led混杂设备结构体定义 .minor=MISC_DYNAMIC_MINOR, //动态分配次设备号 .name=DEVICE_NAME, //设备名称 .fops=&dev_fops, //设备操作结构体 }; static int __init led_init() //led初始化 { int ret; ret=misc_register(&misc_led); //注册混杂设备成功注册返回0 if(ret==0) printk(KERN_INFO "led_init driver success.\n"); else { printk(KERN_INFO "led_init driver failed.\n"); ret=-1;} return ret; } static void __exit led_exit() //led卸载 { int ret=misc_deregister(&misc_led); //卸载混杂设备 ,成功返回0 if(ret==0) printk(KERN_INFO "led_exit driver success.\n"); else printk(KERN_INFO "led_exit driver failed.\n"); } //模块入口与出口 module_init(led_init); module_exit(led_exit); MODULE_LICENSE("GPL"); //gpl许可
Makefile文件
obj-m :=led_unders.o KERNELDIR :=~/java/Kernel_3.0.8_TQ210_for_Android_v1.0/ PWD :=$(shell pwd) build:kernel_module kernel_module: make -C $(KERNELDIR) M=$(PWD) modules clean: make -C $(KERNELDIR) M=$(PWD) clean
Makefile的详细编写 参看GUN的Makefile手册 给一个简单实例连接 http://www.embedu.org/Column/Column310.htm
该驱动模块采用混杂设备来表示led设备,通过使用misc_register函数告诉内核misc_led设备所拥有的功能,
对于混杂设备我看了看源码,个人理解misc_register主要做了三件事,
1.通过MISC_DYNAMIC_MINOR这个标志获取到次设备号
2.通过class_device_create创建/dev/led_unders设备文件
3.通过list_add将misc_led添加到混杂设备链表
测试文件
led_under_driver_test.c
#include <stdio.h> #include <fcntl.h> //文件操作 #define DEVICE_NAME "/dev/led_unders" //设备名称 #define GPIO_IOCTL_ON 1 //打开led #define GPIO_IOCTL_OFF 0 //关闭led #define LED1 1 #define LED2 2 /* usage: led1/led2 on/off */ int main(int argc,char **argv) { int fd,ison=0,isnumber=0; fd=open(DEVICE_NAME,O_RDWR); //以可读可写的方式打开设备文件 if(fd<0) //判断是否成功打开文件 { printf("open %s failed.\n",DEVICE_NAME); return 0; } if(argc!=3) //判断参数是否合法 { printf("usage:\n"); printf("led1/led2 on/off\n"); } if(strcmp(argv[2],"on")==0) ison=GPIO_IOCTL_ON; //判断是打开还是关闭LED else ison=GPIO_IOCTL_OFF; if(strcmp(argv[1],"led1")==0) isnumber=LED1; //判断是操作哪一个LED else isnumber=LED2; if(ison!=0&&isnumber!=0) ioctl(fd,ison,isnumber); //操作led return 0; }
通过输入的参数来控哪个led灯的亮或者灭
编译文件 Android.mk
LOCAL_PATH :=$(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS :=eng LOCAL_SRC_FILES :=led_under_driver_test.c LOCAL_MODULE :=led_unders LOCAL_MODULE_PATH :=$(LOCAL_PATH) include $(BUILD_EXECUTABLE)
对于android编译系统 可以查看官网 http://www.kandroid.org/online-pdk/guide/build_system.html