3 Replies Latest reply on Jan 7, 2015 12:40 PM by helmut.forren

    Trouble with SPI Slave

    helmut.forren

      I'm using PSOC Creator 2.2, SPI_Slave_v2_50, targeting a CY8C5868AXI-LP032.

         

      I can't seem to get the SPI slave to work at all.  I have confirmed all three incoming signals from a different processor, these signals being ss, sclk, and mosi.  So I know that those signals are getting inside the PSOC, with a clock rate of roughly 96kHz. However, I can't seem to get any response out of the SPI slave component, as measured on the rx_interrupt output in multiple ways.

         

      I've attached images of my TopDesign and the three configuration tabs for the SPI slave.  I've also pasted the relevant source code below, taken largely from the Cypress example.  The entry point is init_spis_psoc() near the bottom.  

         

      In the recent past, I routed each of the three incoming signals (ss, sclk, mosi) directly to one of my LED output pins.  I confirmed with a scope that the LED was blinking exactly as the measured SPI signal being generated by a different processor.  However, I don't see the result from the dma.  I don't see an interrupt happening, whether it was at the moment configured to blink an LED or if I set a breakproint with the debugger.  I made sure to call my ISR from inside the automatically generated ...ISR.c files  And most recently I don't see an LED output in response to interrupts occurring, having routed the interrupt outputs directly to my LED pins.  I've tentatively enabled all external interrupt types.  I've set the bit rate to 1000 kHz, ten times faster than the actual sclk, and I've set to internal clock to be sure.  The SPI slave just seems totally dead.

         

      What am I possibly doing wrong?

         

       

         

       

         

        #ifdef DO_SPIS_PSOC

         

       

         

      /* DMA Configuration for DMA_TX_S */

         

      #define DMA_TX_S_BYTES_PER_BURST       (1u)

         

      #define DMA_TX_S_REQUEST_PER_BURST     (1u)

         

      #define DMA_TX_S_SRC_BASE              (CYDEV_SRAM_BASE)

         

      #define DMA_TX_S_DST_BASE              (CYDEV_PERIPH_BASE)

         

       

         

      /* DMA Configuration for DMA_RX_S */

         

      #define DMA_RX_S_BYTES_PER_BURST       (1u)

         

      #define DMA_RX_S_REQUEST_PER_BURST     (1u)

         

      #define DMA_RX_S_SRC_BASE              (CYDEV_PERIPH_BASE)

         

      #define DMA_RX_S_DST_BASE              (CYDEV_SRAM_BASE)

         

       

         

      /* Variable declarations for DMA_Tx_S */

         

      uint8 S_TxChannel;

         

      uint8 S_TxTD[2u];

         

       

         

      /* Variable declarations for DMA_Rx_S */

         

      uint8 S_RxChannel;

         

      uint8 S_RxTD[2u];

         

       

         

      #define TX_TD_SIZE   128

         

      #define RX_TD_SIZE   128

         

      uint8 s_txBuffer[TX_TD_SIZE];

         

      uint8 s_rxBuffer[RX_TD_SIZE];

         

       

         

      /*******************************************************************************

         

      * Function Name: Dma_M_Tx_Configuration

         

      ********************************************************************************

         

      * Summary:

         

      *  Configures the DMA transfer for TX direction

         

      *   

         

      * Parameters:

         

      *  None.

         

      *

         

      * Return:

         

      *  None.

         

      *

         

      *******************************************************************************/

         

      void Dma_S_Tx_Configuration()

         

      {

         

      cystatus status;

         

       

         

         /* Init DMA, 1 byte bursts, each burst requires a request */ 

         

         S_TxChannel = DMA_TX_S_DmaInitialize(DMA_TX_S_BYTES_PER_BURST, DMA_TX_S_REQUEST_PER_BURST, 

         

                                             HI16(DMA_TX_S_SRC_BASE), HI16(DMA_TX_S_DST_BASE));

         

       

         

         S_TxTD[0u] = CyDmaTdAllocate();

         

         S_TxTD[1u] = CyDmaTdAllocate();

         

       

         

         /* Configure this Td chain as follows:

         

         *  - The TD is looping on itself

         

         *  - Increment the source address, but not the destination address   

         

         */

         

         status = CyDmaTdSetConfiguration(S_TxTD[0u], 7u, S_TxTD[1u], TD_INC_SRC_ADR);

         

      if (CYRET_SUCCESS != status) goto FAIL_Dma_S_Tx_Configuration;

         

         status = CyDmaTdSetConfiguration(S_TxTD[1u], 1u, S_TxTD[1u], 0u);

         

      if (CYRET_SUCCESS != status) goto FAIL_Dma_S_Tx_Configuration;

         

         

         

         /* From the memory to the SPIS */

         

         #if(CY_PSOC3_ES2 || CY_PSOC5_ES1)

         

             status = CyDmaTdSetAddress(S_TxTD[0u], LO16((uint32)s_txBuffer), LO16((uint32)SPIS_PSOC_BSPIS_es2_SPISlave_sR8_DpMISO_u0__F0_REG));

         

      if (CYRET_SUCCESS != status) goto FAIL_Dma_S_Tx_Configuration;

         

         #else

         

             status = CyDmaTdSetAddress(S_TxTD[0u], LO16((uint32)s_txBuffer), LO16((uint32)SPIS_PSOC_BSPIS_es3_SPISlave_sR8_Dp_u0__F0_REG));

         

      if (CYRET_SUCCESS != status) goto FAIL_Dma_S_Tx_Configuration;

         

         #endif    

         

         status = CyDmaTdSetAddress(S_TxTD[1u], LO16((uint32)s_txBuffer), LO16((uint32)s_txBuffer));

         

      if (CYRET_SUCCESS != status) goto FAIL_Dma_S_Tx_Configuration;

         

         /* Associate the TD with the channel */

         

         status = CyDmaChSetInitialTd(S_TxChannel, S_TxTD[0u]);

         

      if (CYRET_SUCCESS != status) goto FAIL_Dma_S_Tx_Configuration;

         

      return;

         

       

         

      FAIL_Dma_S_Tx_Configuration:

         

      UART_UPSTRM_PutString("SPIS_PSOC Dma_S_Tx_Configuration FAILED\r\n");

         

      }    

         

       

         

       

         

      /*******************************************************************************

         

      * Function Name: Dma_S_Rx_Configuration

         

      ********************************************************************************

         

      * Summary:

         

      *  Configures the DMA transfer for RX direction

         

      *   

         

      * Parameters:

         

      *  None.

         

      *

         

      * Return:

         

      *  None.

         

      *

         

      *******************************************************************************/

         

      void Dma_S_Rx_Configuration()

         

         

      cystatus status;

         

       

         

         /* Init DMA, 1 byte bursts, each burst requires a request */ 

         

         S_RxChannel = DMA_RX_S_DmaInitialize(DMA_RX_S_BYTES_PER_BURST, DMA_RX_S_REQUEST_PER_BURST,

         

                                          HI16(DMA_RX_S_SRC_BASE), HI16(DMA_RX_S_DST_BASE));

         

       

         

         S_RxTD[0u] = CyDmaTdAllocate();

         

         S_RxTD[1u] = CyDmaTdAllocate();

         

         /* Configure this Td as follows:

         

         *  - The TD is looping on itself

         

         *  - Increment the destination address, but not the source address

         

         */

         

         status = CyDmaTdSetConfiguration(S_RxTD[0u], 8u, S_RxTD[1u], TD_INC_DST_ADR);

         

      if (CYRET_SUCCESS != status) goto FAIL_Dma_S_Rx_Configuration;

         

         status = CyDmaTdSetConfiguration(S_RxTD[1u], 1u, S_RxTD[1u], 0u);

         

      if (CYRET_SUCCESS != status) goto FAIL_Dma_S_Rx_Configuration;

         

       

         

         /* From the SPIS to the memory */

         

         #if(CY_PSOC3_ES2 || CY_PSOC5_ES1)

         

             status = CyDmaTdSetAddress(S_RxTD[0u], LO16((uint32)SPIS_PSOC_BSPIS_es2_SPISlave_sR8_DpMOSI_u0__F0_REG), LO16((uint32)s_rxBuffer));

         

      if (CYRET_SUCCESS != status) goto FAIL_Dma_S_Rx_Configuration;

         

         #else

         

          status = CyDmaTdSetAddress(S_RxTD[0u], LO16((uint32)SPIS_PSOC_BSPIS_es3_SPISlave_sR8_Dp_u0__F1_REG), LO16((uint32)s_rxBuffer));

         

      if (CYRET_SUCCESS != status) goto FAIL_Dma_S_Rx_Configuration;

         

         #endif

         

         status = CyDmaTdSetAddress(S_RxTD[1u], LO16((uint32)s_rxBuffer), LO16((uint32)s_rxBuffer));

         

      if (CYRET_SUCCESS != status) goto FAIL_Dma_S_Rx_Configuration;

         

         /* Associate the TD with the channel */

         

         status = CyDmaChSetInitialTd(S_RxChannel, S_RxTD[0u]);

         

      if (CYRET_SUCCESS != status) goto FAIL_Dma_S_Rx_Configuration;

         

      return;

         

       

         

      FAIL_Dma_S_Rx_Configuration:

         

      UART_UPSTRM_PutString("SPIS_PSOC Dma_S_Rx_Configuration FAILED\r\n");

         

      }

         

       

         

      void SPIS_PSOC_RX_ISR(void)

         

      {

         

      ToggleDebugA(); // Toggle RED LED

         

      SPIS_PSOC_RX_ISR_ClearPending();

         

      }

         

       

         

      void SPIS_PSOC_TX_ISR(void)

         

      {

         

      ToggleDebugA(); // Toggle RED LED

         

      SPIS_PSOC_TX_ISR_ClearPending();

         

      }

         

       

         

      void init_spis_psoc()

         

      {

         

      PSOC_SPI_MISO_PIN_SetDriveMode(PSOC_SPI_MISO_PIN_DM_STRONG); // Make strong output

         

      PSOC_SPI_MOSI_PIN_SetDriveMode(PSOC_SPI_MOSI_PIN_DM_DIG_HIZ);

         

      PSOC_SPI_CLK_SetDriveMode(PSOC_SPI_CLK_DM_DIG_HIZ);

         

      nCS_PSOC_PIN_SetDriveMode(nCS_PSOC_PIN_DM_DIG_HIZ);

         

       

         

      SPIS_PSOC_RX_ISR_Start();

         

      SPIS_PSOC_TX_ISR_Start();

         

       

         

      Dma_S_Tx_Configuration();

         

         Dma_S_Rx_Configuration();

         

         CyDmaChEnable(S_TxChannel, 1u);

         

         CyDmaChEnable(S_RxChannel, 1u);

         

       

         

      SPIS_PSOC_Start();

         

       

         

      UART_UPSTRM_PutString("SPIS_PSOC initialized\r\n");

         

       

         

      }

         

      #endif

         
              
        • 1. Re: Trouble with SPI Slave
          user_1377889

          Can you post your complete project, so that we all can have a look at all of your settings? To do so, use
          Creator->File->Create Workspace Bundle (minimal)
          and attach the resulting file.
           

             

          Is there any special reason why you stick to Creator 2.2? We are now at version 3.1 and there have been corrections of some components since.


          Bob
           

          • 2. Re: Trouble with SPI Slave
            helmut.forren

             Bob,

               

            Thanks very much for helping.  I am not allowed to post the complete project, as it includes company confidential information.  Regarding PSOC Creator 2.2, I do generally stick with what works in my IT life, finding so many bugs in new stuff.  I will consider a newer version, but surely it's not the version that's the problem here.

               

            I understand completely wanting to see everything, but it's not possible.  Can we please move forward with the information that I have provided.  The system works otherwise, in other places and other ways.  Can you think of a place where a germain problem may exist outside of the information I already provided?  If so, I can both check that and provide it.

               

            Thanks VERY much for your assistance and understanding.  I recognize your name.  You've helped me before.  Thanks even more.

               

            -Helmut

            • 3. Re: Trouble with SPI Slave
              helmut.forren

              Bob,

                 

              1) Can I install Creator 3.1 and not destroy my working Creator 2.2 install?

                 

              2) I modified the cypress example project and have a similar problem.  The problem is obviously my understanding of how the SPI Slave component works.

                 

              I've attached a zip of this project.

                 

              I have a custom board with no LCD display.  The board is "solid".  It has a UART output that I use, as well as a red and green LED.  For simplicity's sake, I've modified this example to use only the two LEDs.  Any other board one might try to run this on ought to at least have two digital output opportunities, if not with LEDs on them then at least such that a scope can watch them.

                 

              The attached example has two toggle flip flops driving the LEDs.  The red led is toggled whenever the incoming SS has the appropriate edge.  This works in my test case, proving the design concept of the TFF and output pin.  The green led is supposed to toggle every time the rx_interrupt has the appropriate edge.  This green led does not toggle in my case.  I believe it should

                 

              So obviously, I'm missing something.  Is the rx_interrupt output not compatible with the TFF clk input?  Or is the rx_interrupt not happening because the SPI slave is never doing what it needs to do for this to happen?  The original sample was a useless one-shot deal.  So I enhanced its empty loop a little.  I doubt it's needed, but I accidentally put the SPIS_Start() and while inside the loop once while testing.  It seemed to run "in sync" with my incoming once-per-second SS.  So I tried it inside the loop here.  In an earlier version, an LED did blink once per second.  I may go back to that for testing, because it did seem that the while waited until the next SS (and SPI completion).  But with DMA, this thing ought to behave asynchronously (outside of doing something in the main() loop.

                 

              I guess my big question is why does the green LED not toggle in response to rx_interrupt, which should be happening after SS and the red LED toggles?

                 

              My incoming data is 60 something 8-bit bytes under a single SS active-low pulse, with a bit time of about 10.5us (~95kHz).