Regmap子系统:(寄存器映射)

Regmap简述
  • Regmap野心很大,希望加入所有总线接口,目前已支持I2C、SPI、MMIO、SPMI等。
  • 当然Regmap框架不仅提供了一种统一接口,而且支持缓存(减少内存的开销)。
Remap配置流程:
  • 1配置regmap_config结构体
  • 2 Regmap初始化
  • 3调用Remap API函数进行读写操作
  • 4释放Regmap
    经过上面的步骤,我们就可以使用Regmap。

**1配置结构体:(一般在驱动程序中声明)

static struct regmap *xxx_regmap;

struct regmap_config{
	const char *name;
	int reg_bits;//寄存器地址的位数,必须初始化一个有效值
	int val_bits;//寄存器值的位数,必须初始化一个有效值
	bool (*writeable_reg)(struct device *dev, unsigned int reg);//回调函数,值为可写寄存器表
	bool (*readable_reg)(struct device *dev, unsigned int reg);//同上,针对每一个寄存器的读取操作
	bool (*volatile_reg)(struct device *dev, unsigned int reg);//回调函数,涉及缓存中读写寄存器会触发
	unsigned int max_register;//最大寄存器地址,防止越界
	const struct regmap_access_table* wr_table;//no support
};

**2结构体初始化:(一般在probe函数中)

由于Regmap仅仅只是一个统一的接口,其底层调用最终还是走的各个子系统协议。

例如要使用I2C子系统,那么我们需要将Regmap映射到I2C接口上(regmap_init_i2c函数),
这样操作regmap的时候实际上就是在操作i2c接口

struct regmap * regmap_init_i2c(struct i2c_client *i2c, //I2C客户端结构体
							const struct *regmap_config)//regmap配置结构体
struct regmap * regmap_init_spi(struct spi_device *spi,//spi设备结构体
							const struct *regmap_config);//regmap配置结构体

**3 Regmap读写操作(在桥梁函数里,即实际的设备操作)
最终目的是操作各个设备进行通信,linux内核提供了响应的接口函数供驱动开发者使用。

//单个寄存器写一个值
static inline int regmap_write(struct regmap *map, unsigned int reg,unsigned int val)
//向单个寄存器写入多个数据
static inline int regmap_raw_write( struct regmap *map,unsigned int reg,//寄存器地址								const void *val, size_t val_len)//写入数据的地址//写入数据的长度
//向多个连续的寄存器中写入多个值
static inline int regmap_bulk_write(struct regmap *map, unsigned int reg,
const void *val, size_t val_count)
//同样还有读操作,以及其它操作
regmap_read、regmap_raw_read、regmap_bulk_read

**4 释放Regmap结构体

void regmap_exit(struct regmap *map)
Remap示例(I2C操作OLED):
  • 0 添加设备树节点:(其中使用OLED内部显示控制器为SSD1306驱动)
    在这里插入图片描述
  • 1 驱动绑定与解绑(sysfs、regmap、platform)
static struct regmap *oled_regmap;
static uint8_t diaplay_buffer[128][8]static int oled_write_cmd(uint8_t cmd){
	ret = regmap_write(oled_regmap,0x00,cmd); //DC=0 command
}
static int oled_write_data(uint8_t data){
	ret = regmap_write(oled_regmap,0x40,data); //DC=1 command
}
static void oled_on(void) {
	oled_write_cmd(0x8D); oled_write_cmd(0x14); oled_write_cmd(0xAF); 
}
static void oled_off(void) {
	oled_write_cmd(0x8D); oled_write_cmd(0x10); oled_write_cmd(0xAE); 
}

//xxxxxxxxxx省略代码xxxxxxxxxregmap提供读写寄存器函数xxxxxxxxxx

static const struct regmap_config oled_config = {//regmap配置结构体
	.reg_bits = 8, //寄存器 8 位
	.val_bits = 8, //数据 8 位
	.max_register = 255, //最大寄存器 255 个
	.cache_type = REGCACHE_NONE, //不使用 cache
	.volatile_reg = false,
};

static ssize_t oled_show(struct device *dev,struct device_attribute *attr,char *buf) {
	oled_off();return 1; 
}
static ssize_t oled_store(struct device *dev,struct device_attribute *attr,const char*buf, size_t count){
	oled_fill_screen(*buf);return count; 
}

static DEVICE_ATTR(oled, 0660, oled_show, oled_store); //定义文件属性
static int oled_probe(struct i2c_client *client, const struct i2c_device_id *id) {
	ret = device_create_file(&client->dev,&dev_attr_oled);//创建属性文件
	oled_regmap = regmap_init_i2c(client,&oled_config);
}
static int oled_remove(struct i2c_client *client){
device_remove_file(&client->dev,&dev_attr_oled);//删除属性文件
	regmap_exit(oled_regmap);
}

static const struct i2c_device_id oled_id[] = {
{ "test,oled", 0 },
}
static const struct of_device_id oled_of_match[] = {
{ .compatible = "test,oled"},
};
MODULE_DEVICE_TABLE(of, oled_of_match);

static struct i2c_driver oled_driver = {
.driver = {
.name = "test,oled",
.owner = THIS_MODULE, 
.of_match_table = oled_of_match,
},
.probe = oled_probe,
.remove = oled_remove,
.id_table = oled_id,
};
module_i2c_driver(oled_driver);

bb那么多的模型框架以及接口目的就是简化我们驱动开发,提高代码规范,到底还是内核抗下了所有

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
存储器映射是为物理内存按照一定的编码规则分配地址的行为,由芯片厂商或用户规定,用户不能随意更改。存储器映射将程序存储器、数据存储器、寄存器和I/O端口排列在同一个顺序的地址空间内,以便进行访存操作。\[1\]\[2\] 寄存器映射是给已经分配好地址的具有特定功能的内存单元取别名的过程。通过给这些内存单元取别名,即寄存器,可以更好地区分其功能并方便后续的程序开发。例如,通过寄存器映射,可以将一个内存单元的地址0x4001 1010取别名为GPIOC_BSRR,并且这个寄存器的地址就是0x4001 1010。这样的映射过程就是寄存器映射。\[3\] 因此,存储器映射寄存器映射都是为了方便对内存单元进行访问和操作,其中存储器映射是为整个物理内存分配地址,而寄存器映射是为具有特定功能的内存单元取别名。 #### 引用[.reference_title] - *1* [【嵌入式系统】存储器映射寄存器映射原理](https://blog.csdn.net/FRIGIDWINTER/article/details/106826511)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [3 . 存储器映射寄存器映射](https://blog.csdn.net/weixin_41043617/article/details/116034629)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

栋哥爱做饭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值