|
学会操作AXI控制器、DMA及其驱动程序,是一种非常有用的技能,可用于高速数据传输应用。不少同学在初期可能会遇到一些挑战和困难,这也曾是一个让我非常头疼的难点,总以为需要具备广泛的硬件和软件开发技能,要非常熟悉AXI协议、DMA的数据缓冲管理、驱动程序编写等方面的知识,才能上手。
现在回头来看,有一种非常直观且迅速的办法同时掌握这两点。
先使用M_AXI/DMA搭建一个简单的通路,然后再测量分析协议细节,整个过程最好在一小时内。
平台:Zynq MPSoC
环境:Vitis HLS
首先,使用Vitis HLS构建一个工程,实现一个简单的目标:将DDR内存地址a开始的50个int数据通过M_AXI传输到FPGA,将这50个数据每个加100后,通过DMA回传至DDR,存放在地址b之后的50个int空间。
//Vitis HLS代码
void example(volatile int *a, volatile int *b){
#pragma HLS INTERFACE mode=s_axilite port=return
#pragma HLS INTERFACE mode=m_axi port=a depth=50
#pragma HLS INTERFACE mode=m_axi port=b depth=50
int i;
int buff[50];
// memcpy函数会触发突发模式
// memcpy必须本地buff用于暂存
// 多个memcpy函数只会被顺序执行
memcpy(buff, (const int*)a, 50*sizeof(int));
for(i=0; i < 50; i++){
buff = buff + 100;
}
memcpy((int *)b, buff, 50*sizeof(int));
}此函数构建了一个IP模块,包含一个AXI4Lite和AXI4FULL,功能很简单,AXI4Lite用控制DMA的工作状态,AXI4FULL用于数据搬运(AXI4FULL可以控制PS端的AXI互联总线,从而直接操控DDR),具体见裸机驱动程序。
这里提供一种方法,先让你跑通整个过程,然后去测试每一根信号线的变化。充分理解每个信号的作用。
以下是裸机驱动程序:
int main(){
int a[50];
int b[50];
XExample hlsXExample;
Xil_DCacheEnable();//默认是开启DCache的
XExample_Initialize(&hlsXExample,XPAR_XEXAMPLE_0_DEVICE_ID); //初始化
for(i = 0; i < 50; i++){ a = i; }
Xil_DCacheFlushRange((INTPTR)b, 50*sizeof(int)); //刷新内存
XExample_Set_a(&hlsXExample, (INTPTR)a);//设置地址a
XExample_Set_b(&hlsXExample, (INTPTR)b);//设置地址b
XExample_Start(&hlsXExample); //启动DMA
while(XExample_IsDone(&hlsXExample) == 0);
Xil_DCacheInvalidateRange((INTPTR)b, 50*sizeof(int)); //刷新内存
for(i = 0; i < 50; i++){printf(&#34;b[%d] = %d\n\r&#34;, i, b);}
}驱动程序也就三条语句是重点:设置地址a、设置地址b、启动DMA。其余部分都可以暂时不管,因为对于操作DMA而言,我们也就关心你要从DDR哪个地址开始操作数据,以及什么时候开始。
接下来就是通过Vitis IDE编译并运行程序,通过Vivado ILA抓取AXI总线的波形,可以快速掌握AXI协议。
这里提供一种方法,先让你跑通整个过程,然后去测试每一根信号线的变化。充分理解每个信号的作用。
通过学习和实践,可以掌握这些技能,并将其应用于实际应用中,以实现高效的数据传输。因此,不要放弃,保持积极的态度,不断学习和尝试,你也可以掌握这些工具,并在应用中获得提升。 |
|