acannell
Junior Member level 2
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):
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: