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.

MSP430FR2433: I2C code from Walter Schurr does not work.

Part Number: MSP430FR2433
Other Parts Discussed in Thread: MSP-EXP430FR2433, MSP430F5329

//=======================================================================

#include "msp430.h"
#include "driverlib.h"

#define DCOFREQ 8000000

#define I2C_0_BASE (EUSCI_B0_BASE)
#define I2C_RECEIVE_BUFFER_SIZE (32)

uint8_t I2C_0_rxBuffer[I2C_RECEIVE_BUFFER_SIZE];
int8_t I2C_0_rxBytesRemaining = 0;
int8_t I2C_0_rxCnt = 0;

void setup(void)
{
    EUSCI_B_I2C_initMasterParam I2C_0;

    // SMCLK = MCLK = DCO = 4MHz
    // ACL = 32kHz
    CS_initClockSignal(CS_FLLREF, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1);
    CS_initClockSignal(CS_ACLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1);
    CS_initClockSignal(CS_MCLK, CS_DCOCLKDIV_SELECT, CS_CLOCK_DIVIDER_1);
    CS_initClockSignal(CS_SMCLK, CS_DCOCLKDIV_SELECT, CS_CLOCK_DIVIDER_1);
    CS_initFLL((DCOFREQ/1000), DCOFREQ/32768);
    CS_clearAllOscFlagsWithTimeout(1000);

    // I2C port mux selection
    P1OUT = 0;
    P1DIR |= BIT0 | BIT1 | BIT4 | BIT5 | BIT6;
    P1SEL0 |= BIT2 | BIT3;
    PM5CTL0 &= ~LOCKLPM5;

    // I2C Setup
    I2C_0.selectClockSource = EUSCI_B_I2C_CLOCKSOURCE_SMCLK;
    I2C_0.i2cClk = DCOFREQ;
    I2C_0.dataRate = EUSCI_B_I2C_SET_DATA_RATE_400KBPS;
    I2C_0.byteCounterThreshold = 0;
    I2C_0.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP;

    EUSCI_B_I2C_disable(I2C_0_BASE);
    EUSCI_B_I2C_initMaster(I2C_0_BASE, &I2C_0);
    EUSCI_B_I2C_enable(I2C_0_BASE);

    __delay_cycles(8000000);
}

uint8_t I2C_0_readCmd(uint8_t slave, uint8_t cmd)
{
    P1OUT |= BIT0 | BIT4 | BIT5 | BIT6;

    // Set slave address and wait for bus
    EUSCI_B_I2C_setSlaveAddress(I2C_0_BASE, slave);
    EUSCI_B_I2C_clearInterrupt(I2C_0_BASE,
                EUSCI_B_I2C_RECEIVE_INTERRUPT0 |\
                EUSCI_B_I2C_TRANSMIT_INTERRUPT0 |\
                EUSCI_B_I2C_STOP_INTERRUPT );
    EUSCI_B_I2C_enableInterrupt(I2C_0_BASE,
                EUSCI_B_I2C_RECEIVE_INTERRUPT0 |\
                EUSCI_B_I2C_STOP_INTERRUPT );
    I2C_0_rxBytesRemaining = 0;

    // Write command to slave
    EUSCI_B_I2C_setMode(I2C_0_BASE, EUSCI_B_I2C_TRANSMIT_MODE);
    EUSCI_B_I2C_masterSendMultiByteStart(I2C_0_BASE, cmd);
    while(!(EUSCI_B_I2C_getInterruptStatus(I2C_0_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0)))
    {
        if (EUSCI_B_I2C_getInterruptStatus(I2C_0_BASE, EUSCI_B_I2C_NAK_INTERRUPT))
        {

            return 0;
        }
    }

    // Read response from slave
    EUSCI_B_I2C_masterReceiveStart(I2C_0_BASE);
    while (EUSCI_B_I2C_isBusBusy(I2C_0_BASE));
    EUSCI_B_I2C_disableInterrupt(I2C_0_BASE,
                EUSCI_B_I2C_RECEIVE_INTERRUPT0 |\
                EUSCI_B_I2C_STOP_INTERRUPT );

    P1OUT &= ~BIT0;
    return I2C_0_rxCnt;
}

void run(void)
{
    I2C_0_readCmd(0x0B, 0x02);
    __no_operation();
    __delay_cycles(1000000);
}

void main(void)
{
    WDTCTL = WDTPW | WDTHOLD;
    __enable_interrupt();
    setup();
    while(1)
    {
        run();
    }
}

