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

address-cell size-cell

I2C子设备为啥size-cell为零

在设备树(Device Tree)中,I2C 子设备的#size-cells为零,主要是由I2C 总线的寻址特性决定的。

简单来说,这是因为 I2C 设备在总线上占据的是一个**“点”(单一地址),而不是一个“范围”**(地址区间)。

以下是详细的原因分析:

1.reg属性的含义

在设备树中,子节点的reg属性通常由父节点的两个属性来定义格式:

  • #address-cells:定义reg中“地址”字段占用的字数(cell,每个 cell 为 32 位)。
  • #size-cells:定义reg中“长度/大小”字段占用的字数。

对于常见的内存映射设备(如片上外设),它们占据一段连续的内存空间(例如:起始地址0x40001000,长度0x100),因此需要size来描述范围。

2. I2C 的寻址方式:单一地址 vs 地址范围

  • 非内存映射:I2C 是一种串行总线,每个从设备(Slave)由一个唯一的7位或10位地址标识。
  • 没有“长度”概念:当你访问一个 I2C 设备时,你只需要知道它的从机地址(Slave Address)。这个地址是一个离散的标识符,它不代表一段地址空间,也没有“从地址 A 到地址 B”这种长度的概念。
  • reg 属性的简化:在 I2C 节点下,reg = <0x50>;就足够表示这个设备(比如 EEPROM)的地址是0x50。由于不需要描述“占用多少地址空间”,所以reg里不需要包含length字段。

3. 设置为零的具体作用

在 I2C 控制器(父节点)中设置#size-cells = <0>;,是为了告诉内核:“我的子设备(I2C 从机)在描述自己的资源(reg)时,只需要写地址,不需要写长度。”

