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.

CCS/TMDS570LS31HDK: TMDS570LS31HDK, Hercules TMS570LS31x/21x Development Kit

Part Number: TMDS570LS31HDK
Other Parts Discussed in Thread: TMS570LS3137

Tool/software: Code Composer Studio

I want to interface AT24C256 with Hercules TMS570LS31x/21x Development Kit, following code was not working:

 /* USER CODE BEGIN (0) */

#include "het.h"
#include "gio.h"
#include "rti.h"
#include "i2c.h"
/* USER CODE END */

/* Include Files */

#include "sys_common.h"

/* USER CODE BEGIN (1) */
/* USER CODE END */

/** @fn void main(void)
* @brief Application main function
* @note This function is empty by default.
*
* This function is called after startup.
* The user can use this function to implement the application.
*/

/* USER CODE BEGIN (2) */
#define Slave_Address 0xA0 // 1 0 1 0 0 A1 A0 R/W
uint8_t TX_Data[4] = {0x00, 0x00, 0xAA, 0x55};       // first two bytes are word address then 2 bytes are data
/* USER CODE END */

int main(void)
{
/* USER CODE BEGIN (3) */

i2cInit();

i2cSetSlaveAdd(i2cREG1, Slave_Address);

i2cSetDirection(i2cREG1, I2C_TRANSMITTER);

i2cSetCount(i2cREG1, 4);

i2cSetMode(i2cREG1, I2C_MASTER);

i2cSetStop(i2cREG1);

i2cSetStart(i2cREG1);

i2cSend(i2cREG1, 4, TX_Data);

while(i2cIsBusBusy(i2cREG1) == true);

while(i2cIsStopDetected(i2cREG1) == 0);

i2cClearSCD(i2cREG1);

while(1);

/* USER CODE END */

}

 

The controller is waiting in the i2cSend() function as follows:

