Сигналы Zynq7000 PS DMA "Готово" слишком скоро

TL;DR: встроенный DMA Zynq7000 PS возвращает сигнал "Готово" слишком рано. Кажется, он сигнализирует, как только он (я предполагаю) заполнил свое внутреннее "MFIFO" и больше не нуждается в доступе к источнику данных. Но мой SW должен знать, когда он фактически закончил передачу данных.

Имеет ли PS DMA бит состояния, чтобы указать, завершена ли передача? Документация Xilinx неясна для некоторых из этих регистров DMA ( http://www.xilinx.com/support/documentation/user_guides/ug585-Zynq-7000-TRM.pdf, стр. 276).

Я использую DMA для перекачки данных из памяти DDR в PL IP, используя следующий код C:

// Allocate memory in DDR, 1600 bytes PLZ.
char *mem_block = malloc(1600*sizeof(char));

// Fill memory with data (not shown)

// Configure the DMA command
memset(&dmaCmd, 0, sizeof(XDmaPS_Cmd));
dmaCmd.ChanCtrl.SrcBurstSize = 1;
dmaCmd.ChanCtrl.SrcBurstLen = 4;
dmaCmd.ChanCtrl.SrcInc = 1;
dmaCmd.ChanCtrl.DstBurstSize = 1;
dmaCmd.ChanCtrl.DstBurstLen = 4;
dmaCmd.ChanCtrl.DstInc = 0; // Do not increment, (Fixed DST Addr.)
dmaCmd.BD.SrcAddr = (u32)mem_block;
dmaCmd.BD.DstAddr = (u32)0x43c10000; // Destination address (in PL)
dmaCmd.BD.Length  = 1600; // Bytes

Я тогда начинаю передачу DMA...

status = XDmaPs_Start(&dmaInst, 0, &dmaCmd, 0);
if (status != XST_SUCCESS) {
    printf("ERROR, could not start DMA Txfer.");
    return XST_FAILURE;
}

И дождитесь его завершения, прежде чем прочитать результат с моего IP.

while (!(Xil_In32(XPAR_PS7_DMA_S_BASEADDR + XDMAPS_INTSTATUS_OFFSET) & 0x00000001)) {
   i++; // Waiting for DMA to finish...
}
result = Xil_In32(0x43c10004); // read result from my IP 
// Result is available as soon as DMA is finished--on the very next 100MHz fabric clock.

У меня проблема в том, что этот результат часто читается слишком рано, до того, как передача данных была завершена. По-видимому, DMA иногда говорит, что это сделано, пока передача DMA все еще продолжается (я могу сказать, потому что из чипоскопа я могу видеть, что чтение происходит, в то время как пакеты записи все еще происходят).

Как я могу настроить свое программное обеспечение так, чтобы оно ожидало, пока DMA фактически не выполнит передачу данных?

1 ответ

Решение

Документация была хорошо замаскирована, но я нашел именно то, что искал.

Когда я набирал этот вопрос, я понял, что в этих регистрах каналов DMA должно быть несколько битов состояния. Оказывается, на самом деле для каждого канала есть регистр состояния канала, младшие 4 бита которого представляют состояние канала. (Мне пришлось покопаться в Приложении B к их документации, чтобы найти его, страница 1201 документа связана с вопросом). Это 4-битное состояние равно 1001 ("Завершено"), когда DMA вызвало DONE, но все еще передает данные, и переходит в 0000 ("Остановлено"), когда канал фактически завершен.

Xilinx даже предоставляет удобный макрос в своем автоматически сгенерированном BSP, чтобы получить смещение для адреса регистра состояния каждого канала: XDmaPs_CSn_OFFSET(n) где n это номер канала -0 в моем случае.

Мое исправление состояло в том, чтобы просто изменить цикл while, чтобы проверить состояние канала, чтобы перейти в состояние "Остановлено", сигнализируя о завершении передачи.

while (!(Xil_In32(XPAR_PS_DMA_S_BASEADDR + XDmaPs_CSn_OFFSET(0) & 0x0000000F) != 0x00000000) {
    // Wait until done
    i++;
}
// Now DMA is truly, really done transferring data.
// get real result
result = Xil_In32(0x43C10004); // Read from my IP

Надеюсь, что это может сэкономить кому-то время и разочарование!:D

Другие вопросы по тегам