分类: LINUX
2009-03-20 14:42:58
一. 模块的初始化函数
static int __int s
{
int ret;
ret = register_chrdev(BUTTON_MAJOR, DEVICE_NAME, &3sc24xx_buttons_fops);
if(ret < 0) {
printk(DEVICE_NAME" Can not register major number\n");
return ret;
}
printk(DEVICE_NAME" inittialized\n");
return 0;
}
二. 模块的退出函数:
static void __exit s
{
unregister_chrdev(BUTTON_MAJOR, DEVICE_NAME);
}
三. 指定模块的初始化和退出函数:
module_init(s
module_exit(s
四.定义s
static struct file_operations s
.owner = THIS_MODULE,
.open = s
.release = s
.read = s
};
五.编写s
static int s
{
int i;
int err;
for(i=0; i<4; i++) {
err = request_irq(button_irqs[i].irq, buttons_interrupt, button_irqs[i].flags, button_irqs[i].name, (void *)&press_cnt[i]);
if(err)
break;
}
if(err) {
i--;
for(; i>=0; i--)
free_irq(button_irqs[i].irq, (void *)&press_cnt[i]);
return -EBUSY;
}
return 0;
}
六.编写close函数:
static int s
{
int i;
for(i=0; i<4; i++) {
free_irq(button_irqs[i].irq, (void *)&press_cnt[i]);
}
return 0;
}
七.编写read 函数:
static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
static volatile int ev_press = 0;
static int s
{
unsigned long err;
wait_event_interruptible(button_waitq, ev_press);
ev_press = 0;
err = copy_to_user(buff, (const void *)press_cnt, min(sizeof(press_cnt), count));
memset((void *)press_cnt, 0, sizeof(press_cnt));
return err ? -EFAULT : 0;
}
8.编写中断函数
static irqreturn_t buttons_interrupt(int irq, void *dev_id)
{
volatile int *press_cnt = (volatile int *)dev_id;
*press_cnt = *press_cnt + 1;
ev_press = 1;
wake_up_interruptible(&button_waitq);
return IRQ_RETVAL(IRQ_HANDLED);
}
八.添加宏定义等:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define DEVICE_NAME "buttons" /* 加载模式后,执行”cat /proc/devices”命令看到的设备名称 */
#define BUTTON_MAJOR 232 /* 主设备号 */
/* 按键被按下的次数(准确地说,是发生中断的次数) */
static volatile int press_cnt [] = {0, 0, 0, 0};
九.将s
Obj-m +=s
十.在内核目录下执行 make modules,可以driver/char目录下生成可加载模块s
十一.在开发板上:mknod /dev/buttons c 232 0