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.

AM2634: I2C Bus Hanging Issues with MCAL Version AM263x 08.06.02 and Cdd_I2c Driver

Part Number: AM2634

Hi,

this is my first time working with Sitara and posting a question here, so please bear with me if the question seems somewhat unusual :)

I have occasional I2C bus hanging due to arbitration loss after an "ungraceful" reset. How can I address this?

Before initiating any I2C communication, I call the Cdd_I2c_Init function. However, due to the design, it's impossible to call Cdd_I2c_DeInit before a "warm-start" reset.

I'm using the MCAL Version AM263x 08.06.02, and I'm utilizing the Cdd_I2c Driver included in that package.

As a workaround, I modified the startup sequence to run Cdd_I2c_Init, Cdd_I2c_DeInit, and then Cdd_I2c_Init again to reset the I2C peripheral. This approach has somewhat helped, but I'm still facing issues with the bus hanging. To address the remaining hanging issues, I set the CddI2cArbitrationLossParam variable to CDD_I2C_RECURRENT_MODE, aiming to send 9 clock pulses to the slave to synchronize the bus - but this hasn't been effective.

Of course, there might be issues with the target I'm communicating with, but do you have any suggestions on what I can do from the microcontroller side to resolve the I2C bus hanging, despite resetting the I2C peripheral and using CDD_I2C_RECURRENT_MODE?

Additionally, I'm using the I2C1 instance in polling mode and running the communication at a 100KHz bitrate.

Moreover, in Code Composer, I see the hang in Cdd_I2c_Polling_Mode_Receive, specifically in the while loop on line 509. The IsrStatus variable holds the value 400h.

