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.

EK-TM4C1294XL: I2C FIFO triggering doesn't cause an interrupt

Part Number: EK-TM4C1294XL
Other Parts Discussed in Thread: TM4C1294NCPDT

Hi guys. I am doing a project with I2C, and I have been unable to trigger an interrupt based on how full the FIFO is. For instance, I want to trigger an interrupt when the Master TX hardware FIFO is half full. So I have set the proper bit to a value of 4 and unmasked bit number 8 in the I2CMIMR register. But no interrupt occurs. I CAN trigger an interrupt if I unmask bit number 10, for instance, when I empty the FIFO. SO interrupts are working.....but the way I understand it to work for the triggering must be wrong. Anyway, I am a FIFO half full kind of guy, so I am sure there is a solution. Data is also being sent just fine from the TX FIFO of I2C0 to the RX FIFO of I2C3. Everything is working how I want EXCEPT triggering an interrupt when I want to. Relevant code using built in API:

I2CMasterInitExpClk(I2C0_BASE, ui32SysClock, false);

I2CSlaveInit(I2C3_BASE, SLAVE_ADDRESS);

I2CMasterSlaveAddrSet(I2C0_BASE, SLAVE_ADDRESS, false);

uint32_t pui32DataTx[8] = {'F', 'I', 'F', 'O','L', 'O','V', 'E'};

I2CTxFIFOConfigSet(I2C0_BASE, (I2C_FIFO_CFG_TX_MASTER|I2C_FIFO_CFG_TX_TRIG_4));

I2CRxFIFOConfigSet(I2C3_BASE,(I2C_FIFO_CFG_RX_SLAVE|I2C_FIFO_CFG_RX_TRIG_4));

I2CSlaveFIFOEnable(I2C3_BASE,I2C_SLAVE_RX_FIFO_ENABLE);

IntEnable(INT_I2C0);
I2CMasterIntEnable(I2C0_BASE);
I2CMasterIntEnableEx(I2C0_BASE, I2C_SLAVE_INT_RX_FIFO_REQ);

IntEnable(INT_I2C3);
I2CSlaveIntEnable(I2C3_BASE);
I2CSlaveIntEnableEx(I2C3_BASE, I2C_SLAVE_INT_RX_FIFO_REQ);

I2CFIFODataPut(I2C0_BASE, pui32DataTx[0]); 
I2CFIFODataPut(I2C0_BASE, pui32DataTx[1]); 
I2CFIFODataPut(I2C0_BASE, pui32DataTx[2]);
I2CFIFODataPut(I2C0_BASE, pui32DataTx[3]);  //*************************I want to trigger an interrupt here....when the TX FIFO is half full
I2CFIFODataPut(I2C0_BASE, pui32DataTx[4]);
I2CFIFODataPut(I2C0_BASE, pui32DataTx[5]);
I2CFIFODataPut(I2C0_BASE, pui32DataTx[6]);
I2CFIFODataPut(I2C0_BASE, pui32DataTx[7]);

I2CMasterBurstLengthSet(I2C0_BASE, 0x04);

I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_FIFO_BURST_SEND_START); //send the first 4 bytes to the RX FIFO

//******************************here the interrupt is triggered for I2C3 RX. This is working fine. the ISR just puts the data into a global data array and sets a flag to true

//wait for ISR to complete
while(!g_bIntFlag);
g_bIntFlag = false;

I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_FIFO_BURST_SEND_CONT);  //send the last 4 bytes to the RX FIFO

//wait for ISR to complete

while(!g_bIntFlag);
g_bIntFlag = false;

I2CTxFIFOFlush(I2C0_BASE);

I2CRxFIFOFlush(I2C3_BASE);

Am I missing something important or is there some other problem with this feature?? 

