Собственно, тема баян (судя по поисковику). Кто-то сразу предлагает на регистрах организовать. Мне же хочется все запустить на 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;
}