内存类型Normal Non-cacheable Bufferable详解
好的,我们来深入剖析 AXI 协议中一个非常实用且常见的内存属性:Normal Non-cacheable Bufferable。
这个属性是性能与一致性之间一个经典的、精心设计的权衡。理解它对于设计高性能的嵌入式系统和驱动至关重要。
核心结论先行
- 是什么: 这是一种用于普通内存(Normal Memory) 的属性,它要求访问不经过缓存,但允许写操作被缓冲。
 - 目标: 在保证数据最终一致性(所有访问者最终都看到相同数据)的前提下,显著提升写入性能。
 - 核心价值: 它是DMA缓冲区和共享内存区域的理想选择,因为它避免了缓存一致性的开销,同时通过写缓冲隐藏了相对缓慢的内存写入延迟。
 
详细解析
1. 属性定义:AxCACHE = 4‘b0001
让我们分解这个信号:
- 
Non-cacheable (C=0):
- 这是根本。该事务绝不能与缓存(Cache)发生任何关系。
 - 读操作必须从主内存(DDR)获取数据。
 - 写操作的目标是主内存(DDR)。
 - 这确保了所有总线主设备(CPU, DMA, GPU等)看到的都是内存中的同一份数据,避免了缓存一致性(Cache Coherency)的复杂问题。
 
 - 
Bufferable (B=1):
- 这是关键所在,也是性能提升的来源。
 - 它允许写操作被放入一个写缓冲区(Write Buffer) 中。
 - 发起写操作的主机(如 CPU)可以立即得到一个“完成”响应,然后继续执行后续指令,而无需等待数据真正穿越系统互联并物理写入 DDR。
 - 写缓冲区会异步地、在后台将数据最终完成到内存中。
 
 - 
Non-allocate (RA=0, WA=0):
- 自然不会分配缓存行。
 
 
2. 内存类型:Normal
再次强调,这个属性的目标是 Normal Memory 区域(如 DDR)。这意味着:
- 无副作用: 多次读取同一地址不会改变数据本身。
 - 允许重试: 如果访问失败,可以安全地重试。
 - 访问顺序相对灵活: 系统互联可以对访问进行优化和重排序,只要最终结果符合内存一致性模型。
 
行为与工作原理
写操作流程(CPU Perspective):
- CPU 执行一条存储指令(如 
STR),目标地址被标记为Normal Non-cacheable Bufferable。 - 数据被 CPU 的总线接口单元放入写缓冲区。
 - 几乎立即,CPU 收到一个“写入成功”的确认。CPU 的流水线可以继续流动,不会因为这次内存写入而停滞。
 - 在后台,写缓冲区负责将数据通过 AXI 互联发送到内存控制器,最终写入 DDR。这个过程对 CPU 是透明的。
 
读操作流程:
- CPU 执行一条加载指令(如 
LDR),目标地址是Normal Non-cacheable。 - 由于是 
Non-cacheable,请求会直接发送到内存控制器。 - CPU 必须等待数据从 DDR 读取并返回。读操作不能被缓冲(缓冲读会引入陈旧的旧数据),因此读延迟是真实的。
 
为什么需要它?—— 性能与一致性的完美权衡
这是一种“鱼与熊掌兼得”的策略:
- 
避免缓存一致性开销 (Non-cacheable 的好处):
- 当多个主设备(如 CPU 和 DMA)共享一块内存时,如果 CPU 缓存了该内存,就需要复杂的缓存一致性协议(如硬件嗅探)来保证数据同步,这会消耗总线带宽和功耗。
 - 直接标记为 
Non-cacheable,就彻底避免了这个问题。所有设备都直接读/写 DDR,数据视图天然就是一致的。这是一种简单而有效的共享方案。 
 - 
