在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

ZYNQ SOC驗(yàn)證設(shè)計(jì):PS端DMA緩存數(shù)據(jù)到PS端DDR

電子設(shè)計(jì) ? 來源:CSDN博主 ? 作者:沒落騎士 ? 2020-12-31 11:24 ? 次閱讀

上篇該系列博文中講述W5500接收到上位機(jī)傳輸?shù)臄?shù)據(jù),此后需要將數(shù)據(jù)緩存起來。當(dāng)數(shù)據(jù)量較大或者其他數(shù)據(jù)帶寬較高的情況下,片上緩存(OCM)已無法滿足需求,這時需要將大量數(shù)據(jù)保存在外掛的DDR SDRAM中。

最簡單的方式是使用Xilinx的讀寫地址庫函數(shù)Xil_In32()和Xil_Out32(),當(dāng)然不僅支持32bit位寬,還包括8 16和64bit。但這種方式每次讀寫都要占用CPU,無法在讀寫的同時接收后續(xù)數(shù)據(jù)或者對之前的數(shù)據(jù)進(jìn)一步處理,也就無法形成類似FPGA邏輯設(shè)計(jì)中的“流水線結(jié)構(gòu)”,此時前段數(shù)據(jù)緩存過程中,后段數(shù)據(jù)會被丟棄。所以,需要利用PS端CPU子系統(tǒng)內(nèi)的專用硬件DMA完成高速的批量數(shù)據(jù)搬移工作。

pIYBAF9uKQWAI-4wAAMm2ngn2_4294.png

在Xilinx SDK的system.mss頁面下直接導(dǎo)入ps_dma示例工程。
#include
#include
#include "sleep.h"
#include "xparameters.h"
#include "xil_types.h"
#include "xil_assert.h"
#include "xil_io.h"
#include "xil_exception.h"
#include "xil_cache.h"
#include "xil_printf.h"
#include "xscugic.h"
#include "xdmaps.h"

/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define DMA_DEVICE_ID XPAR_XDMAPS_1_DEVICE_ID
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID

#define DMA_DONE_INTR_0 XPAR_XDMAPS_0_DONE_INTR_0
#define DMA_DONE_INTR_1 XPAR_XDMAPS_0_DONE_INTR_1
#define DMA_DONE_INTR_2 XPAR_XDMAPS_0_DONE_INTR_2
#define DMA_DONE_INTR_3 XPAR_XDMAPS_0_DONE_INTR_3
#define DMA_DONE_INTR_4 XPAR_XDMAPS_0_DONE_INTR_4
#define DMA_DONE_INTR_5 XPAR_XDMAPS_0_DONE_INTR_5
#define DMA_DONE_INTR_6 XPAR_XDMAPS_0_DONE_INTR_6
#define DMA_DONE_INTR_7 XPAR_XDMAPS_0_DONE_INTR_7
#define DMA_FAULT_INTR XPAR_XDMAPS_0_FAULT_INTR

#define TEST_ROUNDS 1 /* Number of loops that the Dma transfers run.*/
#define DMA_LENGTH 1024 /* Length of the Dma Transfers */
#define TIMEOUT_LIMIT 0x2000 /* Loop count for timeout */

/**************************** Type Definitions *******************************/

/***************** Macros (Inline Functions) Definitions *********************/

/************************** Function Prototypes ******************************/

int XDmaPs_Example_W_Intr(XScuGic *GicPtr, u16 DeviceId);
int SetupInterruptSystem(XScuGic *GicPtr, XDmaPs *DmaPtr);
void DmaDoneHandler(unsigned int Channel, XDmaPs_Cmd *DmaCmd,
void *CallbackRef);

/************************** Macro Definitions *****************************/

/************************** Variable Definitions *****************************/
#ifdef __ICCARM__
#pragma data_alignment=32
static int Src[DMA_LENGTH];
static int Dst[DMA_LENGTH];
#pragma data_alignment=4
#else
static int Src[DMA_LENGTH] __attribute__ ((aligned (32)));
static int Dst[DMA_LENGTH] __attribute__ ((aligned (32)));
#endif

XDmaPs DmaInstance;
#ifndef TESTAPP_GEN
XScuGic GicInstance;
#endif

/****************************************************************************/
/**
*
* This is the main function for the DmaPs interrupt example.
*
* @param None.
*
* @return XST_SUCCESS to indicate success, otherwise XST_FAILURE.
*
* @note None.
*
****************************************************************************/
#ifndef TESTAPP_GEN
int main(void)
{
int Status;

Status = XDmaPs_Example_W_Intr(&GicInstance,DMA_DEVICE_ID);
if (Status != XST_SUCCESS) {
xil_printf("Error: XDMaPs_Example_W_Intr failed/r/n");
return XST_FAILURE;
}

xil_printf("XDMaPs_Example_W_Intr passed/r/n");
return XST_SUCCESS;

}
#endif

