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.

MSP430FR2100: MSP430FR2100 eUSCI in SPI mode missing interrupts and bit shift

Part Number: MSP430FR2100
Other Parts Discussed in Thread: MSP430FR4133, MSP430FR2000, MSP430WARE, MSP-EXP430FR4133

Hi,

I am having some trouble with the eUSCI of the MSP430FR2100 in SPI mode.

The code below is a simplified version of the example "msp430fr211x_eusci_spi_standard_slave.c" with added support for the "MSP430FR4133 LaunchPad Development Kit".

(MSP430Ware_3_80_04_05/examples/devices/MSP430FR2xx_4xx/MSP430FR21xx_MSP430FR2000_Code_Examples/C/msp430fr211x_eusci_spi_standard_slave.c)

As seen in the interrupt routine each received char is simply written to the transmit register unless the value is 0xAA in which case 0x00 is written.

Placing an interrupt at line 136 "if (uca0_rx_val == 0xAA)" and running the code on the MSP430FR4133 works as expected.

However when the code is run on the MSP430FR2100 the break-point in the interrupt routine is only hit for every 8th char received. Also the transmitted char is shifted as seen below:

root@host:~# spidev_test -D /dev/spidev0.0 -H -O -s 1000 -v -p "\x10"
spi mode: 0x3
bits per word: 8
max speed: 1000 Hz (1 KHz)
TX | 10 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | .
RX | 01 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | .
root@host:~# spidev_test -D /dev/spidev0.0 -H -O -s 1000 -v -p "\x10"
spi mode: 0x3
bits per word: 8
max speed: 1000 Hz (1 KHz)
TX | 10 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | .
RX | 02 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | .
root@host:~# spidev_test -D /dev/spidev0.0 -H -O -s 1000 -v -p "\x10"
spi mode: 0x3
bits per word: 8
max speed: 1000 Hz (1 KHz)
TX | 10 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | .
RX | 04 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | .
root@host:~# spidev_test -D /dev/spidev0.0 -H -O -s 1000 -v -p "\x10"
spi mode: 0x3
bits per word: 8
max speed: 1000 Hz (1 KHz)
TX | 10 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | .
RX | 08 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | .
root@host:~# spidev_test -D /dev/spidev0.0 -H -O -s 1000 -v -p "\x10"
spi mode: 0x3
bits per word: 8
max speed: 1000 Hz (1 KHz)
TX | 10 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | .
RX | 10 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | .

Does anybody have an idea about what is going on here and how to solve this issue.

Best regards,
Anders

//******************************************************************************
//   MSP430FR211x Demo - eUSCI_A0, SPI 4-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.
//
//
//                   MSP430FR2111
//                 -----------------
//            /|\ |             RST |<- Master's GPIO (To reset slave)
//             |  |                 |
//             ---|RST          P1.7|<- Data In (UCA0SIMO)
//                |                 |
//                |             P1.6|-> Data Out (UCA0SOMI)
//                |                 |
//                |             P1.5|<- Serial Clock In (UCA0CLK)
//                |                 |
//                |             P1.4|<- Master's GPIO (UCA0STE)
//
//   Nima Eskandari and Ryan Meredith
//   Texas Instruments Inc.
//   February 2018
//   Built with CCS V7.3
//******************************************************************************

#include <msp430.h> 
#include <stdint.h>
#include <stdbool.h>

//******************************************************************************
// Device Initialization *******************************************************
//******************************************************************************

void initSPI()
{
#ifdef __MSP430FR4133__
    UCB0CTLW0 = UCSWRST;                       // **Put state machine in reset**
    UCB0CTLW0 |= UCCKPL | UCMSB | UCSYNC | UCMODE_2;    // 4-pin, 8-bit SPI Slave
    UCB0CTLW0 &= ~UCSWRST;                     // **Initialize USCI state machine**
    UCB0IE |= UCRXIE;                          // Enable USCI0 RX interrupt
#else
    //Clock Polarity: The inactive state is high
    //MSB First, 8-bit, Master, 4-pin mode, Synchronous
    UCA0CTLW0 = UCSWRST;                       // **Put state machine in reset**
    UCA0CTLW0 |= UCCKPL | UCMSB | UCSYNC | UCMODE_2;    // 4-pin, 8-bit SPI Slave
    UCA0CTLW0 &= ~UCSWRST;                     // **Initialize USCI state machine**
    UCA0IE |= UCRXIE;                          // Enable USCI0 RX interrupt
#endif
}

