EmbeddedRelated.com
Forums

MSP430 LPM4, UART wakeup, crashing...

Started by jerry_bp May 15, 2005
Hi all, I'm currently working in an application that requires the MCU to g
into deep sleep (LPM4) and wake up and process data on UART receive, an
then go back to LPM4. What is the right way to do this? I tried doing th
following as TI's guide Rev. E. suggests, but this crashes the MCU. 
tried to debug the code but I just can't find where the problem is. Th
serial data is received using IR, in a constant stream that does not sto
until the "transmitter" is taken away from the receiver. This will wor
fine for a while but it eventually crashes. 

What I've seen is that somehow when the software is busy handling a
interrupt, it STILL accepts other interrupts even when the GIE bit is off
Sometimes the instruction that sends the MCU back to active mode doesn't d
anything or messes everything up. I really need help here as I'm runnin
out of ideas. BTW, the problem is not on hardware, all of the require
pins are correctly terminated to either VCC or ground, even th
programming pins, reset, etc.


#include "msp430x12x.h"
;_______________________________________________________________________
; INTERRUPT VECTORS USED
;_______________________________________________________________________
          ORG 0FFFEh               ; power-up interrupt
          DW RESET

          ORG 0FFEEh               ; USART0 receive interrupt
          DW RECEIVE

;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; CODE
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
          ORG 0F000h               ; program start for MSP430F122
;___________________________
; Reset Interrupt sequence
;___________________________
RESET
          MOV.W #0300h, SP         ; initialize stack pointer
          CALL #INIT               ; initalize the UART

MAIN
          BIS #LPM4+GIE, SR        ; wait for start-edge
	  NOP		           ; Needed by debugger
	  CMP.B #f0, r8            ; check received data
          JNZ MAIN                 ; incorrect data! jmp!
          XOR.B #1, P1OUT          ; toggle LED pin to ack received flag
          JMP MAIN

;_______________________________________________________________________
; USART Interrupt sequence
;_______________________________________________________________________
RECEIVE
          BIT.B #URXIFG0,&IFG2      ; Test URXIFGx to determine
          JNZ StartRec              ; If start-edge or character
                                    ; if IFG is set, Z=0, continue.
                                    ; if IFG not set (no complet
transmission), return!

StartEdge                           ; wake up and receive char
          BIC.B #URXSE,&U0TCTL      ; Clear URXS signal
          BIS.B #URXSE,&U0TCTL      ; Re-enable edge detect
          BIC #SCG0+SCG1,0(SP)      ; Enable BRCLK = DCO; CPU still off
          JMP EndRcv

StartRec
          MOV.B &U0RXBUF, r8        ; Save received char in r8
	  BIC #OE+FE+PE+RXERR,U0RCTL ;Clear any errors received
          BIC #LPM4+GIE,0(SP)       ; Char received, wake up and proces
data

EndRcv
          RETI

;_______________________________________________________________________
; Initialization function (sets up UART, flags and interrupts)
;_______________________________________________________________________
INIT
          MOV.W #WDTPW+WDTHOLD, &WDTCTL   ; stop watchdog
          BIS #OSCOFF, SR                 ; not using LFXTL1

          //Initialize UART
          BIS.B #CHAR, &U0CTL
                                  ; 1 stop bit
                                  ; 8-bit word
          BIS.B #SSEL1, &U0TCTL   ; use sub-main clock for UART (@750kHz)
          MOV.B #RATIO, &U0BR0    ; f = 750kHz in MSP430F122
          MOV.B #000h, &U0BR1     ;
          MOV.B #00h, &U0MCTL     ; receive moodulation set to zero; 0.0
is small
          BIS.B #URXSE, &U0TCTL   ; enable start-edge wake-up
          BIS.B #020h, &P3SEL     ; select P3.5 for serial reception
          BIC.B #020h, &P3DIR     ; and input
          BIS.B #URXE0, &ME2      ; enable receiver (MSP430F122)
          BIC.B #SWRST, &U0CTL    ; clear UART software reset
          BIS.B #URXIE0, &IE2     ; enable receiver interrupt
