当前位置: 首页 > news >正文

嵌入式Linux驱动开发 —— 从DTS到代码的桥梁与简单OF系列API(5)

接前一篇文章:嵌入式Linux驱动开发 —— 从DTS到代码的桥梁与简单OF系列API(4)

内存映射 API:如何将设备树地址转换为可访问的虚拟地址

前面讲了如何从设备树里读取地址值,但那些只是物理地址(或者总线地址)。驱动程序要访问这些地址,还需要把它们映射到内核虚拟地址空间。这一步通常用ioremap()来完成。

但OF API提供了更便捷的方法,把“读reg属性”和“ioremap”两步合成一步。

of_iomap:一步到位的地址映射

这是驱动里最常用的函数之一:

void __iomem *of_iomap(struct device_node *np, int index);

参数说明:

  • np:设备节点
  • index:reg属性的索引(从0开始)

返回值是映射后的内核虚拟地址,失败返回NULL

这个函数会自动完成以下步骤:

1)从reg属性里读取第index组地址;

2)处理地址转换(如果需要的话);

3)调用ioremap()建立映射。

我们的LED驱动用它来映射所有寄存器地址:

/* 5. 使用 of_iomap 进行寄存器地址映射 */ led.ccm_ccgr1 = of_iomap(led.device_tree_node, 0); led.sw_mux_gpio = of_iomap(led.device_tree_node, 1); led.sw_pad_gpio = of_iomap(led.device_tree_node, 2); led.gpio_dr = of_iomap(led.device_tree_node, 3); led.gpio_gdir = of_iomap(led.device_tree_node, 4); if (!led.ccm_ccgr1 || !led.sw_mux_gpio || !led.sw_pad_gpio || !led.gpio_dr || !led.gpio_gdir) { pr_err("ioremap failed!\n"); of_node_put(led.device_tree_node); return -ENOMEM; }

这里连续调用了5次of_iomap(),每次传入不同的索引。这些索引对应reg属性里的5组地址:

reg = < 0X020C406C 0X04 /* 索引 0: CCM_CCGR1_BASE */ 0X020E0068 0X04 /* 索引 1: SW_MUX_GPIO1_IO03_BASE */ 0X020E02F4 0X04 /* 索引 2: SW_PAD_GPIO1_IO03_BASE */ 0X0209C000 0X04 /* 索引 3: GPIO1_DR_BASE */ 0X0209C004 0X04 >; /* 索引 4: GPIO1_GDIR_BASE */

注意这里有个重要的错误处理:我们检查了所有映射是否成功,只要有一个失败就报错退出。这点很重要,因为部分成功会导致后续代码访问空指针,引发内核panic。

of_get_address:获取地址原始数据

有时候你不想直接映射,而是想先拿到地址的原始数据,这时候可以用of_get_address()

const __be32 *of_get_address(struct device_node *dev, int index, u64 *size, unsigned int *flags);

参数说明:

  • dev:设备节点
  • index:reg属性的索引
  • size:输出参数,返回地址长度
  • flags:输出参数,返回标志(比如IORESOURCE_MEM)

返回值是读取到的地址数据指针(大端格式的u32数组),失败返回NULL

这个函数返回的是设备树里的原始数据,可能还需要地址转换才能变成CPU物理地址。

of_translate_address:地址转换

设备树里的地址有时是总线地址,需要转换成CPU物理地址:

u64 of_translate_address(struct device_node *dev, const __be32 *in_addr);

参数说明:

  • dev:设备节点
  • in_addr:of_get_address()拿到的地址

返回值是转换后的物理地址,如果是OF_BAD_ADDR表示转换失败。

of_address_to_resource:转换成标准资源结构

Linux内核用struct resource统一描述各种资源。这个函数把设备树里的reg直接转成resource

int of_address_to_resource(struct device_node *dev, int index, struct resource *r);

参数说明:

  • dev:设备节点
  • index:reg属性的索引
  • r:出的resource结构体

返回值是0表示成功,负值表示失败。

这个函数在某些场景下很实用,比如你需要把地址信息传递给其它子系统时。但在简单的字符设备驱动里,直接用of_iomap()往往更方便。

资源管理 API:如何正确释放引用

到这里我们讲的都是"获取"资源的 API,但Linux内核编程有个黄金法则:有获取就必须有释放。OF API也不例外。

