EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

Problems with MSP430F2132

Started by Onestone October 22, 2013
No problem, I agree with your points. And I just want to show people here
some parts of my program so that the ideas might come out to help them to
solve there problems.

Anthony Ha

Beginning Microcontrollers with the MSP430

Hi Anthony

I can see what you are doing at RESET. It is similar to mine but I have a
MSP430F2132 and am using DCO at 1MHz. In the NMI interrupt (DOZE), I cannot
see how you ever exit this. There is no RETI? What is the routine supposed
to do apart from re-initialising the stack and setting up the registers
again? I turn on a LED in the NMI interrupt routine but I never see this
happen. I am beginning to think that this may not be a NMI problem, but
something silly I am doing.

Thanks

Peter

From: m... [mailto:m...] On Behalf Of
a...@gmail.com
Sent: Wednesday, 23 October 2013 11:40 AM
To: m...
Subject: RE: [msp430] Problems with MSP430F2132

Here is my assembler layout for a typical MSP430F449 chip:

The first section of the program is the declanation of Interrupt Vector
(IV). Depending on what chip, you will have 2, 4, 8 IV. The 449 chip has 2
IV and the address from FFE0 to FFFE (the last two by is POWER ON RESET)
that I named PWRON and I called DOZE (address FFFC for the Oscillator, NMI
reset). I called MAIN address FFFA for the timer_B compare 0: with Timer B
we will have 7 of them from 0,1,2,3,4,5,6). I use here for example only 1
compare interrupt Timer B_0 . And I named BINTR for Port 1 address FFE8.

;********************** INTERRUPT VECTORS
***********************************

RSEG INTVEC ;

DW TRAPE0
;$FFE0.........................N/U
DW TRAPE2
;$FFE2.........................N/U
DW TRAPE4
;$FFE4.........................N/U
DW TRAPE6
;$FFE6.........................N/U
DW BINTR ;$FFE8....I/O PORT P1
DW TRAPEA
;$FFEA.........................N/U
DW TRAPEC
;$FFEC.........................N/U
DW TRAPEE
;$FFEE.........................N/U
DW TRAPF0 ;$FFF0....UART0 XMIT
DW TRAPF2 ;$FFF2....UART0 RCVE
DW TRAPF4 ;$FFF4....WATCHDOG TIMER
DW TRAPF6
;$FFF6.........................N/U
DW TRAPF8 ;$FFF8....TIMER_B (CAP/COMP
1/6, OVRFLOW)
DW MAIN ;$FFFA....TIMER_B
(COMPARE0)
DW DOZE ;$FFFC....OSC FAULT, NMI
DW PWRON ;$FFFE....POWER UP RESET

;********************** INITIAL RESET
***************************************
;
RSEG CODE

;---
--------------------

PWRON: DINT
;DISABLE GENERAL INTERRUPTS

MOV.W #WDTPW+WDTHOLD,&WDTCTL ; DISABLE
WATCHDOG TIMER,
CLR.B &P1IE
;DISABLE P1 INTERRUPTS
MOV.W #SFE(CSTACK),SP
;START OF STACK

PWR0A: BIT.B #LFOF,&FLL_CTL0
;LOOP WHILE LF FAULT
JNZ PWR0A

BIT.B #DCOF,&FLL_CTL0
;LOOP WHILE DCO FAULT
JNZ PWR0A

;---
------------------

As you can see, the chip will start the CODE at PWRON as the battery
inserted, the comments for each line of code is good enough for
explanation, isn't it? SO the chip will stablize after 2 loops to check for
LF fault and DCO fault. After that you can initialize all the ports, clear
all the RAM memory, ... Do wahtever you have to do to initially, setup the
program, and finally, branch to ENDAY: put the chip to sleep mode for
storage, save the power.

Suppose I have only 1 button for the device port 1.0. I need to enable the
button interrupt for port 1.0

;-------------- code for ENDAY --------------------------

ENDAY: CLR.B &P1IFG
; CLR POSSIBLE INTERRUPT FLAGS
BIC.B #01H,&P1DIR
; MAKE P1.0 INPUT
MOV.B #01H,&P1IES
; INTERUPT EDGE...P1.0 HI TO LO
MOV.B #01H,&P1IE
; ENBL P1.0 INTERRUPT

MOV.W #SFE(CSTACK),SP
; START OF STACK (CLEAR)
MOV.W #SCG1+SCG0+CPUOFF+GIE,SR ;
LPMODE3..ENABLE GENERAL INTERRUPT and

NOP
; WHILE ASLEEP

; A SWITCH ACTIVATION WILL VECTOR TO

; BINTR AND WILL RETI AFTER ALTERING THE

; SR ON THE STACK, IF THE CONTACT IS VALID.

; THE PROGRAM WILL CONTINUE FROM HERE WITH A

; BRANCH TO `NEWDAY', WHICH WILL CAUSE THE

; UNIT TO POWERUP. IF AN INTERMITTENT

; CLOSURE, THE UNIT WILL SHUTDOWN IN LOW

; POWER MODE AGAIN.

BIC #TBIE,&TB0CTL
; DISABLE TIMER B OVERFLOW INTERRUPT
BRA #NEWDAY
;. START THE PROGRAM WHEN THE BUTTON INTERRUPT

; TO TURN THE DEVICE ON.

;---
-----------

Now the chip is sleep in LPM mode 3 to save power. When the button is
pressed:

;---------------- CODE TO CHECK FOR BUTTON INTERRUPT
----

BINTR: CLR.B &P1IFG
;CLEAR PORT 1 INTERRUPT FLAGS
BIS.W #GIE,SR
;RE-ENABLE GENERAL INTERRUPT

MOV.W #0400H,TEMP
;DELAY FOR 5 MS

BINT00: DEC.W TEMP
;16 BIT.W REGISTER..DECREMENT TILL 0000H
JNZ BINT00

MOV.B &P1IN,BTNSAV
;CHECK FOR SWITCH INTERRUPT (XITION TO LO)
INV.B BTNSAV
;CHANGE TO POSITIVE LOGIC
AND.B #01H,BTNSAV
;MASK FOR BIT 0
JZ BINT01
;FALSE INTERRUPT
TST.B OPMODE
;IF OPMODE = SLEEPMODE=0 THEN SET SR ON

; THE STACK TO POWERUP ON RTI
JNZ BINT02
; NOT SLEEP

;ASLEEP
BIC #TBIE,&TB0CTL
;DISABLE TIMER_B OVERFLOW INTERRUPTS
CLR 0(SP)
;SET CPU ACTIVE ON RTI

BINT01: RETI

BINT02: MOV.B BTNSAV,BTNMEM
;SAVE FOR BUTTON CHECK ROUTINE
RETI ; ..

;--------------- END OF BUTTON INTERRUPT
---------------------------------

As you can see the code to detect the bouncing button for 5 ms. if the
button is pressed < 5 ms then it will be ignored. An valid button pressed
will return and wake the CPU up and start the NEWDAY routine (in DOZE). It
will start your program (turn on your device). If it is not from the sleep
mode (OPMODE = 0 operation mode) then it will be OPMODE 1, 2,3, 4 whatever
you named it then you know what to do with the button pressed. Example,
OPMODE 1 is in SET HOUR, the button will increase the HOURS, if the OPMODE 2
is in SET MINUTE, the button pressed will increase MINUTES. And as you know
, with port 1 we can have total 8 buttons to do so many thing.

Now for the DOZE, this is the place for the CPU to rest (LPM3) to save
power:

;----------- code for the DOZE
--------------

DOZE: MOV #SFE(CSTACK),SP
;START OF STACK (CLR POSSIBLE PENDING RTI)

BIC.B #01H,&P1DIR
; MAKE P1.0 INPUTS
MOV.B #01H,&P1IES
;INTERUPT EDGE...HI TO LO ON P1.0

MOV.B #01H,&P1IE
;ENABLE P1.0 INTERRUPTS

MOV #0120H,&TBCTL
;RECONDITION TIMERB 32KHZ, CONT UP..CAUTIONARY
ADD #1000H,&TBCCR0
;ADD 125MS TO COMPARE B0 REG (4096/32768)
MOV #0010H,&TBCCTL0
;ENABLE TIMERB COMPARE0 INTERRUPT

;-----------------------------------

DOZ00: MOV #00D8H,SR
;LPMODE3..ENABLE GENERAL INTERRUPT
NOP
;BTTN PRESSES WHILE IN DOZE WILL VECTOR TO

; BINTR AND ReTI BACK TO HERE TO THE LO PWR mode

;125MS COMPARE WILL VECTOR TO MAIN.

;MAIN WILL TERMINATE WITH A BRANCH BACK TO DOZE.

; IN ORDER TO SET UP THE SWITCH INTERRUPTS

; AND ADD 125MS TO THE NEXT COMPARE INTERRUPT.

JMP DOZ00
;PRECAUTION

;-------------- end code for doze
----
---

As you see up to now, the program (the CPU) resets at PWRON, loop until the
CPU is stable then go to ENDAY to sleep to save power. If a button is
pressed during sleep mode, the RETI will trigger the SR to turn the CPU ON,
the program will go to NEWDAY:

;----------- code for the NEWDAY ----------------------------

NEWDAY:

.......... DO whatever you have to do to display the device or do something
then branch to DOZE to let the CPU sleep. During the CPU sleep in DOZE, the
timer B compare 0 with 125 ms (1000H will be 125 ms, 2000H will be 250 ms,
and so on ... depends on how many ms seconds you want the button to react.)

BR #DOZE

;--------- end code for NEWDAY ----------------------------

Now the code for the MAIN: the MAIN will be running every 125 ms during
awake mode and you can do different task in the MAIN depends on what you
want to do:

;---------------- Code for MAIN running every 125 ms during awake
-------------

MAIN: MOV.W #WDTPW+WDTHOLD,&WDTCTL ; DISABLE WATCHDOG
TIMER,

INC.B EIGHTHS
;INCREMENT 1/8 SEC CTR

AND.B #07H,EIGHTHS
;MASK OFF UNUSED BITS

BIS.W #GIE,SR
;RE-ENABLE GEN INTERRUPTS FOR BTTN PRESSES

MOV.B EIGHTHS,R5

RLA R5

BR MAIN00(R5)

MAIN00: DW JOB0

DW JOB1

DW JOB2

DW JOB3

DW JOB4

DW JOB5

DW JOB6

DW JOB7

JOB0: Do something then ..

BR #DOZE

JOB1: Do something then ..

BR #DOZE

JOB2: Do something then ..

BR #DOZE

JOB3: Do something then ..

BR #DOZE

JOB4: Do something then ..

BR #DOZE

JOB5: Do something then ..

BR #DOZE

JOB6: Do something then ..

BR #DOZE

JOB7: Do something then ..

BR #DOZE

;-------------- end code for MAIN -------------------

This is a complete frame programming for a MSP430F449 chip from start power
up, detect LF and DCO fault to make sure 100% the CPU is stable and back to
sleep, wait for a button pressed to wake up and start a NEWDAY then go back
to sleep. During AWAKE mode, every 125 ms, the CPU will wake up to check
for any task that it has to do, then back to sleep until the program go back
to ENDAY (like 2 hours without a button pressed, the program will go back to
sleep mode.

Finally about TRAPE0, TRAPE2, ... I name it and put a code in it routine to
see if any interrupt occur during my program running so I can trap that
interrupt back to DOZE so I don't have any unwanted interrupt that will make
my program go haywired.

TRAPE0: MOV.B #0E0H,ERROR

... display the ERROR so I know what going all

.. delay the dislpay for 10 seconds ....

BR #DOZE

it is also a good programming when we put all the initialization in one
routine that I called PREP (prepare):

;------------ code to put all initialization in one routine ----------------

PREP: MOV.W #WDTPW+WDTHOLD,&WDTCTL ; DISABLE
WATCHDOG TIMER,

MOV.B #032H,&SCFQCTL
;DCOCLK = 50*30.518 = 1.52mhz, MODULATION ON
CLR.B &SCFI0
;DCO RANGE = .65/6mhz
CLR.B &SCFI1
; ..

MOV.B #0B0H,FLL_CTL0
;SELECT.. DCO, LO FREQ, 10pf LOAD
MOV.B #020H,FLL_CTL1
;XT2OFF, ACLK/1

CLR.B &IE1
;CAUTIONARY DISABLE MODULE INTERRUPT REGISTERS
CLR.B &IE2

CLR.B &IFG1
;CAUTIONARY CLEAR MODULE INTERRUPT FLAGS
CLR.B &IFG2
; ..
CLR.B &ME1
;CAUTIONARY MODULE DISABLES
CLR.B &ME2
; ..

;-------------- TIMER A SETUP
----
------------

; SET UP TIMER A FOR SOME USE, LIKE A PIEZO TO MAKE A SOUND OR SOMETHING

;---
----------------
MOV #0104H,&TACTL
;TIMERA ACLK, STOPPED, CLEARED
MOV #0008H,&CCR0
;COMPARE REG0 TO 7(DELAYED), TACL0 4096hz
MOV #0004H,&CCR2
;COMPARE REG1 TO 4, TACL1 (50%DC)
MOV #00E0H,&CCTL2
;PREPARE OUTP UNIT1 FOR RESET/SET
CLR &CCTL0
;CLR CAP/COMP CONTROL REG0
BIC #0010H,&TACTL
;STOP 4KHZ PIEZO DRIVE

;------------ PORT1 ----------------
;P1.0 button

;P1.1 to P1.7 N/U

CLR.B &P1IES
;INTERUPT EDGE...LOW TO HI
CLR.B &P1OUT
;SET PORT1 OUTPUT LATCHES LOW
MOV.B #0FEH,&P1DIR
;ALL OUTPUT EXCEPT P1.0 is INPUT
CLR.B &P1IE
;DISABLE P1 INTERRUPTS
CLR.B &P1IFG
;RESET POSSIBLE INTERRUPT FLAG
CLR.B &P1SEL
;Make port 1 to be all IO line
;PORT2
;PORT3
;PORT4
;PORT5
;PORT6

CLR &ADC12CTL0
;CLEAR A/D CONTROL REGISTERS
CLR &ADC12CTL1 ; ..
CLR &ADC12IFG
;CLEAR INTERRUPT ENABLE FLAG REGS
CLR &ADC12IE ; ..

RET

;---------- end code for PREP -------
You can put the PREP right after the CPU is stable then clear RAM, read
EEPROM ... before put the CPU into sleep mode.

I hope to help you guy with some information that I worked in the field of
assembler for the MSP430.

Anthony Ha

-------Original Message-------

From: Peter Grey

Date: 10/22/2013 6:32:41 PM

To: m...

Subject: RE: [msp430] Problems with MSP430F2132

Hi Al,

Thanks for the detailed reply. I must admit I have not used NMI since I was
using the PDP mini's, and that is a while ago! I shall take a look and may
have a few questions

Thanks

Peter

From: m... [mailto:m...] On Behalf Of
Onestone
Sent: Tuesday, 22 October 2013 4:26 PM
To: m...
Subject: Re: [msp430] Problems with MSP430F2132

This is probably just the usual issue with debounce of a switch (attaching
the battery is a switch), and the system getting caught out. Typically you
would have an INIT process shortly after start up with a clock stabilisation
loop or similar. I don't know how you handle NMI's but typically if your NMI
handling is too simplistic you will get a clock error, jump to the NMI which
might then get stuck in a loop or stall, or simply corrupt the PC. If you
have a LED try having the LED flash briefly during INIT, ie on very fast
then off once stable. Then have it turned fully on in the NMNI and point the
NMI back to itself. That will tell you if this is the issue.

Al

On 22/10/2013 4:50 PM, Peter Grey wrote:

I have been using these chips for a while. My devices have a battery
connected to them and, in some cases a battery charger. I find that when I
first connect a battery or take it off a charger it will not work. I need to
push a reset button. I have tried a reset chip and it makes no difference. I
can tell a customer to always press reset after the above events but I want
to find out what is going on and fix it. Has anyone experienced any such
behaviour.

TIA

Peter












 

Peter,

 

Look at my INTVEC again. Do you see MAIN (in red color) that I am using Timer B compare 0 interrupt?

 

 



;********************** INTERRUPT VECTORS ***********************************<?XML:NAMESPACE PREFIX = "O" />



 



 RSEG         INTVEC  ;



 



 DW             TRAPE0                         ;$FFE0.........................N/U
 DW             TRAPE2                         ;$FFE2.........................N/U
 DW             TRAPE4                         ;$FFE4.........................N/U
 DW             TRAPE6                         ;$FFE6.........................N/U
 DW              BINTR                            ;$FFE8....I/O PORT P1
 DW             TRAPEA                        ;$FFEA.........................N/U
 DW             TRAPEC                         ;$FFEC.........................N/U
 DW             TRAPEE                         ;$FFEE.........................N/U
 DW             TRAPF0                          ;$FFF0....UART0 XMIT
 DW             TRAPF2                           ;$FFF2....UART0 RCVE
 DW             TRAPF4                          ;$FFF4....WATCHDOG TIMER
 DW             TRAPF6                          ;$FFF6.........................N/U
 DW             TRAPF8                          ;$FFF8....TIMER_B (CAP/COMP 1/6, OVRFLOW)
 DW             MAIN                               ;$FFFA....TIMER_B (COMPARE0)
 DW             DOZE                             ;$FFFC....OSC FAULT, NMI
 DW             PWRON                        ;$FFFE....POWER UP RESET


;--------------------- END OF INTVEC SETUP ------------------


 


 

Now in the DOZE, do you see the three lines (in red color) that I setup for 125 ms interrupt with Timer B compare 0?


When I put the CPU to LPM3, the interrupt wil wake the CPU up every 125 ms and MAIN will be the place the interrupt will activate.


 

 



;----------- code for the DOZE --------------



DOZE:        MOV         #SFE(CSTACK),SP                                     ;START OF STACK (CLR POSSIBLE PENDING RTI)



                   



                    BIC.B        #01H,&P1DIR                                                ; MAKE P1.0 INPUTS
                    MOV.B     #01H,&P1IES                                                 ;INTERUPT EDGE...HI TO LO ON P1.0



                    MOV.B     #01H,&P1IE                                                   ;ENABLE P1.0  INTERRUPTS
                                



                    MOV         #0120H,&TBCTL                                           ;RECONDITION TIMERB 32KHZ, CONT UP..CAUTIONARY



                    ADD         #1000H,&TBCCR0                                         ;ADD 125MS TO COMPARE B0 REG (4096/32768)
                    MOV         #0010H,&TBCCTL0                                       ;ENABLE TIMERB COMPARE0 INTERRUPT



 



;-----------------------------------



 



DOZ00:     MOV          #00D8H,SR                                                     ;LPMODE3..ENABLE GENERAL INTERRUPT 
                   NOP                                                                                    ;BTTN PRESSES WHILE IN DOZE WILL VECTOR TO
                                                                                                                ; BINTR AND ReTI BACK TO HERE TO THE LO PWR mode
                                                                                                                ;125MS COMPARE WILL VECTOR TO MAIN. 



                                                                                                                ;MAIN WILL TERMINATE WITH A BRANCH BACK TO DOZE.
                                                                                                                ; IN ORDER TO SET UP THE SWITCH INTERRUPTS
                                                                                                                ; AND ADD 125MS TO THE NEXT COMPARE INTERRUPT.



 



                  JMP             DOZ00                                                              ;PRECAUTION



;-------------- end code for doze -------


 

 

Now look at the MAIN routine. The first line when the CPU wake up is I re-disable the Watch dog timer interrupt. The variable EIGHTHS increase every 125 ms so I know which 125 ms I am dealing with. And the two important lines (in red color) is re-enable general interrupt and disable Timer B compare 0 interrupt. The reason that I disable the Timer B compare 0 here is that I want to finish whatever my job here that will take time to do before I return to the DOZE.


 

Do you see the line BR        #DOZE  at every end of the 125 ms job? The reason that I do not use the RETI but I use BR  #DOZE instead because I want to reinitialize the 125 MS Timer B compare 0 interrupt. With the RETI , it will return back to the LPM3 sleep mode in DOZE but it will not re-initialize the 125 ms timer B compare 0 interrupt.


 

 

 



;---------------- Code for MAIN running every 125 ms during awake -------------



MAIN:     MOV.W       #WDTPW+WDTHOLD,&WDTCTL          ; DISABLE WATCHDOG TIMER,
               



                 INC.B         EIGHTHS                                                  ;INCREMENT 1/8 SEC CTR



                 AND.B       #07H,EIGHTHS                                        ;MASK OFF UNUSED BITS
 
                 BIS.W         #GIE,SR                                                      ;RE-ENABLE GEN INTERRUPTS FOR BTTN PRESSES



                


                CLR             &TBCCTL0                                                 ;DISABLE COMPARE REG B0 UNTIL DOZE
       



                 MOV.B       EIGHTHS,R5



                 RLA            R5



                 BR               MAIN00(R5)



 



MAIN00:    DW            JOB0



                   DW            JOB1



                   DW            JOB2



                   DW            JOB3



                   DW            JOB4



                   DW            JOB5



                   DW            JOB6



                   DW            JOB7



 



JOB0:    Do something then ..



                    BR            #DOZE



 




JOB1:    Do something then ..



                    BR            #DOZE



                   



JOB2:    Do something then ..



                    BR            #DOZE




 



JOB3:    Do something then ..



                    BR            #DOZE



 



JOB4:    Do something then ..



                    BR            #DOZE




 



JOB5:    Do something then ..



                    BR            #DOZE



 



JOB6:    Do something then ..



                    BR            #DOZE




 



JOB7:    Do something then ..



                    BR            #DOZE



;-------------- end code for MAIN -------------------


 

 

You can ask me, what will happen if the job is longer than 125 ms, and the timer B compare 0 is disable in MAIN (CLR      &TBCCTL0 )? The answer is yes, some job might be longer than 125 ms , and if you do not write another few lines of CODE in DOZE, then the timer B compare 0 will continue to count and wrap arround at FFFF back to 0 then when it reaches the next set point. The maximum time is 2 seconds.

 

EXPLANATION:
; TBR is the TIMER B counter that increases from 0 to FFF then back to 0.
; TBCCR0 is the timer B compare 0 that will interrupt every time the TBR reaches that number.
; EXAMPLE:
; TBCCR0 set at 1000H (I add 1000H every time I BR back from MAIN) and the TBR can be any number at that time.
; When the TBR reaches 1000H, the Timer B compare 0 will interrupt and start at MAIN routine.
;
; Sometimes, somehow the TBR passes the TBCCR0 setting when I branh back from MAIN to DOZE.

; TBCCR0 is compare to TBR. If the TBR ( suppose count up to 0500H) which is less than TBCCR0 ( the set point at  1000H)
; Then the CPU goes to sleep mode and wait for the TBR to reach 1000H then interrupt occurs.
; If the TBR ( suppose it counts up to 1200H) then it passes the set point of TBCCR0 ( at 1000H) .

; To prevent the TBR keep counting up to FFFFh then wrap arround at 0 and counts up to 1000H again (maximum wait time is 2 seconds)

; you can see in the code below, I make the TBCCR0 = TBR, then add the next 125 ms interrupt.

; Do you see the trick that I made? I add 1100H more instead of 1000H then I clear the last 3 nibbles to keep the 0000,1000H,2000H,
; Example, When I return the TBR is already counts up to 1E00h (pass the 1000H set point). I add 1100H to 1E00H = 2F00H
;Then I clear the last 3 nibbles to make it 2000H. Now the interrupt will occur at 2000H.
;-

 

                    MOV         #0120H,&TBCTL                                           ;RECONDITION TIMERB 32KHZ, CONT UP..CAUTIONARY



                    ADD         #1000H,&TBCCR0                                         ;ADD 125MS TO COMPARE B0 REG (4096/32768)
                    MOV         #0010H,&TBCCTL0                                       ;ENABLE TIMERB COMPARE0 INTERRUPT



 


DOZ01:  
                    CMP         &TBCCR0,&TBR                        ;NORMAL CASE: TBR SHOULD LESS THAN SET POINT TBCCR0
                    JLO            DOZ00                                         ; YES .. back to sleep

 

                    MOV          &TBR,&TBCCR0                        ;LET SET POINT EQUAL TBR
                    ADD         #1100H,&TBCCR0                    ;ADD 125MS TO COMPARE B0 REG (4096/32768)
                    BIC            #0FFFH,&TBCCR0                  ;MAKE IT ALWAYS AT THE NEXT 125MS
                    JMP          DOZ01

 

;-----------------------------------     
DOZ00:      MOV.W       #00D8H,SR                              ;LPMODE3..ENABLE GENERAL INTERRUPT 
                    NOP                     

       

 

                    JMP             DOZ00           ;PRECAUTION

;----------------END CODE of DOZE -----------------------

 

 

 

NOTES:

1 - Watch dog timer has to be disable if you do not want it to do any job like RESET in some special occasions.

2- TRAP all the interrupts and if the device in sleep mode, BRANCH it back to ENDAY to let the CPU to go back to sleep mode.

If the device is in AWAKE mode then TRAP all unwanted interrupts back to DOZE if it happens.

 

3- When you deal with Timer B interrupt then ALL 7 timer B from compare 0 to 7 should be handled even though you don't use it.


I use TBINTX routine to hable the timer B interrupt compare 1 to 6.

 

 DW             TBINTX                          ;$FFF8....TIMER_B (CAP/COMP 1/6, OVRFLOW)
 DW             MAIN                              ;$FFFA....TIMER_B (COMPARE0)
 DW             DOZE                             ;$FFFC....OSC FAULT, NMI
 DW             PWRON                        ;$FFFE....POWER UP RESET

;--------------------- END OF INTVEC SETUP ------------------


 


The best way is, making a routine to return all the interrupt if you don't use it.

 

;********************* TIMERB OVERFLO INTERRUPT *****************************
;                      TIMERB CAPT/COMP CH1/6 INTERRUPT
;
;THIS INTERRUPT IS SHARED WITH THE REMAINING TIMERB COMPARE CHANNELS AND
;ALSO THE OVERFLOW OF TIMERB.  THE TBIV VECTOR REGISTER DETERMINES THE
;CAPTURE/COMPARE CHANNEL REQUIRING SERVICE.
;TBIV=2/CMP 1
;     4/CMP 2
;     6/CMP 3
;     8/CMP 4
;    10/CMP 5
;    12/CMP 6
;    14=OVERFLOW VECTOR

 


TBINTX:         ADD         &TBIV,PC                                 ;ADD VECTOR TO PROGR CTR

 

                         RETI                                                           ;VECTOR 0 .. 

                         JMP         TBINT1                                      ;VECTOR 2 .. 

                         JMP         TBINT2                                      ;VECTOR 4 .. 

                         JMP         TBINT3                                      ;VECTOR 6 .. 

                         JMP         TBINT4                                      ;VECTOR 8 .. 
                         JMP         TBINT5                                      ;VECTOR 10 . 
                         JMP         TBINT6                                      ;VECTOR 12 . 
                         JMP         TBINT7                                     ;VECTOR 14 . 

 

TBINT1:            RETI


TBINT2:            RETI


TBINT3:            RETI


TBINT4:            RETI


TBINT5:            RETI


TBINT6:            RETI


TBINT7:            RETI

 

;--------------------- END CODE FOR TBINTX ----------------

 

You can put RETI as vector 0 on the TOP, don't need to JMP  .... But I use all 7 timer B for a lot of jobs like CHRONO for the watches, receiving transmitter signals, ....

 

Anthony Ha

 

 

 


-------Original Message-------

 



Date: 10/25/2013 7:48:57 PM

To: m...

Subject: RE: [msp430] Problems with MSP430F2132

 


Hi Anthony


 


I can see what you are doing at RESET. It is similar to mine but I have a MSP430F2132 and am using DCO at 1MHz. In the NMI interrupt (DOZE), I cannot see how you ever exit this. There is no RETI? What is the routine supposed to do apart from re-initialising the stack and setting up the registers again? I turn on a LED in the NMI interrupt routine but I never see this happen. I am beginning to think that this may not be a NMI problem, but something silly I am doing.


 


Thanks


 


Peter


 












__._,_.___






















stime82762905













__,_._,___
--------------Boundary-00=_Q3F9G6G0000000000000
Content-Type: Text/Plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

Peter,



I have just sent you an email that I explained something, but I don't know
that is what you want. If you think part of your code has problem, you can
zip that part and send it to me as an attachment file (txt file). I can read
and have my opinion for you.



Anthony Ha









-------Original Message-------



From: Peter Grey

Date: 10/25/2013 7:48:57 PM

To: m...

Subject: RE: [msp430] Problems with MSP430F2132









Hi Anthony



I can see what you are doing at RESET. It is similar to mine but I have a
MSP430F2132 and am using DCO at 1MHz. In the NMI interrupt (DOZE), I cannot
see how you ever exit this. There is no RETI? What is the routine supposed
to do apart from re-initialising the stack and setting up the registers
again? I turn on a LED in the NMI interrupt routine but I never see this
happen. I am beginning to think that this may not be a NMI problem, but
something silly I am doing.



Thanks



Peter



From: m... [mailto:m...] On Behalf Of
a...@gmail.com

Sent: Wednesday, 23 October 2013 11:40 AM

To: m...

Subject: RE: [msp430] Problems with MSP430F2132











Here is my assembler layout for a typical MSP430F449 chip:



The first section of the program is the declanation of Interrupt Vector (IV)
Depending on what chip, you will have 2, 4, 8 IV. The 449 chip has 2 IV
and the address from FFE0 to FFFE (the last two by is POWER ON RESET) that I
named PWRON and I called DOZE (address FFFC for the Oscillator, NMI reset).
I called MAIN address FFFA for the timer_B compare 0: with Timer B we will
have 7 of them from 0,1,2,3,4,5,6). I use here for example only 1 compare
interrupt Timer B_0 . And I named BINTR for Port 1 address FFE8.



;********************** INTERRUPT VECTORS
***********************************



RSEG INTVEC ;



DW TRAPE0 ;$FFE0.......................
.N/U

DW TRAPE2 ;$FFE2.......................
.N/U

DW TRAPE4 ;$FFE4.......................
.N/U

DW TRAPE6 ;$FFE6.......................
.N/U

DW BINTR ;$FFE8....I/O PORT P1

DW TRAPEA ;$FFEA........................
N/U

DW TRAPEC ;$FFEC.......................
.N/U

DW TRAPEE ;$FFEE.......................
.N/U

DW TRAPF0 ;$FFF0....UART0 XMIT

DW TRAPF2 ;$FFF2....UART0 RCVE

DW TRAPF4 ;$FFF4....WATCHDOG TIMER

DW TRAPF6 ;$FFF6......................
..N/U

DW TRAPF8 ;$FFF8....TIMER_B (CAP/COMP
1/6, OVRFLOW)

DW MAIN ;$FFFA....TIMER_B
(COMPARE0)

DW DOZE ;$FFFC....OSC FAULT, NMI

DW PWRON ;$FFFE....POWER UP RESET





;********************** INITIAL RESET
***************************************

;

RSEG CODE

;----
------------------

PWRON: DINT
;DISABLE GENERAL INTERRUPTS

MOV.W #WDTPW+WDTHOLD,&WDTCTL ; DISABLE
WATCHDOG TIMER,

CLR.B &P1IE
;DISABLE P1 INTERRUPTS

MOV.W #SFE(CSTACK),SP
;START OF STACK



PWR0A: BIT.B #LFOF,&FLL_CTL0
;LOOP WHILE LF FAULT

JNZ PWR0A



BIT.B #DCOF,&FLL_CTL0
;LOOP WHILE DCO FAULT

JNZ PWR0A

;----
----------------





As you can see, the chip will start the CODE at PWRON as the battery
inserted, the comments for each line of code is good enough for explanation
isn't it? SO the chip will stablize after 2 loops to check for LF fault and
DCO fault. After that you can initialize all the ports, clear all the RAM
memory, ... Do wahtever you have to do to initially, setup the program, and
finally, branch to ENDAY: put the chip to sleep mode for storage, save the
power.

Suppose I have only 1 button for the device port 1.0. I need to enable the
button interrupt for port 1.0

;-------------- code for ENDAY --------------------------

ENDAY: CLR.B &P1IFG
; CLR POSSIBLE INTERRUPT FLAGS

BIC.B #01H,&P1DIR
; MAKE P1.0 INPUT

MOV.B #01H,&P1IES
; INTERUPT EDGE...P1.0 HI TO LO

MOV.B #01H,&P1IE
; ENBL P1.0 INTERRUPT





MOV.W #SFE(CSTACK),SP
; START OF STACK (CLEAR)

MOV.W #SCG1+SCG0+CPUOFF+GIE,SR ;
LPMODE3..ENABLE GENERAL INTERRUPT and



NOP
; WHILE ASLEEP


; A SWITCH ACTIVATION WILL VECTOR
TO


; BINTR AND WILL RETI AFTER
ALTERING THE


; SR ON THE STACK, IF THE CONTACT
IS VALID.


; THE PROGRAM WILL CONTINUE FROM
HERE WITH A


; BRANCH TO `NEWDAY', WHICH WILL
CAUSE THE


