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.

TMS320C6657: Extra Clock after SPI Transfer

Part Number: TMS320C6657

I've begun integrating an eInfoChips C6657 EVM with an FPGA EVM connected via SPI.  I now can communicate as desired but I needed to change some code in SPI_v0.c which for source code control is not desired.

We are transferring 32-bits in 4 8-bit frames.  With the unmodified SPI_v0.c code I see 40 spi clocks instead of the expected 32 clocks.  I copied the file SPI_v0.c into my project and I removed the following section of code from SPI_v0_hwiFxn().

if (loop == true)
{
   /* Read the interrupt status to check if there are any pending interrupts */
   intCode = SPIIntStatusGet(hwAttrs->baseAddr);

   /* Check if transmit is completed but data read is pending */
   if((object->writeCountIdx == 0U) && !(intCode & SPI_INT_RX_FULL) && (object->readCountIdx))
   {
      /* Send a dummy transfer to trigger a receive interrupt to handle delayed RX
      * interrupt to read the missed data during transmit.
      */
      if (intCode & SPI_INT_TX_EMPTY)
      {
         SPITransmitData(hwAttrs->baseAddr, csHold, 0);
      }
   }
}

That dummy transfer is causing the extra clocks I am seeing and making the SPI state machine in the FPGA unhappy.  Without this code I am able correctly read and write my 32-bit data to/from the FPGA so it would seem these "dummy transfers' are not needed.  It is curious that the code says "dummy transfer" but it results in real clocks to the FPGA.  This also caused the CS to behave incorrectly, leaving it in the wrong state.

Perhaps I am configuring something wrong to cause this?  Here is my basic setup of the SPI driver.  

/* Get the default SPI init configurations */
SPI_socGetInitCfg(SPI_INSTANCE, &spi_cfg);

this->baseAddr = spi_cfg.baseAddr;

/* Modify the default SPI configurations if necessary */
spi_cfg.enableIntr = true;

/* 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;
}

spi_cfg.csNum = this->spiCS;

/* Set the default SPI init configurations */
SPI_socSetInitCfg(SPI_INSTANCE, &spi_cfg);

SPI_init();

SPI_Params_init(&spiParams);
spiParams.frameFormat = SPI_POL0_PHA0;

// Make sure are not using semaphores since this is not running in a BIOS Task.
spiParams.transferMode = SPI_MODE_CALLBACK;
spiParams.transferTimeout = SPI_TRANSACTION_TIMEOUT;
spiParams.transferCallbackFxn = SPICallbackFxn;
spiParams.dataSize = 8; // We send 4 8-bit frames

this->handle = SPI_open(SPI_INSTANCE, &spiParams);

/* Enable transfer*/
UInt32 xferEnable = 1;
SPI_control(handle, SPI_V0_CMD_XFER_ACTIVATE, (void *)&xferEnable);

