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.

TMS320C6678: Reading data from external ADC using SPI

Part Number: TMS320C6678

Hi,

I am trying to read data from an external FPGA which is interfaced with a ADC. I am using evmc66x_spi.c (Processor SDK 5.2) for calling SPI routines. I have pasted my main code below. I have initialized the SPI core (for CS1 ). In this code I am trying to read 16 bit data from FPGA (initialized as Slave). I am using infinite for loop so that I can continuously receive data from FPGA. When I run the code, the status flag in the FPGA get high but the C6678 does not read any values in the buffer and when I pause the code anytime, it is stuck at this while loop (line 42 in below code) in spi_xfer() function in evmc66x_spi.c file.

spi_xfer
(
    uint32_t              nbytes,
    uint8_t*              data_out,
    uint8_t*              data_in,
    Bool                terminate
)
{
    uint32_t          i, buf_reg;
    uint8_t*          tx_ptr = data_out;
    uint8_t*          rx_ptr = data_in;
    
    
    /* Clear out any pending read data */
    SPI_SPIBUF;
    
    for (i = 0; i < nbytes; i++) 
    {
        /* Wait untill TX buffer is not full */
        while( SPI_SPIBUF & CSL_SPI_SPIBUF_TXFULL_MASK );
        
        /* Set the TX data to SPIDAT1 */
        data1_reg_val &= ~0xFFFF;
        if(tx_ptr) 
        {
            data1_reg_val |= *tx_ptr & 0xFF;
            tx_ptr++;
        }
        
        /* Write to SPIDAT1 */
        if((i == (nbytes -1)) && (terminate)) 
        {
            /* Release the CS at the end of the transfer when terminate flag is TRUE */
            SPI_SPIDAT1 = data1_reg_val & ~(CSL_SPI_SPIDAT1_CSHOLD_ENABLE << CSL_SPI_SPIDAT1_CSHOLD_SHIFT);
        } else 
        {
            SPI_SPIDAT1 = data1_reg_val;
        }
        
        
        /* Read SPIBUF, wait untill the RX buffer is not empty */
        while ( SPI_SPIBUF & ( CSL_SPI_SPIBUF_RXEMPTY_MASK ) );
        
        /* Read one byte data */
        buf_reg = SPI_SPIBUF;
        if(rx_ptr) 
        {
            *rx_ptr = buf_reg & 0xFF;
            rx_ptr++;
        }
    }
    
    return SPI_EOK;
    
}

The main code:

uint32_t status;
uint32_t status1;

uint8_t *in1 = 0;
uint8_t *in2 = 0;
int i;
    spi_claim(1,1000000);

    for(i=0;i>-1;i++)
    {
        status = spi_xfer(nbytes,NULL,in1,FALSE);
        status1 = spi_xfer(nbytes,NULL,in2,TRUE);

        rxBuf[i%100] = (int)in1 + ((int)in2)*256;
    }

    spi_release();

 

Can anyone please help me find any mistake in the code?