; UNIT TO POWERUP. IF AN
INTERMITTENT


; CLOSURE, THE UNIT WILL SHUTDOWN
IN LOW


; POWER MODE AGAIN.



BIC #TBIE,&TB0CTL
; DISABLE TIMER B OVERFLOW INTERRUPT

BRA #NEWDAY
;. START THE PROGRAM WHEN THE BUTTON INTERRUPT


; TO TURN THE DEVICE ON.

;----
---------



Now the chip is sleep in LPM mode 3 to save power. When the button is
pressed:



;---------------- CODE TO CHECK FOR BUTTON INTERRUPT
----

BINTR: CLR.B &P1IFG
;CLEAR PORT 1 INTERRUPT FLAGS

BIS.W #GIE,SR
;RE-ENABLE GENERAL INTERRUPT



MOV.W #0400H,TEMP
;DELAY FOR 5 MS

BINT00: DEC.W TEMP
;16 BIT.W REGISTER..DECREMENT TILL 0000H

JNZ BINT00





MOV.B &P1IN,BTNSAV
;CHECK FOR SWITCH INTERRUPT (XITION TO LO)

INV.B BTNSAV
;CHANGE TO POSITIVE LOGIC

AND.B #01H,BTNSAV
;MASK FOR BIT 0

JZ BINT01
;FALSE INTERRUPT

TST.B OPMODE
;IF OPMODE = SLEEPMODE=0 THEN SET SR ON


; THE STACK TO POWERUP ON RTI

JNZ BINT02
; NOT SLEEP


;ASLEEP

BIC #TBIE,&TB0CTL
;DISABLE TIMER_B OVERFLOW INTERRUPTS

CLR 0(SP)
;SET CPU ACTIVE ON RTI



BINT01: RETI



BINT02: MOV.B BTNSAV,BTNMEM
;SAVE FOR BUTTON CHECK ROUTINE

RETI ; ..

;--------------- END OF BUTTON INTERRUPT
---------------------------------



As you can see the code to detect the bouncing button for 5 ms. if the
button is pressed < 5 ms then it will be ignored. An valid button pressed
will return and wake the CPU up and start the NEWDAY routine (in DOZE). It
will start your program (turn on your device). If it is not from the sleep
mode (OPMODE = 0 operation mode) then it will be OPMODE 1, 2,3, 4 whatever
you named it then you know what to do with the button pressed. Example,
OPMODE 1 is in SET HOUR, the button will increase the HOURS, if the OPMODE 2
is in SET MINUTE, the button pressed will increase MINUTES. And as you know
with port 1 we can have total 8 buttons to do so many thing.





Now for the DOZE, this is the place for the CPU to rest (LPM3) to save
power:

;----------- code for the DOZE
--------------

DOZE: MOV #SFE(CSTACK),SP
;START OF STACK (CLR POSSIBLE PENDING RTI)



BIC.B #01H,&P1DIR
; MAKE P1.0 INPUTS

MOV.B #01H,&P1IES
;INTERUPT EDGE...HI TO LO ON P1.0

MOV.B #01H,&P1IE
;ENABLE P1.0 INTERRUPTS



MOV #0120H,&TBCTL
;RECONDITION TIMERB 32KHZ, CONT UP..CAUTIONARY



ADD #1000H,&TBCCR0
;ADD 125MS TO COMPARE B0 REG (4096/32768)

MOV #0010H,&TBCCTL0
;ENABLE TIMERB COMPARE0 INTERRUPT



;-----------------------------------



DOZ00: MOV #00D8H,SR
;LPMODE3..ENABLE GENERAL INTERRUPT

NOP
;BTTN PRESSES WHILE IN DOZE WILL VECTOR TO


; BINTR AND ReTI BACK TO HERE TO THE LO
PWR mode


;125MS COMPARE WILL VECTOR TO MAIN.


;MAIN WILL TERMINATE WITH A BRANCH BACK
TO DOZE.


; IN ORDER TO SET UP THE SWITCH
INTERRUPTS


; AND ADD 125MS TO THE NEXT COMPARE
INTERRUPT.



JMP DOZ00
;PRECAUTION

;-------------- end code for doze
-----
-



As you see up to now, the program (the CPU) resets at PWRON, loop until the
CPU is stable then go to ENDAY to sleep to save power. If a button is
pressed during sleep mode, the RETI will trigger the SR to turn the CPU ON,
the program will go to NEWDAY:



;----------- code for the NEWDAY ----------------------------

NEWDAY:

.......... DO whatever you have to do to display the device or do something
then branch to DOZE to let the CPU sleep. During the CPU sleep in DOZE, the
timer B compare 0 with 125 ms (1000H will be 125 ms, 2000H will be 250 ms,
and so on ... depends on how many ms seconds you want the button to react.)

BR #DOZE

;--------- end code for NEWDAY ----------------------------



Now the code for the MAIN: the MAIN will be running every 125 ms during
awake mode and you can do different task in the MAIN depends on what you
want to do:



;---------------- Code for MAIN running every 125 ms during awake
-------------

MAIN: MOV.W #WDTPW+WDTHOLD,&WDTCTL ; DISABLE WATCHDOG
TIMER,



INC.B EIGHTHS
;INCREMENT 1/8 SEC CTR

AND.B #07H,EIGHTHS
;MASK OFF UNUSED BITS



BIS.W #GIE,SR
;RE-ENABLE GEN INTERRUPTS FOR BTTN PRESSES



MOV.B EIGHTHS,R5

RLA R5

BR MAIN00(R5)



MAIN00: DW JOB0

DW JOB1

DW JOB2

DW JOB3

DW JOB4

DW JOB5

DW JOB6

DW JOB7



JOB0: Do something then ..

BR #DOZE



JOB1: Do something then ..

BR #DOZE



JOB2: Do something then ..

BR #DOZE



JOB3: Do something then ..

BR #DOZE



JOB4: Do something then ..

BR #DOZE



JOB5: Do something then ..

BR #DOZE



JOB6: Do something then ..

BR #DOZE



JOB7: Do something then ..

BR #DOZE

;-------------- end code for MAIN -------------------



