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.

TMS570LS0432: TMS570 spi in interrupt mode

Part Number: TMS570LS0432

Hello,
I am using TMS570LS0432 Hercules micro-controller  In that I am using spi protocol in interrupt mode, I have set all parameters through code generator as per process stated in example_spi_master_slave

/** @file example_SPI_Master_Slave.c
*   @brief Application main file
*   @date 25.July.2013
*   @version 03.06.00
*
*   This file contains an example of SPI1 and SPI2 Master / Slave configurations.
*
*   PIN Connections must be as Below
*     ---------------         ---------------
*     SPI1 ( Master )          SPI2 ( SLave)
*     ---------------         ---------------
*     SIM0             --->    SIMO
*     S0MI             <---    SOMI
*     CLK              --->    CLK
*     CS0              --->    CS0
*
*  ------------------
*  GUI configurations
*  ------------------
*  1) Driver TAB
*       - Select SPI2
*       - Select SPI1
*  2) VIm Channel 0-31
*       - Enable SPI2 Level 0 and Level 1 channels.
*  3) SPI2 TAB
*       - SPI2 Global SubTAB
*       	- Uncheck Master Mode
*       	- Uncheck Internal Clock
*       - SPI2 Port SubTAB
*       	- Uncheck DIR for CS 0
*  3) SPI1 TAB
*       - Have it default
*  4) Generate Code.
*
*/

/* (c) Texas Instruments 2009-2013, All rights reserved. */

/* 
* Copyright (C) 2009-2015 Texas Instruments Incorporated - 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.
*
*/

/* USER CODE BEGIN (0) */
/* USER CODE END */

/* Include Files */

#include "sys_common.h"
#include "system.h"

/* USER CODE BEGIN (1) */
#include "spi.h"
/* USER CODE END */

/** @fn void main(void)
*   @brief Application main function
*   @note This function is empty by default.
*
*   This function is called after startup.
*   The user can use this function to implement the application.
*/

/* USER CODE BEGIN (2) */
uint16 TX_Data_Master[16] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 };
uint16 TX_Data_Slave[16]  = { 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20 };
uint16 RX_Data_Master[16] = { 0 };
uint16 RX_Data_Slave[16]  = { 0 };
/* USER CODE END */

void main(void)
{
/* USER CODE BEGIN (3) */

	spiDAT1_t dataconfig1_t;

	dataconfig1_t.CS_HOLD = FALSE;
	dataconfig1_t.WDEL    = TRUE;
	dataconfig1_t.DFSEL   = SPI_FMT_0;
	dataconfig1_t.CSNR    = 0xFE;


	/* Enable CPU Interrupt through CPSR */
	_enable_IRQ();

	/* Initialize SPI Module Based on GUI configuration
	 * SPI1 - Master ( SIMO, SOMI, CLK, CS0 )
	 * SPI2 - Slave  ( SIMO, SOMI, CLK, CS0 )
	 * */
	spiInit();

	/* Initiate SPI2 Transmit and Receive through Interrupt Mode */
	spiSendAndGetData(spiREG2, &dataconfig1_t, 16, TX_Data_Slave, RX_Data_Slave);

	/* Initiate SPI1 Transmit and Receive through Polling Mode*/
	spiTransmitAndReceiveData(spiREG1, &dataconfig1_t, 16, TX_Data_Master, RX_Data_Master);

	while(1);
/* USER CODE END */
}

/* USER CODE BEGIN (4) */
/* USER CODE END */
file.


When I call the
spiSendAndGetData();then again
spiSendAndGetData()


I am not getting correct data from my slave device but when I change the my above code to


spiSendAndGetData();
while(SpiRxStatus(spiREG3) ==1);
spiSendAndGetData();
while(SpiRxStatus(spiREG3) ==1);


then I am getting correct data from my slave device.
But due to while loop after spiSendAndGetData(); it take more time for spi communication which is not correct for our application
Please give me any hint or correct me if I am doing wrong...
Waiting for your reply.