void initGPIO()
{
    // Configure GPIO
#ifdef __MSP430FR4133__
    P5SEL0 |= BIT0 | BIT1 | BIT2 | BIT3;
#else
    P1SEL0 |= BIT4 | BIT5 | BIT6 | BIT7;      // Configure SPI pins
#endif
//    P1SEL1 = 0x00;

    // Disable the GPIO power-on default high-impedance mode to activate
    // previously configured port settings
    PM5CTL0 &= ~LOCKLPM5;
}

void initClockTo16MHz()
{
    // Configure one FRAM waitstate as required by the device datasheet for MCLK
    // operation beyond 8MHz _before_ configuring the clock system.
    FRCTL0 = FRCTLPW | NWAITS_1;

    __bis_SR_register(SCG0);    // disable FLL
    CSCTL3 |= SELREF__REFOCLK;  // Set REFO as FLL reference source
    CSCTL0 = 0;                 // clear DCO and MOD registers
    CSCTL1 &= ~(DCORSEL_7);     // Clear DCO frequency select bits first
    CSCTL1 |= DCORSEL_5;        // Set DCO = 16MHz
    CSCTL2 = FLLD_0 + 487;      // set to fDCOCLKDIV = (FLLN + 1)*(fFLLREFCLK/n)
                                //                   = (487 + 1)*(32.768 kHz/1)
                                //                   = 16 MHz

    __delay_cycles(3);
    __bic_SR_register(SCG0);                        // enable FLL
    while(CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1));      // FLL locked
}


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

    initClockTo16MHz();
    initGPIO();
    initSPI();

    __bis_SR_register(LPM0_bits + GIE);                 // Enter LPM0, enable interrupts
    __no_operation();

    return 0;
}

//******************************************************************************
// SPI Interrupt ***************************************************************
//******************************************************************************