示例对比:

  • 内存总线(需要 Size)

    soc { #address-cells = <1>; #size-cells = <1>; serial@40001000 { reg = <0x40001000 0x100>; // 地址是0x40001000,长度是0x100 }; };
  • I2C 总线(不需要 Size)

    i2c@40002000 { #address-cells = <1>; #size-cells = <0>; // 规定子设备不需要长度字段 eeprom@50 { reg = <0x50>; // 只需要地址,没有第二个数字 }; };

总结

I2C 子设备的size-cell为零是因为:

  1. I2C 协议基于从机 ID 寻址,每个设备只占用一个逻辑地址。
  2. 没有物理上的“空间长度”需要被映射。
  3. 同样的逻辑也适用于SPI 总线(地址是片选线编号)和CPU 节点(地址是内核 ID),它们的#size-cells通常也是 0。

为啥内存总线需要 Size

内存总线(Memory-mapped I/O,简称 MMIO)之所以需要size(即#size-cells不为 0),是因为内存地址空间和 I2C 这种串行总线在硬件寻址逻辑操作系统管理方式上有本质的区别。

以下是为什么要定义“长度(Size)”的四个核心原因:

1. 内部寄存器范围(Offset 概念)

一个内存映射设备(如 UART 控制器、网卡、GPU)通常不只有一个寄存器,而是有一堆寄存器。

  • I2C 设备:你向地址0x50发送指令,具体的内部寄存器(如 EEPROM 的存储地址)是在数据包里定义的,不是在总线层面定义的。
  • 内存映射设备:CPU 直接通过地址访问。比如一个 UART 控制器:
    • 0x40001000是数据寄存器
    • 0x40001004是控制寄存器
    • 0x40001008是状态寄存器
  • 结论:这个设备占据了从0x40001000开始的一整块“领地”。操作系统必须知道这块地有多大,才能给驱动程序提供正确的访问范围。

2. 内存管理单元(MMU)与页表映射

在现代操作系统(如 Linux)中,驱动程序不能直接访问物理地址,必须通过虚拟地址访问。

  • 内核在加载驱动时,会调用类似ioremap(base, size)的函数。
  • 映射单位:MMU 是按“页”(通常是 4KB)来映射的。如果 OS 不知道设备的size,它就不知道该为这个设备在虚拟地址空间里分配多大的区域,也不知道该映射多少个页表项。

3. 防止地址冲突(Resource Allocation)

系统内存地址空间是极其宝贵的“房地产”。

  • 内核有一个资源管理器(在 Linux 里可以通过cat /proc/iomem查看)。
  • 为了防止两个设备被分配到重叠的地址区域,内核需要记录每个设备从哪开始以及到哪结束
  • 如果没有size,内核只知道0x40001000被占用了,但不知道0x40001004是不是也被这个设备占用了,这会导致资源管理的混乱。

4. 总线解码器(Hardware Decoder)的工作原理

从硬件设计的角度看:

  • I2C:总线上的所有设备都看着数据流,当地址匹配时,某个设备跳出来响应。
  • 内存总线:CPU 发出一个地址信号。总线控制器(Bus Fabric/Interconnect)需要根据这个地址来决定把信号传给哪个外设。
  • 译码逻辑:硬件内部的地址译码器就像一个“围墙”。它判断:if (Address >= Base && Address < Base + Size),则激活该设备。这个Size是硬件逻辑电路中真实存在的范围。

类比理解

  • I2C 就像“快递员投递”
    你只需要写一个门牌号(地址0x50)。快递员顺着街道走,看到门牌号就敲门。他不需要知道你家房子有多大。
  • 内存总线就像“土地规划”
    政府(CPU/OS)要把一块地划拨给工厂(外设)。政府不仅要给工厂一个起始坐标(Base Address),还必须标明这块地占地几亩(Size)。否则,隔壁的工厂可能会把楼盖到你的地盘上,或者你在自家院里走路(访问寄存器)却走到了别人家里。

总结

特性I2C 子设备内存映射设备 (MMIO)
访问方式串行协议包发送地址CPU 指令直接读写内存地址
占用空间逻辑上的一个点物理上的一个地址区间
映射需求不需要映射,直接由驱动发包需要 MMU 映射成虚拟地址
#size-cells0通常为 1 或 2
http://www.jsqmd.com/news/716788/

相关文章:

  • NVIDIA显卡性能调优指南:如何通过Profile Inspector解锁隐藏性能的5个实用技巧
  • 别再手动录入了!用ABAP BAPI批量创建SAP销售计划协议(VA31)的完整代码与避坑指南
  • 5分钟掌握163MusicLyrics:网易云QQ音乐歌词获取终极指南
  • Claude-mem在WindowsOpenclaw上的安装与调试指南
  • 别再为喇叭没声音发愁了!手把手教你用ES8311芯片搞定TTS云喇叭播放(附完整寄存器配置表)
  • MTK-Android12-假横屏-竖屏开机解决各类APP USB相机适配问题
  • 这次抽卡生成的页面很棒! - AI
  • 独立站建站平台有哪些?
  • 电脑加密如何设置?快试试这六个电脑加密方法,建议码住了
  • 别再只玩颜色追踪了!用OpenMV的find_blobs()函数,5分钟搞定智能小车巡线(附完整代码)
  • 【Java 25 FFI终极指南】:20年JVM专家亲授外部函数接口增强的5大生产级落地陷阱与避坑清单
  • springboot+vue3的BS架构勤工助学信息管理系统设计与实现
  • 麒麟V10生产环境WordPress部署与分布式迁移完全指南
  • Allegrao软件操作:用于修复未连接的引脚
  • OpCore-Simplify:三步搞定黑苹果配置的终极开源自动化工具指南
  • RAG面试通关秘籍:15个核心问题深度解析,小白也能轻松掌握大模型(收藏版)
  • ggplot_比例表现01
  • 告别复制粘贴!用Keil5为GD32F4xx搭建标准工程模板的保姆级流程
  • Mac M1安装PyTorch踩坑全记录:从conda环境冲突到numpy版本问题的实战解决
  • 基于Holoscan与OpenCV的零拷贝AI处理流水线实践
  • 收藏!2026最新7个低门槛AI岗位|小白普通程序员大模型转型必看
  • 键盘守护者 iwck:告别误触烦恼的智能解决方案
  • springboot+vue3的保护野生动物信息管理系统 生物多样性观测与保护科普系统设计与实现
  • R语言生态学入门:用rgbif包5分钟搞定GBIF物种分布数据下载(以十大功劳属为例)
  • 亚马逊Fire TV Cube 2022解析:Amlogic POP1-G芯片与流媒体性能
  • Arm Cortex-A720处理器错误分析与解决方案
  • 正点原子u-boot学习nfs版本不匹配解决方案
  • 2026年,想解决新疆荒漠与园林绿化难题,选靠谱之选看这里!
  • 部署与可视化系统:保姆级边缘计算教程:NVIDIA Jetson Orin Nano 刷机、CUDA 配置与 TensorRT 极限部署全流程
  • 避开Unity PS5开发第一个大坑:手把手教你搞定Build-In管线环境与打包(基于2021.3.32f1)