本文以下的描述均为建立在pl端已经创建好程序,本文主要描述不使用petalinux,使用原版的linux根据SDK提供的例程进行移植的。
demo工程测试
能够移植成功的前提是要先通过sdk工程的demo测试,建立axidma工程,在bsp system.mss里面选择下面的demo工程:
这是一个不带中断的轮训demo,通过不断查询总线是否空闲的标志位来判断pl端是否有数据写入,测试通过后,说明pl-pl的链路是没有问题的,可以基于此demo进行移植,这里我就不把我的测试结果贴出来的,可以通过查看内存值或者打印数据的方式来检验。
移植到linux应用程序中
这里说明几个特别的注意事项然后贴上自己的代码就好了,都是我使用的时候出现问题的地方。
1、MAX_PKT_LEN需要与pl端设置的每包长度保持一致,可以是其整数倍;
2、因为linux用户空间是没有办法看到物理地址的,所以需要进行寄存器地址的映射,基本上使用的都是mmap这个库函数实现。
下面主要是两段代码,一段是初始化,一段是数据搬运;
//初始化代码
int XAxiDma_Init(u16 DeviceId)
{
XAxiDma_Config *CfgPtr;
int Status;
int Tries = NUMBER_OF_TRANSFERS;
int Index;
g_pio_fd = open("/dev/mem", O_RDWR|O_SYNC);
g_rx_buffer_base_map = (unsigned char *)mmap(NULL,0xffff, 0x01|0x02,MAP_SHARED, g_pio_fd,RX_BUFFER_BASE);
if(g_rx_buffer_base_map == MAP_FAILED)
{
iray_err("sharemen_map_base mapping for absolute memory access failed.\n");
return -1;
}
g_dma_base_reg_map = (unsigned char *)mmap(NULL,0xffff, 0x01|0x02,MAP_SHARED, g_pio_fd,XPAR_AXI_DMA_0_BASEADDR);
if(g_dma_base_reg_map == MAP_FAILED)
{
iray_err("sharemen_map_base mapping for absolute memory access failed.\n");
return -1;
}
/* Initialize the XAxiDma device.
*/
CfgPtr = XAxiDma_LookupConfig(DeviceId);
if (!CfgPtr) {
printf("No config found for %d\r\n", DeviceId);
return XST_FAILURE;
}
CfgPtr->BaseAddr = (UINTPTR)g_dma_base_reg_map;
//printf("ox%x, 0x%x\n", (UINTPTR)dma_base_reg_map, dma_base_reg_map);
Status = XAxiDma_CfgInitialize(&g_AxiDma, CfgPtr);
if (Status != XST_SUCCESS) {
printf("Initialization failed %d\r\n", Status);
return XST_FAILURE;
}
if(XAxiDma_HasSg(&g_AxiDma)){
printf("Device configured as SG mode \r\n");
return XST_FAILURE;
}
/* Disable interrupts, we use polling mode
*/
XAxiDma_IntrDisable(&g_AxiDma, XAXIDMA_IRQ_ALL_MASK,
XAXIDMA_DEVICE_TO_DMA);
XAxiDma_IntrDisable(&g_AxiDma, XAXIDMA_IRQ_ALL_MASK,
XAXIDMA_DMA_TO_DEVICE);
printf("当前代码行:%d\n", __LINE__);
for(Index = 0; Index < Tries; Index ++) {}
/* Test finishes successfully
*/
return XST_SUCCESS;
}
//数据搬运代码
int XAxiDma_Read_From_Pl(void)
{
int Status;
Status = XAxiDma_SimpleTransfer(&g_AxiDma,(UINTPTR) RX_BUFFER_BASE,
MAX_PKT_LEN, XAXIDMA_DEVICE_TO_DMA);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
return Status;
}
主要程序实现就是这些了,后面可以自己实现sg模式的dma,一般在图像开窗的时候可以使用,理论上也是比较简单的。
大家有问题可以相互讨论,我也是小白,微信 yucaohua001