Hi Folks,
I'm using an LM4F120H Evaluation kit board. Trying to do a REAL simple test of the I2C bus, using I2C0, with Master and slave in loopback mode. Send a single character and print it to a console is the aim of the game. I have two issues: 1) The Master is always busy if I perform the while (I2CMasterBusy(ulBase)) { } test and 2) I do not get the correct data (all zeroes). Attached is the following. They are heavily based off the example loopback code, plus interesting and useful diversions which I really wish to heck had been shoved more in front of my face, like the golden nugget of GPIOPinTypeI2CSCL() which only exists in these forums and not even on the datasheet.
I also am making the following assumptions (which may very well be where the problem lies!):
1) SLAVE_ADDRESS 0x40 is valid. I know about the 7 bit address + R/W bit caveat. This should be "1000 000x" where x = 0 to read and 1 to write if its bit-shifted.
2) Using ROM_ variant of a function is equivalent to its API equivalent, only that the API program code has been hardcoded and the ROM_ is an alias to that physical ROM memory to save space for application code in flash.
3) I use both the master and slave of the same module to do loopback
4) GPIOPinTypeI2CSCL() looks like an afterthought, but even the weak pullup should be strong enough for internal usage.
Thanks in advance for your help, as I'm only just a beginner really.
Rik
1) Function to perform single byte write:
unsigned long I2CMasterTxSingle(unsigned long ulBase,unsigned long ulSlaveAddr,
unsigned char *ucDataTx) {
//1. Set the slave address to talk to and the receive parameter = false (i.e. send)
I2CMasterSlaveAddrSet(ulBase, ulSlaveAddr, false);
//2. Wait until bus is not busy
//DEBUG: UARTwrite("Waiting for bus", 15);
while (I2CMasterBusBusy(ulBase)) {
}
//3. Place the data to be sent in the data register
I2CMasterDataPut(ulBase, *ucDataTx);
//4. Initiate send of data from the master.
I2CMasterControl(ulBase, I2C_MASTER_CMD_SINGLE_SEND);
//5. Wait until master is not busy
//DEBUG: UARTwrite("Waiting for master", 18);
while (I2CMasterBusy(ulBase)) { //Why does master not go to idle?
}
//5. Return any errors
return (I2CMasterErr(ulBase));
}
2) Test Environment for function
int32_t Cmd_I2CMasterTxSgl(int16_t argc, char*argv[]) {
unsigned long ulDataRx[NUM_I2C_DATA];
unsigned long ulindex;
unsigned long ulBase = I2C0_MASTER_BASE;
unsigned long ulClock = SysCtlClockGet();
/*Announce start of test*/
UARTprintf("Sending packets individually:\n\r");
/*Initialize the receive buffer.*/
for (ulindex = 0; ulindex < NUM_I2C_DATA; ulindex++) {
ulDataRx[ulindex] = 0;
}
/*Indicate the direction of the data.*/
UARTprintf("Transferring from: Master -> Slave\n");
/*Send 3 pieces of I2C data from the master to the slave.*/
for (ulindex = 0; ulindex < NUM_I2C_DATA; ulindex++) {
/*Display the data that the I2C0 master is transferring.*/
UARTprintf(" Sending: '%c' . . . ", ucDataTx[ulindex]);
/*Place the data to be sent in the data register*/
I2CMasterTxSingle(I2C0_MASTER_BASE,SLAVE_ADDRESS, &ucDataTx[ulindex]);
/*Wait until the slave has received and acknowledged the data.*/
while (!(I2CSlaveStatus(ulBase) & I2C_SCSR_RREQ)) {
}
/*Read the data from the slave.*/
ulDataRx[ulindex] = I2CSlaveDataGet(I2C0_SLAVE_BASE);
/*Display the data that the slave has received.*/
UARTprintf("Received: '%u'\n", ulDataRx[ulindex]); //Why is data bad?
SysCtlDelay(ulClock / 30000);
}
/*Tell the user that the test is done.*/
UARTprintf("\nDone.\n\n");
/*Return no errors*/
return (0);
}
3) Setup Function
/*Initialize both the physical module and the functionality*/
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_I2C0);
ROM_GPIOPinConfigure(GPIO_PB2_I2C0SCL);
ROM_GPIOPinConfigure(GPIO_PB3_I2C0SDA);
GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2); // I2CSCL special function for M4F, select M3
ROM_GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
/* Enable and initialize the I2C0 master module. Use the system clock for
the I2C0 module. The last parameter sets the I2C data transfer rate.
If false the data rate is set to 100kbps and if true the data rate will
be set to 400kbps. For this example we will use a data rate of 100kbps.*/
ROM_I2CMasterInitExpClk(I2C0_MASTER_BASE, SysCtlClockGet(), bFast);
HWREG(ulBase + I2C_O_MCR) |= 0x01;
/* Enable the I2C0 slave module. This module is enabled only for testing
purposes. It does not need to be enabled for proper operation of the
I2Cx master module.*/
ROM_I2CSlaveEnable(ulBase);
/* Set the slave address to SLAVE_ADDRESS. In loopback mode, it's an
arbitrary 7-bit number (set in a macro above) that is sent to the
I2CMasterSlaveAddrSet function.*/
ROM_I2CSlaveInit(ulBase, ulSlaveAddr);