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.

RTOS SPI Tx/Rx Delayed (MSP430F5529)

Other Parts Discussed in Thread: MSP430F5529

I am using TI-RTOS (SYS/BIOS) in 2 MSP430F5529 and trying to have the F5529s to talk to each other through SPI. 

Master basically does this: 

while (!(UCA0IFG&UCTXIFG)); // USCI_A0 TX buffer ready?

if (UCA0RXBUF==SLV_Data) // Test for correct character RX'd
P1OUT |= 0x01; // If correct, light LED
else
P1OUT &= ~0x01; // If incorrect, clear LED

MST_Data++; // Increment data
SLV_Data++;
UCA0TXBUF = MST_Data; // Send next value

for(i = 100; i>0; i--); // Add time between transmissions to
// make sure slave can process information

Slave basically does this: 

while (!(UCA0IFG&UCTXIFG));             // USCI_A0 TX buffer ready?
UCA0TXBUF = UCA0RXBUF;

The master is suppose to tx a number, and the slave is suppose to tx the number - 1. This works without RTOS. However, with RTOS, the slave is tx-ing the number - 2.

Seems like the slave is delayed. Could anyone help on this?

- RW 

Code for the master and slave, main.c and app.cfg:

/*
 *  ======== main.c ========
 */

#include <xdc/std.h>
#include <ti/sysbios/BIOS.h>
#include <xdc/cfg/global.h>
#include <xdc/runtime/System.h>
#include <xdc/runtime/Log.h>

#include <msp430.h>
#include <driverlib.h>

#define SPI_CLK_HZ  320000

void start_SPI( void );

//-----------------------------------------
// Globals
//-----------------------------------------
unsigned char MST_Data,SLV_Data;
unsigned char temp;

/*
 *  ======== main ========
 */
Int main(){
	volatile unsigned int i;

	WDTCTL = WDTPW+WDTHOLD;                   // Stop watchdog timer

	UCSCTL1 = DCORSEL_5;
	UCSCTL2 = FLLD_1 + FLLN8 + FLLN7 + FLLN6 + FLLN4 + FLLN3 + FLLN0;
	UCSCTL3 = SELREF_2 + FLLREFDIV_0;
	UCSCTL4 = SELA_2 + SELS_4 + SELM_4;
	UCSCTL5 = DIVPA_0 + DIVA_0 + DIVS_0 + DIVM_0;
	UCSCTL6 = 0xC1CD;
	UCSCTL7 = 0x0400;
	UCSCTL8 = 0x0707;

	P1OUT |= 0x02;                            // Set P1.0 for LED
	                                              	// Set P1.1 for slave reset
	P1DIR |= 0x03;                            // Set P1.0-2 to output direction
	P3SEL |= BIT3+BIT4;                       // P3.3,4 option select
	P2SEL |= BIT7;                            // P2.7 option select

	UCA0CTL1 |= UCSWRST;                      // **Put state machine in reset**
	USCI_A_SPI_initMasterParam param = { 0 };
	param.selectClockSource = USCI_A_SPI_CLOCKSOURCE_SMCLK;
	param.clockSourceFrequency = UCS_getSMCLK();
	param.desiredSpiClock = SPI_CLK_HZ;
	param.msbFirst = USCI_A_SPI_MSB_FIRST;
	param.clockPhase = USCI_A_SPI_PHASE_DATA_CHANGED_ONFIRST_CAPTURED_ON_NEXT;
	param.clockPolarity = USCI_A_SPI_CLOCKPOLARITY_INACTIVITY_LOW;
	USCI_A_SPI_initMaster( USCI_A0_BASE, &param );
	UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
	UCA0IE |= UCRXIE;                         // Enable USCI_A0 RX interrupt

	P1OUT &= ~0x02;                           // Now with SPI signals initialized,
	P1OUT |= 0x02;                            // reset slave
	for(i=50;i>0;i--);                        // Wait for slave to initialize

	MST_Data = 0x01;                          // Initialize data values
	SLV_Data = 0x00;                          //

	while (!(UCA0IFG&UCTXIFG));               // USCI_A0 TX buffer ready?
	UCA0TXBUF = MST_Data;                     // Transmit first character

	__bis_SR_register(GIE);       // CPU off, enable interrupts

	System_printf( "Start BIOS_start\n" );
	System_flush();

    BIOS_start();    /* does not return */
    return(0);
}

void start_SPI( void ){
	volatile unsigned int i;

	while (!(UCA0IFG&UCTXIFG));         // USCI_A0 TX buffer ready?

	if (UCA0RXBUF==SLV_Data)            // Test for correct character RX'd
		P1OUT |= 0x01;                  // If correct, light LED
	else
	    P1OUT &= ~0x01;                 // If incorrect, clear LED

	MST_Data++;                         // Increment data
	SLV_Data++;
	UCA0TXBUF = MST_Data;               // Send next value

	for(i = 100; i>0; i--);				// Add time between transmissions to
	                                   	// make sure slave can process information
}

4666.app.cfg

/*
 *  ======== main.c ========
 */

#include <xdc/std.h>
#include <ti/sysbios/BIOS.h>
#include <xdc/cfg/global.h>
#include <xdc/runtime/System.h>
#include <xdc/runtime/Log.h>

#include <msp430.h>
#include <driverlib.h>

//-----------------------------------------
// Globals
//-----------------------------------------

void start_SPI( void );

/*
 *  ======== main ========
 */
Int main(){
	WDTCTL = WDTPW+WDTHOLD;                   // Stop watchdog timer

	UCSCTL1 = DCORSEL_5;
	UCSCTL2 = FLLD_1 + FLLN8 + FLLN7 + FLLN6 + FLLN5 + FLLN4 + FLLN3 + FLLN0;
	UCSCTL3 = SELREF_2 + FLLREFDIV_0;
	UCSCTL4 = SELA_2 + SELS_4 + SELM_4;
	UCSCTL5 = DIVPA_0 + DIVA_0 + DIVS_0 + DIVM_0;
	UCSCTL6 = 0xC1CD;
	UCSCTL7 = 0x0400;
	UCSCTL8 = 0x0707;

	//P2DIR |= BIT2;            // Define P1.0 and P1.4 as outputs
	//P2SEL |= BIT2;   			// Connect ACLK to P1.0 and SMCLK to P1.4,
		  	                      // and set all other bits for digital I/O.

//	while(!(P2IN&0x80));                      					// If clock sig from mstr stays low,
	                                            		  	  	  // it is not yet in SPI mode
	P3SEL |= BIT3+BIT4;                       					// P3.3,4 option select
	P2SEL |= BIT7;                            					// P2.7 option select
	USCI_A_SPI_disable( USCI_A0_BASE );       					// **Put state machine in reset**
	USCI_A_SPI_initSlave( USCI_A0_BASE, USCI_A_SPI_MSB_FIRST, USCI_A_SPI_PHASE_DATA_CHANGED_ONFIRST_CAPTURED_ON_NEXT,
				  USCI_A_SPI_CLOCKPOLARITY_INACTIVITY_LOW );
	USCI_A_SPI_enable( USCI_A0_BASE );        					// **Initialize USCI state machine**
	USCI_A_SPI_enableInterrupt( USCI_A0_BASE, UCRXIE );			// Enable USCI_A0 RX interrupt

	__bis_SR_register( GIE );       // Enter LPM4, enable interrupts
	
	System_printf( "Start BIOS_start()\n" );
	System_flush();

    BIOS_start();    /* does not return */
    return( 0 );
}

void start_SPI( void ){
	while (!(UCA0IFG&UCTXIFG));             // USCI_A0 TX buffer ready?
	UCA0TXBUF = UCA0RXBUF;


}

7824.app.cfg

  • Trying a process of elimination, I replaced the slave RTOS program with the non-RTOS program that does the same function and left the master with RTOS. Also vice versa, I replaced the master RTOS program with the non-RTOS program that does the same function and left the slave with RTOS. Both cases showed delays in the SPI bus. But when the master had no RTOS, the bus had less delays. For example, if I sent bytes manually with the master, there was no problems on the bus.

    The non-RTOS programs can be found in the TI example programs for the MSP430F5529.

    processors.wiki.ti.com/.../MSP430F5529_LaunchPad (Code examples for each MSP430F55xx peripheral)

    - RW
  • Hi RW,

    I looked at your source code and it looks like you are not leveraging any TI-RTOS features except the Hwi module for registering an ISR. It looks unlikely that using TI-RTOS is causing delays.

    Can you describe your setup in more detail ? Specifically, I want to know if you are starting the Slave before the Master. It is important for the Slave to be ready before the Master is started. Otherwise, some of the data may get lost.

    Best,

    Ashish

  • Yes, I am using the Hwi module in the code. I thought using the Hwi instead of a swi would be faster. I found that they are about the same speed.

    Yes, the slave is ran before the master.

    Thank you Ashish. I look forward for more info from you.
  • Can you describe your setup in more detail ? Also, can you describe the run time behavior (i.e. what output is getting printed on each board, etc.) ?

    Best,
    Ashish

  • Hi Ashish,

    Sorry for the late reply. I was out of the country with limited internet connection.

    Well, the systems were running at 16MHz each. Could that be a problem? Do the they need to run faster to accommodate bytes going through SPI every ~10us?

    No System_Printf() was used in the RTOS runtime. However, one System_Printf() was used prior to going into the RTOS. To see the data through the SPI bus, a logic analyzer was used. 

    - RW