This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430 enters TI_ISR_TRAP when using structs & union

Other Parts Discussed in Thread: MSP430F2132

This is my first time, using this forum.

I have a little hardware consisting of a digital temperature sensor a DAC (i2c) and the MSP430F2132. I already had a working code but i had problems with the sensor output
I tried to adapt my code with a former project where they used a lot of structs and unions. 

When i was done, nearly nothing worked than before. The i2C-interrupt routine was entered once and afterwards the MSP entered the TI_ISR_TRAP and i don´t why or how  i can solve it. 

MAIN.c
#include "Digipile.h"
/*
 * main.c
 */
#define DAC_slave_address 0x60

DIGIPILEPARA_Typedef *pilepara;
u32 Temperature;
u8 TXByteCtr;
u8 *PTxData;
u8 data_to_transmit[2];
u16 DAC_out;

s16 mittelwert;
s32 filter_summe;
s32 filter_summe_soll;
s16 filter_wert[3];
u8 i;
s16 fehler_zaehler=0;
u8 filter_index;
u8 filter_counter;
s16 filtered_Temperature;
u8 Ausgabe;
//Function Prototypes
void i2c_init(void);

int main(void) {

    WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer
  /*  pilepara->counts_c = 271.35;
    pilepara->counts_m = 233.18;
    pilepara->ntc_c = 61.667;
    pilepara->ntc_m = 90;
    pilepara->tp_offset = 64500;*/
    i2c_init();
    while(1){

    	__disable_interrupt();	//Interrupts disable because of the Digipile algorithm
    	__delay_cycles(50);
    	Temperature = Digipile_auslesen();

    	/*
    	 * gleitendes Mittelwertfilter
    	 */
    	// ältesten Wert von der Summe subtrahieren
    	filter_summe = filter_summe - filter_wert[filter_index];
    	// neuen Wert dazuaddieren
    	filter_summe = filter_summe + Temperature;
    	//neuen Wert anstelle des alten Wertes speichern
    	filter_wert[filter_index] = Temperature;

    	if(++filter_index >=3){
    		filter_index = 0;
    	}

    	mittelwert = filter_summe / 3;

    	//Filter für Messwerte größer +-500mV -> 10% Abweichung
    	for(i=0; i<3; i++){

    		if( (filter_wert[i]<(mittelwert+10)) && (filter_wert[i]>(mittelwert-10)) ){
    			filter_summe_soll= filter_summe_soll + filter_wert[i];
    			filter_counter++;
    		}
    		if(i==2){
    			if(filter_counter ==0){		//wenn keiner der drei Werte ins Toleranzband passen so wäre filter_counter = 0, Division durch 0 ergibt -1
    				Ausgabe = 0;
    			}
    			else{
    				Ausgabe =1;
    				filtered_Temperature = (filter_summe_soll / filter_counter);
    				filter_summe_soll=0;
    				filter_counter=0;
    			}
    		}

    	}
    	if(Ausgabe==1){

    		DAC_out = 20.475*filtered_Temperature+819;		//Umrechnung der Temperaturwerte in DAC werte -> 4mA = 0,66V = 819 counts, 20mA = 3,3V = 4095 counts
    		data_to_transmit[0] =(u8)(DAC_out >>8);			//DAC_out wird in zwei byte aufgespalten
    		data_to_transmit[1] =(u8)(DAC_out);
    		PTxData = &data_to_transmit[0];					//Pointer auf Transmit-Array setzen
    		TXByteCtr = sizeof(data_to_transmit);			//TXByteCounter == 2 Byte
    		while(UCB0CTL1 & UCTXSTP);						//auf i2c_Stop warten
    		UCB0CTL1 |= UCTR +UCTXSTT;						// i2c als sender konfigurieren und mit UCTXSTT Start-Condition senden
    		__bis_SR_register(CPUOFF + GIE);				//entspricht enable_interrupt und ist Rücksprungaddresse der ISR
    	}
    }

}

void i2c_init(void)
{
	P3SEL |= 0x06;                            // Assign I2C pins to USCI_B0
	UCB0CTL1 |= UCSWRST;                      // Enable SW reset
	UCB0CTL0 = UCMST+UCMODE_3+UCSYNC;         // I2C Master, synchronous mode
	UCB0CTL1 = UCSSEL_2+UCSWRST;              // Use SMCLK, keep SW reset
	UCB0BR0 = 12;                             // fSCL = SMCLK/12 = ~100kHz
	UCB0BR1 = 0;
	UCB0I2CSA = DAC_slave_address;            // Set slave address
	UCB0CTL1 &= ~UCSWRST;					  // release USCI for Operation -> exit configuration mode
	IE2 |= UCB0TXIE;

	data_to_transmit[0] = 0x98;				  // DAC konfigurieren -> externe Referenz verwenden
	PTxData = &data_to_transmit[0];
	TXByteCtr =1;
	while(UCB0CTL1 & UCTXSTP);
	UCB0CTL1 |= UCTR +UCTXSTT;
	__bis_SR_register(CPUOFF + GIE);
}

