2)创建设备节点
----->手动创建设备节点
mknod 设备名 设备类型 主设备号 次设备号
mknod /dev/hello c 254 0
----->自动创建设备节点
创建类
class_create(owner, name)
参数1:表示模块 一般用THIS_MODULE表示
参数2:类的描述信息--------》自定义
成功:返回struct class的结构体,失败用PTR_ERR()表示
创建设备
device_create(struct class * cls, struct device * parent, dev_t devt, void * drvdata, const char * fmt,...)
参数1:class_create中成功返回的结构体struct class
参数2:父类------》一般为NULL
参数3:设备号
#define MINORBITS 20
#define MINORMASK ((1U << MINORBITS) - 1)
#define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS)) //通过设备号获取主设备号
#define MINOR(dev) ((unsigned int) ((dev) & MINORMASK)) //通过设备号获取次设备号
#define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi)) //获取设备号
参数4:私有数据-------->一般为NULL
参数5:设备名
成功:返回struct device的结构体,失败用PTR_ERR()表示
3)实现操作方法
int hello_open(struct inode *inode,struct file *filp)
{
printk("open success -----> %s\n",__FUNCTION__);
return 0;
}
int hello_close(struct inode *inode,struct file *filp)
{
printk("close sad -----> %s\n",__FUNCTION__);
return 0;
}
struct file_operations fops={
.open = hello_open,
.release = hello_close,
};
4)实例化对象
kzalloc(size_t size, gfp_t flags)
参数1:要申请空间的大小
参数2:分配空间的标志-----> 一般用GFP_KERNEL(表示没有资源可申请时,休眠)
5)硬件初始化:地址映射
ioremap(cookie, size)
参数1:表示映射的起始地址
参数2:表示映射空间的大小
gpc0_conf = ioremap(0xE0200060,8);
gpc0_data = gpc0_conf + 1;
四:实现应用空间与内核空间的数据交互
应用空间:实现策略--------》如何实现功能
内核空间:实现机制--------》能不能实现
应用空间------->内核空间 实现write函数接口
copy_from_user(void * to, const void __user * from, unsigned long n)
参数1: 目标地址---内核中的空间地址
参数2: 原地址-----应用空间中数据的地址
参数3: 传递给内核的数据的长度
返回值: 0---成功,非0 ---- 没有传递过来的数据的个数
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
内核空间------->应用空间 实现read函数接口
copy_to_user(void __user * to, const void * from, unsigned long n)
参数1: 目标地址---应用空间的地址
参数2: 原地址-----内核中数据的地址
参数3: 传递给应用空间的数据的长度
返回值: 0---成功,非0 ---- 没有传递给应用空间的数据的个数
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
五: ioctl实现点灯,指定某个亮或者灭
1)通过使用ioctl实现应用层的ioctl
应用层
int ioctl(int d, int request, ...);
——————————————————————————————————————————
内核层
long xxx_ioctl (struct file *, unsigned int, unsigned long)
switch(cmd)
{
case LED_NUM1_ON:
.................
break;
case LED_NUM1_ON:
.................
break;
case LED_NUM1_ON:
.................
break;
}
方法1:任意定义一些数来表示某个命令
#define LED_NUM1_ON 0X1234
#define LED_NUM1_OFF 0X5678
方法2:利用内核的算法生成一些数
#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOR_BAD(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
#define _IOW_BAD(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
#define _IOWR_BAD(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
2)通过库函数实现
//获取/申请IO
static inline int gpio_request(unsigned gpio, const char *label)
//给某个指定的IO设置值
static inline void gpio_set_value(unsigned gpio, int value)
//从某个指定的IO口获取值
static inline int gpio_get_value(unsigned gpio)
//向指定的IO口输出一个特定的值
static inline int gpio_direction_output(unsigned gpio, int value)
//从指定的IO口输入
static inline int gpio_direction_input(unsigned gpio)
//释放/回收IO
static inline void gpio_free(unsigned gpio)