wordpress 数据库设计太原seo建站
- 作者: 多梦笔记
- 时间: 2026年02月18日 14:19
当前位置: 首页 > news >正文
wordpress 数据库设计,太原seo建站,代充网站怎么做,vi设计公司排行我们在前面学习 I2C 和 SPI 驱动的时候#xff0c;针对 I2C 和 SPI 设备寄存器的操作都是通过相关 的 API 函数进行操作的。这样 Linux 内核中就会充斥着大量的重复、冗余代码#xff0c;但是这些本质 上都是对寄存器的操作#xff0c;所以为了方便内核开发人员统一访问 I2C…我们在前面学习 I2C 和 SPI 驱动的时候针对 I2C 和 SPI 设备寄存器的操作都是通过相关 的 API 函数进行操作的。这样 Linux 内核中就会充斥着大量的重复、冗余代码但是这些本质 上都是对寄存器的操作所以为了方便内核开发人员统一访问 I2C/SPI 设备的时候为此引入 了 Regmap 子系统本章我们就来学习一下如何使用 RegmapAPI 函数来读写 I2C/SPI 设备寄存 器 1Regmap API 简介 1.1什么是 Regmap Linux 下大部分设备的驱动开发都是操作其内部寄存器比如 I2C/SPI 设备的本质都是一样 的通过 I2C/SPI 接口读写芯片内部寄存器。芯片内部寄存器也是同样的道理比如 I.MX6ULL 的 PWM、定时器等外设初始化最终都是要落到寄存器的设置上。 Linux 下使用 i2c_transfer 来读写 I2C 设备中的寄存器SPI 接口的话使用 spi_write/spi_read 等。I2C/SPI 芯片又非常的多因此 Linux 内核里面就会充斥了大量的 i2c_transfer 这类的冗余 代码再者代码的复用性也会降低。比如 icm20608 这个芯片既支持 I2C 接口也支持 SPI 接 口。假设我们在产品设计阶段一开始将 icm20608 设计为 SPI 接口但是后面发现 SPI 接口不够 用或者 SOC 的引脚不够用我们需要将 icm20608 改为 I2C 接口。这个时候 icm20608 的驱动 就要大改我们需要将 SPI 接口函数换为 I2C 的工作量比较大。 基于代码复用的原则Linux 内核引入了 regmap 模型regmap 将寄存器访问的共同逻辑抽 象出来驱动开发人员不需要再去纠结使用 SPI 或者 I2C 接口 API 函数统一使用 regmapAPI 函数。这样的好处就是统一使用 regmap降低了代码冗余提高了驱动的可以移植性。regmap 模型的重点在于 通过 regmap 模型提供的统一接口函数来访问器件的寄存器SOC 内部的寄存器也可以使 用 regmap 接口函数来访问。 regmap 是 Linux 内核为了减少慢速 I/O 在驱动上的冗余开销提供了一种通用的接口来操 作硬件寄存器。另外regmap 在驱动和硬件之间添加了 cache降低了低速 I/O 的操作次数提 高了访问效率缺点是实时性会降低。 什么情况下会使用 regmap ①、硬件寄存器操作比如选用通过 I2C/SPI 接口来读写设备的内部寄存器或者需要读 写 SOC 内部的硬件寄存器。 ②、提高代码复用性和驱动一致性简化驱动开发过程。 ③、减少底层 I/O 操作次数提高访问效率。 本章教程我们就来重点学习一下如何将《第六十二章 Linux SPI 驱动实验》中编写的 SPI 接口的 icm20608 驱动改为使用 regmap API。 1.2Regmap 驱动框架 1.2.1regmap 框架结构 regmap 驱动框架如下图所示 regmap 框架分为三层 ①、底层物理总线regmap 就是对不同的物理总线进行封装目前 regmap 支持的物理总 线有 i2c、i3c、spi、mmio、sccb、sdw、slimbus、irq、spmi 和 w1。 ②、regmap 核心层用于实现 regmap我们不用关心具体实现。 ③、regmapAPI 抽象层regmap 向驱动编写人员提供的 API 接口驱动编写人员使用这些 API 接口来操作具体的芯片设备也是驱动编写人员重点要掌握的。 2、regmap 结构体 Linux 内 核 将 regmap 框 架 抽 象 为 regmap 结 构 体 这 个 结 构 体 定 义 在 文 件 drivers/base/regmap/internal.h 中结构体内容如下(有缩减) 51 struct regmap { 52 union { 53 struct mutex mutex; 54 struct { 55 spinlock_t spinlock; 56 unsigned long spinlock_flags; 57 }; 58 }; 59 regmap_lock lock; 60 regmap_unlock unlock; 61 void lock_arg; / This is passed to lock/unlock functions */ 62 63 struct device dev; / Device we do I/O on */ 64 void work_buf; / Scratch buffer used to format I/O / 65 struct regmap_format format; / Buffer format */ 66 const struct regmap_bus *bus; 67 void *bus_context; 68 const char *name; 69 70 bool async; 71 spinlock_t async_lock; 72 wait_queue_head_t async_waitq; 73 struct list_head async_list; 74 struct list_head async_free; 75 int async_ret; …… 89 unsigned int max_register; 90 bool (*writeable_reg)(struct device *dev, unsigned int reg); 91 bool (*readable_reg)(struct device *dev, unsigned int reg); 92 bool (*volatile_reg)(struct device *dev, unsigned int reg); 93 bool (*precious_reg)(struct device *dev, unsigned int reg); 94 const struct regmap_access_table *wr_table; 95 const struct regmap_access_table *rd_table; 96 const struct regmap_access_table *volatile_table; 97 const struct regmap_access_table *precious_table; 98 99 int (*reg_read)(void *context, unsigned int reg, unsigned int *val); 100 int (*reg_write)(void *context, unsigned int reg,unsigned int val); …… 147 struct rb_root range_tree; 148 void selector_work_buf; / Scratch buffer used for selector */ 149 }; 要使用 regmap肯定要先给驱动分配一个具体的 regmap 结构体实例一会讲解如何分配 regmap 实例。大家可以看到示例代码 74.1.2.1 中第 90~100 行有很多的函数以及 table这些需 要驱动编写人员根据实际情况选择性的初始化regmap 的初始化通过结构体 regmap_config 来 完成。 1.2.2regmap_config 结构体 顾名思义regmap_config 结构体就是用来初始化 regmap 的这个结构体也定义在 include/linux/regmap.h 文件中结构体内容如下 186 struct regmap_config { 187 const char *name; 188 189 int reg_bits; 190 int reg_stride; 191 int pad_bits; 192 int val_bits; 193 194 bool (*writeable_reg)(struct device *dev, unsigned int reg); 195 bool (*readable_reg)(struct device *dev, unsigned int reg); 196 bool (*volatile_reg)(struct device *dev, unsigned int reg); 197 bool (*precious_reg)(struct device *dev, unsigned int reg); 198 regmap_lock lock; 199 regmap_unlock unlock; 200 void *lock_arg; 201 202 int (*reg_read)(void *context, unsigned int reg, unsigned int *val); 203 int (*reg_write)(void *context, unsigned int reg, unsigned int val); 204 205 bool fast_io; 206 207 unsigned int max_register; 208 const struct regmap_access_table *wr_table; 209 const struct regmap_access_table *rd_table; 210 const struct regmap_access_table *volatile_table; 211 const struct regmap_access_table *precious_table; 212 const struct reg_default *reg_defaults; 213 unsigned int num_reg_defaults; 214 enum regcache_type cache_type; 215 const void *reg_defaults_raw; 216 unsigned int num_reg_defaults_raw; 217 218 u8 read_flag_mask; 219 u8 write_flag_mask; 220 221 bool use_single_rw; 222 bool can_multi_write; 223 224 enum regmap_endian reg_format_endian; 225 enum regmap_endian val_format_endian; 226 227 const struct regmap_range_cfg *ranges; 228 unsigned int num_ranges; 229 };Linux 内核里面已经对 regmap_config 各个成员变量进行了详细的讲解这里我们只看一些 比较重要的 第 187 行 name名字。 第 189 行 reg_bits寄存器地址位数必填字段。 第 190 行 reg_stride寄存器地址步长。 第 191 行 pad_bits寄存器和值之间的填充位数。 第 192 行 val_bits寄存器值位数必填字段。 第 194 行 writeable_reg可选的可写回调函数寄存器可写的话此回调函数就会被调用 并返回 true。 第 195 行 readable_reg可选的可读回调函数寄存器可读的话此回调函数就会被调用并 返回 true。 第 196 行 volatile_reg可选的回调函数当寄存器值不能缓存的时候此回调函数就会被调 用并返回 true。 第 197 行 precious_reg当寄存器值不能被读出来的时候此回调函数会被调用比如很多中 断状态寄存器读清零读这些寄存器就可以清除中断标志位但是并没有读出这些寄存器内部 的值。 第 202 行 reg_read可选的读操作回调函数所有读寄存器的操作此回调函数就会执行。 第 203 行 reg_write可选的写操作回调函数所有写寄存器的操作此回调函数就会执行。 第 205 行 fast_io快速 I/O使用 spinlock 替代 mutex 来提升锁性能。 第 207 行 max_register有效的最大寄存器地址可选。 第 208 行 wr_table可写的地址范围为 regmap_access_table 结构体类型。后面的 rd_table、 volatile_table、precious_table、wr_noinc_table 和 rd_noinc_table 同理。 第 212 行 reg_defaults寄存器模式值为 reg_default 结构体类型此结构体有两个成员变 量reg 和 defreg 是寄存器地址def 是默认值。 第 216 行 num_reg_defaults默认寄存器表中的元素个数。 第 218 行 read_flag_mask读标志掩码。 第 219 行 write_flag_mask写标志掩码。 关于 regmap_config 结构体成员变量就介绍这些其他没有介绍的自行查阅 Linux 内核中的 相关描述。 1.3:Regmap 操作函数 1.3.1:Regmap 申请与初始化 前面说了regmap 支持多种物理总线比如 I2C 和 SPI我们需要根据所使用的接口来选 择合适的 regmap 初始化函数。Linux 内核提供了针对不同接口的 regmap 初始化函数SPI 接口 初始化函数为 regmap_init_spi函数原型如下 struct regmap * regmap_init_spi(struct spi_device *spi,const struct regmap_config *config) 函数参数和返回值含义如下 spi需要使用 regmap 的 spi_device。 configregmap_config 结构体需要程序编写人员初始化一个 regmap_config 实例然后将 其地址赋值给此参数。 返回值申请到的并进过初始化的 regmap I2C 接口的 regmap 初始化函数为 regmap_init_i2c函数原型如下 struct regmap * regmap_init_i2c(struct i2c_client *i2c,const struct regmap_config *config) 函数参数和返回值含义如下 i2c需要使用 regmap 的 i2c_client。 configregmap_config 结构体需要程序编写人员初始化一个 regmap_config 实例然后将 其地址赋值给此参数。 返回值申请到的并进过初始化的 regmap。 还有很多其他物理接口对应的 regmap 初始化函数这里就不介绍了大家直接查阅 Linux 内核即可基本和 SPI/I2C 的初始化函数相同 在退出驱动的时候需要释放掉申请到的 regmap不管是什么接口全部使用 regmap_exit 这 个函数来释放 regmap函数原型如下 void regmap_exit(struct regmap *map) 函数参数和返回值含义如下 map需要释放的 regmap 返回值无。 我们一般会在 probe 函数中初始化 regmap_config然后申请并初始化 regmap。 1.3.2:regmap 设备访问 API 函数 不管是 I2C 还是 SPI 等接口还是 SOC 内部的寄存器对于寄存器的操作就两种读和 写。regmap 提供了最核心的两个读写操作regmap_read 和 regmap_write。这两个函数分别用来 读/写寄存器regmap_read 函数原型如下 int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val)函数参数和返回值含义如下 map要操作的 regmap。 reg要读的寄存器。 val读到的寄存器值。 返回值0读取成功其他值读取失败。 regmap_write 函数原型如下 int regmap_write(struct regmap *map, unsigned int reg, unsigned int val) 函数参数和返回值含义如下 map要操作的 regmap。 reg要写的寄存器。 val要写的寄存器值。 返回值0写成功其他值写失败。 在 regmap_read 和 regmap_write 的基础上还衍生出了其他一些 regmap 的 API 函数首先是 regmap_update_bits 函数看名字就知道此函数用来修改寄存器指定的 bit函数原型如下 int regmap_update_bits (struct regmap *map, unsigned int reg,unsigned int mask, unsigned int val,) 函数参数和返回值含义如下 map要操作的 regmap。 reg要操作的寄存器。 mask掩码需要更新的位必须在掩码中设置为 1。 val需要更新的位值。 返回值0写成功其他值写失败。 比如要将寄存器的 bit1 和 bit2 置 1那么 mask 应该设置为 0X00000011此时 val 的 bit1 和 bit2 应该设置为 1也就是 0Xxxxxxx11。如果要清除寄存器的 bit4 和 bit7那么 mask 应该 设置为 0X10010000val 的 bit4 和 bit7 设置为 0也就是 0X0xx0xxxx。 接下来看一下 regmap_bulk_read 函数此函数用于读取多个寄存器的值函数原型如下 int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,size_t val_count) 函数参数和返回值含义如下 map要操作的 regmap。 reg要读取的第一个寄存器。 val读取到的数据缓冲区。 val_count要读取的寄存器数量。 返回值0写成功其他值读失败。 另外也有多个寄存器写函数 regmap_bulk_write函数原型如下 int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,size_t val_count)函数参数和返回值含义如下 map要操作的 regmap。 reg要写的第一个寄存器。 val要写的寄存器数据缓冲区。 val_count要写的寄存器数量。 返回值0写成功其他值读失败。 关于 regmap 常用到 API 函数就讲解到这里还有很多其他功能的 API 函数大家自行查 阅 Linux 内核即可内核里面对每个 API 函数都有详细的讲解。 1.4:regmap_config 掩码设置 结构体 regmap_config 里面有三个关于掩码的成员变量read_flag_mask 和 write_flag_mask 这二个掩码非常重要本节我们来学习一下如何使用这三个掩码。我们在学习 icm20608 的时候 讲过了icm20608 支持 i2c 和 spi 接口但是当使用 spi 接口的时候读取 icm20608 寄存器的 时候地址最高位必须置 1写内部寄存器的是时候地址最高位要设置为 0。因此这里就涉及到对 寄存器地址最高位的操作在《第六十二章 SPI 驱动实验》中我们在使用 SPI 接口函数读取 icm20608 内部寄存器的时候手动将寄存器地址的最高位置 1代码如下所示 1 static int icm20608_read_regs(struct icm20608_dev *dev, u8 reg, void buf, int len) 2 { 3 …… 21 txdata[0] reg | 0x80; / 写数据的时候首寄存器地址 bit7 要置 1 / 22 t-tx_buf txdata; / 要发送的数据 / 23 t-rx_buf rxdata; / 要读取的数据 / 24 t-len len1; / t-len发送的长度读取的长度 / 25 spi_message_init(m); / 初始化 spi_message / 26 spi_message_add_tail(t, m); 27 ret spi_sync(spi, m); / 同步发送 */ …… 39 return ret; 40 }示例代码 74.1.4.1 就是标准的 SPI 驱动其中第 21 行将寄存器的地址 bit7 置 1表示这是 一个读操作。 当我们使用 regmap 的时候就不需要手动将寄存器地址的 bit7 置 1在初始化 regmap_config 的时候直接将 read_flag_mask 设置为 0X80 即可这样通过 regmap 读取 SPI 内部寄存器的时候 就会将寄存器地址与 read_flag_mask 进行或运算结果就是将 bit7 置 1但是整个过程不需要 我们来操作全部由 regmap 框架来完成的。 同理 write_flag_mask 用法也一样的只是 write_flag_mask 用于写寄存器操作。 打开 regmap-spi.c 文件这个文件就是 regmap 的 spi 总线文件找到如下所示内容 105 static struct regmap_bus regmap_spi { 106 .write regmap_spi_write, 107 .gather_write regmap_spi_gather_write, 108 .async_write regmap_spi_async_write, 109 .async_alloc regmap_spi_async_alloc, 110 .read regmap_spi_read, 111 .read_flag_mask 0x80, 112 .reg_format_endian_default REGMAP_ENDIAN_BIG, 113 .val_format_endian_default REGMAP_ENDIAN_BIG, 114 }; …… 125 struct regmap *regmap_init_spi(struct spi_device *spi, 126 const struct regmap_config *config) 127 { 128 return regmap_init(spi-dev, regmap_spi, spi-dev, config); 129 } 第 105~114 行初始化了一个 regmap_bus 实例regmap_spi我们重点看一下第 111 行中 read_flag_mask 默认为 0X80。注意这里是将 regmap_bus 的 read_flag_mask 成员变量设置为 0X80。regmap_bus 结构体大家自行查看一下这里就不讲了。 第 125~129 行为 regmap_init_spi 函数前面说了要想在 spi 总线中使用 regmap 框架首先 要使用 regmap_init_spi 函数用于并申请一个 SPI 总线的 regmap。 从第 128 行可以看出 regmap_init_spi 函数只是对 regmap_init 的简单封装因此最终完成 regmap 申请并初始化的是 regmap_init 函数。在 regmap_init 函数中找到如下所示内容 598 if (config-read_flag_mask || config-write_flag_mask) { 599 map-read_flag_mask config-read_flag_mask; 600 map-write_flag_mask config-write_flag_mask; 601 } else if (bus) { 602 map-read_flag_mask bus-read_flag_mask; 603 } 第 598~601 行就是用 regmap_config 中的读写掩码来初始化 regmap_bus 中的掩码。由于 regmap_spi 默认将 read_flag_mask 设置为 0X80当你所使用的 SPI 设备不需要读掩码在初始 化 regmap_config 的时候一定要将 read_flag_mask 设置为 0X00。 regmap 框架就讲解到这里接下来学习如何将《第六十二章 Linux SPI 驱动实验》中编写 的 icm20608 驱动改为 regmap 框架。 2:实验程序编写 本实验不需要修改设备树直接使用《第六十二章 Linux SPI 驱动实验》中的 ICM20608 设 备树。注意第六十二章以前版本教程里面没有使用 Linux 内核自带的片选信号新版本教程 (V1.6 及以后版本以后)改为了使用内部片选信号。因此如果你的 ICM20608 设备树节点按照以 前教程编写的在这里请将其参考新版教程修改。 本实验对 应的例程路径为 开发 板光盘 - 01、程序源 码 -02、 Linux 驱动例 程 -26_regmap-spi。 2.1:修改设备结构体添加 regmap 和 regmap_config regmap 框架的核心就是 regmap 和 regmap_config 结构体我们一般都是在自定义的设备结 构体里面添加这两个类型的成员变量所以我们首先在 icm20608_dev 结构体里面添加 regmap 和 regmap_config修改完成以后的 icm20608_dev 结构体内容如下 1 struct icm20608_dev { 2 struct spi_device spi; / spi 设备 / 3 dev_t devid; / 设备号 / 4 struct cdev cdev; / cdev */ 5 struct class class; / 类 */ 6 struct device device; / 设备 */ 7 struct device_node nd; / 设备节点 / 8 signed int gyro_x_adc; / 陀螺仪 X 轴原始值 / 9 signed int gyro_y_adc; / 陀螺仪 Y 轴原始值 / 10 signed int gyro_z_adc; / 陀螺仪 Z 轴原始值 / 11 signed int accel_x_adc; / 加速度计 X 轴原始值 / 12 signed int accel_y_adc; / 加速度计 Y 轴原始值 / 13 signed int accel_z_adc; / 加速度计 Z 轴原始值 / 14 signed int temp_adc; / 温度原始值 */ 15 struct regmap *regmap; 16 struct regmap_config regmap_config; 17 };第 15 行regmap 指针变量regmap 我们需要使用 regmap_init_spi 函数来申请和初始化 所以这里是指针类型。 第 16 行regmap_config 结构体成员变量从来配置 regmap。 2.2:初始化 regmap 一般在 probe 函数中初始化 regmap本章节就是 icm20608_probe 函数初始化内容如下 1 static int icm20608_probe(struct spi_device *spi) 2 { 3 int ret; 4 struct icm20608_dev icm20608dev; 5 6 / 分配 icm20608dev 对象的空间 */ 7 icm20608dev devm_kzalloc(spi-dev, sizeof(icm20608dev), GFP_KERNEL); 8 if(!icm20608dev) 9 return -ENOMEM; 10 11 / 初始化 regmap_config 设置 / 12 icm20608dev-regmap_config.reg_bits 8; / 寄存器长度 8bit / 13 icm20608dev-regmap_config.val_bits 8; / 值长度 8bit / 14 icm20608dev-regmap_config.read_flag_mask 0x80; / 读掩码 / 15 16 / 初始化 IIC 接口的 regmap / 17 icm20608dev-regmap regmap_init_spi(spi, icm20608dev-regmap_config); 18 if (IS_ERR(icm20608dev-regmap)) { 19 return PTR_ERR(icm20608dev-regmap); 20 } 21 22 / 注册字符设备驱动 / 23 / 1、创建设备号 */ 24 ret alloc_chrdev_region(icm20608dev-devid, 0, ICM20608_CNT,ICM20608_NAME); 25 if(ret 0) { 26 pr_err(%s Couldnt alloc_chrdev_region, ret%d\r\n, ICM20608_NAME, ret); 27 goto del_regmap; 28 } …… 61 62 return 0; 63 destroy_class: 64 device_destroy(icm20608dev-class, icm20608dev-devid); 65 del_cdev: 66 cdev_del(icm20608dev-cdev); 67 del_unregister: 68 unregister_chrdev_region(icm20608dev-devid, ICM20608_CNT); 69 del_regmap: 70 regmap_exit(icm20608dev-regmap); 71 return -EIO; 72 }第 11~14 行regmap_config 的初始化icm20608 的寄存器地址地址长度为 8bit寄存器值 也是 8bit因此 reg_bits 和 val_bits 都设置为 8。由于 icm20608 通过 SPI 接口读取的时候地址寄 存器最高位要设置为 1因此 read_flag_mask 设置为 0X80。 第 17 行通过 regmap_init_spi 函数来申请并初始化 SPI 总线的 regmap。 第 70 行如果要删除 regmap 就使用 regmap_exit 函数。 同理在 remove 函数中就要删除 probe 里面申请的 regmapicm20608_remove 函数内容如 下 1 static int icm20608_remove(struct spi_device *spi) 2 { 3 struct icm20608_dev icm20608dev spi_get_drvdata(spi); 4 …… 12 / 4、注销类 / 13 class_destroy(icm20608dev-class); 14 / 5、删除 regmap / 15 regmap_exit(icm20608dev-regmap); 16 return 0; 17 }第 17 行卸载驱动的时候使用 regmap_exit 删除掉 probe 函数中申请的 regmap。 2.3:读写设备内部寄存器 regmap 已经设置好了接下来就是使用 regmap API 函数来读写 icm20608 内部寄存器了。 以前我们使用 spi 驱动框架编写读写函数现在直接使用 regmap_read、regmap_write 的函数即 可修改后的 icm20608 内部寄存器读写函数如下 1 / 2 * description : 读取 icm20608 指定寄存器值读取一个寄存器 3 * param – dev : icm20608 设备 4 * param – reg : 要读取的寄存器 5 * return : 读取到的寄存器值 6 */ 7 static unsigned char icm20608_read_onereg(struct icm20608_dev dev, u8 reg) 8 { 9 u8 ret; 10 unsigned int data; 11 12 ret regmap_read(dev-regmap, reg, data); 13 return (u8)data; 14 } 15 16 / 17 * description : 向 icm20608 指定寄存器写入指定的值写一个寄存器 18 * param – dev : icm20608 设备 19 * param – reg : 要写的寄存器 20 * param – data : 要写入的值 21 * return : 无 22 */ 23 24 static void icm20608_write_onereg(struct icm20608_dev dev, u8 reg, u8 value) 25 { 26 regmap_write(dev-regmap, reg, value); 27 } 28 29 / 30 * description : 读取 ICM20608 的数据读取原始数据包括三轴陀螺仪、 31 * : 三轴加速度计和内部温度。 32 * param - dev : ICM20608 设备 33 * return : 无。 34 */ 35 void icm20608_readdata(struct icm20608_dev *dev) 36 { 37 u8 ret; 38 unsigned char data[14]; 39 40 ret regmap_bulk_read(dev-regmap, ICM20_ACCEL_XOUT_H, data, 14); 41 42 dev-accel_x_adc (signed short)((data[0] 8) | data[1]); 43 dev-accel_y_adc (signed short)((data[2] 8) | data[3]); 44 dev-accel_z_adc (signed short)((data[4] 8) | data[5]); 45 dev-temp_adc (signed short)((data[6] 8) | data[7]); 46 dev-gyro_x_adc (signed short)((data[8] 8) | data[9]); 47 dev-gyro_y_adc (signed short)((data[10] 8) | data[11]); 48 dev-gyro_z_adc (signed short)((data[12] 8) | data[13]); 49 } 第 7~14 行icm20608_read_onereg 函数用于读取 icm20608 内部单个寄存器这里直接使 用 regmap_read 函数来完成寄存器读取操作。 第 24~27 行icm20608_write_onereg 函数用于向 icm20608 指定寄存器写入数据这里也 直接使用 regmap_write 函数来完成写操作。 第 35~49 行icm20608_readdata 函数用于读取 icm20608 内部陀螺仪、加速度计和温度计 的数据从 ICM20_ACCEL_XOUT_H 寄存器开始连续读取 14 个寄存器。这里直接使用 regmap_bulk_read 函数来显示多个寄存器的读取。 对比《第四十五章 Linux SPI 驱动实验》中的 icm20608 驱动采用 regmap API 以后驱动 程序精简了很多。具体涉及到 SPI 总线的部分全部由 regmap 来处理了驱动编写人员不用管 极大的方便了我们的驱动编写。而且驱动的可以执行提高了很多即使将来更换为 IIC 接口 也只需要更改很少的一部分即可。 3:运行测试 测试 APP 直接第四十五章编写的 icm20608App.c 即可。测试方法也和四十五章一样输入 如下命令 depmod //第一次加载驱动的时候需要运行此命令 modprobe icm20608.ko //加载驱动模块 ./icm20608App /dev/icm20608 //app 读取内部数据如果 regmap API 工作正常那么就会正确的初始化 icm20608并且读出传感器数据结果 和四十五章一样如图 74.3.1 所示 IIC 总线的 regmap 框架基本和 SPI 一样只是需要使用 regmap_init_i2c 来申请并初始化对 应的 regmap同样都是使用 regmap_read 和 regmap_write 来读写 I2C 设备内部寄存器。这里我 们也已经将《第六十一章 Linux I2C 驱动实验》中的 ap3216c 驱动改为了 regmap API 接口的 相应的驱动程序已经放到了开发板光盘中路径为本实验对应的例程路径为开发板光盘- 01、程序源码-02、Linux 驱动例程-26_regmap-iic。大家自行查阅这里就不详细详解了。
相关文章
-
wordpress 手工网站51星变网页游戏官网
wordpress 手工网站51星变网页游戏官网
- 站长
- 2026年02月18日
-
wordpress 视频站模版赣州市网站建设
wordpress 视频站模版赣州市网站建设
- 站长
- 2026年02月18日
-
wordpress 视频站模版百度推广 网站备案
wordpress 视频站模版百度推广 网站备案
- 站长
- 2026年02月18日
-
wordpress 搜索引索seo黑帽有哪些技术
wordpress 搜索引索seo黑帽有哪些技术
- 站长
- 2026年02月18日
-
wordpress 提请审批网站seo推广seo教程
wordpress 提请审批网站seo推广seo教程
- 站长
- 2026年02月18日
-
wordpress 添加编辑器seo黑帽技术有哪些
wordpress 添加编辑器seo黑帽技术有哪些
- 站长
- 2026年02月18日