#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
{
	if(TXByteCtr){
		UCB0TXBUF = *PTxData++;
		TXByteCtr--;
	}
	else{										//sobald alle Daten übertragen worden sind
		UCB0CTL1 |= UCTXSTP;					//Stop Condition
		IFG2 &= ~UCB0TXIFG;						// Interrupt Pending bit disable
		__bic_SR_register_on_exit(CPUOFF);		// in LPM0 wechseln
	}
}


Digipile.h
#ifndef DIGIPILE_H_
#define DIGIPILE_H_

#include <msp430.h>
#include "typedefs.h"

#define P3_5 0x80

#define BIT_SET(a,b) ((a |= (1<<(b))))

typedef union
{
	u32 data;
	struct{
		u32 amb:14;
		u32 obj:17;
	}t;

}DIGIPILE_Typedef;

typedef struct{
	s32 tp_offset;
	u32 ntc_m;
	s32 ntc_c;
	s32 counts_m;
	s32 counts_c;

}DIGIPILEPARA_Typedef;


s16 Digipile_auslesen(void);
void clear_DPEL(void);

#endif /* DIGIPILE_H_ */

Digipile.c
#include "Digipile.h"

DIGIPILE_Typedef *pileread;
DIGIPILEPARA_Typedef *pilepara;

s32 Tobj;			//Object Temperature
u32 Tamb;			//Ambient Temperature
u8 bits;

float cpk;


void clear_DPEL(void)
{
	P1OUT &= ~P3_5;
	P1DIR |= P3_5;
	__delay_cycles(5);
	P1DIR &= ~P3_5;
}

s16 Digipile_auslesen(void)
	{
		pileread->data=0;

		//clear_DPEL();
		P1OUT |= P3_5;
		P1DIR |= P3_5;
		__delay_cycles(90);

		bits=31;
		while(bits){
			bits--;
			P1OUT &= ~P3_5;
			P1DIR |= P3_5;
			__delay_cycles(1);
			P1OUT |= P3_5;
			__delay_cycles(1);
			P1DIR &= ~P3_5;

			__delay_cycles(5);
			if(P3_5 & P1IN){
				BIT_SET(pileread->data, bits);
			}
		}

		clear_DPEL();
		Tamb = (pileread->t.amb / pilepara->ntc_m) + pilepara->ntc_c;
		Tobj = pileread->t.obj - pilepara->tp_offset;
		cpk = (Tobj  / pilepara->counts_m) + pilepara->counts_c;
		Tobj /= cpk;

		return (Tobj + Tamb);
	}


  • using -> with structures though you are not in a pointer-function is kind of wrong.

    Using German words for functions names and notes, not sure if that is internationally acceptable,
    does for example Bosch allow their programmers to do that?

    Just because the program go overboard with union and structs, a IRQ is still a IRQ.
    If the vector is filled in and the ISR clears it's own IFG flag (by reading it's BUF for example)
    What could it be then, writing to address zero due to the incorrect use of struct pointers?

    A union stack all the vars together on top of each other, so different definition types but accesses the same memory,
    a struct inside a union lets you override this stacking when needed for these particular group of vars.

  • Tony Philipsson said:
    using -> with structures though you are not in a pointer-function is kind of wrong.

    Huh? The only uses of -> in the code above are with pointers to struct types. I'm not sure what you mean by "not in a pointer-function" either.

    EDIT: From a quick read through the code it seems that pileread and pilepara are never set, so point to some unknown address. That's definitely not good: pointers need to point at something before they can be safely dereferenced with -> or *.

  • though it's commented out for now

    int main(void) {
    WDTCTL = WDTPW | WDTHOLD;   // Stop watchdog timer
    /*  pilepara->counts_c = 271.35;
    pilepara->counts_m = 233.18;
    pilepara->ntc_c = 61.667;

    Where is Pointer value set?, why even use pointer?

    If there is only one struct and there are no plans to get more of the same type, why even use pointers all over your code?
    A pointer-function I meant that the functions takes a pointer to struct, as you have many iterations of the same struct,
    you use entry pointer+offset e.g the -> in C.

    The whole code should be rewritten from scratch.

  • Hi Martin,

    Usually the ISR trap occurs when you have an interrupt with no specified ISR routine.
    Can you provide the Digipile.h file so I can help debug this problem?

    Regards,
    Charles O
  • Yes it´s commented out, because if not, the whole code isnt executed properly. Breakpoint at line 41 is not reached and when i hit pause the programm hangs at the closing bracket of i2c_init.
    Guess you are right. The problem is the behavior of the sensor, a lot of wrong measurements. So i thought i try to copy the code from a different project where everthing worked. From this project i have the structures.
  • This was actually the solution. I don´t know which Interrupt occured but with a own TrapIsr routine where i put all unused Interrupt vectors, the problem with the TI_TRAP_ISR was solved.  

    #pragma vector = ADC10_VECTOR, NMI_VECTOR, PORT1_VECTOR, PORT2_VECTOR, \
    TIMER0_A0_VECTOR, TIMER0_A1_VECTOR, WDT_VECTOR
    __interrupt void TrapIsr(void)
    {
    // this is a trap ISR - check for the interrupt cause here by
    // checking the interrupt flags, if necessary also clear the interrupt
    // flag
    }

  • You should try to find out which interrupt you get (use separate handler functions, and check the corresponding interrupt flags).

**Attention** This is a public forum