MSP430FR2355: Does the UCRXBUFx's Receive Shift Register shift in bits in LPM3 where UART/SMCLK is disabled?

Part Number: MSP430FR2355

Tool/software:

I have a main loop that enters LPM3 by default at startup. I also have a timer (TB2) configured to wake the CPU for about 10 ms every 2 seconds. A corresponding UART (eUSCI_A1) interrupt sets the enter_LPM3 flag, which either wakes the CPU from LPM3 or puts it back to LPM3.

Because SMCLK and the UART are disabled in LPM3, I expect the only way the CPU could catch the 'w' (wake-up) command is if it arrives during that 10 ms window. That’s just 10 ms out of every 2 seconds – about 0.5% of the time. Logically, that should fail most of the time (99.5%), but in practice, my code magically works 100% of the time. I can put the CPU into LPM3 or wake it up at any moment, and I never miss the 'w' command.

Unless I’m misinterpreting my own code, my guess is that, while the CPU is in LPM3 and SMCLK/UART are supposedly off, the Receive Shift Register might still be shifting in incoming UART data. Then, as soon as the CPU wakes for that 10 ms window and enables SMCLK, the data appears in UCAxRXBUF and fires the interrupt. Otherwise, I can’t explain why my code works so reliably.  Hope someone can shed me some light on this.

I'm not sure if posing the code is necessary but here is it just in case:

My main loop:
  

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Beginning of my main loop
// 'enter_LPM3' is initialized to be true
// Main loop
while(1)
{
// 'enter_LPM3' is initialized to be true, meaning we enter LPM3 after power up
if (enter_LPM3)
{
// (LPM3) Small delay to increase the time-window in catching 'w' UART command (~10ms @ 1MHz MCLK)
// before entering LPM3.
__delay_cycles(10000);
P1OUT &= ~BIT0; // LED Off
// Check enter_LPM3 again before entering LPM3 because the UART ISR may set 'enter_LPM3' to false
// with a 'w' wake-up command
if (enter_LPM3)
{
__bis_SR_register(LPM3_bits | GIE); // Enter LPM3 (Wake up by Timer_B2)
}
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

My timer and timer ISR:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// (LPM3) Configure Timer2_B3 (TB2)
void configure_tb2_wakeup(void)
{
TB2CTL |= TBCLR; // (TB2) Clear Timer_B2
TB2CTL |= TBSSEL__ACLK; // (TB2) Source Timer_B2 from ACLK (32.768 kHz)
//TB2CTL |= ID__1; // (TB2) No clock division
//TB2EX0 |= TBIDEX__1; // (TB2) No extra division
//TB2CCR0 = 327; // (TB2) Set wake-up interval (~10ms: 327 / 32.768kHz ≈ 10ms)
//TB2CCR0 = 32768; // (TB2) Set wake-up interval (~1s: 32768 / 32.768kHz ≈ 1s)
//TB2CCR0 = 65535; // (CANNOT USE - OVERFLOW!)(TB2) Set wake-up interval (~2s: 32.768kHz / 65536 ≈ 2s)
// Because TB2CCR0 is a 16-bit counter that has a maximum value of 65535 and overflows at 65536,
// we can use the clock divider to slow down ACLK in order to achieve a more accurate 2s interrupt
TB2CTL |= ID__4; // (TB2) Divide ACLK by 4 (32.768 kHz / 4 = 8.192 kHz)
TB2EX0 |= TBIDEX__8; // (TB2) Further divide by 8 (8.192 kHz / 8 = 1.024 kHz)
TB2CCR0 = 2048; // (TB2) Set wake-up interval (~2s: 2048 / 1.024 kHz = ~2s interval
TB2CCTL0 |= CCIE; // (TB2) Enable Timer_B2 interrupt
TB2CTL |= MC__UP; // (TB2) Set Timer_B2 to UP mode
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

UART and UART ISR:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void configure_uart(void)
{
UCA1CTLW0 |= UCSWRST; // (eUSCI_A1)(UART) hold eUSCI_A1 in SW reset
UCA1CTLW0 |= UCSSEL__SMCLK; // (eUSCI_A1)(UART) clock source: use SMCLK 1MHz
UCA1BRW = 8; // (eUSCI_A1)(UART) 115200 baud (UG-p.589) <-- neg error
UCA1MCTLW |= 0xD600; // (eUSCI_A1)(UART) 115200 baud (UG-p.589) <-- neg error
P4SEL1 &= ~BIT3; // (eUSCI_A1)(UART) P4.3/TXD (P4SEL1.3=0)
P4SEL0 |= BIT3; // (eUSCI_A1)(UART) P4.3/TXD (P4SEL0.3=1)
P4SEL1 &= ~BIT2; // (eUSCI_A1)(UART) P4.2/RXD (P4SEL1.2=0)
P4SEL0 |= BIT2; // (eUSCI_A1)(UART) P4.2/RXD (P4SEL0.2=1)
UCA1CTLW0 &= ~UCSWRST; // Take UART out of reset
}
#pragma vector = EUSCI_A1_VECTOR
__interrupt void ISR_EUSCI_A1(void)
{
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • From the guide:

    "A peripheral module requests its clock sources automatically from the CS module if required for its proper
    operation, regardless of the current mode of operation (see Figure 3-5)."

    Or, the system is in LPM3 when the UART detects a falling edge (start bit) on its input. It requests its clock causing it to run. When reception of the data completes, the clock can stop and it returns to LPM3.

  • Thank you I missed that in the guide.  Does the UART (1) service the interrupt immediately in LPM3 before returning to LPM3 automatically or (2) does it only set the interrupt flag, and the ISR gets serviced only after the CPU gets out of LPM3?  

**Attention** This is a public forum