Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Mysterious: Timer A interrupt occuring although never enabled

Status
Not open for further replies.

acannell

Junior Member level 2
Joined
Apr 16, 2012
Messages
23
Helped
3
Reputation
6
Reaction score
3
Trophy points
1,283
Activity points
1,630
Setup is:

MSP430F1101A

Internal DCO at wakeup then switch to external 4.096MHz crystal.

AQ430 C compiler/IDE

MSP-FET430UIF

This processor keeps getting locked up. I've added all kinds of pin wiggles to watch whats happening, because it doesnt happen while connected to the debugger. As far as I can tell, it appears that a Timer A interrupt sometimes starts to repeatedly occur, keeping the processor in an infinite loop of some kind. The mystery is that as far as I can tell by breaking in the simulator and my own analysis of the code, I never enable TAIE.

To prove this, I added interrupt handler functions for every vector, and when any of them are activated (interrupt occurs), I wiggle a pin as many times as that vector. So if vector 8 occurs, I wiggle a pin 8 times so I can tell. And the wiggles indicate timer a vector is occuring.

The way this processor is used is:

Initial power on.

Setup hardware in a typical way, go to sleep LPM4.

Get awoken every 1000ms by a port 1 interrupt, switch oscillators, use timer A capture to measure something (without interrupt), go back to sleep.

The code is (not including cstart.asm):


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
// --------------
// Include Files
// --------------
 
#include <msp430x11X1.h>
 
// ---------------------
// Function Prototypes
// ---------------------
 
void main( void );
void init_hardware( void );
void check_cha_frequency( void );
void check_chb_frequency( void );
void isr(void);
unsigned char vect;
 
// ------------
// Definitions
// ------------
 
// To make the program easier to understand.
#define TRUE     1 
#define FALSE     0
 
// For Time Delay Loops
#define HS_OSC_DELAY   0xFF
#define INTERRUPT_DELAY_TIME  100
 
// Define Window Limits
#define SMCLK_FREQ    4096000
#define SMCLK_FREQ_ERROR   40   // Allowable deviation.
#define MAX_BAD_COUNTS   100   // Used for filtering bad counts.
#define CHA_HIGH_LIMIT    ( SMCLK_FREQ / 4000 ) + SMCLK_FREQ_ERROR
#define CHA_LOW_LIMIT     ( SMCLK_FREQ / 4000 ) - SMCLK_FREQ_ERROR
#define CHB_HIGH_LIMIT   ( SMCLK_FREQ / 4000 ) + SMCLK_FREQ_ERROR 
#define CHB_LOW_LIMIT   ( SMCLK_FREQ / 4150 ) - SMCLK_FREQ_ERROR
 
// Inputs
#define HV_ACTIVE    BIT3
#define CHA_HV_DETECT   BIT2
#define CHB_HV_DETECT   BIT1
#define CHA_AND_CHB    ( BIT1+BIT2 )
 
// Outputs
#define CHA_HV_GOOD    BIT2
#define CHB_HV_GOOD    BIT1
#define TEST_OUT    BIT0
 
// -------------
// Define Enums
// -------------
 
// ----------------------
// Structure Definitions
// ----------------------
 
// ------------------
// Global Variables
// ------------------
 
// ----------------
// Local Variables
// ----------------
 
// Channel A Related Variables
unsigned char ucChAError;
unsigned int uiChAFrequency;
unsigned int uiPrevChAFrequency;
unsigned int uiCurrentChAFrequency;
unsigned char ucChAHVPresentFlag;
 
// Channel B Related Variables
unsigned char ucChBError;
unsigned int uiChBFrequency;
unsigned int uiPrevChBFrequency;
unsigned int uiCurrentChBFrequency;
unsigned char ucChBHVPresentFlag;
 
// Diagnostics Related Variables
unsigned int ucNumberWdResets = 0;
 
// Store Version Number
unsigned int uiVersionNumber = 101; // Can only be seen with a debugger.
 