This is a complete frame programming for a MSP430F449 chip from start power
up, detect LF and DCO fault to make sure 100% the CPU is stable and back to
sleep, wait for a button pressed to wake up and start a NEWDAY then go back
to sleep. During AWAKE mode, every 125 ms, the CPU will wake up to check
for any task that it has to do, then back to sleep until the program go back
to ENDAY (like 2 hours without a button pressed, the program will go back to
sleep mode.



Finally about TRAPE0, TRAPE2, ... I name it and put a code in it routine to
see if any interrupt occur during my program running so I can trap that
interrupt back to DOZE so I don't have any unwanted interrupt that will make
my program go haywired.



TRAPE0: MOV.B #0E0H,ERROR

... display the ERROR so I know what going all

.. delay the dislpay for 10 seconds ....

BR #DOZE



it is also a good programming when we put all the initialization in one
routine that I called PREP (prepare):

;------------ code to put all initialization in one routine ----------------

PREP: MOV.W #WDTPW+WDTHOLD,&WDTCTL ; DISABLE
WATCHDOG TIMER,



MOV.B #032H,&SCFQCTL
;DCOCLK = 50*30.518 = 1.52mhz, MODULATION ON

CLR.B &SCFI0
;DCO RANGE = .65/6mhz

CLR.B &SCFI1
; ..



MOV.B #0B0H,FLL_CTL0
;SELECT.. DCO, LO FREQ, 10pf LOAD

MOV.B #020H,FLL_CTL1
;XT2OFF, ACLK/1



CLR.B &IE1
;CAUTIONARY DISABLE MODULE INTERRUPT
REGISTERS

CLR.B &IE2

CLR.B &IFG1
;CAUTIONARY CLEAR MODULE INTERRUPT FLAGS

CLR.B &IFG2
; ..

CLR.B &ME1
;CAUTIONARY MODULE DISABLES

CLR.B &ME2
; ..



;-------------- TIMER A SETUP
-----
----------

; SET UP TIMER A FOR SOME USE, LIKE A PIEZO TO MAKE A SOUND OR SOMETHING

;----
--------------

MOV #0104H,&TACTL
;TIMERA ACLK, STOPPED, CLEARED

MOV #0008H,&CCR0
;COMPARE REG0 TO 7(DELAYED), TACL0 4096hz

MOV #0004H,&CCR2
;COMPARE REG1 TO 4, TACL1 (50%DC)

MOV #00E0H,&CCTL2
;PREPARE OUTP UNIT1 FOR RESET/SET

CLR &CCTL0
;CLR CAP/COMP CONTROL REG0

BIC #0010H,&TACTL
;STOP 4KHZ PIEZO DRIVE



;------------ PORT1 ----------------

;P1.0 button

;P1.1 to P1.7 N/U



CLR.B &P1IES
;INTERUPT EDGE...LOW TO HI

CLR.B &P1OUT
;SET PORT1 OUTPUT LATCHES LOW

MOV.B #0FEH,&P1DIR
;ALL OUTPUT EXCEPT P1.0 is INPUT

CLR.B &P1IE
;DISABLE P1 INTERRUPTS

CLR.B &P1IFG
;RESET POSSIBLE INTERRUPT FLAG

CLR.B &P1SEL
;Make port 1 to be all IO line



;PORT2

;PORT3

;PORT4

;PORT5

;PORT6



CLR &ADC12CTL0
;CLEAR A/D CONTROL REGISTERS

CLR &ADC12CTL1 ; ..

CLR &ADC12IFG
;CLEAR INTERRUPT ENABLE FLAG REGS

CLR &ADC12IE ; ..



RET

;---------- end code for PREP -------


You can put the PREP right after the CPU is stable then clear RAM, read
EEPROM ... before put the CPU into sleep mode.



I hope to help you guy with some information that I worked in the field of
assembler for the MSP430.



Anthony Ha



























-------Original Message-------



From: Peter Grey

Date: 10/22/2013 6:32:41 PM

To: m...

Subject: RE: [msp430] Problems with MSP430F2132



Hi Al,



Thanks for the detailed reply. I must admit I have not used NMI since I was
using the PDP minis, and that is a while ago! I shall take a look and may
have a few questions



Thanks



Peter



From: m... [mailto:m...] On Behalf Of
Onestone

Sent: Tuesday, 22 October 2013 4:26 PM

To: m...

Subject: Re: [msp430] Problems with MSP430F2132







This is probably just the usual issue with debounce of a switch (attaching
the battery is a switch), and the system getting caught out. Typically you
would have an INIT process shortly after start up with a clock stabilisation
loop or similar. I don't know how you handle NMI's but typically if your NMI
handling is too simplistic you will get a clock error, jump to the NMI which
might then get stuck in a loop or stall, or simply corrupt the PC. If you
have a LED try having the LED flash briefly during INIT, ie on very fast
then off once stable. Then have it turned fully on in the NMNI and point the
NMI back to itself. That will tell you if this is the issue.



Al

On 22/10/2013 4:50 PM, Peter Grey wrote:

I have been using these chips for a while. My devices have a battery
connected to them and, in some cases a battery charger. I find that when I
first connect a battery or take it off a charger it will not work. I need to
push a reset button. I have tried a reset chip and it makes no difference. I
can tell a customer to always press reset after the above events but I want
to find out what is going on and fix it. Has anyone experienced any such
behaviour.



TIA



Peter






































--------------Boundary-00=_Q3F9G6G0000000000000
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable


























Peter,

 

I have just sent you an email that I explained something, but I don't know that is what you want. If you think part of your code has problem, you can zip that part and send it to me as an attachment file (txt file). I can read and  have my opinion  for you.

 

Anthony Ha

 

 


 

 


-------Original Message-------

 



Date: 10/25/2013 7:48:57 PM

To: m...

Subject: RE: [msp430] Problems with MSP430F2132

 


Hi Anthony


 


I can see what you are doing at RESET. It is similar to mine but I have a MSP430F2132 and am using DCO at 1MHz. In the NMI interrupt (DOZE), I cannot see how you ever exit this. There is no RETI? What is the routine supposed to do apart from re-initialising the stack and setting up the registers again? I turn on a LED in the NMI interrupt routine but I never see this happen. I am beginning to think that this may not be a NMI problem, but something silly I am doing.


 


Thanks


 


Peter


 




From: m... [mailto:m...] On Behalf Of a...@gmail.com
Sent: Wednesday, 23 October 2013 11:40 AM
To: m...
Subject: RE: [msp430] Problems with MSP430F2132


 










Here is my assembler layout for a typical MSP430F449 chip:



 



The first section of the program is the declanation of Interrupt Vector (IV). Depending on what chip, you will have 2, 4, 8  IV. The 449 chip has 2 IV and the address from FFE0 to FFFE (the last two by is POWER ON RESET) that I named PWRON and I called DOZE (address FFFC for the Oscillator, NMI reset). I called MAIN address FFFA for the timer_B compare 0: with Timer B we will have 7 of them from 0,1,2,3,4,5,6). I use here for example only 1 compare interrupt Timer B_0 . And I named BINTR for Port 1 address FFE8.



 



;********************** INTERRUPT VECTORS ***********************************



 



 RSEG         INTVEC  ;



 



 DW             TRAPE0                         ;$FFE0.........................N/U
 DW             TRAPE2                         ;$FFE2.........................N/U
 DW             TRAPE4                         ;$FFE4.........................N/U
 DW             TRAPE6                         ;$FFE6.........................N/U
 DW              BINTR                            ;$FFE8....I/O PORT P1
 DW             TRAPEA                        ;$FFEA.........................N/U
 DW             TRAPEC                         ;$FFEC.........................N/U
 DW             TRAPEE                         ;$FFEE.........................N/U
 DW             TRAPF0                          ;$FFF0....UART0 XMIT
 DW             TRAPF2                           ;$FFF2....UART0 RCVE
 DW             TRAPF4                          ;$FFF4....WATCHDOG TIMER
 DW             TRAPF6                          ;$FFF6.........................N/U
 DW             TRAPF8                          ;$FFF8....TIMER_B (CAP/COMP 1/6, OVRFLOW)
 DW             MAIN                               ;$FFFA....TIMER_B (COMPARE0)
 DW             DOZE                             ;$FFFC....OSC FAULT, NMI
 DW             PWRON                        ;$FFFE....POWER UP RESET



 




;********************** INITIAL RESET ***************************************
;
 RSEG        CODE  



;-----------------------



PWRON:      DINT                                                                                 ;DISABLE GENERAL INTERRUPTS



                      MOV.W       #WDTPW+WDTHOLD,&WDTCTL          ; DISABLE WATCHDOG TIMER,
                      CLR.B          &P1IE                                                         ;DISABLE P1 INTERRUPTS
                       MOV.W       #SFE(CSTACK),SP                                 ;START OF STACK
       



PWR0A:       BIT.B          #LFOF,&FLL_CTL0                                   ;LOOP WHILE LF FAULT
                      JNZ             PWR0A               



 



                       BIT.B          #DCOF,&FLL_CTL0                                   ;LOOP WHILE DCO FAULT
                        JNZ            PWR0A              



;---------------------------------------------------------



 



 



As you can see, the chip will start the CODE at PWRON as the battery inserted,  the comments for each line of code is good enough for explanation, isn't it? SO the chip will stablize after 2 loops to check for LF fault and DCO fault. After that you can initialize all the ports, clear all the RAM memory, ... Do wahtever you have to do to initially, setup the program, and finally, branch to ENDAY: put the chip to sleep mode for storage, save the power.



Suppose I have only 1 button for the device port 1.0. I need to enable the button interrupt for port 1.0



;-------------- code for ENDAY --------------------------                 



ENDAY:      CLR.B        &P1IFG                                                              ; CLR POSSIBLE INTERRUPT FLAGS 
                     BIC.B        #01H,&P1DIR                                                    ; MAKE P1.0 INPUT
                     MOV.B      #01H,&P1IES                                                    ; INTERUPT EDGE...P1.0 HI TO LO
                     MOV.B      #01H,&P1IE                                                       ; ENBL P1.0  INTERRUPT



 




                     MOV.W       #SFE(CSTACK),SP                                         ; START OF STACK  (CLEAR)
                     MOV.W       #SCG1+SCG0+CPUOFF+GIE,SR                ; LPMODE3..ENABLE GENERAL INTERRUPT and



 



                     NOP                                                                                         ; WHILE ASLEEP
                                                                                                                       ; A SWITCH ACTIVATION WILL VECTOR TO
                                                                                                                       ; BINTR AND WILL RETI  AFTER ALTERING THE
                                                                                                                       ; SR ON THE STACK, IF THE CONTACT IS VALID.
                                                                                                                       ; THE PROGRAM WILL CONTINUE FROM HERE WITH A
                                                                                                                       ; BRANCH TO `NEWDAY', WHICH WILL CAUSE THE
                                                                                                                       ; UNIT TO POWERUP.  IF AN INTERMITTENT
                                                                                                                       ; CLOSURE, THE UNIT WILL SHUTDOWN IN LOW
                                                                                                                       ; POWER MODE AGAIN.



 



                     BIC             #TBIE,&TB0CTL                                                 ; DISABLE TIMER B OVERFLOW INTERRUPT
                     BRA           #NEWDAY                                                           ;. START THE PROGRAM WHEN THE BUTTON INTERRUPT



                                                                                                                       ; TO TURN THE DEVICE ON.



;--------------------------------------------------



 



Now the chip is sleep in LPM  mode 3 to save power. When the button is pressed:  



 



;---------------- CODE TO CHECK FOR BUTTON INTERRUPT ----



BINTR:    CLR.B           &P1IFG                                                                  ;CLEAR PORT 1 INTERRUPT FLAGS
                BIS.W            #GIE,SR                                                                 ;RE-ENABLE GENERAL INTERRUPT
       



                MOV.W          #0400H,TEMP                                                   ;DELAY FOR 5 MS 



BINT00:   DEC.W        TEMP                                                                   ;16 BIT.W REGISTER..DECREMENT TILL 0000H
                JNZ                BINT00          
       



   



               MOV.B           &P1IN,BTNSAV                                                 ;CHECK FOR SWITCH INTERRUPT (XITION TO LO)
                INV.B              BTNSAV                                                             ;CHANGE TO POSITIVE LOGIC
               AND.B             #01H,BTNSAV                                                  ;MASK FOR BIT 0
               JZ                    BINT01                                                                  ;FALSE INTERRUPT
               TST.B             OPMODE                                                             ;IF OPMODE = SLEEPMODE=0 THEN SET SR ON
                                                                                                                      ; THE STACK TO POWERUP ON RTI
               JNZ                 BINT02                                                                  ; NOT SLEEP
                                                                                                                      ;ASLEEP
                BIC                 #TBIE,&TB0CTL                                                 ;DISABLE TIMER_B OVERFLOW INTERRUPTS
                 CLR              0(SP)                                                                     ;SET CPU ACTIVE ON RTI



 



 BINT01: RETI   



 



BINT02:    MOV.B         BTNSAV,BTNMEM                                             ;SAVE FOR BUTTON CHECK ROUTINE
                 RETI                    ; ..   



;--------------- END OF BUTTON INTERRUPT ---------------------------------



 



As you can see the code to detect the bouncing button for 5 ms. if the button is pressed < 5 ms then it will be ignored. An valid button pressed will return and wake the CPU up and start the NEWDAY routine (in DOZE). It will start your program (turn on your device). If it is not from the sleep mode (OPMODE = 0 operation mode) then it will be OPMODE 1, 2,3, 4 whatever you named it then you know what to do with the button pressed. Example, OPMODE 1 is in SET HOUR, the button will increase the HOURS, if the OPMODE 2 is in SET MINUTE, the button pressed will increase MINUTES. And as you know , with port 1 we can have total 8 buttons to do so many thing.



 















Peter,

 

One more note before I go to sleep mode ( I mean I go to bed).

 

You can see I did not RETI from MAIN routine, but use BR  #DOZE instead, and the first line of code in DOZE is I clear all possible pending RETI.

 



;----------- code for the DOZE --------------



DOZE:        MOV         #SFE(CSTACK),SP                                     ;START OF STACK (CLR POSSIBLE PENDING RTI)

 

;-----------------

 



I clear the STACK POINTER in three places:

 

PWRON:

DOZE:

ENDAY:

 

In ENDAY before I put the CPU to sleep mode, I CLEAR all possible pending RETI and put the STACK POINTER to start of the stack. Some one remind me that it is high risk to do it, but it is the way I am doing.

 

Anthony Ha

---------

 

-------Original Message-------




 



Date: 10/25/2013 7:48:57 PM

To: m...

Subject: RE: [msp430] Problems with MSP430F2132

 


Hi Anthony


 


I can see what you are doing at RESET. It is similar to mine but I have a MSP430F2132 and am using DCO at 1MHz. In the NMI interrupt (DOZE), I cannot see how you ever exit this. There is no RETI? What is the routine supposed to do apart from re-initialising the stack and setting up the registers again? I turn on a LED in the NMI interrupt routine but I never see this happen. I am beginning to think that this may not be a NMI problem, but something silly I am doing.


 


Thanks


 


Peter


 


 











__._,_.___






















stime82765097













__,_._,___
--------------Boundary-00=_RNH9QL80000000000000
Content-Type: Text/Plain;
charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

I wrote the firmware for the Dive Computer and Dive Watches in assembler. I
wrote this simple demonstration for the Dive Computer Algorithm in FLASH.
You can play with it on the internet. This is from my home server:



http://anthonyha.dyndns-home.com/anthonyha/



You can press CTRL and the + sign to increase the font size. It just
calculate the dive time for Pre Dive Planning.



I wrote the trimix (Nitrogen, Oxygen, and Helium) algorithm totally in
assembler ( I can write in C with the IAR, but I prefer assembler) and
Hollis will release this trimix dive computer next in the name "Hollis TX1".



Anthony Ha











-------Original Message-------



From: Onestone

Date: 10/24/13 19:21:01

To: m...

Subject: Re: [msp430] Problems with MSP430F2132







My point was that your program structure and implementation has some
potential issues, and could be improved. I've been programming for over 40
years and it makes no difference. Other than lots of experience, which I
believe gives me the right to comment too, it doesn't make me perfect or
immune to doing dumb shit. Nor does a program which is reliable mean that it
is necessarily perfect for other tasks, or even well written. It is great
that you spend the time to try and help people, that is the whole purpose of
the group, and my intention wasn't to knock you down, but to try and
highlight what could cause some issues for Peter (the OP), and by doing so
also help him out and give him options.



I'm especially very happy to see another assembly programmer here, we are a
dying breed, so huge kudos for that.



Sorry i offended, it wasn't meant to offend, but to clarify.



Al





On 25/10/2013 12:22 PM, a...@gmail.com wrote:



This is not a complete program, just some parts of a layout. I wrote
assembler over 20 years for Scuba Diving Industry and never had a recall.
Ofcourse, some units might be defected like leaking but the firmware to
control the CPU is very low power. It lasts for years because when it goes
to sleep mode, it is only a few micro amp. Ofcourse as you said, all ports
have to be under control, as a port is left high of floating, it might draw
current.



It is not only a sample program, but it is a part of my life also. The main
code for the Scuba Dive Computer is about over 30 thousand line of code The
algorithm for the diving computer). Other part like read write EEPROM,
Communicating to the PC thru USB (or Bluetooth), BSL code (that I gave you
guy in another email), .....



I have two kinds of programs: One for the dive watches, and one for the
Scuba dive Computers. Both of them have the same structure, that is when it
is awake, it is a 125 ms interrupt (in DOZE) to check for any task (in MAIN)
that the CPU has to do then back to sleep. The different between the two is
when power up, the watches will stay awake until is is put in to deep sleep
for storage. The dive computer after power up, it is put into sleep as you
can see in the sample program. Ofcourse, I removed all the others code that
I thought it would make you confuse or I had to explain if I included the
code ịn.



Anthony Ha











-------Original Message-------



From: Onestone

Date: 10/23/2013 8:35:38 PM

To: m...

Subject: Re: [msp430] Problems with MSP430F2132



This is actually typical of a routine that has a subtle bug. Possibly a
corrupted stack. You can test this with a RAM counter (since a corrupted PC
doesn't force a POR), just don't init that word/byte on power up, or set
flags to say it has been a POR. then use a LED to flash if the counter is
non-zero. If it is disappearing up its own bum then you will need to trap
the routine. If you can only clear by a reset then it could still be an NMI
or simple PC corruption.



Watch the sample code, the switch check is polled, and inefficient, and the
clearing of SP prior to entering a sleep mode can be dangerous, sometimes
routines may be left operating, unless you explicitly structure your code to
clear all pending tasks before sleeping.



Al





On 24/10/2013 12:42 PM, Peter Grey wrote:



Hi

My technician was the one who reported to me that it had locked up
completely. I conducted some tests and found that it was only one area of
the program that did not work. I now do not believe it is a NMI problem.
However, your program looks interesting and I will study it a while.



Thanks



Peter



From: m... [mailto:m...] On Behalf Of
a...@gmail.com

Sent: Wednesday, 23 October 2013 11:40 AM

To: m...

Subject: RE: [msp430] Problems with MSP430F2132











Here is my assembler layout for a typical MSP430F449 chip:



The first section of the program is the declanation of Interrupt Vector (IV)
Depending on what chip, you will have 2, 4, 8 IV. The 449 chip has 2 IV
and the address from FFE0 to FFFE (the last two by is POWER ON RESET) that I
named PWRON and I called DOZE (address FFFC for the Oscillator, NMI reset).
I called MAIN address FFFA for the timer_B compare 0: with Timer B we will
have 7 of them from 0,1,2,3,4,5,6). I use here for example only 1 compare
interrupt Timer B_0 . And I named BINTR for Port 1 address FFE8.



;********************** INTERRUPT VECTORS
***********************************



RSEG INTVEC ;



DW TRAPE0 ;$FFE0.......................
.N/U

DW TRAPE2 ;$FFE2.......................
.N/U

DW TRAPE4 ;$FFE4.......................
.N/U

DW TRAPE6 ;$FFE6.......................
.N/U

DW BINTR ;$FFE8....I/O PORT P1

DW TRAPEA ;$FFEA........................
N/U

DW TRAPEC ;$FFEC.......................
.N/U

DW TRAPEE ;$FFEE.......................
.N/U

DW TRAPF0 ;$FFF0....UART0 XMIT

DW TRAPF2 ;$FFF2....UART0 RCVE

DW TRAPF4 ;$FFF4....WATCHDOG TIMER

DW TRAPF6 ;$FFF6......................
..N/U

DW TRAPF8 ;$FFF8....TIMER_B (CAP/COMP
1/6, OVRFLOW)

DW MAIN ;$FFFA....TIMER_B
(COMPARE0)

DW DOZE ;$FFFC....OSC FAULT, NMI

DW PWRON ;$FFFE....POWER UP RESET





;********************** INITIAL RESET
***************************************

;

RSEG CODE

;----
------------------

PWRON: DINT
;DISABLE GENERAL INTERRUPTS

MOV.W #WDTPW+WDTHOLD,&WDTCTL ; DISABLE
WATCHDOG TIMER,

CLR.B &P1IE
;DISABLE P1 INTERRUPTS

MOV.W #SFE(CSTACK),SP
;START OF STACK



PWR0A: BIT.B #LFOF,&FLL_CTL0
;LOOP WHILE LF FAULT

JNZ PWR0A



BIT.B #DCOF,&FLL_CTL0
;LOOP WHILE DCO FAULT

JNZ PWR0A

;----
----------------





As you can see, the chip will start the CODE at PWRON as the battery
inserted, the comments for each line of code is good enough for explanation
isn't it? SO the chip will stablize after 2 loops to check for LF fault and
DCO fault. After that you can initialize all the ports, clear all the RAM
memory, ... Do wahtever you have to do to initially, setup the program, and
finally, branch to ENDAY: put the chip to sleep mode for storage, save the
power.

Suppose I have only 1 button for the device port 1.0. I need to enable the
button interrupt for port 1.0

;-------------- code for ENDAY --------------------------

ENDAY: CLR.B &P1IFG
; CLR POSSIBLE INTERRUPT FLAGS

BIC.B #01H,&P1DIR
; MAKE P1.0 INPUT

MOV.B #01H,&P1IES
; INTERUPT EDGE...P1.0 HI TO LO

MOV.B #01H,&P1IE
; ENBL P1.0 INTERRUPT





MOV.W #SFE(CSTACK),SP
; START OF STACK (CLEAR)

MOV.W #SCG1+SCG0+CPUOFF+GIE,SR ;
LPMODE3..ENABLE GENERAL INTERRUPT and



NOP
; WHILE ASLEEP


; A SWITCH ACTIVATION WILL VECTOR
TO


; BINTR AND WILL RETI AFTER
ALTERING THE


; SR ON THE STACK, IF THE CONTACT
IS VALID.


; THE PROGRAM WILL CONTINUE FROM
HERE WITH A


; BRANCH TO `NEWDAY', WHICH WILL
CAUSE THE


