本次实验测试CDMA来在ddr与bram之间搬运数据。
1.Vivado工程
CDMA上同时连接了四个BRAM。Bram设置为BRAM Controller模式,真双口BRAM,宽度64,深度1024,这样分配地址8k即可。
2.地址分配(要注意)
3.SDK代码
#include "xparameters.h"
#include <stdio.h>
#include "xuartps.h" // if PS uart is used
#include "xscutimer.h" // if PS Timer is used
#include "xaxicdma.h" // if CDMA is used
#include "xscugic.h" // if PS GIC is used
#include "xil_exception.h" // if interrupt is used
#include "xil_cache.h"
#include "xil_printf.h"
#include "xil_types.h"
#define RESET_LOOP_COUNT 10 // Number of times to check reset is done
#define LENGTH 32768 // source and destination buffers lengths in number of bytes
#define PROCESSOR_BRAM_MEMORY 0x80000000 // BRAM Port A mapped through 1st BRAM Controller accessed by CPU
#define CDMA_BRAM_MEMORY0 0xC0000000 // BRAM Port B mapped through 2nd BRAM Controller accessed by CDMA
#define CDMA_BRAM_MEMORY1 0xC0002000
#define CDMA_BRAM_MEMORY2 0xC0004000
#define CDMA_BRAM_MEMORY3 0xC0006000
#define DDR_MEMORY 0x01000000
#define TIMER_DEVICE_ID XPAR_SCUTIMER_DEVICE_ID
#define TIMER_LOAD_VALUE 0xFFFFFFFF
#define INTC_DEVICE_INT_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
volatile static int Done = 0; /* Dma transfer is done */
volatile static int Error = 0; /* Dma Bus Error occurs */
XUartPs Uart_PS; /* Instance of the UART Device */
XScuTimer Timer; /* Cortex A9 SCU Private Timer Instance */
XScuGic Gic; /* PS GIC */
int getNumber (){
uint8_t byte;
uint8_t uartBuffer[16];
int validNumber;
int digitIndex;
int digit, number, sign;
int c;
while(1){
byte = 0x00;
digit = 0;
digitIndex = 0;
number = 0;
validNumber = TRUE;
//get bytes from uart until RETURN is entered
while(byte != 0x0d){
while (!XUartPs_IsReceiveData(STDIN_BASEADDRESS));
byte = XUartPs_ReadReg(STDIN_BASEADDRESS,
XUARTPS_FIFO_OFFSET);
uartBuffer[digitIndex] = byte;
XUartPs_Send(&Uart_PS, &byte, 1);
digitIndex++;
}
//calculate number from string of digits
for(c = 0; c < (digitIndex - 1); c++){
if(c == 0){
//check if first byte is a "-"
if(uartBuffer[c] == 0x2D){
sign = -1;
digit = 0;
}
//check if first byte is a digit
else if((uartBuffer[c] >> 4) == 0x03){
sign = 1;
digit = (uartBuffer[c] & 0x0F);
}
else
validNumber = FALSE;
}
else{
//check byte is a digit
if((uartBuffer[c] >> 4) == 0x03){
digit = (uartBuffer[c] & 0x0F);
}
else
validNumber = FALSE;
}
number = (number * 10) + digit;
}
number *= sign;
if(validNumber == TRUE){
print("\r\n");
return number*4; //number of bytes
}
print("This is not a valid number.\n\r");
}
}
static void Example_CallBack(void *CallBackRef, u32 IrqMask, int *IgnorePtr)
{
if (IrqMask & XAXICDMA_XR_IRQ_ERROR_MASK) {
Error = 1;
}
if (IrqMask & XAXICDMA_XR_IRQ_IOC_MASK) {
Done = 1;
}
}
//Connect dma to Generic Interrupt Controller
int SetupIntrSystem(XScuGic *GicPtr, XAxiCdma *DmaPtr)
{
int Status;
Xil_ExceptionInit();
// Connect the interrupt controller interrupt handler to the hardware
// interrupt handling logic in the processor.
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,
(Xil_ExceptionHandler)XScuGic_InterruptHandler,
GicPtr);
// Connect a device driver handler that will be called when an interrupt
// for the device occurs, the device driver handler performs the specific
// interrupt processing for the device
Status = XScuGic_Connect(GicPtr,
XPAR_FABRIC_AXI_CDMA_0_CDMA_INTROUT_INTR, //interrupt responding to real physical CDMA//
(Xil_InterruptHandler)XAxiCdma_IntrHandler,
(void *)DmaPtr);
if (Status != XST_SUCCESS)
return XST_FAILURE;
// Enable the interrupt for the device
XScuGic_Enable(GicPtr, XPAR_FABRIC_AXI_CDMA_0_CDMA_INTROUT_INTR);
return XST_SUCCESS;
}
int main (void) {
uint8_t select;
int i, CDMA_Status;
int numofbytes;
u8 * source = DDR_MEMORY, * destination, *destination1 = DDR_MEMORY+32768*4;
int32_t software_cycles, interrupt_cycles, polled_cycles;
int test_done = 0;
// UART related definitions
int Status;
XUartPs_Config *Config;
// PS Timer related definitions
volatile u32 CntValue1, CntValue2;
XScuTimer_Config *ConfigPtr;
XScuTimer *TimerInstancePtr = &Timer;
// CDMA related definitions
XAxiCdma xcdma;
XAxiCdma_Config * CdmaCfgPtr;
// PS Interrupt related definitions
XScuGic_Config *GicConfig;
// Initialize UART
// Look up the configuration in the config table, then initialize it.
Config = XUartPs_LookupConfig(XPAR_PS7_UART_0_DEVICE_ID);
if (NULL == Config) {
return XST_FAILURE;
}
Status = XUartPs_CfgInitialize(&Uart_PS, Config, Config->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
// Initialize timer counter
ConfigPtr = XScuTimer_LookupConfig(TIMER_DEVICE_ID);
Status = XScuTimer_CfgInitialize(TimerInstancePtr, ConfigPtr,
ConfigPtr->BaseAddr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
// Initialize GIC
GicConfig = XScuGic_LookupConfig(INTC_DEVICE_INT_ID);
if (NULL == GicConfig) {
xil_printf("XScuGic_LookupConfig(%d) failed\r\n",
INTC_DEVICE_INT_ID);
return XST_FAILURE;
}
Status = XScuGic_CfgInitialize(&Gic, GicConfig,
GicConfig->CpuBaseAddress);
if (Status != XST_SUCCESS) {