2117.03.06备注:在恢复文章时代码的格式丢失,请匆阅读此文,以免误导.
本文简略地分析总结了一下linux的字符型设备驱动编写流程,以满足一些简单的驱动编写,如驱动硬件IO等操作.
除了要包含的那一堆头文件外,linux的字符型驱动主要程序实际上只有两个接口:
module_initmydev_init;
module_exitmydev_exit;
module_init与module_ext分别用来指明内核在初始化与卸载驱动时所指向的函数入口. 在指明了函数入口后,就须要编写这两个函数的具估内容了.
首先:拿mydev_init来说:
static int __init mydev_initvoid;
int ret;
some_codes;
ret=register_chrdevXXX_MAJOR,DEVICE_NAME,&XXX_fops;
some_codes;
其中mydev_init的函数格式为固定的static int __init mydev_init(void)
;
整个函数里最重要的一步当然是ret=register_chrdev(XXX_MAJOR,DEVICE_NAME,&XXX_fops)
;
作 用是向内核注册一个字符型设备驱动,其中第一个参数为主设备号(如果为0表示由系统分配),第二个为驱动名称(将会在/dev目录下升成这个文件),第三 个参数为file_operations结构函数地址.我们要做的工作就是去完成file_operations这个结构体里的各个成员,它们完成与应用 程序的沟通.
在file_operations结构体中有非常多的成员,我们只须要完成我们关心的部份即可,不须要完全是实现它.以下是一个适用于s3c2440控制IO的一个演示示例,这里我们假定GPG4上接有一个LED,我们的目的就是驱动它的亮灭:
1.创建文件csmekdev.c放到内核源码目录/drivers/char.内容如下
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/miscdevice.h>
#include <linux/gpio.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <mach/regs-clock.h>
#include <plat/regs-timer.h>
#include <mach/regs-gpio.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#define DEVICE_NAME "csmekdev" //设备名csmekdev
#define CSMEKDEV_MAJOR 220 //主设备号220
static int csmekdev_ioctlstruct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg
s3c2410_gpio_setpinS3C2410_GPG4,
cmd;
static ssize_t dev_writestruct file *file, const char *buffer, size_t count, loff_t *ppos
unsigned char stats;
int ret;
if
count == 0 return count;
ret = copy_from_user & stats, buffer, sizeof stats ? -EFAULT : 0;
if
ret return ret;
stats &= 0x01;
s3c2410_gpio_setpinS3C2410_GPG4, stats;
return count;
static struct file_operations csmekdev_fops =
.owner = THIS_MODULE,
.ioctl = csmekdev_ioctl,
.write = dev_write,
;
static int __init csmekdev_module_initvoid
int ret;
int i;
ret = register_chrdevCSMEKDEV_MAJOR, DEVICE_NAME, &csmekdev_fops;
if
ret < 0 printkDEVICE_NAME " can't register major number\n";
return ret;
s3c2410_gpio_cfgpinS3C2410_GPG4, S3C2410_GPIO_OUTPUT;
/* s3c2410_gpio_setpin(S3C2410_GPG4, 0); */
printkDEVICE_NAME " initialized\n";
return 0;
static void __exit csmekdev_module_exitvoid
unregister_chrdevCSMEKDEV_MAJOR,
DEVICE_NAME;
printkDEVICE_NAME " removed\n";
module_initcsmekdev_module_init;
module_exitcsmekdev_module_exit;
2.然后修改Kconfig在文件最后加入
“
config CSMEKDEV_SMDK2440
tristate "CsmekDev on SMDK2440"
“`
[MEDIUM]3.再修改makefile加入:[/MEDIUM]
“obj-$(CONFIG_CSMEKDEV_SMDK2440) += csmekdev.o”
然后menuconfig时,在 Device Drivers->Character devices中,将CsmekDev on SMDK2440编译进内核(即选择为* 不能是选择为M).然后编译,烧录.在开发板上运行”cat /proc/devices”可以看到我们的驱动已经注册到内核,如下图:
http–csmek.com-images-article-201110-proc
然后我们建立设备文件:”mknod /dev/csmekdev c 220 0″.
这 样就会在/dev目录下建立一个csmekdev的文件.我们对这个文件的操作就可完成一些动作比如: “echo 0 > /dev/csmekdev” 即GPG4置低,”echo 1 > /dev/csmekdev”置高GPIO,也可以使用IOCTL的方式,只需要我们去完善csmekdev_fops结构体成员.