Tool/software: TI-RTOS
Using TIRTOS 2.16.01.04 and CCS v8.
I'm trying to implement an I2C Slave on I2C7, but I'm not getting the expected interrupts, and no ACK is generated for data bytes.
I'm stuck and don't find the cause. I know mixing RTOS and Driverlib is not the best way to do but I haven't found anything suitable in the RTOS abstraction layer.
Best Regards
Frank-Christian Kruegel
My Code:
/* * I2C_Slaves.c */ #include <stdint.h> #include <stdbool.h> #include <xdc/std.h> #include <xdc/runtime/Error.h> #include <xdc/runtime/System.h> #include <ti/sysbios/family/arm/m3/Hwi.h> #include <inc/hw_ints.h> #include <inc/hw_memmap.h> #include <inc/hw_types.h> #include <inc/hw_gpio.h> #include <driverlib/gpio.h> #include <driverlib/i2c.h> #include <driverlib/pin_map.h> #include <driverlib/sysctl.h> #include "I2C_Slaves.h" // I2C Address PCA9536 #define SLAVE_ADDRESS 0x41 #define NUM_REGISTERS 4 /* * Emulates an PCA9536/9538 Port Expander * Register 0 contains Boot Data and is read only. * Register 1...3 are read-write, but the content * is ignored (different from real chip) */ // Registers static volatile unsigned char PCA_Regs[NUM_REGISTERS]; static volatile unsigned char PCA_RegPtr; static volatile _Bool PCA_RegFlag; Error_Block eb; Hwi_Handle hInt; Hwi_Params IntParams; static void CommonI2CSlaveIntHandler(UArg m) { uint32_t IntStatus = I2CSlaveIntStatusEx(I2C7_BASE, true); uint32_t UiStatus = I2CSlaveStatus(I2C7_BASE); I2CSlaveIntClear(I2C7_BASE); if (IntStatus & I2C_SLAVE_INT_START) { PCA_RegFlag = true; } if (IntStatus & I2C_SLAVE_INT_DATA) { if (UiStatus & I2C_SLAVE_ACT_TREQ) { // reads register. PCA_RegFlag doesn't care here I2CSlaveDataPut(I2C7_BASE, PCA_Regs[PCA_RegPtr]); PCA_RegPtr++; if (PCA_RegPtr >= NUM_REGISTERS) { PCA_RegPtr = 0; } } if (UiStatus & I2C_SLAVE_ACT_RREQ) { unsigned char c = I2CSlaveDataGet(I2C7_BASE); if (PCA_RegFlag) // Set Register Number { PCA_RegFlag = false; PCA_RegPtr = c; if (PCA_RegPtr >= NUM_REGISTERS) { PCA_RegPtr = 0; } } else // write register data and autoincrement register number { if (PCA_RegPtr) { PCA_Regs[PCA_RegPtr] = c; } PCA_RegPtr++; if (PCA_RegPtr >= NUM_REGISTERS) { PCA_RegPtr = 0; } } } } } void Init_I2C_Slaves(void) { PCA_RegPtr = 0; PCA_RegFlag = true; for (int j = 1; j < NUM_REGISTERS; j++) { PCA_Regs[j] = 0; } Error_init(&eb); Hwi_Params_init(&IntParams); IntParams.arg = 0; IntParams.enableInt = true; IntParams.eventId = -1; IntParams.priority = -1; hInt = Hwi_create(INT_I2C7, CommonI2CSlaveIntHandler, &IntParams, &eb); /* I2C7 Init */ /* Enable the peripheral */ SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C7); /* Configure the appropriate pins to be I2C instead of GPIO. */ GPIOPinConfigure(GPIO_PD0_I2C7SCL); GPIOPinConfigure(GPIO_PD1_I2C7SDA); GPIOPinTypeI2CSCL(GPIO_PORTD_BASE, GPIO_PIN_0); GPIOPinTypeI2C(GPIO_PORTD_BASE, GPIO_PIN_1); I2CSlaveIntEnableEx(I2C7_BASE, I2C_SLAVE_INT_DATA | I2C_SLAVE_INT_START); I2CSlaveEnable(I2C7_BASE); I2CSlaveACKOverride(I2C7_BASE, true); I2CSlaveACKValueSet(I2C7_BASE, true); I2CSlaveInit(I2C7_BASE, SLAVE_ADDRESS); Hwi_enableInterrupt(INT_I2C7); }
Logic Analyzer Output: