uClinux设备驱动程序的设计与编写

来源:本站
导读:目前正在解读《uClinux设备驱动程序的设计与编写》的相关信息,《uClinux设备驱动程序的设计与编写》是由用户自行发布的知识型内容!下面请观看由(电工技术网 - www.9ddd.net)用户发布《uClinux设备驱动程序的设计与编写》的详细说明。
简介:本文章详细讲解了uClinux设备驱动程序的设计与编写方法及步骤。

1设备驱动程序的一般编写步骤

(1) 确定设备的主设备号

(2) 填充static struct file_operation这样的结构

(3) 定义一个类似__init mydriver_init(void)这样的注册函数,大体如下:

int __init mydriver_init(void)

{

int rc;

rc = register_chrdev(mydevice_Major, "mydev", &mydriver_fops);

if (rc < 0) {

printk(KERN_WARNING "mydevice: can/'t get Major %d//n",

mydevice_Major);

return rc;

}

printk("mydevice Driver Support.//n");

return 0;

}

其中mydev表示的设备文件为/dev/mydev X X,即习惯上起名为mydev mydev01 mydev02……如had hda1 hda2 hda3。不过名字是可以随意的。如果成功就返回0,否则返回-1

2 填充驱动程序子函数集struct file_operation结构

(1)驱动程序子函数集struct file_operation结构

struct file_operation结构共有11个成员,分别表示一函数指针,内容及作用说明如下:

struct file_operations {

/*需要改变文件位置时调用*/

loff_t (*llseek) (struct file *, loff_t, int);

/*执行read(2)系统调用时调用*/

ssize_t (*read) (struct file *, char *, size_t, loff_t *);

/*执行write(2)系统调用时调用*/

ssize_t (*write) (struct file *, const char *, size_t, loff_t *);

/*读目录内容时调用*/

int (*readdir) (struct file *, void *, filldir_t);

/*执行poll 系统调用时调用*/

unsigned int (*poll) (struct file *, struct poll_table_struct *);

/*执行ioctl(2) 系统调用时调用*/

int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);

/*执行mmap(2) 系统调用时调用*/

int (*mmap) (struct file *, struct vm_area_struct *);

/*打开设备时调用*/

int (*open) (struct inode *, struct file *);

/*只在file的使用计数为0时调用,它用来释放file结构*/

int (*release) (struct inode *, struct file *);

/*执行fsync(2)系统调用时调用*/

int (*fsync) (struct file *, struct dentry *);

/*执行fcntl(2)系统调用时调用*/

int (*fasync) (int, struct file *, int);

};

(2)根据需要,按以下方法构造上述函数,如:

static int ReadPower(struct inode * inode, struct file * file, char * buffer, int count)

{

if (!Ready)

return -EAGAIN;

if (count != sizeof(int))

return -EINVAL;

copy_to_user(buffer, &myvar, sizeof(int));

return sizeof(int);

}

这里定义成static是因为该驱动程序子函数在文件外是通过上述的间接方法被调用的,文件外不需要该符号。

(3)把相关操作对应的函数名填入mydevice_operations中

填充static struct file_operations mydevice_operations时,用以上构造的函数名填充相应成员,例如:

struct file_operations TouchPanel_fops = {

read: ReadTouchPanel,

poll: TouchPanelSelect,

ioctl: TouchPanelIoctl,

open: OpenTouchPanel,

release: CloseTouchPanel,

};

3 中断处理

首先,中断不是必须的。如果设备要用中断模式,就要构造中断处理函数,并注册中断处理函数。

Linux中断处理过程由中断子系统完成;而中断处理函数只是处理具体操作,即读写数据等。成功注册该中断处理函数,就挂接到中断子系统上了。

中断处理一般由两个主要部分组成:

(1)构造中断处理函数void MyDriverInterrupt(int irq, void *dev_id, struct pt_regs *regs),

一般说来,Linux中断处理函数完成工作一方面把设备来的数据读出并保存起来,另一方面把内核中的数据写入设备。这样,驱动程序只需从内核读出数据,把用户提交的数据写入内核;这里可以使用一个简单的数组。

中断处理函数时要防止其他中断的干扰,可用"save_flags(flags); cli();"来关闭中断,相关处理完毕,用"restore_flags(flags)"来恢复。

(2) 注册中断可在mydriver_init()中,也 可在 mydriver_open()中,例如:

if (request_irq(

MYDEVICE_IRQ_NUM,

MyDeviceInterrupt,

IRQ_FLG_STD,

"mydevice",

NULL

)

) {

printk("TouchPanel: Cannot register interrupt.//n");

return -EBUSY;

}

其中:

MYDEVICE_IRQ_NUM: 注册中断号码

MyDeviceInterrupt: 中断处理程序

mydevice: 中断说明(可随便写)

如果返回0,表示成功,否则失败。

4 时间处理

在驱动程序中可以使用定时器来调度函数在未来某个特定时间执行。定时器包括它的超时值(timeout, 单位是jiffies)和超时时调用的函数。定时器列表的数据结构如下:

struct timer_list {

struct list_head list;

unsigned long expires; /*timeout超时值,以jiffies值为单位*/

unsigned long data; /*传递给定时器处理程序的参数*/

void (*function)(unsigned long); /*超时调用的定时器处理程序*/

};

定时器的timeout是个"jiffy"值,当jiffies值大于等于timer->expires时,timer->function函数就会执行,timeout值是个绝对数值,它与当前时间无关,不需要更新。

操作定时器有下面几个函数:

void init_timer(struct timer_list *timer);

该函数初始化新分配的定时器队列。

void add_timer(struct timer_list *timer);

该函数将定时器插入挂起的定时器的全局队列。

void del_timer(struct timer_list *timer);

如果需要在定时器超时前将它从列表中删除,应调用del_timer函数。但当定时器超时时,系统会自动地将它从列表中删除。

提醒:《uClinux设备驱动程序的设计与编写》最后刷新时间 2024-03-14 01:03:10,本站为公益型个人网站,仅供个人学习和记录信息,不进行任何商业性质的盈利。如果内容、图片资源失效或内容涉及侵权,请反馈至,我们会及时处理。本站只保证内容的可读性,无法保证真实性,《uClinux设备驱动程序的设计与编写》该内容的真实性请自行鉴别。