Thanks in advance..

  • The example you started with sets up two SPI, one as a master and the other as a slave. The two calls are to different SPIs. While you did not include the actual calls with parameters from your code, it appears as though you call spiSendAndGetData() twice using the same SPI, (SPI3). This function sets up buffers to do multiple transfers. It uses a static structure to keep track of status. If you call the function a second time, before the first buffer has completely sent, it will overwrite the static structure, aborting the first transmission block.

    You can either combine the buffers into a single buffer and do one call to spiSendAndGetData(), or you can create your own queue, using the spiEndNotification() callback function (which is still in the interrupt routine) to load the next transmission block in your queue.
  • Thank you for your quick reply,

    Let me clear things now i am using only one SPI3 port at TMS570(Master control) micro-controller side and for slave side i am not using another SPI port of TMS570. I am just transmitting SPI data from TMS570 to my slave device and for every transmission i am reading data from slave.

    and another thing is sorry for i am not mentioned above argument of spi but in my code i am passing 5 arguments.

    i want to transmit spi data for every 10ms in RTI timer interrupt mode but i am unable to get correct data from slave.

    And how to write spiEndNotification() callback function. 

    I'd appreciate if you can help

  • Is the SPI data you transmit every 10ms a single frame (8 or 16 bits)? Do you want to wait for the transmission to complete before continuing, or do you want an interrupt when the new data is received? The more clearly you describe what you are trying to do, the better my suggestions.
  • i am transmitting 8 bit of data. I just want to transmit and receive SPI data for every 10ms in RTI timer interrupt routine.and in another time my main loop will do a task.
  • Ok, the way the SPI works is when data is shifted out (transmitted) data is also received. I think you have three options. It really depends on when you need the received data.

    1. Transmit your first byte with a direct write to the SPI DAT0 register

            spi->DAT0 = my_data;

    Then in the RTI interrupt read the data that came in with the first transmit, and then send the second data. This is an easy implementation, but the data you read is 10mS old.

            if((spi->FLG & 0x00000100U) != 0x00000100U)
            {
            } /* error routine here because no received data*/
            my_read_data = (uint8)spi->BUF;
            spi->DAT0 = next_tx_data; //Start transmission of next byte
    
    

    2. If you can't wait 10mS to get the read data, you can do the data transmit every 10mS in the RTI interrupt, but then in your main loop poll for the received data. The issue with this method is that you may miss some received data if your main loop is too slow (takes longer than 10ms to execute some times).

    3. You can do the data  transmit in the 10mS RTI interrupt routine, and have an interrupt generated on SPI receive. In the SPI interrupt routine, read the character and put it in a buffer. Set a flag if necessary and then let your main routine process the data.

  • Here is my sample code please provide any solution

    spiDAT1_t dataconfig;

    dataconfig.CS_HOLD = TRUE;
    dataconfig.WDEL = TRUE;
    dataconfig.DFSEL = SPI_FMT_0;
    dataconfig.CSNR = 0xFC;

    int rdcfb(uint8_t nIC, uint8_t r_config[][12],unsigned char *ReadDataBuff,spiDAT1_t *dataconfig,spiBASE_t *spi)
    {
    int8_t pec_error = 0;

    uint16_t data_pec;
    uint16_t received_pec;

    unsigned int pntr=0,DataStartLocation=0;
    memset((char *)tx,0,sizeof(tx_LTC));
    memset((char *)rx,0,sizeof(rx_LTC));

    tx[pntr]=0x00; pntr++; DataStartLocation++;
    tx[pntr]=0x02; pntr++; DataStartLocation++;
    tx[pntr]=0x2B; pntr++; DataStartLocation++;
    tx[pntr]=0x0A; pntr++; DataStartLocation++;
    pntr+=8;                                                                            //for Reading  8  byte data from slave

    wakeup_idle (dataconfig,spiREG3);   //Dummy data required for Slave device before transmitting each packet to slave

    spiSendAndGetData(spiREG3,dataconfig, pntr, tx, rx);

    memcpy((char *)ReadDataBuff,(char *)&rx[DataStartLocation],8);

    }

    void wakeup_idle(spiDAT1_t *dataconfig,spiBASE_t *spi)
    {
    int wpntr=0;uint8_t w_tx[10],w_rx[10];
    uint8_t ut; int i;
    memset((char *)w_tx,0,sizeof(w_tx));
    memset((char *)w_rx,0,sizeof(w_rx));
    w_tx[wpntr] = 0x00; wpntr++;
    w_tx[wpntr] = 0x00; wpntr++;

    spiSendAndGetData(spiREG3,dataconfig, wpntr, w_tx, w_rx); 

    }

    if i call the  LTC6811_rdcfb(total_IC, r_config,rdcfb,&dataconfig,spiREG3);  in rtinotification

    then i am unable to get correct data.

    Both timer and spi interrupts are IRQ interrupt