#ifdef __MSP430FR4133__
#pragma vector=USCI_B0_VECTOR
__interrupt void USCI_B0_ISR(void)
#else
#pragma vector=USCI_A0_VECTOR
__interrupt void USCI_A0_ISR(void)
#endif
{
    uint8_t uca0_rx_val = 0;
#ifdef __MSP430FR4133__
    switch(__even_in_range(UCB0IV, USCI_SPI_UCTXIFG))
#else
    switch(__even_in_range(UCA0IV, USCI_SPI_UCTXIFG))
#endif
    {
        case USCI_NONE: break;
        case USCI_SPI_UCRXIFG:
#ifdef __MSP430FR4133__
            uca0_rx_val = UCB0RXBUF;
            UCB0IFG &= ~UCRXIFG;
#else
            uca0_rx_val = UCA0RXBUF;
            UCA0IFG &= ~UCRXIFG;
#endif
            if (uca0_rx_val == 0xAA)
                uca0_rx_val = 0x00;

#ifdef __MSP430FR4133__
            while (!(UCB0IFG & UCTXIFG));              // USCI_A0 TX buffer ready?
            UCB0TXBUF = uca0_rx_val;
#else
            while (!(UCA0IFG & UCTXIFG));              // USCI_A0 TX buffer ready?
            UCA0TXBUF = uca0_rx_val;
#endif
            break;
        case USCI_SPI_UCTXIFG:
            break;
        default:
            break;
    }
}

  • Hi,

    Does the official code example work? Is there any problem with the hardware or slave? I think the best way to figure out this question is capture the signal using oscilloscope.

    B.R
    Winter
  • Hi,

    Sorry that I left out a few details in the initial message.
    The MSP430FR is used as a 4-wire SPI slave in my application.
    I have verified SPI data send and received using a Saleae logic analyzer and they match the output from spidev_test.
    The signals have also been verified using a scope.

    I have not tested the original code example directly as it is quite complicated. Instead I have removed the state machine handling and simplified the interrupt routine to implement a simple loop-back. The initialization code is used unmodified.

    I have added support for the MSP430FR4133 MCU and tested the SW successfully on an evaluation board as mentioned above.
    The SW behavior on the MSP430FR2100 MCU however is very strange with regards to interrupts and data transmitted.

    Best regards
    Anders
  • Hi again,

    Tried changing the SPI mode from 0x3 to 0x0 (by replacing UCCKPL with UCCKPH) and that solves the byte shift issue.

    Still only get an interrupt for every 8th char though. I see the following behavior.

    - First char triggers the RX interrupt
    - The next 7 chars does not trigger the RX interrupt
    - 8th char triggers the RX interrupt

    and so on as seen below. The code works perfectly on the MSP430FR4133 as before.

    root@host:~# spidev_test -D /dev/spidev0.0 -s 40000 -p "\x01" -v
    spi mode: 0x0
    bits per word: 8
    max speed: 40000 Hz (40 KHz)
    TX | 01 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | .
    RX | 00 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | .
    root@host:~# spidev_test -D /dev/spidev0.0 -s 40000 -p "\x02" -v
    spi mode: 0x0
    bits per word: 8
    max speed: 40000 Hz (40 KHz)
    TX | 02 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | .
    RX | 01 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | .
    root@host:~# spidev_test -D /dev/spidev0.0 -s 40000 -p "\x02" -v
    spi mode: 0x0
    bits per word: 8
    max speed: 40000 Hz (40 KHz)
    TX | 02 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | .
    RX | 01 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | .
    root@host:~# spidev_test -D /dev/spidev0.0 -s 40000 -p "\x02" -v
    spi mode: 0x0
    bits per word: 8
    max speed: 40000 Hz (40 KHz)
    TX | 02 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | .
    RX | 01 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | .
    root@host:~# spidev_test -D /dev/spidev0.0 -s 40000 -p "\x02" -v
    spi mode: 0x0
    bits per word: 8
    max speed: 40000 Hz (40 KHz)
    TX | 02 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | .
    RX | 01 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | .
    root@host:~# spidev_test -D /dev/spidev0.0 -s 40000 -p "\x02" -v
    spi mode: 0x0
    bits per word: 8
    max speed: 40000 Hz (40 KHz)
    TX | 02 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | .
    RX | 01 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | .
    root@host:~# spidev_test -D /dev/spidev0.0 -s 40000 -p "\x02" -v
    spi mode: 0x0
    bits per word: 8
    max speed: 40000 Hz (40 KHz)
    TX | 02 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | .
    RX | 01 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | .
    root@host:~# spidev_test -D /dev/spidev0.0 -s 40000 -p "\x02" -v
    spi mode: 0x0
    bits per word: 8
    max speed: 40000 Hz (40 KHz)
    TX | 02 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | .
    RX | 01 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | .
    root@host:~# spidev_test -D /dev/spidev0.0 -s 40000 -p "\x02" -v
    spi mode: 0x0
    bits per word: 8
    max speed: 40000 Hz (40 KHz)
    TX | 02 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | .
    RX | 01 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | .
    root@host:~# spidev_test -D /dev/spidev0.0 -s 40000 -p "\x02" -v
    spi mode: 0x0
    bits per word: 8
    max speed: 40000 Hz (40 KHz)
    TX | 02 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | .
    RX | 02 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | .
    root@host:~#

  • Screenshot of Saleae logic data capture using SPI mode 0x0 (UCCKPL = 0,  UCCKPH = 1). Only interrupt for every 8th char on the MSP430FR2100.

    Could it be a problem that the clock is running after the CS is deasserted?

  • Here is the Saleae logic analyzer output from the MSP430FR4133 setup that is using an RPI and spidev_test as the master. Notice that on the MSP430FR2100 test setup above there is 9 clock periods and only 8 on the MSP430FR4133 setup. Could this be the cause of only getting an USCI_SPI_UCRXIFG interrupt for every 8th char received?

  • Hi,

    I see that there is a byte count UCB0TBCNT for interrupt in I2C mode on eUSCI port B. Could there be a similar hidden count register for SPI on port A?

    Regards
    Anders
  • Tried to connect the MSP430FR4133 MCU to the MSP430FR2100 SPI master using the measuring wires soldered on the prototype board. Using this setup I get an interrupt for every char. Therefore the missing interrupt issue must be caused by missing configuration of the MSP430FR2100. However the sample code does not provide any clue about what is missing. It seems to have been only tested on the MSP-EXP430FR4133 evaluation board.

  • Have also tried using the SPI init function from the example http://www.ti.com/lit/pdf/slaa807

    void initSPI(void)
    {
        P1SEL0 |= BIT4 | BIT5 | BIT6 | BIT7;           // set 4-SPI pin as second function
    
        UCA0CTLW0 |= UCSWRST;                          // **Put state machine in reset**
                                                       // 4-pin, 8-bit SPI slave
        UCA0CTLW0 |= UCSYNC|UCCKPH|UCMSB|UCMODE_2|UCSTEM|UCSSEL__SMCLK;
                                                       // SPI mode is selected when the UCSYNC bit is set
                                                       // Clock polarity inactive state high
                                                       // MSB first, 8-bit character length
                                                       // 4-pin SPI with STE active low
                                                       // STE pin generates the enable signal for 4-wire slave
                                                       // eUSCI clock source select SMCLK
        UCA0BR0 = 0x01;                                // Bit clock prescaler setting: BRCLK = SMCLK/1
        UCA0MCTLW = 0;                                 // clear MCTLW when using SPI mode for eUSCI_A
        UCA0CTLW0 &= ~UCSWRST;                         // **Initialize USCI state machine**
        UCA0IE |= UCRXIE;                              // Enable USCI_A0 RX interrupt
    }

    However this makes no difference. Interrupts are still misbehaving.

    Also tried running the ASM example "MSP430Ware_3_80_04_05/examples/devices/MSP430FR2xx_4xx/MSP430FR413x_MSP430FR203x_Code_Examples/Assembly_CCS/msp430fr413x_uscia0_spi_12.asm" with the same result. Had to modify it slightly to match the HW of cause as shown below:

    --- msp430fr413x_uscia0_spi_12.asm	2018-04-30 19:30:00.000000000 +0200
    +++ workspace_v8/msp430_asm_test/msp430fr413x_uscia0_spi_12.asm	2018-11-02 12:50:08.079405737 +0100
    @@ -86,11 +86,12 @@
     RESET       mov.w   #__STACK_END,SP         ; Initialize stack pointer
                 mov.w    #WDTPW+WDTHOLD,&WDTCTL ; Stop WDT
                 
    -            bis.b    #BIT0+BIT1+BIT2,&P1SEL0
    +            bis.b    #BIT4+BIT5+BIT6+BIT7,&P1SEL0
                 bis.w    #UCSWRST,&UCA0CTLW0    ; **Put state machine in reset**
    -            bis.w    #UCSYNC+UCCKPL+UCMSB,&UCA0CTLW0 ; 3-pin, 8-bit SPI master
    +            bis.w    #UCCKPH+UCMSB+UCSYNC+UCMODE_2,&UCA0CTLW0 ; 4-pin, 8-bit SPI master
                                                          ; Clock polarity high, MSB
    -            bis.w    #UCSSEL__MODCLK,&UCA0CTLW0        ; MODCLK
    +;            bis.w    #UCSSEL__MODCLK,&UCA0CTLW0        ; ACLK
    +            bis.w    #UCSSEL_2,&UCA0CTLW0        ; ACLK
                 mov.b    #0x01,&UCA0BR0         ; /2
                 clr.b    &UCA0BR1
                 clr.w    &UCA0MCTLW             ; No modulation
    

  • Did some more investigating by disconnecting the MIPS SPI master and connecting the RPI SPI master to the MSP430FR2100. Turns out that it is the extra clock pulse that is the cause of the problem. Sorry for the noise.

**Attention** This is a public forum