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.

UNABLE to enter interrupt service routine of I2C...

Other Parts Discussed in Thread: MSP430FR5738, MSP430WARE

OK so I'm using MSP430FR5738 to configure Si4705 FM radio receiver. I need to send commands of multiple bytes through I2C within the same start-stop period, plus reading back a single byte, in master mode. The byte length varies based on command, but right now I'm just sending a single 3-byte "power-up" command. What I do is storing those commands in arrays, and send them to the UCB0TXBUF register through an "intermediate buffer array" using I2C interrupt service. The STOP condition is generated by software in ISR. Only NACK, TX0, RX0 interrupts are enabled.

The step-by-step debug run (I'm using Code Composer Studio + MSPFET with spy-by-wire connection to FR5738) shows that the program is unable to enter interrupt service routine, while everything else works normal. The UCB IE, IFG, IV registers all show correct values with interrupt flag + interrupt signals set, but it just refuse to enter ISR and load UCB0 TX buffer...

And I've checked everything on PCB too, no problem found. It looks like a software problem.

By the way I've also been trying with DMA. But it seems the compiler put the next "command" array element (static unsigned short) in +2 memory address, while DMA address increments by only 1... and I didn't get the correct result either.?!

The code is attached here. Any idea???

#include <msp430.h>
unsigned short status[1]; // holds the single received byte
unsigned short buffer[8]; // for I2C multiple byte handling
unsigned short count;
unsigned short length;

void i2cinit(void);
void i2ctx (unsigned short*, unsigned short);
void i2crx1byte (void);
// unsigned short i2crx (unsigned short*, unsigned short);


int main(void)
{
	// load I2C commands in arrays of unsigned short type

	// CTS interrupt EN, GPO2 out EN, boot normally, RCLK in, transmit, digital audio in
	// response = status
	static unsigned short power_up[3] = {0x0001, 0x00C0, 0x0005};

	// code starts here......
	WDTCTL = WDTPW+WDTHOLD;                   // Stop WDT

	// for testing purpose only
	// enable LED output
	P1OUT &= ~BIT5; // yellow LED @ P1.5, for debugging only...
	P2OUT &= ~0x03; // green/red LED @ P2.0 & P2.1
	PJOUT &= ~BIT5; // Clear PJ.5, connect to RST pin of FM chip
	P1DIR |= BIT5; // set to output direction
	P2DIR |= 0x03;
	PJDIR |= BIT5;
	PM5CTL0 &= ~LOCKLPM5; // disable low power mode
	// LED config end

	// select pins for I2C
	P1SEL1 |= BIT6 + BIT7;

	//configure 8MHz DCO for CPU clock, divide by 4 for SMCLK
	CSCTL0 = CSKEY;                    // Unlock CS registers, password = 0xA5
	CSCTL1 = DCOFSEL_3;       // Set DCO to 8MHz
	CSCTL2 = SELS__DCOCLK + SELM__DCOCLK;// Set SMCLK = DCO; MCLK = DCO
	CSCTL3 = DIVS__4 + DIVM__1;     // MCLK = 16MHz, SMCLK = 2MHz
	CSCTL6 |= MCLKREQEN + SMCLKREQEN + ACLKREQEN;     // enable clock requests
	CSCTL0_H = 0; // lock CS register

	PJOUT |= BIT5; // first, RST pin of FM chip = high

	i2cinit(); // initialize I2C
	// yellow LED @ P1.5 on, for testing purpose only
	P1OUT |= BIT5;
	P2OUT |= BIT0;

	i2ctx(power_up, 3);

	i2crx1byte();

	if (status[0] != 0x0080)
	{
		P2OUT &= ~BIT0; // turn off LED
	}

	return 0;
}


// function definition: I2C transmit, of one full command sequence with "size"
void i2ctx (unsigned short *command, unsigned short size)
{
	unsigned short noob = 0;
	// fill the buffer array...
	count = size;
	length = size;
	while (count != 0)
	{
		count--;
		buffer[count] = command[count];
	}

	// set transmit mode
	UCB0CTLW0 |= UCTR;
	// enable Tx and non-acknowledge interrupt
	UCB0IE |= UCTXIE0 + UCNACKIE;
	// start transmission
	UCB0CTLW0 |= UCTXSTT;

	// this loop makes sure CPU stays here before Tx finish...
	while (UCB0IFG & UCBCNTIFG == 0)
	{
		noob = noob;
	}
	P2OUT &= ~BIT1; // LED @ P2.0 back to green after successful resend
	P2OUT |= BIT0;
}

// receive a single byte
void i2crx1byte (void)
{
	unsigned short noob = 0;
	count = 0;
	// set receive mode
	UCB0CTLW0 &= ~UCTR;
	// enable receive and non-acknowledge interrupt
	UCB0IE |= UCRXIE0 + UCNACKIE;
	// start transmission and stop, same time...
	UCB0CTLW0 |= UCTXSTT + UCTXSTP;

	// loop makes sure CPU stays here before stop...
	while (UCB0IFG & UCRXIFG0 == 0)
	{
		noob = noob;
	}
	status[0] = buffer[0];
	P2OUT &= ~BIT1; // LED @ P2.0 back to green after successful resend
	P2OUT |= BIT0;
}


// interrupt service routine of I2C

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCI_B0_VECTOR
__interrupt void USCIB0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCIB0_ISR (void)
#else
#error Compiler not supported!
#endif
{
  switch(__even_in_range(UCB0IV,0x1E))
  {
        case 0x00: break;                    // Vector 0: No interrupts break;

        case 0x04:  // non-acknowledge
        	UCB0CTLW0 |= UCTXSTP;             // stop I2C
        	count = 0;
        	UCB0CTLW0 &= ~UCTXNACK; // clear interrupt flag
        	P2OUT &= ~BIT0;  // LED turns red
        	P2OUT |= BIT2;
        	UCB0CTLW0 |= UCTXSTT; // start after stop
          break;                            // Vector 4: NACKIFG break;
          // to cope with FM chip, cannot use START without STOP first...

        case 0x16: // receive 0 ready
        	buffer[count] = UCB0RXBUF; // move data from buffer
        	count++;
        	break;

        case 0x18: // transmit 0 ready
        	UCB0TXBUF = buffer[count]; // move data from buffer
        	count++;
        	if (count >= length)
        		UCB0CTLW0 |= UCTXSTP; // software stop once size is reached
        	break;
        default: break;
  }
}


// initialize I2C
void i2cinit(void)
{
	// enable config
	UCB0CTLW0 = UCSWRST;
	// I2C master mode, SMCLK, sync
	UCB0CTLW0 |= UCMST + UCMODE_3 + UCSYNC + UCSSEL__SMCLK;
	// de-glitch time 25ns
	UCB0CTLW1 |= UCGLIT_1;
	// I2C clock is SMCLK divided by 28
	UCB0BRW = 0x001C;
	// slave address, 7-bit, 0010001
	UCB0I2CSA = 0x11;
	// end config
	UCB0CTLW0 &=~ UCSWRST;
}

**Attention** This is a public forum