Hello,
I'm using the MSP430F5438. The peripheral in question is the SPI bus when configured as Slave and the uC is in LPM3 mode. When that happens, I cannot receive data from the master uC although the uC is waken by the ISR.
If the uC is in LPM1, then there is no problem. The uC is supposed to go into LPM, then wake up when a byte is received. Below is the configuration, ISR and a couple of processing routines.
//-------------------------------------------------------------------------
// Spi::Init() -- Initialize serial interface to MCU3.
//-------------------------------------------------------------------------
void Spi::Init()
{
rxIdx=0; txIdx=0; usingPing=true; InTransit=false; appBuffPtr=0;
bufferReady=false; state=sIdle;
// Indicate "ready to use"
pingBuffer[0] = 0;
pongBuffer[0] = 0;
// uC interface.
P9SEL |= BIT1 | BIT2 | BIT3; // Select P9 for SPI
P9DIR |= BIT2; // SOMI (output)
P9DIR &= ~BIT1; // SIMO (input)
P9DIR &= ~BIT3; // CLK_IN
UCB2CTL1 |= UCSWRST; // Put state machine in reset
UCB2CTL0 |= UCMSB + UCSYNC + UCCKPL; // 3-pin, 8-bit SPI slave
// Clock polarity high, MSB
UCB2CTL1 |= UCSSEL_2; // SMCLK
UCB2BR0 = 0x02; // /2
UCB2BR1 = 0; //
UCA2MCTL = 0; // No modulation
UCB2CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
UCB2IE |= UCRXIE; // Enable USCI_B2 RX interrupt
UCB2IFG &= ~UCRXIFG;
UCB2TXBUF= 0x00; // Idle.
}
//-------------------------------------------------------------------------
// USCI_B2 Interrupt Service Routing
//-------------------------------------------------------------------------
#pragma vector=USCI_B2_VECTOR
__interrupt void USCI_B2_ISR(void)
{
UserInterfaceMcu & PI = UserInterfaceMcu::Instance();
int code = __even_in_range(UCB2IV,4);
switch(code)
{
case 0: // Transmit ISR
break;
case 2: // Receive ISR
switch(PI.McuComm().state)
{
case Spi::sIdle:
PI.McuComm().StartTxRxProcess();
break;
case Spi::sTransmit:
PI.McuComm().TransmitByte();
UCB2IFG &= ~UCRXIFG; // To clear interrupt.
break;
case Spi::sReceive:
PI.McuComm().ReceiveByte();
break;
default:
break;
}
break;
case 4:
default:
break;
}
__low_power_mode_off_on_exit();
}
//-------------------------------------------------------------------------
// void StartReceiveProcess()
//-------------------------------------------------------------------------
void Spi::StartTxRxProcess()
{
rxIdx = 0;
txIdx = 0;
unsigned char rxByte = UCB2RXBUF;
if (rxByte == 0x00)
{
if (InTransit) // Change variable name !!!
{
Mutex m;
state = sTransmit;
TransmitByte();
}
}
else
{
if (rxByte == cRqstToSend)
{
Mutex m;
state = sReceive;
}
}
}
//-------------------------------------------------------------------------
// TransmitByte()
//-------------------------------------------------------------------------
void Spi::TransmitByte()
{
static unsigned char bytesRemaining = 0;
switch (txIdx++)
{
case 0:
while(!(UCB2IFG & UCTXIFG)) ;
UCB2TXBUF = cRqstToSend;
break;
case 1:
while(!(UCB2IFG & UCTXIFG)) ;
UCB2TXBUF = cPreamble;
break;
case 2:
// ID
while(!(UCB2IFG & UCTXIFG)) ;
UCB2TXBUF = TxBuffer[txIdx - 3 ]; // 2 = rqst + preamble.
break;
case 3:
// Length
bytesRemaining = TxBuffer[txIdx - 3 ]-2;
while(!(UCB2IFG & UCTXIFG)) ;
UCB2TXBUF = TxBuffer[txIdx - 3 ] + 2; // Include header bytes.
break;
default:
if (bytesRemaining == 0)
{
while(!(UCB2IFG & UCTXIFG)) ;
UCB2TXBUF = 0x00;
Mutex m;
state = sIdle;
InTransit = false;
}
else
{
bytesRemaining--;
while(!(UCB2IFG & UCTXIFG)) ;
UCB2TXBUF = TxBuffer[txIdx - 3 ];
}
break;
}
}
//-------------------------------------------------------------------------
// ReceiveByte()
//-------------------------------------------------------------------------
void Spi::ReceiveByte()
{ //P11OUT ^= BIT0;
static unsigned char bytesRemaining = 0;
unsigned char rxByte = UCB2RXBUF;
// At a minimum we already have the rqstToSend.
switch (rxIdx++)
{
case 0:
// Preamble
if (rxByte!= cPreamble)
{
Mutex m;
rxIdx = 0;
state = sIdle;
}
break;
case 1:
// ID
if (usingPing)
pingBuffer[rxIdx-2] = rxByte;
else
pongBuffer[rxIdx-2] = rxByte;
break;
case 2:
// Pkt. Length
if (usingPing)
pingBuffer[rxIdx-2] = rxByte-2; // Strip the header contents.
else
pongBuffer[rxIdx-2] = rxByte-2;
bytesRemaining = rxByte - 4; // 4 is the already processed bytes.
if (bytesRemaining > MaxSize)
{
// Something went wrong. Abort this transmission.
ProcessBufferReady(false);
}
if (bytesRemaining == 0) // This is a pkt w/o paylod.
{
ProcessBufferReady(true);
}
break;
default:
// Payload
if (usingPing)
pingBuffer[rxIdx-2] = rxByte;
else
pongBuffer[rxIdx-2] = rxByte;
bytesRemaining --;
if (bytesRemaining == 0)
{
// Post test.
ProcessBufferReady(true);
}
break;
}
UCB2TXBUF = 0x00;
}
Any ideas ?, I have seen some code where the TxIF flag is checked prior to moving a byte in, I am not sure how that can be related to my application, but most of the code samples have that feature.
Thanks. God bless,
Saul