5 Replies Latest reply on Mar 1, 2019 2:08 PM by DaHu_285096

    Code branching to CyPmHviRestore

    DaHu_285096

      I am currently working on a project that controls an external device using SPI.

       

      When I attempt to write data to some locations in the external SPI device and read them back, the program locks up in the read routine by jumping to CyPmHviLviRestore()?

       

      Could this be a pointer issue? This is my calling code

       

      void TestSpi(void){

        uint8 dataA[20] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};

        uint8 dataB[20];

       

       

        dwt_writetodevice(0x21,0, 20,dataA);

        dwt_readfromdevice(0x21,0,20,dataB);

       

       

        asm("nop");

      }

       

      The code doing the work is here

       

      int readfromspi(uint16 headerLength, const uint8 *headerBuffer, uint32 readlength, uint8 *readBuffer)

      {

          int i=0;

          volatile uint8 rxbuf[4];

         

          CS_Write(0);

       

       

          for(i=0; i<headerLength; i++)

          {

          SPIM_WriteTxData(headerBuffer[i]);  //write command to device

              while(!(SPIM_ReadTxStatus() & SPIM_STS_SPI_DONE)){};  //wait till sent

              readBuffer[i] = SPIM_ReadRxData() ; //read any received data

          }

       

       

          for(i=0; i<(int)readlength; i++)

          {

              SPIM_WriteTxData(0x00);  //dummy write for each byte to read

              while(!(SPIM_ReadTxStatus() & SPIM_STS_SPI_DONE)){};  //wait till each byte done

              readBuffer[i] = SPIM_ReadRxData();

              rxbuf[i] = readBuffer[i];

          }

       

       

          CS_Write(1);

       

       

          return 0;

      }

       

      Thanks

        • 1. Re: Code branching to CyPmHviRestore
          himam_31

          Hello David,

           

          Can you please attach the complete Creator project, so that we can review the project. Also can you please let us know which device exactly is acting as the slave?

           

          Thanks,

          Hima

          • 2. Re: Code branching to CyPmHviRestore
            DaHu_285096

            Hima,

             

            Project attached.

             

            Device is Decawave DWM1000 ultra wide band rf module.

             

            The spi functions are in deca_spi.

             

            The problem is the time it takes to execute from line 75 in main.c -> if (status_reg & SYS_STATUS_RXFCG) until transmit is too long and causes timeout that prevents transmission.

             

            This code was ported from an STM32 based project. They also have an arduino version that runs on a relatively slow processor but they manage to get spi up around 20 MHz.

             

            The company has an app note regarding the spi that is also attached.

            • 3. Re: Code branching to CyPmHviRestore
              BragadeeshV_41

              Hi DaHu_285096,

               

              In your code, in the following line,

               

              LINE 80:  if (frame_len <= RX_BUFFER_LEN)  //if correct number of bytes received then process data

                               {

                                   dwt_readrxdata(rx_buffer, frame_len, 0);

                               }

               

              You have defined RX_BUFFER_LEN to be 1024. So I assume you can receive up to 1024 bytes of data (or maybe less). But you have defined  static uint8 rx_buffer[12]; as 12 bytes. Also inside the readfromspi() you have defined volatile uint8 rxbuf[4]; as 4 bytes. When I modified these two buffers to 1024 bytes, this error did not occur.

               

              Since we don't have an actual slave that can respond as per your slave, this may or may not be the problem. Please check it from your actual setup and let us know.

               

              Also I noticed the following in your code. In deca_spi.c, you have set the clock divider value as

               

              void spi_set_rate_low (void)

              {

                 SPI_Clock_SetDividerValue(9); //48 MHz Master / 9 = 5.33 MHz Clock = 2.66MHz bit rate

              }

               

               

              void spi_set_rate_high (void)

              {

                  SPI_Clock_SetDividerValue(2);  //48 MHz Master / 2 = 24 MHz Clock = 12MHz bit rate

              }

               

              But please note that the value given in the function is not the actual clkDivider. It is ClkDivider + 1 . Say you need to divide the clock by 2 (48Mhz/2 = 24 Mhz), you need to set the SetDividerValue as 1 and not 2. Please take this into account.

               

              Regards,

              Bragadeesh

              • 4. Re: Code branching to CyPmHviRestore
                DaHu_285096

                Thanks Bragadeesh,

                I really appreciate you have taken the time to dig into the code and find this.

                The code was written by third party and I am porting it to PSOC.

                 

                Line 80 does not make sense, it should be if number of bytes >= RX_BUF_LEN (which is 12 bytes) because that line will always only process rx_buffer and should never have 1024 bytes.

                 

                I have changed the spi routine to use the DMA (adopted from another forum post) now and managed to get rid of the inter-digit gaps. (snippet below), Will also take a look at clock divider, I did not realize the actual divider value was supplied value + 1.

                 

                The code below looks good on logic analyzer but in the main look it sometimes gets wrong values from spi when running at 16MHz. I thing the hardware is causing this because I have quite long wires dangling around between the PSOC 5 kit and the device. I will lay up a PCB with short tracks and test again.I am able to supply the slave device if anyone is willing to help run through and check the code with device connected.

                 

                int readfromspi(uint16 headerLength, const uint8 *headerBuffer, uint32 readLength, uint8 *readBuffer)

                {

                    const uint8_t DMA_REQUEST_PER_BURST = 1;

                    const uint8_t DMA_BYTES_PER_BURST = 1;

                    uint8_t DMA_Rx_Chan = 0;

                    uint8_t DMA_Tx_Chan = 0;

                    uint8_t DMA_Rx_TD[1] = {0};

                    uint8_t DMA_Tx_TD[1] = {0};

                    uint8 size;

                    uint8 tx_data[50];

                    uint8 rx_data[50];

                   

                    size = headerLength + readLength;

                    memcpy(tx_data,headerBuffer, headerLength);

                    memcpy(tx_data + headerLength, readBuffer, readLength);

                   

                    // Allocate DMA Channels

                    DMA_Rx_Chan = DMA_Rx_DmaInitialize(DMA_BYTES_PER_BURST, DMA_REQUEST_PER_BURST,

                                                        HI16(CYDEV_PERIPH_BASE), HI16(CYDEV_SRAM_BASE));

                    DMA_Tx_Chan = DMA_Tx_DmaInitialize(DMA_BYTES_PER_BURST, DMA_REQUEST_PER_BURST,

                                                        HI16(CYDEV_SRAM_BASE), HI16(CYDEV_PERIPH_BASE));

                    // Allocate TDs

                    DMA_Rx_TD[0] = CyDmaTdAllocate();

                    DMA_Tx_TD[0] = CyDmaTdAllocate();

                    CyDmaTdSetConfiguration(DMA_Rx_TD[0], size, CY_DMA_DISABLE_TD, CY_DMA_TD_INC_DST_ADR);

                    CyDmaTdSetConfiguration(DMA_Tx_TD[0], size, CY_DMA_DISABLE_TD, CY_DMA_TD_INC_SRC_ADR);

                    CyDmaTdSetAddress(DMA_Rx_TD[0], LO16((uint32)SPIM_RXDATA_PTR), LO16((uint32)&rx_data[0]));

                    CyDmaTdSetAddress(DMA_Tx_TD[0], LO16((uint32)&tx_data[0]), LO16((uint32)SPIM_TXDATA_PTR));

                    CyDmaChSetInitialTd(DMA_Rx_Chan, DMA_Rx_TD[0]);

                    CyDmaChSetInitialTd(DMA_Tx_Chan, DMA_Tx_TD[0]);

                 

                 

                    // enable the DMAs

                    CyDmaChEnable(DMA_Rx_Chan, 1);

                    CyDmaChEnable(DMA_Tx_Chan, 1);

                 

                 

                    while(0 == (SPIM_ReadTxStatus() & SPIM_STS_SPI_DONE)) {}

                   

                    /* Freeing the DMA Channel and TDs */

                    CyDmaChDisable(DMA_Rx_Chan);

                    CyDmaChDisable(DMA_Tx_Chan);

                    CyDmaTdFree(DMA_Rx_TD[0]);

                    CyDmaTdFree(DMA_Tx_TD[0]);

                   

                     memcpy(readBuffer,rx_data+headerLength,size - headerLength);  

                   

                    return 0;

                }

                • 5. Re: Code branching to CyPmHviRestore
                  DaHu_285096

                  PS. Not sure why they use 16 bit for header length and 32 bit for body. I think the max number of bytes in any transfer would be less than 100. Te code seems to be all over the place.