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.

CCS/MSP430FR2633: I2C Read function - Issue at the repeated start

Part Number: MSP430FR2633

Tool/software: Code Composer Studio

Hi all,

I have written I2C functions using polling onto a MSP430FR2633 (MSP-CAPT-FR2633 board) to communicate with a peripheral MAX77818 battery charger fuel gauge chip.

My read function hangs at the repeated start condition. By that I mean the check for UCTXSTT being cleared. I have copied the I2C read function code below. My write function seems to work. So I am eliminating the possibility of hardware. I have pull up resistors of 2.2k on SDA and SCL. I also checked the registers in debug which confirmed NACKIFG was not set. 

void Read_I2C_Reg(unsigned char Slave_Addr, unsigned char Reg, unsigned char ReadLength)
{
   UCB0IFG = 0x00;
   PRxDataPtr = 0;				                            // Initialise starting index of rxBuffer
   PRxData = (unsigned char *)RxBuffer[0];    	    // Initialise PRxData pointer to start of RX buffer
   RXByteCtr = ReadLength;                                          // Load arguement ReadLength to RXByteCtr which is for number of bytes to read

   while(UCB0STAT & UCBBUSY);                               // ensure bus isn't busy
   UCB0I2CSA = Slave_Addr >> 1;                              // Slave Address is Slave_Addr's 7 MSB's written on to UCB012CSA

   UCB0CTLW0 |= UCTR;             	    	                   // I2C TX mode
   UCB0CTLW0 |= UCTXSTT;             	    	           // start condition
   UCB0TXBUF = Reg;				                   // Register address to read. this will be the first byte of data transmitted.
   while(UCB0CTLW0 & UCTXSTT);			   // Wait till I2C STT is sent
   while (!(UCB0IFG & UCTXIFG));                              // Reg has been sent

   UCB0CTLW0 &= ~UCTR;				          // Switch to receive mode
   UCB0CTLW0 = UCTXSTT;				          // Send repeated start condition.
   while(UCB0CTLW0 & UCTXSTT);			  // Wait till I2C STT is sent<<<<<<<<<<<<<<<<<<<<<<<<<<<< UCTXSTT doesn't get cleared. Waits here.

   while(RXByteCtr > 0)				                  // If we have requested to read multiple bytes, loop
   {
	while(!(UCB0IFG & UCRXIFG));		          // Wait till RX flag goes up. Then UCB0RXBUF has data
	RxBuffer[PRxDataPtr] = UCB0RXBUF;             // Fill RxBuffer at the index PRxDataPtr with received UCB0RXBUF
	PRxDataPtr++;				                          // Increment PRxDataPtr
	RXByteCtr--;				                                  // decrement RXByteCtr
   }

   while(!(UCB0IFG & UCRXIFG));
   *PRxData = UCB0RXBUF;                 	                 // Move final RX data to PRxData
   UCB0CTLW0 |= UCTXNACK;			         // NACK before stop
   UCB0CTLW0 |= UCTXSTP;                	                 // Issue stop condition
   while (!(UCB0CTL1 & UCTXSTP));		         // Ensure stop condition got set
}   

My initialisation for the I2C is as below. DCO at 16MHz sources SMCLK:

void Init_MSP430_I2C(void)
{
    P1SEL0 |= BIT2 | BIT3;  			                                 //Assign I2C pins to USCI_B0
    UCB0CTLW0 |= UCSWRST;                                          // Enable SW reset
    UCB0CTLW0 |= UCMST | UCMODE_3 | UCSYNC ; //I2C Master, synchronous mode, 7 bit mode by default
    UCB0CTLW0 &= ~UCMM;					        //Setting for multi master I2C, not relevant, but &~'d as a precaution
    UCB0CTLW0 = UCSSEL_3 ;                                            // Use SMCLK, 
    UCB0BR0 = 160;                                                             // fSCL = SMCLK/160 = ~100kHz	Above 100kHz upto 400kHzwould be 'Fast I2C
    UCB0BR1 = 0;
    UCB0I2CSA = 0x00;                                                       // Set to AA for initialisation purposes. Slave address is accepted as a parameter in the read and write function.
    UCB0CTLW0 &= ~UCSWRST;                                         // Clear SW reset, resume operation
    UCB0IFG |= 0x00;
}


Another bizzare observation : Up until the point it gets to the never ending check for UCTXSTT, my register settings stay as I initialised. When it hangs at the highlighted line, I paused and observed a change in some registers through the debugger. Under USCI_B0_I2C registers, most importantly UCB0CTLW0 is showing 0x01D2. Which would mean that the UCMODEx bits are 00b which is not in I2C mode anymore! and UCTR has been turned back on although it was turned off just before.

Is anyone able to help me fix, and understand why the code halts at the repeated start please? Any guidance will be greatly appreciated.


Thanks & kind regards,

Guyan

  • Hi Guyan, 

    UCB0CTLW0 = UCTXSTT;                       // Send repeated start condition.

    With this line of code you are setting the entire register instead of just the start bit, I think you mean to do something like this:

    UCB0CTLW0 |= UCTXSTT;                       // Send repeated start condition.

    Also please take a look at Solutions to Common eUSCI and USCI Serial Communication Issues on MSP430 MCUs when you first experience communication issues. This document has a lot of great information on the most common I2C issues and how to fix them.

    Best regards, 

    Caleb Overbay

  • Hi Caleb,

    Thank you very much for pointing that mistake! I certainly meant to use |=

    My write and read functions don't hang anymore. But the values read are not as they are expected to read. This could possibly be a problem with my I2C slave MAX77818. So I wanted to use printf() from stdio.h to read and print the values nicely in order for debugging purposes. However I get the following error and warning if I include stdio.h and use printf(<with relevant string>).

    Warning in yellow:
    warning #10229-D: output section ".data" refers to load symbol "_nop" and hence cannot be compressed; compression "lzss" is ignored

    Error in red:
    "../lnk_msp430fr2633.cmd", line 132: error #10099-D: program will not fit into available memory. placement with alignment fails for section "ALL_FRAM" size 0x49be . Available memory ranges:


    What do I do in order to be able to use printf in this device please?
    Thanks and kind regards,
    Guyan
  • Hi Caleb,

    I found the fix to the printf issue.
    I will type how I fixed it, below. In case someone else comes across it, hopefully it will help them.

    right click project, and go to properties
    1)CCS Build -> MSP430 Compiler -> Advanced options - > languague options -> level of prontf/scanf support required - Set to minimal.
    2)CCS Build -> MSP430 Compiler -> MSP430 Linker -> basic options -> Heapsize for dynamic memory allocation - set to 320, Set C system stack size to 80

    Kind regards,
    Guyan
  • Hi Guyan,

    I apologize for the late reply, I've been out of office this past week. It's good to here you were able to figure out how to get the printf functionality working. Do you have any more questions before I close this thread?

    Best regards,
    Caleb Overbay
  • Hi Caleb,

    I did have some progress, but I hit another road block with the registers reading the wrong value (same value)when I read registers using the repeated start. Unfortunately I had to park that project for now because I got stuck there. Surely I will need to re-attend it later because that product is essential.

    You could close the thread, I suppose. Because it's a repeated start read(slightly different topic) issue, if I can't get past it after some more tries, I'll post it in the forum. I really appreciate you getting back to me. :)

    Kind regards,
    Guyan

**Attention** This is a public forum