summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: f000f89)
raw | patch | inline | side by side (parent: f000f89)
author | John Dowdal <jdowdal@ti.com> | |
Sun, 11 Sep 2016 19:37:32 +0000 (15:37 -0400) | ||
committer | John Dowdal <jdowdal@ti.com> | |
Sun, 11 Sep 2016 19:37:32 +0000 (15:37 -0400) |
example/edmaPktBench/edmaPktBench.c | patch | blob | history | |
example/edmaPktBench/edmaPktBench.h | patch | blob | history | |
example/edmaPktBench/edmaPktMsiBench.c | [new file with mode: 0644] | patch | blob |
example/edmaPktBench/edmaPktMsiBench.h | [new file with mode: 0644] | patch | blob |
example/sample/am571x/armv7/bios/PCIE_idkAM571x_wSoCLib_armEdmaPktExampleProject.txt | patch | blob | history | |
example/sample/am571x/armv7/bios/pcie_edmapkt.cfg | [new file with mode: 0644] | patch | blob |
example/sample/am57x/src/pcie_sample_board.c | patch | blob | history | |
example/sample/src/pcie_sample.c | patch | blob | history | |
package.xdc | patch | blob | history | |
pciever.h | patch | blob | history |
index b13926a9c0875ae0e6a80479d4429cd0f9481d38..bc08d6b462cf8a47521d29d760d21474ba2fae17 100644 (file)
*/\r
\r
#include "pcie_sample.h"\r
+#include "edmaPktMsiBench.h"\r
#include <ti/csl/csl_edma.h>\r
#include <ti/drv/pcie/src/pcieloc.h> /* for pcie_setbits */\r
#include <ti/osal/CacheP.h>\r
+#include <ti/osal/HwiP.h>\r
+#include <ti/csl/csl_timer.h>\r
+#include <stdio.h> /* snprintf */\r
\r
+/* Which EDMA to use */\r
#define EDMAPKT_BASE (CSL_MPU_EDMA_TPCC_REGS)\r
\r
- EDMA3CCPaRAMEntry rxRAMParams[EDMAPKT_NUM_RX_PARAMS];\r
-volatile EDMA3CCPaRAMEntry txRAMParams[EDMAPKT_NUM_TX_PARAMS] __attribute__ ((aligned(64), section(".bss:txparamram")));\r
-volatile char pktLocRAM[EDMAPKT_TX_PKT_RAM_SIZE] __attribute__ ((aligned(64), section(".bss:pktram")));\r
+/* Starting param/channel for each port model */\r
+#define EDMAPKT_FIRST_REAL_PARAM_TX_P1 (16u)\r
+#define EDMAPKT_FIRST_REAL_CH_TX_P1 (0u)\r
+#define EDMAPKT_INTERRUPT_CH_TX_P1 (2u)\r
\r
-/* Contains destination addresses stored in local memory */\r
-volatile void *txDestDesc[EDMAPKT_NUM_TX_PKTS] __attribute__ ((aligned(64), section(".bss:txDstDesc")));\r
+#define EDMAPKT_FIRST_REAL_PARAM_TX_P2 (21u)\r
+#define EDMAPKT_FIRST_REAL_CH_TX_P2 (4u)\r
+#define EDMAPKT_INTERRUPT_CH_TX_P2 (6u)\r
\r
-/* Starting param index */\r
-#define EDMAPKT_FIRST_REAL_PARAM (16u)\r
+#define EDMAPKT_FIRST_REAL_PARAM_RX_P1 (26u)\r
+#define EDMAPKT_FIRST_REAL_CH_RX_P1 (8u)\r
+#define EDMAPKT_INTERRUPT_CH_RX_P1 (10u)\r
\r
-void setupTxDMA (edmaPktBenchBuf_t *buf)\r
+#define EDMAPKT_FIRST_REAL_PARAM_RX_P2 (31u)\r
+#define EDMAPKT_FIRST_REAL_CH_RX_P2 (12u)\r
+#define EDMAPKT_INTERRUPT_CH_RX_P2 (14u)\r
+\r
+/* Number of times to repeat TX cycle */\r
+#define EDMAPKT_NUM_CYCLES (100u)\r
+#define EDMAPKT_NUM_TX_TXNS (EDMAPKT_NUM_CYCLES) /* space to record timing of TX cycles */\r
+#define EDMAPKT_NUM_RX_TXNS (EDMAPKT_NUM_CYCLES * 32) /* space to record timing of RX cycles */\r
+\r
+/* Interupt vector numbers */\r
+#define EDMAPKT_EDMA_VECTOR (102u)\r
+#define EDMAPKT_TIMER_VECTOR (101u)\r
+\r
+/* Set up timer to tick every 64 bytes at 100M.\r
+ * Assuming 8 byte preamble, 12 byte gap, and 64 byte frame = 84 bytes/672 bits.\r
+ * This is 672/100M = 6.72us.\r
+ * With 20M reference clock this is every 134 clocks.\r
+ */\r
+#define EDMAPKT_TIMER_TICK_CLOCKS (134u)\r
+#define EDMAPKT_TIMER_INITIAL_COUNT (0xffffffffu - EDMAPKT_TIMER_TICK_CLOCKS)\r
+#define EDMAPKT_TIMER_RLD_COUNT (0xffffffffu - EDMAPKT_TIMER_TICK_CLOCKS)\r
+\r
+/* Virtual params for EDMA for TX pkt stored in RAM */\r
+typedef volatile EDMA3CCPaRAMEntry txRAMParams_t[EDMAPKT_NUM_TX_PARAMS + 1]; /* +1 pads to 64 byte line boundary */\r
+/* Local copies of packets pulled over PCIE */\r
+typedef volatile char txLocPktRAM_t[EDMAPKT_TX_PKT_RAM_SIZE];\r
+/* Local copies of packets pushed over PCIE */\r
+typedef volatile char rxLocPktRAM_t[EDMAPKT_RX_PKT_RAM_SIZE];\r
+/* Virtual params for EDMA for RX pkt stored in RAM */\r
+typedef volatile EDMA3CCPaRAMEntry rxRAMParams_t[EDMAPKT_NUM_RX_PARAMS + 1]; /* +1 pads to 64 byte line boundary */\r
+/* Local Descriptors containing addresses in txLocPktRAM for tx pkts */\r
+typedef volatile void *txDestDesc_t[EDMAPKT_NUM_TX_PKTS + 15]; /* +15 pads to 64 byte line boundary */\r
+/* Local Descriptors containing remote destination address in PCIE for rx pkts */\r
+typedef volatile void *rxDestDesc_t[EDMAPKT_NUM_RX_PKTS + 15]; /* +15 pads to 64 byte line boundary */\r
+/* Local Descriptors containing local source address in rxLocPktRAM for rx pkts */\r
+typedef volatile void *rxSrcDesc_t[EDMAPKT_NUM_RX_PKTS + 15]; /* +15 pads to 64 byte line boundary */\r
+\r
+/* All local buffers aligned and padded for cache and put in sections for placement */\r
+rxRAMParams_t rxRAMParamsP1 __attribute__ ((aligned(64), section(".bss:paramram")));\r
+rxRAMParams_t rxRAMParamsP2 __attribute__ ((aligned(64), section(".bss:paramram")));\r
+txRAMParams_t txRAMParamsP1 __attribute__ ((aligned(64), section(".bss:paramram")));\r
+txRAMParams_t txRAMParamsP2 __attribute__ ((aligned(64), section(".bss:paramram")));\r
+txLocPktRAM_t txPktLocRAMP1 __attribute__ ((aligned(64), section(".bss:pktram")));\r
+txLocPktRAM_t txPktLocRAMP2 __attribute__ ((aligned(64), section(".bss:pktram")));\r
+rxLocPktRAM_t rxPktLocRAMP1 __attribute__ ((aligned(64), section(".bss:pktram")));\r
+rxLocPktRAM_t rxPktLocRAMP2 __attribute__ ((aligned(64), section(".bss:pktram")));\r
+txDestDesc_t txDestDescP1 __attribute__ ((aligned(64), section(".bss:pktdesc")));\r
+txDestDesc_t txDestDescP2 __attribute__ ((aligned(64), section(".bss:pktdesc")));\r
+rxDestDesc_t rxDestDescP1 __attribute__ ((aligned(64), section(".bss:pktdesc")));\r
+rxDestDesc_t rxDestDescP2 __attribute__ ((aligned(64), section(".bss:pktdesc")));\r
+rxSrcDesc_t rxSrcDescP1 __attribute__ ((aligned(64), section(".bss:pktdesc")));\r
+rxSrcDesc_t rxSrcDescP2 __attribute__ ((aligned(64), section(".bss:pktdesc")));\r
+\r
+/* Parameters to configure TX chain */\r
+typedef struct txEdmaSetup_s {\r
+ txRAMParams_t *RAMParams; /* Virtual params for edma stored in RAM */\r
+ txDestDesc_t *destDesc; /* local destination descriptors holding destination pkt addresses */\r
+ txLocPktRAM_t *pktLocRAM; /* Local (dst) packet memory */\r
+ int32_t realCh; /* First channel (of 3) for this port */\r
+ int32_t realParam; /* First param number (of EDMAPKT_NUM_TX_PARAMS_PER_PKT + EDMAPKT_NUM_TX_PARAMS_LINKAGE) + 1 */\r
+} txEdmaSetup_t;\r
+\r
+/* Parameters to configure RX chain (only 1 packet at a time implemented) */\r
+typedef struct rxEdmaSetup_s {\r
+ rxRAMParams_t *RAMParams; /* Virtual params for edma stored in RAM */\r
+ rxSrcDesc_t *srcDesc; /* local source descriptors holding source pkt address */\r
+ rxDestDesc_t *destDesc; /* local destination descriptiors holding remote pkt address */\r
+ rxLocPktRAM_t *pktLocRAM; /* Local (src) packet memory */\r
+ int32_t realCh; /* First channel (of 3) for this port */\r
+ int32_t realParam; /* First param number (of EDMAPKT_NUM_TX_PARAMS_PER_PKT + EDMAPKT_NUM_TX_PARAMS_LINKAGE) + 1 */\r
+} rxEdmaSetup_t;\r
+\r
+\r
+/* Memory for timestamp logs */\r
+uint32_t txTime20MHzP1[EDMAPKT_NUM_TX_TXNS];\r
+int32_t txLogIdxP1 = 0;\r
+uint32_t txTime20MHzP2[EDMAPKT_NUM_TX_TXNS];\r
+int32_t txLogIdxP2 = 0;\r
+uint32_t rxTime20MHzP1[EDMAPKT_NUM_RX_TXNS];\r
+int32_t rxLogIdxP1 = 0;\r
+uint32_t rxTime20MHzP2[EDMAPKT_NUM_RX_TXNS];\r
+int32_t rxLogIdxP2 = 0;\r
+\r
+/* State variables used internally */\r
+volatile uint32_t ticks = 0;\r
+volatile uint32_t sendphase = 0;\r
+volatile uint32_t triggered = 0;\r
+#define EDMAPKT_ENABLEESR_TX_P1 (1u)\r
+#define EDMAPKT_ENABLEESR_TX_P2 (2u)\r
+#define EDMAPKT_ENABLEESR_RX_P1 (4u)\r
+#define EDMAPKT_ENABLEESR_RX_P2 (8u)\r
+volatile uint32_t enableESR = 0;\r
+volatile uint32_t finishedESR = 0;\r
+volatile uint32_t lateTX = 0;\r
+volatile uint32_t lateRX = 0;\r
+uint32_t txCyclesP1 = 0; /* Number of TX cycles done on port 1 */\r
+uint32_t txCyclesP2 = 0; /* Number of TX cycles done on port 2 */\r
+uint32_t rxPktsP1 = 0; /* Number of RX packets done on port 1 */\r
+uint32_t rxPktsP2 = 0; /* Number of RX packets done on port 2 */\r
+volatile uint32_t triggerTxTickP1 = 0;\r
+volatile uint32_t triggerTxTickP2 = 0;\r
+volatile uint32_t triggerRxTickP1 = 0;\r
+volatile uint32_t triggerRxTickP2 = 0;\r
+\r
+HwiP_Handle timerIsrHnd;\r
+HwiP_Handle edmaIsrHnd;\r
+\r
+/* Configures self-priming chain of multiple TX packets with virtual\r
+ * parameters in RAM */\r
+void setupTxDMA (edmaPktBenchTxBuf_t *remBuf, txEdmaSetup_t *tx)\r
{\r
int32_t pkt, paIndx;\r
- uint32_t opt_linked, opt_chained_ch1, opt_chained_ch2;\r
+ uint32_t opt_interrupt, opt_static_chained_ch1, opt_chained_ch1, opt_static_chained_ch2, opt_static_chained_ch3;\r
+ volatile EDMA3CCPaRAMEntry *pParam;\r
+\r
+ /* Set up virtual params - set all 0 */\r
+ memset ((void *)tx->RAMParams, 0, sizeof(*tx->RAMParams));\r
+\r
+ /* fix up defaults that aren't 0 outside opt */\r
+ for (paIndx = 0; paIndx < EDMAPKT_NUM_TX_PARAMS; paIndx++)\r
+ {\r
+ pParam = &(*tx->RAMParams)[paIndx];\r
+ pParam->bCnt = 1;\r
+ pParam->cCnt = 1;\r
+ }\r
\r
- memset ((void *)txRAMParams, 0, sizeof(txRAMParams));\r
/* Setup "descriptor" with real src/dst */\r
for (pkt = 0; pkt < EDMAPKT_NUM_TX_PKTS; pkt++)\r
{\r
/* Source will be something on other side of PCIE */\r
/* Normally RC will fill this in, but no real packet traffic so fill it in here */\r
- buf->txSrcDesc[pkt] = &buf->buf[pkt*EDMAPKT_TX_PKT_SIZE];\r
+ remBuf->txSrcDesc[pkt] = &remBuf->buf[pkt*EDMAPKT_TX_PKT_SIZE];\r
/* Destination is local memory. Keeping separate buffers for debug purposes */\r
/* This enables double/triple buffer management */\r
- txDestDesc[pkt] = &pktLocRAM[pkt*EDMAPKT_TX_PKT_SIZE];\r
+ (*tx->destDesc)[pkt] = &(*tx->pktLocRAM)[pkt*EDMAPKT_TX_PKT_SIZE];\r
+ /* Mark each packet to prove dma completed */\r
+ remBuf->buf[pkt*EDMAPKT_TX_PKT_SIZE] = (char)pkt + 1;\r
}\r
- opt_linked = 0;\r
+ opt_interrupt = 0;\r
opt_chained_ch1 = 0;\r
- opt_chained_ch2 = 0;\r
- pcie_setbits (opt_chained_ch1, EDMA_TPCC_OPT_TCCHEN, 0); /* transfer complete chaining */\r
- pcie_setbits (opt_chained_ch1, EDMA_TPCC_OPT_TCC, 1); /* chain channel #1 */\r
- pcie_setbits (opt_chained_ch2, EDMA_TPCC_OPT_TCCHEN, 0); /* transfer complete chaining */\r
- pcie_setbits (opt_chained_ch2, EDMA_TPCC_OPT_TCC, 2); /* chain channel #2 */\r
+ opt_static_chained_ch2 = 0;\r
+ opt_static_chained_ch3 = 0;\r
+\r
+ pcie_setbits (opt_interrupt, EDMA_TPCC_OPT_TCINTEN, 1); /* Interrupt when whole transfer is done */\r
+ pcie_setbits (opt_interrupt, EDMA_TPCC_OPT_TCC, tx->realCh + 2); /* interrupt channel 2 */\r
+ pcie_setbits (opt_interrupt, EDMA_TPCC_OPT_STATIC, 1); /* don't wipe this param so it can be reused */\r
+\r
+ pcie_setbits (opt_chained_ch1, EDMA_TPCC_OPT_TCCHEN, 1); /* transfer complete chaining */\r
+ pcie_setbits (opt_chained_ch1, EDMA_TPCC_OPT_TCC, tx->realCh + 1); /* chain channel #1 */\r
+\r
+ opt_static_chained_ch1 = opt_chained_ch1;\r
+ pcie_setbits (opt_static_chained_ch1, EDMA_TPCC_OPT_STATIC, 1); /* don't wipe this param so it can be reused */\r
+\r
+ pcie_setbits (opt_static_chained_ch2, EDMA_TPCC_OPT_TCCHEN, 1); /* transfer complete chaining */\r
+ pcie_setbits (opt_static_chained_ch2, EDMA_TPCC_OPT_TCC, tx->realCh + 2); /* chain channel #2 */\r
+ pcie_setbits (opt_static_chained_ch2, EDMA_TPCC_OPT_STATIC, 1); /* don't wipe this param so it can be reused */\r
+\r
+ pcie_setbits (opt_static_chained_ch3, EDMA_TPCC_OPT_TCCHEN, 1); /* transfer complete chaining */\r
+ pcie_setbits (opt_static_chained_ch3, EDMA_TPCC_OPT_TCC, tx->realCh + 3); /* chain channel #3 */\r
+ pcie_setbits (opt_static_chained_ch3, EDMA_TPCC_OPT_STATIC, 1); /* don't wipe this param so it can be reused */\r
\r
paIndx = 0;\r
- txRAMParams[paIndx].opt = opt_chained_ch1;\r
+ pParam = &(*tx->RAMParams)[paIndx];\r
+ pParam->opt = opt_static_chained_ch1;\r
/* Step 0 : Fetch first block of params from RAM to PaRAM */\r
- txRAMParams[paIndx].srcAddr = (uint32_t)&txRAMParams[1];\r
- txRAMParams[paIndx].destAddr = EDMAPKT_BASE + EDMA_TPCC_DST(EDMAPKT_FIRST_REAL_PARAM + 1);\r
- txRAMParams[paIndx].aCnt = sizeof(txRAMParams[paIndx].srcAddr);\r
+ pParam->srcAddr = (uint32_t)&(*tx->RAMParams)[1];\r
+ pParam->destAddr = EDMAPKT_BASE + EDMA_TPCC_OPT(tx->realParam + 1);\r
+ pParam->aCnt = EDMAPKT_NUM_TX_PARAMS_PER_LINKAGE * sizeof(*pParam);\r
+\r
/* This transfer links to next param */\r
- txRAMParams[paIndx].linkAddr = 0xffff; /* stop and cross trigger channel */\r
+ pParam->linkAddr = 0xffff; /* stop and cross trigger channel */\r
paIndx++;\r
+ pParam = &(*tx->RAMParams)[paIndx];\r
\r
for (pkt = 0; pkt < EDMAPKT_NUM_TX_PKTS; pkt++)\r
{\r
- txRAMParams[paIndx].opt = opt_linked;\r
+ pParam->opt = opt_chained_ch1; /* chain to self triggers linked param */\r
/* Step 1 : load source addr from desc over pcie to param */\r
- txRAMParams[paIndx].srcAddr = (uint32_t)&buf->txSrcDesc[pkt];\r
- txRAMParams[paIndx].destAddr = EDMAPKT_BASE + EDMA_TPCC_SRC(EDMAPKT_FIRST_REAL_PARAM + 3);\r
- txRAMParams[paIndx].aCnt = sizeof(txRAMParams[paIndx].srcAddr);\r
+ pParam->srcAddr = (uint32_t)&remBuf->txSrcDesc[pkt];\r
+ pParam->destAddr = EDMAPKT_BASE + EDMA_TPCC_SRC(tx->realParam + 3);\r
+ pParam->aCnt = sizeof(pParam->srcAddr);\r
/* This transfer links to next param */\r
- txRAMParams[paIndx].linkAddr = EDMA_TPCC_OPT(EDMAPKT_FIRST_REAL_PARAM + 2);\r
+ pParam->linkAddr = EDMA_TPCC_OPT(tx->realParam + 2);\r
\r
paIndx++;\r
- txRAMParams[paIndx].opt = opt_chained_ch2;\r
+ pParam = &(*tx->RAMParams)[paIndx];\r
+ pParam->opt = opt_static_chained_ch2;\r
/* Step 2 : load dest addr from local desc to param */\r
- txRAMParams[paIndx].srcAddr = (uint32_t)&txDestDesc[pkt];\r
- txRAMParams[paIndx].destAddr = EDMAPKT_BASE + EDMA_TPCC_DST(EDMAPKT_FIRST_REAL_PARAM + 3);\r
- txRAMParams[paIndx].aCnt = sizeof(txRAMParams[paIndx].destAddr);\r
- txRAMParams[paIndx].linkAddr = 0xffff; /* Stop and cross trigger channel */\r
+ pParam->srcAddr = (uint32_t)&((*tx->destDesc)[pkt]);\r
+ pParam->destAddr = EDMAPKT_BASE + EDMA_TPCC_DST(tx->realParam + 3);\r
+ pParam->aCnt = sizeof(pParam->destAddr);\r
+ pParam->linkAddr = 0xffff; /* Stop and cross trigger channel */\r
\r
paIndx++;\r
- txRAMParams[paIndx].opt = opt_linked;\r
+ pParam = &(*tx->RAMParams)[paIndx];\r
+ pParam->opt = opt_static_chained_ch3; /* chain to self triggers linked param */\r
/* Step 3 : Copy the buffer */\r
- txRAMParams[paIndx].srcAddr = 0xfee1deadu; /* replaced by step 1 above */\r
- txRAMParams[paIndx].destAddr = 0xbabefaceu; /* replaced by step 2 above */\r
- txRAMParams[paIndx].aCnt = EDMAPKT_TX_PKT_SIZE;\r
+ pParam->srcAddr = 0xfee1deadu; /* replaced by step 1 above */\r
+ pParam->destAddr = 0xbabefaceu; /* replaced by step 2 above */\r
+ pParam->aCnt = EDMAPKT_TX_PKT_SIZE;\r
+ pParam->linkAddr = 0xffff; /* Stop and cross trigger channel */\r
\r
if (pkt != (EDMAPKT_NUM_TX_PKTS - 1))\r
{\r
- txRAMParams[paIndx].linkAddr = EDMA_TPCC_OPT(EDMAPKT_FIRST_REAL_PARAM + 4);\r
-\r
paIndx++;\r
- txRAMParams[paIndx].opt = opt_chained_ch1;\r
- /* Step 3 : Copy the next params from RAM to PaRAM */\r
- txRAMParams[paIndx].srcAddr = (uint32_t)&txRAMParams[paIndx - 3];\r
- txRAMParams[paIndx].destAddr = EDMAPKT_BASE + EDMA_TPCC_DST(EDMAPKT_FIRST_REAL_PARAM + 1);\r
- txRAMParams[paIndx].aCnt = 4*sizeof(txRAMParams[0]);\r
- txRAMParams[paIndx].linkAddr = 0xffff; /* Stop and cross trigger channel */\r
+ pParam = &(*tx->RAMParams)[paIndx];\r
+ /* Static to avoid clobbering new incoming params */\r
+ pParam->opt = opt_static_chained_ch1;\r
+ /* Step 4 : Copy the next params from RAM to PaRAM */\r
+ pParam->srcAddr = (uint32_t)&(*tx->RAMParams)[paIndx + 1];\r
+ pParam->destAddr = EDMAPKT_BASE + EDMA_TPCC_OPT(tx->realParam + 1);\r
+ pParam->aCnt = EDMAPKT_NUM_TX_PARAMS_PER_LINKAGE * sizeof(*pParam);\r
+ pParam->linkAddr = 0xffff; /* Stop and cross trigger channel */\r
}\r
else\r
{\r
- txRAMParams[paIndx].linkAddr = 0xffff; /* Stop */\r
+ /* After buffer copy done, no more packets */\r
+ pParam->opt = opt_interrupt; /* no chain causes pump to unprime */\r
}\r
\r
paIndx++;\r
+ pParam = &(*tx->RAMParams)[paIndx];\r
}\r
/* Write back all the above so EDMA can see it */\r
- CacheP_wb (&txRAMParams, sizeof(txRAMParams));\r
- CacheP_wb (&txDestDesc, sizeof(txDestDesc));\r
- CacheP_wb (&buf->txSrcDesc, sizeof(buf->txSrcDesc));\r
+ CacheP_wb (tx->RAMParams, sizeof(*tx->RAMParams));\r
+ CacheP_wb (tx->destDesc, sizeof(*tx->destDesc));\r
+ CacheP_wb (&remBuf->txSrcDesc[0], sizeof(remBuf->txSrcDesc));\r
}\r
\r
-void setupRxDMA (void)\r
+/* Configures self-priming chain of multiple RX packets with virtual\r
+ * parameters in RAM. Chain of 1 supported */\r
+void setupRxDMA (edmaPktBenchRxBuf_t *remBuf, rxEdmaSetup_t *rx)\r
{\r
- int32_t pkt, paIndx;\r
- uint32_t opt;\r
-\r
- memset ((void *)rxRAMParams, 0, sizeof(rxRAMParams));\r
- opt = 0; \r
- pcie_setbits (opt, EDMA_TPCC_OPT_ITCCHEN, 0); /* intermediate transfer complete chaining */\r
- pcie_setbits (opt, EDMA_TPCC_OPT_TCCHEN, 0); /* transfer complete chaining */\r
- pcie_setbits (opt, EDMA_TPCC_OPT_ITCINTEN, 0); /* intermediate transfer complete interrupt */\r
- pcie_setbits (opt, EDMA_TPCC_OPT_TCINTEN, 0); /* transfer complete interrupt */\r
- pcie_setbits (opt, EDMA_TPCC_OPT_WIMODE, 0); /* normal mode */\r
- pcie_setbits (opt, EDMA_TPCC_OPT_TCC, 0); /* transfer complete code */\r
- pcie_setbits (opt, EDMA_TPCC_OPT_TCCMODE, 0); /* transfer complete code mode 0=normal, 1=early */\r
- pcie_setbits (opt, EDMA_TPCC_OPT_FWID, 0); /* fifo width for sam/dam */\r
- pcie_setbits (opt, EDMA_TPCC_OPT_SYNCDIM, 0); /* 0=async, 1=absync */\r
- pcie_setbits (opt, EDMA_TPCC_OPT_DAM, 0); /* dst not fifo */\r
- pcie_setbits (opt, EDMA_TPCC_OPT_SAM, 0); /* src not fifo */\r
+ int32_t paIndx;\r
+ uint32_t opt_interrupt, opt_static_chained_ch1, opt_chained_ch1, opt_chained_ch2;\r
+ volatile EDMA3CCPaRAMEntry *pParam;\r
+\r
+ /* Set up virtual params - set all 0 */\r
+ memset ((void *)rx->RAMParams, 0, sizeof(*rx->RAMParams));\r
+\r
+ /* fix up defaults that aren't 0 outside opt */\r
+ for (paIndx = 0; paIndx < EDMAPKT_NUM_RX_PARAMS; paIndx++)\r
+ {\r
+ pParam = &(*rx->RAMParams)[paIndx];\r
+ pParam->bCnt = 1;\r
+ pParam->cCnt = 1;\r
+ }\r
+\r
+ /* destination will be something on other side of PCIE - but descriptor\r
+ * (allocation) is done locally */\r
+ (*rx->destDesc)[0] = &remBuf->buf[0];\r
+ /* source is local memory. This enables double/triple buffer management */\r
+ (*rx->srcDesc)[0] = &(*rx->pktLocRAM)[0];\r
+ /* Mark each packet to prove dma completed */\r
+ (*rx->pktLocRAM)[0] = (char)1;\r
+\r
+ opt_interrupt = 0;\r
+ opt_chained_ch1 = 0;\r
+ opt_chained_ch2 = 0;\r
+\r
+ pcie_setbits (opt_interrupt, EDMA_TPCC_OPT_TCINTEN, 1); /* Interrupt when whole transfer is done */\r
+ pcie_setbits (opt_interrupt, EDMA_TPCC_OPT_TCC, rx->realCh + 2); /* interrupt channel 2 */\r
+ pcie_setbits (opt_chained_ch1, EDMA_TPCC_OPT_TCCHEN, 1); /* transfer complete chaining */\r
+ pcie_setbits (opt_chained_ch1, EDMA_TPCC_OPT_TCC, rx->realCh + 1); /* chain channel #1 */\r
+ opt_static_chained_ch1 = opt_chained_ch1;\r
+ pcie_setbits (opt_static_chained_ch1, EDMA_TPCC_OPT_STATIC, 1); /* don't wipe this param so it can be reused */\r
+\r
+ pcie_setbits (opt_chained_ch2, EDMA_TPCC_OPT_TCCHEN, 1); /* transfer complete chaining */\r
+ pcie_setbits (opt_chained_ch2, EDMA_TPCC_OPT_TCC, rx->realCh + 2); /* chain channel #2 */\r
\r
paIndx = 0;\r
- for (pkt = 0; pkt < EDMAPKT_NUM_RX_PKTS; pkt++)\r
- {\r
- /* Load real source address into param + 2 */\r
- rxRAMParams[paIndx].opt = opt;\r
- /* Following are not used and set to 0 by memset */\r
- /*\r
- rxRAMParams[paIndx].srcAddr;\r
- rxRAMParams[paIndx].aCnt;\r
- rxRAMParams[paIndx].destAddr = &rxRAMParams[paIndx + 2].srcAddr;\r
- rxRAMParams[paIndx].bCnt;\r
- rxRAMParams[paIndx].srcBIdx;\r
- rxRAMParams[paIndx].destBIdx;\r
- rxRAMParams[paIndx].linkAddr;\r
- rxRAMParams[paIndx].bCntReload;\r
- rxRAMParams[paIndx].srcCIdx;\r
- rxRAMParams[paIndx].destCIdx;\r
- rxRAMParams[paIndx].cCnt;\r
- */\r
+ pParam = &(*rx->RAMParams)[paIndx];\r
+ pParam->opt = opt_static_chained_ch1;\r
+ /* Step 0 : Fetch first block of params from RAM to PaRAM */\r
+ pParam->srcAddr = (uint32_t)&(*rx->RAMParams)[1];\r
+ pParam->destAddr = EDMAPKT_BASE + EDMA_TPCC_OPT(rx->realParam + 1);\r
+ pParam->aCnt = 3 * sizeof(*pParam);\r
+\r
+ /* This transfer links to next param */\r
+ pParam->linkAddr = 0xffff; /* stop and cross trigger channel */\r
+ paIndx++;\r
+ pParam = &(*rx->RAMParams)[paIndx];\r
+\r
+ pParam->opt = opt_chained_ch1; /* chain to self triggers linked param */\r
+ /* Step 1 : load source addr from desc locally */\r
+ pParam->srcAddr = (uint32_t)&((*rx->srcDesc)[0]);\r
+ pParam->destAddr = EDMAPKT_BASE + EDMA_TPCC_SRC(rx->realParam + 3);\r
+ pParam->aCnt = sizeof(pParam->srcAddr);\r
+ /* This transfer links to next param */\r
+ pParam->linkAddr = EDMA_TPCC_OPT(rx->realParam + 2);\r
+\r
+ paIndx++;\r
+ pParam = &(*rx->RAMParams)[paIndx];\r
+ pParam->opt = opt_chained_ch2;\r
+ /* Step 2 : load dest addr from local desc to param */\r
+ pParam->srcAddr = (uint32_t)&((*rx->destDesc)[0]);\r
+ pParam->destAddr = EDMAPKT_BASE + EDMA_TPCC_DST(rx->realParam + 3);\r
+ pParam->aCnt = sizeof(pParam->destAddr);\r
+ pParam->linkAddr = 0xffff; /* Stop and cross trigger channel */\r
+\r
+ paIndx++;\r
+ pParam = &(*rx->RAMParams)[paIndx];\r
+ pParam->opt = opt_interrupt; /* no chain causes pump to unprime */\r
+ /* Step 3 : Copy the buffer */\r
+ pParam->srcAddr = 0xfee1deadu; /* replaced by step 1 above */\r
+ pParam->destAddr = 0xbabefaceu; /* replaced by step 2 above */\r
+ pParam->aCnt = EDMAPKT_RX_PKT_SIZE;\r
+ pParam->linkAddr = 0xffff; /* Stop */\r
+\r
+ \r
+ /* Write back all the above so EDMA can see it */\r
+ CacheP_wb (rx->RAMParams, sizeof(*rx->RAMParams));\r
+ CacheP_wb (rx->destDesc, sizeof(*rx->destDesc));\r
+ CacheP_wb (rx->srcDesc, sizeof(*rx->srcDesc));\r
+ CacheP_wb (rx->pktLocRAM, EDMAPKT_RX_PKT_SIZE);\r
+}\r
+\r
+/* Timer interupt - triggers all DMAs. If this moves to devices where\r
+ * EDMA can be triggered by a timer directly it would replace a lot of this */\r
+void timerIsr()\r
+{\r
+ /* Disable the Timer interrupts */\r
+ TIMERIntDisable(SOC_TIMER9_BASE, TIMER_INT_OVF_EN_FLAG);\r
+\r
+ /* Clear the status of the interrupt flags */\r
+ TIMERIntStatusClear(SOC_TIMER9_BASE, TIMER_INT_OVF_IT_FLAG);\r
+\r
+ ticks++;\r
+ sendphase++;\r
+\r
+ if (sendphase < 32) {\r
+ /* TX active, RX active */\r
+ /* fire RX */\r
+ if (triggered)\r
+ {\r
+ if (enableESR & EDMAPKT_ENABLEESR_RX_P1) {\r
+ /* Fire edma */\r
+ EDMA3SetEvt (EDMAPKT_BASE, EDMAPKT_FIRST_REAL_CH_RX_P1 + 0);\r
+ enableESR &= ~EDMAPKT_ENABLEESR_RX_P1;\r
+ triggerRxTickP1 = ticks;\r
+ }\r
+ else\r
+ {\r
+ if ((finishedESR & EDMAPKT_ENABLEESR_RX_P1) == 0) {\r
+ lateRX++;\r
+ }\r
+ }\r
+ if (enableESR & EDMAPKT_ENABLEESR_RX_P2) {\r
+ /* Fire edma */\r
+ EDMA3SetEvt (EDMAPKT_BASE, EDMAPKT_FIRST_REAL_CH_RX_P2 + 0);\r
+ enableESR &= ~EDMAPKT_ENABLEESR_RX_P2;\r
+ triggerRxTickP2 = ticks;\r
+ }\r
+ else\r
+ {\r
+ if ((finishedESR & EDMAPKT_ENABLEESR_RX_P2) == 0) {\r
+ lateRX++;\r
+ }\r
+ }\r
+ }\r
+ } else if (sendphase < 37) {\r
+ /* Idle */\r
+ if (triggered)\r
+ {\r
+ triggered = 0;\r
+ if (((finishedESR | enableESR) & (EDMAPKT_ENABLEESR_TX_P1 | EDMAPKT_ENABLEESR_TX_P2)) == 0)\r
+ {\r
+ lateTX++;\r
+ }\r
+ }\r
+ } else {\r
+ sendphase = 0;\r
+ /* Fire TX and RX */\r
+ if (enableESR & EDMAPKT_ENABLEESR_TX_P1) {\r
+ /* Fire channel 0 */\r
+ EDMA3SetEvt (EDMAPKT_BASE, EDMAPKT_FIRST_REAL_CH_TX_P1 + 0);\r
+ enableESR &= ~EDMAPKT_ENABLEESR_TX_P1;\r
+ triggerTxTickP1 = ticks;\r
+ triggered = 1;\r
+ }\r
+ if (enableESR & EDMAPKT_ENABLEESR_TX_P2) {\r
+ /* Fire channel 0 */\r
+ EDMA3SetEvt (EDMAPKT_BASE, EDMAPKT_FIRST_REAL_CH_TX_P2 + 0);\r
+ enableESR &= ~EDMAPKT_ENABLEESR_TX_P2;\r
+ triggerTxTickP2 = ticks;\r
+ triggered = 1;\r
+ }\r
+ if (enableESR & EDMAPKT_ENABLEESR_RX_P1) {\r
+ /* Fire channel 0 */\r
+ EDMA3SetEvt (EDMAPKT_BASE, EDMAPKT_FIRST_REAL_CH_RX_P1 + 0);\r
+ enableESR &= ~EDMAPKT_ENABLEESR_RX_P1;\r
+ triggerRxTickP1 = ticks;\r
+ triggered = 1;\r
+ }\r
+ if (enableESR & EDMAPKT_ENABLEESR_RX_P2) {\r
+ /* Fire channel 0 */\r
+ EDMA3SetEvt (EDMAPKT_BASE, EDMAPKT_FIRST_REAL_CH_RX_P2 + 0);\r
+ enableESR &= ~EDMAPKT_ENABLEESR_RX_P2;\r
+ triggerRxTickP2 = ticks;\r
+ triggered = 1;\r
+ }\r
+ }\r
+\r
+ /* Enable the Timer interrupts */\r
+ TIMERIntEnable(SOC_TIMER9_BASE, TIMER_INT_OVF_EN_FLAG);\r
+}\r
+\r
+/* Setup/enable timer interrupt */\r
+void setupTimer()\r
+{\r
+ HwiP_Params hwiInputParams;\r
+ HwiP_Fxn hwiFxn;\r
+ uint32_t vector = EDMAPKT_TIMER_VECTOR;\r
+ uint32_t cpuEvent = vector - 37;\r
+ uint32_t xbarIndex = vector - 37;\r
+\r
+ /* Enable timer 9 power/clock */\r
+ HW_WR_REG32(SOC_L4PER_CM_CORE_BASE + CM_L4PER_TIMER9_CLKCTRL, 0x2);\r
+\r
+ while ((HW_RD_REG32(SOC_L4PER_CM_CORE_BASE +\r
+ CM_L4PER_TIMER9_CLKCTRL) & (0x00030000)) != 0x0) ;\r
+ \r
+ /*Reset the timer module */\r
+ TIMERReset(SOC_TIMER9_BASE);\r
+\r
+ /* Disable free run in emulation mode */\r
+ TIMEREmuModeConfigure(SOC_TIMER9_BASE, TIMER_FROZEN);\r
+\r
+ /* Load the counter with the initial count value */\r
+ TIMERCounterSet(SOC_TIMER9_BASE, EDMAPKT_TIMER_INITIAL_COUNT);\r
+\r
+ /* Load the load register with the reload count value */\r
+ TIMERReloadSet(SOC_TIMER9_BASE, EDMAPKT_TIMER_RLD_COUNT);\r
+\r
+ /* Configure the Timer for Auto-reload and compare mode */\r
+ TIMERModeConfigure(SOC_TIMER9_BASE, TIMER_AUTORLD_NOCMP_ENABLE);\r
+\r
+ /* Configure the posted mode of TIMER */\r
+ TIMERPostedModeConfig(SOC_TIMER9_BASE, TIMER_NONPOSTED);\r
+\r
+ /* Configure the read mode of TIMER */\r
+ TIMERReadModeConfig(SOC_TIMER9_BASE, TIMER_READ_MODE_NONPOSTED);\r
+\r
+ /* setup interrupt */\r
+ CSL_xbarIrqConfigure(CSL_XBAR_IRQ_CPU_ID_MPU, xbarIndex, CSL_XBAR_TIMER9_IRQ);\r
+\r
+ hwiFxn = (HwiP_Fxn)timerIsr;\r
+ hwiInputParams.arg = (uintptr_t)NULL;\r
+\r
+ /* Setup Hardware Interrupt Controller */\r
+ hwiInputParams.name = NULL;\r
+ hwiInputParams.priority = 0;\r
+ hwiInputParams.evtId = cpuEvent; /* Event ID not used in GIC */\r
+ hwiInputParams.triggerSensitivity = 0x3; /* interrupt edge triggered */\r
+ timerIsrHnd = HwiP_create(vector, hwiFxn, &hwiInputParams);\r
+\r
+ if (timerIsrHnd == NULL)\r
+ {\r
+ PCIE_logPrintf ("FAIL: Failed to install timer isr\n");\r
+ }\r
+ else \r
+ {\r
+ /* Enable the Timer9 interrupts */\r
+ TIMERIntEnable(SOC_TIMER9_BASE, TIMER_INT_OVF_EN_FLAG);\r
+\r
+ /* Start the Timer */\r
+ TIMEREnable(SOC_TIMER9_BASE);\r
+ }\r
+}\r
+\r
+/* Cleanup/remove timer interrupt */\r
+void removeTimerIsr (void)\r
+{\r
+ /* Disable the Timer9 interrupts */\r
+ TIMERIntDisable(SOC_TIMER9_BASE, TIMER_INT_OVF_EN_FLAG);\r
+\r
+ /* Stop the Timer */\r
+ TIMERDisable(SOC_TIMER9_BASE);\r
+\r
+ HwiP_delete (timerIsrHnd);\r
+}\r
+\r
+/* Helper to discover if channel is pending interrupt */\r
+uint32_t edmaChIPRBit (uint32_t chnum, uint32_t IPR, uint32_t IPRH)\r
+{\r
+ uint32_t result;\r
+ if (chnum < 32)\r
+ {\r
+ result = (IPR >> chnum) & 1U;\r
+ }\r
+ else \r
+ {\r
+ result = (IPRH >> (32U - chnum)) & 1U;\r
+ }\r
+\r
+ return result;\r
+}\r
+\r
+/* Generate log entry */\r
+void edmaPktLogTime (uint32_t timeInTicks, int32_t *logIdxP1, uint32_t *timeBuffer, int32_t maxIdx)\r
+{\r
+ if (*logIdxP1 < maxIdx) {\r
+ timeBuffer[*logIdxP1] = timeInTicks;\r
+ (*logIdxP1)++;\r
+ } \r
+}\r
+\r
+/* EDMA interrupt occurs when a chain of packets completes. Discovers if it was\r
+ * late, records log buffer of timestamps, and requests timer to retrigger.\r
+ * Timer doesn't self retrigger to avoid problems when DMA is late (missed\r
+ * dma events)\r
+ */\r
+void edmaIsr (void)\r
+{\r
+ uint32_t now = TIMERCounterGet (SOC_TIMER9_BASE);\r
+ uint32_t IPR;\r
+ uint32_t IPRH;\r
+ uint32_t timeInTicks;\r
+ uint32_t deltaTicks;\r
+\r
+ timeInTicks = (now - EDMAPKT_TIMER_RLD_COUNT);\r
+\r
+ IPR = EDMA3GetIntrStatus(EDMAPKT_BASE);\r
+ IPRH = EDMA3IntrStatusHighGet(EDMAPKT_BASE);\r
+\r
+ /* Generate log for each finished tx/rx port model, and retrigger if required */\r
+ if (edmaChIPRBit (EDMAPKT_INTERRUPT_CH_TX_P1, IPR, IPRH))\r
+ {\r
+ /* TX for Port 1 model finished */\r
+ deltaTicks = timeInTicks + (ticks - triggerTxTickP1) * EDMAPKT_TIMER_TICK_CLOCKS;\r
+ edmaPktLogTime (deltaTicks, &txLogIdxP1, &txTime20MHzP1[0], sizeof(txTime20MHzP1)/sizeof(txTime20MHzP1[0]));\r
+ txCyclesP1++;\r
+ if (txCyclesP1 < EDMAPKT_NUM_CYCLES) {\r
+ enableESR |= EDMAPKT_ENABLEESR_TX_P1;\r
+ } else {\r
+ finishedESR |= EDMAPKT_ENABLEESR_TX_P1;\r
+ }\r
+\r
+ EDMA3ClrIntr (EDMAPKT_BASE, EDMAPKT_INTERRUPT_CH_TX_P1);\r
+ }\r
+\r
+ if (edmaChIPRBit (EDMAPKT_INTERRUPT_CH_TX_P2, IPR, IPRH))\r
+ {\r
+ /* TX for Port 2 model finished */\r
+ deltaTicks = timeInTicks + (ticks - triggerTxTickP2) * EDMAPKT_TIMER_TICK_CLOCKS;\r
+ edmaPktLogTime (deltaTicks, &txLogIdxP2, &txTime20MHzP2[0], sizeof(txTime20MHzP2)/sizeof(txTime20MHzP2[0]));\r
+ txCyclesP2++;\r
+ if (txCyclesP2 < EDMAPKT_NUM_CYCLES) {\r
+ enableESR |= EDMAPKT_ENABLEESR_TX_P2;\r
+ } else {\r
+ finishedESR |= EDMAPKT_ENABLEESR_TX_P2;\r
+ }\r
+ EDMA3ClrIntr (EDMAPKT_BASE, EDMAPKT_INTERRUPT_CH_TX_P2);\r
+ }\r
+\r
+ if (edmaChIPRBit (EDMAPKT_INTERRUPT_CH_RX_P1, IPR, IPRH))\r
+ {\r
+ /* RX for Port 1 model finished */\r
+ deltaTicks = timeInTicks + (ticks - triggerRxTickP1) * EDMAPKT_TIMER_TICK_CLOCKS;\r
+ edmaPktLogTime (deltaTicks, &rxLogIdxP1, &rxTime20MHzP1[0], sizeof(rxTime20MHzP1)/sizeof(rxTime20MHzP1[0]));\r
+ rxPktsP1++;\r
+ if (rxPktsP1 < EDMAPKT_NUM_RX_TXNS) {\r
+ enableESR |= EDMAPKT_ENABLEESR_RX_P1;\r
+ } else {\r
+ finishedESR |= EDMAPKT_ENABLEESR_RX_P1;\r
+ }\r
+ EDMA3ClrIntr (EDMAPKT_BASE, EDMAPKT_INTERRUPT_CH_RX_P1);\r
+ }\r
+\r
+ if (edmaChIPRBit (EDMAPKT_INTERRUPT_CH_RX_P2, IPR, IPRH))\r
+ {\r
+ /* RX for Port 2 model finished */\r
+ deltaTicks = timeInTicks + (ticks - triggerRxTickP2) * EDMAPKT_TIMER_TICK_CLOCKS;\r
+ edmaPktLogTime (deltaTicks, &rxLogIdxP2, &rxTime20MHzP2[0], sizeof(rxTime20MHzP2)/sizeof(rxTime20MHzP2[0]));\r
+ rxPktsP2++;\r
+ if (rxPktsP2 < EDMAPKT_NUM_RX_TXNS) {\r
+ enableESR |= EDMAPKT_ENABLEESR_RX_P2;\r
+ } else {\r
+ finishedESR |= EDMAPKT_ENABLEESR_RX_P2;\r
+ }\r
+ EDMA3ClrIntr (EDMAPKT_BASE, EDMAPKT_INTERRUPT_CH_RX_P2);\r
+ }\r
+}\r
+\r
+/* Install DMA done ISR */\r
+void setupDmaIsr (void)\r
+{\r
+ HwiP_Params hwiInputParams;\r
+ HwiP_Fxn hwiFxn;\r
+ uint32_t vector = EDMAPKT_EDMA_VECTOR;\r
+ uint32_t cpuEvent = vector - 37;\r
+ uint32_t xbarIndex = vector - 37;\r
+\r
+ /* setup interrupt */\r
+ CSL_xbarIrqConfigure(CSL_XBAR_IRQ_CPU_ID_MPU, xbarIndex, CSL_XBAR_EDMA_TPCC_IRQ_REGION0);\r
+\r
+ hwiFxn = (HwiP_Fxn)edmaIsr;\r
+ hwiInputParams.arg = (uintptr_t)NULL;\r
+\r
+ /* Setup Hardware Interrupt Controller */\r
+ hwiInputParams.name = NULL;\r
+ hwiInputParams.priority = 0;\r
+ hwiInputParams.evtId = cpuEvent; /* Event ID not used in GIC */\r
+ hwiInputParams.triggerSensitivity = 0x3; /* interrupt edge triggered */\r
+ edmaIsrHnd = HwiP_create(vector, hwiFxn, &hwiInputParams);\r
+\r
+ if (edmaIsrHnd == NULL)\r
+ {\r
+ PCIE_logPrintf ("FAIL: Failed to install edma isr\n");\r
}\r
+\r
+ /* Enable interrupts */\r
+ EDMA3EnableEvtIntr (EDMAPKT_BASE, EDMAPKT_INTERRUPT_CH_TX_P1);\r
+ EDMA3EnableEvtIntr (EDMAPKT_BASE, EDMAPKT_INTERRUPT_CH_TX_P2);\r
+ EDMA3EnableEvtIntr (EDMAPKT_BASE, EDMAPKT_INTERRUPT_CH_RX_P1);\r
+ EDMA3EnableEvtIntr (EDMAPKT_BASE, EDMAPKT_INTERRUPT_CH_RX_P2);\r
+}\r
+\r
+/* Cleanup/remove DMA done ISR */\r
+void removeDmaIsr (void)\r
+{\r
+ EDMA3DisableEvtIntr (EDMAPKT_BASE, EDMAPKT_INTERRUPT_CH_TX_P1);\r
+ EDMA3DisableEvtIntr (EDMAPKT_BASE, EDMAPKT_INTERRUPT_CH_TX_P2);\r
+ EDMA3DisableEvtIntr (EDMAPKT_BASE, EDMAPKT_INTERRUPT_CH_RX_P1);\r
+ EDMA3DisableEvtIntr (EDMAPKT_BASE, EDMAPKT_INTERRUPT_CH_RX_P2);\r
+\r
+ HwiP_delete (edmaIsrHnd);\r
+}\r
+\r
+\r
+/* Set up DMA channels to map to tcc/evtq/starting param */\r
+void initChParms (uint32_t realParamNum, EDMA3CCPaRAMEntry *firstRamParam,\r
+ uint32_t realChNum, uint32_t tccNum, uint32_t evtqNum)\r
+{\r
+ uint32_t chnum;\r
+\r
+ /* Prime pump so param used by channel 0 is really in PaRAM */\r
+ EDMA3SetPaRAM (EDMAPKT_BASE, realParamNum, firstRamParam);\r
+ /* Use channel 0 as main trigger to load RAM to PaRAM */\r
+ EDMA3ChannelToParamMap (EDMAPKT_BASE, realChNum + 0, realParamNum + 0);\r
+ /* Channel 1 loads the addresses into PaRAM */\r
+ EDMA3ChannelToParamMap (EDMAPKT_BASE, realChNum + 1, realParamNum + 1);\r
+ /* Channel 2 does the copy then transfers next RAM to PaRAM */\r
+ EDMA3ChannelToParamMap (EDMAPKT_BASE, realChNum + 2, realParamNum + 3);\r
+ /* Channel 3 does the RAM to PaRAM for next packet */\r
+ EDMA3ChannelToParamMap (EDMAPKT_BASE, realChNum + 3, realParamNum + 4);\r
+\r
+ for (chnum = realChNum; chnum < (realChNum + 4); chnum++)\r
+ {\r
+ /* Clear old events */\r
+ EDMA3ClrEvt (EDMAPKT_BASE, chnum);\r
+\r
+ /* Disconnect system event so hw doesn't cause emda to misfire */\r
+ /* 1 is unused DMA source */\r
+ CSL_xbarDmaConfigure (CSL_XBAR_DMA_CPU_ID_EDMA, 1, chnum + CSL_XBAR_INST_DMA_EDMA_DREQ_0);\r
+ \r
+ /* Setup channel */\r
+ EDMA3RequestChannel(EDMAPKT_BASE, EDMA3_CHANNEL_TYPE_DMA, chnum, tccNum,\r
+ evtqNum);\r
+ }\r
+\r
+ /* Clear the pending bit */\r
+ EDMA3ClrIntr (EDMAPKT_BASE, (realChNum + 2));\r
+}\r
+\r
+/* Printf results in microseconds (us) */\r
+void reportStats (uint32_t *buf, int32_t nElem, const char *msg)\r
+{\r
+ uint32_t minTime, maxTime;\r
+ uint64_t sumTime;\r
+ int32_t i;\r
+ float minTimeUS, maxTimeUS, avgTimeUS;\r
+ char printline[80];\r
+\r
+ sumTime = minTime = maxTime = buf[0];\r
+\r
+ for (i = 1; i < nElem; i++)\r
+ {\r
+ sumTime += buf[i];\r
+ if (minTime > buf[i])\r
+ {\r
+ minTime = buf[i];\r
+ }\r
+ if (maxTime < buf[i])\r
+ {\r
+ maxTime = buf[i];\r
+ }\r
+ }\r
+ minTimeUS = (1.0 * minTime) / 20; /* 20mhz */\r
+ maxTimeUS = (1.0 * maxTime) / 20; /* 20mhz */\r
+ avgTimeUS = (1.0 * sumTime) / nElem / 20; /* 20mhz */\r
+\r
+ snprintf (printline, sizeof(printline), \r
+ "For %s: min/max/avg us = %5.2f/%5.2f/%5.2f\n", \r
+ msg, minTimeUS, maxTimeUS, avgTimeUS);\r
+ PCIE_logPrintf (printline);\r
+}\r
+\r
+/* Burn one interrupt before starting test, to make sure other side is ready */\r
+void msiSync (volatile uint32_t *localMsi)\r
+{\r
+ edmaPktBenchWaitMsi (&ticks, 0xffffffffu);\r
+\r
+ /* Send interrupt to RC using CSL to minimize latency */\r
+ edmaPktBenchSendMsi ();\r
+\r
+ do {\r
+ /* Cache invalidate the receive buffer */\r
+ CacheP_Inv ((void *)localMsi, sizeof(*localMsi));\r
+ } while (*localMsi != 1);\r
+}\r
+\r
+/* Transmits MSI while timer drives EDMA */\r
+uint32_t msiTxBench (volatile uint32_t *localMsi, volatile uint32_t *remoteMsi, uint32_t requestedESR)\r
+{\r
+ uint32_t msiTimeout = 0, waitMsiTimeout = 0;\r
+ uint32_t msiMin, msiMax;\r
+ uint64_t msiSum;\r
+ int32_t msiNum = 0;\r
+ uint32_t expectedMsiTrackVal = 2; /* 1 used by sync */\r
+ char printline[80];\r
+\r
+ while (finishedESR != requestedESR)\r
+ {\r
+ uint32_t startMsiTicks = ticks;\r
+ uint32_t startMsiTime;\r
+\r
+ if (edmaPktBenchWaitMsi (&ticks, 10u))\r
+ {\r
+ waitMsiTimeout++; /* Previous MSI timed out */\r
+ }\r
+\r
+ /* Align with tick to maximize delay */\r
+ while (startMsiTicks == ticks);\r
+ startMsiTicks = ticks;\r
+ startMsiTime = TIMERCounterGet (SOC_TIMER9_BASE) - EDMAPKT_TIMER_RLD_COUNT;\r
+\r
+ /* Send interrupt to RC using CSL to minimize latency */\r
+ edmaPktBenchSendMsi ();\r
+\r
+ do {\r
+ /* Cache invalidate the receive buffer */\r
+ CacheP_Inv ((void *)localMsi, sizeof(*localMsi));\r
+ } while ((*localMsi != expectedMsiTrackVal) && ((ticks - startMsiTicks) < 1000));\r
+\r
+ if ((ticks - startMsiTicks) >= 1000)\r
+ {\r
+ msiTimeout++;\r
+ }\r
+ else\r
+ {\r
+ uint32_t stopMsiTicks = ticks;\r
+ uint32_t stopMsiTime = TIMERCounterGet (SOC_TIMER9_BASE) - EDMAPKT_TIMER_RLD_COUNT;\r
+ uint32_t time20Mhz;\r
+\r
+ expectedMsiTrackVal++;\r
+\r
+ if (stopMsiTicks != ticks)\r
+ {\r
+ stopMsiTicks = ticks;\r
+ stopMsiTime = TIMERCounterGet (SOC_TIMER9_BASE);\r
+ }\r
+\r
+ msiNum++;\r
+\r
+ time20Mhz = ((EDMAPKT_TIMER_TICK_CLOCKS * stopMsiTicks) + stopMsiTime) - \r
+ ((EDMAPKT_TIMER_TICK_CLOCKS * startMsiTicks) + startMsiTime);\r
+\r
+ if (msiNum == 1)\r
+ {\r
+ msiSum = msiMin = msiMax = time20Mhz;\r
+ }\r
+ else\r
+ {\r
+ if (msiMin > time20Mhz) {\r
+ msiMin = time20Mhz;\r
+ }\r
+ if (msiMax < time20Mhz) {\r
+ msiMax = time20Mhz;\r
+ }\r
+ msiSum += time20Mhz;\r
+ }\r
+ }\r
+ }\r
+\r
+ /* Tell other side test is done */\r
+ *remoteMsi = 1;\r
+\r
+ if (! msiTimeout)\r
+ {\r
+ float msiMinUS = (1.0 * msiMin) / 20;\r
+ float msiMaxUS = (1.0 * msiMax) / 20;\r
+ float msiAvgUS = (1.0 * msiSum / msiNum) / 20;\r
+ snprintf (printline, sizeof(printline), \r
+ "For %d MSIs: ROUND TRIP min/max/avg us = %5.2f/%5.2f/%5.2f\n", \r
+ (int)msiNum, msiMinUS, msiMaxUS, msiAvgUS);\r
+ PCIE_logPrintf (printline);\r
+ } \r
+ else\r
+ {\r
+ PCIE_logPrintf ("FAIL: %d MSI timed out (%d sent)\n", (int)msiTimeout, (int)msiNum);\r
+ }\r
+ \r
+ return msiTimeout;\r
+}\r
+\r
+/* Receives MSI */\r
+void msiRxBench (volatile uint32_t *localMsi, volatile uint32_t *remoteMsi, SemaphoreP_Handle *sem)\r
+{\r
+ uint32_t msiNum = 1;\r
+ do {\r
+ /* Wait for an interrupt */\r
+ if (SemaphoreP_TIMEOUT != SemaphoreP_pend (sem, 10000))\r
+ {\r
+ /* Not a timeout - real interrupt */\r
+ /* Tell other side got the interrupt */\r
+ *remoteMsi = msiNum;\r
+ msiNum++;\r
+ }\r
+ \r
+ /* Cache invalidate the receive buffer to check if we should exit */\r
+ CacheP_Inv ((void *)localMsi, sizeof(*localMsi));\r
+ } while (*localMsi == 0);\r
}\r
\r
/*\r
* After end of each realtime interval, send one MSI to RC.\r
*/\r
\r
-int32_t PcieEdmaPktBench (edmaPktBenchBuf_t *buf, pcieMode_e mode)\r
+int32_t PcieEdmaPktBench (volatile uint32_t *localMsi, edmaPktBenchBuf_t *buf, \r
+ pcieMode_e mode, SemaphoreP_Handle *msiSem)\r
{\r
- setupTxDMA(buf);\r
- setupRxDMA();\r
+ txEdmaSetup_t txSetup;\r
+ rxEdmaSetup_t rxSetup;\r
+ uint32_t region = 0;\r
+ uint32_t requestedESR;\r
+ int32_t p1Errors, p2Errors;\r
+ int32_t pkt;\r
+ int32_t retVal = 0;\r
\r
- /* Setup DMA */\r
- EDMA3Init (EDMAPKT_BASE, 0);\r
+ /* Let previous printf() settle */\r
+ Task_sleep(1000);\r
\r
- /* Prime pump so param used by channel 0 is really in PaRAM */\r
- EDMA3SetPaRAM (EDMAPKT_BASE, EDMAPKT_FIRST_REAL_PARAM, (EDMA3CCPaRAMEntry *)&txRAMParams[0]);\r
- /* Use channel 0 as main trigger to load RAM to PaRAM */\r
- EDMA3ChannelToParamMap (EDMAPKT_BASE, 0, EDMAPKT_FIRST_REAL_PARAM + 1);\r
- /* Channel 1 loads the addresses into PaRAM */\r
- EDMA3ChannelToParamMap (EDMAPKT_BASE, 1, EDMAPKT_FIRST_REAL_PARAM + 1);\r
- /* Channel 2 does the copy then transfers next RAM to PaRAM */\r
- EDMA3ChannelToParamMap (EDMAPKT_BASE, 2, EDMAPKT_FIRST_REAL_PARAM + 3);\r
+ if (mode == pcie_EP_MODE)\r
+ {\r
+ txSetup.RAMParams = &txRAMParamsP1;\r
+ txSetup.destDesc = &txDestDescP1;\r
+ txSetup.pktLocRAM = &txPktLocRAMP1;\r
+ txSetup.realCh = EDMAPKT_FIRST_REAL_CH_TX_P1;\r
+ txSetup.realParam = EDMAPKT_FIRST_REAL_PARAM_TX_P1;\r
+ setupTxDMA(&buf->tx[0], &txSetup);\r
\r
- /* Clear old events */\r
- EDMA3ClrEvt (EDMAPKT_BASE, 0);\r
- EDMA3ClrEvt (EDMAPKT_BASE, 1);\r
- EDMA3ClrEvt (EDMAPKT_BASE, 2);\r
+ txSetup.RAMParams = &txRAMParamsP2;\r
+ txSetup.destDesc = &txDestDescP2;\r
+ txSetup.pktLocRAM = &txPktLocRAMP2;\r
+ txSetup.realCh = EDMAPKT_FIRST_REAL_CH_TX_P2;\r
+ txSetup.realParam = EDMAPKT_FIRST_REAL_PARAM_TX_P2;\r
+ setupTxDMA(&buf->tx[1], &txSetup);\r
+\r
+ rxSetup.RAMParams = &rxRAMParamsP1;\r
+ rxSetup.destDesc = &rxDestDescP1;\r
+ rxSetup.srcDesc = &rxSrcDescP1;\r
+ rxSetup.pktLocRAM = &rxPktLocRAMP1;\r
+ rxSetup.realCh = EDMAPKT_FIRST_REAL_CH_RX_P1;\r
+ rxSetup.realParam = EDMAPKT_FIRST_REAL_PARAM_RX_P1;\r
+ setupRxDMA(&buf->rx[0], &rxSetup);\r
\r
- /* Enable events/channels */\r
- EDMA3EnableDmaEvt (EDMAPKT_BASE, 0);\r
- EDMA3EnableDmaEvt (EDMAPKT_BASE, 1);\r
- EDMA3EnableDmaEvt (EDMAPKT_BASE, 2);\r
+ rxSetup.RAMParams = &rxRAMParamsP2;\r
+ rxSetup.destDesc = &rxDestDescP2;\r
+ rxSetup.srcDesc = &rxSrcDescP2;\r
+ rxSetup.pktLocRAM = &rxPktLocRAMP2;\r
+ rxSetup.realCh = EDMAPKT_FIRST_REAL_CH_RX_P2;\r
+ rxSetup.realParam = EDMAPKT_FIRST_REAL_PARAM_RX_P2;\r
+ setupRxDMA(&buf->rx[1], &rxSetup);\r
+\r
+ /* Setup DMA */\r
+ EDMAsetRegion(region);\r
+ EDMA3Init (EDMAPKT_BASE, 0);\r
+\r
+ initChParms (EDMAPKT_FIRST_REAL_PARAM_TX_P1, (EDMA3CCPaRAMEntry *)&txRAMParamsP1[0], EDMAPKT_FIRST_REAL_CH_TX_P1, 0, 0);\r
+ initChParms (EDMAPKT_FIRST_REAL_PARAM_TX_P2, (EDMA3CCPaRAMEntry *)&txRAMParamsP2[0], EDMAPKT_FIRST_REAL_CH_TX_P2, 0, 0);\r
+ initChParms (EDMAPKT_FIRST_REAL_PARAM_RX_P1, (EDMA3CCPaRAMEntry *)&rxRAMParamsP1[0], EDMAPKT_FIRST_REAL_CH_RX_P1, 1, 1);\r
+ initChParms (EDMAPKT_FIRST_REAL_PARAM_RX_P2, (EDMA3CCPaRAMEntry *)&rxRAMParamsP2[0], EDMAPKT_FIRST_REAL_CH_RX_P2, 1, 1);\r
+\r
+ /* Set up interupt for dma done */\r
+ setupDmaIsr();\r
+ /* Timer actually fires the DMA!! */\r
+ setupTimer();\r
+\r
+ /* Exchange 1 MSI to sync other side */\r
+ msiSync (localMsi);\r
\r
- /* Fire channel 0 */\r
- EDMA3SetEvt (EDMAPKT_BASE, 0);\r
+ /* Start cycle for both ports */\r
+ requestedESR = (EDMAPKT_ENABLEESR_TX_P1 | EDMAPKT_ENABLEESR_TX_P2 |\r
+ EDMAPKT_ENABLEESR_RX_P1 | EDMAPKT_ENABLEESR_RX_P2);\r
+ enableESR = requestedESR;\r
+\r
+ /* Wait for EDMA to complete, while running MSI latency benchmark */\r
+ if (msiTxBench(localMsi, &buf->msiTracker[0], requestedESR) > 0)\r
+ {\r
+ retVal = 1; /* msi test failed */\r
+ }\r
+\r
+ /* Cache invalidate the receive buffer */\r
+ CacheP_Inv ((void *)&txPktLocRAMP1[0], sizeof(txPktLocRAMP1));\r
+ CacheP_Inv ((void *)&txPktLocRAMP2[0], sizeof(txPktLocRAMP2));\r
+\r
+ /* Verify that all the packets were dma'd */\r
+ p1Errors = 0;\r
+ p2Errors = 0;\r
+\r
+ for (pkt = 0; pkt < EDMAPKT_NUM_TX_PKTS; pkt++)\r
+ {\r
+ if (txPktLocRAMP1[pkt*EDMAPKT_TX_PKT_SIZE] != ((char)pkt + 1))\r
+ {\r
+ p1Errors++;\r
+ }\r
+ if (txPktLocRAMP2[pkt*EDMAPKT_TX_PKT_SIZE] != ((char)pkt + 1))\r
+ {\r
+ p2Errors++;\r
+ }\r
+ }\r
+\r
+ if (buf->rx[0].buf[0] != ((char)1))\r
+ {\r
+ p1Errors++;\r
+ }\r
+\r
+ if (buf->rx[1].buf[0] != ((char)1))\r
+ {\r
+ p2Errors++;\r
+ }\r
+ \r
+ if ((p1Errors != 0) || (p2Errors != 0))\r
+ {\r
+ PCIE_logPrintf ("FAIL: Discovered %d port1 and %d port2 errors\n", p1Errors, p2Errors);\r
+ retVal = 1;\r
+ }\r
+\r
+ if ((lateTX != 0) || (lateRX != 0))\r
+ {\r
+ PCIE_logPrintf ("WARN: %d late transmits and %d late receives\n", lateTX, lateRX);\r
+ }\r
+\r
+ reportStats (txTime20MHzP1, txLogIdxP1, "TX 32 pkts port 1");\r
+ reportStats (txTime20MHzP2, txLogIdxP1, "TX 32 pkts port 2");\r
+ reportStats (rxTime20MHzP1, txLogIdxP1, "RX 1 pkt port 1");\r
+ reportStats (rxTime20MHzP2, txLogIdxP1, "RX 1 pkt port 2");\r
+\r
+ /* Cleanup */\r
+ removeTimerIsr();\r
+ removeDmaIsr();\r
+ EDMA3Deinit(EDMAPKT_BASE, 0);\r
+ }\r
+ else\r
+ {\r
+ if (msiSem != NULL)\r
+ {\r
+ /* Process MSIs */\r
+ msiRxBench(localMsi, &buf->msiTracker[0], msiSem);\r
+ }\r
+ else\r
+ {\r
+ PCIE_logPrintf ("FAIL: Missing semaphore on RC\n");\r
+ retVal = 1;\r
+ }\r
+ }\r
\r
- return 0;\r
+ return retVal;\r
} /* PcieEdmaPktBench */\r
\r
/* Nothing past this point */\r
index 1abe2824ca3071e35d4056719edddf3f9e0a3ed1..f7b37db63cf7da24c0a03c216a0b526f3e08772a 100644 (file)
#ifndef PCIEEDMAPKTBENCH_H_\r
#define PCIEEDMAPKTBENCH_H_\r
\r
+#include <ti/osal/SemaphoreP.h>\r
\r
#define EDMAPKT_NUM_TX_PKTS (32)\r
+#define EDMAPKT_NUM_TX_PKTS_PER_LINKAGE (1)\r
#define EDMAPKT_NUM_TX_PARAMS_PER_PKT (3)\r
#define EDMAPKT_NUM_TX_PARAMS_LINKAGE (1)\r
-#define EDMAPKT_NUM_TX_PARAMS ((EDMAPKT_NUM_TX_PARAMS_LINKAGE+EDMAPKT_NUM_TX_PARAMS_PER_PKT)*EDMAPKT_NUM_TX_PKTS)\r
+#define EDMAPKT_NUM_TX_PARAMS_TOT_LINKAGE ((EDMAPKT_NUM_TX_PKTS + EDMAPKT_NUM_TX_PARAMS_LINKAGE - 1) / \\r
+ (EDMAPKT_NUM_TX_PKTS_PER_LINKAGE))\r
+#define EDMAPKT_NUM_TX_PARAMS_TOT_PKTS (EDMAPKT_NUM_TX_PKTS * EDMAPKT_NUM_TX_PARAMS_PER_PKT)\r
+#define EDMAPKT_NUM_TX_PARAMS (EDMAPKT_NUM_TX_PARAMS_TOT_PKTS + EDMAPKT_NUM_TX_PARAMS_TOT_LINKAGE)\r
+#define EDMAPKT_NUM_TX_PARAMS_PER_LINKAGE ((EDMAPKT_NUM_TX_PKTS_PER_LINKAGE * EDMAPKT_NUM_TX_PARAMS_PER_PKT) + \\r
+ EDMAPKT_NUM_TX_PARAMS_LINKAGE)\r
#define EDMAPKT_TX_PKT_SIZE (64)\r
#define EDMAPKT_TX_PKT_RAM_SIZE (EDMAPKT_TX_PKT_SIZE * EDMAPKT_NUM_TX_PKTS)\r
\r
#define EDMAPKT_NUM_RX_PKTS (1)\r
-#define EDMAPKT_NUM_RX_PARAMS_PER_PKT (8)\r
-#define EDMAPKT_NUM_RX_PARAMS_LINKAGE (0)\r
-#define EDMAPKT_NUM_RX_PARAMS ((EDMAPKT_NUM_RX_PARAMS_LINKAGE+EDMAPKT_NUM_RX_PARAMS_PER_PKT)*EDMAPKT_NUM_RX_PKTS)\r
+#define EDMAPKT_NUM_RX_PKTS_PER_LINKAGE (1)\r
+#define EDMAPKT_NUM_RX_PARAMS_PER_PKT (3)\r
+#define EDMAPKT_NUM_RX_PARAMS_LINKAGE (1)\r
+#define EDMAPKT_NUM_RX_PARAMS_TOT_LINKAGE ((EDMAPKT_NUM_RX_PKTS + EDMAPKT_NUM_RX_PARAMS_LINKAGE - 1) / \\r
+ (EDMAPKT_NUM_RX_PKTS_PER_LINKAGE))\r
+#define EDMAPKT_NUM_RX_PARAMS_TOT_PKTS (EDMAPKT_NUM_RX_PKTS * EDMAPKT_NUM_RX_PARAMS_PER_PKT)\r
+#define EDMAPKT_NUM_RX_PARAMS (EDMAPKT_NUM_RX_PARAMS_TOT_PKTS + EDMAPKT_NUM_RX_PARAMS_TOT_LINKAGE)\r
+#define EDMAPKT_NUM_RX_PARAMS_PER_LINKAGE ((EDMAPKT_NUM_RX_PKTS_PER_LINKAGE * EDMAPKT_NUM_RX_PARAMS_PER_PKT) + \\r
+ EDMAPKT_NUM_RX_PARAMS_LINKAGE)\r
+#define EDMAPKT_RX_PKT_SIZE (64)\r
+#define EDMAPKT_RX_PKT_RAM_SIZE (EDMAPKT_RX_PKT_SIZE * EDMAPKT_NUM_RX_PKTS)\r
\r
-typedef struct edmaPktBenchBuf_s {\r
+\r
+#define EDMAPKT_NUM_PORTS 2\r
+\r
+typedef struct edmaPktBenchTxBuf_s {\r
char buf[EDMAPKT_TX_PKT_RAM_SIZE];\r
volatile void *txSrcDesc[EDMAPKT_NUM_TX_PKTS]; /* "Descriptor" holding real source address */\r
+} edmaPktBenchTxBuf_t;\r
+\r
+typedef struct edmaPktBenchRxBuf_s {\r
+ char buf[EDMAPKT_RX_PKT_RAM_SIZE];\r
+} edmaPktBenchRxBuf_t;\r
+\r
+typedef struct edmaPktBenchBuf_s {\r
+ volatile uint32_t msiTracker[16]; /* *16 for align and pad to cache line */\r
+ edmaPktBenchTxBuf_t tx[EDMAPKT_NUM_PORTS];\r
+ edmaPktBenchRxBuf_t rx[EDMAPKT_NUM_PORTS];\r
} edmaPktBenchBuf_t;\r
\r
-int32_t PcieEdmaPktBench (edmaPktBenchBuf_t *buf, pcieMode_e mode);\r
+int32_t PcieEdmaPktBench (volatile uint32_t *msi, edmaPktBenchBuf_t *buf, \r
+ pcieMode_e mode, SemaphoreP_Handle *msiSem);\r
\r
#endif /* PCIEEDMAPKTBENCH_H_ */\r
\r
diff --git a/example/edmaPktBench/edmaPktMsiBench.c b/example/edmaPktBench/edmaPktMsiBench.c
--- /dev/null
@@ -0,0 +1,66 @@
+/*\r
+ * Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/\r
+ *\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ *\r
+ * Redistributions of source code must retain the above copyright\r
+ * notice, this list of conditions and the following disclaimer.\r
+ *\r
+ * Redistributions in binary form must reproduce the above copyright\r
+ * notice, this list of conditions and the following disclaimer in the\r
+ * documentation and/or other materials provided with the\r
+ * distribution.\r
+ *\r
+ * Neither the name of Texas Instruments Incorporated nor the names of\r
+ * its contributors may be used to endorse or promote products derived\r
+ * from this software without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\r
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ */\r
+\r
+#include "edmaPktMsiBench.h"\r
+#include <ti/csl/soc.h>\r
+#include <ti/csl/hw_types.h>\r
+#include <ti/csl/csl_pcie.h>\r
+\r
+/* CSL-only implementation of send-msi to save latency */\r
+void edmaPktBenchSendMsi (void)\r
+{ \r
+ HW_WR_REG32(\r
+ CSL_MPU_PCIE_SS1_CONF_REGS_I_RC_CFG_DBICS_REGS + \r
+ PCIECTRL_TI_CONF_OFFSET + \r
+ PCIECTRL_TI_CONF_MSI_XMT, 1);\r
+}\r
+\r
+/* Wait for previous MSI to clear */\r
+int32_t edmaPktBenchWaitMsi (volatile uint32_t *ticks, uint32_t timeout)\r
+{\r
+ uint32_t start_ticks = *ticks;\r
+ int32_t retVal = 0;\r
+ /* Check previous MSI went away */\r
+ while (((HW_RD_REG32(\r
+ CSL_MPU_PCIE_SS1_CONF_REGS_I_RC_CFG_DBICS_REGS + \r
+ PCIECTRL_TI_CONF_OFFSET + \r
+ PCIECTRL_TI_CONF_MSI_XMT) & 1u) != 0u) &&\r
+ (((*ticks) - start_ticks) < timeout));\r
+ if (((*ticks) - start_ticks) >= timeout)\r
+ {\r
+ retVal = 1;\r
+ }\r
+\r
+ return retVal;\r
+}\r
diff --git a/example/edmaPktBench/edmaPktMsiBench.h b/example/edmaPktBench/edmaPktMsiBench.h
--- /dev/null
@@ -0,0 +1,47 @@
+/*\r
+ * Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/\r
+ *\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ *\r
+ * Redistributions of source code must retain the above copyright\r
+ * notice, this list of conditions and the following disclaimer.\r
+ *\r
+ * Redistributions in binary form must reproduce the above copyright\r
+ * notice, this list of conditions and the following disclaimer in the\r
+ * documentation and/or other materials provided with the\r
+ * distribution.\r
+ *\r
+ * Neither the name of Texas Instruments Incorporated nor the names of\r
+ * its contributors may be used to endorse or promote products derived\r
+ * from this software without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\r
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+*/\r
+\r
+#ifndef PCIEEDMAPKTMSIBENCH_H_\r
+#define PCIEEDMAPKTMSIBENCH_H_\r
+\r
+#include <stdint.h>\r
+\r
+/* CSL-only implementation of send-msi to save latency */\r
+void edmaPktBenchSendMsi (void);\r
+int32_t edmaPktBenchWaitMsi (volatile uint32_t *ticks, uint32_t timeout);\r
+\r
+#endif /* PCIEEDMAPKTMSIBENCH_H_ */\r
+\r
+/* Nothing past this point */\r
+\r
diff --git a/example/sample/am571x/armv7/bios/PCIE_idkAM571x_wSoCLib_armEdmaPktExampleProject.txt b/example/sample/am571x/armv7/bios/PCIE_idkAM571x_wSoCLib_armEdmaPktExampleProject.txt
index f26bdb7421c8e3e58204ea6bf26f8ae1f77d26b5..1a09b165e66cf8efd92cc3f4e0d611dafafa9c34 100644 (file)
-ccs.linkFile "PDK_INSTALL_PATH/ti/drv/pcie/example/sample/src/pcie_sample.c"
-ccs.linkFile "PDK_INSTALL_PATH/ti/drv/pcie/example/sample/am57x/src/pcie_sample_board.c"
--ccs.linkFile "PDK_INSTALL_PATH/ti/drv/pcie/example/sample/am571x/armv7/bios/pcie_sample_wSoCLib.cfg"
+-ccs.linkFile "PDK_INSTALL_PATH/ti/drv/pcie/example/sample/am571x/armv7/bios/pcie_edmapkt.cfg"
-ccs.linkFile "PDK_INSTALL_PATH/ti/drv/pcie/example/edmaPktBench/edmaPktBench.c"
+-ccs.linkFile "PDK_INSTALL_PATH/ti/drv/pcie/example/edmaPktBench/edmaPktMsiBench.c"
-ccs.setCompilerOptions "-c -mfloat-abi=hard -DPCIESS1_X2 -DSOC_AM571x -DIDK_AM571x -DEDMAPKTBENCH -g -gstrict-dwarf -gdwarf-3 -finstrument-functions -Wall -MMD -MP -I${PDK_INSTALL_PATH}/ti/drv/pcie/example/sample/src -I${PDK_INSTALL_PATH}/ti/drv/pcie/example/sample/am57x/src" -rtsc.enableRtsc
-ccs.setLinkerOptions " -lgcc -lm -lrdimon -nostartfiles -static -Wl,--gc-sections -L$(BIOS_INSTALL_PATH)/packages/gnu/targets/arm/libs/install-native/arm-none-eabi/lib/fpu"
diff --git a/example/sample/am571x/armv7/bios/pcie_edmapkt.cfg b/example/sample/am571x/armv7/bios/pcie_edmapkt.cfg
--- /dev/null
@@ -0,0 +1,241 @@
+/**
+ * \file pcie_sample_wSoCLib.cfg
+ *
+ * \brief Sysbios config file for pcie example project on AM571X IDK EVM.
+ *
+ */
+
+/*
+ * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/* ================ General configuration ================ */
+var Edma = xdc.loadPackage ("ti.sdo.edma3.drv.sample");
+var drv = xdc.loadPackage ("ti.sdo.edma3.drv");
+var rm = xdc.loadPackage ("ti.sdo.edma3.rm");
+var Defaults = xdc.useModule('xdc.runtime.Defaults');
+var Diags = xdc.useModule('xdc.runtime.Diags');
+var Error = xdc.useModule('xdc.runtime.Error');
+var Log = xdc.useModule('xdc.runtime.Log');
+var LoggerBuf = xdc.useModule('xdc.runtime.LoggerBuf');
+var Main = xdc.useModule('xdc.runtime.Main');
+var Memory = xdc.useModule('xdc.runtime.Memory')
+var SysMin = xdc.useModule('xdc.runtime.SysMin');
+var System = xdc.useModule('xdc.runtime.System');
+var Text = xdc.useModule('xdc.runtime.Text');
+var Clock = xdc.useModule('ti.sysbios.knl.Clock');
+var Swi = xdc.useModule('ti.sysbios.knl.Swi');
+var Semaphore = xdc.useModule('ti.sysbios.knl.Semaphore');
+var Hwi = xdc.useModule('ti.sysbios.hal.Hwi');
+var InitXbar = xdc.useModule("ti.sysbios.family.shared.vayu.IntXbar");
+var IntXbar = xdc.useModule('ti.sysbios.family.shared.vayu.IntXbar');
+var HeapMem = xdc.useModule('ti.sysbios.heaps.HeapMem');
+var Task = xdc.useModule('ti.sysbios.knl.Task');
+var SemiHost = xdc.useModule('ti.sysbios.rts.gnu.SemiHostSupport');
+/*
+ * Program.argSize sets the size of the .args section.
+ * The examples don't use command line args so argSize is set to 0.
+ */
+Program.argSize = 0x0;
+
+/* System stack size (used by ISRs and Swis) */
+Program.stack = 0x20000;
+
+/*
+ * Uncomment this line to globally disable Asserts.
+ * All modules inherit the default from the 'Defaults' module. You
+ * can override these defaults on a per-module basis using Module.common$.
+ * Disabling Asserts will save code space and improve runtime performance.
+Defaults.common$.diags_ASSERT = Diags.ALWAYS_OFF;
+ */
+
+/*
+ * Uncomment this line to keep module names from being loaded on the target.
+ * The module name strings are placed in the .const section. Setting this
+ * parameter to false will save space in the .const section. Error and
+ * Assert messages will contain an "unknown module" prefix instead
+ * of the actual module name.
+Defaults.common$.namedModule = false;
+ */
+
+/*
+ * Minimize exit handler array in System. The System module includes
+ * an array of functions that are registered with System_atexit() to be
+ * called by System_exit().
+ */
+System.maxAtexitHandlers = 4;
+
+/*
+ * Uncomment this line to disable the Error print function.
+ * We lose error information when this is disabled since the errors are
+ * not printed. Disabling the raiseHook will save some code space if
+ * your app is not using System_printf() since the Error_print() function
+ * calls System_printf().
+Error.raiseHook = null;
+ */
+
+/*
+ * Uncomment this line to keep Error, Assert, and Log strings from being
+ * loaded on the target. These strings are placed in the .const section.
+ * Setting this parameter to false will save space in the .const section.
+ * Error, Assert and Log message will print raw ids and args instead of
+ * a formatted message.
+Text.isLoaded = false;
+ */
+
+/*
+ * Uncomment this line to disable the output of characters by SysMin
+ * when the program exits. SysMin writes characters to a circular buffer.
+ * This buffer can be viewed using the SysMin Output view in ROV.
+SysMin.flushAtExit = false;
+ */
+
+
+/* Circular buffer size for System_printf() */
+SysMin.bufSize = 0x400;
+System.SupportProxy = SysMin;
+
+
+/*
+ * Create and install logger for the whole system
+ */
+var loggerBufParams = new LoggerBuf.Params();
+loggerBufParams.numEntries = 32;
+var logger0 = LoggerBuf.create(loggerBufParams);
+Defaults.common$.logger = logger0;
+Main.common$.diags_INFO = Diags.ALWAYS_ON;
+
+/* ================ BIOS configuration ================ */
+
+var BIOS = xdc.useModule('ti.sysbios.BIOS');
+/*
+ * Build a custom SYS/BIOS library from sources.
+ */
+BIOS.libType = BIOS.LibType_Custom;
+
+/*
+ * The BIOS module will create the default heap for the system.
+ * Specify the size of this default heap.
+ */
+BIOS.heapSize = 0x10000;
+
+/* ================ Task configuration ================ */
+
+/* Define and add one Task Hook Set */
+Task.addHookSet({
+ registerFxn: '&TaskRegisterId',
+ switchFxn: '&mySwitch',
+});
+
+/* ================ Driver configuration ================ */
+var socType = "am571x";
+
+/*use CSL package*/
+var Csl = xdc.loadPackage('ti.csl');
+Csl.Settings.deviceType = socType;
+
+/* Load Profiling package */
+var Utils = xdc.loadPackage('ti.utils.profiling');
+
+/* Load and use the PCIE packages */
+var Pcie = xdc.loadPackage('ti.drv.pcie');
+Pcie.Settings.enableProfiling = true;
+/* Enable only if soc-specific library should be used */
+Pcie.Settings.socType = socType;
+
+/* Load the I2C package - required by board */
+var I2c = xdc.loadPackage('ti.drv.i2c');
+
+/* Load the uart package -- required by board */
+var Uart = xdc.loadPackage('ti.drv.uart');
+Uart.Settings.socType = socType;
+
+/* Load the Board package and set the board name */
+var Board = xdc.loadPackage('ti.board');
+Board.Settings.boardName = "idkAM571x";
+
+/* Load the osal package -- required by board & interrupt example */
+var osType = "tirtos"
+var Osal = xdc.loadPackage('ti.osal');
+Osal.Settings.osType = osType;
+
+
+/* ================ Cache and MMU configuration ================ */
+
+var Cache = xdc.useModule('ti.sysbios.family.arm.a15.Cache');
+var Mmu = xdc.useModule('ti.sysbios.family.arm.a15.Mmu');
+
+// Enable the cache
+Cache.enableCache = true;
+
+// Enable the MMU (Required for L1/L2 data caching)
+Mmu.enableMMU = true;
+
+// descriptor attribute structure
+var attrs0 = new Mmu.DescriptorAttrs();
+Mmu.initDescAttrsMeta(attrs0);
+attrs0.type = Mmu.DescriptorType_BLOCK; // BLOCK descriptor
+attrs0.shareable = 2; // sharerable
+attrs0.attrIndx = 1; // Non-cache, device memory
+
+// Set the descriptor for each entry in the address range
+for (var i=0x20000000; i < 0x60000000; i = i + 0x00200000) {
+ // Each 'BLOCK' descriptor entry spans a 2MB address range
+ Mmu.setSecondLevelDescMeta(i, i, attrs0);
+}
+
+// descriptor attribute structure
+var attrs1 = new Mmu.DescriptorAttrs();
+
+Mmu.initDescAttrsMeta(attrs1);
+attrs1.type = Mmu.DescriptorType_BLOCK; // BLOCK descriptor
+attrs1.shareable = 2; // sharerable
+attrs1.attrIndx = 2; // Cached, normal memory
+
+// Set the descriptor for each entry in the address range
+for (var i=0x80000000; i < 0xA0000000; i = i + 0x00200000) {
+ // Each 'BLOCK' descriptor entry spans a 2MB address range
+ Mmu.setSecondLevelDescMeta(i, i, attrs1);
+}
+
+// Set the descriptor for each entry in the address range
+for (var i=0x40300000; i < 0x40380000; i = i + 0x00200000) {
+ // Each 'BLOCK' descriptor entry spans a 2MB address range
+ Mmu.setSecondLevelDescMeta(i, i, attrs1);
+}
+
+/* ================ Memory sections configuration ================ */
+Program.sectMap["BOARD_IO_DELAY_DATA"] = "OCMC_RAM1";
+Program.sectMap["BOARD_IO_DELAY_CODE"] = "OCMC_RAM1";
+Program.sectMap[".bss:pktram"] = "OCMC_RAM1";
+Program.sectMap[".bss:paramram"] = "OCMC_RAM1";
+Program.sectMap[".bss:pktdesc"] = "OCMC_RAM1";
+Program.sectMap[".bss:dstBufSec"] = "OCMC_RAM1";
diff --git a/example/sample/am57x/src/pcie_sample_board.c b/example/sample/am57x/src/pcie_sample_board.c
index 1dadcd33d467e369501ddaab0f702a2e8a8b097c..60ac65b132708ec33e8ec61826bd2201a0ab526f 100644 (file)
/*Reset PCIeSS1*/\r
HW_WR_FIELD32(SOC_L3INIT_PRM_BASE + RM_PCIESS_RSTCTRL,\r
RM_PCIESS_RSTCTRL_RST_LOCAL_PCIE1,\r
- RM_PCIESS_RSTCTRL_RST_LOCAL_PCIE1_ASSERT);\r
+ RM_PCIESS_RSTCTRL_RST_LOCAL_PCIE1_CLEAR);\r
\r
/* Wait till PCIeSS1 is out of reset */\r
while (((HW_RD_REG32(SOC_L3INIT_PRM_BASE + RM_PCIESS_RSTST) &\r
/*Reset PCIeSS2*/\r
HW_WR_FIELD32(SOC_L3INIT_PRM_BASE + RM_PCIESS_RSTCTRL,\r
RM_PCIESS_RSTCTRL_RST_LOCAL_PCIE2,\r
- RM_PCIESS_RSTCTRL_RST_LOCAL_PCIE2_ASSERT);\r
+ RM_PCIESS_RSTCTRL_RST_LOCAL_PCIE2_CLEAR);\r
\r
/* Wait till PCIeSS2 is out of reset */\r
while (((HW_RD_REG32(SOC_L3INIT_PRM_BASE + RM_PCIESS_RSTST) &\r
index dca38d589bc8490b1077ce92c0ddf34717d33bcd..bab10f97a50efdcd3045340ca735d98eab38451c 100644 (file)
} dstBuf_t;\r
dstBuf_t dstBuf\r
#ifdef __ARM_ARCH_7A__\r
-__attribute__((aligned(256))) // GCC way of aligning\r
+__attribute__((aligned(256), section(".bss:dstBufSec"))) // GCC way of aligning\r
#endif\r
; // for dstBuf\r
\r
void *pcieBase;\r
dstBuf_t *pciedstBufBase;\r
uint32_t i;\r
+#ifdef PCIE_REV1_HW\r
+ SemaphoreP_Handle sem = NULL;
+#endif\r
\r
+ /* Get remote buffer out of cache */\r
+#ifndef COHERENT\r
+ CacheP_wb (&dstBuf, sizeof(dstBuf));\r
+#endif\r
/* Unlock kicker once, and don't relock, because its not multicore safe */\r
#if !defined(SOC_AM572x) && !defined(SOC_AM571x)\r
CSL_BootCfgUnlockKicker();\r
if(PcieModeGbl == pcie_RC_MODE)\r
{\r
#ifdef PCIE_REV1_HW\r
- SemaphoreP_Handle sem = PlatformSetupMSIAndINTX (handle);\r
+ sem = PlatformSetupMSIAndINTX (handle);\r
#endif\r
/**********************************************************************/\r
/* Push a single message to the EP then verify that it is echoed back */\r
edmaDeinit(hEdma);\r
#endif\r
#ifdef EDMAPKTBENCH
- if (PcieEdmaPktBench(&pciedstBufBase->edmaPktBenchBuf, PcieModeGbl))
+ if (PcieEdmaPktBench(&dstBuf.edmaPktBenchBuf.msiTracker[0],
+ &pciedstBufBase->edmaPktBenchBuf,
+ PcieModeGbl, sem))
{
PCIE_logPrintf ("EDMA packet IO benchmark failed to execute correctly\n");
exit(1);
diff --git a/package.xdc b/package.xdc
index c4b07e890bdde1589027a95a34ac80bdb85e68f6..29fed67f86192af2228e515b90f698439b39aea1 100644 (file)
--- a/package.xdc
+++ b/package.xdc
* Copyright (C) 2012-2016, Texas Instruments, Inc.\r
*****************************************************************************/\r
\r
-package ti.drv.pcie[2, 2, 0, 5] {\r
+package ti.drv.pcie[2, 2, 0, 6] {\r
module Settings;\r
}\r
\r
diff --git a/pciever.h b/pciever.h
index a554b22460d0582e103108ff7040e3442f2f6155..ad077f0cf56aa0dae817e6d8b0233a7c32e6b985 100644 (file)
--- a/pciever.h
+++ b/pciever.h
* format:
* 0xAABBCCDD -> Arch (AA); API Changes (BB); Major (CC); Minor (DD)
*/
-#define pcie_LLD_VERSION_ID (0x02020005U)
+#define pcie_LLD_VERSION_ID (0x02020006U)
/**
* @brief This is the version string which describes the PCIE LLD along with the
* date and build information.
*/
-#define pcie_LLD_VERSION_STR "PCIE LLD Revision: 02.02.00.05"
+#define pcie_LLD_VERSION_STR "PCIE LLD Revision: 02.02.00.06"
#ifdef __cplusplus