Part Number: TM4C123GH6PM
Hello All,
I have been trying to get dual slave address operation on TM4C123GH6PM without success. I can read and write multiple bytes to main address, but not to slave address.
For slave address, it will not return a ACK, resulting in an error on my master side, which is an RPI. That being said, I have been able to transfer multiple bytes from the RaspberryPI side for the main address.
Here is my simplified code:
#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_gpio.h"
#include "inc/hw_i2c.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/i2c.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#define SLAVE_ADDRESS 0x3C
#define SECONDARY_SLAVE_ADDRESS 0x3D
volatile uint8_t rxRegister = 0x00;
volatile uint8_t txRegister = 0x00;
volatile uint8_t rxBuffer[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
volatile uint8_t txBuffer[6] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
volatile uint8_t rxBufferIdx = 0;
volatile uint8_t txBufferIdx = 0;
volatile bool g_i2c_ready = false;
void I2C0SlaveIntHandler(void) {
// clear data interrupt
HWREG(I2C0_BASE + I2C_O_SICR) = I2C_SICR_DATAIC;
switch(I2CSlaveStatus(I2C0_BASE)) {
case I2C_SLAVE_ACT_NONE:
break;
case I2C_SLAVE_ACT_RREQ_FBR:
rxRegister = I2CSlaveDataGet(I2C0_BASE);
break;
case I2C_SLAVE_ACT_RREQ:
rxBuffer[rxBufferIdx++] = I2CSlaveDataGet(I2C0_BASE);
break;
case I2C_SLAVE_ACT_TREQ:
I2CSlaveDataPut(I2C0_BASE, txBuffer[txBufferIdx++]);
break;
case I2C_SLAVE_ACT_OWN2SEL:
break;
default:
break;
}
g_i2c_ready = true;
}
int main(void) {
// init device
SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN);
// pin config for i2c0
SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
GPIOPinConfigure(GPIO_PB2_I2C0SCL);
GPIOPinConfigure(GPIO_PB3_I2C0SDA);
GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
HWREG(GPIO_PORTB_BASE + GPIO_O_PUR) |= (GPIO_PIN_3 | GPIO_PIN_2);
IntEnable(INT_I2C0);
I2CSlaveIntEnableEx(I2C0_BASE, I2C_SLAVE_INT_DATA);
HWREG(I2C0_BASE + I2C_O_SICR) = I2C_SICR_DATAIC;
I2CSlaveEnable(I2C0_BASE);
I2CSlaveInit(I2C0_BASE, SLAVE_ADDRESS);
I2CSlaveAddressSet(I2C0_BASE, 1, SECONDARY_SLAVE_ADDRESS);
while(1){
if(g_i2c_ready) {
g_i2c_ready = false;
}
}
}
I am also able to detect start and stop conditions, where I reset my rxBufferIdx, and txBufferIdx, but these parts are removed for readability.
To enable slave mode, basically I call the following functions:
I2CSlaveEnable(I2C0_BASE);
I2CSlaveInit(I2C0_BASE, SLAVE_ADDRESS);
I2CSlaveAddressSet(I2C0_BASE, 1, SECONDARY_SLAVE_ADDRESS);
Another peculiar observation is that if the secondary slave address is set, the interrupt handler will not work for the first request, but the second. if it is commented out, it will work as expected.
I have tried various debug methods to detect I2C_SLAVE_ACT_OWN2SEL inside the interrupt handler, without any success.
Any ideas, help, recommendations greatly appreciated.
Best Regards,
Can