提升写入性能 (Bufferable 的好处):
- 写入 DDR 的速度远慢于 CPU 的执行速度。如果每次写都要等 (
Non-bufferable),CPU 会花费大量时间“空转等待”。 Bufferable允许 CPU“ fire-and-forget”(发射后不管),将数据扔进写缓冲区后就去干别的事情,极大地隐藏了内存写入延迟,提高了 CPU 的利用率和系统整体吞吐量。
 - 写入 DDR 的速度远慢于 CPU 的执行速度。如果每次写都要等 (
 
典型应用场景
- 
理想的 DMA 缓冲区:
- 场景: 网卡接收数据包。CPU 需要分配一块内存给网卡(DMA)存放收到的数据。网卡写完数据后,需要通知 CPU 来处理。
 - 为什么是它:
Non-cacheable: 确保了 CPU 去处理数据时,直接从 DDR 读取,看到的是网卡 DMA 写入的最新数据,而不是自己缓存里的旧数据。Bufferable: 当 CPU 要配置 DMA 或更新缓冲区描述符时,写入操作可以被缓冲,CPU 无需等待,从而能更快地响应网卡和处理其他任务。
 
 - 
大量数据初始化:
- 场景: 清零一块大内存、或向帧缓冲区(Frame Buffer)填充图像数据。
 - 为什么是它: 顺序写入大量数据是 
Bufferable属性最能发挥优势的地方。CPU 可以以最高速度连续发出写操作,只需关心写缓冲区是否满,而无需关心 DDR 的实际写入速度。 
 - 
多核间通信的共享内存:
- 场景: 两个CPU核心通过共享内存传递消息。
 - 为什么是它: 
Non-cacheable保证了一个核心写入的数据,另一个核心能立刻看到(因为都在直接访问DDR)。Bufferable允许写入方核心高效地执行写入操作。 
 
潜在风险与注意事项
- 数据可见性的延迟: “写入完成”并不代表数据真的在DDR里了,只代表它在写缓冲区里。如果另一个主设备(如DMA)在数据从写缓冲区刷到DDR之前就去读取,它可能会读到旧数据。
 - 解决方案: 这就需要内存屏障(Memory Barrier) 指令(如 ARM 的 
DMB或DSB)。在 CPU 通知其他设备“数据已就绪”之前,必须插入一个屏障,确保所有在屏障之前的缓冲写操作都已经真正完成到内存中。 
示例:
// CPU 准备数据给 DMA
*(volatile uint32_t*)dma_buffer = data; // Bufferable write, goes to write buffer
// ... more bufferable writes ...
DSB(); // Data Synchronization Barrier: Flushes the write buffer, waits for all writes to complete
// Now it's safe to tell the DMA engine that the data is ready
*(volatile uint32_t*)dma_status_reg = DMA_GO; // This should be a Device write
对比总结
| 属性 | AxCACHE | 读操作 | 写操作 | 优点 | 缺点 | 适用场景 | 
|---|---|---|---|---|---|---|
| Normal Non-cacheable Bufferable | 4‘b0001 | 直达内存,慢 | 可缓冲,CPU立即继续 | 高性能共享,避免缓存开销 | 需屏障保证最终可见性 | DMA缓冲区、共享内存、大数据块操作 | 
| Normal Non-cacheable Non-bufferable | 4‘b0000 | 直达内存,慢 | 直达内存,CPU等待 | 写操作立即可见 | 性能差 | 对写完成有即时要求的严格共享数据 | 
| Normal Write-Back Cacheable | 4‘b1111 | 高速缓存命中 | 写回缓存 | 极致性能 | 缓存一致性开销大 | 处理器私有代码和数据 | 
总结
Normal Non-cacheable Bufferable 是 AXI 协议中为共享内存场景设计的高性能实用属性。
- 它的设计哲学: 通过 
Non-cacheable保证多设备数据视图的最终一致性,同时通过Bufferable来最大化写入操作的效率。 - 它的适用场景: 几乎是设备DMA操作和核间通信的标准配置。
 - 对程序员的要求: 开发者必须意识到写操作的异步性,并在需要保证数据全局可见性的关键点,主动使用内存屏障指令来同步操作。
 
                    
                
                
            
        
浙公网安备 33010602011771号