/* Enable chip select pin.*/
SPICSEnable(this->baseAddr, this->spiCS);

  • Dear Customer,

    Though I am not very sure about why you get 40 spi clocks instead of 30 clocks, I just thought of pointing you a sample SPI-driver program, " main_spi_flash_read_example.c" for C6657 EVM. 

    ( Not sure, whether you already referred to it )

    In this file, they have given the SPI configuration for both "bare metal without BIOS" as well as with BIOS. 

    May be, you can consider, comparing your SPI configurations with the one given in  main_spi_flash_read_example.c.

    ---

    File location:  C:\ti\pdk_c665x_2_0_16\packages\ti\drv\spi\example\spi_flash\src

    Part of package : Processor SDK 6.3 Link: PROCESSOR-SDK-RTOS-C665x 06_03_00_106 - TI.com

    ----

    ( Not sure, whether this helps.....)

    For reference, attaching three files, here on SPI-flash- Read/Write.

    1. 

    /******************************************************************************
     * Copyright (c) 2011-2012 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.
     * 
     *****************************************************************************/
    
    /******************************************************************************
     *
     * File Name:   evmc665x_spi.c
     *
     * Description: This file implements SPI driver for the NOR flash
     *  
     *****************************************************************************/
     
    /************************
     * Include Files
     ************************/
    #include "platform_internal.h"
    
    
    static uint32_t data1_reg_val;
    
    static void 
    spi_delay
    ( 
        uint32_t delay 
    )
    {
        volatile uint32_t i;
    
        for ( i = 0 ; i < delay ; i++ ){ };
    }
    
    
    /******************************************************************************
     * 
     * Function:    spi_claim  
     *
     * Description: This function claims the SPI bus in the SPI controller 
     *
     * Parameters:  Uint32 cs       - Chip Select number for the slave SPI device
     *              Uint32 freq     - SPI clock frequency  
     *
     * Return Value: error status
     * 
     ******************************************************************************/
    SPI_STATUS 
    spi_claim
    (
        uint32_t      cs,
        uint32_t      freq
    )
    {
        uint32_t scalar;
    
        PLIBSPILOCK()
    
        /* Enable the SPI hardware */
        SPI_SPIGCR0 = CSL_SPI_SPIGCR0_RESET_IN_RESET;
        spi_delay (2000);
        SPI_SPIGCR0 = CSL_SPI_SPIGCR0_RESET_OUT_OF_RESET;
    
        /* Set master mode, powered up and not activated */
        SPI_SPIGCR1 =   (CSL_SPI_SPIGCR1_MASTER_MASTER << CSL_SPI_SPIGCR1_MASTER_SHIFT)   |
                        (CSL_SPI_SPIGCR1_CLKMOD_INTERNAL << CSL_SPI_SPIGCR1_CLKMOD_SHIFT);
        
        
        /* CS0, CS1, CLK, Slave in and Slave out are functional pins */
        if (cs == 0) {
            SPI_SPIPC0 =    (CSL_SPI_SPIPC0_SCS0FUN0_SPI << CSL_SPI_SPIPC0_SCS0FUN0_SHIFT) |
                            (CSL_SPI_SPIPC0_CLKFUN_SPI << CSL_SPI_SPIPC0_CLKFUN_SHIFT)     |
                            (CSL_SPI_SPIPC0_SIMOFUN_SPI << CSL_SPI_SPIPC0_SIMOFUN_SHIFT)   |
                            (CSL_SPI_SPIPC0_SOMIFUN_SPI << CSL_SPI_SPIPC0_SOMIFUN_SHIFT);
        } else if (cs == 1) {
            SPI_SPIPC0 =    ((CSL_SPI_SPIPC0_SCS0FUN1_SPI << CSL_SPI_SPIPC0_SCS0FUN1_SHIFT) |
                            (CSL_SPI_SPIPC0_CLKFUN_SPI << CSL_SPI_SPIPC0_CLKFUN_SHIFT)     |
                            (CSL_SPI_SPIPC0_SIMOFUN_SPI << CSL_SPI_SPIPC0_SIMOFUN_SHIFT)   |
                            (CSL_SPI_SPIPC0_SOMIFUN_SPI << CSL_SPI_SPIPC0_SOMIFUN_SHIFT)) & 0xFFFF;
        }
        
        /* setup format */
        scalar = ((SPI_MODULE_CLK / freq) - 1 ) & 0xFF;
    
        if ( cs == 0) {
            SPI_SPIFMT0 =   (8 << CSL_SPI_SPIFMT_CHARLEN_SHIFT)               |
                            (scalar << CSL_SPI_SPIFMT_PRESCALE_SHIFT)                      |
                            (CSL_SPI_SPIFMT_PHASE_DELAY << CSL_SPI_SPIFMT_PHASE_SHIFT)     |
                            (CSL_SPI_SPIFMT_POLARITY_LOW << CSL_SPI_SPIFMT_POLARITY_SHIFT) |
                            (CSL_SPI_SPIFMT_SHIFTDIR_MSB << CSL_SPI_SPIFMT_SHIFTDIR_SHIFT);
        }else if ( cs == 1) {
            SPI_SPIFMT0 =   (16 << CSL_SPI_SPIFMT_CHARLEN_SHIFT)               |
                            (scalar << CSL_SPI_SPIFMT_PRESCALE_SHIFT)                      |
                            (CSL_SPI_SPIFMT_PHASE_NO_DELAY << CSL_SPI_SPIFMT_PHASE_SHIFT)     |
                            (CSL_SPI_SPIFMT_POLARITY_LOW << CSL_SPI_SPIFMT_POLARITY_SHIFT) |
                            (CSL_SPI_SPIFMT_SHIFTDIR_MSB << CSL_SPI_SPIFMT_SHIFTDIR_SHIFT);
        }
        
        /* hold cs active at end of transfer until explicitly de-asserted */
        data1_reg_val = (CSL_SPI_SPIDAT1_CSHOLD_ENABLE << CSL_SPI_SPIDAT1_CSHOLD_SHIFT) |
                        (0x02 << CSL_SPI_SPIDAT1_CSNR_SHIFT);
         if (cs == 0) {
             SPI_SPIDAT1 =   (CSL_SPI_SPIDAT1_CSHOLD_ENABLE << CSL_SPI_SPIDAT1_CSHOLD_SHIFT) |
                             (0x02 << CSL_SPI_SPIDAT1_CSNR_SHIFT);
         } 
    
        /* including a minor delay. No science here. Should be good even with
        * no delay
        */
        if (cs == 0) {
            SPI_SPIDELAY =  (8 << CSL_SPI_SPIDELAY_C2TDELAY_SHIFT) |
                            (8 << CSL_SPI_SPIDELAY_T2CDELAY_SHIFT);
            /* default chip select register */
            SPI_SPIDEF  = CSL_SPI_SPIDEF_RESETVAL;        
        } else if (cs == 1) {    
            SPI_SPIDELAY =  (6 << CSL_SPI_SPIDELAY_C2TDELAY_SHIFT) |
                            (3 << CSL_SPI_SPIDELAY_T2CDELAY_SHIFT);
        }
        
        /* no interrupts */
        SPI_SPIINT0 = CSL_SPI_SPIINT0_RESETVAL;
        SPI_SPILVL  = CSL_SPI_SPILVL_RESETVAL;
    
        /* enable SPI */
        SPI_SPIGCR1 |= ( CSL_SPI_SPIGCR1_ENABLE_ENABLE << CSL_SPI_SPIGCR1_ENABLE_SHIFT );
    
        if (cs == 1) {
            SPI_SPIDAT0 = 1 << 15; 
            spi_delay (10000);        
            /* Read SPIFLG, wait untill the RX full interrupt */
            if ( (SPI_SPIFLG & (CSL_SPI_SPIFLG_RXINTFLG_FULL<<CSL_SPI_SPIFLG_RXINTFLG_SHIFT)) ) {                
                /* Read one byte data */
                scalar = SPI_SPIBUF & 0xFF;
                /* Clear the Data */
                SPI_SPIBUF = 0;
            }
            else {
                /* Read one byte data */
                scalar = SPI_SPIBUF & 0xFF;
                return SPI_EFAIL;
            }
        }
        return SPI_EOK;
    }
    
    /******************************************************************************
     * 
     * Function:    spi_release  
     *
     * Description: This function releases the bus in SPI controller 
     *
     * Parameters:  None
     *
     * Return Value: None
     * 
     ******************************************************************************/
    void 
    spi_release
    (
        void
    )
    {
        /* Disable the SPI hardware */
        SPI_SPIGCR1 = CSL_SPI_SPIGCR1_RESETVAL;
    
        PLIBSPIRELEASE()
    }
    
    /******************************************************************************
     * 
     * Function:    spi_xfer  
     *
     * Description: This function sends and receives 8-bit data serially
     *
     * Parameters:  uint32_t nbytes   - Number of bytes of the TX data
     *              uint8_t* data_out - Pointer to the TX data
     *              uint8_t* data_in  - Pointer to the RX data
     *              Bool terminate  - TRUE: terminate the transfer, release the CS
     *                                FALSE: hold the CS
     *
     * Return Value: error status
     * 
     ******************************************************************************/
    SPI_STATUS 
    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 */
        buf_reg = 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;
        
    }
    
    
    /******************************************************************************
     * 
     * Function:    spi_cmd  
     *
     * Description: This function sends a single byte command and receives response data
     *
     * Parameters:  uint8_t  cmd      - Command sent to the NOR flash
     *              uint8_t* response - Pointer to the RX response data
     *              uint32_t len      - Lenght of the response in bytes
     *
     * Return Value: error status
     * 
     ******************************************************************************/
    SPI_STATUS 
    spi_cmd
    (
        uint8_t               cmd,
        uint8_t*              response,
        uint32_t              len
    )
    {
        Bool        flags = FALSE;
        uint32_t      ret;
        
        if (len == 0)
        {
            flags = TRUE;
        }
        
        /* Send the command byte */
        ret = spi_xfer(1, &cmd, NULL, flags);
        if (ret) 
        {
        	IFPRINT (platform_write("SF: Failed to send command %02x: %d\n", cmd, ret));
            return ret;
        }
        
        /* Receive the response */
        if (len) 
        {
            ret = spi_xfer(len, NULL, response, TRUE);
            if (ret)
            {
            	IFPRINT (platform_write("SF: Failed to read response (%zu bytes): %d\n",  len, ret));
            }
        }
        
        return ret;
    }
    
    /******************************************************************************
     * 
     * Function:    spi_cmd_read  
     *
     * Description: This function sends a read command and reads data from the flash
     *
     * Parameters:  uint8_t  cmd      - Command sent to the NOR flash
     *              uint32_t cmd_len  - Length of the command in bytes
     *              uint8_t* dat      - Pointer to the data read
     *              uint32_t data_len - Lenght of the data read in bytes
     *
     * Return Value: error status
     * 
     ******************************************************************************/
    SPI_STATUS 
    spi_cmd_read
    (
        uint8_t*              cmd,
        uint32_t              cmd_len,
        uint8_t*              data,
        uint32_t              data_len
    )
    {
        Bool        flags = FALSE;
        uint32_t      ret;
        
        if (data_len == 0)
        {
            flags = TRUE;
        }
    
        /* Send read command */
        ret = spi_xfer(cmd_len, cmd, NULL, flags);
        if (ret) 
        {
        	IFPRINT (platform_write("SF: Failed to send read command (%zu bytes): %d\n",
                   cmd_len, ret));
        } 
        else if (data_len != 0) 
        {
            /* Read data */
            ret = spi_xfer(data_len, NULL, data, TRUE);
            if (ret)
            {
            	IFPRINT (platform_write("SF: Failed to read %zu bytes of data: %d\n",
                       data_len, ret));
            }
        }
        
        return ret;
    }
    
    /******************************************************************************
     * 
     * Function:    spi_cmd_write  
     *
     * Description: This function sends a write command and writes data to the flash
     *
     * Parameters:  uint8_t  cmd      - Command sent to the NOR flash
     *              uint32_t cmd_len  - Length of the command in bytes
     *              uint8_t* dat      - Pointer to the data to be written
     *              uint32_t data_len - Lenght of the data in bytes
     *
     * Return Value: error status
     * 
     ******************************************************************************/
    SPI_STATUS 
    spi_cmd_write
    (
        uint8_t*        cmd,
        uint32_t        cmd_len,
        uint8_t*        data,
        uint32_t        data_len
    )
    {
        Bool           flags = FALSE;
        uint32_t         ret;
        
        if (data_len == 0)
        {
            flags = TRUE;
        }
        
        /* Send write command */
        ret = spi_xfer(cmd_len, cmd, NULL, flags);
        if (ret) 
        {
        	IFPRINT (platform_write("SF: Failed to send write command (%zu bytes): %d\n",
                cmd_len, ret));
        } 
        else if (data_len != 0) 
        {
            /* Write data */
            ret = spi_xfer(data_len, data, NULL, TRUE);
            if (ret)
            {
            	IFPRINT (platform_write("SF: Failed to write %zu bytes of data: %d\n",
                data_len, ret));
            }
        }
        
        return ret;
    }
    
    
    /******************************************************************************
     * 
     * Function:    spi_read_word  
     *
     * Description: This function sends a read command and reads data in 16-bit data format  
     *
     * Parameters:  uint16_t* cmd_buf  - Pointer to the command sent
     *              uint32_t cmd_len   - Length of the command in words
     *              uint16_t* data_buf - Pointer to the data read
     *              uint32_t data_len  - Lenght of the data read in words
     *
     * Return Value: error status
     * 
     ******************************************************************************/
    SPI_STATUS 
    spi_read_word
    (
        uint16_t*             cmd_buf,
        uint32_t              cmd_len,
        uint16_t*             data_buf,
        uint32_t              data_len
    )
    {
        uint32_t          data1_reg;
        uint16_t*         tx_ptr = cmd_buf;
        uint16_t*         rx_ptr = data_buf;
        
    	/* disable the SPI communication by setting 
    	 * the SPIGCR1.ENABLE to 0 
    	 * 
    	 * 
    	 * SPIGCR1
    	 * ============================================
    	 * Bit 	Field 	Value 		Description
    	 * 24 	ENABLE 	0			SPI disable
    	 * ============================================
    	 */
    	data1_reg = 0x1 << 24;
    	data1_reg = ~data1_reg;
        SPI_SPIGCR1 &= data1_reg;
    
    	/*
    	 * clean TX data into SPIDAT0
    	 * 
    	 * SPIDAT0
    	 * ============================================
    	 * Bit 	Field 	Value 		Description
    	 * 15-0 TXDATA 	0-FFFFh 	SPI transmit data
    	 * ============================================
    	 * 
    	 */
    
        SPI_SPIDAT0 = 0;
    
    	/* 8.
    	 * Enable the SPI communication by setting 
    	 * the SPIGCR1.ENABLE to 1 
    	 * 
    	 * 
    	 * SPIGCR1
    	 * ============================================
    	 * Bit 	Field 	Value 		Description
    	 * 24 	ENABLE 	1			SPI enable
    	 * ============================================
    	 */
    
    	data1_reg = 0x1 << 24;
        SPI_SPIGCR1 = (SPI_SPIGCR1 | data1_reg);    
        
        {
            {
                SPI_SPIDAT0 = *tx_ptr;
                spi_delay(10000);
            }
    
            /* Read SPIFLG, wait untill the RX full interrupt */
            if ( (SPI_SPIFLG & (CSL_SPI_SPIFLG_RXINTFLG_FULL<<CSL_SPI_SPIFLG_RXINTFLG_SHIFT)) ) {                
                /* Read one byte data */
                *rx_ptr = SPI_SPIBUF & 0xFF;
                SPI_SPIBUF = 0;
            }
            else {
                return SPI_EFAIL;
            }
            
        }
        
        return SPI_EOK;
    
    }
    
    /******************************************************************************
     * 
     * Function:    spi_write_word  
     *
     * Description: This function sends a write command and writes data in 16-bit data format 
     *
     * Parameters:  uint16_t* cmd_buf  - Pointer to the command sent
     *              uint32_t cmd_len   - Length of the command in bytes
     *              uint16_t* data_buf - Pointer to the data read
     *              uint32_t data_len  - Lenght of the data read in bytes
     *
     * Return Value: error status
     * 
     ******************************************************************************/
    SPI_STATUS 
    spi_write_word
    (
        uint16_t*             cmd_buf,
        uint32_t              cmd_len,
        uint16_t*             data_buf,
        uint32_t              data_len
    )
    {
        uint32_t          data1_reg;
        uint16_t*         tx_ptr = cmd_buf;
    
    	/* disable the SPI communication by setting 
    	 * the SPIGCR1.ENABLE to 0 
    	 * 
    	 * 
    	 * SPIGCR1
    	 * ============================================
    	 * Bit 	Field 	Value 		Description
    	 * 24 	ENABLE 	0			SPI disable
    	 * ============================================
    	 */
    	data1_reg = 0x1 << 24;
    	data1_reg = ~data1_reg;
        SPI_SPIGCR1 &= data1_reg;
    
    	/*
    	 * clean TX data into SPIDAT0
    	 * 
    	 * SPIDAT0
    	 * ============================================
    	 * Bit 	Field 	Value 		Description
    	 * 15-0 TXDATA 	0-FFFFh 	SPI transmit data
    	 * ============================================
    	 * 
    	 */
    
        SPI_SPIDAT0 = 0;
    
    	/* 8.
    	 * Enable the SPI communication by setting 
    	 * the SPIGCR1.ENABLE to 1 
    	 * 
    	 * 
    	 * SPIGCR1
    	 * ============================================
    	 * Bit 	Field 	Value 		Description
    	 * 24 	ENABLE 	1			SPI enable
    	 * ============================================
    	 */
    
    	data1_reg = 0x1 << 24;
        SPI_SPIGCR1 = (SPI_SPIGCR1 | data1_reg);    
        
        {
            {
                SPI_SPIDAT0 = *tx_ptr;
                spi_delay(10000);
            }
    
            /* Read SPIFLG, wait untill the RX full interrupt */
            if ( (SPI_SPIFLG & (CSL_SPI_SPIFLG_TXINTFLG_EMPTY<<CSL_SPI_SPIFLG_TXINTFLG_SHIFT)) ) {                
                /* Clear the SPIBUF */
                SPI_SPIBUF = 0;
                return SPI_EOK;
            }
            else {
                return SPI_EFAIL;
            }
            
        }
    }
    
    
    

     -- This is from the platform test library of C6657 EVM located at "C:\ti\pdk_c665x_2_0_16\packages\ti\platform\evmc6657l\platform_lib\src"

    2. 

    /**
     *  \file   main_spi_flash_read_write.c
     *
     *  \brief  Example application main file. This application will write and read
     *          the data to/from SPI_NOR flash through Board flash interface.
     *
     */
    
    /*
     * Copyright (C) 2015 - 2017 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 <stdio.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)
    #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 ************************
     **********************************************************************/
    
    /* Function to generate known data */
    static void GeneratePattern(uint8_t *txBuf, uint8_t *rxBuf, uint32_t length);
    
    /* Data compare function */
    bool VerifyData(uint8_t *expData,
                    uint8_t *rxData,
                    uint32_t length);
    
    
    /**********************************************************************
     ************************** Global Variables **************************
     **********************************************************************/
    
    /* Buffer containing the known data that needs to be written to flash */
    uint8_t txBuf[TEST_TX_LENGTH];
    
    /* Buffer containing the received data */
    uint8_t rxBuf[TEST_TX_LENGTH];
    
    /* transfer length */
    uint32_t transferLength;
    
    /*
     *  ======== 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)
        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);
    #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);
    }
    
    
    /*
     *  ======== 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 test SPI port
           and use the default SPI configurations */
        SPI_Params_init(&spiParams);
        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 = TEST_TX_LENGTH;
    
        /* Generate the data */
        GeneratePattern(txBuf, rxBuf, transferLength);
    
    #ifdef TEST_SPI_NOR_WRITE
        /* Erase block, to which data has to be written */
        if (Board_flashEraseBlk(boardHandle, blockNum))
        {
            SPI_log("\n Board_flashEraseBlk failed. \n");
            testPassed = false;
            goto err;
        }
    
        /* Write buffer to flash */
        if (Board_flashWrite(boardHandle, TEST_NOR_ADDR, txBuf,
                             TEST_TX_LENGTH, NULL))
        {
            SPI_log("\n Board_flashWrite failed. \n");
            testPassed = false;
            goto err;
        }
    #endif
    
        /* Read data from flash */
        if (Board_flashRead(boardHandle, TEST_NOR_ADDR, (uint8_t *)&rxBuf[0],
                            TEST_TX_LENGTH, NULL))
        {
            SPI_log("\n Board_flashRead failed. \n");
            testPassed = false;
            goto err;
        }
    
    #ifndef TEST_SPI_NOR_WRITE
        /* if no write test, copy rxBuf to txBuf to pass the test */
        memcpy(txBuf, rxBuf, transferLength);
    #endif
    
        /* Verify Data */
        if (VerifyData(txBuf, rxBuf, transferLength) == false)
        {
            SPI_log("\n Data mismatch. \n");
            testPassed = false;
        }
    
        Board_flashClose(boardHandle);
    
    err:
        if(true == testPassed)
        {
            SPI_log("\n All tests have passed. \n");
        }
        else
        {
            SPI_log("\n Some tests have failed. \n");
        }
    
        while(1);
    }
    
    /*
     *  ======== main ========
     */
    #ifndef BARE_METAL
    int main(void)
    {
        /* Call board init functions */
        Board_initSPI();
    
        /* Start BIOS */
        BIOS_start();
        return (0);
    }
    #endif
    
    /*
     *  ======== CompareData ========
     */
    bool VerifyData(uint8_t *expData,
                    uint8_t *rxData,
                    uint32_t length)
    {
        uint32_t idx = 0;
        uint32_t match = 1;
        bool retVal = false;
    
        for(idx = 0; ((idx < length) && (match != 0)); idx++)
        {
            if(*expData != *rxData)
            {
                match = 0;
            }
            expData++;
            rxData++;
        }
    
        if(match == 1)
        {
            retVal = true;
        }
    
        return retVal;
    }
    
    /*
     *  ======== GeneratePattern ========
     */
    static void GeneratePattern(uint8_t *txBuf, uint8_t *rxBuf, uint32_t length)
    {
        volatile uint32_t idx;
        volatile uint8_t *txPtr = txBuf;
        volatile uint8_t *rxPtr = rxBuf;
    
        for(idx = 0; idx < length; idx++)
        {
        	*txPtr++ = (uint8_t)idx;
        	*rxPtr++ = (uint8_t)0U;
        }
    }
    

    3. 

    /**
     *  \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 <stdio.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 **************************
     **********************************************************************/
    
    /* Buffer containing the received data */
    uint8_t rxBuf[TEST_TX_LENGTH];
    
    /* transfer length */
    uint32_t transferLength;
    
    /*
     *  ======== 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);
    #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);
    }
    
    
    /*
     *  ======== 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.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 = TEST_TX_LENGTH;
    
        /* Read data from flash */
        if (Board_flashRead(boardHandle, TEST_NOR_ADDR, (uint8_t *)&rxBuf[0],
                            TEST_TX_LENGTH, 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");
        }
    
        while(1);
    }
    
    /*
     *  ======== main ========
     */
    #ifndef BARE_METAL
    int main(void)
    {
        /* Call board init functions */
        Board_initSPI();
    
        /* Start BIOS */
        BIOS_start();
        return (0);
    }
    #endif
    
    

    Regards

    Shankari G

  • Thank you Shankari.  I always start using TI example code.  If you look at the code I posted portions of it are a direct copy of the example code, but with the customizations needed for our particular platform.  I was hoping someone familiar with the SPI driver code could look at the code section I removed and see if there is some configuration that would skip over that code, so I did not have to remove it, or agree that in our case this is a bug in the driver that needs to be fixed.

  • Christopher,

    Ok, I understand.

    As, I read through your post, you explained it very neatly at the first shot.

    I tentatively perceived this, " and see if there is some configuration that would skip over that code, so I did not have to remove it ". Thanks for confirming.

    Let me forward to internal team and check, whether, are there any significance on the dummy transfers or is it safe to remove etc.

    Thanks for your patience.

    Regards

    Shankari G

  • Christopher,

    I have not heard from the team. I will keep you posted if I get replies.

    However, as the PDK is common for the series of devices and also the same drivers are migrated/ported for various EVMs from different manufacturers( e-infochips/advantech etc) , not sure about the introduction/significance of dummy transfer of SPI.

    May be, as the author-comment says, "Send a dummy transfer to trigger a receive interrupt to handle delayed RX". 

    For the time being, for your customization, as you already tested, removing the dummy transfer may be a better choice. 

    At-least for future customer, this info, might be useful for forum-members. Thanks for bringing to our notice.

    Regards

    Shankari G