2012 11 3 linux设备驱动程序开发初探(2) udev/mdev机制 LED的驱动程序

编程入门 行业动态 更新时间:2024-10-08 05:33:27

2012 11 3  linux设备<a href=https://www.elefans.com/category/jswz/34/1770317.html style=驱动程序开发初探(2) udev/mdev机制 LED的驱动程序"/>

2012 11 3 linux设备驱动程序开发初探(2) udev/mdev机制 LED的驱动程序

<linux设备驱动程序开发初探(2)>

在<linux设备驱动程序开发初探(1)>中,已经实现了一个最简单的、框架式的linux驱动程序,以及编译、加载和使用的概念与总体流程。这个程序至少有两个方面需要改进:
# 在驱动程序first_drv.c中,手动指定了主设备号为111,如果这个设备号在系统中已经被占用,那么这样的写法就不行。可以让系统自动分配一个主设备号:

int major;
static int first_drv_init(void)
{
major = register_chrdev(0, "first_drv", &first_drv_fops); // 注册, 告诉内核
return 0;
}

这样在模块加载后,系统会自动分配一个主设备号。我们需要手动建立在 /dev/ 目录中的设备节点,这时就要查找这个主设备号了。这种手动建立设备节点的方式不是最好的,可以有一种机制,让系统能够在加载了模块之后,自动创建设备节点,这就是“热拔插 hot plug”机制,具体实现常用udev机制,或者在嵌入式系统中常用的mdev为udev的简化版。

mdev程序会根据 /sys/dev 目录下面的记录的信息进行自动创建、删除设备节点的工作。

为了使用嵌入式系统中的mdev机制,需要在编写驱动程序是注册两个类,“告诉内核的mdev机制”相关的信息,这些信息会被记录在/sys/dev 目录下面供mdev机制(程序)使用:

static struct class *firstdrv_class;
static struct class_device    *firstdrv_class_dev;

并在加载和卸载模块的时候使用(注册与注销):

int major;
static int first_drv_init(void)
{
major = register_chrdev(0, "first_drv", &first_drv_fops); // 注册, 告诉内核firstdrv_class = class_create(THIS_MODULE, "firstdrv");
firstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xyz"); /* 创建设备节点名称 /dev/xyz */return 0;
}static void first_drv_exit(void)
{
unregister_chrdev(major, "first_drv"); // 卸载class_device_unregister(firstdrv_class_dev);
class_destroy(firstdrv_class);
}MODULE_LICENSE("GPL"); //mdev机制必须添加这条注册信息

需要注意的是,驱动程序最后一定要进行GPL的声明,不然无法使用mdev机制。


更改这些信息后重新编译运行便可以发现设备节点被自动加载了,在/sys/class目录下就有关于first_drv的信息。之所以mdev程序会在/sys/class下面信息的改变自动运行,是因为在linux系统启动的脚本文件/etc/init.d/rcS中创建了这个程序的运行热拔插的条件:

echo /sbin/mdev > /proc/sys/kernel/hotplug

=====================================================

<改装最简单驱动程序,控制LEDs>

在裸机上编写LED控制程序时使用的是物理地址,但是在linux的用户空间使用的是虚拟地址,因此需要进行物理地址到虚拟地址的转换,使用的是ioremap函数

先定义两个指针用于指向GPIO的配置寄存器和数据寄存器:

volatile unsigned long *gpfcon = NULL;
volatile unsigned long *gpfdat = NULL;

在注册函数static int first_drv_init(void)中进行地址转换:

gpfcon = (volatile unsigned long *)ioremap(0x56000050, 16);
gpfdat = gpfcon + 1;

在注销函数中也需要用iounmap函数声明

iounmap(gpfcon);

这样使用这两个指针指向的寄存器时就可以控制led了。完整的程序如下:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>static struct class *firstdrv_class;
static struct class_device    *firstdrv_class_dev;volatile unsigned long *gpfcon = NULL;
volatile unsigned long *gpfdat = NULL;static int first_drv_open(struct inode *inode, struct file *file)
{
//printk("first_drv_open\n");
/* 假设led接在GPF4、5、6三个IO上,低电平点亮。配置GPF4,5,6为输出 */
*gpfcon &= ~((0x3<<(4*2)) | (0x3<<(5*2)) | (0x3<<(6*2)));
*gpfcon |= ((0x1<<(4*2)) | (0x1<<(5*2)) | (0x1<<(6*2)));
return 0;
}static ssize_t first_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
int val;//printk("first_drv_write\n");copy_from_user(&val, buf, count); //    copy_to_user();if (val == 1)
{
// 点灯
*gpfdat &= ~((1<<4) | (1<<5) | (1<<6));
}
else
{
// 灭灯
*gpfdat |= (1<<4) | (1<<5) | (1<<6);
}return 0;
}static struct file_operations first_drv_fops = {
.owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
.open = first_drv_open, 
.write    =    first_drv_write,    
};int major;
static int first_drv_init(void)
{
major = register_chrdev(0, "first_drv", &first_drv_fops); // 注册, 告诉内核firstdrv_class = class_create(THIS_MODULE, "firstdrv");
firstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xyz"); /* /dev/xyz */gpfcon = (volatile unsigned long *)ioremap(0x56000050, 16);
gpfdat = gpfcon + 1;return 0;
}static void first_drv_exit(void)
{
unregister_chrdev(major, "first_drv"); // 卸载class_device_unregister(firstdrv_class_dev);
class_destroy(firstdrv_class);
iounmap(gpfcon);
}module_init(first_drv_init);
module_exit(first_drv_exit);MODULE_LICENSE("GPL"); //mdev机制必须添加这条注册信息

转载于:.html

更多推荐

2012 11 3 linux设备驱动程序开发初探(2) udev/mdev机制 LED的驱动程序

本文发布于:2024-02-13 14:14:53,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1759152.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:驱动程序   机制   设备驱动程序   linux   LED

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!