(MSP430F122)
 
	  BIS.B #003h, &P1DIR      ; P1.1 and P1.0 output
          BIS.B #003h, &P1OUT     ; turn LEDs off

          EINT                    ; enable interrupts: GIE<-1

          RET

          END




		
-> This message was sent using the  web interface on
www.EmbeddedRelated.com <-
In article <mtOdnTdj66Gi3BrfRVn_vg@giganews.com>, jerry_bp@hotmail.com 
says...
> Hi all, I'm currently working in an application that requires the MCU to go > into deep sleep (LPM4) and wake up and process data on UART receive, and > then go back to LPM4. What is the right way to do this? I tried doing the > following as TI's guide Rev. E. suggests, but this crashes the MCU. I > tried to debug the code but I just can't find where the problem is. The > serial data is received using IR, in a constant stream that does not stop > until the "transmitter" is taken away from the receiver. This will work > fine for a while but it eventually crashes. > > What I've seen is that somehow when the software is busy handling an > interrupt, it STILL accepts other interrupts even when the GIE bit is off. > Sometimes the instruction that sends the MCU back to active mode doesn't do > anything or messes everything up. I really need help here as I'm running > out of ideas. BTW, the problem is not on hardware, all of the required > pins are correctly terminated to either VCC or ground, even the > programming pins, reset, etc. > >
IIRC, the LPM4 mode shuts off all the clocks, including that to the UART. Are you sure that the UART clock is starting up quickly enough to capture the start bit? If the data is really received in a constant stream, you might be better off not going into LPM4 mode after each character---but only when no character has been received for a pre-determined interval.
> #include "msp430x12x.h" > ;_______________________________________________________________________ > ; INTERRUPT VECTORS USED > ;_______________________________________________________________________ > ORG 0FFFEh ; power-up interrupt > DW RESET > > ORG 0FFEEh ; USART0 receive interrupt > DW RECEIVE > > ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ; CODE > ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ORG 0F000h ; program start for MSP430F122 > ;___________________________ > ; Reset Interrupt sequence > ;___________________________ > RESET > MOV.W #0300h, SP ; initialize stack pointer > CALL #INIT ; initalize the UART > > MAIN > BIS #LPM4+GIE, SR ; wait for start-edge > NOP ; Needed by debugger > CMP.B #f0, r8 ; check received data > JNZ MAIN ; incorrect data! jmp! > XOR.B #1, P1OUT ; toggle LED pin to ack received flag > JMP MAIN > > ;_______________________________________________________________________ > ; USART Interrupt sequence > ;_______________________________________________________________________ > RECEIVE > BIT.B #URXIFG0,&IFG2 ; Test URXIFGx to determine > JNZ StartRec ; If start-edge or character > ; if IFG is set, Z=0, continue. > ; if IFG not set (no complete > transmission), return! > > StartEdge ; wake up and receive char > BIC.B #URXSE,&U0TCTL ; Clear URXS signal > BIS.B #URXSE,&U0TCTL ; Re-enable edge detect > BIC #SCG0+SCG1,0(SP) ; Enable BRCLK = DCO; CPU still off > JMP EndRcv > > StartRec > MOV.B &U0RXBUF, r8 ; Save received char in r8 > BIC #OE+FE+PE+RXERR,U0RCTL ;Clear any errors received > BIC #LPM4+GIE,0(SP) ; Char received, wake up and process > data > > EndRcv > RETI > > ;_______________________________________________________________________ > ; Initialization function (sets up UART, flags and interrupts) > ;_______________________________________________________________________ > INIT > MOV.W #WDTPW+WDTHOLD, &WDTCTL ; stop watchdog > BIS #OSCOFF, SR ; not using LFXTL1 > > //Initialize UART > BIS.B #CHAR, &U0CTL > ; 1 stop bit > ; 8-bit word > BIS.B #SSEL1, &U0TCTL ; use sub-main clock for UART (@750kHz) > MOV.B #RATIO, &U0BR0 ; f = 750kHz in MSP430F122 > MOV.B #000h, &U0BR1 ; > MOV.B #00h, &U0MCTL ; receive moodulation set to zero; 0.05 > is small > BIS.B #URXSE, &U0TCTL ; enable start-edge wake-up > BIS.B #020h, &P3SEL ; select P3.5 for serial reception > BIC.B #020h, &P3DIR ; and input > BIS.B #URXE0, &ME2 ; enable receiver (MSP430F122) > BIC.B #SWRST, &U0CTL ; clear UART software reset > BIS.B #URXIE0, &IE2 ; enable receiver interrupt > (MSP430F122) > > BIS.B #003h, &P1DIR ; P1.1 and P1.0 output > BIS.B #003h, &P1OUT ; turn LEDs off > > EINT ; enable interrupts: GIE<-1 > > RET > > END > > > > >
Mark Borgerson
Mark is right.  Been there, done that.

