1 头文件包含
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <asm/mach/map.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
#include <asm/io.h>
2 宏定义设备定义数量和设备名称
#define NEWCHRLED_CNT 1
#define NEWCHRLED_NAME "newchrled"
3 虚拟地址映射
/*寄存器的物理地址*/
#define IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3_BASE (0x02290000 + 0x14)
#define GPIO5_DR_BASE (0x020AC000)
#define GPIO5_GDIR_BASE (0x020AC004)
/*地址映射后的虚拟地址指针*/
static void __iomem *IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3;
static void __iomem *GPIO5_DR;
static void __iomem *GPIO5_GDIR;
4 定义构建设备类型
struct newchrled_dev
{
dev_t devid; /*设备号*/
struct cdev cdev; /*cdev*/
struct class *class; /*类*/
struct device *device; /*设备*/
int major; /*主设备号*/
int minor; /*次设备号*/
};
struct newchrled_dev newchrled;
5 构建file_operations结构体及具体实现函数
6 创建驱动入口函数static int __init led_init(void),包含以下内容
6.1 根据有无定义设备号进行设备类型成员变量devid的配置
if(newchrled.major)
{
newchrled.devid =MKDEV(newchrled.major,0);
ret = register_chrdev_region(newchrled.devid, NEWCHRLED_CNT, NEWCHRLED_NAME);
}
else
{
ret = alloc_chrdev_region(&newchrled.devid, 0, NEWCHRLED_CNT, NEWCHRLED_NAME);
newchrled.major = MAJOR(newchrled.devid);
newchrled.minor = MINOR(newchrled.devid);
}
6.2 初始化cdev
newchrled.cdev.owner = THIS_MODULE;
cdev_init(&newchrled.cdev, &newchrled_fops);
6.3 添加一个cdev节点
cdev_add(&newchrled.cdev, newchrled.devid, NEWCHRLED_CNT);
6.4 创建一个设备类
newchrled.class = class_create(THIS_MODULE, NEWCHRLED_NAME);
6.5 创建一个具体的设备
newchrled.device = device_create(newchrled.class, NULL, newchrled.devid, NULL, NEWCHRLED_NAME);
7 创建设备驱动函数出口,包含以下内容
7.1 设备必要的IO操作
7.2 取消物理地址映射
7.3 注销字符设备
cdev_del(&newchrled.cdev);
7.4 取消设备注册
unregister_chrdev_region(newchrled.devid, NEWCHRLED_CNT);
7.5 销毁设备
device_destroy(newchrled.class, newchrled.devid);
7.6 销毁设备类
class_destroy(newchrled.class);
8 函数修饰
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");