1.ioremap映射访问和使用in/out直接访问的区别与联系
linux中使用ioremap映射访问和使用in/out直接访问的区别与联系???
在Linux内核中,ioremap()函数用于将物理地址映射到虚拟地址空间,以便在内核中访问设备寄存器或
其他I/O地址空间。而in/out指令则是直接访问I/O端口的指令。
区别:
- ioremap()用于将物理地址映射到虚拟地址空间,而in/out指令是直接对I/O端口进行读写操作。
- ioremap()返回的是虚拟地址,可以通过指针访问设备寄存器,
而in/out指令是直接对I/O端口进行读写操作,不需要进行地址映射。
联系:
- ioremap()和in/out都用于访问设备的I/O地址空间,只是方式不同。
- 在驱动程序中,可以使用ioremap()将设备的物理地址映射到虚拟地址空间,
然后通过指针对设备寄存器进行读写操作。 - 在某些情况下,可能需要使用in/out指令直接对I/O端口进行读写操作,
例如在一些特殊的设备上,或者在一些嵌入式系统中。
总的来说,ioremap()和in/out都是用于访问设备的I/O地址空间,但方式和应用场景略有不同。
ioremap()适用于将物理地址映射到虚拟地址空间,然后通过指针访问设备寄存器;
而in/out指令适用于直接对I/O端口进行读写操作。
2.strrchr()函数
在Linux中,strrchr()函数是一个字符串处理函数,用于在一个字符串中查找最后一个出现的指定字符
函数原型:
char *strrchr(const char *s, int c); //s:搜索的字符串 c:查找的字符
return 指向最后一个匹配字符的指针,若未找到,则返回NULL
3.sysfs_create_file()函数
sysfs_create_file()函数是Linux内核中的一个函数,用于在sysfs文件系统中为指定的内核对象创建一个文件
函数原型:
int sysfs_create_file(struct kobject *kobj, const struct attribute *attr);
kobj:一个指向struct attribute的指针,表示创建文件的属性
struct kobject和struct attribute是Linux内核中用于管理sysfs文件系统的数据结构。
struct attribute结构体包含了文件的属性信息,例如文件名、读写权限等。
4.C语言标准库提供的一组宏
//C语言标准库中的一个头文件,提供了一组宏和类型,用于处理可变参数函数。
//这些宏和类型的目的是允许函数接受可变数量的参数。
#include <stdarg.h> void my_function(int count, ...)
{va_list args;va_start(args, count);// 使用 va_arg 获取可变参数列表中的参数值va_end(args);
}va_list steps;
va_start(steps, step_count);
va_arg(steps, int);
这两句代码是用于处理可变参数的宏和函数,用于获取可变参数列表的首地址。
-
va_list steps
;
va_list 是C语言提供的一种数据类型,用于存储可变参数列表。
valist 类型的 steps 的变量,为可变参数列表分配内存空间。 -
va_start(steps, step_count)
;
va_start是一个宏,用于初始化 va_list 类型的变量,以便访问可变参数列表。
argv[0]是一个 va_list 类型的变量,argv[1] 是可变参数列表中的最后一个已知的固定参数。
va_start 宏将可变参数列表的起始地址存储在 steps 变量中,以便后续访问可变参数。 -
va_arg(steps, int)
;
va_arg是一个宏,用于从可变参数列表中获取下一个参数的值
arg[0]是一个 va_list 类型的变量, argv[1] 是要获取的参数的类型
如:va_arg(steps, int); //表示从steps可变参数列表中获取下一个参数,并将其作为int类型返回
备注:一般会有多个va_arg操作 -
va_end(steps)
;
va_end用于结束可变参数列表的处理,作用是清理和释放与可变参数列表相关的资源。
e.g.
#define STEP(type, addr, value) (type),(addr),(value)
#define STEP_OVER (OP_TYPE_NONE),0,0
#define STEP_CNT(n) (n)
调用:i2c_select_steps_init(&(bd->i2c_select_table[I2C_DEV_FAN + 0]), \STEP_CNT(2), \STEP(OP_TYPE_WR_CPLD, bd->cpldaddr_main_i2c_sel, 0x10), \STEP_OVER);
函数:int i2c_select_steps_init(i2c_select_operation_steps *i2c_steps, int step_count, ...)
5.#define __stringify(x) #x
__stringify(x)函数是一个预处理宏,用于将参数转换为字符串常量
在__stringify(x)宏的定义中,第二个#符号是用于字符串化操作的
在C预处理器中,#符号是一种字符串化操作符,用于将宏参数转换为字符串常量
这个宏在编写宏定义时非常有用,特别是当你需要将参数转换为字符串以进行日志记录或错误消息时!!!
6.出参与入参
func(OUT u8* value, IN u16 offset); //OUT:表示出参 IN:表示入参
这种参数修饰符并不是C语言的标准特性,而是一种约定或命名规则,
用于提供更多的信息给开发者,以便更好地理解函数参数的用途和特性。
在实际代码中,OUT和IN通常是作为注释或文档的一部分使用,以帮助
开发者理解函数的使用方式。
7.底层I/O端口的读写、内存映射相关函数
在Linux系统中,用于访问I/O端口的函数通常定义在asm/io.h头文件中。
该头文件包含了一系列宏和函数,用于进行I/O端口的读写操作。
asm/io.h头文件是Linux内核提供的头文件之一,用于底层硬件访问和驱动程序开发。
它定义了一些宏和函数,用于进行底层I/O端口的读写、内存映射等操作。
以下是一些常用的I/O端口访问函数和宏定义:
inb(port):从指定的I/O端口读取一个字节的数据。
inw(port):从指定的I/O端口读取一个字(两个字节)的数据。
inl(port):从指定的I/O端口读取一个双字(四个字节)的数据。
outb(value, port):向指定的I/O端口写入一个字节的数据。
outw(value, port):向指定的I/O端口写入一个字(两个字节)的数据。
outl(value, port):向指定的I/O端口写入一个双字(四个字节)的数据。
这些函数和宏定义在asm/io.h头文件中,可以通过包含该头文件来使用它们。
在Linux内核开发或底层编程中,使用这些函数和宏可以方便地进行I/O端口的读写操作。
需要注意的是,asm/io.h头文件通常是Linux内核的一部分,因此在用户空间的应用程序中可能无法直接包含该头文件。
如果你想在用户空间的应用程序中进行I/O端口的访问,通常需要使用特定的库或驱动程序接口。
8.驱动编写步骤
前言:
sysfs是一种基于RAM的文件系统,它与Kobject结合使用,能够
将Kernel的数据结构以及属性导出到用户空间,以文件目录结构
的形式提供对这些数据结构的访问支持。
1)module_param(参数, 类型, 权限); //传递权限
2)module_param_named(insmod对应的参数变量名,程序中定义的变量名,类型,权限);
3)MODULE_PARM_DESC(参数,描述…)//对模块的参数进行描述
4)EXPORT_SYMBOL(文件或目录或函数或锁)
EXPORT_SYMBOL标签内定义的函数或者符号对全部内核代码公开,不用修改内核代
码就可以在您的内核模块中直接调用;
将一个函数以符号的方式导出给其他模块使用;
简单驱动步骤:
1)文件引入(共有文件、私有文件)
2)SYSFS_RW_ATTR_DEF(参数, 函数1,函数2); //SYSFS函数族
3)指针数组参数
e.g. static struct attritube *参数名A[] = {参数。。。};
4)释放参数
5)初始化入口函数(可能拥有多个初始化函数)
6)出口函数
7)EXPORT_SYMBOL(本文件中使用的变量)
(备注:向上与内核打交道,向下与硬件打交道)