Nerevarine1810 0 3 мая, 2018 Опубликовано 3 мая, 2018 · Жалоба Собственно, тема баян (судя по поисковику). Кто-то сразу предлагает на регистрах организовать. Мне же хочется все запустить на HAL. В итоге имеем систему с Nios, on-chip, SDRAM, UART, DMA, VIC и прочим. UART подключен к Nios и WriteMaster DMA. ReadMaster подключен к on-chip и sdram. Необходимо средствами HAL NIOS заставить передать массив символов в UART с помощью DMA и вызвать прерывание по окончанию работы. Что же получается: вроде как функции выполняют свою работу, прерывание вызывается, но в UART ничего не идет. Фирменный мануал курил (особенно понравились ссылки из одного документа на другой ради парочки неинформативных предложений). Есть чувство, что кое-что упустил. #include <...> // Все инклуды volatile int dma_complete = 0; char msg[6] = "Hello"; char msg_input[10]; alt_dma_txchan DMA_UART_TX; // Регистрируем прерывание UART static void UART_interrupt (void* context, alt_u32 id) __attribute__((section (".exceptions"))); static void UART_interrupt (void* context, alt_u32 id) { alt_u16 status = IORD_ALTERA_AVALON_UART_STATUS(UART_BASE); IOWR_ALTERA_AVALON_UART_STATUS(UART_BASE, 0); // Обработка UART } static void init_uart (void* base, alt_u32 irq_controller_id, alt_u32 irq) { alt_ic_isr_register (irq_controller_id, irq, UART_interrupt, base, NULL); } // Прерывание DMA_1 static void DMA_1_interrupt (void* handle) __attribute__((section (".exceptions"))); static void DMA_1_interrupt (void* handle) { dma_complete = 1; } int main() { init_uart ((void *)UART_BASE, UART_IRQ_INTERRUPT_CONTROLLER_ID, UART_IRQ); alt_ic_irq_enable(UART_IRQ_INTERRUPT_CONTROLLER_ID, UART_IRQ); printf("Init UART\n"); DMA_UART_TX = alt_dma_txchan_open (DMA_1_NAME); if (DMA_UART_TX == NULL) printf("DMA open error\n"); else { if (alt_dma_txchan_ioctl (DMA_UART_TX, ALT_DMA_SET_MODE_8, NULL) < 0) printf ("Failed to set ALT_DMA_SET_MODE_8"); if (alt_dma_txchan_ioctl (DMA_UART_TX, ALT_DMA_TX_ONLY_ON, (void *)UART_BASE + 1) < 0) printf ("Failed to set ALT_DMA_TX_ONLY_ON"); int dma_tx_done = alt_dma_txchan_send( DMA_UART_TX, msg, sizeof(msg), DMA_1_interrupt, NULL ); if (dma_tx_done < 0) printf("DMA TX error %d\n", dma_tx_done); } while(1) { if (dma_complete) { printf("DMA transferred\n"); if (alt_dma_txchan_ioctl (DMA_UART_TX, ALT_DMA_TX_ONLY_OFF, NULL) < 0) printf ("Failed to set ALT_DMA_TX_ONLY_OFF"); dma_complete = 0; } } return 0; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
doom13 0 3 мая, 2018 Опубликовано 3 мая, 2018 · Жалоба Необходимо средствами HAL NIOS заставить передать массив символов в UART с помощью DMA и вызвать прерывание по окончанию работы. Нет у данного ядра поддержки DMA (если только пробовать по 1му байту в него данные толкать и софтом мониторить статус отправки, но какой тогда смысл в DMA). Очень хочется DMA - сделайте свой драйвер UART на шину Avalon-ST и пользуйтесь SgDMA. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Nerevarine1810 0 3 мая, 2018 Опубликовано 3 мая, 2018 (изменено) · Жалоба Если не секрет, то для чего DMA в QSYS добавлено? И нет поддержки на уровне HAL или в целом? P.S. У самого что-то передать получилось (использовал регистры вместо HAL), правда в UART залетал только последний символ из массива, как будто DMA отправил все по адресу, не задумываясь о медлительности UART. P.S.S. Кстати, на форумах использовали прием через DMA (как я понял успешно), сам не пробовал. Передать бы сначала Изменено 3 мая, 2018 пользователем Nerevarine Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
doom13 0 3 мая, 2018 Опубликовано 3 мая, 2018 · Жалоба Если не секрет, то для чего DMA в QSYS добавлено? И нет поддержки на уровне HAL или в целом? P.S. У самого что-то передать получилось (использовал регистры вместо HAL), правда в UART залетал только последний символ из массива, как будто DMA отправил все по адресу, не задумываясь о медлительности UART. P.S.S. Кстати, на форумах использовали прием через DMA (как я понял успешно), сам не пробовал. Передать бы сначала Прикрутить DMA к ядру UART, которое Вы и добавили в Qsys не получится. Доку на UART почитайте, там три регистра, в тхбуффер писать можно только если он пустой, использование DMA не предполагает проверку статуса готовности UART к передаче :) Свое UART-ядро сделайте с шиной Avalon-ST и будет возможность с SgDMA состыковать. Поддержка DMA/SgDMA/mSgDMA есть, но тут вопрос не в наличии софтовых драйверов, а в возможности корректно состыковать железо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Nerevarine1810 0 4 мая, 2018 Опубликовано 4 мая, 2018 (изменено) · Жалоба Благодарю за разъяснения) теперь это становится понятным У самого что-то передать получилось (использовал регистры вместо HAL), правда в UART залетал только последний символ из массива, как будто DMA отправил все по адресу, не задумываясь о медлительности UART Мда... Туго идет изучение Nios Тема закрыта. P.S. Если кому интересно, то все таки получилось реализовать что-то похожее на решение задачи: использовать не простой UART, а FIFOed_Avalon_UART (с буферами на прием и передачу + еще много плюшек). Код практически не изменился. Логика проста: всё сообщение записывается в буфер, а модуль уже сам постепенно отправляет. Возможно, DMA здесь будет лишним грузом при небольших транзакциях. Пока это дело будет стоять до понедельника. У нового модуля достаточно много прерываний полезных. Изменено 4 мая, 2018 пользователем Nerevarine Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться