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.

LAUNCHXL-CC3235S: SPI interface :: LaunchXL-CC3235 and MSP430FR5969 reg.

Part Number: LAUNCHXL-CC3235S
Other Parts Discussed in Thread: MSP430FR5969, SYSCONFIG

hello TI team,

I'm working on SPI data transfer between MSP430FR5969 (configured as SPI Master) and LaunchXL-CC3235 (configured as SPI Slave) and facing some issues. The implementation and problem statement are as follows. Can someone please help?

Implementation:

  • MSP430FR5969: 
    • configured as master
    • SPI configuration involves clock at 1 MHz, mode 0 and eUSCI_B0 for SPI interface
    • Pin 4.3 (GPIO) configured for interrupt low to high => this responds to Slave ready signal from CC3235 and carries out SPI Transmit in ISR.
  • LaunchXL-CC3235:
    • configured as SPI Slave
    • SPI parameters are as specified in the program attached herewith.
  • for this implementation, I followed below-mentioned steps:
    • firstly I implemented CC3235 - CC3235 master-slave program. The one provided with the simplelink library file. The implementation worked just fine. In the same code, I carried out many modifications and with that as well, the code ran properly. Modifications I did are as follows:
      • replaced all threads with FreeRTOS tasks. 
      • removed master ready synchronisation lines. 
      • changed Slave Transmit message length, message text and number of time the message is being transmitted. 
    • Noe, since all went well, I implemented MSP430 master SPI transfer program. This also worked fine as I could see data available on oscilloscope from MOSI pin of MSP430FR5969. 

Problem:

  • CC3235 generates a slave ready signal on one of its GPIO. This is visible on oscilloscope.
  • This slave ready signal is provided to Pin 4.3 of MSP430. Based on this signal, an interrupt gets generated and MSP430 transmits data over its MOSI pin. This is also visible on oscilloscope. 
  • The problem is, when CC3235 executes the command SPI_Transfer(), it then reaches to the section dmaErrorFxn. What logically should happen is, SPI_Transfer() shall either return True or False. Bus this somehow does not happen.

Can you please look at the implementation and let me know? 

Please let me know if anything else is required on this from my side. 

Regards, 

H C Trivedi

P.S.: 

  • Main.c => SPI master for MSP430
  • query - CC3235 Slave try 1 for Non-RTOS interface.c => SPI Slave program for CC3235

#include <msp430.h> 

void clock_setup();
void port_setup();
void configure_SPI_Master();

char data1[] = {0x12, 0x24, 0x36, 0x48, 0x5A, 0x6C, 0x7E, 0x80, 0x91, 0xA3, 0xB5, 0xC7, 0xD9, 0xEB, 0x00};
unsigned char position=0;

/**
 * The recommended eUSCI initialization or reconfiguration process is:
 * Set UCSWRST
 * Initialize all eUSCI registers with UCSWRST = 1 (including UCxCTL1).
 * Configure ports.
 * Ensure that any input signals into the SPI module such as UCxSOMI (in master mode) or UCxSIMO and UCxCLK (in slave mode) have settled to their final voltage levels before clearing UCSWRST and avoid any unwanted transitions during operation.
 * Clear UCSWRST.
 * Enable interrupts (optional) with UCRXIE or UCTXIE
 */
int main(void)
{
	WDTCTL = WDTPW | WDTHOLD;	// stop watchdog timer
	
    // Disable the GPIO power-on default high-impedance mode to activate
    // previously configured port settings
    PM5CTL0 &= ~LOCKLPM5;

    // Configure one FRAM waitstate as required by the device datasheet for MCLK
    // operation beyond 8MHz _be                                                                                                                                                      fore_ configuring the clock system.
    // Eventhough this is directly not required here since clock operation is @ 1MHz and data transfer is at 500 kHz
    FRCTL0 = FRCTLPW | NWAITS_1;

    clock_setup();
    port_setup();
    configure_SPI_Master();

    P1IE |= BIT1;       // P1.1 interrupt enabled
    P1IES |= BIT1;      // P1.1 Hi/lo falling edge
    P1IFG &= ~BIT1;     // P1.1 IFG cleared just in case

    P4IE |= BIT3;       // P4.3 interrupt enabled
    P4IES &= ~BIT3;      // P4.3 Hi/lo falling edge
    P4IFG &= ~BIT3;     // P4.3 IFG cleared just in case

    _EINT();

	return 0;
}



void clock_setup()
{
    // Clock System Setup
    CSCTL0_H = CSKEY >> 8;                      // Unlock CS registers
    CSCTL1 = 0x0000;                            // Set DCO to 1 MHz
    CSCTL2 = 0x0033;                            // Set SMCLK = DCO = MCLK
    CSCTL3 = 0x0000;                            // no division
    CSCTL0_H = 0;                               // Lock CS registers
}


