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.
I am running a modified version of the eusci_b_i2c_ex3_masterTxMultiple.
When I call the EUSCI_B_I2C_masterSendMultiByteStart, it is getting hung up at the "Poll for transmit interrupt flag"
Any ideas what could be causing this?
The code works sometimes. I have a logic analyzer, and am able to see the bytes of data being sent over the I2C bus.
Code:
/* --COPYRIGHT--,BSD * Copyright (c) 2017, Texas Instruments Incorporated * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --/COPYRIGHT--*/ //****************************************************************************** // //! This example shows how to configure the I2C module as a master for //! multi byte transmission in interrupt driven mode. The address of the slave //! module is set in this example. //! //! Demo - EUSCI_B0 I2C Master TX multiple bytes to MSP430 Slave //! //! Description: This demo connects two MSP430's via the I2C bus. The master //! transmits to the slave. This is the MASTER CODE. It cntinuously //! transmits an array of data and demonstrates how to implement an I2C //! master transmitter sending multiple bytes using the USCI_B0 TX interrupt. //! ACLK = n/a, MCLK = SMCLK = BRCLK = default DCO = ~1MHz //! //! /|\ /|\ //! MSP430FR2xx_4xx Board 10k 10k MSP430FR2xx_4xx Board //! slave | | master //! ----------------- | | ----------------- //! | UCB0SDA|<-|----+->|UCB0SDA | //! | | | | | //! | | | | | //! | UCB0SCL|<-+------>|UCB0SCL | //! | | | | //! //! This example uses the following peripherals and I/O signals. You must //! review these and change as needed for your own board: //! - I2C peripheral //! - GPIO Port peripheral (for I2C pins) //! - SCL //! - SDA //! //! This example uses the following interrupt handlers. To use this example //! in your own application you must add these interrupt handlers to your //! vector table. //! - USCI_B0_VECTOR. // //****************************************************************************** #include "driverlib.h" #include "Board.h" //***************************************************************************** // //Set the address for slave module. This is a 7-bit address sent in the //following format: //[A6:A5:A4:A3:A2:A1:A0:RS] // //A zero in the "RS" position of the first byte means that the master //transmits (sends) data to the selected slave, and a one in this position //means that the master receives data from the slave. // //***************************************************************************** #define SLAVE_ADDRESS 0x77 //***************************************************************************** // //Target frequency for SMCLK in kHz // //***************************************************************************** #define CS_SMCLK_DESIRED_FREQUENCY_IN_KHZ 1000 //***************************************************************************** // //SMCLK/FLLRef Ratio // //***************************************************************************** #define CS_SMCLK_FLLREF_RATIO 30 // Pointer to TX data uint8_t TXData[] = {0x06, 0x00, 0x02, 0xFF, 0x02, 0x00}; int i = 0; uint8_t TXByteCtr; void main(void) { WDT_A_hold(WDT_A_BASE); //Set DCO FLL reference = REFO CS_initClockSignal( CS_FLLREF, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1 ); //Set Ratio and Desired MCLK Frequency and initialize DCO CS_initFLLSettle( CS_SMCLK_DESIRED_FREQUENCY_IN_KHZ, CS_SMCLK_FLLREF_RATIO ); //Set ACLK = VLO with frequency divider of 1 CS_initClockSignal( CS_ACLK, CS_VLOCLK_SELECT, CS_CLOCK_DIVIDER_1 ); //Set SMCLK = DCO with frequency divider of 1 CS_initClockSignal( CS_SMCLK, CS_DCOCLKDIV_SELECT, CS_CLOCK_DIVIDER_1 ); //Set MCLK = DCO with frequency divider of 1 CS_initClockSignal( CS_MCLK, CS_DCOCLKDIV_SELECT, CS_CLOCK_DIVIDER_1 ); // Configure Pins for I2C GPIO_setAsPeripheralModuleFunctionInputPin( GPIO_PORT_UCB0SCL, GPIO_PIN_UCB0SCL, GPIO_FUNCTION_UCB0SCL ); GPIO_setAsPeripheralModuleFunctionInputPin( GPIO_PORT_UCB0SDA, GPIO_PIN_UCB0SDA, GPIO_FUNCTION_UCB0SDA ); /* * Disable the GPIO power-on default high-impedance mode to activate * previously configured port settings */ PMM_unlockLPM5(); EUSCI_B_I2C_initMasterParam param = {0}; param.selectClockSource = EUSCI_B_I2C_CLOCKSOURCE_SMCLK; param.i2cClk = CS_getSMCLK(); param.dataRate = EUSCI_B_I2C_SET_DATA_RATE_400KBPS; param.byteCounterThreshold = 0; param.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP; EUSCI_B_I2C_initMaster(EUSCI_B0_BASE, ¶m); //Specify slave address EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE, SLAVE_ADDRESS ); //Set Master in receive mode EUSCI_B_I2C_setMode(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_MODE ); //Enable I2C Module to start operations EUSCI_B_I2C_enable(EUSCI_B0_BASE); EUSCI_B_I2C_clearInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0 + EUSCI_B_I2C_NAK_INTERRUPT ); //Enable master Receive interrupt EUSCI_B_I2C_enableInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0 + EUSCI_B_I2C_NAK_INTERRUPT ); while (EUSCI_B_I2C_SENDING_STOP == EUSCI_B_I2C_masterIsStopSent(EUSCI_B0_BASE)); EUSCI_B_I2C_masterSendMultiByteStart(EUSCI_B0_BASE, TXData[i]); while(1) { __delay_cycles(5000); // Delay between transmissions TXByteCtr = 1; // Load TX byte counter if(i == 4) i = 2; while (EUSCI_B_I2C_SENDING_STOP == EUSCI_B_I2C_masterIsStopSent(EUSCI_B0_BASE)); EUSCI_B_I2C_masterSendMultiByteStart(EUSCI_B0_BASE, TXData[i]); __bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts // Remain in LPM0 until all data // is TX'd // Increment data byte } } //------------------------------------------------------------------------------ // The USCIAB0TX_ISR is structured such that it can be used to transmit any // number of bytes by pre-loading TXByteCtr with the byte count. Also, TXData // points to the next byte to transmit. //------------------------------------------------------------------------------ #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector=USCI_B0_VECTOR __interrupt #elif defined(__GNUC__) __attribute__((interrupt(USCI_B0_VECTOR))) #endif void USCIB0_ISR(void) { switch(__even_in_range(UCB0IV, USCI_I2C_UCBIT9IFG)) { case USCI_NONE: // No interrupts break; break; case USCI_I2C_UCALIFG: // Arbitration lost break; case USCI_I2C_UCNACKIFG: // NAK received (master only) //resend start if NACK EUSCI_B_I2C_masterSendStart(EUSCI_B0_BASE); break; case USCI_I2C_UCTXIFG0: // TXIFG0 // Check TX byte counter if (TXByteCtr) { i++; EUSCI_B_I2C_masterSendMultiByteNext(EUSCI_B0_BASE, TXData[i]); // Decrement TX byte counter TXByteCtr--; } else { EUSCI_B_I2C_masterSendMultiByteStop(EUSCI_B0_BASE); // Exit LPM0 __bic_SR_register_on_exit(CPUOFF); } break; default: break; } }
I am not a fan of spin loops like that. For I2C whenever I need to wait like that I always include a timeout. Returning an error code rather than getting hung up.
In this case, the fault appears to be polling TXIFG after enabling the transmit interrupt. That never works well.
**Attention** This is a public forum