/****************************************************************************\
* Copyright (C) 2011, 2012, 2013 Texas Instruments Incorporated. *
* All Rights Reserved *
* *
* GENERAL DISCLAIMER *
* ------------------------------------------------------------------- *
* All software and related documentation is provided "AS IS" and without *
* warranty or support of any kind and Texas Instruments expressly disclaims*
* all other warranties, express or implied, including, but not limited to, *
* the implied warranties of merchantability and fitness for a particular *
* purpose. Under no circumstances shall Texas Instruments be liable for *
* any incidental, special or consequential damages that result from the *
* use or inability to use the software or related documentation, even if *
* Texas Instruments has been advised of the liability. *
****************************************************************************
Example to show memory access and interrupt throughput PCIE
In this example, DSP1's memory are mapped to DSP0 through PCIE
so, DSP0 accesses DSP 1 through the PCIE memory window just like
access other memory space.
To run 2 DSP test, You should run this project on the second core of the second
DSP firstly, and then the first core of the first DSP
Internal loopback is also supported in this example, for this case,
DSP0 actually access its own local memory through PCIE memory window.
****************************************************************************
* Written by : *
* Brighton Feng *
* Texas Instruments *
* June 23, 2013 *
* December 29, 2013 Thomas Yang, add two DSPs test
***************************************************************************/
#include <C6x.h>
#include <stdio.h>
#include <string.h>
#include <csl_xmcAux.h>
#include "KeyStone_common.h"
#include "common_test.h"
#include "KeyStone_DDR_init.h"
#include "KeyStone_PCIE_init_drv.h"
#include "PCIE_intc.h"
#include "PCIE_test.h"
PCIE_Loopback_Mode loop_mode= PCIE_PHY_LOOPBACK;
PCIE_Address_Width address_width= PCIE_ADDRESS_32_BITS;
#define PCIE_PREFETCH_BASE_ADDRESS 0x80000000
#define PCIE_NONFETCH_BASE_ADDRESS 0x10000000
/*RC BAR0 directly map to RC's PCIE application registers,
EP may write this space to trigger MSI to RC*/
#define PCIE_RC_BAR0_ADDRESS 0x01000000 //should >=0x400000???
//PCIE remote test address
#pragma DATA_SECTION(PcieRemoteTestAddr,".far:PCIEInit")
PCIERemoteTestAddress PcieRemoteTestAddr=
{
PCIE_OUTBOUND_DATA_WINDOW+0x0000000,//DDR_SRC_ADDR;
PCIE_OUTBOUND_DATA_WINDOW+0x1000000,//DDR_DST_ADDR;
PCIE_OUTBOUND_DATA_WINDOW+0x4000000,//SL2_SRC_ADDR;
PCIE_OUTBOUND_DATA_WINDOW+0x4040000,//SL2_DST_ADDR;
PCIE_OUTBOUND_DATA_WINDOW+0x4100000,//LL2_SRC_ADDR;
PCIE_OUTBOUND_DATA_WINDOW+0x4120000,//LL2_DST_ADDR;
};
/*Used for inbound configuration, as inbound offset*/
#pragma DATA_SECTION(memory_regions,".far:PCIEInit")
PCIE_Memory_Region memory_regions[]=
{
{0x80000000, 64*1024*1024}, //DDR3
{0x0C100000, 1*1024*1024}, //SL2
{0x11820000, 256*1024} //LL2
};
/*outbound PCIE address, only used for 2 DSP test for EP to access RC*/
#pragma DATA_SECTION(EP_OB_PCIE_address,".far:PCIEInit")
unsigned long long EP_OB_PCIE_address[]=
{//EP OB configuration should be done manually
PCIE_RC_BAR0_ADDRESS,
0x0000000080000000,
0x0000000090000000
//to do
};
/*Following two buffers are used for two devices test. Please note, they must
be allocated explicitly in link command file of this test project*/
#pragma DATA_ALIGN(uadEpRxBuf, 256);
//put this section at 0x11840000 at EP side
#pragma DATA_SECTION(uadEpRxBuf,"pcie_ep_rcv_buf")
Uint32 uadEpRxBuf[PCIE_BUFSIZE_APP+1];//The last one is for flag
/*To choose EP OB Offset[2]*/
unsigned int PcieEpToRcTestAddr = CSL_PCIE_REGS+0x1120000;
#pragma DATA_ALIGN(gaudRcRxBuf, 256);
//put this section at 0x90120000 at RC side
#pragma DATA_SECTION(gaudRcRxBuf,"pcie_rc_rcv_buf")
Uint32 gaudRcRxBuf[PCIE_BUFSIZE_APP+1];
#pragma DATA_ALIGN(srcBuf, 256);
Uint32 srcBuf[PCIE_BUFSIZE_APP+1];
#pragma DATA_SECTION(prefetch_regions,".far:PCIEInit")
PCIE_Memory_Regions prefetch_regions;
#pragma DATA_SECTION(nonfetch_regions,".far:PCIEInit")
PCIE_Memory_Regions nonfetch_regions;
#pragma DATA_SECTION(inbound_memory_regions,".far:PCIEInit")
PCIE_Inbound_Memory_Regions inbound_memory_regions;
#pragma DATA_SECTION(outbound_memory_regions,".far:PCIEInit")
PCIE_Outbound_Memory_Regions outbound_memory_regions;
#pragma DATA_SECTION(rc_cfg,".far:PCIEInit")
PCIE_RC_Config rc_cfg;
#pragma DATA_SECTION(PCIE_int_cfg,".far:PCIEInit")
PCIE_Interrupt_Config PCIE_int_cfg;
#pragma DATA_SECTION(remote_cfg_setup,".far:PCIEInit")
PCIE_Remote_CFG_SETUP remote_cfg_setup;
#pragma DATA_SECTION(PCIE_cfg,".far:PCIEInit")
KeyStone_PCIE_Config PCIE_cfg;
extern PCIE_DSP_core_test(PCIERemoteTestAddress* remoteAddr);
extern PCIE_edma_test(PCIERemoteTestAddress* remoteAddr);
/*simple memory test to verfiy basic function of PCIE */
unsigned int PCIE_Mem_Test(unsigned int uiStartAddress,
unsigned int uiTotalByteCount, unsigned int uiFillByteCount)
{
unsigned int uiFailCount;
uiFailCount = Memory_quick_test(uiStartAddress, uiTotalByteCount,
uiFillByteCount, 128);
if(0==uiFailCount)
printf("PCIE memory test passed at address 0x%x\n",
uiStartAddress);
return uiFailCount;
}
/*test data transfer between RC and EP. This function execute on RC.
RC writes data to EP, wait for EP sends back the data to RC, verify the data*/
void PCIE_Remoteloopback_Test(PCIERemoteTestAddress * remoteAddr)
{
Uint32 i;
Uint8 ucErrorFlag = 0;
/*Core 1 LL2*/
//PCIE_Mem_Test(remoteAddr->LL2_DST_ADDR, 0x10000, 1);
Uint32 *pudDestPCIEAddr;
pudDestPCIEAddr = (Uint32*)remoteAddr->LL2_DST_ADDR;
/* add dstOffset to pcieBase for data transfer */
for (i=0; i<PCIE_BUFSIZE_APP; i++)
{
gaudRcRxBuf[i] = 0;
srcBuf[i] = i;
}
puts("#########RC starts sent data to EP!#########");
for (i=0; i<PCIE_BUFSIZE_APP; i++)
{
*((volatile Uint32 *)pudDestPCIEAddr + i) = srcBuf[i];
}
/* Mark that the buffer is full, so EP can process it */
*((volatile Uint32 *)pudDestPCIEAddr + PCIE_BUFSIZE_APP) = PCIE_EXAMPLE_BUF_FULL;
/* Note on cache coherence: Write back is not necessary because pcieBase is in
peripheral address space instead of physical memory*/
/* Data sent to EP.
RC waits for the loopback to be completed and
receive data back from EP */
do {
/* Cleanup the prefetch buffer also. */
CSL_XMC_invalidatePrefetchBuffer();
CACHE_invL1d ((void *)gaudRcRxBuf, PCIE_EXAMPLE_DSTBUF_BYTES, CACHE_FENCE_WAIT);
CACHE_invL2 ((void *)gaudRcRxBuf, PCIE_EXAMPLE_DSTBUF_BYTES, CACHE_FENCE_WAIT);
} while(gaudRcRxBuf[PCIE_BUFSIZE_APP]!= PCIE_EXAMPLE_BUF_FULL);
puts ("RC has received echo data from EP!");
puts("#########RC is verifying the received data!#########");
/* check all the data */
for (i=0; i<PCIE_BUFSIZE_APP; i++)
{
if(gaudRcRxBuf[i] != srcBuf[i])
{
printf ("Received data = %d\nTransmited data = %d\nIndex = %d.\n\nTest failed.\n",
gaudRcRxBuf[i], srcBuf[i], i);
ucErrorFlag = 1;
}
}
if(!ucErrorFlag)
{
puts("All the data are correct, Rc->EP->RC echo test passed!");
}
}
/*test data trans