]> rtime.felk.cvut.cz Git - arc.git/commitdiff
SPI FIFO seems to work
authormahi <devnull@localhost>
Wed, 14 Dec 2011 09:10:40 +0000 (10:10 +0100)
committermahi <devnull@localhost>
Wed, 14 Dec 2011 09:10:40 +0000 (10:10 +0100)
arch/ppc/mpc55xx/drivers/Spi.c
boards/mpc5606s_xpc560s/board_info.txt
include/Spi.h

index 07872630f9fcd09b730be139bfd0927d66804cd1..ca2cc15b5cef17d5e031ca8f7ca8509cb3ba5b83 100644 (file)
  * - It's not obvious how to use different modes. My interpretation:\r
  *\r
  *   Sync\r
- *     Always blocking in Spi_SyncTranmit()\r
+ *     Always blocking in Spi_SyncTransmit()\r
+ *\r
+ *\r
+ * Info:\r
+ *   - The AsyncModeType (SPI_POLLING_MODE,SPI_INTERRUPT_MODE) is used to handle only the\r
+ *     async API, ie Spi_AsyncTransmit().  The synchrone API just calls Spi_SyncTransmit()->Spi_Isr()....\r
+ *\r
  *\r
  *   Async and INTERRUPT\r
  *\r
 \r
 #define SPIE_BAD                 (-1)\r
 #define SPIE_OK                                0\r
-#define SPIE_MORE_TO_SEND   1\r
+#define SPIE_JOB_NOT_DONE   1\r
 \r
 #define IMPL_SIMPLE                    0   /* Not implemented, NOT TESTED */\r
-#define IMPL_FIFO                      1       /* Partly implemented, NOT TESTED */\r
+#define IMPL_FIFO                      1\r
 #define IMPL_DMA                       2\r
 \r
-#define SPI_IMPLEMENTATION     IMPL_DMA\r
+#define SPI_IMPLEMENTATION     IMPL_FIFO\r
+#define USE_DIO_CS          STD_OFF\r
 \r
 // E2 read = cmd + addr + data = 1 + 2 + 64 ) = 67 ~ 72\r
 #define SPI_INTERNAL_MTU    72\r
 \r
 //#define USE_LOCAL_RAMLOG\r
 \r
+\r
+\r
 #if defined(USE_LOCAL_RAMLOG)\r
 #define RAMLOG_STR(_x) ramlog_str(_x)\r
 #define RAMLOG_DEC(_x) ramlog_dec(_x)\r
