Начал пользоваться встроенным в процессорную часть PS DMA.
Примеры работают, принцип понял, но есть проблема.
За основу взял пример
xdmaps_example_w_intr.cЕсть общий файл
app_xdmaps.cВ нем функции
Код
static char Checked [NUMOF_USED_DMA];
int XDMA_init();
int Setup_DMA_Interrupt_System();
void DmaDoneHandler(unsigned int HandleChannel, XDmaPs_Cmd *DmaCmd, void *CallbackRef)
{
Checked[HandleChannel] = 1;
}
int XDMA_PS_memcpy(char *pDst,char *pSrc, size_t len){
// Some code
XDmaPs_SetDoneHandler(&DmaInstance,Channel,DmaDoneHandler,(void *)Checked);
status=XDmaPs_Start(&DmaInstance, Channel, &DmaCmd, 0);
while (!Checked[Channel]&& (TimeOutCnt < TIMEOUT_LIMIT)) {
TimeOutCnt++;
}
if (TimeOutCnt >= TIMEOUT_LIMIT) {
xil_printf("%d Timeout FAILED :-( \r\n",cmd_cnt);
xil_printf("%d Exit XDMA_PS_memcpy \r\n",cmd_cnt);
return status;
}
}
При инициации платформы конфигурирую контроллер DMA, конфигурирую контроллер прерываний, включаю прерывания. Все как в образце.
Затем вызываю функцию XDMA_PS_memcpy.
Указатели src dst и len не обрабатываю, шлю транзакции между фиксированными адресами фиксированной длины.
И вот после вызова функции происходит ситуация, что прерывание как будто "блокируется" кем то. То есть пока я не выйду из функции XDMA_PS_memcpy обработчик прерываний DmaDoneHandler не вызовется. Если убрать счетчик таймаута, то не вызовется никогда.
То есть лог работы выглядит так
Код
1 Timeout FAILED :-(
1 Exit XDMA_PS_memcpy
Handled channel 0
2 Timeout FAILED :-(
2 Exit XDMA_PS_memcpy
Handled channel 0
3 Timeout FAILED :-(
3 Exit XDMA_PS_memcpy
Срабатывает таймаут, выход из функции, вызов обработчика прерываний. Ок, подумал я, попробую сделать в лоб.
Функция XDmaPs_Start может возвращать значения занято, ошибка, Ок. Будем вызывать ее в цикле, пока занято не превратиться в Ок
Код
do {
status=XDmaPs_Start(&DmaInstance, Channel, &DmaCmd, 0);
Channel=(Channel+1) % NUMOF_USED_DMA;
}
while (status==XST_DEVICE_BUSY);
В итоге через некоторое время работы я умудряюсь все 8 каналов погрузить в состояние бизи, то есть результат команды для всех каналов навсегда остается XST_DEVICE_BUSY
Что я могу делать не так?