EmbedFire i.MX 6ull开发板学习笔记(六)---驱动模板

本文介绍了Linux驱动的编译方式,包括编译为模块和编译进内核,并详细讲解了字符设备驱动、platform设备驱动和块设备驱动的概念及应用场景,提供了驱动模板的解析。
摘要由CSDN通过智能技术生成

一、驱动编译

Linux驱动可编译为模块,即.ko文件;也可以编译进内核。每一个驱动几乎都有一个独立的CONFIG配置。例如:在drivers/leds/Makefile中有如下内容:

obj-$(CONFIG_LEDS_GPIO)			+= leds-gpio.o

在make muneconfig配置为m,即是编译为模块。

CONFIG_LEDS_GPIO=m   
obj-m		+= leds-gpio.o

在make muneconfig配置为为y即编译进内核。

CONFIG_LEDS_GPIO=y
obj-y		+= leds-gpio.o

所以:obj-m表示编译为模块;obj-y表示编译进内核。在调试阶段我们一般编译为模块,使用insmod 或modprobe命令加载.ko文件,用rmmod命令卸载.ko文件。

insmod不会加载当前.ko依赖的.ko,加载时.ko文件可在任何目录。modprobe会自动加载当前.ko依赖的.ko,加载时.ko文件必须已在/lib/modules/&(uname -r)/目录下存在。uname -r是当前内核版本。

二、驱动模板

Linux下一切皆文件,加载驱动后会下/dev目录下生成对应的节点,应用程序可以向操作普通文件一样进行open,read,write,close操作。linux驱动分为三大类型,即:字符设备驱动,platform设备驱动和块设备驱动。

1、字符设备驱动:

按字节流顺序读写,如IIC,UART等都是字符设备。Linux下绝大部分驱动都属于此种类型,驱动基本模板如下:

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/cdev.h>
#include <linux/device.h>

#define XXXCHRDEV_CNT			1		  		/* 设备号个数 */
#define XXXCHRDEV_NAME			"xxxchrdev"		/* 名字 */
 
/* xxxchrdev设备结构体 */
struct xxxchr_dev{
   
	dev_t devid;			/* 设备号。在include/linux/types.h中定义有dev_t(32位无符合整数)来表示设备号。*/
							/* 主设备号为高12位,次设备号为低20位。并提供了宏MAJOR(dev),MINOR(dev),MKDEV(ma,mi) */
							/* 来方便提取主次设备号和组合设备号。*/
	struct cdev cdev;		/* cdev。表示一个字符设备 */
	struct class *class;	/* 类 */
	struct device *device;	/* 设备 */
	int major;				/* 主设备号:具体某个驱动。 */						
	int minor;				/* 次设备号:使用该驱动的设备数量。*/
};

struct xxxchr_dev xxxchrdev;

/*
 * @description		: 打开设备
 * @param - inode 	: 传递给驱动的inode
 * @param - filp 	: 设备文件,file结构体有个叫做private_data的成员变量
 * 					  一般在open的时候将private_data指向设备结构体。
 * @return 			: 0 成功;其他 失败
 */
static int xxx_open(struct inode *inode, struct file *filp)
{
   
	filp->private_data = &xxxchrdev; /* 设置私有数据 */
	return 0;
}

/*
 * @description		: 从设备读取数据 
 * @param - filp 	: 要打开的设备文件(文件描述符)
 * @param - buf 	: 返回给用户空间的数据缓冲区
 * @param - cnt 	: 要读取的数据长度
 * @param - offt 	: 相对于文件首地址的偏移
 * @return 			: 读取的字节数,如果为负值,表示读取失败
 */
static ssize_t xxx_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{
   
	return 0;
}

/*
 * @description		: 向设备写数据 
 * @param - filp 	: 设备文件,表示打开的文件描述符
 * @param - buf 	: 要写给设备写入的数据
 * @param - cnt 	: 要写入的数据长度
 * @param - offt 	: 相对于文件首地址的偏移
 * @return 			: 写入的字节数,如果为负值,表示写入失败
 */
static ssize_t xxx_write(struct file *filp, const char __user *buf, size_t cnt, loff_t<
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值