Regards,

  • I did some changes which includes adding the PowerUpDomains() function to enable the clock. I also tried using     "CSL_PSC_setModuleNextState (CSL_PSC_LPSC_EMIF25_SPI,  PSC_MODSTATE_ENABLE)" function to enable SPI clock domain in main file. But the code is still unable to return 1 in "CSL_semAcquireDirect" function due to which I can't see the 1MHz SPI clock on DSO. I am attaching my complete main.c file here. Can anyone please help to resolve this problem?

    #include <vect.h>
    #include <stdio.h>
    #include <stdint.h>
    #include <string.h>
    #include <math.h>
    //#include <ti/dsplib/dsplib.h>
    //#include "gen_twiddle_fft32x32.h"
    /* BIOS Header files */
    #include <ti/sysbios/BIOS.h>
    #include "resource_mgr.h"
    #include "platform.h"
    #include "evmc66x_spi.h"
    #include <cslr_spi.h>
    #include "csl_psc.h"
    #include "csl_pscAux.h"
    #include "cslr_sem.h"
    /* SPI Header files */
    #include <ti/drv/spi/SPI.h>
    #if defined(SOC_K2H) || defined(SOC_K2K) || defined(SOC_K2E) || defined(SOC_K2L) || defined(SOC_K2G) || defined(SOC_C6678) || defined(SOC_C6657) || defined(SOC_OMAPL137) || defined(SOC_OMAPL138)
    #include <ti/drv/spi/src/v0/SPI_v0.h>
    #endif
    #include <ti/drv/spi/soc/SPI_soc.h>
    #include <ti/drv/spi/test/src/SPI_log.h>
    #include <ti/drv/spi/test/src/SPI_test.h>
    
    /* Board Header files */
    #include <ti/board/board.h>
    #include <ti/board/src/flash/include/board_flash.h>
    
    #define nbytes 0x00000002
    
    /* Buffer containing the received data */
    uint16_t rxBuf[NUM_OF_SAMPLES];
    uint16_t txBuf[NUM_OF_SAMPLES];
    uint16_t *ptr_tx = txBuf;
    //ptr_tx = &txBuf;
    uint16_t *ptr_rx = rxBuf;
    //ptr_rx = &rxBuf;
    
    uint32_t status;
    uint32_t status1;
    
    uint8_t *in1 = 0;
    uint8_t *in2 = 0;
    
    /* OSAL functions for Platform Library */
    uint8_t *Osal_platformMalloc (uint32_t num_bytes, uint32_t alignment)
    {
        return malloc(num_bytes);
    }
    
    void Osal_platformFree (uint8_t *dataPtr, uint32_t num_bytes)
    {
        /* Free up the memory */
        if (dataPtr)
        {
            free(dataPtr);
        }
    }
    void Osal_platformSpiCsEnter(void)
    {
        /* Get the hardware semaphore.
         *
         * Acquire Multi core CPPI synchronization lock
         */
        while ((CSL_semAcquireDirect (PLATFORM_SPI_HW_SEM)) == 0);
    
        return;
    }
    
    void Osal_platformSpiCsExit (void)
    {
        /* Release the hardware semaphore
         *
         * Release multi-core lock.
         */
        CSL_semReleaseSemaphore (PLATFORM_SPI_HW_SEM);
    
        return;
    }
    void PowerUpDomains (void);
    int main(void)
    {
        int i;
        CSL_PSC_setModuleNextState (CSL_PSC_LPSC_EMIF25_SPI,  PSC_MODSTATE_ENABLE);
        PowerUpDomains();
        spi_claim(1,1000000);
    
        for(i=0;i>-1;i++)
        {
            status = spi_xfer(nbytes,NULL,in1,FALSE);
            status1 = spi_xfer(nbytes,NULL,in2,TRUE);
    
            rxBuf[i%100] = (int)in1 + ((int)in2)*256;
        }
    
        spi_release();
    //    BIOS_start();
    //    return(0);
    }
    
    

  • Harshu,

    Please let us know if you are seeing the chip select go low and clock on the SPI pins when you run the code. Is there a reason why you have chosen to use platform library  instead of the SPI LLD driver.

    Also please indicate how you have connected the external FPGA and ADC to the SOC given the base EVM has the following SPI  configuration to connect to FPGA/flash.

    Regards,

    Rahul

  • I am not able to see any wave on clock and chip select was always high. I actually tried using the SPI driver functions. I tried to use the SPI example project which reads data from flash through SPI, but it was also not working.

    Actually, the ADC is interfaced with the external FPGA  DE0-nano ( used as a buffer), and then the FPGA is connected as slave to the SPI master of DSP board which is configured for 1 MHz clock. I have attached the SPI example project main file below. If you can tell, what I am doing wrong in this SPI driver functions, it would be great help. The below code doesnot return any boardhandle due to which code is not able to go forward. I am really confused about what to use. To me, the platform library evmc66x_spi.c file functions made some sense, so I started with that. But still I am not getting any result. If you can tell, what I am doing wrong in this SPI driver functions, it would be great help.

    /**
     *  \file   main_spi_flash_read_example.c
     *
     *  \brief  Example application main file. This application will read
     *          the data from flash through spi interface.
     *
     */
    
    /*
     * Copyright (C) 2015 - 2018 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.
     *
     */
    
    #ifndef BARE_METAL
    /* XDCtools Header files */
    #include <xdc/std.h>
    #include <xdc/cfg/global.h>
    #include <xdc/runtime/System.h>
    #include <vect.h>
    #include <stdio.h>
    #include <stdint.h>
    #include <math.h>
    #include <ti/dsplib/dsplib.h>
    #include "gen_twiddle_fft32x32.h"
    /* BIOS Header files */
    #include <ti/sysbios/BIOS.h>
    #endif
    
    /* SPI Header files */
    #include <ti/drv/spi/SPI.h>
    #if defined(SOC_K2H) || defined(SOC_K2K) || defined(SOC_K2E) || defined(SOC_K2L) || defined(SOC_K2G) || defined(SOC_C6678) || defined(SOC_C6657) || defined(SOC_OMAPL137) || defined(SOC_OMAPL138)
    #include <ti/drv/spi/src/v0/SPI_v0.h>
    #endif
    #include <ti/drv/spi/soc/SPI_soc.h>
    #include <ti/drv/spi/test/src/SPI_log.h>
    #include <ti/drv/spi/test/src/SPI_test.h>
    
    /* Board Header files */
    #include <ti/board/board.h>
    #include <ti/board/src/flash/include/board_flash.h>
    
    /**********************************************************************
     ************************** Macros ************************************
     **********************************************************************/
    
    /**********************************************************************
     ************************** Internal functions ************************
     **********************************************************************/
    
    /**********************************************************************
     ************************** Global Variables **************************
     **********************************************************************/
    #define NUM_OF_SAMPLES 100
    #define N 1024
    #define SCALE 32
    
    /* Buffer containing the received data */
    uint32_t rxBuf[NUM_OF_SAMPLES];
    float32_t buffer_in[NUM_OF_SAMPLES];
    /* transfer length */
    uint32_t transferLength;
    float32_t sig[NUM_OF_SAMPLES];
    float32_t wavelets[SCALE][2*NUM_OF_SAMPLES-1];
    float32_t exp_1,cos_1;
    static float32_t coefs[SCALE][NUM_OF_SAMPLES];
    int32_t index,scale_count,wavelet_gen,sc,dt,t_shift,l;
    /* ======================================================================== */
    /*  Kernel-specific alignments                                              */
    /* ======================================================================== */
    #pragma DATA_ALIGN(fft_in,  8);
    #pragma DATA_ALIGN(fft_twiddle,  8);
    #pragma DATA_ALIGN(fft_out,  8);
    
    int32_t fft_in [2*N];
    int32_t fft_twiddle [2*N];
    int32_t fft_out [2*N];
    int32_t fft_out_real [N];
    int32_t fft_out_imag [N];
    int32_t fft_out_mag[N];
    /*
     *  ======== Board_initSPI ========
     */
    void Board_initSPI(void)
    {
        Board_initCfg boardCfg;
    #if defined(SOC_K2H) || defined(SOC_K2K) || defined(SOC_K2E) || defined(SOC_K2L) || defined(SOC_K2G) || defined(SOC_C6678) || defined(SOC_C6657) || defined(SOC_OMAPL137) || defined(SOC_OMAPL138)
        SPI_v0_HWAttrs spi_cfg;
        Board_SoCInfo socInfo;
    
        /* Get the default SPI init configurations */
        SPI_socGetInitCfg(TEST_SPI_PORT, &spi_cfg);
    
        /* Update the SPI functional clock based on CPU clock*/
        Board_getSoCInfo(&socInfo);
        if(socInfo.sysClock != BOARD_SYS_CLK_DEFAULT)
        {
            spi_cfg.inputClkFreq = socInfo.sysClock/SPI_MODULE_CLOCK_DIVIDER;
        }
    
        /* Set the default SPI init configurations */
        SPI_socSetInitCfg(TEST_SPI_PORT, &spi_cfg);
        spi_cfg.csNum = 1;
        spi_cfg.pinMode = 1;
    #endif
    
    #if defined(evmK2E) || defined(evmC6678)
        boardCfg = BOARD_INIT_MODULE_CLOCK |
            BOARD_INIT_UART_STDIO;
    #else
        boardCfg = BOARD_INIT_PINMUX_CONFIG |
            BOARD_INIT_MODULE_CLOCK |
            BOARD_INIT_UART_STDIO;
    #endif
        Board_init(boardCfg);
    }
    
    void generate_wavelets(void)
    {
        for(scale_count=1;scale_count<=SCALE;scale_count++)
        {
            //for(wavelet_gen=-NUM_OF_SAMPLES+1;wavelet_gen<NUM_OF_SAMPLES;wavelet_gen++)
            for(wavelet_gen=0;wavelet_gen<NUM_OF_SAMPLES;wavelet_gen++)
            {
                exp_1 = exp((-1.0*wavelet_gen*wavelet_gen)/(2.0*scale_count*scale_count));
                cos_1 = cos(5*wavelet_gen/scale_count);
    
                if(wavelet_gen == 0)
                {
                    wavelets[scale_count-1][NUM_OF_SAMPLES-1] = exp_1*cos_1;
                }
                else
                {
                    wavelets[scale_count-1][NUM_OF_SAMPLES-1 + wavelet_gen] = exp_1*cos_1;
                    wavelets[scale_count-1][NUM_OF_SAMPLES-1 - wavelet_gen] = exp_1*cos_1;
                }
            }
        }
    }
    
    void DWT(void)
    {
        for(l = 0; l < 512; l++)
        {
           sig[l] =  (float32_t)buffer_in[l] * (3.3f/4096.0f);
        }
    
        for(sc=1;sc<=SCALE;sc++)  //for scaling
        {
            for(t_shift=0;t_shift<NUM_OF_SAMPLES;t_shift++) // time shifting
            {
                for(dt=0;dt<NUM_OF_SAMPLES;dt++) // for dot product
                {
                    coefs[sc-1][t_shift] += sig[dt]*wavelets[sc-1][NUM_OF_SAMPLES-t_shift+dt];
                }
            }
        }
    }
    /*
     *  ======== test function ========
     */
    #ifdef BARE_METAL
    void main()
    #else
    void spi_test(UArg arg0, UArg arg1)
    #endif
    {
        Board_flashHandle  boardHandle;
        Board_FlashInfo   *flashInfo;
        uint32_t           blockNum, pageNum;
        SPI_Params       spiParams;                        /* SPI params structure */
        bool               testPassed = true;
    
    #ifdef BARE_METAL
        /* Call board init functions */
        Board_initSPI();
    #endif
    
        /* Open the Board flash NOR device with the test SPI port
           and use the default SPI configurations */
        SPI_Params_init(&spiParams);
        spiParams.bitRate = 1000000;
        spiParams.dataSize = 16;
        spiParams.frameFormat  = SPI_POL0_PHA1;
        boardHandle = Board_flashOpen(TEST_NOR_DEV_ID,
                                      TEST_SPI_PORT,
                                      (void *)(&spiParams));
        if (!boardHandle)
        {
            SPI_log("\n Board_flashOpen failed. \n");
            goto err;
        }
        else
        {
            flashInfo = (Board_FlashInfo *)boardHandle;
            SPI_log("\n SPI NOR device ID: 0x%x, manufacturer ID: 0x%x \n",
                    flashInfo->device_id, flashInfo->manufacturer_id);
        }
    
        if (Board_flashOffsetToBlkPage(boardHandle, TEST_NOR_ADDR,
                                       &blockNum, &pageNum))
        {
            SPI_log("\n Board_flashOffsetToBlkPage failed. \n");
            testPassed = false;
            goto err;
        }
    
        /* Set the transfer length in number of 32 bit words */
        transferLength = NUM_OF_SAMPLES;
    
        /* Read data from flash */
        if (Board_flashRead(boardHandle, TEST_NOR_ADDR, (uint8_t *)&rxBuf[0],
                            NUM_OF_SAMPLES, NULL))
        {
            SPI_log("\n Board_flashRead failed. \n");
            testPassed = false;
            goto err;
        }
    
        Board_flashClose(boardHandle);
    
    err:
        if(true == testPassed)
        {
            SPI_log("\n All tests have passed. \n");
        }
        else
        {
            SPI_log("\n Some tests have failed. \n");
        }
        int i;
        for (i = 0; i<NUM_OF_SAMPLES; i++)
        {
            buffer_in[i] = (float)rxBuf[i];
        }
    //    for (i = 0; i<N; i++)
    //    {
    //        fft_in[2*i] = rxBuf[i];
    //        fft_in[2*i+1] = 0;
    //    }
    //
    //    gen_twiddle_fft32x32(fft_twiddle, N, 2147483647.5);
    //    DSP_fft32x32(fft_twiddle, N, fft_in, fft_out);
    //    for (i = 0; i<N; i++)
    //    {
    //        fft_out_real[i] = fft_out[2*i];
    //        fft_out_imag[i] = fft_out[2*i+1];
    //        fft_out_mag[i] = sqrt(fft_out_real[i]*fft_out_real[i] + fft_out_imag[i]*fft_out_imag[i]);
    //    }
    ////    tw_gen    (ptr_w_i,  N);
    ////    DSPF_sp_fftSPxSP_r2c (N, &ptr_x_i[0], &ptr_w_i[0], ptr_y_i, brev, 4, 0, N);
    //    generate_wavelets();
    //    DWT();
    //    index=0;
        while(1);
    }
    
    /*
     *  ======== main ========
     */
    #ifndef BARE_METAL
    int main(void)
    {
        /* Call board init functions */
        Board_initSPI();
    
        /* Start BIOS */
        BIOS_start();
        return (0);
    }
    #endif
    
    

  • For normal operation, you should be able to at least see some activity on the clock and chipselect going low. Simplest way for you to look at your configuration would be to setup the SPI flash RW example and then compare the SPI registers with your setup. Other than SPI registers PSC and clocking are the only other things that need to be configured at SOC level.

    Regards,
    Rahul