This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC3235SF: Porting from CC3200 to CC3235SF with SPI and uDMA and FreeRTOS

Part Number: CC3235SF
Other Parts Discussed in Thread: CC3200, SYSCONFIG

Hello,
I am trying to port a working project that uses SPI and uDMA in Ping-Pong mode from a cc3200 to a cc3235sf.
The example with the cc3235sf should use FreeRTOS. So far, there have been significant problems with porting.
The microcontroller receives data via the SPI interface and should trigger an interrupt as soon as the buffer is full.
As I see it, this interrupt is never triggered. Is there an example where SPI is used with uDMA, CC3235SF and FreeRTOS? I configure the SPI driver via Sysconfig.

In the old example, the vector table is defined in a file "startup_ccs.c" file directly in the application folder, in the new example with FreeRTOS, this table appear to be defined in the file
"startup_cc32xxCC32xx_css.c". Could the cause lie here? It would be nice if someone could bring light into the darkness for me.

  • Instead of porting, can you use one of the examples for SPI from the CC32XX SDK?

  • Hi Sabeeh,

    thank you for your reply. I am trying to transfer existing, working code to the new system so i can not just use the Ti-Example . In the old code, the ping-pong transfer is configured in the source code via udma_if.c. With the new building block, this no longer works. The ping pong mode seems to be configured via the Ti driver SPICC32XXDMA.h. In the SPI example, however, this is never addressed directly, SPICC32XXDMA_init(SPI_Handle handle) is not called directly. Do I understand correctly that ping-pong mode is always used? How do I transfer data continuously? With the command "transfer"?

    In the old code i just call this function. How is this done with SPICC32XXDMA.h?

    UDMA_transfer old code:

    void UDMASetupPingPongTransfer(unsigned long ulChannel, void *pvSrcBuf1,
                                  void *pvDstBuf1, void *pvSrcBuf2,
                                  void *pvDstBuf2, unsigned long size)
    {
        UDMASetupTransfer(ulChannel, UDMA_MODE_PINGPONG, size, UDMA_SIZE_8,
                         UDMA_ARB_8, pvSrcBuf1, UDMA_SRC_INC_8,
                         pvDstBuf1, UDMA_DST_INC_8);
    
        UDMASetupTransfer(ulChannel|UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, size,
                          UDMA_SIZE_8, UDMA_ARB_8, pvSrcBuf2, UDMA_SRC_INC_8,
                          pvDstBuf2, UDMA_DST_INC_8);

    ...

    void UDMASetupTransfer(unsigned long ulChannel, unsigned long ulMode,
                                unsigned long ulItemCount, unsigned long ulItemSize,
                                unsigned long ulArbSize, void *pvSrcBuf,
                                unsigned long ulSrcInc, void *pvDstBuf,
                                unsigned long ulDstInc)
    {
        MAP_uDMAChannelControlSet(ulChannel, ulItemSize | ulSrcInc | ulDstInc | ulArbSize);
        MAP_uDMAChannelAttributeEnable(ulChannel,UDMA_ATTR_USEBURST);
        MAP_uDMAChannelTransferSet(ulChannel, ulMode, pvSrcBuf, pvDstBuf, ulItemCount);
        MAP_uDMAChannelEnable(ulChannel);
    }

    thank you.

  • With SPICC32XXDMA.h, ping pong DMA is not being set up. Therefore transferring code as is will not work. This is why I suggest using SPI based off of the example in the CC32XX SDK. 

  • I started to include the SPI example SPISlave in my code. However, in this example, only a message with a length of 30 is received. In my code, a much larger amount of data is to be transmitted. I am a beginner when it comes to this UDMA transmission. With the example transferred to my custom board, I can transfer data with a word length of 128 over SPI and write it to an array. The header file SPICC32XXDMA.h says:
    /* ## DMA and Queueing * This driver utilizes DMA channels in ping pong mode
     (see device TRM) in * order to overcome the 1024 item DMA channel limit. 
     This means the driver * can execute multi kilo-item transactions without 
     pausing to reconfigure the * DMA and causing gaps in transmission.  */
     
     
    So how is this done? How can i transfer a large amount of data via the SPI to an buffer. The buffer will then be send via a weboscket-connection to an web page. 
    Do you have another example where I can understand the behavior of the SPI and uDMA interface? Which Ti example do you mean? SPI slave/master? SPICC32XDMA.h is never included in these examples.
    I would appreciate it if you could help me with this problem.
  • Hi Vignesh, 

    In these examples, ti/drivers/SPI.h then includes the SPICC32XX.h file. SPISlave and SPImaster are simply examples to show some traffic. If you want to send more traffic you can simply change the example or use the same principles in your own application.

    Have you read through our documentation regarding the SPI.h? https://dev.ti.com/tirex/explore/node?node=AIQLpsWAlAhNbRw7tZeAww__fc2e6sr__LATEST 

  • Hello Sabeeh,                                                                                                                                                                                                                                            thank you for your reply. I have now implemented the SPI as shown in the examples. In my program a task is started from which the SPI is initialized and the transfer is started. With this setup I try to transfer an image delivered by an FPGA via the SPI. The FPGA sends 8 byte words 64 times in a row before the FPGA briefly locks its SPI for a short perod of time. In fact, I manage to transfer data, but this data seems to be incorrect. When I evaluate the transmitted data, I can see that although the first part of the header of the jpeg is transferred, the subsequent data is not correct. I suspect that the SPI does not transfer the data correctly and the parameters are set incorrectly.
    In our previous working design, we ran the transmission endlessly in ping-pong mode until a certain number of bytes were reached. With our current code, the transfer function is called until this certain number of frames has been reached.                  
    static void CamControllerInit()
    {
    
    
       MAP_PRCMPeripheralReset(PRCM_GSPI);
    
       SPI_Params      spiParams;
    
       // deafult-Werte der SPI laden
       SPI_Params_init(&spiParams);
    
       //spiParams.bitRate = SPI_IF_BIT_RATE;
       spiParams.mode = SPI_SLAVE;
       spiParams.dataSize = 8;
    
       slaveSpi = SPI_open(CONFIG_SPI_0, &spiParams);
    
       if (slaveSpi == NULL)
       {
           Display_printf(display, 0, 0, "Error initializing slave SPI\n");
           while (1);
       }
    
       else
       {
           Display_printf(display, 0, 0, "Slave SPI initialized\n");
       }
    
    }
    
    
    //*****************************************************************************
    static unsigned short CaptureImage(char** WriteBuffer)
    {
        memset(g_image.g_image_buffer,0xF80F,sizeof(g_image.g_image_buffer));    // fill image array with value 0f
        p_buffer = &(g_image.g_image_buffer[0]);                                 // p_buffer gets address from img array
    
    
    
            bool            transferOK;
            SPI_Transaction transaction;
    
            g_frame_size_in_bytes = 0;
    
    GPIO_IF_Set(GPIO3, g_uiCC3200_RDY_I, g_ucCC3200_RDY_I,true); // fpga activate
    
    
    while(g_frame_size_in_bytes < 40000) {
    
                // p_buffer++;
    
                // transaction.count = TOTAL_DMA_ELEMENTS;
                transaction.count = 64; // 8*8 = 64 -- 5000 * 8 = 40.000 8 bit frames übertragen
                transaction.txBuf = NULL;
                transaction.rxBuf = (void *) p_buffer;                  // in den P_Buffer schreiben
    
              transferOK = SPI_transfer(slaveSpi, &transaction);
    
              if (transferOK)
               {
    
             //   Display_printf(display, 0, 0, "Transfer ok");
                p_buffer += 64;
                g_frame_size_in_bytes += (32*sizeof(unsigned char));
    
              }
    
               else
              {
                    Display_printf(display, 0, 0, "Unsuccessful slave SPI transfer");
                 // break;
               }
    
           }
    
    //    SPI_transferCancel(slaveSpi);
        GPIO_IF_Set(GPIO3, g_uiCC3200_RDY_I, g_ucCC3200_RDY_I,false); // fpga deactivate
    
        // Imagebuffer als hexwerte ausgeben
         printImageBuffer();
    
    
    
      *WriteBuffer = &(g_image.g_image_buffer[0]); // passing address of image array to the pointer
    
      size_t testarraysize = sizeof(testarray1)/sizeof(testarray1[0]);
    
    // *WriteBuffer = &(testarray1[0]); // passing address of image array to the pointer
    
    
     //g_frame_size_in_bytes = (sizeof(unsigned char) * testarraysize);
     Display_printf(display, 0, 0, "gframesizeinbytes %d\n", g_frame_size_in_bytes);
    
       return(g_frame_size_in_bytes);
    
    }
  • Hello Vignesh, 

    I don't see any references in your CamControllerInit function to PHAx and POLy. This would explain why data is being received incorrectly. 

  • Hi Sabeeh,

    as I understand it, these parameters are set in the function SPI_Params_init() in the file SPI.h. Initial value SPI_POL0_PHA0 (as with our old version) 
     *  Defaults values are:
     *  * SPI_Params.transferMode        = #SPI_MODE_BLOCKING
     *  * SPI_Params.transferTimeout     = #SPI_WAIT_FOREVER
     *  * SPI_Params.transferCallbackFxn = NULL
     *  * SPI_Params.mode                = #SPI_MASTER
     *  * SPI_Params.bitRate             = 1000000 (Hz)
     *  * SPI_Params.dataSize            = 8 (bits)
     *  * SPI_Params.frameFormat         = #SPI_POL0_PHA0
     */
    extern void SPI_Params_init(SPI_Params *params);
  • Hello,

    meanwhile I get image data transmitted via the SPI interface and can also send it to my html application via Websocket. Nevertheless, there is a high latency in transmission and image interference occurs. It is still not quite clear to me how SPI.h and SPICC32XMA.c implement the uDMA transfer even from the examples you do not get really smart.

    I understand that the data size is interpreted, for example, as uint8_t. But how do I make sure that the data is address aligned or is this done internally? Can anyone give me inspiration on how to improve the transfer of the images (jpeg compressed)?

    Currently I transfer 40,000 frames via SPI write them to a buffer and transfer this buffer packet by packet via my web socket connection.
    Currently the SPI transfer (callback mode and blocked with semaphore) as well as the web socket transfer takes place in one and the same task. Maybe this is not optimal and the websocket transfer should be in its own task. My idea is to block the SPI and the websocket task alternately via TaskNotifications. Or does someone perhaps have a idea on how to get a better grip on the problem of high latency and faulty image transmission?

  • Hi Vignesh,

    The DMA is used in the SPI example. How are managing the communication between your FPGA and CC32xx? If you are experiencing latency issues, then maybe you need to implement some sort of handshake. You can do this by using two GPIOs from the FPGA to the CC32xx. One can be a "ready to send" flag, and the other is "clear to send". 

    How many bytes are being corrupted? Is the data on the data lines itself corrupted or just the receiving buffer on the CC32xx? Maybe you need to validate the bus with either another device or an oscilloscope. Sounds like you will probably need a CRC to validate the entirety of the image. 

    Furthermore, it sounds like the issue may be related to the FPGA. Is this not the case? 

  • Hi Sabeeh,
    sorry for my late answer I have been busy elsewhere for the last 2 weeks.

    The FPGA is activated by the CC32xx via a low pulse and then starts sending the image data via SPI.
    The data sent by the FPGA should be fine, as we use the same design with the CC3200 in our old setup.
    The data coming from the FPGA is written to a buffer, which is then sent via Websocket.
    I have now packed the SPI transfer and the websocket transfer into individual tasks.
    A TaskNotification switches back and forth between these two tasks. For the data transfer from the FPGA to the SPI I use the command SPI_transfer and a transaction.count of 40000.
    In the old design, 64 byte ping and 64 byte pong were sent via udma. This was done until the cancellation condition of 40,000 bytes was reached.
    As already discussed, the transmission via UDMA of the cc32xx is realized via SPICC32XXDMA.h and I assume that with SPI_transfer the same thing happens as in our old design.
    Another difference is that in our old design no FreeRTOS was used and there was only one task for image transfer and websocket transmission.
    Do you have any other ideas?

  • Hi Vignesh, 

    So ping pong transfer is not available with the TI driver for CC32xx. The hardware does support ping pong transfer, however it is just not supported by software in the SPI TI driver. But the DMA is still used. 

    Thus, your transactions will take longer compared to CC31xx. For experimentation sake, I would suggest trying the transaction on a single task or even noRTOS to validate the image transfer between FPGA/CC32xx.Although this might sacrifice latency, you can atleast verify the "robustness" of the system. 

    What I am having trouble understanding is that you mention there is image interference. Can you understand if this is caused by the SPI transfer? If so, can you confirm that the SPI phase and polarity matches that of the FPGA? Is the image interference caused by the wifi transmission?

  • Hi Sabeeh,

    this is not good news. We have switched to the CC32xx to increase the data throughput with the 5GHz. If we are now slowing down with data transmission via SPI than before, that is not very good for us. I don't quite understand the driver doesn't use ping-pong but DMA is used? Is it then necessary for us to write our own driver? I now strongly suspect that the SPI is the main problem.

    I have made a test:i have read the buffer which is filled by the SPI via Hterm. Then I encoded the hex values I received from hterm with a Base64 converter. I have shown the encoded string in an html as an image. This image is incorrect and incomplete. I attach the picture to this post. That means for me the websocket transmission is not the problem. It must be the SPI. Data must be lost somewhere during transmission. The polarity and phase (both mode 0) I took over from the old design, the FPGA has not changed. I tested all the modes. I get a result at mode 00 and at mode 11 at the other modes nothing happens.

    The current status of the project is: data transmission takes place with extremely high latency and partially distorted images. I suspect the image data coming from the SPI is partly correct and partly damaged. Since it worked with the old building block, in my opinion it has to put on the other use of the udma and the interface.

    Thank you Sabeeh for your help and input.

    This is the image which i get directly from the SPI(decoded by hand). I also see this kind of error in my webapp.

    decoded by Hand (Hterm, hex, base64)

    This is an example of an broken image which i recieve in my webapp (send over websocket) corruptness differs from time to time