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/TMS570LC4357: i2cReceive() issue

Part Number: TMS570LC4357
Other Parts Discussed in Thread: HALCOGEN

Tool/software: Code Composer Studio

Hi All,

I am trying to build an interrupt based i2c receiver application for the tms570lc43 MCU. I am fighting with a strange behavior in receiving data. I am using the i2c module in interrupt mode, 7bit address, 8 bit data, no FDF, receiver mode, "ignore Nack" option set , HL_i2c.c driver.

I can successfully complete a data transfer only if 2 data bytes are transferred (1 byte i2c slave address with R/W = 0, 1 byte register address, 1 data byte and i2CReceive() called with len = 2). If I try to transfer more that 2 bytes (len>2) then everything fails.

Looking the signals at the scope I can clearly see that after the 2nd byte reception then SCL line is tied to '0' by the I2C receiver module for an indefinite time and the transfer definitely doesn't succeed. It seems like the receiver forced to stop the transmission and some point, but I was not able to identify where and how it could happen.

Does anybody experienced the same issue? Conversely, does anybody succeeded in receiving more than 2 bytes in his TMS570 i2c slave application?

I was not able to identify the complete mechanism that could infer this kind of blocking condition. I tried to configure the i2c receiver SCL line as an input (Halcogen) to exclude the chance for it to set the line to '0' but it didn't have any effect (why not?)  Does anybody have some hints on this?

I spent quite a long time investigating on this issue. I am going to change my project setting to stay with this limit of 2 data bytes transfers although this is very frustrating. I would appreciate very much if someone

that have a clue on this could help me understanding how to step forward.

Thanks a lot in advance.

  • Hello Massimo,

    Can you provide more details on 'everything fails'? You mention you are using interrupt mode. Do you properly receive interrupts for the 2 byte transfer? Can you determine if it is the MCU or the slave device that is driving the SCL low? One of the key attributes of I2C is that the lines are only driven low and transitions to high are handled via external pullups so that the timing can be maintained. i.e., the I2C lines are generally open drain so it is possible that the slave is driving the signal for SCL low. If this is the case, then you need to determine what went wrong on the slave end of the bus. This means, was the correct register written to, was the data valid, did the data cause the slave to enter some sort of safe state?

    Often, for I2C development, it is best to develop the I2C application/driver separate from an unknown slave. What I mean by this is that it might be beneficial to connect a device that has been used previously so that you know that the addressing and data are valid. This will help to isolate if the issue is in your source code on the MCU or in the slave device.

    Also, if you can post some code snippets or even a simplified project file, we can review it to see if we can help determine if there might be any issues in your code.
  • Hello Chuck,
    I can correctly receive and process interrupts for the 2 bytes transfer. The only issue I see in 2 byte transfer is that at the end after the last scl falling edge scl is forced low for 100--200 us. Following transfers doesn't succeed, only the first after the cpu reset works.

    I am using a TMS570 HDK Safety MCU kit. I2C1 is used as the Master Transmitter I2C module (polling mode), I2C1 is used as the slave receiver (interrupt mode). I use two flying wires to connect SCL and SDA (pull-ups are installed on the board).
    Trasmission with disconnected wires is correct with every number of bytes in the transfer.

    I am sure that the slave is driving low the scl, I verified it with the scope.

    Here is some code segments from my application (the slave receiver part):

    /**************************************************************************************************************/
    #define MAX_PAR_NUM 1

    char buffer[ MAX_PAR_NUM +1 ]

    void myslave_init(void){
    i2cSetMode(I2CREG2, I2C_SLAVE);
    i2cSetDirection(I2CREG2, I2C_RECEIVER);
    i2cSetOwnAdd(I2CREG2, CCI.i2cadd );

    i2cEnableNotification(I2CREG2, I2C_RX_INT | I2C_SCD_INT | I2C_AAS_INT );
    i2cReceive(I2CREG2, MAX_PAR_NUM+1 ,buffer);
    }


    /**************************************************************************************************************/
    void BEE_CCI_isr(int flags){

    if (flags & I2C_SCD_INT){
    printf("I2C Stop Condition Detected\n"); //just for debug, will be removed
    i2cClearSCD(I2CREG2);
    }

    if (flags & I2C_AAS_INT){
    printf("I2C this slave Add det.\n");//just for debug, will be removed
    }

    if (flags & I2C_RX_INT){
    printf("I2C received cmd %02Xh -> (%02Xh)\n" , buffer[0]
    , buffer[1]);//just for debug, will be removed
    i2cReceive(CCI.i2c, MAX_PAR_NUM+1 ,buffer);

    }
    }

    /**************************************************************************************************************/

    and from the "HL_notification.c":

    /**************************************************************************************************************/
    /* USER CODE BEGIN (11) */
    extern void BEE_CCI_isr(int flags);
    /* USER CODE END */
    #pragma WEAK(i2cNotification)
    void i2cNotification(i2cBASE_t *i2c, uint32 flags)
    {
    /* enter user code between the USER CODE BEGIN and USER CODE END. */
    /* USER CODE BEGIN (24) */
    BEE_CCI_isr((int) flags);
    /* USER CODE END */
    }
    /**************************************************************************************************************/

    The i2cInit() s called in the main().

    MAX_PAR_NUM == 1 translates in a 2 bytes data transfer + the initial i2c slave address with R/W bit set to '0' (3 bytes total).

    printf() doesn't have any impact on the issue. The issue is always there even when printf are removed.

    Thank you for any help.
    Massimo
  • Hello Massimo,

    Thanks for posting the additional information. I'll have a look at this in more detail to see if I can spot where the trouble is coming from and get back with you.
  • Hello Massimo,

    My apologies for the delay in getting back to you on this post. Looking at the code excerpts provided, it seems you may be calling I2CReceive a second time before all of the data has been sent. This would cause the receive to be truncated. you should gate the call to the I2CReceive function with a check of the busy bit to make sure the I2C module is not in the middle of another transfer.

    Also, have you had a look at the I2C examples included with HalCoGen. There are several very good code examples covering I2C Slave or Master Tx/Rx, I2C in interrupt mode, or general I2C communication in polling mode. To get to the examples click Help-->Examples and navigate to the TMS570LC43x directory to see of the different 'c' examples that are available.

    You may also want to consider testing your code in loopback mode to make sure each component is working on its own. The examples cover how to put the module in loopback mode for testing/early development.
  • Dear Chuck,

    I actually appreciate your help very much. In the meanwhile I decided to change the interface to SPI for this project. Anyway I will apply your hints and try to fix my application also for I2c interfaces.  I am always hungry about code or project examples, but always fight looking for them. Could you please provide me with some links for them?

    Thank you very much for your help. I'll be back soon with updates. Kind Regards, Massimo.

  • Hello Massimo,

    The examples are included with HalCoGen and installed under the HalCoGen directory. You can get to them as I mentioned before using the Help menu within HalCoGen or by browsing directly to them using a file explorer window. If you used the default install location for Halcogen, they would be at this location: C:\ti\Hercules\HALCoGen\v04.06.00\examples noting that the HalCoGen version directory could be different dependent on which version you are using.