@@ -241,7 +250,7 @@ typedef struct {
 } Spi_EbType;\r
 \r
 typedef enum {\r
-       SPI_ASYNC, SPI_SYNC,\r
+       SPI_ASYNC_CALL, SPI_SYNC_CALL,\r
 } Spi_CallTypeType;\r
 \r
 typedef struct {\r
@@ -272,27 +281,17 @@ typedef struct {
        // current index for data when sending\r
        // mostly here for debug purposes( since it could be local )\r
        uint32 txCurrIndex;\r
-\r
        // Helper array to assign CTAR's\r
        uint32 channelCodes[7];\r
-\r
        // Status for this unit\r
        Spi_StatusType status;\r
-\r
-\r
-\r
        // The current job\r
        const Spi_JobConfigType *currJob;\r
        Spi_JobType currJobIndex;\r
-\r
        // Points array of jobs current\r
        const Spi_JobType *currJobIndexPtr;\r
        // The Sequence\r
        const Spi_SequenceConfigType *currSeqPtr;\r
-\r
-       // Used by sync call to check when a job is done\r
-       //    volatile _Bool done;\r
-\r
        // 1 -  if the current job is sync. 0 - if not\r
        Spi_CallTypeType callType;\r
 } Spi_UnitType;\r
@@ -314,16 +313,13 @@ typedef struct {
 \r
        const Spi_ChannelType *channelsPtr;\r
 \r
-#if (SPI_IMPLEMENTATION == SPI_FIFO )\r
+#if (SPI_IMPLEMENTATION == IMPL_FIFO )\r
        /* Number of bytes in FIFO (before EOQ is set) */\r
        uint32_t fifoSent;\r
 \r
        /* the currently transmitting channel index for FIFO */\r
        uint8_t currTxChIndex;\r
 \r
-       /* The FIFO is filled for the last time for this job  */\r
-       _Bool jobComplete;\r
-\r
        /* number of Spi_DataType sent for the current channel */\r
        uint32_t txChCnt;\r
 \r
@@ -332,6 +328,7 @@ typedef struct {
 \r
        /* the currently receiving channel index for FIFO */\r
        uint32_t currRxChIndex;\r
+\r
 #endif\r
 \r
        Spi_JobResultType jobResult;\r
@@ -402,7 +399,7 @@ Spi_ChannelInfoType Spi_ChannelInfo[SPI_MAX_CHANNEL];
 \r
 Spi_GlobalType Spi_Global;\r
 \r
-Spi_UnitType Spi_Unit[4];\r
+Spi_UnitType Spi_Unit[4]; // TODO:?\r
 Spi_SeqUnitType Spi_SeqUnit[SPI_MAX_SEQUENCE];\r
 Spi_JobUnitType Spi_JobUnit[SPI_MAX_JOB];\r
 \r
@@ -452,7 +449,12 @@ Spi_DmaConfigType  Spi_DmaConfig[4] = {
 \r
 /* ----------------------------[private functions]---------------------------*/\r
 \r
+\r
 #if (SPI_IMPLEMENTATION == IMPL_FIFO )\r
+\r
+static void Spi_WriteJob_FIFO( Spi_JobType jobIndex );\r
+\r
+\r
 /**\r
  * Get the buffer for a channel.\r
  *
@@ -637,36 +639,6 @@ static Spi_JobType Spi_GetNextJob(Spi_UnitType *spiUnit) {
 }\r
 //-------------------------------------------------------------------\r
 \r
-#if 0\r
-/**\r
- * Schedules next job to do( calls Spi_jobWrite() or not )\r
- *\r
- * @param spiUnit The SPI unit\r
- */\r
-static int Spi_WriteNextJob(Spi_UnitType *spiUnit) {\r
-       Spi_JobType nextJob;\r
-       // Re-cap.\r
-       // - Jobs have the controller\r
-       // - Sequences can we interruptible between jobs.\r
-       // But\r
-       // According to SPI086 you can't share a job with a sequence that\r
-       // is in SPI_SEQ_PENDING ( that happens first thing at Spi_AsyncTranmit() )\r
-       //\r
-       // So, I no clue what to use the priority thing for :(\r
-\r
-       nextJob = Spi_GetNextJob(spiUnit);\r
-       if ((int) nextJob == JOB_NOT_VALID) {\r
-               return JOB_NOT_VALID;\r
-\r
-       } else {\r
-               // Schedule next job\r
-               Spi_JobWrite(nextJob);\r
-       }\r
-       return 0;\r
-}\r
-#endif\r
-\r
-//-------------------------------------------------------------------\r
 \r
 #if (SPI_IMPLEMENTATION==IMPL_DMA)\r
 \r
@@ -748,125 +720,111 @@ static int Spi_PostTransmit_DMA(Spi_UnitType *spiUnit) {
 \r
 #elif (SPI_IMPLEMENTATION==IMPL_FIFO)\r
 \r
-static int Spi_PostTransmit_FIFO(Spi_UnitType *spiUnit) {\r
-       Spi_JobType jobIndex;\r
-       volatile struct DSPI_tag *spiHw;\r
-       Spi_JobUnitType *jobUnitPtr;\r
-       Spi_DataType *buf;\r
-       uint32_t length;\r
-       int i = 0;\r
-       uint32_t popVal;\r
+static int Spi_Rx_FIFO(Spi_UnitType *spiUnit) {\r
+       Spi_JobUnitType *    jobUnitPtr;\r
+       Spi_DataType *       buf;\r
+    uint32_t             copyCnt;\r
+       uint32_t             popVal;\r
+       Spi_ChannelType      currChannel;\r
+       Spi_NumberOfDataType bufLen;\r
+    int i = 0;\r
+    int rv = SPIE_JOB_NOT_DONE;\r
+    const Spi_ChannelConfigType *   chConfig;\r
+    uint32_t bInChar;\r
+\r
 \r
 //     RAMLOG_STR("PostTransmit Job: "); RAMLOG_DEC(spiUnit->currJob->SpiJobId); RAMLOG_STR("\n");\r
+    RAMLOG_STR("Spi_Rx_FIFO\n");\r
 \r
-       jobIndex = spiUnit->currJobIndex;\r
-       spiHw = Spi_JobUnit[jobIndex].hwPtr;\r
+       jobUnitPtr = &Spi_JobUnit[spiUnit->currJobIndex];\r
 \r
-       if( spiHw->TCR.B.SPI_TCNT != jobUnitPtr->fifoSent ) {\r
+       if( jobUnitPtr->hwPtr->TCR.B.SPI_TCNT != jobUnitPtr->fifoSent ) {\r
+#if defined(STEP_VALIDATION)\r
+           while(1) {};\r
+#endif\r
                return SPIE_BAD;\r
        }\r
 \r
        /*\r
-        * Fill receive buffers, either EB or IB
+        * Fill receive buffers, either EB or IB\r
+        * Example with 8-bit CMD, 16-bit ADDR and some data.\r
+        *    CMD |  ADDR   |     DATA\r
+        *   | 12 | 23 | 34 | 00 | 01 | 02 | 03\r
+        *      1    2    3    4    5    6           BYTE CNT\r
+        *      1      2       3    4    5    6      FIFO\r
+        * With a FIFO of 5 we can see that the CMD, ADDR and almost the whole\r
+        * DATA channel is sent.\r
         */\r
-       while ( jobUnitPtr->fifoSent != 0 ) {\r
-               currChannel = jobUnitPtr->channelsPtr[jobUnitPtr->currRxChIndex];\r
-               assert(  currChannel != CH_NOT_VALID );\r
-\r
-               buf             = spiGetRxBuf(jobUnitPtr->rxChCnt, &bufLen);\r
-               copyCnt         = MIN( jobUnitPtr->fifoSent, bufLen - jobUnitPtr->rxChCnt );\r
-               jobUnitPtr->fifoSent -= copyCnt;\r
-\r
-               /* Pop the FIFO */\r
-               if( buff != NULL ) {\r
-                       for(i=0;copyCnt;i++) {\r
-                               popVal = jobUnitPtr->hwPtr->POPR.B.RXDATA;\r
-                               buf[jobUnitPtr->rxChCnt++] = (Spi_DataType)popVal;\r
-                       }\r
-               } else {\r
-                       for(i=0;copyCnt;i++) {\r
-                               popVal = jobUnitPtr->hwPtr->POPR.B.RXDATA;\r
-                       }\r
-               }\r
+    currChannel = jobUnitPtr->channelsPtr[jobUnitPtr->currRxChIndex];\r
+    assert(  currChannel != CH_NOT_VALID );\r
 \r
-               if( (bufLen - jobUnitPtr->rxChCnt) == 0 ) {\r
-                       jobUnitPtr->rxChCnt = 0;\r
-                       jobUnitPtr->currRxChIndex++;\r
-               }\r
-       }\r
+    if( jobUnitPtr->fifoSent != jobUnitPtr->hwPtr->SR.B.RXCTR ) {\r
+#if defined(STEP_VALIDATION)\r
+        while(1) {};\r
+#endif\r
+        return SPIE_BAD;\r
+    }\r
 \r
+       while ( jobUnitPtr->fifoSent != 0 ) {\r
 \r
-       /* Check if we are done with this job */\r
-       if( jobUnitPtr->jobComplete == 0 ) {\r
-               return SPIE_MORE_TO_SEND;\r
-       }\r
+        chConfig = &Spi_Global.configPtr->SpiChannelConfig[currChannel];\r
 \r
-       Spi_DoWrite_FIFO( jobIndex );\r
+           RAMLOG_STR("CIR#");RAMLOG_DEC(jobUnitPtr->currRxChIndex);RAMLOG_STR("\n");\r
 \r
-       return SPIE_OK;\r
+           /* Get this channels destination buffer */\r
+               buf = spiGetRxBuf(currChannel, &bufLen);\r
+               assert(bufLen!=0);  /* We should always get a valid bufLen */\r
 \r
-#if 0\r
+//        copyCnt = MIN( jobUnitPtr->fifoSent, bufLen - jobUnitPtr->rxChCnt );\r
+        copyCnt = MIN( (bufLen - jobUnitPtr->rxChCnt) >> ((chConfig->SpiDataWidth-1)/8), jobUnitPtr->fifoSent );\r
 \r
+        if( copyCnt == 0  ) {\r
+            while(1);\r
+        }\r
 \r
+        jobUnitPtr->fifoSent -= copyCnt;\r
 \r
-       /* Copy data from RX queue to the external buffer( if any ) */\r
-       {\r
-               int j = 0;\r
-               int currIndex = 0;\r
-               int channelIndex;\r
-               const Spi_ChannelConfigType *chConfig;\r
-               Spi_EbType *extChBuff;\r
-               int gotTx;\r
-               int sentTx;\r
+        bInChar = (chConfig->SpiDataWidth > 8 ) ? 2 : 1;\r
 \r
-               // Check that we got the number of bytes we sent\r
-               sentTx = spiUnit->txCurrIndex + 1;\r
-               gotTx = (Dma_GetTcd(spiUnit->dmaRxChannel)->DADDR\r
-                               - (uint32) &spiUnit->rxQueue[0]) / sizeof(uint32);\r
+        /* Pop the FIFO */\r
+        if( buf != NULL ) {\r
+            for(i=0;i<copyCnt;i++) {\r
+                popVal = jobUnitPtr->hwPtr->POPR.B.RXDATA;\r
+                buf[jobUnitPtr->rxChCnt] = (Spi_DataType)popVal;\r
+                jobUnitPtr->rxChCnt += bInChar;\r
+            }\r
+        } else {\r
+            for(i=0;i<copyCnt;i++) {\r
+                popVal = jobUnitPtr->hwPtr->POPR.B.RXDATA;\r
+                jobUnitPtr->rxChCnt += bInChar;\r
 \r
-               if (sentTx != gotTx) {\r
-                       // Something failed\r
-                       DEBUG(DEBUG_LOW,"%s: Expected %d bytes. Got %d bytes\n ",MODULE_NAME,sentTx, gotTx );\r
-                       return SPIE_BAD;\r
-               } else {\r
-                       RAMLOG_STR("Rx "); RAMLOG_DEC(gotTx); RAMLOG_STR(" Bytes\n"); DEBUG(DEBUG_LOW,"%s: Got %d bytes\n",MODULE_NAME,gotTx);\r
-               }\r
+            }\r
+        }\r
 \r
-               // Find the channels for this job\r
-               while ((channelIndex = spiUnit->currJob->ChannelAssignment[j++])\r
-                               != CH_NOT_VALID) {\r
-                       chConfig = &Spi_Global.configPtr->SpiChannelConfig[channelIndex];\r
+        if( (bufLen - jobUnitPtr->rxChCnt ) == 0 ) {\r
+            /* advance to the next channel */\r
+            jobUnitPtr->rxChCnt = 0;\r
+            jobUnitPtr->currRxChIndex++;\r
+            currChannel = jobUnitPtr->channelsPtr[jobUnitPtr->currRxChIndex];\r
+            if( currChannel == CH_NOT_VALID ) {\r
+                //assert(  jobUnitPtr->fifoSent == 0);\r
+                jobUnitPtr->fifoSent = 0;\r
+                jobUnitPtr->currRxChIndex = 0;\r
+                rv = SPIE_OK;\r
+                break;\r
+            }\r
 \r
-                       /* Check configuration error */\r
-#if ( SPI_CHANNEL_BUFFERS_ALLOWED == 1  )\r
-                       assert( chConfig->SpiChannelType == SPI_EB );\r
-#endif\r
+        }\r
+       }\r
 \r
-                       // Send the channels that are setup with external buffers\r
-                       // Get the external buffer for this channel\r
-                       extChBuff = &Spi_Global.extBufPtr[channelIndex];\r
-                       if (extChBuff->dest != NULL) {\r
-                               // Note! No support for >8 "data"\r
-                               for (int k = 0; k < extChBuff->length; k++) {\r
-                                       extChBuff->dest[k] = spiUnit->rxQueue[currIndex++];\r
-                                       DEBUG(DEBUG_LOW," %02x ",extChBuff->dest[k]);\r
-                                       printedSomeThing = 1;\r
-                               }\r
+       /* Check if we are done with this job */\r
+    if( 0 != jobUnitPtr->hwPtr->SR.B.RXCTR ) {\r
+        while(1) {};\r
+    }\r
 \r
-                       } else {\r
-                               if (chConfig->SpiDataWidth > 8) {\r
-                                       currIndex += (extChBuff->length / 2);\r
-                               } else {\r
-                                       currIndex += extChBuff->length;\r
-                               }\r
-                       }\r
-               }\r
-               if (printedSomeThing)\r
-                       DEBUG(DEBUG_LOW,"\n");\r
-       }\r
 \r
-       return 0;\r
-#endif\r
+\r
+       return rv;\r
 }\r
 \r
 #endif\r
@@ -901,18 +859,9 @@ static void Spi_Isr(uint32 unit) {
        }\r
 \r
 #if (SPI_IMPLEMENTATION == IMPL_DMA)\r
-       // To be 100% sure also wait for the DMA transfer to complete.\r
-#if 0\r
-       while (!Dma_ChannelDone(\r
-                       Spi_Global.configPtr->SpiHwConfig[unit].RxDmaChannel)) {\r
-               Spi_Global.totalNbrOfWaitRxDMA++;\r
-       }\r
-#else\r
        while (!Dma_ChannelDone(Spi_Unit[unit].dmaRxChannel)) {\r
                Spi_Global.totalNbrOfWaitRxDMA++;\r
        }\r
-\r
-#endif\r
 #endif\r
 \r
        /* Halt DSPI unit until we are ready for next transfer. */\r
@@ -937,12 +886,19 @@ static void Spi_Isr(uint32 unit) {
 #if (SPI_IMPLEMENTATION==IMPL_DMA)\r
        rv = Spi_PostTransmit_DMA(spiUnit);\r
 #elif (SPI_IMPLEMENTATION==IMPL_FIFO)\r
-       rv = Spi_PostTransmit_FIFO(spiUnit);\r
+       rv = Spi_Rx_FIFO(spiUnit);\r
 \r
-       if( rv == SPIE_MORE_TO_SEND ) {\r
+       if( rv == SPIE_JOB_NOT_DONE ) {\r
+           /* RX FIFO now empty, but the job is not done -> send more */\r
+           Spi_WriteJob_FIFO ( spiUnit->currJobIndex );\r
                RAMLOG_STR("Spi_Isr END\n");\r
                return;\r
        }\r
+#if (USE_DIO_CS == STD_ON)\r
+       else {\r
+           Spi_JobUnit[spiUnit->currJobIndex].extDeviceCfgPtr->SpiCsCallback(1);\r
+       }\r
+#endif\r
 #endif\r
 \r
        // Call notification end\r
@@ -956,6 +912,7 @@ static void Spi_Isr(uint32 unit) {
                Spi_SetJobResult(spiUnit->currJob->SpiJobId, SPI_JOB_FAILED);\r
                Spi_SetSequenceResult(spiUnit->currSeqPtr->SpiSequenceId,\r
                                SPI_SEQ_FAILED);\r
+               while(1);\r
        } else {\r
                Spi_JobType nextJob;\r
 \r
@@ -978,7 +935,7 @@ static void Spi_Isr(uint32 unit) {
                nextJob = Spi_GetNextJob(spiUnit);\r
                if( nextJob != JOB_NOT_VALID ) {\r
                        Spi_JobWrite(nextJob);\r
-                       RAMLOG_STR("More jobs\n");\r
+                       RAMLOG_STR("more_jobs\n");\r
                } else {\r
                        // No more jobs, so set HwUnit and sequence IDLE/OK also.\r
                        Spi_SetHWUnitStatus(unit, SPI_IDLE);\r
@@ -994,7 +951,7 @@ static void Spi_Isr(uint32 unit) {
                        /* We are now ready for next transfer. */\r
                        spiHw->MCR.B.HALT = 1;\r
 \r
-                       RAMLOG_STR("NO more jobs\n");\r
+                       RAMLOG_STR("NO_more_jobs\n");\r
                }\r
        }\r
 \r
@@ -1236,8 +1193,14 @@ static void Spi_InitController(uint32 unit) {
        spiHw->MCR.B.PCSSE = 0;\r
 \r
        /* Enable FIFO's. */\r
+#if (SPI_IMPLEMENTATION == IMPL_DMA)\r
        spiHw->MCR.B.DIS_RXF = 1;\r
        spiHw->MCR.B.DIS_TXF = 1;\r
+#elif (SPI_IMPLEMENTATION == IMPL_FIFO)\r
+    spiHw->MCR.B.DIS_RXF = 0;\r
+    spiHw->MCR.B.DIS_TXF = 0;\r
+#endif\r
+\r
 \r
        /* Set all active low. */\r
        spiHw->MCR.B.PCSIS0 = 1;\r
@@ -1341,8 +1304,6 @@ void Spi_Init(const Spi_ConfigType *ConfigPtr) {
 \r
        Spi_Global.asyncMode = SPI_INTERRUPT_MODE;\r
 \r
-       //      Spi_Global.currSeq = SEQ_NOT_VALID;\r
-\r
        // Set all sequence results to OK\r
        for (Spi_SequenceType i = (Spi_SequenceType) 0; i < SPI_MAX_SEQUENCE; i++) {\r
                Spi_SetSequenceResult(i, SPI_SEQ_OK);\r
@@ -1596,7 +1557,7 @@ static void Spi_DoWrite_DMA(      Spi_UnitType *spiUnit,Spi_JobType jobIndex,
                spiHw->TCR.B.SPI_TCNT = 0;\r
 \r
                if (    (Spi_Global.asyncMode == SPI_INTERRUPT_MODE) &&\r
-                               (spiUnit->callType == SPI_ASYNC)) {\r
+                               (spiUnit->callType == SPI_ASYNC_CALL)) {\r
                        ENABLE_EOQ_INTERRUPT(spiHw);\r
                } else {\r
                        DISABLE_EOQ_INTERRUPT(spiHw);\r
@@ -1628,68 +1589,158 @@ static void Spi_DoWrite_DMA(   Spi_UnitType *spiUnit,Spi_JobType jobIndex,
  * @param jobConfig\r
  * @return\r
  */\r
-static void Spi_DoWrite_FIFO( Spi_JobType jobIndex )\r
+static void Spi_WriteJob_FIFO( Spi_JobType jobIndex )\r
 {\r
-       Spi_ChannelType currChannel;\r
-       Spi_CommandType cmd;\r
-       uint32_t                length;\r
-       Spi_EbType *    extChBuff;\r
-       const Spi_ChannelConfigType *chConfig;\r
-       _Bool   fifoFull = 0;\r
-       int     fifoCnt  = 0;\r
-       Spi_JobUnitType *jobUnitPtr = Spi_JobUnit[jobIndex];\r
+       Spi_ChannelType                 currChannel;\r
+       Spi_CommandType                 cmd;\r
+       Spi_CommandType                 dCmd;\r
+    Spi_NumberOfDataType            bufLen;\r
+       const Spi_ChannelConfigType *   chConfig;\r
+    Spi_JobUnitType *               jobUnitPtr;\r
+    const Spi_DataType *            buf;\r
+    Spi_NumberOfDataType            copyCnt;\r
+    Spi_NumberOfDataType            fifoLeft;\r
+    boolean                         done = 0;\r
+    boolean                         lastJob = 0;\r
+       int     i;\r
+       jobUnitPtr = &Spi_JobUnit[jobIndex];\r
 \r
-       jobUnitPtr->fifoSent = 0;\r
+\r
+       fifoLeft = FIFO_DEPTH;\r
+\r
+       RAMLOG_STR("Spi_WriteJob_FIFO\n");\r
+\r
+#if defined(STEP_VALIDATION)\r
+    if(  jobUnitPtr->hwPtr->SR.B.TXCTR != 0 ) {\r
+        while(1);\r
+    }\r
+#endif\r
+\r
+    cmd.R = 0;\r
+    dCmd.R = 0xfffffffful;\r
 \r
        /* Iterate over the channels for this job */\r
-       while ((currChannel = jobUnitPtr->channelsPtr[jobUnitPtr->currTxChIndex]) != CH_NOT_VALID) {\r
+    currChannel = jobUnitPtr->channelsPtr[jobUnitPtr->currTxChIndex];\r
+    while ( fifoLeft != 0) {\r
 \r
                chConfig = &Spi_Global.configPtr->SpiChannelConfig[currChannel];\r
-               buf = spiGetTxBuf(currChannel, &bufLen);\r
+               buf = spiGetTxBuf( currChannel, &bufLen);\r
 \r
-               /* === Push on the FIFO === */\r
-               copyCnt = MIN( bufLen,  (FIFO_DEPTH - jobUnitPtr->fifoSent));\r
+               /* Minimum of how much data to copy and the limit of the FIFO */\r
+               copyCnt = MIN( (bufLen - jobUnitPtr->txChCnt) >> ((chConfig->SpiDataWidth-1)/8), fifoLeft );\r
 \r
-               while( copyCnt != 0 ) {\r
+        /* Channels should keep CS active ( A job must assert CS continuously) */\r
+        cmd.B.CONT = 1;\r
+        /* Set the Chip Select (PCS) */\r
+        cmd.R |= (1 << (16 + jobUnitPtr->extDeviceCfgPtr->SpiCsIdentifier));\r
 \r
-                       /* Channels should keep CS active ( A job must assert CS continuously) */\r
-                       cmd.B.CONT = 1;\r
-                       /* Set the Chip Select (PCS) */\r
-                       cmd.R |= (1 << (16 + jobUnitPtr->extDeviceCfgPtr->SpiCsIdentifier));\r
+        if( cmd.B.EOQ == 1) {\r
+            while(1) {};\r
+        }\r
 \r
-                       cmd.B.CTAS = Spi_ChannelInfo[currChannel].ctarId;\r
-                       if (buf != NULL) {\r
-                               if (chConfig->SpiDataWidth > 8 ) {\r
-                                       cmd.B.TXDATA =  (buf[jobUnitPtr->dataIndex] << 8) +\r
-                                                                       (buf[jobUnitPtr->dataIndex      + 1] & 0xff);\r
-                                       jobUnitPtr->dataIndex+=2;\r
-                               } else {\r
-                                       cmd.B.TXDATA = buf[jobUnitPtr->dataIndex];\r
-                                       jobUnitPtr->dataIndex++;\r
-                               }\r
+        /* Push as much as we can (FIFO or Channel limits) */\r
+        for(i=0; i < copyCnt ; i++ ) {\r
+            cmd.B.CTAS = Spi_ChannelInfo[currChannel].ctarId;\r
+            if (buf != NULL) {\r
+                if (chConfig->SpiDataWidth > 8 ) {\r
+                    cmd.B.TXDATA =  (buf[jobUnitPtr->txChCnt] << 8) +\r
+                                    (buf[jobUnitPtr->txChCnt  + 1] & 0xff);\r
+                } else {\r
+                    cmd.B.TXDATA = buf[jobUnitPtr->txChCnt];\r
+                }\r
+            } else {\r
+                cmd.B.TXDATA = chConfig->SpiDefaultData;\r
+            }\r
+\r
+            if (chConfig->SpiDataWidth > 8 ) {\r
+                jobUnitPtr->txChCnt+=2;\r
+            } else {\r
+                jobUnitPtr->txChCnt++;\r
+            }\r
+\r
+\r
+            if( dCmd.R != 0xfffffffful) {\r
+                jobUnitPtr->hwPtr->PUSHR.R = dCmd.R;  // Write delayed\r
+            }\r
+\r
+            dCmd.R = cmd.R;     // Save it\r
+            --fifoLeft;\r
+        } /* for */\r
+\r
+        RAMLOG_STR("CI#");RAMLOG_DEC(jobUnitPtr->currTxChIndex);RAMLOG_STR("\n");\r
+\r
+\r
+        /* Done with channel? */\r
+        if( ((bufLen -  jobUnitPtr->txChCnt) == 0) ) {\r
+            jobUnitPtr->txChCnt = 0;\r
+            /* Done with job? */\r
+            jobUnitPtr->currTxChIndex++;\r
+            currChannel = jobUnitPtr->channelsPtr[jobUnitPtr->currTxChIndex];\r
+            if( currChannel == CH_NOT_VALID ) {\r
+                jobUnitPtr->currTxChIndex = 0;\r
+                cmd.B.CONT = 0;\r
+                break;\r
+            }\r
+        }\r
 \r
-                       } else {\r
-                               cmd.B.TXDATA = chConfig->SpiDefaultData;\r
-                       }\r
-                       fifoCnt++;\r
+    } /* while */\r
 \r
-                       /* Set EOQ if last */\r
-                       fifoFull = (fifoCnt == FIFO_DEPTH ) ? 1 : 0;\r
-                       cmd.B.EOQ = fifoFull;\r
+    cmd.B.EOQ = 1;\r
+    jobUnitPtr->hwPtr->PUSHR.R = cmd.R;\r
 \r
-                       /* Push in to FIFO */\r
-                       jobUnitPtr->hwPtr->PUSHR.R = cmd.R;\r
-               }\r
+    jobUnitPtr->fifoSent = FIFO_DEPTH - fifoLeft;\r
 \r
-               if( fifoFull ) {\r
-                       break;\r
-               }\r
-               jobUnitPtr->currTxChIndex++;\r
+#if defined(STEP_VALIDATION)\r
+       if( jobUnitPtr->fifoSent != jobUnitPtr->hwPtr->SR.B.TXCTR ) {\r
+           while(1);\r
        }\r
+#endif\r
 \r
-       if(currChannel == CH_NOT_VALID ) {\r
-               jobUnitPtr->jobComplete = 1;\r
-       }\r
+       jobUnitPtr->hwPtr->TCR.B.SPI_TCNT = 0;\r
+\r
+    if ( (Spi_Global.asyncMode == SPI_INTERRUPT_MODE) &&\r
+         (jobUnitPtr->unitPtr->callType == SPI_ASYNC_CALL)) {\r
+        ENABLE_EOQ_INTERRUPT(jobUnitPtr->hwPtr);\r
+    } else {\r
+        DISABLE_EOQ_INTERRUPT(jobUnitPtr->hwPtr);\r
+    }\r
+\r
+#if defined(STEP_VALIDATION)\r
+    /* Verify FIFO before sending */\r
+    {\r
+        SPICommandType *base = (SPICommandType *)&jobUnitPtr->hwPtr->TXFR[0];\r
+        SPICommandType *curr;\r
+        int i,lastIndex;\r
+\r
+        i = jobUnitPtr->hwPtr->SR.B.TXNXTPTR;\r
+        lastIndex = ( i + jobUnitPtr->hwPtr->SR.B.TXCTR - 1 ) % FIFO_DEPTH;\r
+        while( i != lastIndex )  {\r
+            curr = base + i;\r
+            if( curr->B.EOQ == 1) {\r
+                while(1) {};\r
+            }\r
+\r
+            i = (i + 1) % FIFO_DEPTH;\r
+        }\r
+        curr = base + i;\r
+        if( curr->B.EOQ != 1) {\r
+            while(1) {};\r
+        }\r
+    }\r
+#endif\r
+\r
+       jobUnitPtr->hwPtr->SR.B.EOQF = 1;\r
+       jobUnitPtr->hwPtr->MCR.B.HALT = 0;\r
+\r
+#if defined(STEP_VALIDATION)\r
+        /* Wait for transfer to complete (EOQF bit is set) */\r
+        while (jobUnitPtr->hwPtr->SR.B.EOQF==1) {\r
+            Spi_Global.eoqf_cnt++;\r
+        }\r
+        while (jobUnitPtr->hwPtr->SR.B.TXRXS) {Spi_Global.txrxs_cnt++;}\r
+#endif\r
+\r
+       // TODO: Clear FIFO's? CLR_TXF?\r
 \r
 }\r
 #endif /* (SPI_IMPLEMENTATION==IMPL_FIFO) */\r
@@ -1711,6 +1762,10 @@ static void Spi_JobWrite(Spi_JobType jobIndex) {
        unitPtr->txCurrIndex = 0;\r
        unitPtr->currJob = Spi_JobUnit[jobIndex].jobCfgPtr;\r
        unitPtr->currJobIndex = jobIndex;\r
+#if (SPI_IMPLEMENTATION == IMPL_FIFO)\r
+       Spi_JobUnit[jobIndex].txChCnt = 0;\r
+       Spi_JobUnit[jobIndex].rxChCnt = 0;\r
+#endif\r
 \r
        Spi_SetHWUnitStatus(Spi_JobUnit[jobIndex].jobCfgPtr->SpiHwUnit, SPI_BUSY);\r
        Spi_SetJobResult(jobIndex, SPI_JOB_PENDING);\r
@@ -1719,7 +1774,10 @@ static void Spi_JobWrite(Spi_JobType jobIndex) {
        Spi_DoWrite_DMA( unitPtr, jobIndex, Spi_JobUnit[jobIndex].jobCfgPtr );\r
 #elif (SPI_IMPLEMENTATION==IMPL_FIFO)\r
        Spi_JobUnit[jobIndex].currTxChIndex = 0;\r
-       Spi_DoWrite_FIFO ( jobIndex );\r
+#if (USE_DIO_CS == STD_ON)\r
+    Spi_JobUnit[jobIndex].extDeviceCfgPtr->SpiCsCallback(0);\r
+#endif\r
+       Spi_WriteJob_FIFO ( jobIndex );\r
 #endif\r
 \r
 }\r
@@ -1763,7 +1821,7 @@ static void Spi_SeqWrite(Spi_SequenceType seqIndex, Spi_CallTypeType sync) {
 \r
        // Setup interrupt for end of queue\r
        if (    (Spi_Global.asyncMode == SPI_INTERRUPT_MODE) &&\r
-                       (spiUnit->callType== SPI_ASYNC)) {\r
+                       (spiUnit->callType== SPI_ASYNC_CALL)) {\r
                DEBUG(DEBUG_MEDIUM,"%s: async/interrupt mode\n",MODULE_NAME);\r
        } else {\r
                DEBUG(DEBUG_MEDIUM,"%s: sync/polled mode\n",MODULE_NAME);\r
@@ -1775,7 +1833,7 @@ static void Spi_SeqWrite(Spi_SequenceType seqIndex, Spi_CallTypeType sync) {
 \r
        Spi_JobWrite(jobIndex);\r
 \r
-       if (spiUnit->callType == SPI_SYNC) {\r
+       if (spiUnit->callType == SPI_SYNC_CALL) {\r
                while (Spi_GetSequenceResult(seqIndex) == SPI_SEQ_PENDING) {\r
                        Spi_Isr(jobConfig->SpiHwUnit);\r
                }\r
@@ -1806,6 +1864,13 @@ static _Bool Spi_AnyPendingJobs(Spi_SequenceType Sequence) {
 \r
 //-------------------------------------------------------------------\r
 \r
+\r
+/**\r
+ * Blocking write\r
+ *\r
+ * @param Sequence\r
+ * @return\r
+ */\r
 Std_ReturnType Spi_SyncTransmit(Spi_SequenceType Sequence) {\r
 \r
        VALIDATE_W_RV( ( TRUE == Spi_Global.initRun ), SPI_SYNCTRANSMIT_SERVICE_ID, SPI_E_UNINIT, E_NOT_OK );\r
@@ -1823,7 +1888,7 @@ Std_ReturnType Spi_SyncTransmit(Spi_SequenceType Sequence) {
                return E_NOT_OK;\r
        }\r
 \r
-       Spi_SeqWrite(Sequence, SPI_SYNC);\r
+       Spi_SeqWrite(Sequence, SPI_SYNC_CALL);\r
 \r
        return rv;\r
 }\r
@@ -1847,7 +1912,7 @@ Std_ReturnType Spi_AsyncTransmit(Spi_SequenceType Sequence) {
 \r
        DEBUG(DEBUG_LOW,"%s: Starting seq: %d\n",MODULE_NAME,Sequence);\r
 \r
-       Spi_SeqWrite(Sequence, SPI_ASYNC);\r
+       Spi_SeqWrite(Sequence, SPI_ASYNC_CALL);\r
 \r
        return E_OK;\r
 }\r
index 0bff1d101de8defcbda37bf3897681cf7301de4a..da77e0bce13efa83248fa5a1ef93250a7a09564d 100644 (file)
@@ -71,8 +71,8 @@ PORT J will have the following layout
   SCK/Blue   9-X  X-10  \r
   CS/Green  11-X  X-12\r
             13-X  X-14\r
-  Gnd/Black 15-X  X-16 VCC/Red \r
-    \r
+            15-X  X-16  \r
+  Gnd/Black 17-X  X-18 VCC/Red   \r
 \r
 \r
 \r
index b16618eba00a17c868673fedc7b3c7448bb7caa7..3076334e029eb91f67d1bffbc8b4ce4cea1e7ec1 100644 (file)
@@ -139,6 +139,9 @@ typedef uint8_t Spi_SequenceType;
 \r
 #endif\r
 \r
+#define IMPL_SIMPLE         0   /* Not implemented, NOT TESTED */\r
+#define IMPL_FIFO           1\r
+#define IMPL_DMA            2\r
 \r
 #define SPI_EB_MAX_LENGTH 64\r
 \r