void main( void )
  {  
  init_hardware();
  
  while( TRUE )
    {
    WDTCTL = WDT_ARST_1000;     // Set Watchdog Timer interval.
     
 // So we can  tell that a watchdog reset occured.
    if(( IFG1 & WDTIFG ) == WDTIFG )
      {
      // Set the flag.
      ucNumberWdResets = 0xFF;
       P1OUT &= ~BIT0;
  P1OUT |= BIT0;
  P1OUT &= ~BIT0;
  IFG1 &= ~WDTIFG;
      }
    
    // Start monitoring the frequency for channels A and B.
    check_cha_frequency();  // CHA_HV_GOOD HIGH = LOW, HV OK.
 
    // -----------------
    // ENTER SLEEP MODE
    // -----------------
    
    // If HV_ACTIVE input is low, SLEEEEEPPPP.....   
    if(( P1IN & HV_ACTIVE ) == 0 )
      {
      P2OUT |= CHA_HV_GOOD;  // Set output high so we are in a known state.
      P2OUT |= CHB_HV_GOOD;  // Set output high so we are in a known state.
      _DINT();     // Momentarily disable interrupts.
      P1IE |= HV_ACTIVE;  // Enable HV_ACTIVE interrupts (disabled in ISR).
      P1IFG = 0;    // Clear HV interrupt flag.
      _EINT();     // Re-enable interrupts
      LPM4;      // Enter LPM4.      
      }
    }
  }
  
  
void init_hardware( void )
  {
  unsigned int i;
  
  WDTCTL = WDTPW + WDTHOLD;             // Stop WDT
  BCSCTL1 |= ( XTS+XT2OFF+DIVA_3 );  // ACLK = LFXT1 = HF XTAL ACKL / 8.
  BCSCTL2 |= ( SELS+SELM_2 );   // Switch SMCLK, MCLK to HS Crystal.
  
  // If there is a problem with the HS Oscillator we will hang up here.
  do 
    {
    IFG1 &= ~OFIFG;                     // Clear OSC Fault flag
    for( i = HS_OSC_DELAY; i>0; i-- ); // Time for flag to set
    }    
  while (( IFG1 & OFIFG ) != 0 );       // OSC Fault flag still set? 
  
  // Setup Port 1 Inputs
  P1SEL |= CHA_HV_DETECT;    // Setup CCR1 - Capture mode.     
  P1SEL |= CHB_HV_DETECT;    // Setup CCR0 - Capture mode.
  
  P1DIR |= BIT0;      // Make unused I/O pins outputs.
  P1OUT &= ~BIT0;      // And set unused I/O pins Low.
 
  P1IES = 0;       // Interrupt on Rising Edge
  P1IE |= HV_ACTIVE;     // Enable HV_ACTIVE interrupts.
  P1IFG = 0;       // Clear HV_ACTIVE interrupt flag.
 
  // Setup Capture Compare Rregisters
  TACTL = ( TASSEL_2+MC1+TACLR );  // SMCLK - Clear TAR, Continuous Up mode.       
  TACCTL0 = ( CM_2+SCS+CAP );   // Falling edge, capture mode.
  TACCTL1 = ( CM_2+SCS+CAP );   // Falling edge, capture mode. 
 
  // Setup Port 2 outputs
  P2DIR |= 0x3F;      // Set P2.0 - P2.6 to outputs.
  P2OUT = 0x06;       // Start CH A and CH B Good lines high.
  
  // Initialize global variables. 
  ucChAError = 0;  
  uiChAFrequency = 0;
  uiPrevChAFrequency = 0;
  uiCurrentChAFrequency = 0;
  ucChAHVPresentFlag = FALSE;
  
  ucChBError = 0;
  uiChBFrequency = 0;
  uiPrevChBFrequency = 0;
  uiCurrentChBFrequency = 0;
  ucChBHVPresentFlag = FALSE;
  IE1 |= WDTIE;                         // Enable WDT interrupt
  
  //---------------------------
  // Get ready. Get set. Go!!!
  // --------------------------
  
  _EINT();                              // Enable interrupts 
  }  
                       