; UNIT TO POWERUP. IF AN
INTERMITTENT


; CLOSURE, THE UNIT WILL SHUTDOWN
IN LOW


; POWER MODE AGAIN.



BIC #TBIE,&TB0CTL
; DISABLE TIMER B OVERFLOW INTERRUPT

BRA #NEWDAY
;. START THE PROGRAM WHEN THE BUTTON INTERRUPT


; TO TURN THE DEVICE ON.

;----
---------



Now the chip is sleep in LPM mode 3 to save power. When the button is
pressed:



;---------------- CODE TO CHECK FOR BUTTON INTERRUPT
----

BINTR: CLR.B &P1IFG
;CLEAR PORT 1 INTERRUPT FLAGS

BIS.W #GIE,SR
;RE-ENABLE GENERAL INTERRUPT



MOV.W #0400H,TEMP
;DELAY FOR 5 MS

BINT00: DEC.W TEMP
;16 BIT.W REGISTER..DECREMENT TILL 0000H

JNZ BINT00





MOV.B &P1IN,BTNSAV
;CHECK FOR SWITCH INTERRUPT (XITION TO LO)

INV.B BTNSAV
;CHANGE TO POSITIVE LOGIC

AND.B #01H,BTNSAV
;MASK FOR BIT 0

JZ BINT01
;FALSE INTERRUPT

TST.B OPMODE
;IF OPMODE = SLEEPMODE=0 THEN SET SR ON


; THE STACK TO POWERUP ON RTI

JNZ BINT02
; NOT SLEEP


;ASLEEP

BIC #TBIE,&TB0CTL
;DISABLE TIMER_B OVERFLOW INTERRUPTS

CLR 0(SP)
;SET CPU ACTIVE ON RTI



BINT01: RETI



BINT02: MOV.B BTNSAV,BTNMEM
;SAVE FOR BUTTON CHECK ROUTINE

RETI ; ..

;--------------- END OF BUTTON INTERRUPT
---------------------------------



As you can see the code to detect the bouncing button for 5 ms. if the
button is pressed < 5 ms then it will be ignored. An valid button pressed
will return and wake the CPU up and start the NEWDAY routine (in DOZE). It
will start your program (turn on your device). If it is not from the sleep
mode (OPMODE = 0 operation mode) then it will be OPMODE 1, 2,3, 4 whatever
you named it then you know what to do with the button pressed. Example,
OPMODE 1 is in SET HOUR, the button will increase the HOURS, if the OPMODE 2
is in SET MINUTE, the button pressed will increase MINUTES. And as you know
with port 1 we can have total 8 buttons to do so many thing.





Now for the DOZE, this is the place for the CPU to rest (LPM3) to save
power:

;----------- code for the DOZE
--------------

DOZE: MOV #SFE(CSTACK),SP
;START OF STACK (CLR POSSIBLE PENDING RTI)



BIC.B #01H,&P1DIR
; MAKE P1.0 INPUTS

MOV.B #01H,&P1IES
;INTERUPT EDGE...HI TO LO ON P1.0

MOV.B #01H,&P1IE
;ENABLE P1.0 INTERRUPTS



MOV #0120H,&TBCTL
;RECONDITION TIMERB 32KHZ, CONT UP..CAUTIONARY



ADD #1000H,&TBCCR0
;ADD 125MS TO COMPARE B0 REG (4096/32768)

MOV #0010H,&TBCCTL0
;ENABLE TIMERB COMPARE0 INTERRUPT



;-----------------------------------



DOZ00: MOV #00D8H,SR
;LPMODE3..ENABLE GENERAL INTERRUPT

NOP
;BTTN PRESSES WHILE IN DOZE WILL VECTOR TO


; BINTR AND ReTI BACK TO HERE TO THE LO
PWR mode


;125MS COMPARE WILL VECTOR TO MAIN.


;MAIN WILL TERMINATE WITH A BRANCH BACK
TO DOZE.


; IN ORDER TO SET UP THE SWITCH
INTERRUPTS


; AND ADD 125MS TO THE NEXT COMPARE
INTERRUPT.



JMP DOZ00
;PRECAUTION

;-------------- end code for doze
-----
-



As you see up to now, the program (the CPU) resets at PWRON, loop until the
CPU is stable then go to ENDAY to sleep to save power. If a button is
pressed during sleep mode, the RETI will trigger the SR to turn the CPU ON,
the program will go to NEWDAY:



;----------- code for the NEWDAY ----------------------------

NEWDAY:

.......... DO whatever you have to do to display the device or do something
then branch to DOZE to let the CPU sleep. During the CPU sleep in DOZE, the
timer B compare 0 with 125 ms (1000H will be 125 ms, 2000H will be 250 ms,
and so on ... depends on how many ms seconds you want the button to react.)

BR #DOZE

;--------- end code for NEWDAY ----------------------------



Now the code for the MAIN: the MAIN will be running every 125 ms during
awake mode and you can do different task in the MAIN depends on what you
want to do:



;---------------- Code for MAIN running every 125 ms during awake
-------------

MAIN: MOV.W #WDTPW+WDTHOLD,&WDTCTL ; DISABLE WATCHDOG
TIMER,



INC.B EIGHTHS
;INCREMENT 1/8 SEC CTR

AND.B #07H,EIGHTHS
;MASK OFF UNUSED BITS



BIS.W #GIE,SR
;RE-ENABLE GEN INTERRUPTS FOR BTTN PRESSES



MOV.B EIGHTHS,R5

RLA R5

BR MAIN00(R5)



MAIN00: DW JOB0

DW JOB1

DW JOB2

DW JOB3

DW JOB4

DW JOB5

DW JOB6

DW JOB7



JOB0: Do something then ..

BR #DOZE



JOB1: Do something then ..

BR #DOZE



JOB2: Do something then ..

BR #DOZE



JOB3: Do something then ..

BR #DOZE



JOB4: Do something then ..

BR #DOZE



JOB5: Do something then ..

BR #DOZE



JOB6: Do something then ..

BR #DOZE



JOB7: Do something then ..

BR #DOZE

;-------------- end code for MAIN -------------------



This is a complete frame programming for a MSP430F449 chip from start power
up, detect LF and DCO fault to make sure 100% the CPU is stable and back to
sleep, wait for a button pressed to wake up and start a NEWDAY then go back
to sleep. During AWAKE mode, every 125 ms, the CPU will wake up to check
for any task that it has to do, then back to sleep until the program go back
to ENDAY (like 2 hours without a button pressed, the program will go back to
sleep mode.



Finally about TRAPE0, TRAPE2, ... I name it and put a code in it routine to
see if any interrupt occur during my program running so I can trap that
interrupt back to DOZE so I don't have any unwanted interrupt that will make
my program go haywired.



TRAPE0: MOV.B #0E0H,ERROR

... display the ERROR so I know what going all

.. delay the dislpay for 10 seconds ....

BR #DOZE



it is also a good programming when we put all the initialization in one
routine that I called PREP (prepare):

;------------ code to put all initialization in one routine ----------------

PREP: MOV.W #WDTPW+WDTHOLD,&WDTCTL ; DISABLE
WATCHDOG TIMER,



MOV.B #032H,&SCFQCTL
;DCOCLK = 50*30.518 = 1.52mhz, MODULATION ON

CLR.B &SCFI0
;DCO RANGE = .65/6mhz

CLR.B &SCFI1
; ..



MOV.B #0B0H,FLL_CTL0
;SELECT.. DCO, LO FREQ, 10pf LOAD

MOV.B #020H,FLL_CTL1
;XT2OFF, ACLK/1



CLR.B &IE1
;CAUTIONARY DISABLE MODULE INTERRUPT
REGISTERS

CLR.B &IE2

CLR.B &IFG1
;CAUTIONARY CLEAR MODULE INTERRUPT FLAGS

CLR.B &IFG2
; ..

CLR.B &ME1
;CAUTIONARY MODULE DISABLES

CLR.B &ME2
; ..



;-------------- TIMER A SETUP
-----
----------

; SET UP TIMER A FOR SOME USE, LIKE A PIEZO TO MAKE A SOUND OR SOMETHING

;----
--------------

MOV #0104H,&TACTL
;TIMERA ACLK, STOPPED, CLEARED

MOV #0008H,&CCR0
;COMPARE REG0 TO 7(DELAYED), TACL0 4096hz

MOV #0004H,&CCR2
;COMPARE REG1 TO 4, TACL1 (50%DC)

MOV #00E0H,&CCTL2
;PREPARE OUTP UNIT1 FOR RESET/SET

CLR &CCTL0
;CLR CAP/COMP CONTROL REG0

BIC #0010H,&TACTL
;STOP 4KHZ PIEZO DRIVE



;------------ PORT1 ----------------

;P1.0 button

;P1.1 to P1.7 N/U



CLR.B &P1IES
;INTERUPT EDGE...LOW TO HI

CLR.B &P1OUT
;SET PORT1 OUTPUT LATCHES LOW

MOV.B #0FEH,&P1DIR
;ALL OUTPUT EXCEPT P1.0 is INPUT

CLR.B &P1IE
;DISABLE P1 INTERRUPTS

CLR.B &P1IFG
;RESET POSSIBLE INTERRUPT FLAG

CLR.B &P1SEL
;Make port 1 to be all IO line



;PORT2

;PORT3

;PORT4

;PORT5

;PORT6



CLR &ADC12CTL0
;CLEAR A/D CONTROL REGISTERS

CLR &ADC12CTL1 ; ..

CLR &ADC12IFG
;CLEAR INTERRUPT ENABLE FLAG REGS

CLR &ADC12IE ; ..



RET

;---------- end code for PREP -------


You can put the PREP right after the CPU is stable then clear RAM, read
EEPROM ... before put the CPU into sleep mode.



I hope to help you guy with some information that I worked in the field of
assembler for the MSP430.



Anthony Ha



























-------Original Message-------



From: Peter Grey

Date: 10/22/2013 6:32:41 PM

To: m...

Subject: RE: [msp430] Problems with MSP430F2132



Hi Al,



Thanks for the detailed reply. I must admit I have not used NMI since I was
using the PDP mini’s, and that is a while ago! I shall take a look and may
have a few questions



Thanks



Peter



From: m... [mailto:m...] On Behalf Of
Onestone

Sent: Tuesday, 22 October 2013 4:26 PM

To: m...

Subject: Re: [msp430] Problems with MSP430F2132







This is probably just the usual issue with debounce of a switch (attaching
the battery is a switch), and the system getting caught out. Typically you
would have an INIT process shortly after start up with a clock stabilisation
loop or similar. I don't know how you handle NMI's but typically if your NMI
handling is too simplistic you will get a clock error, jump to the NMI which
might then get stuck in a loop or stall, or simply corrupt the PC. If you
have a LED try having the LED flash briefly during INIT, ie on very fast
then off once stable. Then have it turned fully on in the NMNI and point the
NMI back to itself. That will tell you if this is the issue.



Al

On 22/10/2013 4:50 PM, Peter Grey wrote:

I have been using these chips for a while. My devices have a battery
connected to them and, in some cases a battery charger. I find that when I
first connect a battery or take it off a charger it will not work. I need to
push a reset button. I have tried a reset chip and it makes no difference. I
can tell a customer to always press reset after the above events but I want
to find out what is going on and fix it. Has anyone experienced any such
behaviour.



TIA



Peter




























































--------------Boundary-00=_RNH9QL80000000000000
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
























I wrote the firmware for the Dive Computer and Dive Watches in assembler. I wrote this simple demonstration for the Dive Computer Algorithm in FLASH. You can play with it on the internet. This is from my home server:

 


 

You can press CTRL and the + sign to increase the font size. It just calculate the dive time for Pre Dive Planning.

 

I wrote the trimix (Nitrogen, Oxygen, and Helium) algorithm totally in assembler ( I can write in C with the IAR, but I prefer assembler) and Hollis will release this trimix dive computer next in the name "Hollis TX1".

 

Anthony Ha

 

 

 


 

 


-------Original Message-------

 


From: Onestone

Date: 10/24/13 19:21:01

To: m...

Subject: Re: [msp430] Problems with MSP430F2132

 
My point was that your program structure and implementation has some potential issues, and could be improved. I've been programming for over 40 years and it makes no difference. Other than lots of experience, which I believe gives me the right to comment too, it doesn't make me perfect or immune to doing dumb shit. Nor does a program which is reliable mean that it is necessarily perfect for other tasks, or even well written. It is great that you spend the time to try and help people, that is the whole purpose of the group, and my intention wasn't to knock you down, but to try and highlight what could cause some issues for Peter (the OP), and by doing so also help him out and give him options.

I'm especially very happy to see another assembly programmer here, we are a dying breed, so huge kudos for that.

Sorry i offended, it wasn't meant to offend, but to clarify.

Al


On 25/10/2013 12:22 PM, anthonyha2011@gmail.com wrote:









This is not a complete program, just some parts of a layout. I wrote assembler over 20 years for Scuba Diving Industry  and never had a recall. Ofcourse, some units might be defected like leaking but the firmware to control the CPU is very low power. It lasts for years because when it goes to sleep mode, it is only a few micro amp. Ofcourse as you said, all ports have to be under control, as a port is left high of floating, it might draw current.

 

It is not only a sample program, but it is a part of my life also. The main code for the Scuba Dive Computer is about over 30 thousand line of code The algorithm for the diving computer). Other part like read write EEPROM, Communicating to the PC thru USB (or Bluetooth), BSL code (that I gave you guy in another email), .....

 

I have two kinds of programs: One for the dive watches, and one for the Scuba dive Computers. Both of them have the same structure, that is when it is awake, it is a 125 ms interrupt (in DOZE) to check for any task (in MAIN) that the CPU has to do then back to sleep. The different between the two is when power up, the watches will stay awake until is is put in to deep sleep for storage. The dive computer after power up, it is put into sleep as you can see in the sample program. Ofcourse, I removed all the others code that I thought it would make you confuse or I had to explain if I included the code ịn.

 

Anthony Ha

 

 

 


 

 


-------Original Message-------

 


From: Onestone

Date: 10/23/2013 8:35:38 PM

To: m...

Subject: Re: [msp430] Problems with MSP430F2132

 
This is actually typical of a routine that has a subtle bug. Possibly a corrupted stack. You can test this with a RAM counter (since a corrupted PC doesn't force a POR), just don't init that word/byte on power up, or set flags to say it has been a POR. then use a LED to flash if the counter is non-zero. If it is disappearing up its own bum then you will need to trap the routine. If you can only clear by a reset then it could still be an NMI or simple PC corruption.

Watch the sample code, the switch check is polled, and inefficient, and the clearing of SP prior to entering a sleep mode can be dangerous, sometimes routines may be left operating, unless you explicitly structure your code to clear all pending tasks before sleeping.

Al


On 24/10/2013 12:42 PM, Peter Grey wrote:








Hi


My technician was the one who reported to me that it had locked up completely. I conducted some tests and found that it was only one area of the program that did not work. I now do not believe it is a NMI problem. However, your program looks interesting and I will study it a while.


 


Thanks


 


Peter


 




From: m... [mailto:m...] On Behalf Of a...@gmail.com
Sent: Wednesday, 23 October 2013 11:40 AM
To: msp430
Subject: RE: [msp430] Problems with MSP430F2132


 










Here is my assembler layout for a typical MSP430F449 chip:



 



The first section of the program is the declanation of Interrupt Vector (IV). Depending on what chip, you will have 2, 4, 8  IV. The 449 chip has 2 IV and the address from FFE0 to FFFE (the last two by is POWER ON RESET) that I named PWRON and I called DOZE (address FFFC for the Oscillator, NMI reset). I called MAIN address FFFA for the timer_B compare 0: with Timer B we will have 7 of them from 0,1,2,3,4,5,6). I use here for example only 1 compare interrupt Timer B_0 . And I named BINTR for Port 1 address FFE8.



 