When you sleep in LPM4, there is only one way to get out of it: you can
use an interrupt from any peripheral that *doesn't* use a clock.  All
clocks are off in LPM4.

Waking from LPM4 is slow because it takes some time for the clocks to
restart.  If you're app demands single clock cycle response on wakeup,
then LPM3 might be a better choice for sleeping.

They call LMP4 "done mode".  Please take that tag literally.  You're
app woll be done doing whatever it's doing if it's in LPM4.  LPM is
called "sleep mode".  Your app will be active but waiting to wakeup
(IOW, not done).

There is a useful table in the User' Guide that shows which clocks are
on and off for the various LPMs.

JJS

> IIRC, the LPM4 mode shuts off all the clocks, including that to the > UART. Are you sure that the UART clock is starting up quickly
enough
> to capture the start bit? > > If the data is really received in a constant stream, you might be > better off not going into LPM4 mode after each character---but > only when no character has been received for a pre-determined > interval.
jerry_bp wrote:
> Hi all, I'm currently working in an application that requires the MCU to go > into deep sleep (LPM4) and wake up and process data on UART receive, and > then go back to LPM4. What is the right way to do this? I tried doing the > following as TI's guide Rev. E. suggests, but this crashes the MCU. I > tried to debug the code but I just can't find where the problem is. The > serial data is received using IR, in a constant stream that does not stop > until the "transmitter" is taken away from the receiver. This will work > fine for a while but it eventually crashes.
Just some thoughts: - Does your code work properly while not going LPM or going to another LPM?
> What I've seen is that somehow when the software is busy handling an > interrupt, it STILL accepts other interrupts even when the GIE bit is off.
- You turn it on inside the interrupt routine. Don't do it, the CPU will turn it on while executing RETI.
> Sometimes the instruction that sends the MCU back to active mode doesn't do > anything or messes everything up. I really need help here as I'm running > out of ideas. BTW, the problem is not on hardware, all of the required > pins are correctly terminated to either VCC or ground, even the > programming pins, reset, etc.
You don't properly switch the CPU to inactive mode - you don't use CPUOFF bit.
> MAIN > BIS #LPM4+GIE, SR ; wait for start-edge
GIE is already 1 before this instruction.
> NOP ; Needed by debugger
Needed only if there is nothing after it - it's not your case.
> CMP.B #f0, r8 ; check received data > JNZ MAIN ; incorrect data! jmp! > XOR.B #1, P1OUT ; toggle LED pin to ack received flag > JMP MAIN > BIC #OE+FE+PE+RXERR,U0RCTL ;Clear any errors received > BIC #LPM4+GIE,0(SP) ; Char received, wake up and process > data
Why do you turn interrupts off here?
> BIS.B #020h, &P3SEL ; select P3.5 for serial reception > BIC.B #020h, &P3DIR ; and input
Actually it's an output here.