框架入口源文件: led_drv.c led_dev.c
可根据入口源文件,再按着框架到内核走一遍
内核版本:linux_2.6.22.6 硬件平台:JZ2440
以下是驱动框架:
以下是驱动代码 led_dev.c:
#include <linux/module.h> #include <linux/version.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/types.h> #include <linux/interrupt.h> #include <linux/list.h> #include <linux/timer.h> #include <linux/init.h> #include <linux/serial_core.h> #include <linux/platform_device.h> //定义一个资源结构体 static struct resource led_drv_resource[]= { [0] = {.start =0x56000050 , .end = 0x56000050 + 8 - 1 , .flags = IORESOURCE_MEM, }, [1] = {.start = 5, .end = 5,.flags = IORESOURCE_IRQ,} }; static void led_platform_release(struct device * dev) {} //定义一个 device_platform 结构体 static struct platform_device led_dev_platform = { .name = "platform_led", .id = -1, .num_resources = ARRAY_SIZE(led_drv_resource), .resource = led_drv_resource, .dev = { .release = led_platform_release, }, }; static int led_device_init(void) { platform_device_register(&led_dev_platform); return 0; } static void led_device_exit(void) { platform_device_unregister(&led_dev_platform); } module_init(led_device_init); module_exit(led_device_exit); MODULE_LICENSE("GPL");
以下是驱动代码led_drv.c:
#include <linux/module.h> #include <linux/version.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/sched.h> #include <linux/pm.h> #include <linux/sysctl.h> #include <linux/proc_fs.h> #include <linux/delay.h> #include <linux/platform_device.h> #include <linux/input.h> #include <linux/irq.h> #include <asm/uaccess.h> #include <asm/io.h> //引脚定义 static unsigned long *gpfcon; static unsigned long *gpfdat; static int pin; //为设备定义一个类 static struct class *led_platform_class; //定义主设备号 static int major; static ssize_t led_drv_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { int val; copy_from_user(&val, buf, count); if (val == 1) *gpfdat &= ~(1<<pin); else *gpfdat |= (1<<pin); return 0; } static int led_drv_open(struct inode *inode, struct file *file) { //配置寄存器 *gpfcon &= ~(0x3<<(pin*2)); *gpfcon |= (0x1<<(pin*2)); return 0; } static struct file_operations led_fops = { .owner = THIS_MODULE, .write = led_drv_write, .open = led_drv_open, }; static int probe_led(struct platform_device *pfdrv) { // 引脚初始化 struct resource *sodrv; sodrv = platform_get_resource(pfdrv,IORESOURCE_MEM,0); gpfcon = ioremap(sodrv->start,sodrv->end - sodrv->start+1); gpfdat = gpfcon +1; sodrv = platform_get_resource(pfdrv,IORESOURCE_IRQ,0); pin = sodrv->start; //注册字符设备 类 节点 major = register_chrdev(0,"led_devices",&led_fops); // proc/devices/led_class led_platform_class = class_create(THIS_MODULE,"led_class"); // sys/class/led_class class_device_create(led_platform_class,NULL, MKDEV(major,0), NULL, "led_dev"); // dev/led_dev return 0; } static int remove_led(struct platform_device *pfdrv) { iounmap(gpfcon); unregister_chrdev(major,"led_platform"); class_destroy(led_platform_class); class_device_destroy(led_platform_class,MKDEV(major,0)); return 0; } static struct platform_driver led_platform = { .probe = probe_led, .remove = remove_led, .driver ={.name = "platform_led",} }; static int led_drv_init(void) { platform_driver_register(&led_platform); return 0; } static void led_drv_exit(void) { platform_driver_unregister(&led_platform); } module_init(led_drv_init); module_exit(led_drv_exit); MODULE_LICENSE("GPL");
以下是编译驱动的Makefile:
KER_DIR=/work/systems/kernel/linux-2/linux-2.6.22.6 all: make -C $(KER_DIR) M=`pwd` modules clean: make -C $(KER_DIR) M=`pwd` modules clean rm -fr modules.order obj-m += led_dev.o obj-m += led_drv.o