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.

TMS320F280041C: Is there a way to transfer more than 16 bytes a time on I²C?

Part Number: TMS320F280041C

Hello,

we need to transfer large amounts of data to and from an external eeprom on I²C. For sizes less than 16 bytes this works fine and reproducible.But in case we want to transfer more than 16 byte the transmission stops after 16 with a protocol conform stop condition. We didn't find a way to transfer more than this, even checking transfer ready or shifted out flags flags.

Does anybody have any suggestions how to skip this border?

Regards

Kai

  • Kai,

    Yes, you can use I²C can transmit (or) receive more than 16-bits. Please check the below example.

    //###########################################################################
    //
    // FILE:    Example_2807xI2C_eeprom.c
    //
    // TITLE:   I2C EEPROM Example
    //
    //! \addtogroup cpu01_example_list
    //! <h1>I2C EEPROM Example (i2c_eeprom)</h1>
    //!
    //! This program will write 1-14 words to EEPROM and read them back.
    //! The data written and the EEPROM address written to are contained
    //! in the message structure, I2cMsgOut1. The data read back will be
    //! contained in the message structure I2cMsgIn1.
    //!
    //! \b External \b Connections \n
    //! - This program requires an external I2C EEPROM connected to
    //!   the I2C bus at address 0x50.
    //!
    //
    //###########################################################################
    // $TI Release: F2807x Support Library v3.10.00.00 $
    // $Release Date: Tue May 26 17:19:45 IST 2020 $
    // $Copyright:
    // Copyright (C) 2014-2020 Texas Instruments Incorporated - http://www.ti.com/
    //
    // Redistribution and use in source and binary forms, with or without
    // modification, are permitted provided that the following conditions
    // are met:
    //
    //   Redistributions of source code must retain the above copyright
    //   notice, this list of conditions and the following disclaimer.
    //
    //   Redistributions in binary form must reproduce the above copyright
    //   notice, this list of conditions and the following disclaimer in the
    //   documentation and/or other materials provided with the
    //   distribution.
    //
    //   Neither the name of Texas Instruments Incorporated nor the names of
    //   its contributors may be used to endorse or promote products derived
    //   from this software without specific prior written permission.
    //
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    // $
    //###########################################################################
    
    //
    // Included Files
    //
    #include "F28x_Project.h"
    
    
    //
    // Defines
    //
    #define I2C_SLAVE_ADDR        0x50
    #define I2C_NUMBYTES          2
    #define I2C_EEPROM_ADDRESS    0x0000
    #define I2C_FIFO_LEVEL        16
    
    #define I2C_SUCCESS                 0
    #define I2C_BUS_BUSY_ERROR          999
    #define I2C_STP_NOT_READY_ERROR     1
    #define SLAVE_NOT_READY_ERROR       2
    
    #define DEVICE_SYSCLK_FREQ          120000000//SYSCLK = 120 MHz
    
    #define EEPROM_MAX_WRITE_CYCLE      5     //5ms
    
    #define WRITE_DELAY_TIME            (((EEPROM_MAX_WRITE_CYCLE * DEVICE_SYSCLK_FREQ)/1000)-9)/5
    
    #define DEVICE_DELAY_US(x) F28x_usDelay(x)
    
    
    
    //
    // Function Prototypes
    //
    void i2c_init_old(void);
    void I2C_GPIO_confi(void);
    void I2CA_Init(void);
    Uint16 handleNACK(void);
    
    Uint16 checkBusStatus(void);
    
    Uint16 I2CA_WriteData(Uint16 SlaveAddress, Uint16 address, Uint16 *txbuffer, Uint16 NumOfBytes);
    Uint16 I2CA_ReadData(uint16_t SlaveAddress, uint16_t address, uint16_t *txbuffer, uint16_t NumOfBytes);
    
    Uint16 PassCount=0;
    Uint16 FailCount=0;
    
    
    __interrupt void i2c_int1a_isr(void);
    
    void pass(void);
    void fail(void);
    
    Uint16 r;
    
    Uint16 I2C_status = 9;
    
    //
    // Main
    //
    
    
    uint16_t TXdata[66];
    uint16_t RXdata[256];
    
    void main(void)
    {
    
    
    //
    // Step 1. Initialize System Control:
    // PLL, WatchDog, enable Peripheral Clocks
    // This example function is found in the F2837xS_SysCtrl.c file.
    //
        InitSysCtrl();
    
    //
    // Step 2. Initialize GPIO:
    // This example function is found in the F2837xS_Gpio.c file and
    // illustrates how to set the GPIO to it's default state.
    //
        InitGpio();
    
    //
    // For this example, only init the pins for the SCI-A port.
    // These functions are found in the F2837xS_Gpio.c file.
    
        //XCLKOUT = GPIO73
        GPIO_SetupPinMux(73, GPIO_MUX_CPU1, 3);
    
    
        EALLOW;
        ClkCfgRegs.CLKSRCCTL3.bit.XCLKOUTSEL = 0;
        ClkCfgRegs.XCLKOUTDIVSEL.bit.XCLKOUTDIV = 3;
        EDIS;
    
    
    
        I2C_GPIO_confi();
    //      i2c_init_old();
    //
    // Step 3. Clear all __interrupts and initialize PIE vector table:
    // Disable CPU __interrupts
    //
        DINT;
    
    //
    // Initialize PIE control registers to their default state.
    // The default state is all PIE __interrupts disabled and flags
    // are cleared.
    // This function is found in the F2837xS_PieCtrl.c file.
    //
        InitPieCtrl();
    
    //
    // Disable CPU __interrupts and clear all CPU __interrupt flags:
    //
        IER = 0x0000;
        IFR = 0x0000;
    
    //
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    // This will populate the entire table, even if the __interrupt
    // is not used in this example.  This is useful for debug purposes.
    // The shell ISR routines are found in F2837xS_DefaultIsr.c.
    // This function is found in F2837xS_PieVect.c.
    //
        InitPieVectTable();
    
    //
    // Interrupts that are used in this example are re-mapped to
    // ISR functions found within this file.
    //
        EALLOW;    // This is needed to write to EALLOW protected registers
        PieVectTable.I2CA_INT = &i2c_int1a_isr;
        EDIS;      // This is needed to disable write to EALLOW protected registers
    
    //
    // Step 4. Initialize the Device Peripherals:
    //
        I2CA_Init();
    
    //
    // Step 5. User specific code
    //
    
    //
    // Clear Counters
    //
        PassCount = 0;
        FailCount = 0;
    
    //
    // Enable __interrupts required for this example
    //
    
    //
    // Enable I2C __interrupt 1 in the PIE: Group 8 __interrupt 1
    //
        PieCtrlRegs.PIEIER8.bit.INTx1 = 1;      //Enabling I2C non-FIFO interrupt
    
    //
    // Enable CPU INT8 which is connected to PIE group 8
    //
        IER |= M_INT8;
        EINT;
    
        ESTOP0;
    
        r = 2;
        while(r<=66)
        {
    
           TXdata[r] = 55;
           RXdata[r] = 0;
           r++;
        }
    
        I2C_status = I2CA_WriteData(I2C_SLAVE_ADDR+10, I2C_EEPROM_ADDRESS, TXdata, 4);
        DEVICE_DELAY_US(2*WRITE_DELAY_TIME); //wait for 5ms for max write time for EEPROM i'm using
        I2C_status = I2CA_ReadData(I2C_SLAVE_ADDR+30, I2C_EEPROM_ADDRESS, RXdata, 4);
    
        ESTOP0;
    
        r = 0;
        while(r<=1)
        {
            I2C_status = I2CA_WriteData(I2C_SLAVE_ADDR, I2C_EEPROM_ADDRESS+r*64, TXdata, 64);
            DEVICE_DELAY_US(WRITE_DELAY_TIME); //wait for 5ms for max write time for EEPROM i'm using
            r++;
        }
    
        I2C_status = I2CA_ReadData(I2C_SLAVE_ADDR, I2C_EEPROM_ADDRESS, RXdata, 128);
    
        ESTOP0;
    
    
        TXdata[2] = 0;
        I2C_status = I2CA_WriteData(I2C_SLAVE_ADDR, I2C_EEPROM_ADDRESS, TXdata, 1);
        DEVICE_DELAY_US(WRITE_DELAY_TIME); //wait for 5ms for max write time for EEPROM i'm using
    
        I2C_status = I2CA_ReadData(I2C_SLAVE_ADDR, I2C_EEPROM_ADDRESS, RXdata, 1);
    
        TXdata[2] = 1;
        TXdata[3] = 2;
        I2C_status = I2CA_WriteData(I2C_SLAVE_ADDR, I2C_EEPROM_ADDRESS+1, TXdata, 2);
        DEVICE_DELAY_US(WRITE_DELAY_TIME); //wait for 5ms for max write time for EEPROM i'm using
    
        I2C_status = I2CA_ReadData(I2C_SLAVE_ADDR, I2C_EEPROM_ADDRESS, RXdata, 3);
    
        TXdata[2] = 3;
        TXdata[3] = 4;
        TXdata[4] = 5;
        TXdata[5] = 6;
        I2C_status = I2CA_WriteData(I2C_SLAVE_ADDR, I2C_EEPROM_ADDRESS+3, TXdata, 4);
        DEVICE_DELAY_US(WRITE_DELAY_TIME); //wait for 5ms for max write time for EEPROM i'm using
    
        I2C_status = I2CA_ReadData(I2C_SLAVE_ADDR, I2C_EEPROM_ADDRESS, RXdata, 7);
    
        ESTOP0;
    
        r = 2;
        while(r<=66)
        {
    
           TXdata[r] = 100 + r - 2;
           RXdata[r] = 0;
           r++;
        }
    
        I2C_status = I2CA_WriteData(I2C_SLAVE_ADDR, I2C_EEPROM_ADDRESS+64, TXdata, 64);
        DEVICE_DELAY_US(WRITE_DELAY_TIME); //wait for 5ms for max write time for EEPROM i'm using
    
        I2C_status = I2CA_ReadData(I2C_SLAVE_ADDR, I2C_EEPROM_ADDRESS, RXdata, 128);
    
        ESTOP0;
    
        I2C_status = I2CA_ReadData(I2C_SLAVE_ADDR, I2C_EEPROM_ADDRESS+3, RXdata, 10);
    
        I2C_status = I2CA_WriteData(I2C_SLAVE_ADDR, I2C_EEPROM_ADDRESS+128, TXdata, 64);
        DEVICE_DELAY_US(WRITE_DELAY_TIME); //wait for 5ms for max write time for EEPROM i'm using
    
        I2C_status = I2CA_ReadData(I2C_SLAVE_ADDR, I2C_EEPROM_ADDRESS, RXdata, 128);
    
        I2C_status = I2CA_ReadData(I2C_SLAVE_ADDR, I2C_EEPROM_ADDRESS+128, RXdata, 128);
    
        I2C_status = I2CA_ReadData(I2C_SLAVE_ADDR+10, I2C_EEPROM_ADDRESS+128, RXdata, 17);
    
        ESTOP0;
    
    }
    
    //
    // I2CA_Init - Initialize I2CA settings
    //
    void I2CA_Init(void)
    {
        I2caRegs.I2CSAR.all = 0x0050;     // Slave address - EEPROM control code
    
        I2caRegs.I2CPSC.all = 11;         // Prescaler - need 7-12 Mhz on module clk //I2C Module clock = 100 MHz / (9+1) = 10 MHz
        I2caRegs.I2CCLKL = 45;            // NOTE: must be non zero //I2C configured in standard mode
        I2caRegs.I2CCLKH = 45;             // NOTE: must be non zero
        I2caRegs.I2CIER.all = 0x24;       // Enable SCD & ARDY __interrupts
    
        I2caRegs.I2CMDR.all = 0x0020;     // Take I2C out of reset
                                          // Stop I2C when suspended
    
        I2caRegs.I2CFFTX.all = 0x6000;    // Enable FIFO mode and TXFIFO
        I2caRegs.I2CFFRX.all = 0x2040;    // Enable RXFIFO, clear RXFFINT,
    
        return;
    }
    
    //
    // I2CA_WriteData - Transmit I2CA message
    //
    Uint16 I2CA_WriteData(Uint16 SlaveAddress, Uint16 address, Uint16 *txbuffer, Uint16 NumOfBytes)
    //Uint16 I2CA_WriteData(uint16_t SlaveAddress, Uint16 address)
    {
        Uint16 status;
    
        Uint16 numofSixteenByte  = (2+NumOfBytes) / I2C_FIFO_LEVEL;
        Uint16 remainingBytes    = (2+NumOfBytes) % I2C_FIFO_LEVEL;
    
        status = checkBusStatus();
        if(status)
        {
            return status;
        }
    
        //
        // Setup slave address
        //
        I2caRegs.I2CSAR.all = SlaveAddress;
    
    
        txbuffer[0] = address >> 8;
        txbuffer[1] = (address) & 0xFF;
    
        I2caRegs.I2CCNT = 2+NumOfBytes;
        I2caRegs.I2CMDR.all = 0x6E20;
        F28x_usDelay(3000);
    
        status = handleNACK();
        if(status)
        {
           return status;
        }
    
        Uint16 count,i;
    
        count = 0;
        while(count < numofSixteenByte)
        {
            for(i=1;i<=I2C_FIFO_LEVEL;i++)
            {
                I2caRegs.I2CDXR.all = *(txbuffer);
                txbuffer++;
                status = handleNACK();
                if(status)
                {
                   return status;
                }
            }
    
            count++;
            while(I2caRegs.I2CFFTX.bit.TXFFST);
        }
    
        //I2caRegs.I2CCNT = remainingBytes;
        for (i=0; i < remainingBytes; i++)
        {
            I2caRegs.I2CDXR.all = *(txbuffer);
            txbuffer++;
            status = handleNACK();
            if(status)
            {
              return status;
            }
        }
    
        while(I2caRegs.I2CMDR.bit.STP);
        //
        // Send start as master transmitter
        //
        status = I2C_SUCCESS;
    
        return status;
    }
    
    //
    // I2CA_ReadData - Read I2CA Message
    //
    Uint16 I2CA_ReadData(uint16_t SlaveAddress, uint16_t address, uint16_t *rxbuffer, uint16_t NumOfBytes)
    {
    
        Uint16 status;
    
        Uint16 numofSixteenByte  = NumOfBytes / I2C_FIFO_LEVEL;
        Uint16 remainingBytes    = NumOfBytes % I2C_FIFO_LEVEL;
    
        status = checkBusStatus();
        if(status)
        {
          return status;
        }
        //
        // Setup slave address
        //
        I2caRegs.I2CSAR.all = SlaveAddress;
    
        //
        // Setup number of bytes to send
        // MsgBuffer + Address
        //
        I2caRegs.I2CCNT = 2; //Additional 2 bytes for transmitting eeprom address
    
        //
        // Setup data to send
        //
        I2caRegs.I2CDXR.all = address >> 8;
        I2caRegs.I2CDXR.all = (address) & 0xFF;
    
        I2caRegs.I2CFFTX.bit.TXFFINTCLR = 1;
    
        I2caRegs.I2CMDR.all = 0x6620;
        F28x_usDelay(5000);
    
        status = handleNACK();
        if(status)
        {
          return status;
        }
    
        remainingBytes    = NumOfBytes % I2C_FIFO_LEVEL;
        while(I2caRegs.I2CFFTX.bit.TXFFST);
    
        I2caRegs.I2CCNT = NumOfBytes;    // Setup how many bytes to expect
    
        I2caRegs.I2CMDR.all = 0x6C20;    // Send restart as master receiver
    
        Uint16 count,i;
    
        count = 0;
        while(count < numofSixteenByte)
        {
            status = handleNACK();
            if(status)
            {
    
              return status;
            }
    
            count++;
            while(!(I2caRegs.I2CFFRX.bit.RXFFST == 16));
    
            for(i=0; i<I2C_FIFO_LEVEL; i++)
            {
                *rxbuffer = I2caRegs.I2CDRR.all;
                rxbuffer++;
            }
    
        }
    
        while(!(I2caRegs.I2CFFRX.bit.RXFFST == remainingBytes));
        for(i=0; i<remainingBytes; i++)
        {
               *rxbuffer = I2caRegs.I2CDRR.all;
               rxbuffer++;
        }
    
        status = handleNACK();
        if(status)
        {
          return status;
        }
    
    
        while(I2caRegs.I2CMDR.bit.STP);
    
        return I2C_SUCCESS;
    }
    
    Uint16 checkBusStatus(void)
    {
        if(I2caRegs.I2CMDR.bit.STP == 1)
        {
         // ESTOP0;
            return I2C_STP_NOT_READY_ERROR;
        }
        if(I2caRegs.I2CSTR.bit.BB == 1)
        {
            ESTOP0;
            return I2C_BUS_BUSY_ERROR;
        }
    
        if(I2caRegs.I2CSTR.bit.NACK)
        {
            ESTOP0;
            return SLAVE_NOT_READY_ERROR;
        }
    
        return 0;
    
    }
    
    Uint16 handleNACK(void)
    {
        if(I2caRegs.I2CSTR.bit.NACK)
        {
            I2caRegs.I2CSTR.bit.NACK = 1; //Clear NACK bit to receive future NACKs
            I2caRegs.I2CFFTX.bit.TXFFRST = 0; //Reset TX FIFO to flush FIFO
            I2caRegs.I2CMDR.bit.STP = 1;      //Generate STOP condition
            I2caRegs.I2CFFTX.bit.TXFFRST = 1; //Re-enable TX FIFO
    
            return SLAVE_NOT_READY_ERROR;
        }
    
        return 0;
    }
    
    //
    // i2c_int1a_isr - I2CA ISR
    //
    __interrupt void i2c_int1a_isr(void)
    {
    //    Uint16 IntSource;
    
        //
        // Read __interrupt source
        //
    //    IntSource = I2caRegs.I2CISRC.all;
    
    
    
        //
        // Enable future I2C (PIE Group 8) __interrupts
        //
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP8;
    }
    
    //
    // pass - Halt debugger and signify pass
    //
    void pass()
    {
        __asm("   ESTOP0");
        for(;;);
    }
    
    //
    // fail - Halt debugger and signify fail
    //
    void fail()
    {
        __asm("   ESTOP0");
        for(;;);
    }
    
    //
    // End of file
    //
    /*
    void i2c_init_old(void)
    {
    
    //Assign GetWordData to the I2C-A version of the
    //function. GetWordData is a pointer to a function.
    //GetWordData = I2C_GetWord;
    
    I2C_GPIO_confi(); //configure the GPIO for I2C
    
    EALLOW;
    //CpuSysRegs.PCLKCR9.bit.I2C_A = 1; // Turn I2C module clock on
    // EDIS;
    
    // Initialize I2C in master transmitter mode
    I2caRegs.I2CFFRX.bit.RXFFIL = 3;
    I2caRegs.I2CSAR.all= 0x68; //50// Slave address - EEPROM control code
    I2caRegs.I2CPSC.all =0X14; //9 I2C clock should be between 7Mhz-12Mhz 50MHz/6=8.33
    I2caRegs.I2CCLKL = 40; //43 // Pre scalers set for 100kHz bit rate
    I2caRegs.I2CCLKH = 40; //43 // At a 10Mhz I2C clock
    
    I2caRegs.I2CMDR.all = 0x0620; // Master transmitter
    // Take I2C out of reset
    // Stop when suspended
    
    I2caRegs.I2CFFTX.all = 0x6000; // Enable FIFO mode and TXFIFO
    I2caRegs.I2CFFRX.all = 0x2000; // Enable RXFIFO
    
    EDIS;
    return;
    }
    */
    
    void I2C_GPIO_confi(void)
    {
        GPIO_SetupPinOptions(104, GPIO_INPUT, (GPIO_ASYNC | GPIO_PULLUP));
        GPIO_SetupPinMux(104, GPIO_MUX_CPU1, 1);
    
        GPIO_SetupPinOptions(105, GPIO_INPUT, (GPIO_ASYNC | GPIO_PULLUP));
        GPIO_SetupPinMux(105, GPIO_MUX_CPU1, 1);
    }
    
    
    /*
     * main.c
     *
     *  Created on: 31-Aug-2020
     *      Author: shakti
     */
    
    
    
    
    

    Regards,

    Manoj

  • Hello, Manoj,

    thank you for the link. I'll give it a try and will response as soon as I have new results.

    Regards

    Kai

  • Is this issue resolved? Can I close this thread?

    -Manoj

  • isn't really solved, but for now yout can close the thread. We will ask again, if there are new issues / results

    Regards

    Kai