内存类型device Non-bufferablex详解
好的,我们来详细解释 AXI 协议中的 Device Non-cacheable 属性。这是一个非常关键的概念,尤其在与硬件外设(如寄存器、DMA 缓冲区)打交道时至关重要。
核心思想
Device Non-cacheable 是一种内存类型属性,它告诉系统互联结构和处理器:“这次访问的目标是内存映射的设备(如硬件寄存器),而不是普通的内存。因此,你必须严格按照我的指令来访问,不能做任何可能改变访问行为或顺序的优化。”
为了理解它,我们首先要看 AXI 协议如何定义内存属性。
AXI 协议中的内存属性:AxCACHE 信号
在 AXI 协议中,每次读或写事务都会有一组信号来定义其内存属性。最关键的是 AxCACHE[3:0] 信号(ARACHE 用于读,AWCACHE 用于写)。这 4 个比特位定义了事务的缓存和缓冲特性。
AxCACHE 信号的四个位分别是:
- [0] - Bufferable (B)
 - [1] - Cacheable (C)
 - [2] - Read-Allocate (RA)
 - [3] - Write-Allocate (WA)
 
不同的位组合定义了不同的内存类型。Device Non-cacheable 是其中的一种特定组合。
Device Non-cacheable 的具体含义
通常,Device Non-cacheable 对应于 AxCACHE = 4'b0000(即 Bufferable=0, Cacheable=0, Read-Allocate=0, Write-Allocate=0)。
让我们分解这个配置的含义:
- 
Non-cacheable (C=0)
- 最重要的一点:该事务不能通过缓存(Cache)来完成。
 - 处理器核心必须直接向最终的目标地址发起访问,绝对不能从缓存中读取数据,也绝对不能将数据只写入缓存就结束。
 - 对于读操作,必须从设备/内存中读取最新值。
 - 对于写操作,必须将数据最终写入设备/内存。
 
 - 
Non-bufferable (B=0)
- 强调写入的完成确认:一个写事务只有在它真正到达最终的外设设备并被其接受后,才能返回“完成”信号(BRESP/RRESP)给发起者(如 CPU)。
 - 中间不能有写缓冲区(Write Buffer)暂存数据并提前返回完成信号。发起者需要确切地知道写操作是否被设备成功执行。
 
 - 
Non-allocate (RA=0, WA=0)
- 这次访问绝不会导致缓存行分配(Cache Line Allocation)。因为本身就不是 Cacheable 的,所以自然不会分配。
 
 
为什么需要这种属性?(关键特性)
当你访问一个内存映射的设备(例如 UART 的数据寄存器、GPIO 的控制寄存器、中断控制器等)时,你必须遵守两条铁律:
- 
副作用(Side Effects):
- 对设备的每一次读写都可能具有不可重复的副作用。
 - 读操作:读取一个 UART 的接收数据寄存器,每读一次,硬件可能就会将“数据已就绪”的标志位清零。如果你第一次读操作被缓存了,后续的读操作直接从缓存返回旧数据,你就永远无法读到新的数据,并且硬件状态也会错乱。
 - 写操作:向一个设备控制寄存器写入“启动”和“停止”命令。如果这两个写操作被缓冲或重排序,可能会导致“停止”先于“启动”到达设备,使得设备无法正常工作。
 
 - 
严格有序(Strict Ordering):
- 对设备的访问顺序必须与程序发出的顺序严格一致。编译器或处理器的重排序优化会彻底破坏设备驱动程序的控制流。
 - 例如,必须先配置设备寄存器 A,再配置寄存器 B。如果写操作 B 先于 A 到达设备,设备可能无法初始化。
 
 
Device Non-cacheable (AxCACHE=0000) 的设置正是为了满足这些苛刻要求:
- 禁止缓存:确保每次访问都直接“戳到”硬件设备,避免副作用的重复或丢失。
 - 禁止缓冲:确保写操作完成的确认信号意味着数据已被设备真正接收,驱动程序可以可靠地检查设备状态或发起下一次操作。
 - 隐含的强序:虽然 AXI 协议本身允许事务乱序完成,但对于 Non-bufferable 的访问,系统互联通常会将它们视为强有序的,或者会确保对同一设备的访问保持程序顺序,以满足设备驱动的期望。
 
与其他内存类型的对比
| 内存类型 | 典型 AxCACHE 值 | 用途 | 缓存 | 缓冲 | 分配 | 
|---|---|---|---|---|---|
| Device Non-cacheable | 4‘b0000 | 设备寄存器 | 否 | 否 | 否 | 
| Normal Non-cacheable | 4‘b0001 | 不需要缓存但可缓冲的内存区域(如 DMA 缓冲区) | 否 | 是 | 否 | 
| Write-Back Cacheable | 4‘b1111 | 普通系统内存(如程序堆栈) | 是 | 是 | 是 | 
| Write-Through Cacheable | 4‘b1011 | 需要缓存且写操作需同时更新内存的区域 | 是 | 是 | 是 | 
重要区别:Device vs Normal Non-cacheable
- 两者都是 
Non-cacheable。 - 关键区别在于 
Bufferable位。Device (B=0): 用于有副作用、对顺序敏感的设备访问。必须等待最终完成。Normal Non-cacheable (B=1): 用于无副作用的内存访问(例如,一块标记为 non-cacheable 的 DMA 缓冲区)。写入可以先进写缓冲区,处理器可以继续执行,无需等待写入最终完成,提高了效率。
 
软件视角:如何设置?
在软件中,特别是在编写驱动程序或设置 MMU(内存管理单元)时,程序员需要为设备寄存器的内存映射区域配置正确的页表属性。
在 ARM 架构中,这通常意味着在页表描述符中设置:
- Memory Type:
Device或Strongly-ordered(这两种类型对应到 AXI 上基本都是Device Non-cacheable行为,Strongly-ordered的要求甚至更严格)。
 - Shareability:
- 通常设置为 
Outer Shareable或Global,以确保不同核心(或其它主机,如 DMA)对设备的访问是相互可见和有序的。 
 - 通常设置为 
 
例如,在 Linux 内核中,用 ioremap() 函数来映射设备寄存器时,内核会自动将其映射为 Device Non-cacheable 类型。而你用 dma_alloc_coherent() 分配 DMA 缓冲区时,它可能会被映射为 Normal Non-cacheable。
总结
- 是什么: 
Device Non-cacheable是 AXI 协议中一种关键的内存事务属性,配置为 AxCACHE = 0b0000(Non-bufferable, Non-cacheable)。 - 为什么: 它是为访问内存映射的设备寄存器而设计的,这些访问具有副作用和严格的顺序要求。
 - 做什么: 它强制每次访问都直达设备,并且写操作必须等待设备的最终确认,从而确保软件可以精确地控制硬件状态。
 - 在哪用: 所有设备驱动程序的开发都依赖于正确设置此属性,通常由操作系统内核在映射设备地址空间时自动完成。
 
简单来说,Device Non-cacheable 是处理器与硬件设备之间一种“简单、直接、可靠”的通信方式,避免了任何可能引起歧义的优化手段。
                    
                
                
            
        
浙公网安备 33010602011771号