• TQ210搭载Android4.0.3系统构建之LED从驱动到HAL到JNI到应用程序(驱动篇)


    开发板: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.
    ");
    	else {ret=-1; printk("led_open failed.
    ");}
    	return ret;
    }
    
    
    static int gpio_led_under_close(struct inode *inode,struct file *file)
    {
    	printk(KERN_INFO "led_close success.
    ");
    	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.
    ");
    	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.
    ");
    	else { printk(KERN_INFO "led_init driver failed.
    "); 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.
    ");
    	else printk(KERN_INFO "led_exit driver failed.
    ");
    }
    
    
    //模块入口与出口
    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.
    ",DEVICE_NAME);
    			return 0;
    		}
    	if(argc!=3)   //判断参数是否合法
    		{
    			printf("usage:
    ");
    			printf("led1/led2 on/off
    ");
    		}
    	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


     

  • 相关阅读:
    Oracle通过最小分区增加分区的SQL
    Oracle获取时间段内的各月底日期
    GET_MAPPING_DQL based on columns
    Oracle 分析问题sql的历史执行情况
    Oracle v$sql,v$sqlarea,v$sqltext区别
    Oracle修改表及分区表的表空间
    Oracle tablespace size sql
    ORACLE alter table storage
    Emmet的HTML语法(快速生成代码)
    Js中replace替换所有.
  • 原文地址:https://www.cnblogs.com/liangxinzhi/p/4275633.html
Copyright © 2020-2023  润新知