void port_setup()
{
    // Configure Pins for SPI through B0 registers.
    // following are Pins for SPI through B0 registers:

    // P1.3 Slave transmit enable
    P1SEL0 &= ~BIT3;                            // Clears P1.3 Slave Transmit Enable SEL0
    P1SEL1 |= BIT3;                             // Sets P1.3 Slave Transmit Enable SEL1

    // P2.2    SPI Clock Input (slave) / Output (master)
    P2SEL0 &= ~BIT2;                            // Clears P2.2 SPI Clock SEL0
    P2SEL1 |= BIT2;                             // Sets P2.2 SPI Clock SEL1

    // P1.6    MOSI
    P1SEL0 &= ~BIT6;                            // Clears P1.6 SIMO SEL0
    P1SEL1 |= BIT6;                             // Sets P1.6 SIMO SEL1

    // P1.7    MISO
    P1SEL0 &= ~BIT7;                            // Clears P1.7 SOMI SEL0
    P1SEL1 |= BIT7;                             // Sets P1.7 SOMI SEL1

    // port 4.3 GPIO to generate acknowledge signal for SPI Master ready indication...
    P4SEL0 &= ~BIT3;                            // Clears P4.3 for GPIO through SEL0
    P4SEL1 &= ~BIT3;                            // Clears P4.3 for GPIO through SEL1
    P4DIR &= ~BIT3;                             // sets direction as output direction

    // gets the generated SMCLK on P3.4 to verify
    P3DIR |= BIT4;
    P3SEL1 |= BIT4;                             // Output SMCLK

    P1DIR |= BIT0;                              // P1.0 output
    P1OUT &= ~BIT0;                             // P1.0 output LOW, LED Off

    P1REN |= BIT1;                              // P1.1 Enable Pullup/Pulldown
    P1OUT |= BIT1;                              // P1.1 pullup
}

void configure_SPI_Master()
{
    UCB0CTLW0 |= UCSWRST;                       // Put state machine in reset
    UCB0CTLW0 |= 0x0002;                        // STE pin is used to generate the enable signal for a 4-wire slave
    UCB0CTLW0 |= 0x0080;                        // 10b = SMCLK in master mode. Don't use in slave mode
    UCB0CTLW0 |= 0x0100;                        // 1b = Synchronous mode
    UCB0CTLW0 |= 0x0400;                        // 10b = 4-pin SPI with UCxSTE active low: Slave enabled when UCxSTE = 0
    UCB0CTLW0 |= 0x0800;                        // Master Mode
    UCB0CTLW0 |= 0x2000;                        // MSB First and 8 bit data
    UCB0CTLW0 |= 0x6000;                        // 0b = Data is changed on the first UCLK edge and captured on the following edge
                                                // 1b = The inactive state is high
    UCB0BRW = 0x0010;                           // clock rate division by 16. data transfer occurs at 500 kHz only.
    UCB0CTLW0 &= ~UCSWRST;                      // **Initialize USCI state machine**
}



#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
    unsigned int i;
    for (i=0; i<5000; i++) {}                   // for software debouncing delay
    P1OUT ^= BIT0;                              // Toggle LED at P1.0
    P1IFG &= ~BIT1;                             // P1.1 IFG cleared
}

#pragma vector=PORT4_VECTOR
__interrupt void Port_4(void)
{
    P1OUT ^= BIT0;                              // Toggle LED at P1.0
    UCB0TXBUF = data1[position];
    if (position<16)
    {
        position++;
    }
    else
    {
        position = 0;
    }
    P4IFG &= ~BIT3;                             // P4.3 IFG cleared
}

/*
 *  ======== spislave.c ========
 */
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>

/* POSIX Header files */
#include <semaphore.h>
#include <unistd.h>
#include <FreeRTOS.h>

/* Driver Header files */
#include <ti/drivers/GPIO.h>
#include <ti/drivers/SPI.h>
#include <ti/display/Display.h>

/* Driver configuration */
#include "ti_drivers_config.h"

#define THREADSTACKSIZE (1024)

#define SPI_MSG_LENGTH  (1472)
#define SLAVE_MSG       ("Hello from slave, msg#: ")

#define MAX_LOOP        (1000)

unsigned char slaveRxBuffer[SPI_MSG_LENGTH];
unsigned char slaveTxBuffer[SPI_MSG_LENGTH];
unsigned long counter1 = 0;

/* Semaphore to block slave until transfer is complete */
sem_t slaveSem;

/* Status indicating whether or not SPI transfer succeeded. */
bool transferStatus;

// introducing display handle...
static Display_Handle display;

/*
 *  ======== transferCompleteFxn ========
 *  Callback function for SPI_transfer().
 */