;********************** INTERRUPT VECTORS ***********************************



 



 RSEG         INTVEC  ;



 



 DW             TRAPE0                         ;$FFE0.........................N/U
 DW             TRAPE2                         ;$FFE2.........................N/U
 DW             TRAPE4                         ;$FFE4.........................N/U
 DW             TRAPE6                         ;$FFE6.........................N/U
 DW              BINTR                            ;$FFE8....I/O PORT P1
 DW             TRAPEA                        ;$FFEA.........................N/U
 DW             TRAPEC                         ;$FFEC.........................N/U
 DW             TRAPEE                         ;$FFEE.........................N/U
 DW             TRAPF0                          ;$FFF0....UART0 XMIT
 DW             TRAPF2                           ;$FFF2....UART0 RCVE
 DW             TRAPF4                          ;$FFF4....WATCHDOG TIMER
 DW             TRAPF6                          ;$FFF6.........................N/U
 DW             TRAPF8                          ;$FFF8....TIMER_B (CAP/COMP 1/6, OVRFLOW)
 DW             MAIN                               ;$FFFA....TIMER_B (COMPARE0)
 DW             DOZE                             ;$FFFC....OSC FAULT, NMI
 DW             PWRON                        ;$FFFE....POWER UP RESET



 




;********************** INITIAL RESET ***************************************
;
 RSEG        CODE  



;-----------------------



PWRON:      DINT                                                                                 ;DISABLE GENERAL INTERRUPTS



                      MOV.W       #WDTPW+WDTHOLD,&WDTCTL          ; DISABLE WATCHDOG TIMER,
                      CLR.B          &P1IE                                                         ;DISABLE P1 INTERRUPTS
                       MOV.W       #SFE(CSTACK),SP                                 ;START OF STACK
       



PWR0A:       BIT.B          #LFOF,&FLL_CTL0                                   ;LOOP WHILE LF FAULT
                      JNZ             PWR0A               



 



                       BIT.B          #DCOF,&FLL_CTL0                                   ;LOOP WHILE DCO FAULT
                        JNZ            PWR0A              



;---------------------------------------------------------



 



 



As you can see, the chip will start the CODE at PWRON as the battery inserted,  the comments for each line of code is good enough for explanation, isn't it? SO the chip will stablize after 2 loops to check for LF fault and DCO fault. After that you can initialize all the ports, clear all the RAM memory, ... Do wahtever you have to do to initially, setup the program, and finally, branch to ENDAY: put the chip to sleep mode for storage, save the power.



Suppose I have only 1 button for the device port 1.0. I need to enable the button interrupt for port 1.0



;-------------- code for ENDAY --------------------------                 



ENDAY:      CLR.B        &P1IFG                                                              ; CLR POSSIBLE INTERRUPT FLAGS 
                     BIC.B        #01H,&P1DIR                                                    ; MAKE P1.0 INPUT
                     MOV.B      #01H,&P1IES                                                    ; INTERUPT EDGE...P1.0 HI TO LO
                     MOV.B      #01H,&P1IE                                                       ; ENBL P1.0  INTERRUPT



 




                     MOV.W       #SFE(CSTACK),SP                                         ; START OF STACK  (CLEAR)
                     MOV.W       #SCG1+SCG0+CPUOFF+GIE,SR                ; LPMODE3..ENABLE GENERAL INTERRUPT and



 



                     NOP                                                                                         ; WHILE ASLEEP
                                                                                                                       ; A SWITCH ACTIVATION WILL VECTOR TO
                                                                                                                       ; BINTR AND WILL RETI  AFTER ALTERING THE
                                                                                                                       ; SR ON THE STACK, IF THE CONTACT IS VALID.
                                                                                                                       ; THE PROGRAM WILL CONTINUE FROM HERE WITH A
                                                                                                                       ; BRANCH TO `NEWDAY', WHICH WILL CAUSE THE
                                                                                 &nbs

Hi Anthony

I have solved my problem. In my program I setup the stack at RESET and then
call a subroutine to set up the ports and the clock.

Reset

mov.w #3FFh,SP ; Initialize
stackpointer

call #Setup

In Setup I then setup the clock

clr.b &DCOCTL

mov.b &CALBC1_16MHZ,&BCSCTL1 ; Set DCO to 8MHz

mov.b &CALDCO_16MHZ,&DCOCTL

I then set up the port direction and initial states

SetupP1 mov.b #0f3h,&P1DIR ;
11110011

clr.b &P1OUT ; SET LOW

bic.b #EN_BUZZER,&P1OUT ;turn off beeper

bic.b #EN_30V,&P1OUT

SetupP2 mov.b #0E8h,&P2DIR ;11101000,

mov.b #07h,&P2SEL2 ;A0-A2

clr.b &P2OUT

bis.b #LIS_CS,&P2OUT

clr.b MDA_COUNTER

clr.b DURESS_COUNTER

SetupP3 mov.b #0B0h,&P3DIR ;10110000

clr.b &P3OUT

bis.b #TR_SDI,&P3OUT

bis.b #nSS_CONF+nSS_DATA,&P3OUT ;set both high

Finally I do a ret

My fix was to run this subroutine a second time and all my problems
disappeared??

Thanks

Peter

From: m... [mailto:m...] On Behalf Of
a...@gmail.com
Sent: Saturday, 26 October 2013 12:57 PM
To: m...
Subject: RE: [msp430] Problems with MSP430F2132

Peter,

I have just sent you an email that I explained something, but I don't know
that is what you want. If you think part of your code has problem, you can
zip that part and send it to me as an attachment file (txt file). I can read
and have my opinion for you.

Anthony Ha

-------Original Message-------

From: Peter Grey

Date: 10/25/2013 7:48:57 PM

To: m...

Subject: RE: [msp430] Problems with MSP430F2132

Hi Anthony

I can see what you are doing at RESET. It is similar to mine but I have a
MSP430F2132 and am using DCO at 1MHz. In the NMI interrupt (DOZE), I cannot
see how you ever exit this. There is no RETI? What is the routine supposed
to do apart from re-initialising the stack and setting up the registers
again? I turn on a LED in the NMI interrupt routine but I never see this
happen. I am beginning to think that this may not be a NMI problem, but
something silly I am doing.

Thanks

Peter

From: m... [mailto:m...] On Behalf Of
a...@gmail.com
Sent: Wednesday, 23 October 2013 11:40 AM
To: m...
Subject: RE: [msp430] Problems with MSP430F2132

Here is my assembler layout for a typical MSP430F449 chip:

The first section of the program is the declanation of Interrupt Vector
(IV). Depending on what chip, you will have 2, 4, 8 IV. The 449 chip has 2
IV and the address from FFE0 to FFFE (the last two by is POWER ON RESET)
that I named PWRON and I called DOZE (address FFFC for the Oscillator, NMI
reset). I called MAIN address FFFA for the timer_B compare 0: with Timer B
we will have 7 of them from 0,1,2,3,4,5,6). I use here for example only 1
compare interrupt Timer B_0 . And I named BINTR for Port 1 address FFE8.

;********************** INTERRUPT VECTORS
***********************************

RSEG INTVEC ;

DW TRAPE0
;$FFE0.........................N/U
DW TRAPE2
;$FFE2.........................N/U
DW TRAPE4
;$FFE4.........................N/U
DW TRAPE6
;$FFE6.........................N/U
DW BINTR ;$FFE8....I/O PORT P1
DW TRAPEA
;$FFEA.........................N/U
DW TRAPEC
;$FFEC.........................N/U
DW TRAPEE
;$FFEE.........................N/U
DW TRAPF0 ;$FFF0....UART0 XMIT
DW TRAPF2 ;$FFF2....UART0 RCVE
DW TRAPF4 ;$FFF4....WATCHDOG TIMER
DW TRAPF6
;$FFF6.........................N/U
DW TRAPF8 ;$FFF8....TIMER_B (CAP/COMP
1/6, OVRFLOW)
DW MAIN ;$FFFA....TIMER_B
(COMPARE0)
DW DOZE ;$FFFC....OSC FAULT, NMI
DW PWRON ;$FFFE....POWER UP RESET

;********************** INITIAL RESET
***************************************
;
RSEG CODE

;---
--------------------

PWRON: DINT
;DISABLE GENERAL INTERRUPTS

MOV.W #WDTPW+WDTHOLD,&WDTCTL ; DISABLE
WATCHDOG TIMER,
CLR.B &P1IE
;DISABLE P1 INTERRUPTS
MOV.W #SFE(CSTACK),SP
;START OF STACK

PWR0A: BIT.B #LFOF,&FLL_CTL0
;LOOP WHILE LF FAULT
JNZ PWR0A

BIT.B #DCOF,&FLL_CTL0
;LOOP WHILE DCO FAULT
JNZ PWR0A

;---
------------------

As you can see, the chip will start the CODE at PWRON as the battery
inserted, the comments for each line of code is good enough for
explanation, isn't it? SO the chip will stablize after 2 loops to check for
LF fault and DCO fault. After that you can initialize all the ports, clear
all the RAM memory, ... Do wahtever you have to do to initially, setup the
program, and finally, branch to ENDAY: put the chip to sleep mode for
storage, save the power.

Suppose I have only 1 button for the device port 1.0. I need to enable the
button interrupt for port 1.0

;-------------- code for ENDAY --------------------------

ENDAY: CLR.B &P1IFG
; CLR POSSIBLE INTERRUPT FLAGS
BIC.B #01H,&P1DIR
; MAKE P1.0 INPUT
MOV.B #01H,&P1IES
; INTERUPT EDGE...P1.0 HI TO LO
MOV.B #01H,&P1IE
; ENBL P1.0 INTERRUPT

MOV.W #SFE(CSTACK),SP
; START OF STACK (CLEAR)
MOV.W #SCG1+SCG0+CPUOFF+GIE,SR ;
LPMODE3..ENABLE GENERAL INTERRUPT and

NOP
; WHILE ASLEEP

; A SWITCH ACTIVATION WILL VECTOR TO

; BINTR AND WILL RETI AFTER ALTERING THE

; SR ON THE STACK, IF THE CONTACT IS VALID.

; THE PROGRAM WILL CONTINUE FROM HERE WITH A

; BRANCH TO `NEWDAY', WHICH WILL CAUSE THE

; UNIT TO POWERUP. IF AN INTERMITTENT

; CLOSURE, THE UNIT WILL SHUTDOWN IN LOW

; POWER MODE AGAIN.

BIC #TBIE,&TB0CTL
; DISABLE TIMER B OVERFLOW INTERRUPT
BRA #NEWDAY
;. START THE PROGRAM WHEN THE BUTTON INTERRUPT

; TO TURN THE DEVICE ON.

;---
-----------

Now the chip is sleep in LPM mode 3 to save power. When the button is
pressed:

;---------------- CODE TO CHECK FOR BUTTON INTERRUPT
----

BINTR: CLR.B &P1IFG
;CLEAR PORT 1 INTERRUPT FLAGS
BIS.W #GIE,SR
;RE-ENABLE GENERAL INTERRUPT

MOV.W #0400H,TEMP
;DELAY FOR 5 MS

BINT00: DEC.W TEMP
;16 BIT.W REGISTER..DECREMENT TILL 0000H
JNZ BINT00

MOV.B &P1IN,BTNSAV
;CHECK FOR SWITCH INTERRUPT (XITION TO LO)
INV.B BTNSAV
;CHANGE TO POSITIVE LOGIC
AND.B #01H,BTNSAV
;MASK FOR BIT 0
JZ BINT01
;FALSE INTERRUPT
TST.B OPMODE
;IF OPMODE = SLEEPMODE=0 THEN SET SR ON

; THE STACK TO POWERUP ON RTI
JNZ BINT02
; NOT SLEEP

;ASLEEP
BIC #TBIE,&TB0CTL
;DISABLE TIMER_B OVERFLOW INTERRUPTS
CLR 0(SP)
;SET CPU ACTIVE ON RTI

BINT01: RETI

BINT02: MOV.B BTNSAV,BTNMEM
;SAVE FOR BUTTON CHECK ROUTINE
RETI ; ..

;--------------- END OF BUTTON INTERRUPT
---------------------------------

As you can see the code to detect the bouncing button for 5 ms. if the
button is pressed < 5 ms then it will be ignored. An valid button pressed
will return and wake the CPU up and start the NEWDAY routine (in DOZE). It
will start your program (turn on your device). If it is not from the sleep
mode (OPMODE = 0 operation mode) then it will be OPMODE 1, 2,3, 4 whatever
you named it then you know what to do with the button pressed. Example,
OPMODE 1 is in SET HOUR, the button will increase the HOURS, if the OPMODE 2
is in SET MINUTE, the button pressed will increase MINUTES. And as you know
, with port 1 we can have total 8 buttons to do so many thing.

Now for the DOZE, this is the place for the CPU to rest (LPM3) to save
power:

;----------- code for the DOZE
--------------

DOZE: MOV #SFE(CSTACK),SP
;START OF STACK (CLR POSSIBLE PENDING RTI)

BIC.B #01H,&P1DIR
; MAKE P1.0 INPUTS
MOV.B #01H,&P1IES
;INTERUPT EDGE...HI TO LO ON P1.0

MOV.B #01H,&P1IE
;ENABLE P1.0 INTERRUPTS

MOV #0120H,&TBCTL
;RECONDITION TIMERB 32KHZ, CONT UP..CAUTIONARY
ADD #1000H,&TBCCR0
;ADD 125MS TO COMPARE B0 REG (4096/32768)
MOV #0010H,&TBCCTL0
;ENABLE TIMERB COMPARE0 INTERRUPT

;-----------------------------------

DOZ00: MOV #00D8H,SR
;LPMODE3..ENABLE GENERAL INTERRUPT
NOP
;BTTN PRESSES WHILE IN DOZE WILL VECTOR TO

; BINTR AND ReTI BACK TO HERE TO THE LO PWR mode

;125MS COMPARE WILL VECTOR TO MAIN.

;MAIN WILL TERMINATE WITH A BRANCH BACK TO DOZE.

; IN ORDER TO SET UP THE SWITCH INTERRUPTS

; AND ADD 125MS TO THE NEXT COMPARE INTERRUPT.

JMP DOZ00
;PRECAUTION

;-------------- end code for doze
----
---

As you see up to now, the program (the CPU) resets at PWRON, loop until the
CPU is stable then go to ENDAY to sleep to save power. If a button is
pressed during sleep mode, the RETI will trigger the SR to turn the CPU ON,
the program will go to NEWDAY:

;----------- code for the NEWDAY ----------------------------

NEWDAY:

.......... DO whatever you have to do to display the device or do something
then branch to DOZE to let the CPU sleep. During the CPU sleep in DOZE, the
timer B compare 0 with 125 ms (1000H will be 125 ms, 2000H will be 250 ms,
and so on ... depends on how many ms seconds you want the button to react.)

BR #DOZE

;--------- end code for NEWDAY ----------------------------

Now the code for the MAIN: the MAIN will be running every 125 ms during
awake mode and you can do different task in the MAIN depends on what you
want to do:

;---------------- Code for MAIN running every 125 ms during awake
-------------

MAIN: MOV.W #WDTPW+WDTHOLD,&WDTCTL ; DISABLE WATCHDOG
TIMER,

INC.B EIGHTHS
;INCREMENT 1/8 SEC CTR

AND.B #07H,EIGHTHS
;MASK OFF UNUSED BITS

BIS.W #GIE,SR
;RE-ENABLE GEN INTERRUPTS FOR BTTN PRESSES

MOV.B EIGHTHS,R5

RLA R5

BR MAIN00(R5)

MAIN00: DW JOB0

DW JOB1

DW JOB2

DW JOB3

DW JOB4

DW JOB5

DW JOB6

DW JOB7

JOB0: Do something then ..

BR #DOZE

JOB1: Do something then ..

BR #DOZE

JOB2: Do something then ..

BR #DOZE

JOB3: Do something then ..

BR #DOZE

JOB4: Do something then ..

BR #DOZE

JOB5: Do something then ..

BR #DOZE

JOB6: Do something then ..

BR #DOZE

JOB7: Do something then ..

BR #DOZE

;-------------- end code for MAIN -------------------

