My program runs in a task under freerots environment. I run the DMA loopback experiment (fifo loopback experiment) on the Xilix device of MPSoc-P5 to test the DMA performance. I have already known and modified the problem of external interrupt registration and deleted the external interrupt registration part. XScuGic_Connect and XScuGic_Enable are the only two registration interrupts left, but unfortunately, the DMA program still can’t run. The program keeps busy in the XAxiDma_Busy function while testing whether it is busy, so I wonder if the DMA controller is also registered in the FreeRTOS task. I do not need to use XAxiDma_CfgInitialize with XAxiDma_LookupConfig. If so, how the first argument pointer to XAxiDma_SimpleTransfer should be assigned. If it’s not here, what’s the problem? Thanks for your answer.
My program runs in a task created by the mian function, as follows.
int main()
{
xTaskCreate(main_fun,( const char * ) "main",MAIN_STACK_SIZE,NULL,tskIDLE_PRIORITY + 1,NULL);
return 0;
}
Task definition
static void main_fun( void *pvParameters )
{
for(;;)
{
if(i==0){
dma_test();
xil_printf("finish main \n\r");
}
}
Specific dma_test(); I added in the attachment, the results of the device serial port are as follows:
type or paste code here
#include "dma_test.h"
/************************** Constant Definitions *****************************/
#define DMA_DEV_ID XPAR_AXIDMA_0_DEVICE_ID
#define RX_INTR_ID 121
#define TX_INTR_ID 122
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
#define DDR_BASE_ADDR XPAR_PSU_DDR_0_S_AXI_BASEADDR //0x00000000
#define MEM_BASE_ADDR (DDR_BASE_ADDR + 0x01100000) //0x01100000
#define TX_BUFFER_BASE (MEM_BASE_ADDR + 0x00100000) //0x01200000
#define RX_BUFFER_BASE (MEM_BASE_ADDR + 0x00300000) //0x01400000
#define RESET_TIMEOUT_COUNTER 10000 //��λʱ��
#define TEST_START_VALUE 0x0 //������ʼֵ
#define MAX_PKT_LEN 0x100 //���Ͱ�����
/************************** Function Prototypes ******************************/
/************************** Variable Definitions *****************************/
static XAxiDma axidma; //XAxiDmaʵ��
static XScuGic intc; //�жϿ�������ʵ��
volatile int tx_done; //������ɱ�־
volatile int rx_done; //������ɱ�־
volatile int error; //���������־
//extern XScuGic xInterruptController;
/************************** Function Definitions *****************************/
int dma_test(void)
{
int i;
int status;
u8 value;
u8 *tx_buffer_ptr;
u8 *rx_buffer_ptr;
XAxiDma_Config *config;
tx_buffer_ptr = (u8 *) TX_BUFFER_BASE;
rx_buffer_ptr = (u8 *) RX_BUFFER_BASE;
xil_printf("\r\n--- Entering main() --- \r\n");
config = XAxiDma_LookupConfig(DMA_DEV_ID);
if (!config) {
xil_printf("No config found for %d\r\n", DMA_DEV_ID);
return XST_FAILURE;
}
//��ʼ��DMA����
status = XAxiDma_CfgInitialize(&axidma, config);
if (status != XST_SUCCESS) {
xil_printf("Initialization failed %d\r\n", status);
return XST_FAILURE;
}
if (XAxiDma_HasSg(&axidma)) {
xil_printf("Device configured as SG mode \r\n");
return XST_FAILURE;
}
//�����ж�ϵͳ
status = setup_intr_system(&intc, &axidma, TX_INTR_ID, RX_INTR_ID);
if (status != XST_SUCCESS) {
xil_printf("Failed intr setup\r\n");
return XST_FAILURE;
}
xil_printf("flag10 \n\r");
//��ʼ����־�ź�
tx_done = 0;
rx_done = 0;
error = 0;
value = TEST_START_VALUE;
for (i = 0; i < MAX_PKT_LEN; i++) {
tx_buffer_ptr[i] = value;
value = (value + 1) & 0xFF;
}
if(XAxiDma_Busy(&axidma, XAXIDMA_DEVICE_TO_DMA) )
{
xil_printf("Someone DMA is busy! \r\n");
return XST_FAILURE;
}
xil_printf("flag7 \n\r");
Xil_DCacheFlushRange((UINTPTR) tx_buffer_ptr, MAX_PKT_LEN); //ˢ��Data Cache
xil_printf("flag6 \n\r");
status = XAxiDma_SimpleTransfer(&axidma, (UINTPTR) tx_buffer_ptr,
MAX_PKT_LEN, XAXIDMA_DMA_TO_DEVICE);
if (status != XST_SUCCESS) {
return XST_FAILURE;
}
xil_printf("flag5 \n\r");
status = XAxiDma_SimpleTransfer(&axidma, (UINTPTR) rx_buffer_ptr,
MAX_PKT_LEN, XAXIDMA_DEVICE_TO_DMA);
if (status != XST_SUCCESS) {
return XST_FAILURE;
}
xil_printf("flag4 \n\r");
Xil_DCacheFlushRange((UINTPTR) rx_buffer_ptr, MAX_PKT_LEN); //ˢ��Data Cache
while (!tx_done && !rx_done && !error);
xil_printf("flag8 \n\r");
//�������
if (error) {
xil_printf("Failed test transmit%s done, "
"receive%s done\r\n", tx_done ? "" : " not",
rx_done ? "" : " not");
goto Done;
}
//������ɣ���������Ƿ���ȷ
status = check_data(MAX_PKT_LEN, TEST_START_VALUE);
if (status != XST_SUCCESS) {
xil_printf("Data check failed\r\n");
goto Done;
}
xil_printf("Successfully ran AXI DMA Loop\r\n");
disable_intr_system(&intc, TX_INTR_ID, RX_INTR_ID);
Done: xil_printf("--- Exiting main() --- \r\n");
return XST_SUCCESS;
}
//������ݻ�����
static int check_data(int length, u8 start_value)
{
u8 value;
u8 *rx_packet;
int i = 0;
value = start_value;
rx_packet = (u8 *) RX_BUFFER_BASE;
for (i = 0; i < length; i++) {
if (rx_packet[i] != value) {
xil_printf("Data error %d: %x/%x\r\n", i, rx_packet[i], value);
return XST_FAILURE;
}
value = (value + 1) & 0xFF;
}
xil_printf("flag1 \n\r");
return XST_SUCCESS;
}
//DMA TX�жϴ�������
static void tx_intr_handler(void *callback)
{
int timeout;
u32 irq_status;
XAxiDma *axidma_inst = (XAxiDma *) callback;
//��ȡ���������ж�
irq_status = XAxiDma_IntrGetIrq(axidma_inst, XAXIDMA_DMA_TO_DEVICE);
//ȷ�ϴ��������ж�
XAxiDma_IntrAckIrq(axidma_inst, irq_status, XAXIDMA_DMA_TO_DEVICE);
//Tx����
if ((irq_status & XAXIDMA_IRQ_ERROR_MASK)) {
error = 1;
XAxiDma_Reset(axidma_inst);
timeout = RESET_TIMEOUT_COUNTER;
while (timeout) {
if (XAxiDma_ResetIsDone(axidma_inst))
break;
timeout -= 1;
}
return;
}
xil_printf("flag2 \n\r");
//Tx���
if ((irq_status & XAXIDMA_IRQ_IOC_MASK))
tx_done = 1;
}
//DMA RX�жϴ�������
static void rx_intr_handler(void *callback)
{
u32 irq_status;
int timeout;
XAxiDma *axidma_inst = (XAxiDma *) callback;
irq_status = XAxiDma_IntrGetIrq(axidma_inst, XAXIDMA_DEVICE_TO_DMA);
XAxiDma_IntrAckIrq(axidma_inst, irq_status, XAXIDMA_DEVICE_TO_DMA);
//Rx����
if ((irq_status & XAXIDMA_IRQ_ERROR_MASK)) {
error = 1;
XAxiDma_Reset(axidma_inst);
timeout = RESET_TIMEOUT_COUNTER;
while (timeout) {
if (XAxiDma_ResetIsDone(axidma_inst))
break;
timeout -= 1;
}
return;
}
xil_printf("flag3 \n\r");
//Rx���
if ((irq_status & XAXIDMA_IRQ_IOC_MASK))
rx_done = 1;
}
//����DMA�ж�ϵͳ
// @param int_ins_ptr��ָ��XScuGicʵ����ָ��
// @param AxiDmaPtr��ָ��DMA����ʵ����ָ��
// @param tx_intr_id��TXͨ���ж�ID
// @param rx_intr_id��RXͨ���ж�ID
// @return���ɹ�����XST_SUCCESS������XST_FAILURE
static int setup_intr_system(XScuGic * int_ins_ptr, XAxiDma * axidma_ptr,
u16 tx_intr_id, u16 rx_intr_id)
{
int status;
XScuGic_Config *intc_config;
//��ʼ���жϿ���������
// intc_config = XScuGic_LookupConfig(INTC_DEVICE_ID);
// if (NULL == intc_config) {
// return XST_FAILURE;
// }
// status = XScuGic_CfgInitialize(int_ins_ptr, intc_config,
// intc_config->CpuBaseAddress);
// if (status != XST_SUCCESS) {
// return XST_FAILURE;
// }
// �������ȼ��ʹ�������
// XScuGic_SetPriorityTriggerType(int_ins_ptr, tx_intr_id, 0xA0, 0x3);
// XScuGic_SetPriorityTriggerType(int_ins_ptr, rx_intr_id, 0xA0, 0x3);
//Ϊ�ж������жϴ�������
status = XScuGic_Connect(int_ins_ptr, tx_intr_id,
(Xil_InterruptHandler) tx_intr_handler, axidma_ptr);
if (status != XST_SUCCESS) {
return status;
}
status = XScuGic_Connect(int_ins_ptr, rx_intr_id,
(Xil_InterruptHandler) rx_intr_handler, axidma_ptr);
if (status != XST_SUCCESS) {
return status;
}
XScuGic_Enable(int_ins_ptr, tx_intr_id);
XScuGic_Enable(int_ins_ptr, rx_intr_id);
//��������Ӳ�����ж�
// Xil_ExceptionInit();
// Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
// (Xil_ExceptionHandler) XScuGic_InterruptHandler,
// (void *) int_ins_ptr);
// Xil_ExceptionEnable();
//ʹ��DMA�ж�
XAxiDma_IntrEnable(&axidma, XAXIDMA_IRQ_ALL_MASK, XAXIDMA_DMA_TO_DEVICE);
XAxiDma_IntrEnable(&axidma, XAXIDMA_IRQ_ALL_MASK, XAXIDMA_DEVICE_TO_DMA);
return XST_SUCCESS;
}
//�˺�������DMA������ж�
static void disable_intr_system(XScuGic * int_ins_ptr, u16 tx_intr_id,
u16 rx_intr_id)
{
XScuGic_Disconnect(int_ins_ptr, tx_intr_id);
XScuGic_Disconnect(int_ins_ptr, rx_intr_id);
}