Thanks!

  • Hello Jacob,

    Small little code error I think:

    IntEnable(INT_I2C0);
    I2CMasterIntEnable(I2C0_BASE);
    I2CMasterIntEnableEx(I2C0_BASE, I2C_SLAVE_INT_RX_FIFO_REQ);

    I believe you want this for I2CMasterIntEnableEx

    I2C_MASTER_INT_TX_FIFO_REQ

    Rather than what you have. 

  • Hello Ralph. Thanks for the response. Of course, you are correct. It's a typo on my part. I have tried so many different copy and paste maneuvers that I made a small mistake when bringing the code here. Apologies.

    Anyway, I made the correction and it still doesn't work. After putting all 8 bytes in the TX FIFO the Master Raw interrupt status register is still 0x00000000, so there is nothing for me to unmask to make this work. I have also written my own I2C driver for this microcontroller and every function works except this one. So I came back to the API to try and get it to work, and it still doesn't work even with the API functions. 

    I don't get any change in the RIS until this line:

    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_FIFO_BURST_SEND_START); //send the first 4 bytes to the RX FIFO

    At this point I get interrupts for both I2C0 and I2C3 as I expect. 

    after the master control command the I2C0(master) raw interrupt status reads:

    0x00000021

    At no point does bit number 8(TXRIS) bit ever become active, which is what should happen. In the data sheet for the I2CMRIS, bit number 8 says:

    bit 8 TXRIS

    Transmit Request Raw Interrupt Status
    Value Description
    0                                      No interrupt

    1                                      The trigger level for the TX FIFO has been reached and more
                                            data is needed to complete the burst. Thus, a TX FIFO request
                                            interrupt is pending.


    According to this I should be able to have an interrupt, when the TXFIFO hits my desired fill level, which is 4 bytes.

    Any help is appreciated here. 

  • Hello Jacob,

    Have you checked on the bus that all your bytes are being sent?

    The first flag you got is for start bit if I am reading right.

    Did you put a breakpoint at I2CFIFODataPut(I2C0_BASE, pui32DataTx[4]); in order to assess this?

    I can try and recreate on my end in a little bit here and see what I observe.

    Also you have pull-ups on the LaunchPad right?

  • Hello hello. Yes I have 4.7k pull up resistors on the SCL and SDA.

    Also all bits are being sent. And the RX FIFO is receiving all of them with no problem.

    Will it help if I copy and paste the entire program???

    Thanks.

  • Hi Jacob,

    Yeah that would be helpful so I can compile it and test quickly.

  • //main.c

    //*****************************************************************************
    //
    // 8 byte write from i2c0 to i2c3
    //
    //
    //*****************************************************************************
    
    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_i2c.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 "driverlib/uart.h"
    #include "utils/uartstdio.h"
    #include "inc/tm4c1294ncpdt.h"
    #include "driverlib/interrupt.h"
    volatile bool g_bIntFlag = false;
    
    #define SLAVE_ADDRESS 0x76
    
    //*****************************************************************************
    //
    // This function sets up UART0 to be used for a console to display information
    // as the example is running.
    //
    //*****************************************************************************
    void
    InitConsole(void)
    {
        //
        // Enable GPIO port A which is used for UART0 pins.
        // TODO: change this to whichever GPIO port you are using.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
        //
        // Configure the pin muxing for UART0 functions on port A0 and A1.
        // This step is not necessary if your part does not support pin muxing.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinConfigure(GPIO_PA0_U0RX);
        GPIOPinConfigure(GPIO_PA1_U0TX);
    
        //
        // Enable UART0 so that we can configure the clock.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    
        //
        // Use the internal 16MHz oscillator as the UART clock source.
        //
        UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
    
        //
        // Select the alternate (UART) function for these pins.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        //
        // Initialize the UART for console I/O.
        //
        UARTStdioConfig(0, 115200, 16000000);
    }
    
    //*****************************************************************************
    //
    // Configure the I2C0 master and slave and connect them using loopback mode.
    //
    //*****************************************************************************
    void
    main(void)
    {
    
        uint32_t ui32SysClock;
    
        uint8_t pui32DataTx[8];
        uint32_t pui32DataRx;
        
    
    
    
        //
        // For this example I2C0 is used with PortB[3:2].  I2C3 is used with portK[5:4]
        //The actual port and
        // pins used may be different on your part, consult the data sheet for
        // more information.
    
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK);
        //
        // Wait for the Peripheral to be ready for programming
        //
        while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOB)
        || !SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOK));
    
        //
             //The I2C0 and I2C3 peripheral must be enabled before use.
    
        SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C3);
        //
        // Configure the pin muxing for I2C0 functions on port B2 and B3.
        // Also for I2C3 on port K4 and K5
        GPIOPinConfigure(GPIO_PB2_I2C0SCL);
        GPIOPinConfigure(GPIO_PB3_I2C0SDA);
        GPIOPinConfigure(GPIO_PK4_I2C3SCL);
        GPIOPinConfigure(GPIO_PK5_I2C3SDA);
    
        //
        // Select the I2C function for these pins.  This function will also
        // configure the GPIO pins pins for I2C operation, setting them to
        // open-drain operation with weak pull-ups.  Consult the data sheet
        // to see which functions are allocated per pin.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
        GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
        GPIOPinTypeI2CSCL(GPIO_PORTK_BASE, GPIO_PIN_4);
        GPIOPinTypeI2C(GPIO_PORTK_BASE, GPIO_PIN_5);
    
    
    
        //
        // Stop the Clock, Reset and Enable I2C Module
        // in Master Function
        //
        SysCtlPeripheralDisable(SYSCTL_PERIPH_I2C0);
        SysCtlPeripheralReset(SYSCTL_PERIPH_I2C0);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
        //
        // Wait for the Peripheral to be ready for programming
        //
        while(!SysCtlPeripheralReady(SYSCTL_PERIPH_I2C0));
    
        //set system clock to run at 120MHz
        ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN |
                                      SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000);
        //
        // 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.
        //
    
        I2CMasterInitExpClk(I2C0_BASE, ui32SysClock, false);
    
    
    
        //
        // Set the slave address to SLAVE_ADDRESS.
        // this function also calls the I2CslaveEnable() function
        // so there is no need to call it again
        //
        I2CSlaveInit(I2C3_BASE, SLAVE_ADDRESS);
    
        //
        // Tell the master module what address it will place on the bus when
        // communicating with the slave.  Set the address to SLAVE_ADDRESS
        // (as set in the slave module).  The receive parameter is set to false
        // which indicates the I2C Master is initiating a writes to the slave.  If
        // true, that would indicate that the I2C Master is initiating reads from
        // the slave.
        //
        I2CMasterSlaveAddrSet(I2C0_BASE, SLAVE_ADDRESS, false);
    
        //
        // Set up the serial console to use for displaying messages.  This is
        // just for this example program and is not needed for I2C operation.
        //
        InitConsole();
    
    
    
        //
        // Display the example setup on the console.
        //
        UARTprintf("I2C transmit and receive Example using FIFO->");
        UARTprintf("\n   Module = I2C0 and I2C3");
        UARTprintf("\n   Mode = Single Send/Receive with FIFO");
        UARTprintf("\n   Rate = 100kbps\n\n");
    
        //
        // Initalize the data to send.
        //
        pui32DataTx[0] = 'F';
        pui32DataTx[1] = 'I';
        pui32DataTx[2] = 'F';
        pui32DataTx[3] = 'O';
        pui32DataTx[4] = 'L';
        pui32DataTx[5] = 'O';
        pui32DataTx[6] = 'V';
        pui32DataTx[7] = 'E';
    
    
    
        //*****************************************************************************************************************
        //set up FIFO
        UARTprintf("Configuring FIFO\n");
        I2CTxFIFOConfigSet(I2C0_BASE, (I2C_FIFO_CFG_TX_MASTER|I2C_FIFO_CFG_TX_TRIG_4));         //Set TX fifo to the master and also triggers at 4 bytes
        I2CRxFIFOConfigSet(I2C3_BASE,(I2C_FIFO_CFG_RX_SLAVE|I2C_FIFO_CFG_RX_TRIG_4));           //Set RX fifo to the master and also triggers at 1 byte
    
        I2CSlaveFIFOEnable(I2C3_BASE,I2C_SLAVE_RX_FIFO_ENABLE);                                 //sets 0x05 in the SCSR register enabling the slave AND the RX FIFO for the slave
    
        //******************************************************************************************************************
        //enable and configure interrupts
        UARTprintf("Configuring Interrupts\n");
        IntEnable(INT_I2C0);
        I2CMasterIntEnable(I2C0_BASE);
        I2CMasterIntEnableEx(I2C0_BASE, I2C_MASTER_INT_TX_FIFO_REQ | I2C_MASTER_INT_DATA);
        IntEnable(INT_I2C3);
        I2CSlaveIntEnable(I2C3_BASE);
        I2CSlaveIntEnableEx(I2C3_BASE, I2C_SLAVE_INT_RX_FIFO_REQ);
        //*******************************************************************************************************************
        
        //add data to TX FIFO
        UARTprintf("Placing 8 bytes in the I2C0 TX FIFO\n", pui32DataTx[0]);
        I2CFIFODataPut(I2C0_BASE, pui32DataTx[0]);                                              //single byte of data added to TX FIFO. trigger is set to 1
        I2CFIFODataPut(I2C0_BASE, pui32DataTx[1]);                                              //single byte of data added to TX FIFO. trigger is set to 1
        I2CFIFODataPut(I2C0_BASE, pui32DataTx[2]);
        I2CFIFODataPut(I2C0_BASE, pui32DataTx[3]);
        I2CFIFODataPut(I2C0_BASE, pui32DataTx[4]);
        I2CFIFODataPut(I2C0_BASE, pui32DataTx[5]);
        I2CFIFODataPut(I2C0_BASE, pui32DataTx[6]);
        I2CFIFODataPut(I2C0_BASE, pui32DataTx[7]);
        pui32DataRx = 0;
        pui32DataRx = I2CFIFOStatus(I2C0_BASE);                                                //check TX FIFO status
        I2CMasterBurstLengthSet(I2C0_BASE, 0x04);                                               //set length of burst to 4 bytes
        
    
    
        UARTprintf("Sending FIFO BURST START command to master\n");
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_FIFO_BURST_SEND_START);                           //command to send a burst of bytes from FIFO
        
    
    
    
        //wait for ISR to complete
                while(!g_bIntFlag);
                g_bIntFlag = false;
               
        UARTprintf("Sending FIFO BURST CONT command to master\n");
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_FIFO_BURST_SEND_CONT);                           //command to send next burst of byte from FIFO
        
    
    
        //wait for ISR to complete
            while(!g_bIntFlag);
            g_bIntFlag = false;
    
    
    
            
        pui32DataRx = I2CFIFOStatus(I2C0_BASE);                                                //check TX FIFO status
        I2CTxFIFOFlush(I2C0_BASE);                                                              //FLUSH TX FIFO -- empties the FIFO
        
    
    
    
    while(1);
    }

    //*****************************************************************************//// 8 byte write from i2c0 to i2c3//////*****************************************************************************
    #include <stdbool.h>#include <stdint.h>#include "inc/hw_i2c.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 "driverlib/uart.h"#include "utils/uartstdio.h"#include "inc/tm4c1294ncpdt.h"#include "driverlib/interrupt.h"volatile bool g_bIntFlag = false;
    #define SLAVE_ADDRESS 0x76
    //*****************************************************************************//// This function sets up UART0 to be used for a console to display information// as the example is running.////*****************************************************************************voidInitConsole(void){    //    // Enable GPIO port A which is used for UART0 pins.    // TODO: change this to whichever GPIO port you are using.    //    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
        //    // Configure the pin muxing for UART0 functions on port A0 and A1.    // This step is not necessary if your part does not support pin muxing.    // TODO: change this to select the port/pin you are using.    //    GPIOPinConfigure(GPIO_PA0_U0RX);    GPIOPinConfigure(GPIO_PA1_U0TX);
        //    // Enable UART0 so that we can configure the clock.    //    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
        //    // Use the internal 16MHz oscillator as the UART clock source.    //    UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
        //    // Select the alternate (UART) function for these pins.    // TODO: change this to select the port/pin you are using.    //    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
        //    // Initialize the UART for console I/O.    //    UARTStdioConfig(0, 115200, 16000000);}
    //*****************************************************************************//// Configure the I2C0 master and slave and connect them using loopback mode.////*****************************************************************************voidmain(void){
        uint32_t ui32SysClock;
        uint8_t pui32DataTx[8];    uint32_t pui32DataRx;    


        //    // For this example I2C0 is used with PortB[3:2].  I2C3 is used with portK[5:4]    //The actual port and    // pins used may be different on your part, consult the data sheet for    // more information.
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK);    //    // Wait for the Peripheral to be ready for programming    //    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOB)    || !SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOK));
        //         //The I2C0 and I2C3 peripheral must be enabled before use.
        SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C3);    //    // Configure the pin muxing for I2C0 functions on port B2 and B3.    // Also for I2C3 on port K4 and K5    GPIOPinConfigure(GPIO_PB2_I2C0SCL);    GPIOPinConfigure(GPIO_PB3_I2C0SDA);    GPIOPinConfigure(GPIO_PK4_I2C3SCL);    GPIOPinConfigure(GPIO_PK5_I2C3SDA);
        //    // Select the I2C function for these pins.  This function will also    // configure the GPIO pins pins for I2C operation, setting them to    // open-drain operation with weak pull-ups.  Consult the data sheet    // to see which functions are allocated per pin.    // TODO: change this to select the port/pin you are using.    //    GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);    GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);    GPIOPinTypeI2CSCL(GPIO_PORTK_BASE, GPIO_PIN_4);    GPIOPinTypeI2C(GPIO_PORTK_BASE, GPIO_PIN_5);


        //    // Stop the Clock, Reset and Enable I2C Module    // in Master Function    //    SysCtlPeripheralDisable(SYSCTL_PERIPH_I2C0);    SysCtlPeripheralReset(SYSCTL_PERIPH_I2C0);    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);    //    // Wait for the Peripheral to be ready for programming    //    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_I2C0));
        //set system clock to run at 120MHz    ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN |                                  SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000);    //    // 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.    //
        I2CMasterInitExpClk(I2C0_BASE, ui32SysClock, false);


        //    // Set the slave address to SLAVE_ADDRESS.    // this function also calls the I2CslaveEnable() function    // so there is no need to call it again    //    I2CSlaveInit(I2C3_BASE, SLAVE_ADDRESS);
        //    // Tell the master module what address it will place on the bus when    // communicating with the slave.  Set the address to SLAVE_ADDRESS    // (as set in the slave module).  The receive parameter is set to false    // which indicates the I2C Master is initiating a writes to the slave.  If    // true, that would indicate that the I2C Master is initiating reads from    // the slave.    //    I2CMasterSlaveAddrSet(I2C0_BASE, SLAVE_ADDRESS, false);
        //    // Set up the serial console to use for displaying messages.  This is    // just for this example program and is not needed for I2C operation.    //    InitConsole();


        //    // Display the example setup on the console.    //    UARTprintf("I2C transmit and receive Example using FIFO->");    UARTprintf("\n   Module = I2C0 and I2C3");    UARTprintf("\n   Mode = Single Send/Receive with FIFO");    UARTprintf("\n   Rate = 100kbps\n\n");
        //    // Initalize the data to send.    //    pui32DataTx[0] = 'F';    pui32DataTx[1] = 'I';    pui32DataTx[2] = 'F';    pui32DataTx[3] = 'O';    pui32DataTx[4] = 'L';    pui32DataTx[5] = 'O';    pui32DataTx[6] = 'V';    pui32DataTx[7] = 'E';


        //*****************************************************************************************************************    //set up FIFO    UARTprintf("Configuring FIFO\n");    I2CTxFIFOConfigSet(I2C0_BASE, (I2C_FIFO_CFG_TX_MASTER|I2C_FIFO_CFG_TX_TRIG_4));         //Set TX fifo to the master and also triggers at 4 bytes    I2CRxFIFOConfigSet(I2C3_BASE,(I2C_FIFO_CFG_RX_SLAVE|I2C_FIFO_CFG_RX_TRIG_4));           //Set RX fifo to the master and also triggers at 1 byte
        I2CSlaveFIFOEnable(I2C3_BASE,I2C_SLAVE_RX_FIFO_ENABLE);                                 //sets 0x05 in the SCSR register enabling the slave AND the RX FIFO for the slave
        //******************************************************************************************************************    //enable and configure interrupts    UARTprintf("Configuring Interrupts\n");    IntEnable(INT_I2C0);    I2CMasterIntEnable(I2C0_BASE);    I2CMasterIntEnableEx(I2C0_BASE, I2C_MASTER_INT_TX_FIFO_REQ | I2C_MASTER_INT_DATA);    IntEnable(INT_I2C3);    I2CSlaveIntEnable(I2C3_BASE);    I2CSlaveIntEnableEx(I2C3_BASE, I2C_SLAVE_INT_RX_FIFO_REQ);    //*******************************************************************************************************************        //add data to TX FIFO    UARTprintf("Placing 8 bytes in the I2C0 TX FIFO\n", pui32DataTx[0]);    I2CFIFODataPut(I2C0_BASE, pui32DataTx[0]);                                              //single byte of data added to TX FIFO. trigger is set to 1    I2CFIFODataPut(I2C0_BASE, pui32DataTx[1]);                                              //single byte of data added to TX FIFO. trigger is set to 1    I2CFIFODataPut(I2C0_BASE, pui32DataTx[2]);    I2CFIFODataPut(I2C0_BASE, pui32DataTx[3]);    I2CFIFODataPut(I2C0_BASE, pui32DataTx[4]);    I2CFIFODataPut(I2C0_BASE, pui32DataTx[5]);    I2CFIFODataPut(I2C0_BASE, pui32DataTx[6]);    I2CFIFODataPut(I2C0_BASE, pui32DataTx[7]);    pui32DataRx = 0;    pui32DataRx = I2CFIFOStatus(I2C0_BASE);                                                //check TX FIFO status    I2CMasterBurstLengthSet(I2C0_BASE, 0x04);                                               //set length of burst to 4 bytes    

        UARTprintf("Sending FIFO BURST START command to master\n");    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_FIFO_BURST_SEND_START);                           //command to send a burst of bytes from FIFO    


        //wait for ISR to complete            while(!g_bIntFlag);            g_bIntFlag = false;               UARTprintf("Sending FIFO BURST CONT command to master\n");    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_FIFO_BURST_SEND_CONT);                           //command to send next burst of byte from FIFO    

        //wait for ISR to complete        while(!g_bIntFlag);        g_bIntFlag = false;


                pui32DataRx = I2CFIFOStatus(I2C0_BASE);                                                //check TX FIFO status    I2CTxFIFOFlush(I2C0_BASE);                                                              //FLUSH TX FIFO -- empties the FIFO    


    while(1);}

  • //int_handler.h header file for interrupt handlers

    /*
     * int_handler.h
     *
     *  Created on: 29 Apr 2020
     *      Author: jacob
     */
    #include <stdbool.h>
    #ifndef INT_HANDLER_H_
    #define INT_HANDLER_H_
    
    extern volatile bool g_bIntFlag;
    void I2C0MasterIntHandler(void);
    void I2C3SlaveIntHandler(void);
    
    
    #endif /* INT_HANDLER_H_ */
    

  • //int_handler.c interrupt handler functions

    /*
     * int_handler.c
     *
     *  Created on: 26 Apr 2020
     *      Author: jacob
     */
    #include <stdbool.h>
    #include <stdint.h>
    #include "driverlib/i2c.h"
    #include "inc/hw_memmap.h"
    #include "utils/uartstdio.h"
    #include "int_handler.h"
    //int init = 0;
    //*****************************************************************************
    //
    // The interrupt handler for the for I2C0 data slave interrupt.
    //
    //*****************************************************************************
    void
    I2C0MasterIntHandler(void)
    {
    
    
        I2CMasterIntClear(I2C0_BASE);
    
        UARTprintf("Interrupt I2C0 triggered\n\n");
    
    
        g_bIntFlag = true;
    
    }
    
    //*****************************************************************************
    //
    // The interrupt handler for the for I2C3 data slave interrupt.
    //
    //*****************************************************************************
    void
    I2C3SlaveIntHandler(void)
    {
    
        uint32_t data;
    
    
    
        //status = I2CFIFOStatus(I2C3_BASE);
        UARTprintf("Interrupt I2C3 triggered\n\n");
        data=I2CFIFODataGet(I2C3_BASE);
        UARTprintf("RX FIFO read byte '%c' \n", data);
        data=I2CFIFODataGet(I2C3_BASE);
        UARTprintf("RX FIFO read byte '%c' \n", data);
        data=I2CFIFODataGet(I2C3_BASE);
        UARTprintf("RX FIFO read byte '%c' \n", data);
        data=I2CFIFODataGet(I2C3_BASE);
        UARTprintf("RX FIFO read byte '%c' \n", data);
    
        I2CRxFIFOFlush(I2C3_BASE);
        I2CSlaveIntClear(I2C3_BASE, 0xFFFF);
        g_bIntFlag = true;
    
    }
    

  • Ok there you go. It'S in 3 different files so the ISR's are not in the same .c file as the main program and configuration stuff. 

    Thanks Ralph, and please let me know if you have any success. 

    Jacob

  • Hello Jacob,

    The smallest of things sometimes...

    In your RX handler you did not use the TM4C129x API:

    I2CSlaveIntClearEx(I2C3_BASE, 0xFFFF);

    I had made a couple other mods while debugging but I think that was the one that broke everything. Try that.

    Also I would recommend: 

    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_FIFO_BURST_SEND_FINISH);                           //command to send next burst of byte from FIFO

    over what you have which is 

    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_FIFO_BURST_SEND_CONT);                           //command to send next burst of byte from FIFO

  • Hello Ralph. Thank you for your continued support. I really need to figure this FIFO triggering thing out.

    In response, that function doesn't break my program because I have extended that function as follows in the I2c.c API:

    void
    I2CSlaveIntClear(uint32_t ui32Base, uint32_t CMD)
    {
    //
    // Check the arguments.
    //
    ASSERT(_I2CBaseValid(ui32Base));

    //
    // Clear the I2C slave interrupt source.
    //
    HWREG(ui32Base + I2C_O_SICR) = CMD;
    }

    This way I can choose to clear specific interrupts. Sorry for that. I had actually forgotten about that. So, anyway that is not the problem. Data transfer of all 8 bytes is happening successfully in 2 bursts of length 4 on my end. This is OK and working as I expect, but I will also change the master control command as you have suggested. 

    My problem is specifically only this:

        UARTprintf("Placing 8 bytes in the I2C0 TX FIFO\n", pui32DataTx[0]);
        I2CFIFODataPut(I2C0_BASE, pui32DataTx[0]); //single byte of data added to TX FIFO. trigger is set to 4
        I2CFIFODataPut(I2C0_BASE, pui32DataTx[1]);                                             
        I2CFIFODataPut(I2C0_BASE, pui32DataTx[2]);
        I2CFIFODataPut(I2C0_BASE, pui32DataTx[3]); //***********HERE i want in interrupt here after placing 4 bytes
        I2CFIFODataPut(I2C0_BASE, pui32DataTx[4]);
        I2CFIFODataPut(I2C0_BASE, pui32DataTx[5]);
        I2CFIFODataPut(I2C0_BASE, pui32DataTx[6]);
        I2CFIFODataPut(I2C0_BASE, pui32DataTx[7]);

    What I have set is TX FIFO trigger value of 4. I have unmasked bit 8 in the master interrupt mask register. This should cause an interrupt when the FIFO reaches a level of 4 bytes, according to the descriptor in the data sheet. It doesn't. Even in the raw interrupt status register, bit 8 never changes from 0. I cannot find any error in my configuration, so there is something that I don't understand. I need this to work for the specific functionality requirements that I have been given for this project.

    Any ideas on that? Are you able to successfully trigger an interrupt based on how many bytes are in the FIFO???? On the receiving or transmitting end. I have tried both and neither seems to work. 

    Thanks and have a nice weekend. 

  • Hello Jacob,

    Okay I will resume looking into that on Monday.

    Because of that undocumented function change, it looked to me that the program was broken.

    Since I saw the message for TX interrupt on UART I figured that it was working as expected, sorry for not cross checking that exact bit to see what was going on there.

    By the way I would recommend editing the Ex version if you edit any because if you later use TivaWare for TM4C123x devices, your edit may not allow that API to work. The 'Ex' functions are ones that were added specifically to enable different functionality with TM4C129x due to changes in the peripheral between the devices.

  • Ok thanks Ralph. I will talk to you on Monday. Have a nice weekend.

  • Hi Jacob,

    I spent a few hours today debugging and I haven't been able to trigger the interrupt yet, and like you said, it doesn't seem to pass into the I2C interrupt register. I am asking another colleague to have a look into this too in case I am missing something as well.

    Surprisingly, no one else has asked about this before from all my searching...

    One thing I have noticed is the FIFO empty interrupt does work, is that something you can use for your program?

    I ask because ideally I missed something and my colleague will catch it and I'll feel dumb... but if I really did try everything to get it to work and it doesn't trigger the interrupt, then this might end up being a device issue...

  • Ok thanks. Let me know what you find out.

    The requirements for this project from my professor are to trigger at half full, but if the hardware doesn't allow that then we will have to find another solution. I will await your final word before I move on.

    Thanks

    Jacob

  • So, I guess there is no solution here for the TX FIFO trigger level??

    Just as an update, I did some testing on the SLAVE RX FIFO trigger level and it does indeed seem to work. I can set the level from 1 to 8 and it works fine. It's just on the MASTER TX side where it doesn't work. I have come up with a workaround, but it would really work best if the TX side would work also. 

    Thanks!

  • Hi Jacob,

    Let me check back with my colleague, they didn't have access to all the the hardware needed earlier in the week but should have been able to look yesterday. COVID situation delayed that more than normal.

  • Hello Jacob,

    So mixed bag of results. We have been able to get the interrupt to fire, but not with BURST mode.

    It seems there is some level of delay needed for the interrupt to take hold

    The way we were able to get it to work when free running code is like this:

        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_FIFO_SINGLE_SEND);
        while(!I2CMasterBusy(I2C0_BASE))
        {
        }
        while(I2CMasterBusy(I2C0_BASE))
        {
        }
        
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_FIFO_SINGLE_SEND); 
        while(!I2CMasterBusy(I2C0_BASE))
        {
        }
        while(I2CMasterBusy(I2C0_BASE))
        {
        }
    
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_FIFO_SINGLE_SEND); 
        while(!I2CMasterBusy(I2C0_BASE))
        {
        }
        while(I2CMasterBusy(I2C0_BASE))
        {
        }
    
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_FIFO_SINGLE_SEND); 
        while(!I2CMasterBusy(I2C0_BASE))
        {
        }
        while(I2CMasterBusy(I2C0_BASE))
        {
        }
    
    

    So if that works for you, then give it a try.

    We are going to have further discussions regarding burst mode and assess if we need an errata item for this as well. In this case, the code used is a workaround for another errata for I2C when in polling mode, but using interrupt mode isn't supposed to have such problems.

    Anyways, from your end hopefully this helps.

  • Thanks for all the work and time looking into it. I have managed to work around it, and everything is working as I expect it to. I can't trigger the half full interrupt with a burst, but that is OK. At least it can work this way, it just isn't optimal.

    I will go ahead and consider this closed. You guys are always very helpful. It is appreciated.