Other Parts Discussed in Thread: MSP430WARE
Tool/software: Code Composer Studio
I'm working on a project with an MSP430F67621A, in which I need to send data from two MSP430s to a Linux-based host. The three devices are connected over SPI, with a chip select line from the Linux host to each MSP430. The Linux host is the SPI master, and the MSP430s are slaves.
I am seeing a strange issue, whereby if I have the MSP430 eUSCI module configure in 3-pin SPI slave mode everything seems to be OK, but when I try to use 4-pin mode the MSP430 only responds to the master on the very first occasion - every time after that, the slave does not respond. (Note that although I do have two MSP430s to talk to, this example is running on just one of them, with the second being disabled).
It seems to not matter how many bytes I read in the one transfer from the master, I always get data the first time and then get zeroes on subsequent transfers. I've mapped the STE pin to P2.7.
I've set up a basic Code Composer Studio project that demonstrates the problem, this is the main.c file:
#include <stdio.h> #include <msp430.h> #include <stdint.h> uint8_t send_bytes[] = \ { 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x01, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x02, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x03, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x04, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x05, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x06, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x07, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x08, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x09, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x0A, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x0B, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x0C, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x0D, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x0E, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x0F }; const uint8_t send_len = 120; uint8_t send_ctr = 0; int main(void) { WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer // Enable global interrupt __bis_SR_register(GIE); // Configure SPI pins to secondary function mode P1SEL |= BIT4 | BIT5; // P1.4 + P1.5 (UCA1SOMI, UCA1SIMO) P2SEL |= BIT4; // P2.4 (UCA1CLK) // Configure SPI 'STE' pin PMAPPWD = PMAPPW; // Enable Write-access to modify port mapping registers P2SEL |= BIT7; // Set P2.7 as secondary function mode P2MAP7 = PM_UCA1STE; // Map to UCA1STE function // Put USCI state machine into reset, so that options can be changed UCA1CTLW0 = UCSWRST; /* * UCA1CTLW0: USCI_A1 Control Register * Bit fields mean the following: * UCCKPH: Clock phase select * UCCKPL: Clock polarity select * UCMSB: MSB first select * UC7BIT: Character length * UCMST: Master mode select * UCMODEx: USCI mode * UCSYNC: Synchronous mode enable */ UCA1CTLW0 = UCCKPH | // 1b = Data is captured on the first UCLK edge and changed on the following edge //UCCKPL | // 0b = The inactive state is low UCMSB | // 1b = MSB first //UC7BIT | // 0b = 8-bit data //UCMST | // 0b = Slave mode UCMODE_2 | // 10b = 4-pin SPI with UCxSTE active low: Slave enabled when UCxSTE = 0 UCMODE_0 | // 00b = 3-pin SPI UCSYNC; // 1b = Synchronous mode /* * UCA1BR0: USCI_A1 Bit Rate Control Register 0 * UCA1BR1: USCI_A1 Bit Rate Control Register 1 * Bit clock prescaler bytes. The 16-bit value of * (UCA1BR0 + UCA1BR1 × 256) forms the prescaler * value UCBR1. */ UCA1BR0 = 0x02; UCA1BR1 = 0; // Take USCI state machine out of reset, starting it with the given options UCA1CTLW0 &= ~UCSWRST; /* * UCA1IE: USCI_A1 Interrupt Enable Register * UCTXIE: Transmit interrupt enable * UCRXIE: Receive interrupt enable */ UCA1IE |= UCRXIE; // Enable the RX interrupt // UCA1IE |= UCTXIE; // Enable the TX interrupt } //// USCI_A1 interrupt vector service routine. #if defined(__TI_COMPILER_VERSION__) #pragma vector=USCI_A1_VECTOR __interrupt #elif defined(__GNUC__) __attribute__((interrupt(USCI_A1_VECTOR))) #endif void USCI_A1_ISR (void) { switch (__even_in_range(UCA1IV,2)){ //Vector 2 - RXIFG case 2: // Wait for USCI_A1 TX buffer to be ready while (!(UCA1IFG & UCTXIFG)); // Send over SPI UCA1TXBUF = send_bytes[send_ctr]; send_ctr++; if(send_ctr > send_len){ send_ctr = 0; } break; default: break; } }
EDIT: Updated array and length in example
Is there something I need to do to re-enable the eUSCI module after it has been triggered as a slave by the STE pin?