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.

MSP-EXP430F5529LP: SPI slave sending wrong bytes

Part Number: MSP-EXP430F5529LP

I am working on a project where I need to use the MSP430 as a SPI slave with a chip select. I have it mostly working except the wrong bytes are sometimes sent. I cant figure out why. I suspected that it might be something to do with USCI40 but I don't have clock phase select =1.

My SPI code is below companion_SPI_reset() is called from an interrupt on P2.3 that is tied to the CS line (couldn't figure out another way to reset the transactions at the end of the transmission). The interrupt triggers when the CS goes high.

/*
 * Companion.c
 *
 *  Created on: Apr 6, 2019
 *      Author: jesse
 */


#include <msp430.h>
#include "Companion.h"
#include <string.h>

//Board ID, just made this up
#define BOARD_ID        1986

struct ao_companion_command cpCmd;
const struct ao_companion_setup cpSetup={BOARD_ID,~BOARD_ID,AO_SEC_TO_TICKS(1),TLM_ITEMS};

struct telemitry_dat cpTLM={};

#define DUMMY_TX (0x05)
//char to write to if we have nothing to receive
static uint8_t dummy_Rx;

static int cp_SPI_state;

static char* rx_ptr,*rx_end;
static const char* tx_ptr,*tx_end;

void SPI_rx_ptr_setup(void *rxptr,size_t size)
{

    //set tx pointer
    rx_ptr=rxptr;

    //setup end pointer
    rx_end=((char*)rxptr)+size;
}

void SPI_tx_ptr_setup(const void *txptr,size_t size)
{

    //set tx pointer
    tx_ptr=txptr;

    //setup end pointer
    tx_end=((char*)txptr)+size;
}

void SPI_ptr_setup(void *rxptr,const void *txptr,size_t size)
{
    SPI_tx_ptr_setup(txptr,size);
    SPI_rx_ptr_setup(rxptr,size);
}

void init_Companion(void)
{
    //pull down on chip select
    P2DIR&=~BIT3;           //input
    P2OUT&=~BIT3;
    P2REN|= BIT3;
    //setup interrupt for chip select
    P2DIR&=~BIT3;           //input
    P2IES&=~BIT3;           //rising edge triggered
    P2IFG&=~BIT3;           //clear flag
    P2IE |= BIT3;           //enable interrupt


    //allow port mapping
    PMAPKEYID=PMAPKEY;

    P4MAP3 = PM_UCB1CLK;
    P4MAP0 = PM_UCB1STE;
    P4MAP2 = PM_UCB1SOMI;
    P4MAP1 = PM_UCB1SIMO;

    //allow reconfiguration
    PMAPCTL|=PMAPRECFG;
    //lock port mapping with invalid key
    PMAPKEYID=0;

    //put UCB1 in reset mode
    UCB1CTLW0|=UCSWRST;

    //set up UCB1 for SPI
     UCB1CTL0=UCMSB|UCMODE_2|UCSYNC;
     UCB1CTL1=UCSSEL_2|UCSWRST;
     //set clock rate to 1MHz
     UCB1BRW=25;
     //set clock rate to 5MHz
     //UCB1BRW=5;

     //setup pins
     P4DIR&=~(BIT0|BIT1|BIT2|BIT3);
     P4SEL|=  BIT0|BIT1|BIT2|BIT3;

     //take peripheral out of reset mode
     UCB1CTLW0&=~UCSWRST;

     //setup SPI buffers
     SPI_ptr_setup(&cpCmd,NULL,sizeof(cpCmd));

     //enable interrupts
     UCB1IE|=UCTXIE|UCRXIE;


     //set SPI data state
     cp_SPI_state=CP_COMMAND_RX;
     //output status
     P6OUT=(P6OUT&(~(BIT0|BIT1|BIT2)))|(cp_SPI_state&(BIT0|BIT1|BIT2));

}

void companion_SPI_reset(void)
{
    //disable pins
    P4SEL|=~(BIT0|BIT1|BIT2|BIT3);
    //disable interrupts
    UCB1IE&=~(UCTXIE|UCRXIE);
    //put peripheral in reset
    UCB1CTLW0|= UCSWRST;
    //put peripheral in master mode
    UCB1CTL0|= UCMST;
    //setup to receive command
    SPI_rx_ptr_setup(&cpCmd,sizeof(cpCmd));
    SPI_tx_ptr_setup(NULL,sizeof(cpCmd));
    //set next state
    cp_SPI_state=CP_COMMAND_RX;
    //output status
    P6OUT=(P6OUT&(~(BIT0|BIT1|BIT2)))|(cp_SPI_state&(BIT0|BIT1|BIT2));
    //put peripheral in slave mode
    UCB1CTL0&=~UCMST;
    //enable pins
    P4SEL|=  BIT0|BIT1|BIT2|BIT3;
    //take peripheral out of reset
    UCB1CTLW0&=~UCSWRST;
    //enable interrupts
    UCB1IE|=UCTXIE|UCRXIE;
}

/*
 * ======== SPI_ISR ========
 */
#if defined(__TI_COMPILER_VERSION__) || (__IAR_SYSTEMS_ICC__)
#pragma vector = USCI_B1_VECTOR
__interrupt void Companion_ISR (void)
#elif defined(__GNUC__) && (__MSP430__)
void __attribute__ ((interrupt(USCI_B1_VECTOR))) Companion_ISR (void)
#else
#error Compiler not found!
#endif
{
    switch(UCB1IV)

    {
    case USCI_UCRXIFG:
        if(rx_ptr==NULL){
            rx_end--;
            dummy_Rx=UCB1RXBUF;
        }else{
            *(rx_ptr++)=UCB1RXBUF;
        }
        //check if we have ended
        if(rx_ptr>=rx_end){
            //toggle bit 3 for debugging
            P6OUT^=BIT3;
            //setup next transaction
            //state has already been set
            switch(cp_SPI_state)
            {
            case CP_SETUP_TX:
                //setup for setup Tx, send dummy bytes
                SPI_rx_ptr_setup(NULL,sizeof(cpSetup));
                break;
            case CP_TLM_TX:
                //setup for TLM tx, send dummy bytes
                SPI_rx_ptr_setup(NULL,sizeof(cpTLM));
                break;
            default:
            case CP_COMMAND_RX:
                //setup to receive command
                SPI_rx_ptr_setup(&cpCmd,sizeof(cpCmd));
                break;
            }
        }
        break;
    case USCI_UCTXIFG:
        if(tx_ptr==NULL){
            UCB1TXBUF=DUMMY_TX;
            tx_end--;
        }else{
            UCB1TXBUF=*(tx_ptr++);
        }
        //check if we have ended
        if(tx_ptr>=tx_end){
            //setup next transaction
            switch(cp_SPI_state)
            {
            case CP_COMMAND_RX:
                //check what command we got
                switch(cpCmd.command)
                {
                    case AO_COMPANION_SETUP:
                        //send command
                        SPI_tx_ptr_setup(&cpSetup,sizeof(cpSetup));
                        //set next state
                        cp_SPI_state=CP_SETUP_TX;
                        break;
                    case AO_COMPANION_FETCH:
                        //send command
                        SPI_tx_ptr_setup(&cpTLM,sizeof(cpTLM));
                        //set next state
                        cp_SPI_state=CP_TLM_TX;
                        break;
                    default:
                    case AO_COMPANION_NOTIFY:
                        //send command
                        SPI_tx_ptr_setup(NULL,sizeof(cpCmd));
                        //set next state
                        cp_SPI_state=CP_COMMAND_RX;
                        break;
                }
                break;
            case CP_SETUP_TX:
            case CP_TLM_TX:
                //send command
                SPI_tx_ptr_setup(NULL,sizeof(cpCmd));
                //set next state
                cp_SPI_state=CP_COMMAND_RX;
                break;
            }
            //output status
            P6OUT=(P6OUT&(~(BIT0|BIT1|BIT2)))|(cp_SPI_state&(BIT0|BIT1|BIT2));
        }
        break;
    }
}

Here is a capture of the output. The MISO bytes in the first part of the transaction should all be 0x05's but some are 0x02's and some are 0x85's the second part is actually correct but it isn't always this way.

  • Hello Jesse,

    Thanks for your detailed post. Unfortunately, your attachment didn't come through. Can you try re-attaching it using the "Insert/Edit Media" option?

    For a SPI slave configuration with Chip Select (CS), I'd recommend looking over our 'MSP430F55xx_usci_spi_standard_slave.c' code example. There, you'll find where P2.0 was used as CS. In the SPI ISR, you can see how the CS is checked before proceeding.

    Also, you'll notice how the UCTXIFG is checked before writing to UCA0TXBUF in the code example. Try adding this check to your code since data written to UCxTXBUF when UCTXIFG = 0 may result in erroneous data transmission.

    MSP430F55xx_usci_spi_standard_slave.c

    //******************************************************************************
    //   MSP430F552x Demo - USCI_A0, SPI 3-Wire Slave multiple byte RX/TX
    //
    //   Description: SPI master communicates to SPI slave sending and receiving
    //   3 different messages of different length. SPI slave will enter LPM0
    //   while waiting for the messages to be sent/receiving using SPI interrupt.
    //   ACLK = NA, MCLK = SMCLK = DCO 16MHz.
    //
    //
    //                   MSP430F5529
    //                 -----------------
    //            /|\ |             P2.0|<- Master's GPIO (Chip Select)
    //             |  |                 |
    //             ---|RST          RST |<- Master's GPIO (To reset slave)
    //                |                 |
    //                |             P3.3|<- Data In (UCA0SIMO)
    //                |                 |
    //                |             P3.4|-> Data Out (UCA0SOMI)
    //                |                 |
    //                |             P2.7|<- Serial Clock In (UCA0CLK)
    //
    //   Nima Eskandari
    //   Texas Instruments Inc.
    //   April 2017
    //   Built with CCS V7.0
    //******************************************************************************
    
    #include <msp430.h> 
    #include <stdint.h>
    #include <stdbool.h>
    
    //******************************************************************************
    // Example Commands ************************************************************
    //******************************************************************************
    
    #define DUMMY   0xFF
    
    #define SLAVE_CS_IN     P2IN
    #define SLAVE_CS_DIR    P2DIR
    #define SLAVE_CS_PIN    BIT0
    
    /* CMD_TYPE_X_SLAVE are example commands the master sends to the slave.
     * The slave will send example SlaveTypeX buffers in response.
     *
     * CMD_TYPE_X_MASTER are example commands the master sends to the slave.
     * The slave will initialize itself to receive MasterTypeX example buffers.
     * */
    
    #define CMD_TYPE_0_SLAVE              0
    #define CMD_TYPE_1_SLAVE              1
    #define CMD_TYPE_2_SLAVE              2
    
    #define CMD_TYPE_0_MASTER              3
    #define CMD_TYPE_1_MASTER              4
    #define CMD_TYPE_2_MASTER              5
    
    #define TYPE_0_LENGTH              1
    #define TYPE_1_LENGTH              2
    #define TYPE_2_LENGTH              6
    
    #define MAX_BUFFER_SIZE     20
    
    /* MasterTypeX are example buffers initialized in the master, they will be
     * sent by the master to the slave.
     * SlaveTypeX are example buffers initialized in the slave, they will be
     * sent by the slave to the master.
     * */
    
    uint8_t MasterType2 [TYPE_2_LENGTH] = {0};
    uint8_t MasterType1 [TYPE_1_LENGTH] = { 0, 0};
    uint8_t MasterType0 [TYPE_0_LENGTH] = { 0};
    
    uint8_t SlaveType2 [TYPE_2_LENGTH] = {'A', 'B', 'C', 'D', '1', '2'};
    uint8_t SlaveType1 [TYPE_1_LENGTH] = {0x15, 0x16};
    uint8_t SlaveType0 [TYPE_0_LENGTH] = {12};
    
    //******************************************************************************
    // General SPI State Machine ***************************************************
    //******************************************************************************
    
    typedef enum SPI_ModeEnum{
        IDLE_MODE,
        TX_REG_ADDRESS_MODE,
        RX_REG_ADDRESS_MODE,
        TX_DATA_MODE,
        RX_DATA_MODE,
        TIMEOUT_MODE
    } SPI_Mode;
    
    /* Used to track the state of the software state machine*/
    SPI_Mode SlaveMode = RX_REG_ADDRESS_MODE;
    
    /* The Register Address/Command to use*/
    uint8_t ReceiveRegAddr = 0;
    
    /* ReceiveBuffer: Buffer used to receive data in the ISR
     * RXByteCtr: Number of bytes left to receive
     * ReceiveIndex: The index of the next byte to be received in ReceiveBuffer
     * TransmitBuffer: Buffer used to transmit data in the ISR
     * TXByteCtr: Number of bytes left to transfer
     * TransmitIndex: The index of the next byte to be transmitted in TransmitBuffer
     * */
    uint8_t ReceiveBuffer[MAX_BUFFER_SIZE] = {0};
    uint8_t RXByteCtr = 0;
    uint8_t ReceiveIndex = 0;
    uint8_t TransmitBuffer[MAX_BUFFER_SIZE] = {0};
    uint8_t TXByteCtr = 0;
    uint8_t TransmitIndex = 0;
    
    /* Initialized the software state machine according to the received cmd
     *
     * cmd: The command/register address received
     * */
    void SPI_Slave_ProcessCMD(uint8_t cmd);
    
    /* The transaction between the slave and master is completed. Uses cmd
     * to do post transaction operations. (Place data from ReceiveBuffer
     * to the corresponding buffer based in the last received cmd)
     *
     * cmd: The command/register address corresponding to the completed
     * transaction
     */
    void SPI_Slave_TransactionDone(uint8_t cmd);
    void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count);
    void SendUCA0Data(uint8_t val);
    
    void SendUCA0Data(uint8_t val)
    {
        while (!(UCA0IFG & UCTXIFG));              // USCI_A0 TX buffer ready?
        UCA0TXBUF = val;
    }
    
    void SPI_Slave_ProcessCMD(uint8_t cmd)
    {
        ReceiveIndex = 0;
        TransmitIndex = 0;
        RXByteCtr = 0;
        TXByteCtr = 0;
    
        switch (cmd)
        {
            case (CMD_TYPE_0_SLAVE):                        //Send slave device id (This device's id)
                SlaveMode = TX_DATA_MODE;
                TXByteCtr = TYPE_0_LENGTH;
                //Fill out the TransmitBuffer
                CopyArray(SlaveType0, TransmitBuffer, TYPE_0_LENGTH);
                //Send First Byte
                SendUCA0Data(TransmitBuffer[TransmitIndex++]);
                TXByteCtr--;
                break;
            case (CMD_TYPE_1_SLAVE):                      //Send slave device time (This device's time)
                SlaveMode = TX_DATA_MODE;
                TXByteCtr = TYPE_1_LENGTH;
                //Fill out the TransmitBuffer
                CopyArray(SlaveType1, TransmitBuffer, TYPE_1_LENGTH);
                //Send First Byte
                SendUCA0Data(TransmitBuffer[TransmitIndex++]);
                TXByteCtr--;
                break;
            case (CMD_TYPE_2_SLAVE):                  //Send slave device location (This device's location)
                SlaveMode = TX_DATA_MODE;
                TXByteCtr = TYPE_2_LENGTH;
                //Fill out the TransmitBuffer
                CopyArray(SlaveType2, TransmitBuffer, TYPE_2_LENGTH);
                //Send First Byte
                SendUCA0Data(TransmitBuffer[TransmitIndex++]);
                TXByteCtr--;
                break;
            case (CMD_TYPE_0_MASTER):
                SlaveMode = RX_DATA_MODE;
                RXByteCtr = TYPE_0_LENGTH;
                break;
            case (CMD_TYPE_1_MASTER):
                SlaveMode = RX_DATA_MODE;
                RXByteCtr = TYPE_1_LENGTH;
                break;
            case (CMD_TYPE_2_MASTER):
                SlaveMode = RX_DATA_MODE;
                RXByteCtr = TYPE_2_LENGTH;
                break;
            default:
                //while(1);
                __no_operation();
                break;
        }
    }
    
    
    void SPI_Slave_TransactionDone(uint8_t cmd)
    {
        switch (cmd)
        {
            case (CMD_TYPE_0_SLAVE):                        //Slave device id was sent(This device's id)
                break;
            case (CMD_TYPE_1_SLAVE):                      //Slave device time was sent(This device's time)
                break;
            case (CMD_TYPE_2_SLAVE):                  //Send slave device location (This device's location)
                break;
            case (CMD_TYPE_0_MASTER):
                CopyArray(ReceiveBuffer, MasterType0, TYPE_0_LENGTH);
                break;
            case (CMD_TYPE_1_MASTER):
                CopyArray(ReceiveBuffer, MasterType1, TYPE_1_LENGTH);
                break;
            case (CMD_TYPE_2_MASTER):
                CopyArray(ReceiveBuffer, MasterType2, TYPE_2_LENGTH);
                break;
            default:
                __no_operation();
                break;
        }
    }
    
    void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count)
    {
        uint8_t copyIndex = 0;
        for (copyIndex = 0; copyIndex < count; copyIndex++)
        {
            dest[copyIndex] = source[copyIndex];
        }
    }
    
    
    //******************************************************************************
    // Device Initialization *******************************************************
    //******************************************************************************
    
    void initGPIO()
    {
      //LEDs
      P1OUT = 0x00;                             // P1 setup for LED & reset output
      P1DIR |= BIT0 + BIT5;
    
      P4DIR |= BIT7;
      P4OUT &= ~(BIT7);
    
      //SPI Pins
      P3SEL |= BIT3 + BIT4;                     // P3.3,4 option select
      P2SEL |= BIT7;                            // P2.7 option select
    
    }
    
    void initSPI()
    {
      //Clock Polarity: The inactive state is high
      //MSB First, 8-bit, Master, 3-pin mode, Synchronous
      UCA0CTL1 = UCSWRST;                       // **Put state machine in reset**
      UCA0CTL0 |= UCCKPL + UCMSB + UCSYNC;      // 3-pin, 8-bit SPI Slave
      UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
      UCA0IE |= UCRXIE;                          // Enable USCI0 RX interrupt
    
      SLAVE_CS_DIR &= ~(SLAVE_CS_PIN);
    
    }
    
    void initClockTo16MHz()
    {
        UCSCTL3 |= SELREF_2;                      // Set DCO FLL reference = REFO
        UCSCTL4 |= SELA_2;                        // Set ACLK = REFO
        __bis_SR_register(SCG0);                  // Disable the FLL control loop
        UCSCTL0 = 0x0000;                         // Set lowest possible DCOx, MODx
        UCSCTL1 = DCORSEL_5;                      // Select DCO range 16MHz operation
        UCSCTL2 = FLLD_0 + 487;                   // Set DCO Multiplier for 16MHz
                                                  // (N + 1) * FLLRef = Fdco
                                                  // (487 + 1) * 32768 = 16MHz
                                                  // Set FLL Div = fDCOCLK
        __bic_SR_register(SCG0);                  // Enable the FLL control loop
    
        // Worst-case settling time for the DCO when the DCO range bits have been
        // changed is n x 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx
        // UG for optimization.
        // 32 x 32 x 16 MHz / 32,768 Hz = 500000 = MCLK cycles for DCO to settle
        __delay_cycles(500000);//
        // Loop until XT1,XT2 & DCO fault flag is cleared
        do
        {
            UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG); // Clear XT2,XT1,DCO fault flags
            SFRIFG1 &= ~OFIFG;                          // Clear fault flags
        }while (SFRIFG1&OFIFG);                         // Test oscillator fault flag
    }
    
    uint16_t setVCoreUp(uint8_t level){
        uint32_t PMMRIE_backup, SVSMHCTL_backup, SVSMLCTL_backup;
    
        //The code flow for increasing the Vcore has been altered to work around
        //the erratum FLASH37.
        //Please refer to the Errata sheet to know if a specific device is affected
        //DO NOT ALTER THIS FUNCTION
    
        //Open PMM registers for write access
        PMMCTL0_H = 0xA5;
    
        //Disable dedicated Interrupts
        //Backup all registers
        PMMRIE_backup = PMMRIE;
        PMMRIE &= ~(SVMHVLRPE | SVSHPE | SVMLVLRPE |
                    SVSLPE | SVMHVLRIE | SVMHIE |
                    SVSMHDLYIE | SVMLVLRIE | SVMLIE |
                    SVSMLDLYIE
                    );
        SVSMHCTL_backup = SVSMHCTL;
        SVSMLCTL_backup = SVSMLCTL;
    
        //Clear flags
        PMMIFG = 0;
    
        //Set SVM highside to new level and check if a VCore increase is possible
        SVSMHCTL = SVMHE | SVSHE | (SVSMHRRL0 * level);
    
        //Wait until SVM highside is settled
        while((PMMIFG & SVSMHDLYIFG) == 0)
        {
            ;
        }
    
        //Clear flag
        PMMIFG &= ~SVSMHDLYIFG;
    
        //Check if a VCore increase is possible
        if((PMMIFG & SVMHIFG) == SVMHIFG)
        {
            //-> Vcc is too low for a Vcore increase
            //recover the previous settings
            PMMIFG &= ~SVSMHDLYIFG;
            SVSMHCTL = SVSMHCTL_backup;
    
            //Wait until SVM highside is settled
            while((PMMIFG & SVSMHDLYIFG) == 0)
            {
                ;
            }
    
            //Clear all Flags
            PMMIFG &= ~(SVMHVLRIFG | SVMHIFG | SVSMHDLYIFG |
                         SVMLVLRIFG | SVMLIFG |
                         SVSMLDLYIFG
                         );
    
            //Restore PMM interrupt enable register
            PMMRIE = PMMRIE_backup;
            //Lock PMM registers for write access
            PMMCTL0_H = 0x00;
            //return: voltage not set
            return false;
        }
    
        //Set also SVS highside to new level
        //Vcc is high enough for a Vcore increase
        SVSMHCTL |= (SVSHRVL0 * level);
    
        //Wait until SVM highside is settled
        while((PMMIFG & SVSMHDLYIFG) == 0)
        {
            ;
        }
    
        //Clear flag
        PMMIFG &= ~SVSMHDLYIFG;
    
        //Set VCore to new level
        PMMCTL0_L = PMMCOREV0 * level;
    
        //Set SVM, SVS low side to new level
        SVSMLCTL = SVMLE | (SVSMLRRL0 * level) |
                   SVSLE | (SVSLRVL0 * level);
    
        //Wait until SVM, SVS low side is settled
        while((PMMIFG & SVSMLDLYIFG) == 0)
        {
            ;
        }
    
        //Clear flag
        PMMIFG &= ~SVSMLDLYIFG;
        //SVS, SVM core and high side are now set to protect for the new core level
    
        //Restore Low side settings
        //Clear all other bits _except_ level settings
        SVSMLCTL &= (SVSLRVL0 + SVSLRVL1 + SVSMLRRL0 +
                     SVSMLRRL1 + SVSMLRRL2
                     );
    
        //Clear level settings in the backup register,keep all other bits
        SVSMLCTL_backup &=
            ~(SVSLRVL0 + SVSLRVL1 + SVSMLRRL0 + SVSMLRRL1 + SVSMLRRL2);
    
        //Restore low-side SVS monitor settings
        SVSMLCTL |= SVSMLCTL_backup;
    
        //Restore High side settings
        //Clear all other bits except level settings
        SVSMHCTL &= (SVSHRVL0 + SVSHRVL1 +
                     SVSMHRRL0 + SVSMHRRL1 +
                     SVSMHRRL2
                     );
    
        //Clear level settings in the backup register,keep all other bits
        SVSMHCTL_backup &=
            ~(SVSHRVL0 + SVSHRVL1 + SVSMHRRL0 + SVSMHRRL1 + SVSMHRRL2);
    
        //Restore backup
        SVSMHCTL |= SVSMHCTL_backup;
    
        //Wait until high side, low side settled
        while(((PMMIFG & SVSMLDLYIFG) == 0) &&
              ((PMMIFG & SVSMHDLYIFG) == 0))
        {
            ;
        }
    
        //Clear all Flags
        PMMIFG &= ~(SVMHVLRIFG | SVMHIFG | SVSMHDLYIFG |
                    SVMLVLRIFG | SVMLIFG | SVSMLDLYIFG
                    );
    
        //Restore PMM interrupt enable register
        PMMRIE = PMMRIE_backup;
    
        //Lock PMM registers for write access
        PMMCTL0_H = 0x00;
    
        return true;
    }
    
    bool increaseVCoreToLevel2()
    {
        uint8_t level = 2;
        uint8_t actlevel;
        bool status = true;
    
        //Set Mask for Max. level
        level &= PMMCOREV_3;
    
        //Get actual VCore
        actlevel = PMMCTL0 & PMMCOREV_3;
    
        //step by step increase or decrease
        while((level != actlevel) && (status == true))
        {
            if(level > actlevel)
            {
                status = setVCoreUp(++actlevel);
            }
        }
    
        return (status);
    }
    
    //******************************************************************************
    // Main ************************************************************************
    // Enters LPM0 and waits for SPI interrupts. The data sent from the master is  *
    // then interpreted and the device will respond accordingly                    *
    //******************************************************************************
    
    int main(void) {
        WDTCTL = WDTPW + WDTHOLD;               // Stop watchdog timer
    
        while (!(P1IN & BIT4));                 // If clock sig from mstr stays low,
                                                // it is not yet in SPI mode
        increaseVCoreToLevel2();
        initClockTo16MHz();
        initGPIO();
        initSPI();
    
    
        __bis_SR_register(LPM0_bits + GIE);                 // Enter LPM0, enable interrupts
        __no_operation();
    	return 0;
    }
    
    
    //******************************************************************************
    // SPI Interrupt ***************************************************************
    //******************************************************************************
    
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=USCI_A0_VECTOR
    __interrupt void USCI_A0_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(USCI_A0_VECTOR))) USCI_A0_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
      uint8_t uca0_rx_val = 0;
      switch(__even_in_range(UCA0IV,4))
      {
        case 0:break;                             // Vector 0 - no interrupt
        case 2:
            uca0_rx_val = UCA0RXBUF;
            if (!(SLAVE_CS_IN & SLAVE_CS_PIN))
            {
                switch (SlaveMode)
                {
                      case (RX_REG_ADDRESS_MODE):
                          ReceiveRegAddr = uca0_rx_val;
                          SPI_Slave_ProcessCMD(ReceiveRegAddr);
                          break;
                      case (RX_DATA_MODE):
                          ReceiveBuffer[ReceiveIndex++] = uca0_rx_val;
                          RXByteCtr--;
                          if (RXByteCtr == 0)
                          {
                              //Done Receiving MSG
                              SlaveMode = RX_REG_ADDRESS_MODE;
                              SPI_Slave_TransactionDone(ReceiveRegAddr);
                          }
                          break;
                      case (TX_DATA_MODE):
                          if (TXByteCtr > 0)
                          {
                              SendUCA0Data(TransmitBuffer[TransmitIndex++]);
                              TXByteCtr--;
                          }
                          if (TXByteCtr == 0)
                          {
                              //Done Transmitting MSG
                              SlaveMode = RX_REG_ADDRESS_MODE;
                              SPI_Slave_TransactionDone(ReceiveRegAddr);
                          }
                          break;
                      default:
                          __no_operation();
                          break;
                }
            }
            break;
        case 4:break;                             // Vector 4 - TXIFG
        default: break;
      }
    }

    Regards,

    James

  • The picture I tried to attach before is shown below. the clock rate is fairly slow 180kHz I think. D1 is chip select

    For the code I use the SPI interrupts so I am, in effect, checking the flags. So, CS like that won't work in this application cause there are other devices on the bus so CS is needed to disable the outputs from the slave. Also the CS pin is used for framing and I'd like to force that in the code.

  • Turns out the issue was the clock phase setting in the SPI

**Attention** This is a public forum