]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/pcie-lld.git/commitdiff
PRSDK-748 : pcie+icss+edma benchmark/demo
authorJohn Dowdal <jdowdal@ti.com>
Sun, 11 Sep 2016 19:37:32 +0000 (15:37 -0400)
committerJohn Dowdal <jdowdal@ti.com>
Sun, 11 Sep 2016 19:37:32 +0000 (15:37 -0400)
example/edmaPktBench/edmaPktBench.c
example/edmaPktBench/edmaPktBench.h
example/edmaPktBench/edmaPktMsiBench.c [new file with mode: 0644]
example/edmaPktBench/edmaPktMsiBench.h [new file with mode: 0644]
example/sample/am571x/armv7/bios/PCIE_idkAM571x_wSoCLib_armEdmaPktExampleProject.txt
example/sample/am571x/armv7/bios/pcie_edmapkt.cfg [new file with mode: 0644]
example/sample/am57x/src/pcie_sample_board.c
example/sample/src/pcie_sample.c
package.xdc
pciever.h

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
@@ -203,37 +911,146 @@ void setupRxDMA (void)
  * 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
new file mode 100644 (file)
index 0000000..5d593b7
--- /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
new file mode 100644 (file)
index 0000000..9e354be
--- /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
index f26bdb7421c8e3e58204ea6bf26f8ae1f77d26b5..1a09b165e66cf8efd92cc3f4e0d611dafafa9c34 100644 (file)
@@ -1,6 +1,7 @@
 -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
new file mode 100644 (file)
index 0000000..62f244b
--- /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";
index 1dadcd33d467e369501ddaab0f702a2e8a8b097c..60ac65b132708ec33e8ec61826bd2201a0ab526f 100644 (file)
@@ -295,7 +295,7 @@ void PlatformPCIESS1Reset(void)
     /*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
@@ -687,7 +687,7 @@ void PlatformPCIESS2Reset(void)
     /*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)
@@ -126,7 +126,7 @@ typedef struct dstBuf_s {
 } 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
@@ -1561,7 +1561,14 @@ void pcie (void)
   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
@@ -1777,7 +1784,7 @@ void pcie (void)
   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
@@ -1887,7 +1894,9 @@ PCIE_logPrintf ("Failed to pass token \n");
   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);
index c4b07e890bdde1589027a95a34ac80bdb85e68f6..29fed67f86192af2228e515b90f698439b39aea1 100644 (file)
@@ -9,7 +9,7 @@
  * 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
index a554b22460d0582e103108ff7040e3442f2f6155..ad077f0cf56aa0dae817e6d8b0233a7c32e6b985 100644 (file)
--- a/pciever.h
+++ b/pciever.h
@@ -51,13 +51,13 @@ extern "C" {
  * 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