/*****************************************************************************/
/**
*
* Interrupt Example to test the DMA.
*
* @param DeviceId is the Device ID of the DMA controller.
*
* @return XST_SUCCESS to indicate success, otherwise XST_FAILURE.
*
* @note None.
*
****************************************************************************/
int XDmaPs_Example_W_Intr(XScuGic *GicPtr, u16 DeviceId)
{
int Index;
unsigned int Channel = 0;
int Status;
int TestStatus;
int TestRound;
int TimeOutCnt;
volatile int Checked[XDMAPS_CHANNELS_PER_DEV];
XDmaPs_Config *DmaCfg;
XDmaPs *DmaInst = &DmaInstance;
XDmaPs_Cmd DmaCmd;

memset(&DmaCmd, 0, sizeof(XDmaPs_Cmd));

DmaCmd.ChanCtrl.SrcBurstSize = 4;
DmaCmd.ChanCtrl.SrcBurstLen = 4;
DmaCmd.ChanCtrl.SrcInc = 1;
DmaCmd.ChanCtrl.DstBurstSize = 4;
DmaCmd.ChanCtrl.DstBurstLen = 4;
DmaCmd.ChanCtrl.DstInc = 1;
DmaCmd.BD.SrcAddr = (u32) Src;
DmaCmd.BD.DstAddr = (u32) Dst;
DmaCmd.BD.Length = DMA_LENGTH * sizeof(int);

/*
* Initialize the DMA Driver
*/
DmaCfg = XDmaPs_LookupConfig(DeviceId);
if (DmaCfg == NULL) {
return XST_FAILURE;
}

Status = XDmaPs_CfgInitialize(DmaInst,
DmaCfg,
DmaCfg->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}

/*
* Setup the interrupt system.
*/
Status = SetupInterruptSystem(GicPtr, DmaInst);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}

TestStatus = XST_SUCCESS;

for (TestRound = 0; TestRound xil_printf("Test round %d/r/n", TestRound);
for (Channel = 0;
Channel Channel++) {

/* Initialize source */
for (Index = 0; Index Src[Index] = DMA_LENGTH - Index;

/* Clear destination */
for (Index = 0; Index Dst[Index] = 0;

Checked[Channel] = 0;

/* Set the Done interrupt handler */
XDmaPs_SetDoneHandler(DmaInst,
Channel,
DmaDoneHandler,
(void *)Checked);

Status = XDmaPs_Start(DmaInst, Channel, &DmaCmd, 0);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}

TimeOutCnt = 0;

/* Now the DMA is done */
while (!Checked[Channel]
&& TimeOutCnt TimeOutCnt++;
}

if (TimeOutCnt >= TIMEOUT_LIMIT) {
TestStatus = XST_FAILURE;
}

if (Checked[Channel] /* DMA controller failed */
TestStatus = XST_FAILURE;
}
}
}

return TestStatus;

}

/******************************************************************************/
/**
*
* This function connects the interrupt handler of the interrupt controller to
* the processor. This function is seperate to allow it to be customized for
* each application. Each processor or RTOS may require unique processing to
* connect the interrupt handler.
*
* @param GicPtr is the GIC instance pointer.
* @param DmaPtr is the DMA instance pointer.
*
* @return None.
*
* @note None.
*
****************************************************************************/
int SetupInterruptSystem(XScuGic *GicPtr, XDmaPs *DmaPtr)
{
int Status;
#ifndef TESTAPP_GEN
XScuGic_Config *GicConfig;

Xil_ExceptionInit();

/*
* Initialize the interrupt controller driver so that it is ready to
* use.
*/
GicConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
if (NULL == GicConfig) {
return XST_FAILURE;
}

Status = XScuGic_CfgInitialize(GicPtr, GicConfig,
GicConfig->CpuBaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}

/*
* 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);
#endif
/*
* Connect the device driver handlers that will be called when an interrupt
* for the device occurs, the device driver handler performs the specific
* interrupt processing for the device
*/

/*
* Connect the Fault ISR
*/
Status = XScuGic_Connect(GicPtr,
DMA_FAULT_INTR,
(Xil_InterruptHandler)XDmaPs_FaultISR,
(void *)DmaPtr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}

/*
* Connect the Done ISR for all 8 channels of DMA 0
*/
Status = XScuGic_Connect(GicPtr,
DMA_DONE_INTR_0,
(Xil_InterruptHandler)XDmaPs_DoneISR_0,
(void *)DmaPtr);
Status |= XScuGic_Connect(GicPtr,
DMA_DONE_INTR_1,
(Xil_InterruptHandler)XDmaPs_DoneISR_1,
(void *)DmaPtr);
Status |= XScuGic_Connect(GicPtr,
DMA_DONE_INTR_2,
(Xil_InterruptHandler)XDmaPs_DoneISR_2,
(void *)DmaPtr);
Status |= XScuGic_Connect(GicPtr,
DMA_DONE_INTR_3,
(Xil_InterruptHandler)XDmaPs_DoneISR_3,
(void *)DmaPtr);
Status |= XScuGic_Connect(GicPtr,
DMA_DONE_INTR_4,
(Xil_InterruptHandler)XDmaPs_DoneISR_4,
(void *)DmaPtr);
Status |= XScuGic_Connect(GicPtr,
DMA_DONE_INTR_5,
(Xil_InterruptHandler)XDmaPs_DoneISR_5,
(void *)DmaPtr);
Status |= XScuGic_Connect(GicPtr,
DMA_DONE_INTR_6,
(Xil_InterruptHandler)XDmaPs_DoneISR_6,
(void *)DmaPtr);
Status |= XScuGic_Connect(GicPtr,
DMA_DONE_INTR_7,
(Xil_InterruptHandler)XDmaPs_DoneISR_7,
(void *)DmaPtr);

if (Status != XST_SUCCESS)
return XST_FAILURE;

/*
* Enable the interrupts for the device
*/
XScuGic_Enable(GicPtr, DMA_DONE_INTR_0);
XScuGic_Enable(GicPtr, DMA_DONE_INTR_1);
XScuGic_Enable(GicPtr, DMA_DONE_INTR_2);
XScuGic_Enable(GicPtr, DMA_DONE_INTR_3);
XScuGic_Enable(GicPtr, DMA_DONE_INTR_4);
XScuGic_Enable(GicPtr, DMA_DONE_INTR_5);
XScuGic_Enable(GicPtr, DMA_DONE_INTR_6);
XScuGic_Enable(GicPtr, DMA_DONE_INTR_7);
XScuGic_Enable(GicPtr, DMA_FAULT_INTR);

Xil_ExceptionEnable();

return XST_SUCCESS;

}

