Hi,
I'm trying to bring up the I2C peripheral on an MSP430FG6426 in slave mode (BeagleBoneBlack - BBB is master).
What I know:
1. I can used "i2cdetect -y 1" on BBB to detect MSP and other devices on the bus.
2. I can transfer data on the same I2C bus from another device to the BBB.
3. When I execute the read I get the chars below. "`abcdpqrst" are the chars I'm expecting and I get exactly 64 bytes again as expected.
Address: 0x55 rx_len: 64 Data: `abcdpqrst`abcdpqrst`abcdpqrst`abcdpqrst`abcdpqrst`abcdpqrst`abc omap_i2c 4802a000.i2c: controller timed out Error: Connection timed out (os error 110) omap_i2c 4802a000.i2c: timeout waiting for bus ready Error: Connection timed out (os error 110)
4. From the scope I can clearly see that both SCL & SDA are pulled low. The moment I reset the MSP SCL & SDA returns to 3.29V, indicating that in fact the MSP is holding it low.
5. I'm using a slightly modified driverlib example code (usci_b_i2c_ex4_slaveTxMultiple.c) with TI compiler v21.6 LTS. Biggest modifications: 1. it is not alone (while loop is not here), 2. I'm using USCI_B1. For clarity here is the whole code
#define SLAVE_ADDRESS 0x55 #define TXLENGTH 0x09 uint8_t transmitData[] = { 0x60, 0x61, 0x62, 0x63, 0x64, 0x70, 0x71, 0x72, 0x73, 0x74}; uint8_t *transmitDataPointer; uint8_t transmitLength = TXLENGTH; //38.3.4.1.1 I2C Slave Transmitter Mode void i2c_init(void) { //Assign I2C pins to USCI_B1 GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P8, GPIO_PIN5 + GPIO_PIN6); //Initialize I2C as a slave device USCI_B_I2C_initSlave(USCI_B1_BASE, SLAVE_ADDRESS); //Set in transmit mode USCI_B_I2C_setMode(USCI_B1_BASE, USCI_B_I2C_TRANSMIT_MODE); //Enable I2C Module to start operations USCI_B_I2C_enable(USCI_B1_BASE); //Enable master transmit interrupt USCI_B_I2C_clearInterrupt(USCI_B1_BASE, USCI_B_I2C_TRANSMIT_INTERRUPT + USCI_B_I2C_STOP_INTERRUPT); USCI_B_I2C_enableInterrupt(USCI_B1_BASE, USCI_B_I2C_TRANSMIT_INTERRUPT + USCI_B_I2C_STOP_INTERRUPT); transmitDataPointer = transmitData; transmitLength = TXLENGTH; //Enter low power mode 0 with interrupts enabled. // __bis_SR_register(LPM0_bits + GIE); // __no_operation(); } //****************************************************************************** // //This is the USCI_B1 interrupt vector service routine. // //****************************************************************************** #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector=USCI_B1_VECTOR __interrupt #elif defined(__GNUC__) __attribute__((interrupt(USCI_B1_VECTOR))) #endif void USCI_B1_ISR(void) { uint16_t iv = UCB1IV; USCI_A_UART_transmitData(USCI_A0_BASE, iv + 0x61); switch (__even_in_range(iv, 12)) { case USCI_I2C_UCSTPIFG: //Exit LPM0 if data was transmitted __bic_SR_register_on_exit(LPM0_bits); break; case USCI_I2C_UCTXIFG: //Transmit data //if (transmitLength > 0x00) { USCI_B_I2C_slavePutData(USCI_B1_BASE, *transmitDataPointer++); //transmitLength--; if (transmitDataPointer >= (transmitData+10)) { transmitDataPointer = transmitData; } } break; default: break; } }
Questions:
1. Why are both the SCL & SDA pulled low?
2. Separately how can I indicate to master that I have nothing to send? Do I just send 0x0 or 0x20 and on the other end that should mean I should not be asking anymore?
3. Is there a way to force MSP to release I2C bus?