This is a complete frame programming for a MSP430F449 chip from start power
up, detect LF and DCO fault to make sure 100% the CPU is stable and back to
sleep, wait for a button pressed to wake up and start a NEWDAY then go back
to sleep. During AWAKE mode, every 125 ms, the CPU will wake up to check
for any task that it has to do, then back to sleep until the program go back
to ENDAY (like 2 hours without a button pressed, the program will go back to
sleep mode.

Finally about TRAPE0, TRAPE2, ... I name it and put a code in it routine to
see if any interrupt occur during my program running so I can trap that
interrupt back to DOZE so I don't have any unwanted interrupt that will make
my program go haywired.

TRAPE0: MOV.B #0E0H,ERROR

... display the ERROR so I know what going all

.. delay the dislpay for 10 seconds ....

BR #DOZE

it is also a good programming when we put all the initialization in one
routine that I called PREP (prepare):

;------------ code to put all initialization in one routine ----------------

PREP: MOV.W #WDTPW+WDTHOLD,&WDTCTL ; DISABLE
WATCHDOG TIMER,

MOV.B #032H,&SCFQCTL
;DCOCLK = 50*30.518 = 1.52mhz, MODULATION ON
CLR.B &SCFI0
;DCO RANGE = .65/6mhz
CLR.B &SCFI1
; ..

MOV.B #0B0H,FLL_CTL0
;SELECT.. DCO, LO FREQ, 10pf LOAD
MOV.B #020H,FLL_CTL1
;XT2OFF, ACLK/1

CLR.B &IE1
;CAUTIONARY DISABLE MODULE INTERRUPT REGISTERS
CLR.B &IE2

CLR.B &IFG1
;CAUTIONARY CLEAR MODULE INTERRUPT FLAGS
CLR.B &IFG2
; ..
CLR.B &ME1
;CAUTIONARY MODULE DISABLES
CLR.B &ME2
; ..

;-------------- TIMER A SETUP
----
------------

; SET UP TIMER A FOR SOME USE, LIKE A PIEZO TO MAKE A SOUND OR SOMETHING

;---
----------------
MOV #0104H,&TACTL
;TIMERA ACLK, STOPPED, CLEARED
MOV #0008H,&CCR0
;COMPARE REG0 TO 7(DELAYED), TACL0 4096hz
MOV #0004H,&CCR2
;COMPARE REG1 TO 4, TACL1 (50%DC)
MOV #00E0H,&CCTL2
;PREPARE OUTP UNIT1 FOR RESET/SET
CLR &CCTL0
;CLR CAP/COMP CONTROL REG0
BIC #0010H,&TACTL
;STOP 4KHZ PIEZO DRIVE

;------------ PORT1 ----------------
;P1.0 button

;P1.1 to P1.7 N/U

CLR.B &P1IES
;INTERUPT EDGE...LOW TO HI
CLR.B &P1OUT
;SET PORT1 OUTPUT LATCHES LOW
MOV.B #0FEH,&P1DIR
;ALL OUTPUT EXCEPT P1.0 is INPUT
CLR.B &P1IE
;DISABLE P1 INTERRUPTS
CLR.B &P1IFG
;RESET POSSIBLE INTERRUPT FLAG
CLR.B &P1SEL
;Make port 1 to be all IO line
;PORT2
;PORT3
;PORT4
;PORT5
;PORT6

CLR &ADC12CTL0
;CLEAR A/D CONTROL REGISTERS
CLR &ADC12CTL1 ; ..
CLR &ADC12IFG
;CLEAR INTERRUPT ENABLE FLAG REGS
CLR &ADC12IE ; ..

RET

;---------- end code for PREP -------
You can put the PREP right after the CPU is stable then clear RAM, read
EEPROM ... before put the CPU into sleep mode.

I hope to help you guy with some information that I worked in the field of
assembler for the MSP430.

Anthony Ha

-------Original Message-------

From: Peter Grey

Date: 10/22/2013 6:32:41 PM

To: m...

Subject: RE: [msp430] Problems with MSP430F2132

Hi Al,

Thanks for the detailed reply. I must admit I have not used NMI since I was
using the PDP mini's, and that is a while ago! I shall take a look and may
have a few questions

Thanks

Peter

From: m... [mailto:m...] On Behalf Of
Onestone
Sent: Tuesday, 22 October 2013 4:26 PM
To: m...
Subject: Re: [msp430] Problems with MSP430F2132

This is probably just the usual issue with debounce of a switch (attaching
the battery is a switch), and the system getting caught out. Typically you
would have an INIT process shortly after start up with a clock stabilisation
loop or similar. I don't know how you handle NMI's but typically if your NMI
handling is too simplistic you will get a clock error, jump to the NMI which
might then get stuck in a loop or stall, or simply corrupt the PC. If you
have a LED try having the LED flash briefly during INIT, ie on very fast
then off once stable. Then have it turned fully on in the NMNI and point the
NMI back to itself. That will tell you if this is the issue.

Al

On 22/10/2013 4:50 PM, Peter Grey wrote:

I have been using these chips for a while. My devices have a battery
connected to them and, in some cases a battery charger. I find that when I
first connect a battery or take it off a charger it will not work. I need to
push a reset button. I have tried a reset chip and it makes no difference. I
can tell a customer to always press reset after the above events but I want
to find out what is going on and fix it. Has anyone experienced any such
behaviour.

TIA

Peter
You're setting TOS (SP) to an odd number TOS should be end of RAM + 1,
that is your bug here. so set it to 0X0400

Al

On 29/10/2013 1:46 PM, Peter Grey wrote:
> Hi Anthony
>
> I have solved my problem. In my program I setup the stack at RESET and
> then call a subroutine to set up the ports and the clock.
>
> Reset
>
> mov.w #3FFh,SP ; Initialize stackpointer
>
> call #Setup
>
> In Setup I then setup the clock
>
> clr.b &DCOCTL
>
> mov.b &CALBC1_16MHZ,&BCSCTL1 ; Set DCO to 8MHz
>
> mov.b &CALDCO_16MHZ,&DCOCTL
>
> I then set up the port direction and initial states
>
> SetupP1 mov.b #0f3h,&P1DIR ; 11110011
>
> clr.b &P1OUT ; SET LOW
>
> bic.b #EN_BUZZER,&P1OUT ;turn off beeper
>
> bic.b #EN_30V,&P1OUT
>
> SetupP2 mov.b #0E8h,&P2DIR ;11101000,
>
> mov.b #07h,&P2SEL2 ;A0-A2
>
> clr.b &P2OUT
>
> bis.b #LIS_CS,&P2OUT
>
> clr.b MDA_COUNTER
>
> clr.b DURESS_COUNTER
>
> SetupP3 mov.b #0B0h,&P3DIR ;10110000
>
> clr.b &P3OUT
>
> bis.b #TR_SDI,&P3OUT
>
> bis.b #nSS_CONF+nSS_DATA,&P3OUT ;set both high
>
> Finally I do a ret
>
> My fix was to run this subroutine a second time and all my problems
> disappeared??
>
> Thanks
>
> Peter
>
> *From:*m... [mailto:m...] *On
> Behalf Of *a...@gmail.com
> *Sent:* Saturday, 26 October 2013 12:57 PM
> *To:* m...
> *Subject:* RE: [msp430] Problems with MSP430F2132
> Peter,
>
> I have just sent you an email that I explained something, but I don't
> know that is what you want. If you think part of your code has
> problem, you can zip that part and send it to me as an attachment file
> (txt file). I can read and have my opinion for you.
>
> Anthony Ha
>
> /-------Original Message-------/
>
> */From:/*Peter Grey */Date:/*10/25/2013 7:48:57 PM
>
> */To:/*m... */Subject:/*RE: [msp430] Problems with MSP430F2132
>
> Hi Anthony
>
> I can see what you are doing at RESET. It is similar to mine but I
> have a MSP430F2132 and am using DCO at 1MHz. In the NMI interrupt
> (DOZE), I cannot see how you ever exit this. There is no RETI? What is
> the routine supposed to do apart from re-initialising the stack and
> setting up the registers again? I turn on a LED in the NMI interrupt
> routine but I never see this happen. I am beginning to think that this
> may not be a NMI problem, but something silly I am doing.
>
> Thanks
>
> Peter
>
> *From:*m...
> [mailto:m...] *On Behalf Of *a...@gmail.com
>
> *Sent:* Wednesday, 23 October 2013 11:40 AM
> *To:* m...
> *Subject:* RE: [msp430] Problems with MSP430F2132
>
> Here is my assembler layout for a typical MSP430F449 chip:
>
> The first section of the program is the declanation of Interrupt
> Vector (IV). Depending on what chip, you will have 2, 4, 8 IV. The
> 449 chip has 2 IV and the address from FFE0 to FFFE (the last two by
> is POWER ON RESET) that I named PWRON and I called DOZE (address FFFC
> for the Oscillator, NMI reset). I called MAIN address FFFA for the
> timer_B compare 0: with Timer B we will have 7 of them from
> 0,1,2,3,4,5,6). I use here for example only 1 compare interrupt Timer
> B_0 . And I named BINTR for Port 1 address FFE8.
>
> ;********************** INTERRUPT VECTORS
> ***********************************
>
> RSEG INTVEC ;
>
> DW TRAPE0 ;$FFE0.........................N/U
> DW TRAPE2 ;$FFE2.........................N/U
> DW TRAPE4 ;$FFE4.........................N/U
> DW TRAPE6 ;$FFE6.........................N/U
> DW BINTR ;$FFE8....I/O PORT P1
> DW TRAPEA ;$FFEA.........................N/U
> DW TRAPEC ;$FFEC.........................N/U
> DW TRAPEE ;$FFEE.........................N/U
> DW TRAPF0 ;$FFF0....UART0 XMIT
> DW TRAPF2 ;$FFF2....UART0 RCVE
> DW TRAPF4 ;$FFF4....WATCHDOG TIMER
> DW TRAPF6 ;$FFF6.........................N/U
> DW TRAPF8 ;$FFF8....TIMER_B (CAP/COMP 1/6, OVRFLOW)
> DW MAIN ;$FFFA....TIMER_B (COMPARE0)
> DW DOZE ;$FFFC....OSC FAULT, NMI
> DW PWRON ;$FFFE....POWER UP RESET
> ;********************** INITIAL RESET
> ***************************************
> ;
> RSEG CODE
>
> ;-----------------------
>
> PWRON: DINT ;DISABLE GENERAL INTERRUPTS
>
> MOV.W #WDTPW+WDTHOLD,&WDTCTL ; DISABLE WATCHDOG TIMER,
> CLR.B &P1IE ;DISABLE P1 INTERRUPTS
> MOV.W #SFE(CSTACK),SP ;START OF
> STACK
>
> PWR0A: BIT.B #LFOF,&FLL_CTL0 ;LOOP WHILE LF FAULT
> JNZ PWR0A
>
> BIT.B #DCOF,&FLL_CTL0 ;LOOP WHILE
> DCO FAULT
> JNZ PWR0A
>
> ;---------------------
>
> As you can see, the chip will start the CODE at PWRON as the battery
> inserted, the comments for each line of code is good enough for
> explanation, isn't it? SO the chip will stablize after 2 loops to
> check for LF fault and DCO fault. After that you can initialize all
> the ports, clear all the RAM memory, ... Do wahtever you have to do to
> initially, setup the program, and finally, branch to ENDAY: put the
> chip to sleep mode for storage, save the power.
>
> Suppose I have only 1 button for the device port 1.0. I need to enable
> the button interrupt for port 1.0
>
> ;-------------- code for ENDAY --------------------------
>
> ENDAY: CLR.B &P1IFG ; CLR POSSIBLE
> INTERRUPT FLAGS
> BIC.B #01H,&P1DIR ; MAKE P1.0 INPUT
> MOV.B
> #01H,&P1IES ;
> INTERUPT EDGE...P1.0 HI TO LO
> MOV.B #01H,&P1IE ; ENBL P1.0 INTERRUPT
> MOV.W #SFE(CSTACK),SP ;
> START OF STACK (CLEAR)
> MOV.W #SCG1+SCG0+CPUOFF+GIE,SR ;
> LPMODE3..ENABLE GENERAL INTERRUPT and
>
> NOP ; WHILE ASLEEP
> ;
> A SWITCH ACTIVATION WILL VECTOR TO
> ; BINTR AND WILL RETI AFTER ALTERING THE
> ;
> SR ON THE STACK, IF THE CONTACT IS VALID.
> ;
> THE PROGRAM WILL CONTINUE FROM HERE WITH A
> ; BRANCH TO `NEWDAY', WHICH WILL CAUSE THE
> ;
> UNIT TO POWERUP. IF AN INTERMITTENT
> ;
> CLOSURE, THE UNIT WILL SHUTDOWN IN LOW
> ;
> POWER MODE AGAIN.
>
> BIC #TBIE,&TB0CTL ;
> DISABLE TIMER B OVERFLOW INTERRUPT
> BRA #NEWDAY ;. START THE PROGRAM WHEN THE
> BUTTON INTERRUPT
>
> ; TO TURN THE DEVICE ON.
>
> ;--------------
>
> Now the chip is sleep in LPM mode 3 to save power. When the button is
> pressed:
>
> ;---------------- CODE TO CHECK FOR BUTTON INTERRUPT
> ----
>
> BINTR: CLR.B &P1IFG ;CLEAR PORT 1 INTERRUPT FLAGS
> BIS.W #GIE,SR ;RE-ENABLE GENERAL INTERRUPT
>
> MOV.W #0400H,TEMP ;DELAY FOR 5 MS
>
> BINT00: DEC.W TEMP ;16 BIT.W REGISTER..DECREMENT TILL 0000H
> JNZ BINT00
>
> MOV.B
> &P1IN,BTNSAV ;CHECK
> FOR SWITCH INTERRUPT (XITION TO LO)
> INV.B BTNSAV ;CHANGE TO POSITIVE LOGIC
> AND.B #01H,BTNSAV ;MASK FOR BIT 0
> JZ
> BINT01 ;FALSE
> INTERRUPT
> TST.B OPMODE ;IF OPMODE = SLEEPMODE=0 THEN SET SR ON
> ; THE STACK TO POWERUP ON RTI
> JNZ BINT02 ; NOT SLEEP
> ;ASLEEP
> BIC #TBIE,&TB0CTL ;DISABLE TIMER_B
> OVERFLOW INTERRUPTS
> CLR
> 0(SP) ;SET
> CPU ACTIVE ON RTI
>
> BINT01: RETI
>
> BINT02: MOV.B BTNSAV,BTNMEM ;SAVE FOR BUTTON CHECK ROUTINE
> RETI ; ..
>
> ;--------------- END OF BUTTON INTERRUPT
> ---------------------------------
>
> As you can see the code to detect the bouncing button for 5 ms. if the
> button is pressed < 5 ms then it will be ignored. An valid button
> pressed will return and wake the CPU up and start the NEWDAY routine
> (in DOZE). It will start your program (turn on your device). If it is
> not from the sleep mode (OPMODE = 0 operation mode) then it will be
> OPMODE 1, 2,3, 4 whatever you named it then you know what to do with
> the button pressed. Example, OPMODE 1 is in SET HOUR, the button will
> increase the HOURS, if the OPMODE 2 is in SET MINUTE, the button
> pressed will increase MINUTES. And as you know , with port 1 we can
> have total 8 buttons to do so many thing.
>
> Now for the DOZE, this is the place for the CPU to rest (LPM3) to save
> power:
>
> ;----------- code for the DOZE
> --------------
>
> DOZE: MOV #SFE(CSTACK),SP ;START OF STACK (CLR
> POSSIBLE PENDING RTI)
>
> BIC.B #01H,&P1DIR ;
> MAKE P1.0 INPUTS
> MOV.B #01H,&P1IES ;INTERUPT EDGE...HI TO LO ON P1.0
>
> MOV.B #01H,&P1IE ;ENABLE P1.0 INTERRUPTS
>
> MOV #0120H,&TBCTL ;RECONDITION TIMERB 32KHZ,
> CONT UP..CAUTIONARY
> ADD #1000H,&TBCCR0 ;ADD
> 125MS TO COMPARE B0 REG (4096/32768)
> MOV #0010H,&TBCCTL0
> ;ENABLE TIMERB COMPARE0 INTERRUPT
>
> ;-----------------------------------
>
> DOZ00: MOV #00D8H,SR ;LPMODE3..ENABLE GENERAL INTERRUPT
> NOP ;BTTN PRESSES WHILE IN DOZE WILL VECTOR TO
> ; BINTR AND ReTI BACK TO HERE TO THE LO PWR mode
> ;125MS
> COMPARE WILL VECTOR TO MAIN.
>
> ;MAIN WILL TERMINATE WITH A BRANCH BACK TO DOZE.
> ; IN ORDER TO SET UP THE SWITCH INTERRUPTS
> ; AND ADD 125MS TO THE NEXT COMPARE INTERRUPT.
>
> JMP DOZ00 ;PRECAUTION
>
> ;-------------- end code for doze
> -------
>
> As you see up to now, the program (the CPU) resets at PWRON, loop
> until the CPU is stable then go to ENDAY to sleep to save power. If a
> button is pressed during sleep mode, the RETI will trigger the SR to
> turn the CPU ON, the program will go to NEWDAY:
>
> ;----------- code for the NEWDAY ----------------------------
>
> NEWDAY:
>
> .......... DO whatever you have to do to display the device or do
> something then branch to DOZE to let the CPU sleep. During the CPU
> sleep in DOZE, the timer B compare 0 with 125 ms (1000H will be 125
> ms, 2000H will be 250 ms, and so on ... depends on how many ms seconds
> you want the button to react.)
>
> BR #DOZE
>
> ;--------- end code for NEWDAY ----------------------------
>
> Now the code for the MAIN: the MAIN will be running every 125 ms
> during awake mode and you can do different task in the MAIN depends on
> what you want to do:
>
> ;---------------- Code for MAIN running every 125 ms during awake
> -------------
>
> MAIN: MOV.W #WDTPW+WDTHOLD,&WDTCTL ; DISABLE WATCHDOG TIMER,
>
> INC.B EIGHTHS ;INCREMENT 1/8 SEC CTR
>
> AND.B
> #07H,EIGHTHS ;MASK OFF UNUSED BITS
>
> BIS.W #GIE,SR ;RE-ENABLE GEN
> INTERRUPTS FOR BTTN PRESSES
>
> MOV.B EIGHTHS,R5
>
> RLA R5
>
> BR MAIN00(R5)
>
> MAIN00: DW JOB0
>
> DW JOB1
>
> DW JOB2
>
> DW JOB3
>
> DW JOB4
>
> DW JOB5
>
> DW JOB6
>
> DW JOB7
>
> JOB0: Do something then ..
>
> BR #DOZE
>
> JOB1: Do something then ..
>
> BR #DOZE
>
> JOB2: Do something then ..
>
> BR #DOZE
>
> JOB3: Do something then ..
>
> BR #DOZE
>
> JOB4: Do something then ..
>
> BR #DOZE
>
> JOB5: Do something then ..
>
> BR #DOZE
>
> JOB6: Do something then ..
>
> BR #DOZE
>
> JOB7: Do something then ..
>
> BR #DOZE
>
> ;-------------- end code for MAIN -------------------
>
> This is a complete frame programming for a MSP430F449 chip from start
> power up, detect LF and DCO fault to make sure 100% the CPU is stable
> and back to sleep, wait for a button pressed to wake up and start a
> NEWDAY then go back to sleep. During AWAKE mode, every 125 ms, the CPU
> will wake up to check for any task that it has to do, then back to
> sleep until the program go back to ENDAY (like 2 hours without a
> button pressed, the program will go back to sleep mode.
>
> Finally about TRAPE0, TRAPE2, ... I name it and put a code in it
> routine to see if any interrupt occur during my program running so I
> can trap that interrupt back to DOZE so I don't have any unwanted
> interrupt that will make my program go haywired.
>
> TRAPE0: MOV.B #0E0H,ERROR
>
> ... display the ERROR so I know what going all
>
> .. delay the dislpay for 10 seconds ....
>
> BR #DOZE
>
> it is also a good programming when we put all the initialization in
> one routine that I called PREP (prepare):
>
> ;------------ code to put all initialization in one routine
> ----------------
>
> PREP: MOV.W #WDTPW+WDTHOLD,&WDTCTL ; DISABLE WATCHDOG TIMER,
>
> MOV.B #032H,&SCFQCTL ;DCOCLK = 50*30.518 > 1.52mhz, MODULATION ON
> CLR.B &SCFI0 ;DCO RANGE = .65/6mhz
> CLR.B &SCFI1 ; ..
>
> MOV.B #0B0H,FLL_CTL0 ;SELECT.. DCO, LO FREQ,
> 10pf LOAD
> MOV.B #020H,FLL_CTL1 ;XT2OFF, ACLK/1
>
> CLR.B &IE1 ;CAUTIONARY DISABLE MODULE
> INTERRUPT REGISTERS
> CLR.B &IE2
>
> CLR.B &IFG1 ;CAUTIONARY CLEAR MODULE
> INTERRUPT FLAGS
> CLR.B &IFG2 ; ..
> CLR.B &ME1 ;CAUTIONARY MODULE
> DISABLES
> CLR.B &ME2 ; ..
>
> ;-------------- TIMER A SETUP
> ----------------
>
> ; SET UP TIMER A FOR SOME USE, LIKE A PIEZO TO MAKE A SOUND OR SOMETHING
>
> ;-------------------
> MOV #0104H,&TACTL ;TIMERA ACLK, STOPPED, CLEARED
> MOV #0008H,&CCR0 ;COMPARE REG0 TO 7(DELAYED), TACL0 4096hz
> MOV #0004H,&CCR2 ;COMPARE REG1 TO 4, TACL1 (50%DC)
> MOV #00E0H,&CCTL2 ;PREPARE OUTP UNIT1 FOR RESET/SET
> CLR &CCTL0 ;CLR CAP/COMP CONTROL REG0
> BIC #0010H,&TACTL ;STOP 4KHZ PIEZO DRIVE
>
> ;------------ PORT1
> ----------------
> ;P1.0 button
>
> ;P1.1 to P1.7 N/U
>
> CLR.B &P1IES ;INTERUPT EDGE...LOW TO HI
> CLR.B &P1OUT ;SET PORT1 OUTPUT LATCHES LOW
> MOV.B #0FEH,&P1DIR ;ALL OUTPUT EXCEPT P1.0 is INPUT
> CLR.B
> &P1IE ;DISABLE
> P1 INTERRUPTS
> CLR.B &P1IFG ;RESET POSSIBLE INTERRUPT FLAG
> CLR.B &P1SEL ;Make port 1 to be all IO line
> ;PORT2
> ;PORT3
> ;PORT4
> ;PORT5
> ;PORT6
>
> CLR &ADC12CTL0 ;CLEAR A/D CONTROL REGISTERS
> CLR &ADC12CTL1 ; ..
> CLR &ADC12IFG ;CLEAR INTERRUPT ENABLE
> FLAG REGS
> CLR &ADC12IE ; ..
>
> RET
>
> ;---------- end code for PREP -------
>
> You can put the PREP right after the CPU is stable then clear RAM,
> read EEPROM ... before put the CPU into sleep mode.
>
> I hope to help you guy with some information that I worked in the
> field of assembler for the MSP430.
>
> Anthony Ha
>
> /-------Original Message-------/
>
> */From:/*Peter Grey */Date:/*10/22/2013 6:32:41 PM
>
> */To:/*m... */Subject:/*RE: [msp430] Problems with MSP430F2132
>
> Hi Al,
>
> Thanks for the detailed reply. I must admit I have not used NMI since
> I was using the PDP mini's, and that is a while ago! I shall take a
> look and may have a few questions
>
> Thanks
>
> Peter
>
> *From:*m...
> [mailto:m...] *On Behalf Of *Onestone
> *Sent:* Tuesday, 22 October 2013 4:26 PM
> *To:* m...
> *Subject:* Re: [msp430] Problems with MSP430F2132
>
> This is probably just the usual issue with debounce of a switch
> (attaching the battery is a switch), and the system getting caught
> out. Typically you would have an INIT process shortly after start up
> with a clock stabilisation loop or similar. I don't know how you
> handle NMI's but typically if your NMI handling is too simplistic you
> will get a clock error, jump to the NMI which might then get stuck in
> a loop or stall, or simply corrupt the PC. If you have a LED try
> having the LED flash briefly during INIT, ie on very fast then off
> once stable. Then have it turned fully on in the NMNI and point the
> NMI back to itself. That will tell you if this is the issue.
>
> Al
>
> On 22/10/2013 4:50 PM, Peter Grey wrote:
>
> I have been using these chips for a while. My devices have a battery
> connected to them and, in some cases a battery charger. I find that
> when I first connect a battery or take it off a charger it will not
> work. I need to push a reset button. I have tried a reset chip and it
> makes no difference. I can tell a customer to always press reset after
> the above events but I want to find out what is going on and fix it.
> Has anyone experienced any such behaviour.
>
> TIA
>
> Peter
>
>
>
It is also unnecessary to first clear DCOCTL before setting it to the
stored calibratiob value, however that is trivia.

Al

On 29/10/2013 1:46 PM, Peter Grey wrote:
> Hi Anthony
>
> I have solved my problem. In my program I setup the stack at RESET and
> then call a subroutine to set up the ports and the clock.
>
> Reset
>
> mov.w #3FFh,SP ; Initialize stackpointer
>
> call #Setup
>
> In Setup I then setup the clock
>
> clr.b &DCOCTL
>
> mov.b &CALBC1_16MHZ,&BCSCTL1 ; Set DCO to 8MHz
>
> mov.b &CALDCO_16MHZ,&DCOCTL
>
> I then set up the port direction and initial states
>
> SetupP1 mov.b #0f3h,&P1DIR ; 11110011
>
> clr.b &P1OUT ; SET LOW
>
> bic.b #EN_BUZZER,&P1OUT ;turn off beeper
>
> bic.b #EN_30V,&P1OUT
>
> SetupP2 mov.b #0E8h,&P2DIR ;11101000,
>
> mov.b #07h,&P2SEL2 ;A0-A2
>
> clr.b &P2OUT
>
> bis.b #LIS_CS,&P2OUT
>
> clr.b MDA_COUNTER
>
> clr.b DURESS_COUNTER
>
> SetupP3 mov.b #0B0h,&P3DIR ;10110000
>
> clr.b &P3OUT
>
> bis.b #TR_SDI,&P3OUT
>
> bis.b #nSS_CONF+nSS_DATA,&P3OUT ;set both high
>
> Finally I do a ret
>
> My fix was to run this subroutine a second time and all my problems
> disappeared??
>
> Thanks
>
> Peter
>
> *From:*m... [mailto:m...] *On
> Behalf Of *a...@gmail.com
> *Sent:* Saturday, 26 October 2013 12:57 PM
> *To:* m...
> *Subject:* RE: [msp430] Problems with MSP430F2132
> Peter,
>
> I have just sent you an email that I explained something, but I don't
> know that is what you want. If you think part of your code has
> problem, you can zip that part and send it to me as an attachment file
> (txt file). I can read and have my opinion for you.
>
> Anthony Ha
>
> /-------Original Message-------/
>
> */From:/*Peter Grey */Date:/*10/25/2013 7:48:57 PM
>
> */To:/*m... */Subject:/*RE: [msp430] Problems with MSP430F2132
>
> Hi Anthony
>
> I can see what you are doing at RESET. It is similar to mine but I
> have a MSP430F2132 and am using DCO at 1MHz. In the NMI interrupt
> (DOZE), I cannot see how you ever exit this. There is no RETI? What is
> the routine supposed to do apart from re-initialising the stack and
> setting up the registers again? I turn on a LED in the NMI interrupt
> routine but I never see this happen. I am beginning to think that this
> may not be a NMI problem, but something silly I am doing.
>
> Thanks
>
> Peter
>
> *From:*m...
> [mailto:m...] *On Behalf Of *a...@gmail.com
>
> *Sent:* Wednesday, 23 October 2013 11:40 AM
> *To:* m...
> *Subject:* RE: [msp430] Problems with MSP430F2132
>
> Here is my assembler layout for a typical MSP430F449 chip:
>
> The first section of the program is the declanation of Interrupt
> Vector (IV). Depending on what chip, you will have 2, 4, 8 IV. The
> 449 chip has 2 IV and the address from FFE0 to FFFE (the last two by
> is POWER ON RESET) that I named PWRON and I called DOZE (address FFFC
> for the Oscillator, NMI reset). I called MAIN address FFFA for the
> timer_B compare 0: with Timer B we will have 7 of them from
> 0,1,2,3,4,5,6). I use here for example only 1 compare interrupt Timer
> B_0 . And I named BINTR for Port 1 address FFE8.
>
> ;********************** INTERRUPT VECTORS
> ***********************************
>
> RSEG INTVEC ;
>
> DW TRAPE0 ;$FFE0.........................N/U
> DW TRAPE2 ;$FFE2.........................N/U
> DW TRAPE4 ;$FFE4.........................N/U
> DW TRAPE6 ;$FFE6.........................N/U
> DW BINTR ;$FFE8....I/O PORT P1
> DW TRAPEA ;$FFEA.........................N/U
> DW TRAPEC ;$FFEC.........................N/U
> DW TRAPEE ;$FFEE.........................N/U
> DW TRAPF0 ;$FFF0....UART0 XMIT
> DW TRAPF2 ;$FFF2....UART0 RCVE
> DW TRAPF4 ;$FFF4....WATCHDOG TIMER
> DW TRAPF6 ;$FFF6.........................N/U
> DW TRAPF8 ;$FFF8....TIMER_B (CAP/COMP 1/6, OVRFLOW)
> DW MAIN ;$FFFA....TIMER_B (COMPARE0)
> DW DOZE ;$FFFC....OSC FAULT, NMI
> DW PWRON ;$FFFE....POWER UP RESET
> ;********************** INITIAL RESET
> ***************************************
> ;
> RSEG CODE
>
> ;-----------------------
>
> PWRON: DINT ;DISABLE GENERAL INTERRUPTS
>
> MOV.W #WDTPW+WDTHOLD,&WDTCTL ; DISABLE WATCHDOG TIMER,
> CLR.B &P1IE ;DISABLE P1 INTERRUPTS
> MOV.W #SFE(CSTACK),SP ;START OF
> STACK
>
> PWR0A: BIT.B #LFOF,&FLL_CTL0 ;LOOP WHILE LF FAULT
> JNZ PWR0A
>
> BIT.B #DCOF,&FLL_CTL0 ;LOOP WHILE
> DCO FAULT
> JNZ PWR0A
>
> ;---------------------
>
> As you can see, the chip will start the CODE at PWRON as the battery
> inserted, the comments for each line of code is good enough for
> explanation, isn't it? SO the chip will stablize after 2 loops to
> check for LF fault and DCO fault. After that you can initialize all
> the ports, clear all the RAM memory, ... Do wahtever you have to do to
> initially, setup the program, and finally, branch to ENDAY: put the
> chip to sleep mode for storage, save the power.
>
> Suppose I have only 1 button for the device port 1.0. I need to enable
> the button interrupt for port 1.0
>
> ;-------------- code for ENDAY --------------------------
>
> ENDAY: CLR.B &P1IFG ; CLR POSSIBLE
> INTERRUPT FLAGS
> BIC.B #01H,&P1DIR ; MAKE P1.0 INPUT
> MOV.B
> #01H,&P1IES ;
> INTERUPT EDGE...P1.0 HI TO LO
> MOV.B #01H,&P1IE ; ENBL P1.0 INTERRUPT
> MOV.W #SFE(CSTACK),SP ;
> START OF STACK (CLEAR)
> MOV.W #SCG1+SCG0+CPUOFF+GIE,SR ;
> LPMODE3..ENABLE GENERAL INTERRUPT and
>
> NOP ; WHILE ASLEEP
> ;
> A SWITCH ACTIVATION WILL VECTOR TO
> ; BINTR AND WILL RETI AFTER ALTERING THE
> ;
> SR ON THE STACK, IF THE CONTACT IS VALID.
> ;
> THE PROGRAM WILL CONTINUE FROM HERE WITH A
> ; BRANCH TO `NEWDAY', WHICH WILL CAUSE THE
> ;
> UNIT TO POWERUP. IF AN INTERMITTENT
> ;
> CLOSURE, THE UNIT WILL SHUTDOWN IN LOW
> ;
> POWER MODE AGAIN.
>
> BIC #TBIE,&TB0CTL ;
> DISABLE TIMER B OVERFLOW INTERRUPT
> BRA #NEWDAY ;. START THE PROGRAM WHEN THE
> BUTTON INTERRUPT
>
> ; TO TURN THE DEVICE ON.
>
> ;--------------
>
> Now the chip is sleep in LPM mode 3 to save power. When the button is
> pressed:
>
> ;---------------- CODE TO CHECK FOR BUTTON INTERRUPT
> ----
>
> BINTR: CLR.B &P1IFG ;CLEAR PORT 1 INTERRUPT FLAGS
> BIS.W #GIE,SR ;RE-ENABLE GENERAL INTERRUPT
>
> MOV.W #0400H,TEMP ;DELAY FOR 5 MS
>
> BINT00: DEC.W TEMP ;16 BIT.W REGISTER..DECREMENT TILL 0000H
> JNZ BINT00
>
> MOV.B
> &P1IN,BTNSAV ;CHECK
> FOR SWITCH INTERRUPT (XITION TO LO)
> INV.B BTNSAV ;CHANGE TO POSITIVE LOGIC
> AND.B #01H,BTNSAV ;MASK FOR BIT 0
> JZ
> BINT01 ;FALSE
> INTERRUPT
> TST.B OPMODE ;IF OPMODE = SLEEPMODE=0 THEN SET SR ON
> ; THE STACK TO POWERUP ON RTI
> JNZ BINT02 ; NOT SLEEP
> ;ASLEEP
> BIC #TBIE,&TB0CTL ;DISABLE TIMER_B
> OVERFLOW INTERRUPTS
> CLR
> 0(SP) ;SET
> CPU ACTIVE ON RTI
>
> BINT01: RETI
>
> BINT02: MOV.B BTNSAV,BTNMEM ;SAVE FOR BUTTON CHECK ROUTINE
> RETI ; ..
>
> ;--------------- END OF BUTTON INTERRUPT
> ---------------------------------
>
> As you can see the code to detect the bouncing button for 5 ms. if the
> button is pressed < 5 ms then it will be ignored. An valid button
> pressed will return and wake the CPU up and start the NEWDAY routine
> (in DOZE). It will start your program (turn on your device). If it is
> not from the sleep mode (OPMODE = 0 operation mode) then it will be
> OPMODE 1, 2,3, 4 whatever you named it then you know what to do with
> the button pressed. Example, OPMODE 1 is in SET HOUR, the button will
> increase the HOURS, if the OPMODE 2 is in SET MINUTE, the button
> pressed will increase MINUTES. And as you know , with port 1 we can
> have total 8 buttons to do so many thing.
>
> Now for the DOZE, this is the place for the CPU to rest (LPM3) to save
> power:
>
> ;----------- code for the DOZE
> --------------
>
> DOZE: MOV #SFE(CSTACK),SP ;START OF STACK (CLR
> POSSIBLE PENDING RTI)
>
> BIC.B #01H,&P1DIR ;
> MAKE P1.0 INPUTS
> MOV.B #01H,&P1IES ;INTERUPT EDGE...HI TO LO ON P1.0
>
> MOV.B #01H,&P1IE ;ENABLE P1.0 INTERRUPTS
>
> MOV #0120H,&TBCTL ;RECONDITION TIMERB 32KHZ,
> CONT UP..CAUTIONARY
> ADD #1000H,&TBCCR0 ;ADD
> 125MS TO COMPARE B0 REG (4096/32768)
> MOV #0010H,&TBCCTL0
> ;ENABLE TIMERB COMPARE0 INTERRUPT
>
> ;-----------------------------------
>
> DOZ00: MOV #00D8H,SR ;LPMODE3..ENABLE GENERAL INTERRUPT
> NOP ;BTTN PRESSES WHILE IN DOZE WILL VECTOR TO
> ; BINTR AND ReTI BACK TO HERE TO THE LO PWR mode
> ;125MS
> COMPARE WILL VECTOR TO MAIN.
>
> ;MAIN WILL TERMINATE WITH A BRANCH BACK TO DOZE.
> ; IN ORDER TO SET UP THE SWITCH INTERRUPTS
> ; AND ADD 125MS TO THE NEXT COMPARE INTERRUPT.
>
> JMP DOZ00 ;PRECAUTION
>
> ;-------------- end code for doze
> -------
>
> As you see up to now, the program (the CPU) resets at PWRON, loop
> until the CPU is stable then go to ENDAY to sleep to save power. If a
> button is pressed during sleep mode, the RETI will trigger the SR to
> turn the CPU ON, the program will go to NEWDAY:
>
> ;----------- code for the NEWDAY ----------------------------
>
> NEWDAY:
>
> .......... DO whatever you have to do to display the device or do
> something then branch to DOZE to let the CPU sleep. During the CPU
> sleep in DOZE, the timer B compare 0 with 125 ms (1000H will be 125
> ms, 2000H will be 250 ms, and so on ... depends on how many ms seconds
> you want the button to react.)
>
> BR #DOZE
>
> ;--------- end code for NEWDAY ----------------------------
>
> Now the code for the MAIN: the MAIN will be running every 125 ms
> during awake mode and you can do different task in the MAIN depends on
> what you want to do:
>
> ;---------------- Code for MAIN running every 125 ms during awake
> -------------
>
> MAIN: MOV.W #WDTPW+WDTHOLD,&WDTCTL ; DISABLE WATCHDOG TIMER,
>
> INC.B EIGHTHS ;INCREMENT 1/8 SEC CTR
>
> AND.B
> #07H,EIGHTHS ;MASK OFF UNUSED BITS
>
> BIS.W #GIE,SR ;RE-ENABLE GEN
> INTERRUPTS FOR BTTN PRESSES
>
> MOV.B EIGHTHS,R5
>
> RLA R5
>
> BR MAIN00(R5)
>
> MAIN00: DW JOB0
>
> DW JOB1
>
> DW JOB2
>
> DW JOB3
>
> DW JOB4
>
> DW JOB5
>
> DW JOB6
>
> DW JOB7
>
> JOB0: Do something then ..
>
> BR #DOZE
>
> JOB1: Do something then ..
>
> BR #DOZE
>
> JOB2: Do something then ..
>
> BR #DOZE
>
> JOB3: Do something then ..
>
> BR #DOZE
>
> JOB4: Do something then ..
>
> BR #DOZE
>
> JOB5: Do something then ..
>
> BR #DOZE
>
> JOB6: Do something then ..
>
> BR #DOZE
>
> JOB7: Do something then ..
>
> BR #DOZE
>
> ;-------------- end code for MAIN -------------------
>
> This is a complete frame programming for a MSP430F449 chip from start
> power up, detect LF and DCO fault to make sure 100% the CPU is stable
> and back to sleep, wait for a button pressed to wake up and start a
> NEWDAY then go back to sleep. During AWAKE mode, every 125 ms, the CPU
> will wake up to check for any task that it has to do, then back to
> sleep until the program go back to ENDAY (like 2 hours without a
> button pressed, the program will go back to sleep mode.
>
> Finally about TRAPE0, TRAPE2, ... I name it and put a code in it
> routine to see if any interrupt occur during my program running so I
> can trap that interrupt back to DOZE so I don't have any unwanted
> interrupt that will make my program go haywired.
>
> TRAPE0: MOV.B #0E0H,ERROR
>
> ... display the ERROR so I know what going all
>
> .. delay the dislpay for 10 seconds ....
>
> BR #DOZE
>
> it is also a good programming when we put all the initialization in
> one routine that I called PREP (prepare):
>
> ;------------ code to put all initialization in one routine
> ----------------
>
> PREP: MOV.W #WDTPW+WDTHOLD,&WDTCTL ; DISABLE WATCHDOG TIMER,
>
> MOV.B #032H,&SCFQCTL ;DCOCLK = 50*30.518 > 1.52mhz, MODULATION ON
> CLR.B &SCFI0 ;DCO RANGE = .65/6mhz
> CLR.B &SCFI1 ; ..
>
> MOV.B #0B0H,FLL_CTL0 ;SELECT.. DCO, LO FREQ,
> 10pf LOAD
> MOV.B #020H,FLL_CTL1 ;XT2OFF, ACLK/1
>
> CLR.B &IE1 ;CAUTIONARY DISABLE MODULE
> INTERRUPT REGISTERS
> CLR.B &IE2
>
> CLR.B &IFG1 ;CAUTIONARY CLEAR MODULE
> INTERRUPT FLAGS
> CLR.B &IFG2 ; ..
> CLR.B &ME1 ;CAUTIONARY MODULE
> DISABLES
> CLR.B &ME2 ; ..
>
> ;-------------- TIMER A SETUP
> ----------------
>
> ; SET UP TIMER A FOR SOME USE, LIKE A PIEZO TO MAKE A SOUND OR SOMETHING
>
> ;-------------------
> MOV #0104H,&TACTL ;TIMERA ACLK, STOPPED, CLEARED
> MOV #0008H,&CCR0 ;COMPARE REG0 TO 7(DELAYED), TACL0 4096hz
> MOV #0004H,&CCR2 ;COMPARE REG1 TO 4, TACL1 (50%DC)
> MOV #00E0H,&CCTL2 ;PREPARE OUTP UNIT1 FOR RESET/SET
> CLR &CCTL0 ;CLR CAP/COMP CONTROL REG0
> BIC #0010H,&TACTL ;STOP 4KHZ PIEZO DRIVE
>
> ;------------ PORT1
> ----------------
> ;P1.0 button
>
> ;P1.1 to P1.7 N/U
>
> CLR.B &P1IES ;INTERUPT EDGE...LOW TO HI
> CLR.B &P1OUT ;SET PORT1 OUTPUT LATCHES LOW
> MOV.B #0FEH,&P1DIR ;ALL OUTPUT EXCEPT P1.0 is INPUT
> CLR.B
> &P1IE ;DISABLE
> P1 INTERRUPTS
> CLR.B &P1IFG ;RESET POSSIBLE INTERRUPT FLAG
> CLR.B &P1SEL ;Make port 1 to be all IO line
> ;PORT2
> ;PORT3
> ;PORT4
> ;PORT5
> ;PORT6
>
> CLR &ADC12CTL0 ;CLEAR A/D CONTROL REGISTERS
> CLR &ADC12CTL1 ; ..
> CLR &ADC12IFG ;CLEAR INTERRUPT ENABLE
> FLAG REGS
> CLR &ADC12IE ; ..
>
> RET
>
> ;---------- end code for PREP -------
>
> You can put the PREP right after the CPU is stable then clear RAM,
> read EEPROM ... before put the CPU into sleep mode.
>
> I hope to help you guy with some information that I worked in the
> field of assembler for the MSP430.
>
> Anthony Ha
>
> /-------Original Message-------/
>
> */From:/*Peter Grey */Date:/*10/22/2013 6:32:41 PM
>
> */To:/*m... */Subject:/*RE: [msp430] Problems with MSP430F2132
>
> Hi Al,
>
> Thanks for the detailed reply. I must admit I have not used NMI since
> I was using the PDP mini's, and that is a while ago! I shall take a
> look and may have a few questions
>
> Thanks
>
> Peter
>
> *From:*m...
> [mailto:m...] *On Behalf Of *Onestone
> *Sent:* Tuesday, 22 October 2013 4:26 PM
> *To:* m...
> *Subject:* Re: [msp430] Problems with MSP430F2132
>
> This is probably just the usual issue with debounce of a switch
> (attaching the battery is a switch), and the system getting caught
> out. Typically you would have an INIT process shortly after start up
> with a clock stabilisation loop or similar. I don't know how you
> handle NMI's but typically if your NMI handling is too simplistic you
> will get a clock error, jump to the NMI which might then get stuck in
> a loop or stall, or simply corrupt the PC. If you have a LED try
> having the LED flash briefly during INIT, ie on very fast then off
> once stable. Then have it turned fully on in the NMNI and point the
> NMI back to itself. That will tell you if this is the issue.
>
> Al
>
> On 22/10/2013 4:50 PM, Peter Grey wrote:
>
> I have been using these chips for a while. My devices have a battery
> connected to them and, in some cases a battery charger. I find that
> when I first connect a battery or take it off a charger it will not
> work. I need to push a reset button. I have tried a reset chip and it
> makes no difference. I can tell a customer to always press reset after
> the above events but I want to find out what is going on and fix it.
> Has anyone experienced any such behaviour.
>
> TIA
>
> Peter
>
>
>
Hi Al

Thank you for that. You would be surprised at how many times I have done
this!! Can you explain why I get over the problem by calling this subroutine
twice?

Cheers

Peter

From: m... [mailto:m...] On Behalf Of
Onestone
Sent: Tuesday, 29 October 2013 12:45 PM
To: m...
Subject: Re: [msp430] Problems with MSP430F2132

You're setting TOS (SP) to an odd number TOS should be end of RAM + 1, that
is your bug here. so set it to 0X0400

Al

On 29/10/2013 1:46 PM, Peter Grey wrote:

Hi Anthony

I have solved my problem. In my program I setup the stack at RESET and then
call a subroutine to set up the ports and the clock.

Reset

mov.w #3FFh,SP ; Initialize
stackpointer

call #Setup

In Setup I then setup the clock

clr.b &DCOCTL

mov.b &CALBC1_16MHZ,&BCSCTL1 ; Set DCO to 8MHz

mov.b &CALDCO_16MHZ,&DCOCTL

I then set up the port direction and initial states

SetupP1 mov.b #0f3h,&P1DIR ;
11110011

clr.b &P1OUT ; SET LOW

bic.b #EN_BUZZER,&P1OUT ;turn off beeper

bic.b #EN_30V,&P1OUT

SetupP2 mov.b #0E8h,&P2DIR ;11101000,

mov.b #07h,&P2SEL2 ;A0-A2

clr.b &P2OUT

bis.b #LIS_CS,&P2OUT

clr.b MDA_COUNTER

clr.b DURESS_COUNTER

SetupP3 mov.b #0B0h,&P3DIR ;10110000

clr.b &P3OUT

bis.b #TR_SDI,&P3OUT

bis.b #nSS_CONF+nSS_DATA,&P3OUT ;set both high

Finally I do a ret

My fix was to run this subroutine a second time and all my problems
disappeared??

Thanks

Peter

From: m... [mailto:m...] On Behalf Of
a...@gmail.com
Sent: Saturday, 26 October 2013 12:57 PM
To: m...
Subject: RE: [msp430] Problems with MSP430F2132

Peter,

I have just sent you an email that I explained something, but I don't know
that is what you want. If you think part of your code has problem, you can
zip that part and send it to me as an attachment file (txt file). I can read
and have my opinion for you.

Anthony Ha

-------Original Message-------

From: Peter Grey

Date: 10/25/2013 7:48:57 PM

To: m...

Subject: RE: [msp430] Problems with MSP430F2132

Hi Anthony

I can see what you are doing at RESET. It is similar to mine but I have a
MSP430F2132 and am using DCO at 1MHz. In the NMI interrupt (DOZE), I cannot
see how you ever exit this. There is no RETI? What is the routine supposed
to do apart from re-initialising the stack and setting up the registers
again? I turn on a LED in the NMI interrupt routine but I never see this
happen. I am beginning to think that this may not be a NMI problem, but
something silly I am doing.

Thanks

Peter

From: m... [mailto:m...] On Behalf Of
a...@gmail.com
Sent: Wednesday, 23 October 2013 11:40 AM
To: m...
Subject: RE: [msp430] Problems with MSP430F2132

Here is my assembler layout for a typical MSP430F449 chip:

The first section of the program is the declanation of Interrupt Vector
(IV). Depending on what chip, you will have 2, 4, 8 IV. The 449 chip has 2
IV and the address from FFE0 to FFFE (the last two by is POWER ON RESET)
that I named PWRON and I called DOZE (address FFFC for the Oscillator, NMI
reset). I called MAIN address FFFA for the timer_B compare 0: with Timer B
we will have 7 of them from 0,1,2,3,4,5,6). I use here for example only 1
compare interrupt Timer B_0 . And I named BINTR for Port 1 address FFE8.

;********************** INTERRUPT VECTORS
***********************************

RSEG INTVEC ;

DW TRAPE0
;$FFE0.........................N/U
DW TRAPE2
;$FFE2.........................N/U
DW TRAPE4
;$FFE4.........................N/U
DW TRAPE6
;$FFE6.........................N/U
DW BINTR ;$FFE8....I/O PORT P1
DW TRAPEA
;$FFEA.........................N/U
DW TRAPEC
;$FFEC.........................N/U
DW TRAPEE
;$FFEE.........................N/U
DW TRAPF0 ;$FFF0....UART0 XMIT
DW TRAPF2 ;$FFF2....UART0 RCVE
DW TRAPF4 ;$FFF4....WATCHDOG TIMER
DW TRAPF6
;$FFF6.........................N/U
DW TRAPF8 ;$FFF8....TIMER_B (CAP/COMP
1/6, OVRFLOW)
DW MAIN ;$FFFA....TIMER_B
(COMPARE0)
DW DOZE ;$FFFC....OSC FAULT, NMI
DW PWRON ;$FFFE....POWER UP RESET

;********************** INITIAL RESET
***************************************
;
RSEG CODE

;---
--------------------

PWRON: DINT
;DISABLE GENERAL INTERRUPTS

MOV.W #WDTPW+WDTHOLD,&WDTCTL ; DISABLE
WATCHDOG TIMER,
CLR.B &P1IE
;DISABLE P1 INTERRUPTS
MOV.W #SFE(CSTACK),SP
;START OF STACK

PWR0A: BIT.B #LFOF,&FLL_CTL0
;LOOP WHILE LF FAULT
JNZ PWR0A

BIT.B #DCOF,&FLL_CTL0
;LOOP WHILE DCO FAULT
JNZ PWR0A

;---
------------------

As you can see, the chip will start the CODE at PWRON as the battery
inserted, the comments for each line of code is good enough for
explanation, isn't it? SO the chip will stablize after 2 loops to check for
LF fault and DCO fault. After that you can initialize all the ports, clear
all the RAM memory, ... Do wahtever you have to do to initially, setup the
program, and finally, branch to ENDAY: put the chip to sleep mode for
storage, save the power.

Suppose I have only 1 button for the device port 1.0. I need to enable the
button interrupt for port 1.0

;-------------- code for ENDAY --------------------------

ENDAY: CLR.B &P1IFG
; CLR POSSIBLE INTERRUPT FLAGS
BIC.B #01H,&P1DIR
; MAKE P1.0 INPUT
MOV.B #01H,&P1IES
; INTERUPT EDGE...P1.0 HI TO LO
MOV.B #01H,&P1IE
; ENBL P1.0 INTERRUPT

MOV.W #SFE(CSTACK),SP
; START OF STACK (CLEAR)
MOV.W #SCG1+SCG0+CPUOFF+GIE,SR ;
LPMODE3..ENABLE GENERAL INTERRUPT and

NOP
; WHILE ASLEEP

; A SWITCH ACTIVATION WILL VECTOR TO

; BINTR AND WILL RETI AFTER ALTERING THE

; SR ON THE STACK, IF THE CONTACT IS VALID.

; THE PROGRAM WILL CONTINUE FROM HERE WITH A

; BRANCH TO `NEWDAY', WHICH WILL CAUSE THE

; UNIT TO POWERUP. IF AN INTERMITTENT

; CLOSURE, THE UNIT WILL SHUTDOWN IN LOW

; POWER MODE AGAIN.

BIC #TBIE,&TB0CTL
; DISABLE TIMER B OVERFLOW INTERRUPT
BRA #NEWDAY
;. START THE PROGRAM WHEN THE BUTTON INTERRUPT

; TO TURN THE DEVICE ON.

;---
-----------

Now the chip is sleep in LPM mode 3 to save power. When the button is
pressed:

;---------------- CODE TO CHECK FOR BUTTON INTERRUPT
----

BINTR: CLR.B &P1IFG
;CLEAR PORT 1 INTERRUPT FLAGS
BIS.W #GIE,SR
;RE-ENABLE GENERAL INTERRUPT

MOV.W #0400H,TEMP
;DELAY FOR 5 MS

BINT00: DEC.W TEMP
;16 BIT.W REGISTER..DECREMENT TILL 0000H
JNZ BINT00

MOV.B &P1IN,BTNSAV
;CHECK FOR SWITCH INTERRUPT (XITION TO LO)
INV.B BTNSAV
;CHANGE TO POSITIVE LOGIC
AND.B #01H,BTNSAV
;MASK FOR BIT 0
JZ BINT01
;FALSE INTERRUPT
TST.B OPMODE
;IF OPMODE = SLEEPMODE=0 THEN SET SR ON

; THE STACK TO POWERUP ON RTI
JNZ BINT02
; NOT SLEEP

;ASLEEP
BIC #TBIE,&TB0CTL
;DISABLE TIMER_B OVERFLOW INTERRUPTS
CLR 0(SP)
;SET CPU ACTIVE ON RTI

BINT01: RETI

BINT02: MOV.B BTNSAV,BTNMEM
;SAVE FOR BUTTON CHECK ROUTINE
RETI ; ..

;--------------- END OF BUTTON INTERRUPT
---------------------------------

As you can see the code to detect the bouncing button for 5 ms. if the
button is pressed < 5 ms then it will be ignored. An valid button pressed
will return and wake the CPU up and start the NEWDAY routine (in DOZE). It
will start your program (turn on your device). If it is not from the sleep
mode (OPMODE = 0 operation mode) then it will be OPMODE 1, 2,3, 4 whatever
you named it then you know what to do with the button pressed. Example,
OPMODE 1 is in SET HOUR, the button will increase the HOURS, if the OPMODE 2
is in SET MINUTE, the button pressed will increase MINUTES. And as you know
, with port 1 we can have total 8 buttons to do so many thing.

Now for the DOZE, this is the place for the CPU to rest (LPM3) to save
power:

;----------- code for the DOZE
--------------

DOZE: MOV #SFE(CSTACK),SP
;START OF STACK (CLR POSSIBLE PENDING RTI)

BIC.B #01H,&P1DIR
; MAKE P1.0 INPUTS
MOV.B #01H,&P1IES
;INTERUPT EDGE...HI TO LO ON P1.0

MOV.B #01H,&P1IE
;ENABLE P1.0 INTERRUPTS

MOV #0120H,&TBCTL
;RECONDITION TIMERB 32KHZ, CONT UP..CAUTIONARY
ADD #1000H,&TBCCR0
;ADD 125MS TO COMPARE B0 REG (4096/32768)
MOV #0010H,&TBCCTL0
;ENABLE TIMERB COMPARE0 INTERRUPT

;-----------------------------------

DOZ00: MOV #00D8H,SR
;LPMODE3..ENABLE GENERAL INTERRUPT
NOP
;BTTN PRESSES WHILE IN DOZE WILL VECTOR TO

; BINTR AND ReTI BACK TO HERE TO THE LO PWR mode

;125MS COMPARE WILL VECTOR TO MAIN.

;MAIN WILL TERMINATE WITH A BRANCH BACK TO DOZE.

; IN ORDER TO SET UP THE SWITCH INTERRUPTS

; AND ADD 125MS TO THE NEXT COMPARE INTERRUPT.

JMP DOZ00
;PRECAUTION

;-------------- end code for doze
----
---

As you see up to now, the program (the CPU) resets at PWRON, loop until the
CPU is stable then go to ENDAY to sleep to save power. If a button is
pressed during sleep mode, the RETI will trigger the SR to turn the CPU ON,
the program will go to NEWDAY:

;----------- code for the NEWDAY ----------------------------

NEWDAY:

.......... DO whatever you have to do to display the device or do something
then branch to DOZE to let the CPU sleep. During the CPU sleep in DOZE, the
timer B compare 0 with 125 ms (1000H will be 125 ms, 2000H will be 250 ms,
and so on ... depends on how many ms seconds you want the button to react.)

BR #DOZE

;--------- end code for NEWDAY ----------------------------

Now the code for the MAIN: the MAIN will be running every 125 ms during
awake mode and you can do different task in the MAIN depends on what you
want to do:

;---------------- Code for MAIN running every 125 ms during awake
-------------

MAIN: MOV.W #WDTPW+WDTHOLD,&WDTCTL ; DISABLE WATCHDOG
TIMER,

INC.B EIGHTHS
;INCREMENT 1/8 SEC CTR

AND.B #07H,EIGHTHS
;MASK OFF UNUSED BITS

BIS.W #GIE,SR
;RE-ENABLE GEN INTERRUPTS FOR BTTN PRESSES

MOV.B EIGHTHS,R5

RLA R5

BR MAIN00(R5)

MAIN00: DW JOB0

DW JOB1

DW JOB2

DW JOB3

DW JOB4

DW JOB5

DW JOB6

DW JOB7

JOB0: Do something then ..

BR #DOZE

JOB1: Do something then ..

BR #DOZE

JOB2: Do something then ..

BR #DOZE

JOB3: Do something then ..

BR #DOZE

JOB4: Do something then ..

BR #DOZE

JOB5: Do something then ..

BR #DOZE

JOB6: Do something then ..

BR #DOZE

JOB7: Do something then ..

BR #DOZE

;-------------- end code for MAIN -------------------

This is a complete frame programming for a MSP430F449 chip from start power
up, detect LF and DCO fault to make sure 100% the CPU is stable and back to
sleep, wait for a button pressed to wake up and start a NEWDAY then go back
to sleep. During AWAKE mode, every 125 ms, the CPU will wake up to check
for any task that it has to do, then back to sleep until the program go back
to ENDAY (like 2 hours without a button pressed, the program will go back to
sleep mode.

Finally about TRAPE0, TRAPE2, ... I name it and put a code in it routine to
see if any interrupt occur during my program running so I can trap that
interrupt back to DOZE so I don't have any unwanted interrupt that will make
my program go haywired.

TRAPE0: MOV.B #0E0H,ERROR

... display the ERROR so I know what going all

.. delay the dislpay for 10 seconds ....

BR #DOZE

it is also a good programming when we put all the initialization in one
routine that I called PREP (prepare):

;------------ code to put all initialization in one routine ----------------

PREP: MOV.W #WDTPW+WDTHOLD,&WDTCTL ; DISABLE
WATCHDOG TIMER,

MOV.B #032H,&SCFQCTL
;DCOCLK = 50*30.518 = 1.52mhz, MODULATION ON
CLR.B &SCFI0
;DCO RANGE = .65/6mhz
CLR.B &SCFI1
; ..

MOV.B #0B0H,FLL_CTL0
;SELECT.. DCO, LO FREQ, 10pf LOAD
MOV.B #020H,FLL_CTL1
;XT2OFF, ACLK/1

CLR.B &IE1
;CAUTIONARY DISABLE MODULE INTERRUPT REGISTERS
CLR.B &IE2

CLR.B &IFG1
;CAUTIONARY CLEAR MODULE INTERRUPT FLAGS
CLR.B &IFG2
; ..
CLR.B &ME1
;CAUTIONARY MODULE DISABLES
CLR.B &ME2
; ..

;-------------- TIMER A SETUP
----
------------

; SET UP TIMER A FOR SOME USE, LIKE A PIEZO TO MAKE A SOUND OR SOMETHING

;---
----------------
MOV #0104H,&TACTL
;TIMERA ACLK, STOPPED, CLEARED
MOV #0008H,&CCR0
;COMPARE REG0 TO 7(DELAYED), TACL0 4096hz
MOV #0004H,&CCR2
;COMPARE REG1 TO 4, TACL1 (50%DC)
MOV #00E0H,&CCTL2
;PREPARE OUTP UNIT1 FOR RESET/SET
CLR &CCTL0
;CLR CAP/COMP CONTROL REG0
BIC #0010H,&TACTL
;STOP 4KHZ PIEZO DRIVE

;------------ PORT1 ----------------
;P1.0 button

;P1.1 to P1.7 N/U

CLR.B &P1IES
;INTERUPT EDGE...LOW TO HI
CLR.B &P1OUT
;SET PORT1 OUTPUT LATCHES LOW
MOV.B #0FEH,&P1DIR
;ALL OUTPUT EXCEPT P1.0 is INPUT
CLR.B &P1IE
;DISABLE P1 INTERRUPTS
CLR.B &P1IFG
;RESET POSSIBLE INTERRUPT FLAG
CLR.B &P1SEL
;Make port 1 to be all IO line
;PORT2
;PORT3
;PORT4
;PORT5
;PORT6

CLR &ADC12CTL0
;CLEAR A/D CONTROL REGISTERS
CLR &ADC12CTL1 ; ..
CLR &ADC12IFG
;CLEAR INTERRUPT ENABLE FLAG REGS
CLR &ADC12IE ; ..

RET

;---------- end code for PREP -------
You can put the PREP right after the CPU is stable then clear RAM, read
EEPROM ... before put the CPU into sleep mode.

I hope to help you guy with some information that I worked in the field of
assembler for the MSP430.

Anthony Ha

-------Original Message-------

From: Peter Grey

Date: 10/22/2013 6:32:41 PM

To: m...

Subject: RE: [msp430] Problems with MSP430F2132

Hi Al,

Thanks for the detailed reply. I must admit I have not used NMI since I was
using the PDP mini's, and that is a while ago! I shall take a look and may
have a few questions

Thanks

Peter

From: m... [mailto:m...] On Behalf Of
Onestone
Sent: Tuesday, 22 October 2013 4:26 PM
To: m...
Subject: Re: [msp430] Problems with MSP430F2132

This is probably just the usual issue with debounce of a switch (attaching
the battery is a switch), and the system getting caught out. Typically you
would have an INIT process shortly after start up with a clock stabilisation
loop or similar. I don't know how you handle NMI's but typically if your NMI
handling is too simplistic you will get a clock error, jump to the NMI which
might then get stuck in a loop or stall, or simply corrupt the PC. If you
have a LED try having the LED flash briefly during INIT, ie on very fast
then off once stable. Then have it turned fully on in the NMNI and point the
NMI back to itself. That will tell you if this is the issue.

Al

On 22/10/2013 4:50 PM, Peter Grey wrote:

I have been using these chips for a while. My devices have a battery
connected to them and, in some cases a battery charger. I find that when I
first connect a battery or take it off a charger it will not work. I need to
push a reset button. I have tried a reset chip and it makes no difference. I
can tell a customer to always press reset after the above events but I want
to find out what is going on and fix it. Has anyone experienced any such
behaviour.

TIA

Peter

The 2024 Embedded Online Conference