第一步:在Linux下编写驱动程序

1,在Linux3.0/driver/ ->mkdir   hello_me

2,在hello_me目录下,新建编写makefiel和Kconfig


makefile 如下:

#
# Makefile for HELLO_ME_LEDS
#

#  SPI testing only for (using spidev driver)
# \file  -> spi_test.c
  
#  \version     1.0.0
 
#  \date        2014年04月23日
  
#  \author      jiangdou  <jiangdouu88@126.com>
 
# Copyright (c) 2014 jiangdou. All Rights Reserved.
 
obj-$(CONFIG_HELLO_ME_LEDS)	+= leds.o

Kconfig 如下:

#
# HSI driver configuration
#



config HELLO_ME_LEDS
	tristate "HELLO_ME LEDS Driver"
	
	help
	  Say Y here if you want to support the LEDS device

leds.c 如下:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>


#if 1
#define GPIO_BASE 0x01C20800
#define GPE_CFG0  (GPIO_BASE + 0x90)	//PE CFG0
#define GPE06_CFG         (1 << 24)		//配置PE06为输出模式
#define GPE_DATA  (GPIO_BASE + 0xA0)
#endif

/*自动创建设备节点结构体*/
static struct class *leddrv_class;
/*cfg0里面有PE06*/
volatile unsigned  long  *gpe_cfg0 = NULL;
volatile unsigned  long  *gpe_date = NULL;


/*设备打开函数,当你在应用程序里面对led执行open函数这个函数就会被执行*/
static int led_drv_open(struct inode *inode, struct file *file)
{

		/*将PE06_CFG位清零*/
         *gpe_cfg0 &= ~(GPE06_CFG);
         /*将PE06_CFG位置1,即设置为输出模式*/
         *gpe_cfg0 |= GPE06_CFG;
 
         /*在内核里面打印要用printk*/
         //printk(KERN_ALERT"led openi\n");
		 printk("led openi\n");
         return 0;
}
/*设备写函数,当你在应用程序里面对led执行write函数这个函数就会被执行*/
static ssize_t led_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
         //printk(KERN_ALERT"led write\n");
         int val ;
         /*内核空间和用户空间相互独立,两者之间数据交换要用这个函数*/
         copy_from_user(&val,buf,count);
         if(val == 1)
         {
                   /*置0,相当pin_write写0*/
                   //*gph_date &= ~(0×03<<15);	//写PH15,PH16
				   *gpe_date &= ~(0x01<<6);	//写PE06
         }
         else
         {      
                   /*置1,相当pin_write写1*/
                  // *gph_date |= (0×03<<15);
				  *gpe_date |= (0x01<<6);
         }
         return 0;
}
/*linux设备驱动里面每个设备都得要一个设备描述符,其实就可以结构体,有兴趣的可以看看他的原型*/
static struct file_operations led_drv_fops = {
    .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
    .open   =   led_drv_open,     /*函数指针赋值*/
    .write  =          led_drv_write,             /*函数指针赋值*/
};
/*主设备号变量*/
int major;
/*当执行insmod命令的时候这个函数会被执行 */
static int led_drv_init(void)
{      

		 
		 pr_err("leds_init by jiangdou 20140420\n");
         /*注册一个LED设备,参数0表示让操作系统分配主设备号,分配好了之后返回给major */
         major = register_chrdev(0, "jiangdou_led", &led_drv_fops);
         /*创建设备节点,有了这两个函数,我们在文件系统里面就会看到/dev/led */
         leddrv_class = class_create(THIS_MODULE,"jiangdou_led");
         device_create(leddrv_class,NULL,MKDEV(major,0),NULL,"jiangdou_led");
         /*linux系统里面都是虚拟地址 ioremap就是将虚拟地址转换为物理地址,然后我们可以对寄存器进行操作
          *第一个参数表示需要映射的基地址,第二个参数表示长度,即基地址+0×10*/
		 gpe_cfg0 = (volatile unsigned long *)ioremap(GPE_CFG0,20);//20表示20 byte,5个32
        // /*0×A0 = 0×90 +4*4*/
         gpe_date = gpe_cfg0 + 4;
         return 0;
}
/*当执行rmmod的时候会被执行*/
static void led_drv_exit(void)
{
         /*注销LED设备*/
         unregister_chrdev(major, "led"); // 卸载
         /*释放申请的地址*/
         iounmap(gpe_cfg0);
         /*销毁创建的设备节点*/
         device_destroy(leddrv_class,MKDEV(major,0));
         class_destroy(leddrv_class);
         printk(KERN_ALERT"leds unregister\n");
}
/*linux设备驱动的两个修饰符*/
module_init(led_drv_init);
module_exit(led_drv_exit);
 
/*遵循GPL协议*/
MODULE_AUTHOR("by jiangdou");
MODULE_LICENSE("GPL");

5,在Linux3.0/driver/makefile 的修改,如下:

#
# Makefile for the Linux kernel device drivers.
#
# 15 Sep 2000, Christoph Hellwig <hch@infradead.org>
# Rewritten to use lists instead of if-statements.
#

obj-y				+= gpio/

obj-$(CONFIG_HELLO_ME_LEDS)				+= hello_me/

obj-$(CONFIG_PCI)		+= pci/
..............

...............略
6,,在Linux3.0/driver/Kconfig 的修改,如下:

menu "Device Drivers"

source "drivers/base/Kconfig"

source "drivers/hello_me/Kconfig"

source "drivers/connector/Kconfig"

source "drivers/mtd/Kconfig"

......................................

...........................略

7,在Linux3.0下执行make   ARCH=arm menuconfig


选择进入 device driver,会看到:


在【M】HELLO_ME LEDS Driver,按M,编译成leds.ko即可


第二步,加载leds.ko驱动

1,用adb push D:\lins\leds.ko   /system/vendor/modules/

->  这个会有一个小问题:


解决办法如下:

执行命令:



2,adb shell     &  insmod  /system/vendor/modules/leds.ko

3,cd dev   &  ls


如图:



5,出现一个jiangdou_led的IO设备,是不是很奇特:

6,输入命令:echo  1 >  jiangdou_led



7,打开led,


Logo

更多推荐