/*****************************************************************************/
/**
*
* DmaDoneHandler.
*
* @param Channel is the Channel number.
* @param DmaCmd is the Dma Command.
* @param CallbackRef is the callback reference data.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void DmaDoneHandler(unsigned int Channel, XDmaPs_Cmd *DmaCmd, void *CallbackRef)
{

/* done handler */
volatile int *Checked = (volatile int *)CallbackRef;
int Index;
int Status = 1;
int *Src;
int *Dst;

Src = (int *)DmaCmd->BD.SrcAddr;
Dst = (int *)DmaCmd->BD.DstAddr;

/* DMA successful */
/* compare the src and dst buffer */
for (Index = 0; Index if ((Src[Index] != Dst[Index]) ||
(Dst[Index] != DMA_LENGTH - Index)) {
Status = -XST_FAILURE;
}
}

Checked[Channel] = Status;
}

ps_dma_demo

其實(shí)demo中做的操作非常簡單,僅僅是定義了兩個數(shù)組Src和Dst,之后利用PS_DMA將Src中數(shù)據(jù)搬移到Dst中,搬移完成后進(jìn)入中斷函數(shù)比較兩部分地址數(shù)據(jù)是否一致。Xilinx的SDK軟件代碼有固定的套路,“上有政策,下有對策”,我們可以將其封裝成固定格式的一個個子函數(shù),方便今后調(diào)用。這里把整個工程分為:系統(tǒng)中斷,PS_DMA專有中斷以及主函數(shù)三個部分。
#include "xscugic.h"
#include "sys_intr.h"

int sys_IntrInit(XScuGic *GicPtr)
{
XScuGic_Config *GicConfig;
/*
* Initialize the interrupt controller driver so that it is ready to
* use.
*/
int Status;
GicConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
if (NULL == GicConfig) {
return XST_FAILURE;
}

Status = XScuGic_CfgInitialize(GicPtr, GicConfig,
GicConfig->CpuBaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}

void setupIntrException(XScuGic *GicPtr)
{
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);
Xil_ExceptionEnable();
}

sys_intr.c

#ifndef SRC_SYS_INTR_H_
#define SRC_SYS_INTR_H_

#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID

int sys_IntrInit(XScuGic *GicPtr);
void setupIntrException(XScuGic *GicPtr);

#endif /* SRC_SYS_INTR_H_ */

sys_intr.h

#include "xil_types.h"
#include "xdmaps.h"
#include "xscugic.h"
#include "psdma_intr.h"