void i2cSend(i2cBASE_t *i2c, uint32 length, uint8 * data)
{

/* USER CODE BEGIN (17) */
/* USER CODE END */

if ((g_i2cTransfer_t.mode & (uint32)I2C_TX_INT) != 0U)
{
/* Interrupt mode */
/*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Valid non NULL input parameters are only allowed in this driver" */
g_i2cTransfer_t.data = data;
/* start transmit by sending first byte */
/*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Valid non NULL input parameters are only allowed in this driver" */
i2c->DXR = (uint32)(*g_i2cTransfer_t.data);
/*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Valid non NULL input parameters are only allowed in this driver" */
/*SAFETYMCUSW 567 S MR:17.1,17.4 <APPROVED> "Pointer increment needed" */
g_i2cTransfer_t.data++;

/* Length -1 since one data is written already */
g_i2cTransfer_t.length = (length - 1U);

/* Enable Transmit Interrupt */
i2c->IMR |= (uint32)I2C_TX_INT;
}
else
{
/* send the data */
while (length > 0U)
{
/*SAFETYMCUSW 28 D MR:NA <APPROVED> "Potentially infinite loop found - Hardware Status check for execution sequence" */
while ((i2c->STR & (uint32)I2C_TX_INT) == 0U)                      < < <- - - -  controller is waiting here
{
} /* Wait */
/*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Valid non NULL input parameters are only allowed in this driver" */
i2c->DXR = (uint32)(*data);
/*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Valid non NULL input parameters are only allowed in this driver" */
/*SAFETYMCUSW 567 S MR:17.1,17.4 <APPROVED> "Pointer increment needed" */
data++;
length--;
}
}
/* USER CODE BEGIN (18) */
/* USER CODE END */
}

  • I want to use GIOA[0]-[7], GIOB[0]-[7], DMMDATA[0]-[15], RTP_DATA[0]-[15], CANxxx, LINRX, LINTX these pins as a normal purpose GPIO, Please provide me example code (software functions)

    For Example :  gioSetDirection(hetPORT1, 0xFFFFFFFF);

                            gioSetBit(hetPORT1, 0, 1);

                            gioSetBit(hetPORT1, 17, 1);

                            gioSetBit(hetPORT1, 18, 1);

  • Hello,

    I am not familiar with AT24C256. When you read data from this device, don't you need to send the word address first?

  • Hello,

    DMMDATA[0]-[15], RTP_DATA[0]-[15], LINRX, LINTX can be used as GIO pins, and the GIO APIs can be used to configure those GIO pins. 

    The CAN_RX and CAN_TX pins can be used as GIO pins too. This function is controlled by the CAN TX IO Control register. The values of the IO Control registers are only writable if Init bit of CAN Control Register is set. The GIO APIs can not be used here.

     

  • by telling "I am not familiar with AT24C256. When you read data from this device, don't you need to send the word address first?" my problem is not resolved.

    Please try to understand where I am facing issue and what is the solution for that?

    My work is getting delayed because of no response from from you, please solve this issue as soon as possible. 

    I am requesting you again please provide me correct steps to send and receive data from AT24C256 EEPROM.

    Following are the screenshots of AT24C256 data format for your better understanding and see the code above, i don't know why controller is waiting here

    "while ((i2c->STR & (uint32)I2C_TX_INT) == 0U){}

    I have checked SCL and SDA pins of controller using DSO with and without connecting EEPROM still not getting any signals.

  • I want to use GIOA as a output port what should I write in the following function?

    void gioSetDirection(gioPORT_t *port, uint32 dir)

    What should I write in place of *port?

    As GIOA is 8 bit only and dir is 32 bit, what should be the value of dir?

    Reply me as soon as possible. 

  • Hi Rahul,

    From your drawing, the Slave_Address is 0x50 rather than 0xA0. The salve address in I2CSAR register doesn't include the R/W bit. 

  • I have tried with slave address 0x50, still not working.

  • Waiting for your reply?

  • gioSetDirection(gioPORTA, ....)
    gioSetDirection(gioPORTB, ....)
    gioSetDirection(hetPORT1, ...)
    The GIODIR register is 32-bit. Writing to rsved bit field has no effect, bit 0 is for GIO[0], bit 1 is for GIO[1],...
  • 1. Please double check the pinmux is set correctly. I2C pins (B2, C3) are multiplexed with MibSPI CSx and N2HET pins.

    2. Probe I2C bus to check if the I2C slave address has been sent and ACK bit is LOW (Acknowledged) after calling i2cSetStart(i2cREG1)

    3. If yes, please send the word addresses 92 bytes) byte by byte to make sure the response of I2C slave is correct.

    4. AT24C supports byte write and page write (64 bytes). Can you try byte write first instead of partial page write?

  • I want to use DMMDATA[0]-[15] & RTP_DATA[0]-[15] as a IO port what should I write in the following function?

    void gioSetDirection(gioPORT_t *port, uint32 dir)

    What should I write in place of *port?

    Provide me the API for same.

    Reply me as soon as possible. 

  • Can you please use a separate post for DMM IO question, and leave this thread for I2C question only? Thanks

  • I have tried with slave address 0x50, but still I2C is not responding...

    My work is pending. I am waiting for your reply?

    What I will do?

    My code is waiting here --->>  while ((i2c->STR & (uint32)I2C_TX_INT) == 0U)
                                                    {
                                                    } /* Wait */

  • I have checked for pinmux and it is correct. I have checked SDA and SCL on DSO, both the lines are high only. There is no any signal on these pins.

  • When the code gets stuck, what is the value of length? 

    Can you send the 2-byte word address and 2-byte data separately? 

    Did you get correct ACK after sending the device address, and word addresses? 

  • Q. When the code gets stuck?

    A: My code is getting stuck here --->>  while ((i2c->STR & (uint32)I2C_TX_INT) == 0U)
                                                                  {
                                                                  } /* Wait */

    Q. What is the value of length? 

    A: 4

    Q. Can you send the 2-byte word address and 2-byte data separately? 

    A: I have tried this, but not working. i2cSend(i2cREG1, 2, TX_Word_Addr);

       i2cSend(i2cREG1, 2, TX_Data);

    Q. Did you get correct ACK after sending the device address, and word addresses? 

    A: When I have checked using DSO, both the pins are high, not getting any cock and data, even not getting any slave address on SDA pin.

  • Hello,

    The Serial Clock Line (SCL) and Serial Data Line (SDA) are pulled high with external pull-up resistors, so two lines are at HIGH level when no data is transmitted.

    The protocol consists of a Start bit, Address bits, read/write (R/W) bit, data byte, acknowledge bit (ACK), no-acknowledge bit (NACK), stop bit, and re-start bit (which is equivalent to Start bit without a stop bit).

    The Start bit (S) is always sent by a master to initiate communication. It is defined as high to low transition on the SDA line, while SCL is held high. Did you see the start bit on scope?

    The acknowledge bit (ACK) occurs on the ninth SCL clock pulse. It is transmitted by the receiving device, while it pulls SDA line low. The no-acknowledge bit is transmitted when the receiving device fails to pull the SDA line low. The transfer is aborted when NACK is received. The stop bit is always sent by the master to end the communication. It is defined as low to high transition on the SDA line while the SCL line is held high. So after the master sends device's address, the device should send ACK back to the master.

    From your message, you don't see any clock signal on SCL bus. The transfer is not stared. 

  • Q. Did you see the start bit on scope?

    A: I already told you previously, not getting any signals on SDA and SCL pins, both lines are high.

  • If the pinmux is configured correctly, you should see the start bit and slave address on SDA bus when i2cSetStart(i2cREG1) is executed whatever the I2C device is connected or not.

    1. Please double check your pinmux configuration for balls B2 and C3 

    2. Double check the wires connection to make sure B2 is connected to SDA of I2C device, and C3 is to SCL of I2C device

    3. In I2C configuration window (I2C Port), make sure I2C signals are not configured as GIO 

    The following is my I2C loopback test, the own address is 0x75:

    1. After i2cSetStart(i2cREG1) is executed: You can see the start bit, slave address (0x75), R/W, and ACK bit

       

    2. After 1 byte of data is transferred: You can see the start bit, slave address, R/W, ACK, 1 byte data, and ACK.

       

    This is my test code:

    /* Include Files */

    #include "sys_common.h"

    /* USER CODE BEGIN (1) */
    #include "system.h"
    #include "i2c.h"

    /* USER CODE END */

    /** @fn void main(void)
    * @brief Application main function
    * @note This function is empty by default.
    *
    * This function is called after startup.
    * The user can use this function to implement the application.
    */

    /* USER CODE BEGIN (2) */
    #define own_add 0x75
    #define slv_add 0x5A
    #define bsize 8

    uint8 TX_PACK[16]={0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,0x5A,0x5B,0x5C,0x5D};
    uint8 RX_PACK[16]={0};
    uint32 data;

    void i2cEnableLoopback(i2cBASE_t *i2c);
    /* USER CODE END */

    int main(void)
    {
    /* USER CODE BEGIN (3) */
    uint32 buf_size = bsize, i, errNum;
    uint8 *t_buff = &TX_PACK[0];
    uint8 *r_buff = &RX_PACK[0];

    /* i2c initialization */
    i2cInit();

    /* set i2c own address */
    i2cSetOwnAdd(i2cREG1,own_add);

    /* enable internal loopback */
    i2cEnableLoopback(i2cREG1);

    /* Initiate Start condition for Transmission */
    i2cSetStart(i2cREG1);

    /* send data packets */
    while(buf_size--)
    {
    i2cSendByte(i2cREG1,*t_buff++);
    /* receive data packets */
    *r_buff++ = i2cReceiveByte(i2cREG1);

    asm(" nop"); //for breakpoint
    }

    errNum = 0;
    for (i=0; i<bsize; i++){
    if (RX_PACK[i] != RX_PACK[i])
    errNum++;
    }

    /* Clear Stop Condition detect flag */
    i2cClearSCD(i2cREG1);


    while(1){}; /* wait forever after tx-rx complete. */
    /* USER CODE END */

    return 0;
    }

  • Please read TMS570LS3137 datasheet and TRM for more information about pinmux and I2C protocol. Thanks

  • I have tested above loopback code and it is working fine.

    But i want to interface EEPROM (AT24C256) with this board.

    My code is not working:

    /* Include Files */

    #include "sys_common.h"

    /* USER CODE BEGIN (1) */

    #include "system.h"
    #include "i2c.h"


    /* USER CODE END */

    /** @fn void main(void)
    * @brief Application main function
    * @note This function is empty by default.
    *
    * This function is called after startup.
    * The user can use this function to implement the application.
    */

    /* USER CODE BEGIN (2) */

    #define Slave_Address 0x50 
    uint8_t TX_Data[4] = {0x00, 0x00, 0xAA, 0x55};
    uint8_t RX_Data[2] = { 0 };

    /* USER CODE END */

    int main(void)
    {
    /* USER CODE BEGIN (3) */

    i2cInit();

    i2cSetSlaveAdd(i2cREG1, Slave_Address); 

    i2cSetDirection(i2cREG1, I2C_TRANSMITTER);

    i2cSetCount(i2cREG1, 4); 

    i2cSetMode(i2cREG1, I2C_MASTER); 

    i2cSetStop(i2cREG1); 

    i2cSetStart(i2cREG1); 

    i2cSend(i2cREG1, 4, TX_Data); 

    while(i2cIsBusBusy(i2cREG1) == true);

    while(i2cIsStopDetected(i2cREG1) == 0);

    i2cClearSCD(i2cREG1); 

    while(1);

    /* USER CODE END */

    }

    My code is waiting in i2cSend(i2cBASE_t *i2c, uint32 length, uint8 * data) function 

    while ((i2c->STR & (uint32)I2C_TX_INT) == 0U)                         < < < -----   Waiting here
    {
    } /* Wait */

  • If the loopback works, the i2cSetStart(i2cREG1) in your code should generate clock, start bit, and send I2C device address. But you said you did not see signal on SCL and SDA lines. You need to figure out why there is no signal on the I2C bus.   

    A strong pullup (small resistor) prevents the I2C pin from being able to drive low. So please double check your pull-up, and wire connection. 

  • I have captured two screenshots before code gets stuck into the while ((i2c->STR & (uint32)I2C_TX_INT) == 0U)                         < < < -----   Waiting here
                                                                                                           {
                                                                                                           } /* Wait */


  • We have tested with the above code in our development kit, and found the different wave forms, which are attached along with this link. Please suggest us the further inputs to solve the issue.

    1. Waveform after calling i2cSetStart();

      

    2. Waveform after First_byte data transfer

  • The I2C module can be placed in free run mode when the FREE bit (I2CMDR.14) is set to 1. Free running mode is used when you debug software with breakpoints.

    i2cREG1->MDR |=  (uint32)((uint32)1U << 14U);     /* free running */

    This is why only one pulse is captured in your first screenshot, your breakpoint is added at next instruction of  i2cSetStart(i2cREG1).

    Please add 

    i2cREG1->MDR |=  (uint32)((uint32)1U << 14U);     /* free running */

    after i2cInit(), then capture the I2C waveform for:

    1. i2cSetStart(i2cREG1);  --- to check slave address, R/W, ACK

    2. i2cSend(..): -- check word address, ACK, and data, ACK

  • I have attached my main file of I2C communication, and its working fine while placing the breakpoints or maintaining the delay between successive read and write calls. But, without those breakpoints or the delay the code is stays inside the i2cSend()   --->> while ((i2c->STR & (uint32)I2C_TX_INT) == 0U) . 
    Could you please help us to sort out this issue.

    Please find the attachments for the reference of our code.

    sys_main.c

    /* Include Files */

    #include "sys_common.h"

    /* USER CODE BEGIN (1) */
    #include "i2c.h"
    #include "at24c256.h"
    /* USER CODE END */

    /** @fn void main(void)
    * @brief Application main function
    * @note This function is empty by default.
    *
    * This function is called after startup.
    * The user can use this function to implement the application.
    */

    /* USER CODE BEGIN (2) */
    extern void EEPROM_write_object( uint16_t byte_addr, void *obj_p, uint16_t obj_size);
    extern void EEPROM_read_object( uint16_t byte_addr, void *obj_p, uint16_t obj_size);
    void wait(uint32 time);


    uint8_t Tx_Data[10] = {0x45, 0x19, 0xA1, 0xA2, 0x25, 0xA4, 0xA5, 0xA6, 0xB5, 0x12};
    uint8_t Rx_Data[10] = { 0 };

    /* USER CODE END */

    int main(void)
    {
    /* USER CODE BEGIN (3) */

    i2cInit();

    EEPROM_write_object(0x0001, Tx_Data, 10);

    EEPROM_read_object(0x0001, Rx_Data, 10);

    EEPROM_write_object(0x0010, Tx_Data, 10);

    EEPROM_read_object(0x0010, Rx_Data, 10);

    asm(" nop");

    while(1);

    /* USER CODE END */


    }

    at24c256.c

    /**
    ******************************************************************************
    * @file at24c256.c
    * @author Rahul
    * @brief This file contains read/write functions for EEPROM (AT24C256).
    ******************************************************************************
    */

    /* Includes ------------------------------------------------------------------*/
    #include "at24c256.h"
    #include "i2c.h"

    /** @addtogroup <Write Group name>
    * @{
    */

    /** @defgroup <Write Module name>
    * @brief <Give Breif>
    * @{
    */

    /* External variables --------------------------------------------------------*/
    /* Private typedef -----------------------------------------------------------*/
    /* Private defines -----------------------------------------------------------*/
    #define SLAVE_ADDRESS 0x50

    /* Private macros ------------------------------------------------------------*/
    /* Private variables ---------------------------------------------------------*/
    /* Private function prototypes -----------------------------------------------*/
    /* Private functions ---------------------------------------------------------*/


    /**
    * @brief This function is used to write data to EEPROM
    * @param byte_addr: byte address; *obj_p: pointer to the data; obj_size: size of data
    * @retval None
    */
    void EEPROM_write_object( uint16_t byte_addr, void *obj_p, uint16_t obj_size)
    {

    uint8_t word_addr[2], *tx_data = obj_p;

    memcpy(word_addr, (const void *) &byte_addr, sizeof(word_addr));

    i2cSetSlaveAdd(i2cREG1, SLAVE_ADDRESS); /* Configure address of Slave to talk to */

    i2cSetDirection(i2cREG1, I2C_TRANSMITTER); /* Set direction to Transmitter */

    i2cSetCount(i2cREG1, obj_size + sizeof(word_addr)); /* Configure Data count */

    i2cSetMode(i2cREG1, I2C_MASTER); /* Set mode as Master */

    i2cSetStop(i2cREG1); /* Set Stop after programmed Count */

    i2cSetStart(i2cREG1); /* Transmit Start Condition */

    i2cSend(i2cREG1, sizeof(word_addr), word_addr); /* Transmit word address */

    i2cSend(i2cREG1, obj_size, tx_data); /* Transmit data */

    while(i2cIsBusBusy(i2cREG1) == true); /* Wait until Bus Busy is cleared */

    while(i2cIsStopDetected(i2cREG1) == 0); /* Wait until Stop is detected */

    i2cClearSCD(i2cREG1); /* Clear the Stop condition */

    }

    /**
    * @brief This function is used to read data from EEPROM
    * @param byte_addr: byte address; *obj_p: pointer to the data; obj_size: size of data
    * @retval None
    */
    void EEPROM_read_object( uint16_t byte_addr, void *obj_p, uint16_t obj_size)
    {

    uint8_t word_addr[2], *rx_data = obj_p;

    memcpy(word_addr, (const void *) &byte_addr, sizeof(word_addr));

    while(i2cIsMasterReady(i2cREG1) != true); /* wait until MST bit gets cleared, this takes few cycles after Bus Busy is cleared */

    i2cSetSlaveAdd(i2cREG1, SLAVE_ADDRESS); /* Configure address of Slave to talk to */

    i2cSetDirection(i2cREG1, I2C_TRANSMITTER); /* Set direction to Transmitter */

    i2cSetCount(i2cREG1, sizeof(word_addr)); /* Configure Data count */

    i2cSetMode(i2cREG1, I2C_MASTER); /* Set mode as Master */

    i2cSetStop(i2cREG1); /* Set Stop after programmed Count */

    i2cSetStart(i2cREG1); /* Transmit Start Condition */

    i2cSend(i2cREG1, sizeof(word_addr), word_addr); /* Send the Word Address */

    while(i2cIsBusBusy(i2cREG1) == true); /* Wait until Bus Busy is cleared */

    while(i2cIsStopDetected(i2cREG1) == 0); /* Wait until Stop is detected */

    i2cClearSCD(i2cREG1); /* Clear the Stop condition */

    while(i2cIsMasterReady(i2cREG1) != true); /* wait until MST bit gets cleared, this takes few cycles after Bus Busy is cleared */

    i2cSetSlaveAdd(i2cREG1, SLAVE_ADDRESS); /* Configure address of Slave to talk to */

    i2cSetDirection(i2cREG1, I2C_RECEIVER); /* Set direction to receiver */

    i2cSetCount(i2cREG1, obj_size); /* Configure Data count */

    i2cSetMode(i2cREG1, I2C_MASTER); /* Set mode as Master */

    i2cSetStop(i2cREG1); /* Set Stop after programmed Count */

    i2cSetStart(i2cREG1); /* Transmit Start Condition */

    i2cReceive(i2cREG1, obj_size, rx_data); /* Transmit data */

    while(i2cIsBusBusy(i2cREG1) == true); /* Wait until Bus Busy is cleared */

    while(i2cIsStopDetected(i2cREG1) == 0); /* Wait until Stop is detected */

    i2cClearSCD(i2cREG1); /* Clear the Stop condition */

    }

    /******************END OF FILE**************************************************/

  • Hello,

    Both read and write functions check the stop bit , so the code looks fine to me. Do you mean add delay between each function call in your main()? How many cycles is needed?

    EEPROM_write_object(0x0001, Tx_Data, 10);

    delay()  ----- How many cycles?

    EEPROM_read_object(0x0001, Rx_Data, 10);

    delay()

    EEPROM_write_object(0x0010, Tx_Data, 10);

    delay()

    EEPROM_read_object(0x0010, Rx_Data, 10);

  • We have tried with 3mS delay, it working fine.

    Will it be possible to execute the same code without delay?

  • There is no restriction from I2C master side (TMS570). Please check datasheet of EEPROM to see if it has this requirement. 

    Without delay, does the I2C master generate start bit and send slave address properly?