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.

MSP432P401R: SPI Peripheral outputs data on MOSI, but no clock

Part Number: MSP432P401R

I'm configuring one of the EUSCI_A modules as a master SPI interface. Before my custom board with an MSP432 arrived, I bought an MSP432 LaunchPad and began developing code on the dev board. Now, I'm moving my development code over to my custom board. My development code successfully configures a EUSCI_B module to work as a master SPI, verified with a logic analyzer. My custom board is attempting to use a EUSCI_A.

When I move the same code over to my custom board, change EUSCIs because the custom board has different pins connected, and try to run the SPI peripheral I get an output on the MOSI pin, but no CLK or CS. I can get data on the MOSI pin by polling or by using interrupts. I've triple checked how I'm configuring the SEL0 and SEL1 registers for my desired pins. The DIR for the pins should be handled by the peripheral. I've also measured to make sure my CLK pin isn't tied to ground somehow.

Not really sure what to troubleshoot next.

Thanks for the help!

  • Hey Jamse,

    Would love to help, can you first share your code? If not all of it, at least your code snippets that you use to setup the SPI CLK source, the clock configurations for your device and the EUSCI settings and desired port/pin numbers that you wish to use?
  • Here's the initialization:

    Here's the register view after loading and running the code:

    I was able to apply the same initialization code to a EUSCI_B on the custom PCB and have it work as expected, so I believe it's something particular about EUSCI_A SPI vs EUSCI_B SPI. Also, EUSCI_A1 is using Port 2 which has Port Mapping as an option. My understanding is that using the Port 2 pins for the EUSCI is the default Port Mapping and I shouldn't have to deliberately re-configure anything? But just in case, here are the PMAP registers:

    To test the SPI peripheral, I'm just putting 0xAA into the transmit buffer on a timer interrupt.

    If you have any other questions, please let me know. Thank you for the help!

    -James

  • mse,

    Given what you've given me, I thought the best bet would be to create a working code example using eUSCI A1 for you with SMCLK as the source, using DCO to feed MLCK=SMCLK at 12MHz. I used your BRW as well of 0x0018. The resultant was a code example that had a BRW CLK of 500kHz and can effectively communicate with a slave. Master sends a byte, slave echos the byte back. Master receives, checks the received byte to see if it was accurate. if it is not accurate, a red LED on the LaunchPad (P1.0) goes high.

    My setup is two Red LaunchPads running Rev C silicon using P2.0 for STE/CS, P2.1 as A1CLK, P2.2 as SOMI, P2.3 as MISO. Please see the attached.

    msp432p401x_euscia1_spi_slave.c
    #include "ti/devices/msp432p4xx/inc/msp.h"
    
    int main(void)
    {
        WDT_A->CTL = WDT_A_CTL_PW |             // Stop watchdog timer
                WDT_A_CTL_HOLD;
    
        P2->SEL0 |= BIT0 | BIT1 | BIT2 | BIT3;  // set 4-SPI pin as second function
    
        CS->KEY = CS_KEY_VAL ;                  // Unlock CS module for register access
        CS->CTL0 = 0;                           // Reset tuning parameters
        CS->CTL0 = CS_CTL0_DCORSEL_3;           // Set DCO to 12MHz (nominal, center of 8-16MHz range)
        // Select ACLK = REFO, SMCLK = MCLK = DCO
        CS->CTL1 = CS_CTL1_SELA_2 | CS_CTL1_SELS_3 | CS_CTL1_SELM_3;
        CS->KEY = 0;                            // Lock CS module from unintended accesses
    
        EUSCI_A1->CTLW0 |= EUSCI_A_CTLW0_SWRST; // Put state machine in reset
                                                // 4-pin, 8-bit SPI slave
        EUSCI_A1->CTLW0 = EUSCI_A_CTLW0_SWRST |
                EUSCI_A_CTLW0_SYNC |            // Synchronous mode
                EUSCI_A_CTLW0_CKPL |            // Clock polarity high
                EUSCI_A_CTLW0_MSB |             // MSB first
                EUSCI_A_CTLW0_MODE_1 |          // 4-pin SPI mode
                EUSCI_A_CTLW0_STEM |            // STE mode select
                EUSCI_A_CTLW0_SSEL__SMCLK;       // ACLK
        EUSCI_A1->BRW = 0x0018;                   // /2,fBitClock = fBRCLK/(UCBRx+1).
        EUSCI_A1->CTLW0 &= ~EUSCI_A_CTLW0_SWRST;// **Initialize USCI state machine**
        EUSCI_A1->IE |= EUSCI_A_IE_RXIE;        // Enable USCI_A1 RX interrupt
    
        // Remain in LPM on exit from ISR
        SCB->SCR |= SCB_SCR_SLEEPONEXIT_Msk;
    
        // Ensures SLEEPONEXIT takes effect immediately
        __DSB();
    
        // Enable global interrupt
        __enable_irq();
    
        // Enable eUSCI_A1 interrupt in NVIC module
        NVIC->ISER[0] = 1 << ((EUSCIA1_IRQn) & 31);
    
        // Enter LPM0
        __sleep();
    
        __no_operation();                       // for debug
    }
    
    // SPI interrupt service routine
    void EUSCIA1_IRQHandler(void)
    {
        if (EUSCI_A1->IFG & EUSCI_A_IFG_RXIFG)
        {
            // USCI_A1 TX buffer ready?
            while (!(EUSCI_A1->IFG & EUSCI_A_IFG_TXIFG));
    
            // Echo received data
            EUSCI_A1->TXBUF = EUSCI_A1->RXBUF;
        }
    }
    
    

    msp432p401x_euscia1_spi_master.c
    #include "ti/devices/msp432p4xx/inc/msp.h"
    #include <stdint.h>
    
    uint8_t RXData = 0;
    uint8_t TXData;
    
    int main(void)
    {
        volatile uint32_t i;
        uint8_t previousData;
    
        WDT_A->CTL = WDT_A_CTL_PW |             // Stop watchdog timer
                WDT_A_CTL_HOLD;
    
        P1->OUT &= ~BIT0;
        P1->DIR |= BIT0;                        // Configure P1.0 LED as output
    
        P2->SEL0 |= BIT0 | BIT1 | BIT2 | BIT3;  // set 4-SPI pin as second function
    
        CS->KEY = CS_KEY_VAL ;                  // Unlock CS module for register access
        CS->CTL0 = 0;                           // Reset tuning parameters
        CS->CTL0 = CS_CTL0_DCORSEL_3;           // Set DCO to 12MHz (nominal, center of 8-16MHz range)
        // Select ACLK = REFO, SMCLK = MCLK = DCO
        CS->CTL1 = CS_CTL1_SELA_2 | CS_CTL1_SELS_3 | CS_CTL1_SELM_3;
        CS->KEY = 0;                            // Lock CS module from unintended accesses
    
        EUSCI_A1->CTLW0 |= EUSCI_A_CTLW0_SWRST; // Put state machine in reset
    
        EUSCI_A1->CTLW0 = EUSCI_A_CTLW0_SWRST | // Remain in reset state
                EUSCI_A_CTLW0_MST |             // SPI master
                EUSCI_A_CTLW0_SYNC |            // Synchronous mode
                EUSCI_A_CTLW0_CKPL |            // Clock polarity high
                EUSCI_A_CTLW0_MSB |             // MSB first
                EUSCI_A_CTLW0_MODE_1 |          // 4-pin mode
                EUSCI_A_CTLW0_STEM |            // STE mode select
                EUSCI_A_CTLW0_SSEL__SMCLK;       // SMCLK
    
        EUSCI_A1->BRW = 0x0018;                   // /2,fBitClock = fBRCLK/(UCBRx+1).
        EUSCI_A1->CTLW0 &= ~EUSCI_A_CTLW0_SWRST;// **Initialize USCI state machine**
        TXData = 0x01;                          // Holds TX data
    
        // Enable global interrupt
        __enable_irq();
    
        // Enable eUSCIA1 interrupt in NVIC module
        NVIC->ISER[0] = 1 << ((EUSCIA1_IRQn) & 31);
    
        // Wake up on exit from ISR
        SCB->SCR &= ~SCB_SCR_SLEEPONEXIT_Msk;
    
        // Ensures SLEEPONEXIT takes effect immediately
        __DSB();
    
        while(1)
        {
            EUSCI_A1->IFG |= EUSCI_A_IFG_TXIFG; // Clear TXIFG flag
            EUSCI_A1->IE |= EUSCI_A__TXIE;      // Enable TX interrupt
    
            // Enter LPM0
            __sleep();
            __no_operation();                    // For debug
    
            // Check the received data
            previousData = TXData - 1;
            if (RXData != (previousData))
            {
                // If the Received data is not equal to TXData-1, then
                // Set P1.0 LED
                P1->OUT |= BIT0;
            }
            else
            {
                P1->OUT &= ~BIT0;
            }
    
            for (i = 2000; i > 0; i--);          // Delay before next transmission
            TXData++;                            // Increment transmit data
        }
    }
    
    // SPI interrupt service routine
    void EUSCIA1_IRQHandler(void)
    {
        if (EUSCI_A1->IFG & EUSCI_A_IFG_TXIFG)
        {
            // Transmit characters
            EUSCI_A1->TXBUF = TXData;
    
            // Disable tx interrupt
            EUSCI_A1->IE &= ~EUSCI_A__TXIE;
    
            // Wait till a character is received
            while (!(EUSCI_A1->IFG & EUSCI_A_IFG_RXIFG));
    
            // Move data to a temporary buffer
            RXData = EUSCI_A1->RXBUF;
    
            // Clear the receive interrupt flag
            EUSCI_A1->IFG &= ~EUSCI_A_IFG_RXIFG;
        }
    }
    

    Please let me know if you have any other questions. My suggestion is to review this, see if you can get it to work on the LaunchPads, then move to your custom board. That way, you can determine if it's your board, or the code you have written. 

  • Thanks Evan,

    I only have one LaunchPad, but I can use a logic analyzer/scope to verify that I'm at least getting a clock and data. 

    For the record, I have a 48 MHz crystal that I'm using as an oscillator on my custom board. I've tried using both the DCO and the 48 MHz external oscillator to the drive the peripheral with the same result.

    I'm currently load testing the power supply on the board, but that will be finished this afternoon. I can test your code on the LaunchPad in the meantime.

    Cheers!

    -James

  • Sounds good! If you find the tests do work on your launchpad with my code, the next step would be to look at your HFXT settings to ensure it's properly getting started and sourcing SMCLK for eUSCI A1.
  • Thanks for the help, Evan!

    Your example code got everything up and running. Now I'm moving onto an issue with my external crystal, but I think that's another thread.

    Cheers!

    -James

**Attention** This is a public forum