#pragma vector=USCI_B0_VECTOR
__interrupt void I2C_0_ISR(void)
{
    uint8_t data;

    P1OUT |= BIT1;
    switch(__even_in_range(UCB0IV,0x1E))
    {
        case 0x00: break;       // Vector 0: No interrupts break;
        case 0x02: break;       // Vector 2: ALIFG break;
        case 0x04: break;       // Vector 4: NACKIFG break;
        case 0x06: break;       // Vector 6: STT IFG break;
        case 0x08:
            P1OUT &= ~BIT5;
            break;       // Vector 8: STPIFG break;
        case 0x0a: break;       // Vector 10: RXIFG3 break;
        case 0x0c: break;       // Vector 14: TXIFG3 break;
        case 0x0e: break;       // Vector 16: RXIFG2 break;
        case 0x10: break;       // Vector 18: TXIFG2 break;
        case 0x12: break;       // Vector 20: RXIFG1 break;
        case 0x14: break;       // Vector 22: TXIFG1 break;
        case 0x16:              // Vector 24: RXIFG0 break;
            // Receive byte
            data = EUSCI_B_I2C_masterReceiveMultiByteNext(I2C_0_BASE);

            // If this is the first byte (RX Length Invalid), then save the length to read
            // and reset the receive counter to 0
            if (I2C_0_rxBytesRemaining == 0x00)
            {
                I2C_0_rxBytesRemaining = data;
                if (I2C_0_rxBytesRemaining > I2C_RECEIVE_BUFFER_SIZE)
                {
                    I2C_0_rxBytesRemaining = I2C_RECEIVE_BUFFER_SIZE;
                }
                I2C_0_rxCnt = 0;
            }

            // If this is not the first byte, append the response to the RX
            // buffer
            else
            {
                I2C_0_rxBuffer[I2C_0_rxCnt++] = data;
                I2C_0_rxBytesRemaining--;
            }

            // Send NACK and STOP on last byte coming in
            if (I2C_0_rxBytesRemaining == 1)
            {
                P1OUT &= ~BIT4;
                EUSCI_B_I2C_masterReceiveMultiByteStop(I2C_0_BASE);
            }
            break;
        case 0x18: break;       // Vector 26: TXIFG0 break;
        case 0x1a: break;       // Vector 28: BCNTIFG break;
        case 0x1c: break;       // Vector 30: clock low timeout break;
        case 0x1e: break;       // Vector 32: 9th bit break;
        default: break;
    }

    P1OUT &= ~BIT1;
}


I got this code from Walter in the "MSP430F5329: How do you send a NAK in I2C SMBus Protocol

post. 

I thought I understood it and used it to write my code. I was not getting any SDA or SCL pin movement in my code. So I decided to start with Walter's "working code" and slowly migrate to my application. 

In the main routine

void main(void)
{
    WDTCTL = WDTPW | WDTHOLD;
    __enable_interrupt();
    setup();
    while(1)
    {
        run();
    }
}

I compile no warnings or errors. 

When I single step it appears to go out of control just after the __enable_Interrupt(); when I try to step into the setup(); . 

The Disassembly looks like a valid call to #setup

But it jumped to 00C400 __program_start



Why would it do that?

Is this a watchdog timer? Or another interrupt not handled? 

I am confused. I am using the MSP-EXP430FR2433 with the IAR compiler. 

Thanks,

Kip

  • In the demo code from the MSP-EXP430FR2433 they use this to stop the Watchdog Timer.

    /* Halt the watchdog timer */
    WDT_A_hold(WDT_A_BASE);

    I put that in before the __enable_interrupt(); and commented out //WDTCTL = WDTPW | WDTHOLD;

    And the single step into setup(): never came back. I could not see where it went.
  • void main(void)
    {
        //WDTCTL = WDTPW | WDTHOLD;
        /* Halt the watchdog timer */
        WDT_A_hold(WDT_A_BASE);
        setup();
        __enable_interrupt();
        
        while(1)
        {
            run();
        }
    }

    I modified the main to put the enable interrupts after the setup();

    I was able to get through the setup, but it never returned from the single step into run();

    I am guessing some interrupt is firing that is not handled. What interrupts are on by default?

    Kip

  • Hi Kip,

    I'll try this with IAR.  I was building with CCS on my side.  CCS has a trap for interrupt requests without defined handlers; I am not sure if IAR does.  In either case I should have seen it on my side as well because I would end up in a CPU trap.

    Walter

  • I was able to run successfully in IAR and get to line 86 using the code as-is with no strange issues.  From your explanation, I am assuming that on your hardware you don't  get this far?  Do you have anything else connected to the LaunchPad?  In setup I configur GPIO pins as outputs; perhaps this is conflicting with some other wiring and creating some other issue.

  • Well heck.

    The only thing I had hooked to the board was the SDA, SCL, and Ground to my board with the MSP430F5329. So I disconnected the cable, and now there is only the USB cable connected to the MSP-EXP430FR2433.

    Same issue.

    I was looking at the IDE and the icons for Force Single Stepping, Enable/Disable GIE bit, Force RTS/NMI and Clock Control are all flashing when it stops responding.
  •  I had cheated and still had other files in my project and had used a #if 0 and #endif in all the other code in the main.c outside your code.

    So I removed all the other files from the project and all the other lines from main.c. and still the same issue.

    So I did the exact same thing it appears you did. I set a breakpoint at run();  and at the first line in the run subroutine.

    When I said go the disassembly stopped at __program_start:

  • Just trying to cover all my bases. I had two debuggers connected to my computer. (Windows 10) and the workspace knew this one was at COM4 and the other was at COM7.

    Disconnected the other one, and hit factory settings on the Options for the project.
    No difference. Same problem.

    I am just at a loss here as to what to try next.
  • I tried one last thing.

    I unplugged the MSP-EXP430FR2433 from the USB port on my computer, and plugged it in again.

    Now it is working.

    So somehow it is not getting reset from the debugger the same as if you cycled power.
  • Latest update.

    I connected the e MSP-EXP430FR2433 to my board with the MSP430F5329 via I2C.

    I set the speed to 100 kBPS, slave address to 0x16, and the command 0x20 which is my first SMBUS Block Read command, and it worked!

    Now to test the code more thoroughly. Thank you for all your help.

    Kip

**Attention** This is a public forum