int PS_DMA_IntrInit(XDmaPs *DmaInst,u16 DeviceId)
{
/*
* Initialize the DMA Driver
*/
int Status;
XDmaPs_Config *DmaCfg = NULL;
DmaCfg = XDmaPs_LookupConfig(DeviceId);
if (DmaCfg == NULL) {
return XST_FAILURE;
}

Status = XDmaPs_CfgInitialize(DmaInst,
DmaCfg,
DmaCfg->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}

int PS_DMA_SetupIntr(XScuGic *GicPtr,XDmaPs *DmaPtr,unsigned Channel)
{
int Status;
/*
* Connect the device driver handlers that will be called when an interrupt
* for the device occurs, the device driver handler performs the specific
* interrupt processing for the device
*/

/*
* Connect the Fault ISR
*/
Status = XScuGic_Connect(GicPtr,
DMA_FAULT_INTR,
(Xil_InterruptHandler)XDmaPs_FaultISR,
(void *)DmaPtr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}

/*
* Connect the Done ISR for all 8 channels of DMA 0
*/
Status = XScuGic_Connect(GicPtr,
DMA_DONE_INTR_0,
(Xil_InterruptHandler)XDmaPs_DoneISR_0,
(void *)DmaPtr);
/*Status |= XScuGic_Connect(GicPtr,
DMA_DONE_INTR_1,
(Xil_InterruptHandler)XDmaPs_DoneISR_1,
(void *)DmaPtr);
Status |= XScuGic_Connect(GicPtr,
DMA_DONE_INTR_2,
(Xil_InterruptHandler)XDmaPs_DoneISR_2,
(void *)DmaPtr);
Status |= XScuGic_Connect(GicPtr,
DMA_DONE_INTR_3,
(Xil_InterruptHandler)XDmaPs_DoneISR_3,
(void *)DmaPtr);
Status |= XScuGic_Connect(GicPtr,
DMA_DONE_INTR_4,
(Xil_InterruptHandler)XDmaPs_DoneISR_4,
(void *)DmaPtr);
Status |= XScuGic_Connect(GicPtr,
DMA_DONE_INTR_5,
(Xil_InterruptHandler)XDmaPs_DoneISR_5,
(void *)DmaPtr);
Status |= XScuGic_Connect(GicPtr,
DMA_DONE_INTR_6,
(Xil_InterruptHandler)XDmaPs_DoneISR_6,
(void *)DmaPtr);
Status |= XScuGic_Connect(GicPtr,
DMA_DONE_INTR_7,
(Xil_InterruptHandler)XDmaPs_DoneISR_7,
(void *)DmaPtr);*/

if (Status != XST_SUCCESS)
return XST_FAILURE;

/* Set the Done interrupt handler */
XDmaPs_SetDoneHandler(DmaPtr,
Channel,//Channel
DmaDoneHandler,//真正的中斷函數(shù)
(void *)Checked);

/*
* Enable the interrupts for the device
*/
XScuGic_Enable(GicPtr, DMA_DONE_INTR_0);
/*
XScuGic_Enable(GicPtr, DMA_DONE_INTR_1);
XScuGic_Enable(GicPtr, DMA_DONE_INTR_2);
XScuGic_Enable(GicPtr, DMA_DONE_INTR_3);
XScuGic_Enable(GicPtr, DMA_DONE_INTR_4);
XScuGic_Enable(GicPtr, DMA_DONE_INTR_5);
XScuGic_Enable(GicPtr, DMA_DONE_INTR_6);
XScuGic_Enable(GicPtr, DMA_DONE_INTR_7);*/
XScuGic_Enable(GicPtr, DMA_FAULT_INTR);

return XST_SUCCESS;
}

void DmaDoneHandler(unsigned int Channel, XDmaPs_Cmd *DmaCmd, void *CallbackRef)
{

/* done handler */
volatile int *Checked = (volatile int *)CallbackRef;
//int Index;
int Status = 1;

xil_printf("Enter into the interrupt/n");
Checked[Channel] = Status;
}

void PS_DMA_InitPara(XDmaPs_Cmd* DmaCmd)
{

memset(DmaCmd, 0, sizeof(XDmaPs_Cmd));

DmaCmd->ChanCtrl.SrcBurstSize = 4;
DmaCmd->ChanCtrl.SrcBurstLen = 4;
DmaCmd->ChanCtrl.SrcInc = 1;
DmaCmd->ChanCtrl.DstBurstSize = 4;
DmaCmd->ChanCtrl.DstBurstLen = 4;
DmaCmd->ChanCtrl.DstInc = 1;
DmaCmd->BD.SrcAddr = (u32) Src;
DmaCmd->BD.DstAddr = (u32) DDR_BASEADDR;//Dst
DmaCmd->BD.Length = DMA_LENGTH * sizeof(int);
}

psdma_intr.c

#ifndef SRC_PSDMA_INTR_H_
#define SRC_PSDMA_INTR_H_

#define DMA_DONE_INTR_0 XPAR_XDMAPS_0_DONE_INTR_0
#define DMA_DONE_INTR_1 XPAR_XDMAPS_0_DONE_INTR_1
#define DMA_DONE_INTR_2 XPAR_XDMAPS_0_DONE_INTR_2
#define DMA_DONE_INTR_3 XPAR_XDMAPS_0_DONE_INTR_3
#define DMA_DONE_INTR_4 XPAR_XDMAPS_0_DONE_INTR_4
#define DMA_DONE_INTR_5 XPAR_XDMAPS_0_DONE_INTR_5
#define DMA_DONE_INTR_6 XPAR_XDMAPS_0_DONE_INTR_6
#define DMA_DONE_INTR_7 XPAR_XDMAPS_0_DONE_INTR_7
#define DMA_FAULT_INTR XPAR_XDMAPS_0_FAULT_INTR

#define DDR_BASEADDR 0x00600000//XPAR_PS7_DDR_0_S_AXI_BASEADDR 0x00100000
#define DMA_LENGTH 1024 /* Length of the Dma Transfers */

int Src[DMA_LENGTH] __attribute__ ((aligned (32)));
volatile int Checked[XDMAPS_CHANNELS_PER_DEV];

int PS_DMA_IntrInit(XDmaPs *DmaInst,u16 DeviceId);
int PS_DMA_SetupIntr(XScuGic *GicPtr,XDmaPs *DmaPtr,unsigned Channel);
void DmaDoneHandler(unsigned int Channel, XDmaPs_Cmd *DmaCmd, void *CallbackRef);
void PS_DMA_InitPara(XDmaPs_Cmd* DmaCmd);

#endif /* SRC_PSDMA_INTR_H_ */

psdma_intr.h

#include
#include
#include "sleep.h"
#include "xparameters.h"
#include "xil_types.h"
#include "xil_assert.h"
#include "xil_io.h"
#include "xil_exception.h"
#include "xil_cache.h"
#include "xil_printf.h"
#include "xscugic.h"
#include "xdmaps.h"

#include "sys_intr.h"
#include "psdma_intr.h"

#define DMA_DEVICE_ID XPAR_XDMAPS_1_DEVICE_ID
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID

#define TEST_ROUNDS 1 /* Number of loops that the Dma transfers run.*/
#define TIMEOUT_LIMIT 0x2000 /* Loop count for timeout */

static XScuGic GicInstance;
static XDmaPs DmaInstance;
static XDmaPs_Cmd DmaCmd;
unsigned int Channel = 0;

/************************** Function Prototypes ******************************/

int PS_DMA_WriteTest();
int SetupInterruptSystem(XScuGic *GicPtr, XDmaPs *DmaPtr);
void DmaDoneHandler(unsigned int Channel, XDmaPs_Cmd *DmaCmd,
void *CallbackRef);
int dataCheck(u32 baseAddr,u32 len);
int systemInit(XScuGic *GicPtr,u16 DeviceId);

int main(void)
{
int Status;
Status = systemInit(&GicInstance,DMA_DEVICE_ID);
if (Status != XST_SUCCESS) {
xil_printf("System initialization is failed/r/n");
return XST_FAILURE;
}

Status = PS_DMA_WriteTest();
if (Status != XST_SUCCESS) {
xil_printf("Error: XDMaPs_Example_W_Intr failed/r/n");
return XST_FAILURE;
}
xil_printf("Checking data.../n");
Status = dataCheck(DDR_BASEADDR,DMA_LENGTH);
if(Status != XST_SUCCESS)
{
xil_printf("Error:check failed/n");
return XST_FAILURE;
}

xil_printf("Writing data to DDR using DMA test passed!/r/n");
return XST_SUCCESS;

}

int dataCheck(u32 baseAddr,u32 len)
{
u32 DDR_ReadData[1024];
int i;
for(i=0;i {
DDR_ReadData[i] = Xil_In32(baseAddr+i*4);
if(DDR_ReadData[i]!=Src[i])
return XST_FAILURE;
//else //將寫入DDR數(shù)據(jù)讀回 并打印
// xil_printf("data at %x is %d/n",baseAddr+i*4,DDR_ReadData[i]);
}
return XST_SUCCESS;
}

/*****************************************************************************/
/**
*
* Interrupt Example to test the DMA.
*
* @param DeviceId is the Device ID of the DMA controller.
*
* @return XST_SUCCESS to indicate success, otherwise XST_FAILURE.
*
* @note None.
*
****************************************************************************/
int PS_DMA_WriteTest()
{
int Index;
int Status;
int TestStatus;
int TestRound;
int TimeOutCnt;

TestStatus = XST_SUCCESS;

for (TestRound = 0; TestRound xil_printf("Test round %d/r/n", TestRound);
for (Channel = 0;Channel {
/* Initialize source */
for (Index = 0; Index Src[Index] = DMA_LENGTH - Index;

Checked[Channel] = 0;

Status = XDmaPs_Start(&DmaInstance, Channel, &DmaCmd, 0);
if (Status != XST_SUCCESS) {
xil_printf("Starting the DMA is failed./n");
return XST_FAILURE;
}
xil_printf("Starting the DMA is successful./n");
TimeOutCnt = 0;

while (!Checked[Channel]
&& TimeOutCnt TimeOutCnt++;
}
/* Now the DMA is done */
xil_printf("Jump out of the interrupt/n");
if (TimeOutCnt >= TIMEOUT_LIMIT) {
xil_printf("Overtime!/n");
TestStatus = XST_FAILURE;
}

if (Checked[Channel] /* DMA controller failed */
xil_printf("Checking failure!/n");
TestStatus = XST_FAILURE;
}
}
}

return TestStatus;

}

int systemInit(XScuGic *GicPtr,u16 DeviceId)
{
xil_printf("Start to initialize interrupt system./n");

PS_DMA_InitPara(&DmaCmd);//主要設(shè)置DMA的源目的地址
//xil_printf("Configuring DMA parameters is successful./n");

int Status;

Status = PS_DMA_IntrInit(&DmaInstance,DeviceId);
if (Status != XST_SUCCESS) {
xil_printf("DMA initialization is failed./n");
return XST_FAILURE;
}
//xil_printf("DMA initialization is successful./n");

Status = sys_IntrInit(GicPtr);
if (Status != XST_SUCCESS) {
xil_printf("Initialization of the interrupt system is failed./n");
return XST_FAILURE;
}
//xil_printf("Initialization of the interrupt system is successful./n");

setupIntrException(GicPtr);

Status = PS_DMA_SetupIntr(GicPtr,&DmaInstance,Channel);//////////////////////////DMA中斷入口///////////////////////
if (Status != XST_SUCCESS) {
xil_printf("Setting up DMA interrupt is failed./n");
return XST_FAILURE;
}
//xil_printf("Setting up DMA interrupt is successful./n");

xil_printf("System initialization is finished./n");
xil_printf("------------------------------------------/n");
return XST_SUCCESS;
}

main.c

上述代碼的封裝方式參考了米聯(lián)客教程中的思想。先說明系統(tǒng)中斷部分:sys_IntrInit()函數(shù)中進(jìn)行查找表配置和中斷控制器初始化操作,setupIntrException()函數(shù)負(fù)責(zé)使能中斷異常處理。再來說說PS_DMA中斷部分:PS_DMA_IntrInit()函數(shù)與系統(tǒng)中斷中sys_IntrInit()從操作到格式幾乎完成相同,亦是查找表配置和DMA的初始化。PS_DMA_SetupIntr()函數(shù)完成了中斷源和中斷控制器的連接和設(shè)置中斷處理器,以及中斷使能,也就是所有PS_DMA的專用中斷操作。

PS_DMA_SetupIntr()內(nèi)最重要的部分是XDmaPs_SetDoneHandler(),其相當(dāng)于一個調(diào)用中斷函數(shù)的通用處理框架,它的第三個參數(shù)DoneHandler才是真正的中斷處理函數(shù)。這里涉及到C語言的高級話題:函數(shù)通過函數(shù)指針調(diào)用另一個函數(shù),被函數(shù)指針調(diào)用的函數(shù)就是通常講的“回調(diào)函數(shù)”了。指針調(diào)用函數(shù)的方式兼顧了程序的通用架構(gòu)和靈活性,具體參考文章:不懂C語言回調(diào)函數(shù),那就看這篇文章吧! - 簡書 https://www.jianshu.com/p/2f695d6fd64f 在該程序中,中斷回調(diào)函數(shù)為DmaDoneHandler()。

PS_DMA_InitPara()是自行添加的PS_DMA參數(shù)初始化函數(shù),內(nèi)部的參數(shù)更是重中之重了,我們來查看Xilinx官方文檔ug585的DMA Controller章節(jié)。

pIYBAF9uKQiAex56AAKFFebVFeI958.png

簡要來說,DMA以burst形式傳輸數(shù)據(jù),意思是分批次搬移。手冊說明原或目的burst_size位寬不能超過64bit,這也是其掛載AXI總線的數(shù)據(jù)位寬。PS_DMA_InitPara()里的SrcBurstSize為源突發(fā)傳輸位寬字節(jié)數(shù),最大為8.SrcBurstLen是手冊中所說的“burst length”,即突發(fā)傳輸數(shù)據(jù)個數(shù)。SrcInc表示burst types為地址自增(1)還是地址固定(0)模式。目的控制字同理。剩下的三個參數(shù)最重要:SrcAddr DstAddr Length分別代表源首地址 目的首地址和一共需要搬移的數(shù)據(jù)字節(jié)數(shù)。需要注意的是,一定要滿足srcburstsize*srcburstlen == dstburstsize*dstburstlen,否則發(fā)生錯誤。這一點(diǎn)也比較好理解,相當(dāng)于FPGA邏輯設(shè)計(jì)中的異步FIFO兩側(cè)數(shù)據(jù)帶寬要匹配。

那么要想完成OCM到DDR的數(shù)據(jù)搬移,改動下地址就可以嘛。由于讀寫DDR要訪問絕對地址,所以要格外注意讀寫操作的地址不能和DDR內(nèi)存儲程序代碼和中間數(shù)據(jù)的地址段重疊。避免程序崩潰很簡單的做法就是在XPAR_PS7_DDR_0_S_AXI_BASEADDR 的基礎(chǔ)上加一段偏移量,具體加多少的問題本人也不是很明確,希望看到的朋友能在評論中指點(diǎn)一二。

對于ZYNQ這一SOC架構(gòu)來說,PS端連接如以太網(wǎng)USB等高帶寬外設(shè)計(jì)接口更加方便,所以PS_DMA的靈活運(yùn)用還好是十分必要的,更靈活高效的利用這一硬件資源還要后期繼續(xù)探索。PS端和PL端高速數(shù)據(jù)交互就需要用到另一個DMA成員AXI_DMA,可以說它利用片內(nèi)總線打破了CPU+FPGA架構(gòu)的性能瓶頸,該部分內(nèi)容將在后續(xù)說明。

編輯:hfy


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • FPGA
    +關(guān)注

    關(guān)注

    1643

    文章

    21983

    瀏覽量

    614660
  • 以太網(wǎng)
    +關(guān)注

    關(guān)注

    40

    文章

    5594

    瀏覽量

    174988
  • usb
    usb
    +關(guān)注

    關(guān)注

    60

    文章

    8150

    瀏覽量

    271146
  • Zynq
    +關(guān)注

    關(guān)注

    10

    文章

    614

    瀏覽量

    48059
收藏 人收藏

    評論

    相關(guān)推薦
    熱點(diǎn)推薦

    一文帶你厘清自動駕駛架構(gòu)差異

    [首發(fā)于智駕最前沿微信公眾號]隨著自動駕駛技術(shù)飛速發(fā)展,智能駕駛系統(tǒng)的設(shè)計(jì)思路也經(jīng)歷了從傳統(tǒng)模塊化架構(gòu)大模型轉(zhuǎn)變。傳統(tǒng)模塊化架構(gòu)將感知、預(yù)測、規(guī)劃和控制等子任務(wù)拆分開,分別由不
    的頭像 發(fā)表于 05-08 09:07 ?203次閱讀
    一文帶你厘清自動駕駛<b class='flag-5'>端</b><b class='flag-5'>到</b><b class='flag-5'>端</b>架構(gòu)差異

    ZYNQ FPGA的PSIIC設(shè)備接口使用

    zynq系列中的FPGA,都會自帶兩個iic設(shè)備,我們直接調(diào)用其接口函數(shù)即可運(yùn)用。使用xilinx官方提供的庫函數(shù),開發(fā)起來方便快捷。
    的頭像 發(fā)表于 04-17 11:26 ?946次閱讀
    <b class='flag-5'>ZYNQ</b> FPGA的<b class='flag-5'>PS</b><b class='flag-5'>端</b>IIC設(shè)備接口使用

    東風(fēng)汽車推出自動駕駛開源數(shù)據(jù)

    近日,智能網(wǎng)聯(lián)汽車智駕數(shù)據(jù)空間構(gòu)建研討會暨中汽協(xié)會智能網(wǎng)聯(lián)汽車分會、數(shù)據(jù)分會2024年度會議在上海舉辦。會上,東風(fēng)汽車發(fā)布行業(yè)規(guī)模最大、涵蓋125萬組高質(zhì)量數(shù)據(jù)
    的頭像 發(fā)表于 04-01 14:54 ?522次閱讀

    技術(shù)分享 |多模態(tài)自動駕駛混合渲染HRMAD:將NeRF和3DGS進(jìn)行感知驗(yàn)證AD測試

    多模態(tài)自動駕駛混合渲染HRMAD,融合NeRF與3DGS技術(shù),實(shí)現(xiàn)超10萬㎡場景重建,多傳感器實(shí)時輸出,仿真更接近真實(shí)數(shù)據(jù)!然而,如何用高保真仿真場景快速驗(yàn)證自動駕駛算法?HRMAD已集成至aiSim平臺,
    的頭像 發(fā)表于 03-26 16:05 ?3279次閱讀
    技術(shù)分享 |多模態(tài)自動駕駛混合渲染HRMAD:將NeRF和3DGS進(jìn)行感知<b class='flag-5'>驗(yàn)證</b>和<b class='flag-5'>端</b><b class='flag-5'>到</b><b class='flag-5'>端</b>AD測試

    ZYNQ基礎(chǔ)---AXI DMA使用

    前言 在ZYNQ中進(jìn)行PL-PS數(shù)據(jù)交互的時候,經(jīng)常會使用到DMA,其實(shí)在前面的ZYNQ學(xué)習(xí)當(dāng)中,也有學(xué)習(xí)過
    的頭像 發(fā)表于 01-06 11:13 ?2045次閱讀
    <b class='flag-5'>ZYNQ</b>基礎(chǔ)---AXI <b class='flag-5'>DMA</b>使用

    自動駕駛技術(shù)研究與分析

    傳遞和全局優(yōu)化的優(yōu)勢,成為智能駕駛技術(shù)發(fā)展的重要方向。與傳統(tǒng)模塊化架構(gòu)相比,技術(shù)通過深度神經(jīng)網(wǎng)絡(luò)實(shí)現(xiàn)從傳感器數(shù)據(jù)輸入車輛控制信號輸出
    的頭像 發(fā)表于 12-19 13:07 ?806次閱讀

    在自動泊車的應(yīng)用

    與城市環(huán)境的復(fù)雜性和高速公路駕駛的風(fēng)險(xiǎn)相比,停車場景的特點(diǎn)是低速、空間有限和高可控性。這些特點(diǎn)為在車輛中逐步部署自動駕駛能力提供了可行的途徑。最重要的是自動泊車對時間不敏感,而自動駕駛幀率至少
    的頭像 發(fā)表于 12-18 11:38 ?857次閱讀
    <b class='flag-5'>端</b><b class='flag-5'>到</b><b class='flag-5'>端</b>在自動泊車的應(yīng)用

    PS3111固件下載,PS3111 SSD開卡工具成功修復(fù),HG2258量產(chǎn)開卡參考教程

    PS3111 SSD開卡成功,PS3111固件下載,HG2258量產(chǎn)開卡參考教程
    的頭像 發(fā)表于 12-04 18:18 ?6035次閱讀
    <b class='flag-5'>PS</b>3111固件下載,<b class='flag-5'>PS</b>3111 SSD開卡工具成功修復(fù),HG2258量產(chǎn)開卡參考教程

    爆火的如何加速智駕落地?

    自動駕駛,唯有?)技術(shù)通過消除模塊間數(shù)據(jù)
    的頭像 發(fā)表于 11-26 13:17 ?995次閱讀
    爆火的<b class='flag-5'>端</b><b class='flag-5'>到</b><b class='flag-5'>端</b>如何加速智駕落地?

    連接視覺語言大模型與自動駕駛

    自動駕駛在大規(guī)模駕駛數(shù)據(jù)上訓(xùn)練,展現(xiàn)出很強(qiáng)的決策規(guī)劃能力,但是面對復(fù)雜罕見的駕駛場景,依然存在局限性,這是因?yàn)?b class='flag-5'>端
    的頭像 發(fā)表于 11-07 15:15 ?643次閱讀
    連接視覺語言大模型與<b class='flag-5'>端</b><b class='flag-5'>到</b><b class='flag-5'>端</b>自動駕駛

    InfiniBand網(wǎng)絡(luò)解決LLM訓(xùn)練瓶頸

    的,這需要大量的計(jì)算資源和高速數(shù)據(jù)傳輸網(wǎng)絡(luò)。InfiniBand(IB)網(wǎng)絡(luò)作為高性能計(jì)算和AI模型訓(xùn)練的理想選擇,發(fā)揮著重要作用。在本文中,我們將深入探討大型語言模型(LLM)
    的頭像 發(fā)表于 10-23 11:26 ?1165次閱讀
    <b class='flag-5'>端</b><b class='flag-5'>到</b><b class='flag-5'>端</b>InfiniBand網(wǎng)絡(luò)解決LLM訓(xùn)練瓶頸

    測試用例怎么寫

    測試方法,旨在驗(yàn)證整個應(yīng)用程序從前端后端的流程是否能夠按照預(yù)期工作。它涉及多個系統(tǒng)組件和接口的交互,確保業(yè)務(wù)流程的完整性和正確性。 二、編寫
    的頭像 發(fā)表于 09-20 10:29 ?907次閱讀

    復(fù)旦微PS+PL異構(gòu)多核開發(fā)案例分享,基于FMQL20SM國產(chǎn)處理器平臺

    FMQL20S400M是復(fù)旦微四核ARM Cortex-A7@1GHz(PS)+85K可編程邏輯資源(PL)異構(gòu)多核SoC處理器。創(chuàng)龍科技基于FMQL20S400M設(shè)計(jì)的工業(yè)核心板
    發(fā)表于 08-22 14:04

    實(shí)現(xiàn)自動駕駛,唯有

    ,去年行業(yè)主流方案還是輕高精地圖城區(qū)智駕,今年大家的目標(biāo)都瞄到了(End-to-End, E2E)。
    的頭像 發(fā)表于 08-12 09:14 ?1342次閱讀
    實(shí)現(xiàn)自動駕駛,唯有<b class='flag-5'>端</b><b class='flag-5'>到</b><b class='flag-5'>端</b>?

    FM20S用戶手冊-PS + PL異構(gòu)多核案例開發(fā)手冊

    PS) + FPGA可編程邏輯資源(PL)異構(gòu)多核SoC處理器設(shè)計(jì)的全國產(chǎn)工業(yè)評估板,PS
    發(fā)表于 07-25 16:14
    主站蜘蛛池模板: 色综合久久久久久久久久久 | 成人三级视频 | 花怜write. as| 在线黄色大片 | 美女喷白浆视频 | 国产三级久久久精品三级 | 亚洲伊人精品综合在合线 | 日本免费一区二区三区视频 | 国产成人午夜片在线观看 | 亚洲h视频 | 国产免费人成在线看视频 | 欧美一级在线观看 | 五月婷六月婷婷 | 国产三a级日本三级日产三级 | 在线观看亚洲天堂 | 成人影院久久久久久影院 | 亚洲qingse中文字幕久久 | 天天干天天色综合网 | 国产福利在线观看一区二区 | 男人免费看片 | 噜噜噜动态图超猛烈 | 视频网站免费 | 中文字幕一二三区乱码老 | 欧美精品亚洲网站 | 韩国xxxxxxxx69 | 性做久久久久久久久 | 一级片aaa| 综综综综合网 | 天天爽夜夜操 | 天天se天天cao综合网蜜芽 | 国产大片免费观看中文字幕 | 久久久精品波多野结衣 | 日本又粗又长一进一出抽搐 | 久久综合九九亚洲一区 | 婷婷九月色| 综合aⅴ| 97影院理伦在线观看 | 香蕉视频在线免费播放 | 婷婷色九月综合激情丁香 | 精品无码中出一区二区 | 97人摸人人澡人人人超一碰 |