Zynq Cache问题的解决方法

本文探讨了在PS-PL间DMA传输时出现的Cache一致性问题,并介绍了两种解决方案:禁用Cache及使用Cache Flush和Invalidate操作。提供了裸机及Linux环境下具体的编程实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在进行PS-PL之间的DMA传输时,不可避免会遇到Cache问题。今天在这里讲一下Cache的解决方法。其中参考了forums.xilinx.com的处理方法。
首先解释为什么DMA会引入Cache问题(专业名称为Cache一致性问题)。
PS和PL都在独立运行,PS通过DDR控制器来对DDR存储器进行访问,为了加速,常常将一些数据缓存(Cache),而且不是针对一个数据缓存,而是针对一批(Xilinx称为一行,即Line,一行长度为32)。这样好处很明显,下一次访问速度会加快;但坏处也很明显,就是Cache里的数据如果发生了改变,不能迅速反映到DDR2实际数据中,反之亦然。因此,当PL通过DMA修改了DDR2数据时,CPU可能还不知道发生了些什么,拿到的数据仍然是Cache中的没有改过的数据。
在裸机开发时,规避Cache最简单的方法就是禁用Cache。
#include "xil_cache.h"
void Xil_DCacheDisable(void);
这样操作后,CPU将直接访问DDR内存,读写都是直接的。这样显然会降低CPU性能,但简化了数据传输操作,属于极端的方法。

另外一种操作要多加一道手续,在我的文章【参赛手记】详细介绍AXI-HP接口+DMA+GIC编程中,给出的例程里有Cache Flush和Cache Invalidate操作。从字面理解,Flush就是把Cache里的数据流放出去,清空Cache,也就是将Cache的内容推到DDR中去;而Cache Invalidate表示当场宣布Cache里的内容无效,需要从DDR中重新加载,即把数据从DDR中拉到Cache中来。
理解了这个原理,在编程的时候心里就非常有底气了!
#include "xil_cache.h"
//写点什么到发送缓冲区sendram
Xil_DCacheFlushRange((u32)sendram,sizeofbuffer);//将内容刷新至DDR
//启动发送DMA过程。。。。

//启动接收DMA过程。。。。。
Xil_DCacheInvalidateRange((u32)recvram,sizeofbuffer);//将DDR内容拉进Cache
//从recvram中读取数据吧!

好了,裸机工程下面开发是非常简单的,出错了也容易定位,调试起来方便。在Linux下开发时,由于编写的接口模块处于驱动层面,调试可能不如SDK中那么直观,只能关键部位打印printk,然后慢慢去寻找错误,定位比较麻烦。
在Linux下,Cache的Flush和Invalidate操作需要调用内核函数 dma_sync_single_for_device和 dma_sync_single_for_cpu。
这两个函数包含时可以这样:
#include
其代码可以在内核源码的/arch/arm/include/asm中看到。
同样,在驱动程序中,涉及到DMA操作时,也需要在DMA写之前先Flush,DMA读之后Invalidate操作。
其参数为:第一个参数是device结构体,第二个参数为DMA的实际地址,需要通过虚拟地址到实际地址的映射才能实现(这是Linux的本身特点),第三个参数为方向,可以选择DMA_TO_DEVICE或 DMA_FROM_DEVICE(需要包含头文件#include )。
具体驱动代码如下:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include //use this for dma_sync_single_for_cpu
#include //use this for DMA_FROM_DEVICE
#define DEVICE_NAME "AXI_DMA_DEV"
#define MAX_LEN 8
#define WITH_SG 0
#define AXI_DMA_BASE 0x40440000
#define MM2S_DMACR 0
#define MM2S_DMASR 1
#if WITH_SG
#define MM2S_CURDESC 2
#define MM2S_TAILDESC 4
#else
#define MM2S_SA 6
#define MM2S_LENGTH 10
#endif
#define S2MM_DMACR 12
#define S2MM_DMASR 13
#if WITH_SG
#define S2MM_CURDESC 14
#define S2MM_TAILDESC 16
#else
#define S2MM_DA 18
#define S2MM_LENGTH 22
#endif

static void __iomem* Regs;
int *sendbuffer;
int *recvbuffer;

static int axi_dma_open(struct inodeinode,struct filefilp)
{
return 0;
}
static int axi_dma_release(struct inodeinode,struct file filp)
{
return 0;
}
static int axi_dma_ioctl(struct file
filp,unsigned int reg_num,unsigned long arg)
{
if((reg_numMM2S_DMACR)||(reg_numMM2S_DMASR)||(reg_numMM2S_SA)||(reg_numMM2S_LENGTH)||(reg_numS2MM_DMACR)||(reg_numS2MM_DMASR)||(reg_numS2MM_DA)||(reg_numS2MM_LENGTH))
{
iowrite32(arg,Regs+reg_num
4);
printk("axi_dma:Write data 0x%x to address 0x%x!\n",arg,Regs+reg_num*4);
}
else
{
printk("axi_dma:[ERROR] Wrong register number!\n");
return -EINVAL;
}
return 0;
}

static int axi_dma_read(struct file*filp,char *buffer,size_t length,loff_t * offset)
{
int bytes_read = 0;
int i = 0;
if(filp->f_flags&O_NONBLOCK)
{
return -EAGAIN;
}
if((length>0)&&(length

### 复旦微 Zynq FMQL45T900 Cache 配置及常见问题 对于从100tai芯片更换至45T900芯片的情况,在集成开发环境(IAR)中的确可能需要调整一些配置文件,特别是涉及硬件调试接口的部分,比如`I-jet independent.ProbeConfig`等设置[^1]。 #### 一、缓存(Cache)概述 复旦微Zynq系列器件FMQL45T900内置有L1指令和数据缓存以及共享的L2缓存。这些缓存在提高处理器性能方面起着至关重要的作用。具体来说: - **L1 缓存**:每个ARM Cortex-A9内核拥有独立的32KB L1指令缓存和32KB L1数据缓存。 - **L2 缓存**:两个A9内核共用512KB统一结构(L1+L2)的二级缓存。 #### 二、Cache配置要点 当涉及到不同型号之间的迁移时,需要注意以下几点关于缓存配置的变化: - **一致性模型**:确保新旧平台之间的一致性协议相同;如果发生变化,则需相应更新软件驱动程序以适应新的内存访问模式。 - **预取机制**:某些高级特性如分支预测或DMA传输可能会依赖特定版本的CPU核心实现方式,因此建议查阅最新版的手册来确认是否有任何差异并作出适当调整。 - **电源管理策略**:现代SoC通常具备多种省电状态,这会影响缓存的行为(例如自动关闭未使用的部分)。应仔细审查目标设备文档中有关功耗优化方面的指导方针,并据此修改应用程序逻辑。 #### 三、常见问题解答 针对可能出现的问题提供如下解决方案: - 如果遇到频繁的数据丢失现象,可能是由于不当的操作导致了缓存失效或者刷新不及时造成的。此时可以尝试通过编程手段强制同步缓存内容到主存储器。 - 对于多线程环境下发生的竞争条件错误,考虑启用硬件级别的互斥锁功能或是采用更精细粒度的锁定方案来保护临界区资源。 ```c // 清除整个D-cache的例子 void flush_dcache_all(void){ asm volatile ("mcr p15, 0, %0, c7, c14, 0" : : "r"(0)); } ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值