of_node_put:释放节点引用

当你用of_find_xxx()系列函数获取了一个device_node指针后,你就有了对这个节点的引用。内核用引用计数来管理这些节点,当你用完后必须调用of_node_put()来释放引用:

void of_node_put(struct device_node *node);

参数node是你要释放的节点指针。

我们的LED驱动在出错处理和反初始化函数里都用到了它:

/* 出错处理 */ ret = of_property_read_u32_array(led.device_tree_node, "reg", regdata, 10); if (ret < 0) { pr_err("reg property read failed!\n"); of_node_put(led.device_tree_node); /* 释放节点引用 */ return -EINVAL; } /* 反初始化函数 */ void led_hw_deinit(void) { /* ... 先 unmap 所有地址 ... */ if (led.device_tree_node) { of_node_put(led.device_tree_node); led.device_tree_node = NULL; } }

这里有个小技巧:我们在释放引用后把指针设为NULL。这样即使deinit()函数被多次调用,也不会 double-free。

你可能会问:of_find_property()需要配合of_node_put()吗?答案是:不需要property结构体是device_node的一部分,它的生命周期由节点管理。你只需要在用完整个节点后调用一次of_node_put()就行了。

更多内容请看下回。

http://www.gsyq.cn/news/1502663.html

相关文章:

  • 英雄联盟自动化工具箱:5个核心功能提升游戏效率
  • 从原理到代码:手把手用Python复现D-InSAR二轨法核心流程(附Jupyter Notebook)
  • MATLAB人脸考勤工具包:摄像头实时识别+GUI操作+打卡记录自动生成
  • 别再死记硬背Zookeeper命令了!用Curator 5.5.0 + Spring Boot 3.x实战分布式锁(附12306抢票源码)
  • 别再硬算!用Python的SciPy库5行代码搞定‘翻译任务分配’这类指派问题
  • 威海黄金回收避坑指南 2026年6月最新金价与靠谱店铺推荐 - 余生黄金回收
  • 独立开发者必看:如何用 Claude 快速构建一个 Chrome 插件原型 | 实战攻略
  • 致远OA漏洞检测终极指南:12大安全漏洞一键扫描与利用
  • 用 Rust 写 AI Agent 是什么体验?ADK-Rust 框架深度解析
  • MATLAB车牌识别小工具:带GUI界面,支持本地BMP图一键识别与字符高亮显示
  • 2026年成都专线物流公司排行:成都零担物流/成都上门接货的物流公司/成都专线托运/五大服务商核心能力对比 - 优质品牌商家
  • AVI视频一键拆解成单帧图片的小巧Windows工具
  • 2026年6月博物馆展柜定制厂家技术分享:靠谱选择与实测标准 - 奔跑123
  • 2026年最火的鱼蛙火锅加盟品牌排行榜单 - 品牌排行榜
  • 铜川各区旧黄金怎么卖才划算 2026回收防坑干货指南 - 余生黄金回收
  • 拒绝被淘汰:基于大模型Agent的全栈临床科研新范式,医生如何抢占学术先机?
  • TMS320F28377D CLA+FPU实战:手把手教你搞定1024点FFT(附完整源码)
  • 知识花园实战指南:用自动化脚本打造高效个人知识管理系统
  • Thanos构建企业级统一告警管理平台:高可用架构设计与实施路径
  • 微信数据备份终极指南:如何安全合规地管理你的数字记忆
  • 手把手教你用Matlab复刻RTKPlot的天空视图(附源码与数据)
  • AI 生成的短视频不打「AI生成」标识,正在被悄悄限流——新规落地一年,发布前你得自查这几样
  • Python自动化神器:5分钟掌握Windows GUI测试的终极指南
  • 钉钉消息防撤回补丁:企业通讯安全完整解决方案
  • IMU手写识别技术:ECHWR框架与边缘计算实践
  • LegacyUpdate:终极Windows更新修复工具,让老旧系统重获新生
  • ProcessMaker:企业级开源BPM平台如何重塑工作流自动化
  • 养慢虾哲学:nanobot适配低速大模型
  • 会话+知识融合:全品类企业服务AI智能体底层技术方案
  • 用51单片机和MPX4115做个简易气压计:Proteus仿真+ADC0832驱动全流程