欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

3.5【Linux驱动基础之五】:驱动常用函数总结

程序员文章站 2022-06-03 23:02:21
...




一、地址映射、地址取消映射

ioremap():地址映射

释义:在驱动入口函数中进行地址映射,获取指定物理空间对应的虚拟空间的地址。
   即:将返回值赋值给定义好的地址指针,以后操作该指针指向的位置就是操作该地址。

ioremap();

iounmap():地址取消映射

释义:在驱动出口函数中进行地址取消映射,解除实际物理地址和指针变量的关系。

iounmap();

示例

/* 实际物理地址,芯片手册中查询 */
#define GPIO1_BASE_ADDR  0x4804c000
#define GPIO1_OE_ADDR    ((GPIO1_BASE_ADDR) + (0x134))

/*  虚拟地址指针变量 */
volatile unsigned long *gpio1_oe = NULL;

/* 驱动入口函数 */
static int __init led_init(void) {
    ...

    gpio1_oe = (volatile unsigned long *)ioremap(GPIO1_OE_ADDR, 32);    /* 添加地址映射 */

    ...
}

/* 驱动出口函数 */
static void __exit led_exit(void) {
    ...

    iounmap(gpio1_oe);    /* 取消地址映射 */
    
    ...
}

二、IO内存操作函数

当映射完地址以后,可以直接通过指针访问寄存器,如:

/* 将oe寄存器bit25、26、27置0 */
*gpio1_oe &= ((~(1<<25)) | (~(1<<26)) | (~(1<<27)));

也可以使用如下操作函数进行内存读写操作。

2.1 读操作函数

readb()

readw()

readl()

原型如下:

分别对应8/16/32位机器。

参数 addr 就是要读取写内存地址,返回值就是读取到的数据。

u8  readb(const volatile void __iomem *addr)
u16 readw(const volatile void __iomem *addr)
u32 readl(const volatile void __iomem *addr)

2.2 写操作函数

writeb()

writew()

writel()

原型如下:

分别对应8/16/32位机器。

参数 value 是要写入的数值, addr 是要写入的地址。

void writeb(u8 value, volatile void __iomem *addr)
void writew(u16 value, volatile void __iomem *addr)
void writel(u32 value, volatile void __iomem *addr)

三、设备号、主设备号、设备号操作宏

MKDEV(xxx.major, 0)

MAJOR(xxx.devid)

MINOR(xxx.devid)

设备号、主设备号、次设备号操作宏

MKDEV(ma,mi)     /* 已经知道主设备号ma和次设备号mi,使用该宏可以合成为完成的设备号 */
MAJOR(xxx.devid)
MINOR(xxx.devid)

上述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.1 注册、注销设备驱动

register_chrdev():注册设备驱动

注册设备驱动函数一般在【驱动入口函数】中调用。

register_chrdev(); 

unregister_chrdev():注销设备驱动

注销设备驱动函数一般在【驱动出口函数】中调用。

unregister_chrdev()

五、【新字符设备驱动框架】

5.1 申请、注册、注销设备号

alloc_chrdev_region(xxx.devid);
register_chrdev_region(&xxx.devid);
unregister_chrdev_region()

alloc_chrdev_region()

register_chrdev_region()

unregister_chrdev_region()

5.2 初始化/删除设备结构体

cdev_init(xxx.cdev,  &file_operation结构体);
cdev_add(xxx.cdev,  xxx.devid,  设备个数);

cdev_del()

cdev_init()

cdev_add()

cdev_del()

5.3 创建类、删除类

class_create();
class_destroy();

class_create():创建类

xxx.class = class_create();

自动创建设备节点代码一般在cdev_add()函数之后完成,创建之前首先要创建一个class类。

class结构在内核源码的【include/linux/device.h 】文件中定义。

和class相关的函数有:

struct class *class_create (struct module *owner, const char *name);
void class_destroy(struct class *cls);

class_destroy():删除类

5.4 创建设备、摧毁设备

device_create();
device_destroy();

device_create():创建设备

xxx.device = device_create(xxx.class…);

设备结构体,在内核中由函数:

struct device *device_create(struct class *class, struct device *parent,
                             dev_t devt, void *drvdata, const char *fmt, ...)

创建一个设备,返回值由device接收。

device_destroy():摧毁设备