Программа передает массив данных из Zynq-7000 PS DDR в память BRAM IP (блочная RAM) в PL-части FPGA из-за PL AXI DMA IP. Используя драйвер dma xilinx axi (не режим разброса-сбора), контроллер прерываний и функцию printf поставщика, массив данных переносится из DDR в BRAM.
main.c
#include "xstatus.h"
#include "platform_.h"
#include "axi_dma_intr_poll.h"
#define TX_BUFFER (uint32_t *) 0x01100000
#define RX_BUFFER (uint32_t *) XPAR_BRAM_0_BASEADDR
#define RESET_TIMEOUT_CNTR_VAL 0x1000
#define MAX_TX_VALUE 0x100
#define PAYLOAD_SIZE MAX_TX_VALUE
volatile _Bool tx_done_flag, rx_done_flag, tx_error, rx_error;
axi_dma_init_str init;
axi_dma_poll_str poll;
axi_dma_handler_str handler;
static void tx_intr_handler(void *callback);
static void rx_intr_handler(void *callback);
static inline void printf_array(uint32_t *p_array, size_t size);
int main(void) {
uint8_t mul_coefficient = 0;
const uint8_t c_ascii_num_offset = 0x30;
uint32_t i = 0;
memset((uint8_t *) XPAR_BRAM_0_BASEADDR,0,0x100);
init.dma_id = XPAR_AXIDMA_0_DEVICE_ID;
init.rx_intr_handler = rx_intr_handler;
init.tx_intr_handler = tx_intr_handler;
init.rx_intr_id = XPAR_FABRIC_AXIDMA_0_S2MM_INTROUT_VEC_ID;
init.tx_intr_id = XPAR_FABRIC_AXIDMA_0_MM2S_INTROUT_VEC_ID;
poll.p_tx_buf = TX_BUFFER;
poll.p_rx_buf = RX_BUFFER;
poll.size = PAYLOAD_SIZE;
axi_dma_init(&init, &handler);
while(1) {
xil_printf("AXI DMA %d: ready. Insert multiplier coefficient (1 - 9): ", init.dma_id);
mul_coefficient = inbyte();
mul_coefficient -= c_ascii_num_offset;
if ((0 == mul_coefficient) || (mul_coefficient > 9)) {
xil_printf("nrAXI DMA %d ERROR: the coefficient must have a value from 1 to 9nr", init.dma_id);
continue;
}
xil_printf("%dnr", mul_coefficient);
for(i = 0; i < MAX_TX_VALUE; i++) {
poll.p_tx_buf[i] = (i * mul_coefficient) % MAX_TX_VALUE;
}
tx_done_flag = FALSE;
rx_done_flag = FALSE;
axi_dma_poll(&poll, &handler.axi_dma, init.dma_id);
xil_printf("AXI DMA %d: waiting completion of the poll...", init.dma_id);
while((FALSE == tx_done_flag) || (FALSE == rx_done_flag)) {
asm("NOP");
}
if ((TRUE == tx_error) || (TRUE == rx_error)) {
xil_printf("AXI DMA %d ERROR: the polling ERROR", init.dma_id);
}
else {
xil_printf("nnrAXI DMA %d: the tx buffer:nr", init.dma_id);
printf_array(TX_BUFFER ,PAYLOAD_SIZE);
xil_printf("nnrAXI DMA %d: the rx buffer:nr", init.dma_id);
printf_array(RX_BUFFER, PAYLOAD_SIZE);
}
xil_printf("nnr");
}
return XST_SUCCESS;
}
static void tx_intr_handler(void *callback) {
uint32_t status = 0;
int reset_cntr = RESET_TIMEOUT_CNTR_VAL;
XAxiDma *axi_dma = (XAxiDma *) callback;
status = XAxiDma_IntrGetIrq(axi_dma, XAXIDMA_DMA_TO_DEVICE);
XAxiDma_IntrAckIrq(axi_dma, status, XAXIDMA_DMA_TO_DEVICE);
tx_done_flag = TRUE;
if (FALSE != (status & XAXIDMA_IRQ_ALL_MASK) &&
(TRUE == (status & XAXIDMA_IRQ_ERROR_MASK))) {
tx_error = TRUE;
XAxiDma_Reset(axi_dma);
while (reset_cntr--) {
if (XAxiDma_ResetIsDone(axi_dma)) {
break;
}
}
}
}
static void rx_intr_handler(void *callback)
{
uint32_t status = 0;
int reset_cntr = RESET_TIMEOUT_CNTR_VAL;
XAxiDma *axi_dma = (XAxiDma *) callback;
status = XAxiDma_IntrGetIrq(axi_dma, XAXIDMA_DEVICE_TO_DMA);
XAxiDma_IntrAckIrq(axi_dma, status, XAXIDMA_DEVICE_TO_DMA);
rx_done_flag = TRUE;
if ((FALSE != (status & XAXIDMA_IRQ_ALL_MASK)) &&
(TRUE == (status & XAXIDMA_IRQ_ERROR_MASK))) {
rx_error = TRUE;
XAxiDma_Reset(axi_dma);
while (reset_cntr--) {
if (XAxiDma_ResetIsDone(axi_dma)) {
break;
}
}
}
}
static inline void printf_array(uint32_t *p_array, size_t size) {
const uint8_t c_values_per_line = 10;
uint32_t i = 0;
for(i = 0; i < size; i++) {
xil_printf("%d ", *(TX_BUFFER + i));
if (FALSE == (i % c_values_per_line) && (0 != i)) {
xil_printf("nr");
}
}
}
axi_dma_intr_poll.c
#include "xil_exception.h"
#include "axi_dma_intr_poll.h"
static int enable_intr_(axi_dma_handler_str *p_handler, axi_dma_init_str *p_init);
int axi_dma_init(axi_dma_init_str *p_init, axi_dma_handler_str *p_handler) {
if ((NULL == p_init) || (NULL == p_handler)) {
xil_printf("AXI DMA %d ERROR: the entire axi_dma_init function ERRORrn", p_init->dma_id);
return XST_FAILURE;
}
memset(p_handler, 0, sizeof(axi_dma_handler_str));
p_handler->p_config = XAxiDma_LookupConfig(p_init->dma_id);
if (NULL == p_handler->p_config) {
xil_printf("AXI DMA %d ERROR: the dma lookup config FAILEDrn", p_init->dma_id);
return XST_FAILURE;
}
if (XST_SUCCESS != XAxiDma_CfgInitialize(&(p_handler->axi_dma), p_handler->p_config)) {
xil_printf("AXI DMA %d ERROR: the dma initialization FAILEDrn", p_init->dma_id);
return XST_FAILURE;
}
if(TRUE == XAxiDma_HasSg(&(p_handler->axi_dma))){
xil_printf("AXI DMA %d ERROR: the device configured as SG modern", p_init->dma_id);
return XST_FAILURE;
}
if (XST_SUCCESS != enable_intr_(p_handler, p_init)) {
xil_printf("AXI DMA %d ERROR: the interrupt setup FAILEDrn");
return XST_FAILURE;
}
return XST_SUCCESS;
}
int axi_dma_poll(axi_dma_poll_str *p_poll, XAxiDma *p_axi_dma, uint32_t dma_id) {
if ((NULL == p_poll) || (NULL == p_axi_dma)) {
xil_printf("AXI DMA %d ERROR: the entire axi_dma_poll function ERRORrn", dma_id);
return XST_FAILURE;
}
Xil_DCacheFlushRange((UINTPTR) (p_poll->p_tx_buf), p_poll->size);
if (XST_SUCCESS != XAxiDma_SimpleTransfer(p_axi_dma,(UINTPTR) (p_poll->p_tx_buf),
p_poll->size, XAXIDMA_DMA_TO_DEVICE)) {
xil_printf("AXI DMA %d ERROR: the tx buffer setting FAILEDrn", dma_id);
return XST_FAILURE;
}
if (XST_SUCCESS != XAxiDma_SimpleTransfer(p_axi_dma,(UINTPTR) (p_poll->p_rx_buf),
p_poll->size, XAXIDMA_DEVICE_TO_DMA)) {
xil_printf("AXI DMA %d ERROR: the rx buffer setting FAILEDrn", dma_id);
return XST_FAILURE;
}
return XST_SUCCESS;
}
int axi_dma_release(XScuGic *p_scu_gic, uint32_t tx_intr_id, uint32_t rx_intr_id) {
if ((NULL == p_scu_gic) || (0 == tx_intr_id) || (0 == rx_intr_id)) {
xil_printf("AXI DMA %d ERROR: the entire axi_dma_release function ERRORrn", p_scu_gic->Config->DeviceId);
return XST_FAILURE;
}
XScuGic_Disconnect(p_scu_gic, tx_intr_id);
XScuGic_Disconnect(p_scu_gic, rx_intr_id);
return XST_SUCCESS;
}
static int enable_intr_(axi_dma_handler_str *p_handler, axi_dma_init_str *p_init) {
const uint8_t c_priority = 0xA0, c_trigger_type = 0x3;
p_handler->p_intc_config = XScuGic_LookupConfig(XPAR_SCUGIC_SINGLE_DEVICE_ID);
if (NULL == p_handler->p_intc_config) {
xil_printf("AXI DMA %d ERROR: the scu gic lookup config FAILEDrn", p_init->dma_id);
return XST_FAILURE;
}
if (XST_SUCCESS != XScuGic_CfgInitialize(&(p_handler->scu_gic), p_handler->p_intc_config,
p_handler->p_intc_config->CpuBaseAddress)) {
xil_printf("AXI DMA %d ERROR: the scu gic initialization FAILEDrn", p_init->dma_id);
return XST_FAILURE;
}
XScuGic_SetPriorityTriggerType(&(p_handler->scu_gic), p_init->tx_intr_id, c_priority, c_trigger_type);
XScuGic_SetPriorityTriggerType(&(p_handler->scu_gic), p_init->rx_intr_id, c_priority, c_trigger_type);
if (XST_SUCCESS != XScuGic_Connect(&(p_handler->scu_gic), p_init->tx_intr_id,
(Xil_InterruptHandler)p_init->tx_intr_handler,
&(p_handler->axi_dma))) {
xil_printf("AXI DMA %d ERROR: the scu gic tx connection FAILEDrn", p_init->dma_id);
return XST_FAILURE;
}
if (XST_SUCCESS != XScuGic_Connect(&(p_handler->scu_gic), p_init->rx_intr_id,
(Xil_InterruptHandler)p_init->rx_intr_handler,
&(p_handler->axi_dma))) {
xil_printf("AXI DMA %d ERROR: the scu gic rx connection FAILEDrn", p_init->dma_id);
return XST_FAILURE;
}
XScuGic_Enable(&(p_handler->scu_gic), p_init->tx_intr_id);
XScuGic_Enable(&(p_handler->scu_gic), p_init->rx_intr_id);
Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler,
(void *)&(p_handler->scu_gic));
Xil_ExceptionEnable();
XAxiDma_IntrDisable(&(p_handler->axi_dma), XAXIDMA_IRQ_ALL_MASK,
XAXIDMA_DMA_TO_DEVICE);
XAxiDma_IntrDisable(&(p_handler->axi_dma), XAXIDMA_IRQ_ALL_MASK,
XAXIDMA_DEVICE_TO_DMA);
XAxiDma_IntrEnable(&(p_handler->axi_dma), XAXIDMA_IRQ_ALL_MASK,
XAXIDMA_DMA_TO_DEVICE);
XAxiDma_IntrEnable(&(p_handler->axi_dma), XAXIDMA_IRQ_ALL_MASK,
XAXIDMA_DEVICE_TO_DMA);
return XST_SUCCESS;
}
axi_dma_intr_poll.h
#ifndef INC_AXI_DMA_POLL_H
#define INC_AXI_DMA_POLL_H
#include "xaxidma.h"
#include "xscugic.h"
#include "platform_.h"
typedef struct {
uint32_t *p_tx_buf;
uint32_t *p_rx_buf;
size_t size;
} axi_dma_poll_str;
typedef struct {
uint32_t tx_intr_id;
uint32_t rx_intr_id;
void (*rx_intr_handler)(void *);
void (*tx_intr_handler)(void *);
uint32_t dma_id;
} axi_dma_init_str;
typedef struct {
XAxiDma axi_dma;
XAxiDma_Config *p_config;
XScuGic scu_gic;
XScuGic_Config *p_intc_config;
} axi_dma_handler_str;
int axi_dma_init(axi_dma_init_str *p_init, axi_dma_handler_str *p_handler);
int axi_dma_poll(axi_dma_poll_str *p_poll, XAxiDma *p_axi_dma, uint32_t dma_id);
int axi_dma_release(XScuGic *p_scu_gic, uint32_t tx_intr_id, uint32_t rx_intr_id);
#endif