Я написал специальный драйвер для AXI DMA, который использует функции ядра Linux DMA по умолчанию, поскольку Xilinx написала свой драйвер, который интегрируется в Linux. Поскольку оба моих порта M_AXI_SG и M_AXI_S2MM подключены к PL RAM (
Код: Выделить всё
0x4_0000_0000Код: Выделить всё
reserved-memory {
#address-cells = ;
#size-cells = ;
ranges;
pl_dma_pool: dma_pool@400000000 {
compatible = "shared-dma-pool";
no-map;
reg = ;
};
};
reserved-mem@400000000 {
compatible = "xlnx,reserved-memory";
memory-region = ;
};
Код: Выделить всё
axi_dma_0: dma@80000000 {
interrupts = ;
compatible = "xlnx,axi-dma-7.1", "xlnx,axi-dma-1.00.a";
xlnx,s2mm-data-width = ;
xlnx,mm2s-burst-size = ;
xlnx,m-axi-mm2s-data-width = ;
xlnx,num-s2mm-channels = ;
xlnx,dlytmr-resolution = ;
interrupt-parent = ;
xlnx,sg-length-width = ;
xlnx,prmry-is-aclk-async = ;
xlnx,include-s2mm-sf = ;
#dma-cells = ;
xlnx,ip-name = "axi_dma";
xlnx,single-interface = ;
xlnx,sg-include-stscntrl-strm = ;
xlnx,include-s2mm-dre = ;
reg = ;
xlnx,addr-width = ;
xlnx,include-s2mm = ;
clocks = ,
,
;
xlnx,s-axis-s2mm-tdata-width = ;
xlnx,micro-dma = ;
xlnx,increase-throughput = ;
xlnx,mm2s-data-width = ;
xlnx,addrwidth = ;
xlnx,include-sg;
xlnx,sg-use-stsapp-length = ;
xlnx,m-axis-mm2s-tdata-width = ;
xlnx,edk-iptype = "PERIPHERAL";
xlnx,s2mm-burst-size = ;
xlnx,m-axi-s2mm-data-width = ;
xlnx,num-mm2s-channels = ;
xlnx,enable-multi-channel = ;
status = "okay";
xlnx,include-mm2s-sf = ;
clock-names = "m_axi_s2mm_aclk", "m_axi_sg_aclk", "s_axi_lite_aclk";
interrupt-names = "s2mm_introut";
xlnx,include-mm2s = ;
xlnx,include-mm2s-dre = ;
phandle = ;
memory-region = ;
dma_channel_80000030: dma-channel@80000030 {
interrupts = ;
xlnx,datawidth = ;
xlnx,device-id = ;
compatible = "xlnx,axi-dma-s2mm-channel";
dma-channels = ;
phandle = ;
memory-region = ;
};
};
axidma_driver {
compatible = "xlnx,axidma_driver";
reg = ;
dmas = ;
dma-names = "axidma_rx";
dma-coherent;
memory-region = ;
};
В моей функции setup_transfer(), которая вызывается в ioctl(), я использую axidmatest.c в качестве примера и выполните этот код:
Код: Выделить всё
spin_lock(&adev->s2mm->lock);
adev->s2mm->transfer_complete = false;
spin_unlock(&adev->s2mm->lock);
sg_init_table(adev->s2mm->sglist, BD_CNT);
for (int i = 0; i < BD_CNT; i++) {
sg_set_buf(&adev->s2mm->sglist[i], adev->s2mm->data_virt_addr + i*TRANSFER_SIZE, TRANSFER_SIZE);
sg_dma_address(&adev->s2mm->sglist[i]) = data_phys_addr + i * TRANSFER_SIZE;
sg_dma_len(&adev->s2mm->sglist[i]) = TRANSFER_SIZE;
}
adev->s2mm->desc = adev->s2mm->dma_dev->device_prep_slave_sg(adev->s2mm->dma_channel, adev->s2mm->sglist, BD_CNT, DMA_DEV_TO_MEM, flags, NULL);
if (!adev->s2mm->desc) {
pr_err("Failed to prepare SG list\n");
return -ENOMEM;
}
adev->s2mm->desc->callback = axidma_callback;
adev->s2mm->desc->callback_param = adev;
adev->s2mm->cookie = adev->s2mm->desc->tx_submit(adev->s2mm->desc);
dma_async_issue_pending(adev->s2mm->dma_channel);
Вот дампы регистров. Первый находится в начале зонда(), второй — в конце зонда() и третий — в конце setup_transfer():
Код: Выделить всё
[ 4.688662] axidma: loading out-of-tree module taints kernel.
[ 4.695278] AXI DMA driver initialization started!
[ 4.700074] Successfully allocated AXI DMA device!
[ 4.704865] axidma_driver 80000000.axidma_driver: Reg base address: 0x0x0000000080000000, size: 0x10000
[ 4.714274] axidma_driver 80000000.axidma_driver: Reg virtual address: 0xffff800081b50000
[ 4.722456] axidma_driver 80000000.axidma_driver: Register 48 stores: 0x00017002
[ 4.729851] axidma_driver 80000000.axidma_driver: Register 52 stores: 0x00010009
[ 4.737246] axidma_driver 80000000.axidma_driver: Register 56 stores: 0x00000000
[ 4.744642] axidma_driver 80000000.axidma_driver: Register 60 stores: 0x00000000
[ 4.752037] axidma_driver 80000000.axidma_driver: Register 64 stores: 0x00000000
[ 4.759432] axidma_driver 80000000.axidma_driver: Register 68 stores: 0x00000000
[ 4.766828] Successfully allocated S2MM channel!
[ 4.772648] Successfully requested S2MM DMA channel!
[ 4.777626] Successfuly acquired DMA device!
[ 4.782029] axidma_driver 80000000.axidma_driver: assigned reserved memory node dma_pool@400000000
[ 5.730493] Successfully allocated data buffer!
[ 5.735022] Successfully allocated SG list!
[ 5.739394] Successfully registered miscellaneous device!
[ 5.744822] axidma_driver 80000000.axidma_driver: Register 48 stores: 0x00017002
[ 5.752227] axidma_driver 80000000.axidma_driver: Register 52 stores: 0x00010009
[ 5.759631] axidma_driver 80000000.axidma_driver: Register 56 stores: 0x00000000
[ 5.767035] axidma_driver 80000000.axidma_driver: Register 60 stores: 0x00000000
[ 5.774438] axidma_driver 80000000.axidma_driver: Register 64 stores: 0x00000000
[ 5.781841] axidma_driver 80000000.axidma_driver: Register 68 stores: 0x00000000
root@rfsoc-axrf47-sdt-wave:~# axidma-transfer
axidma-transfer started!
axidma device opened successfully!
[ 28.739513] Entered axidma_mmap()
[ 28.758756] axidma_driver 80000000.axidma_driver: Register 48 stores: 0x00017002
[ 28.766193] axidma_driver 80000000.axidma_driver: Register 52 stores: 0x00014509
[ 28.773603] axidma_driver 80000000.axidma_driver: Register 56 stores: 0x019A4000
[ 28.781009] axidma_driver 80000000.axidma_driver: Register 60 stores: 0x00000000
[ 28.788416] axidma_driver 80000000.axidma_driver: Register 64 stores: 0x019A407C
[ 28.795815] axidma_driver 80000000.axidma_driver: Register 68 stores: 0x00000000
[ 28.803210] AXI DMA transfer has been set up!
mmap() executed successfully!'nTransfer started successfully!
[ 28.807642] Entered axidma_poll()
[ 28.816371] Went past poll_wait()
Подробнее здесь: https://stackoverflow.com/questions/798 ... -on-zynqmp
Мобильная версия