void transferCompleteFxn(SPI_Handle handle, SPI_Transaction *transaction)
{
    // this function executes as many times as number of loop iterations..

    // printf("\n\n Entered SPI Callback function .............");
    if (transaction->status != SPI_TRANSFER_COMPLETED) {
        transferStatus = false;
    }
    else {
        transferStatus = true;
    }

    sem_post(&slaveSem);
}

// ======== slaveThread ========

void *slaveThread(void *arg0)
{
    SPI_Handle      slaveSpi;
    SPI_Params      spiParams;
    SPI_Transaction transaction;
    uint32_t        i;
    bool            transferOK;
    int32_t         status;
    char client_message[100];

    status = sem_init(&slaveSem, 0, 0);
    if (status != 0)
    {
        printf("\n Error creating slaveSem");

        while(1);
    }

    SPI_Params_init(&spiParams);
    spiParams.frameFormat = SPI_POL0_PHA0;
    spiParams.mode = SPI_SLAVE;
    spiParams.transferCallbackFxn = transferCompleteFxn;
    spiParams.transferMode = SPI_MODE_CALLBACK;
    slaveSpi = SPI_open(CONFIG_SPI_SLAVE, &spiParams);
    if (slaveSpi == NULL)
    {
        Display_printf(display, 0, 0, "\n Error initializing slave SPI");
        while (1);
    }
    else
    {
        Display_printf(display, 0, 0, "\n Slave SPI initialized");
    }

    GPIO_setConfig(CONFIG_SPI_SLAVE_READY, GPIO_CFG_OUTPUT | GPIO_CFG_OUT_LOW);
    // GPIO_setConfig(CONFIG_SPI_MASTER_READY, GPIO_CFG_INPUT);

    GPIO_write(CONFIG_SPI_SLAVE_READY, 1);
    // while (GPIO_read(CONFIG_SPI_MASTER_READY) == 0) {}

    // while (GPIO_read(CONFIG_SPI_MASTER_READY)) {}

    // Initialize slave SPI transaction structure
    memset((void *) slaveRxBuffer, 0, SPI_MSG_LENGTH);
    transaction.count = SPI_MSG_LENGTH;
    transaction.rxBuf = (void *) slaveRxBuffer;

    transferOK = SPI_transfer(slaveSpi, &transaction);
    if (transferOK)
    {
        GPIO_write(CONFIG_SPI_SLAVE_READY, 0);

        // Wait until transfer has completed
        sem_wait(&slaveSem);

        // GPIO_write(CONFIG_SPI_SLAVE_READY, 1);

        if (transferStatus == false)
        {
            printf("\n SPI transfer failed!");
        }
        else
        {
            /*if ((counter1 %100) == 0)
            {
                printf("\n Slave received: %s", slaveRxBuffer);
            }*/
            Display_printf(display, 0, 0, "Slave received: %s", slaveRxBuffer);
            // printf("\n Slave transmitted: %s", slaveTxBuffer);
            // counter1++;
        }
    }
    else
    {
        printf("\n Unsuccessful slave SPI transfer");
    }

    SPI_close(slaveSpi);

    // GPIO_setConfig(CONFIG_SPI_MASTER_READY, GPIO_CFG_OUTPUT | GPIO_CFG_OUT_LOW);
    // GPIO_write(CONFIG_SPI_SLAVE_READY, 0);

    printf("\n Done");

    while(1);

    return (NULL);
}

/*
 *  ======== mainThread ========
 */
void *mainThread(void *arg0)
{
    int                 retc;
    int                 detachState;

    /* Call driver init functions. */
    GPIO_init();
    SPI_init();
    Display_init();

    /* Open the display for output */
    display = Display_open(Display_Type_UART, NULL);
    if (display == NULL) {
        /* Failed to open display driver */
        while (1);
    }

    printf("\n Starting the SPI slave example");
    printf("\n This example requires external wires to be connected to the header pins. Please see the Readme.html and Board.html for details.");
    printf("\n\n");

    retc = xTaskCreate( slaveThread,                    // Pointer to the function that implements the task.
                        "slaveThread 1",                // Text name for the task. This is to facilitate debugging only.
                        THREADSTACKSIZE,                // Stack depth - small microcontrollers will use much less stack than this.
                        NULL,                           // This example does not use the task parameter.
                        4,                              // This task will run at Maximum priority.
                        NULL );                         // This example does not use the task handle.

    if(retc != pdPASS)
    {
        // printf("slaveThread Task Creation failed!!!");
        // printf("\n\n");
        while(1)
        {
            ;
        }
    }

    if(retc == pdPASS)
    {
        // printf("slaveThread Task Creation Succeeded !!!");
        // printf("\n\n");
    }

    while(1);

    return (NULL);
}