void check_cha_frequency( void )
  {
  unsigned int i, n;
  
  // See if electrical stimulation is being produced on Channel A.
  
  // This loop is so that we can get a specified number of errors in a row
  // before concluding that the frequency is off.
 
  ucChAError = 0;
  for( i=0; i<MAX_BAD_COUNTS; i++ )
    {
    TACCTL1 &= ~CCIFG;      // Clear the CCR1 interrupt flag.
    n=0;         // Intialize delay loop counter.
    while( TRUE )
      {
      // This loop is so that we don't get hung up forever waiting for an
      // interrupt to occur. If it has not occured after n times through the
      // loop we just return.
      
      if(( TACCTL1 & CCIFG ) == CCIFG )  // CCR1 Interruptflag set?
        {
        uiCurrentChAFrequency = TACCR1;  // Yes, Save the TAR count.
        uiChAFrequency = uiCurrentChAFrequency - uiPrevChAFrequency;
        
        // Is the TAR count within prescribed limits?
        if(( uiChAFrequency < CHA_LOW_LIMIT ) || ( uiChAFrequency > CHA_HIGH_LIMIT ))
          {
          ucChAError++;      // Out of limits. Increment the error count.
          }
        uiPrevChAFrequency =  TACCR1;  // Read current TAR for next iteration.
        break; 
        }
      else
        {
        n++;        // Increment delay loop counter.
        if( n > INTERRUPT_DELAY_TIME )
          {
    // Set output high because no frequency was detected.
     P2OUT |= CHA_HV_GOOD;
          return;       // Bail out.
          }
        }
      }    
    }
         
  // Evaluate results of frequency test for Channel A 
  if( ucChAError < MAX_BAD_COUNTS )
    {
    P2OUT &= ~CHA_HV_GOOD;     // Set output LOW because frequency is within limits.
    }
  else  
    {
    P2OUT |= CHA_HV_GOOD;     // Set output high because frequency is out of bounds.
    }
  }
 
interrupt[ PORT1_VECTOR ] void hv_active_int( void )
  {
  unsigned int i;
 
  // Wake up if HV Active goes high. We should be running off the DCO
  // Clock at first.
  LPM4_EXIT;             // Resume normal operation.  
  WDTCTL = WDT_ARST_1000;       // Start Watchdog Timer interval
    
  // Switch to HS Osillator.
  BCSCTL1 |= ( XTS+XT2OFF+DIVA_3 );  // ACLK = LFXT1 = HF XTAL ACKL / 8.
  BCSCTL2 |= ( SELS+SELM_2 );   // Switch SMCLK, MCLK to HS Crystal.
  
  // Wait for HS Oscillator to stablize.  
  do 
    {   
    IFG1 &= ~OFIFG;      // Clear OSC Fault flag
    for( i = HS_OSC_DELAY; i>0; i-- ); // Time for flag to set
    }    
  while (( IFG1 & OFIFG ) != 0 );       // OSC Fault flag still set?
  
  P1IFG = 0;       // Clear interrupt flag.
  }
 
 
void isr(void)
{
 unsigned char count;
 P1DIR |= BIT0;
 for(count = 0; count < vect; count++)
 {
  P1OUT &= ~BIT0;
  P1OUT |= BIT0;
  P1OUT &= ~BIT0;
 }
 if(TACTL & 0x0002)
 {
  P1OUT &= ~BIT0;
  P1OUT |= BIT0;
 }
}
/*
interrupt [0] void int0(void)
{
isr();
}
*/
interrupt [2] void int1(void)
{
vect = 1;
isr();
}
 
interrupt [6] void int3(void)
{
vect = 3;
isr();
}
 
interrupt [8] void int4(void)
{
vect = 4;
isr();
}
 
interrupt [10] void int5(void)
{
vect = 5;
isr();
}
 
interrupt [12] void int6(void)
{
vect = 6;
isr();
}
 
interrupt [14] void int7(void)
{
vect = 7;
isr();
}
 
interrupt [16] void int8(void)
{
vect = 8;
isr();
}
 
interrupt [18] void int9(void)
{
vect = 9;
isr();
}
 
interrupt [20] void int10(void)
{
vect = 10;
isr();
}
 
interrupt [22] void int11(void)
{
vect = 11;
isr();
}
 
interrupt [24] void int12(void)
{
vect = 12;
isr();
}
 
interrupt [26] void int13(void)
{
vect = 13;
isr();
}
 
interrupt [28] void int14(void)
{
vect = 14;
isr();
}

 
Last edited by a moderator:

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top