Any suggestions for improving the implementation are most welcome.
Many thanks,
Mikael

  • Hi Mikael,

    The AM263x Control Card uses I2C0 and I2C2 ports as controller for EEPROM, Temperature sensor, LED driver etc. The MCAL includes an I2C example of reading/writing data to an on-board EEPROM. The example is located in .\mcal\examples\I2c

    How did you generate MCAL I2C configuration file?

  • Hi, I'm using I2C1 primarily to read the date and time from an RTC, with occasional writes to update the RTC. I'd like to mention that reading from the bus usually works well. I'm aware of the examples in the folder you mentioned and have implemented the read and write operations similarly.

    The configuration is essentially a two-parter: i) it is adapted from examples_config\I2c_Demo_Cfg\ to fit my needs, and ii) I have also configured the I2C1 instance in the .syscfg. Perhaps these two configurations are conflicting or overwriting each other. Do you think that's the case? I've tried removing the configuration in the .syscfg, but I still encounter the same issue.

  • Hi Mike,

    Do you add a sequence and a channel for writing data to RTC using I2C1 (HW_UNIT_1)? For example channel 5 and channel 6 in my EB config:

    Did you enable the interrupt for I2C1? The MCAL driver doesn't have function to enable/disable module's interrupt.

  • In my Cdd_I2c_Cfg.c file, I have a similar configuration to yours. However, I'm only using CDD_I2C_HW_UNIT 1, not 0 or 2, configured for channels 0 and 1.

    Also, I didn't enable interrupts for the I2C1 instance - it's running entirely in polling mode.

  • Hi Mikael,

    I am sorry for late response. I did a test this morning using MCAL driver. I sent message to I2C slave (aardvark), but I didn't see the data on I2C1 bus. I am investigating if I2C1 is supported in the MCAL driver. 

  • No worries about the late reply. Thank you for further testing and investigating the issue.

  • Hi Mikael,

    The I2C1 of MCAL driver works. I configured I2C to write data without slave attached, and probed the SCL/SDA pins on AM263x CC dock card. I got the correct clock signal, and data signal: slave address is 0x32, write mode. 

  • attached are the MCAL I2C and Port configuration file generated by EB Tresos:

    7510.Port_PBcfg.c
    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    /* ======================================================================
    * Copyright (c) 2022-2023 Texas Instruments Incorporated
    *
    * All rights reserved. Property of Texas Instruments Incorporated.
    * Restricted rights to use, duplicate or disclose this code are
    * granted through contract.
    *
    * The program may not be used without the written permission
    * of Texas Instruments Incorporated or against the terms and conditions
    * stipulated in the agreement under which this program has been
    * supplied.
    * ==================================================================== */
    /**
    * \file Port_PBcfg.c
    *
    * \brief This file contains generated post build configuration file
    * for PORT MCAL driver
    *
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    Cdd_I2c_Cfg.c
    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    /* ======================================================================
    * Copyright (C) 2022 Texas Instruments Incorporated
    *
    * All rights reserved. Property of Texas Instruments Incorporated.
    * Restricted rights to use, duplicate or disclose this code are
    * granted through contract.
    *
    * The program may not be used without the written permission
    * of Texas Instruments Incorporated or against the terms and conditions
    * stipulated in the agreement under which this program has been
    * supplied.
    * ==================================================================== */
    /**
    * \file Cdd_I2c_Cfg.c
    *
    * \brief This file contains generated pre compile configurations
    * for CDD I2C MCAL driver
    *
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    Port_Cfg.hCdd_I2c_Cfg.h

    The following are the app file to run I2C test:

    I2cApp.c
    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    /* ======================================================================
    * Copyright (c) 2022 Texas Instruments Incorporated
    *
    * All rights reserved. Property of Texas Instruments Incorporated.
    * Restricted rights to use, duplicate or disclose this code are
    * granted through contract.
    *
    * The program may not be used without the written permission
    * of Texas Instruments Incorporated or against the terms and conditions
    * stipulated in the agreement under which this program has been
    * supplied.
    * ==================================================================== */
    /**
    * \file I2cExample.c
    *
    * \brief This file contains the I2c test example
    */
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    I2cApp_Startup.c
    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    /*
    *
    * Copyright (c) 2023 Texas Instruments Incorporated
    *
    * All rights reserved not granted herein.
    *
    * Limited License.
    *
    * Texas Instruments Incorporated grants a world-wide, royalty-free, non-exclusive
    * license under copyrights and patents it now or hereafter owns or controls to make,
    * have made, use, import, offer to sell and sell ("Utilize") this software subject to the
    * terms herein. With respect to the foregoing patent license, such license is granted
    * solely to the extent that any such patent is necessary to Utilize the software alone.
    * The patent license shall not apply to any combinations which include this software,
    * other than combinations with devices manufactured by or for TI ("TI Devices").
    * No hardware patent is licensed hereunder.
    *
    * Redistributions must preserve existing copyright notices and reproduce this license
    * (including the above copyright notice and the disclaimer and (if applicable) source
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • I2C slave (0x32) received the data from AM263x I2C1. The I2C slave is total phase I2C adaptor:

    probed I2C signals 

    0246.I2cApp_Startup.c
    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    /*
    *
    * Copyright (c) 2023 Texas Instruments Incorporated
    *
    * All rights reserved not granted herein.
    *
    * Limited License.
    *
    * Texas Instruments Incorporated grants a world-wide, royalty-free, non-exclusive
    * license under copyrights and patents it now or hereafter owns or controls to make,
    * have made, use, import, offer to sell and sell ("Utilize") this software subject to the
    * terms herein. With respect to the foregoing patent license, such license is granted
    * solely to the extent that any such patent is necessary to Utilize the software alone.
    * The patent license shall not apply to any combinations which include this software,
    * other than combinations with devices manufactured by or for TI ("TI Devices").
    * No hardware patent is licensed hereunder.
    *
    * Redistributions must preserve existing copyright notices and reproduce this license
    * (including the above copyright notice and the disclaimer and (if applicable) source
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • Great, perhaps you can offer ideas on solving the initial question posted above.

  • I'm using the MCAL Version AM263x 08.06.02, and I'm utilizing the Cdd_I2c Driver included in that package.

    Can you use a newer version? I am using MCAL 9.00.01

  • Hi, I already tested that version and experienced the same issue. Comparing the two versions, I didn't notice any significant changes, especially nothing affecting Cdd_I2c_Init or its direct dependencies, as far as I can see anyways. This leads me to believe that upgrading to that version is not going to improve my startup sequence anyhow, and, as mentioned, testing shows it doesn't. Or do you have something else in mind that the new version will solve?

  • If the address of slave on the bus doesn't match the address in the I2C data frame sent by I2C master, the master will receive a NACK and end the transmission. 

    You said that IsrStatus =0x400 ( IsrStatus = Cdd_I2c_Isr_Check(HwUnit);), NACK is not set, data RX ready is not set.

    Is the I2C1 pinmux configured correctly? Does the slave and master have the same settings: address mode? 

  • Well, the I2C1 mux appears correctly configured, as it always works after power-on, and communication is fine.

    Correct, I read IsrStatus=0x400 after an "ungraceful" software reset (not running Cdd_I2c_DeInit). The driver never recovers from that - it doesn't timeout nor try to reset the I2C peripheral.

  • I2C is an open drain bus. If any slave holds the SDA line low, the master will detect it as a arbitration lost. Can you investigate who is pulling SDA line low?

    If you have multiple slaves on the bus, can you remove the slave one by one and identify the offending device?

    Does your code inadvertently change the IRS bit in ICMDR register after "ungraceful" reset? Resetting IRS bit during transfer will cause the I2C bus hang. What is the value of INTCODE in IVR register?

    Are you able to reproduce the symptom (I2C bus hung) by forcing a reset at a point while reading from an I2C slave who is sending a zero?

  • Hi, yes, I believe we are nearing my main question. For context, I have only one slave device on the I2C bus, which, as you mentioned, might hold the SDA line low. So far, so good.

    In the Cdd_I2c.c file, there's a comment on line 178 stating that calling Cdd_I2c_DeInit will put the I2C peripheral into reset mode. That's why I'm running Cdd_I2c_DeInit in the startup sequence, which seems to help in some cases.

    But, my real question is: Is there a way to improve the startup sequence, regardless of the failing slave, without having to call Cdd_I2c_Init, Cdd_I2c_DeInit, and then Cdd_I2c_Init again before starting communication?

    Additionally, is it possible to send a series of clock pulses (by toggling the SCL line) to help release the SDA line if a slave device is stuck? I'm unsure which API to use for this, or if you could direct me to the right one, or perhaps share some code that I could add to my project to implement such a feature?

  • In the Cdd_I2c.c file, there's a comment on line 178 stating that calling Cdd_I2c_DeInit will put the I2C peripheral into reset mode. That's why I'm running Cdd_I2c_DeInit in the startup sequence, which seems to help in some cases.

    I2C_init() brings the I2C out of reset (MDR.IRS=1), and I2C_Deinit() puts the I2C to reset state. The Cdd_I2c_Init() assumes the I2C is in reset state, otherwise the frequency will not be programmed.  

    If the I2C module has been initialized (IDLE mode), calling Cdd_I2c_Init() will not reconfig the I2C module. The Cdd_I2c_DeInit() should be called first, if you want to reconfigure the I2C module. 

    Can you check if the I2C module is in reset state before calling I2C_init() API?

    is it possible to send a series of clock pulses (by toggling the SCL line) to help release the SDA line if a slave device is stuck? I'm unsure which API to use for this, or if you could direct me to the right one, or perhaps share some code that I could add to my project to implement such a feature?

    I don't think so. Since I2C is an open drain bus, I2C master or slave can only pull the SDA LOW not HIGH. 

  • Can you check if the I2C module is in reset state before calling I2C_init() API?

    Yes, that might actually improve my startup sequence and make it look nicer. However, I'm unsure how to check if the I2C peripheral is in a reset state. How can I verify that with the Cdd driver?

    I don't think so. Since I2C is an open drain bus, I2C master or slave can only pull the SDA LOW not HIGH. 

    Okay, I was referring to the SCL, but I understand your point. My question arises because there's a comment in the newer driver version (including the one I use), at line 119 in Cdd_I2c_Cfg.c, stating "For sending 9 clock pulses to the slave in order to synchronize the bus." That's the functionality I aim to trigger, but I'm unsure how to do so.

  • I2C module is in the reset state if ICMDR.IRS = 0

    The I2C clock is generated when sending data on SDA line.