AM2634: I2C card to card Commincation

Part Number: AM2634

Tool/software:

@@�

Starting QSPI Bootloader ... 

KPI_DATA: [BOOTLOADER_PROFILE] Boot Media       : NOR SPI FLASH 

KPI_DATA: [BOOTLOADER_PROFILE] Boot Media Clock : 80.000 MHz 

KPI_DATA: [BOOTLOADER_PROFILE] Boot Image Size  : 96 KB 

KPI_DATA: [BOOTLOADER_PROFILE] Cores present    : 

r5f0-0

KPI_DATA: [BOOTLOADER PROFILE] System_init                      :        371us 

KPI_DATA: [BOOTLOADER PROFILE] Drivers_open                     :         82us 

KPI_DATA: [BOOTLOADER PROFILE] LoadHsmRtFw                      :       8980us 

KPI_DATA: [BOOTLOADER PROFILE] Board_driversOpen                :         49us 

KPI_DATA: [BOOTLOADER PROFILE] CPU load                         :       2938us 

KPI_DATA: [BOOTLOADER PROFILE] SBL End                          :       5636us 

KPI_DATA: [BOOTLOADER_PROFILE] SBL Total Time Taken             :      18059us 



Image loading done, switching to application ...

[MCAN] Initializing...
[MCAN] Configuring FIFO Mode...
[MCAN-0] 62 Config complete. Mode = FIFO
[MCAN] Initialization complete.
[MCAN] Initializing...
[MCAN] Configuring FIFO Mode...
[MCAN-1] 62 Config complete. Mode = FIFO
[MCAN] Initialization complete.

 FSI_initTx : Successful 

 FSI_initRx : Successful 

 Top[1] Bottom[0] Card Pos[00] CtlrId[03] UniqueID[03]
 Top[1] Bottom[0] Card Pos[00] CtlrId[03] UniqueID[03]
[I2C] Switching role to TARGET...

 11111!

 2222!

 before deinit 
 after deinit [0]
 close result[0]
[I2C] C2C Handle closed!

[I2C] C2C Handle reopened successfully.

[I2C]4444

[I2C]6666

[I2C] Role switched to TARGET. RX armed.

[I2C Init] C2C Initialized. SelfAddr: 0x03, PeerAddr: 0x07

[I2C] First Window expired or skipped. CardPos 0 promoting to CONTROLLER... [1114]

[I2C] Switching role to CONTROLLER...

[I2C PROBE] Peer [7] NOT responding - Status = -1

 11111!

 2222!

 before deinit 
 after deinit [0]
 close result[0]
[I2C] C2C Handle closed!

[I2C] C2C Handle reopened successfully.

[I2C] Role switched to CONTROLLER. Ready to send/receive. peerProbe[0]

[I2C] Current Role: CONTROLLER

 --- Excuting [0] ----gVar[0] 

[I2C] Current Role: CONTROLLER
 
 Coner 23:  
 Rx : 
 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
  --- exit callback 

 --- Excuting [1] ----gVar[255] 

[I2C] Current Role: CONTROLLER
 
 Coner 23:  
 Rx : 
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  --- exit callback 

 --- Excuting [2] ----gVar[0] 

[I2C] Current Role: CONTROLLER
 
 Coner 23:  
 Rx : 
 01 01 01 01 01 01 01 01 01 01 00 00 00 00 00 00 00 00 00 00
  --- exit callback 

 --- Excuting [3] ----gVar[1] 

[I2C] Current Role: CONTROLLER
 
 Coner 23:  
 Rx : 
 02 02 02 02 02 02 02 02 02 02 00 00 00 00 00 00 00 00 00 00
  --- exit callback 

 --- Excuting [4] ----gVar[2] 

[I2C] Current Role: CONTROLLER
 
 Coner 23:  
 Rx : 
 03 03 03 03 03 03 03 03 03 03 00 00 00 00 00 00 00 00 00 00
  --- exit callback 

 --- Excuting [5] ----gVar[3] 

[I2C] Current Role: CONTROLLER
 
 Coner 23:  
 Rx : 
 04 04 04 04 04 04 04 04 04 04 00 00 00 00 00 00 00 00 00 00
  --- exit callback 

 --- Excuting [6] ----gVar[4] 

[I2C] Current Role: CONTROLLER
 
 Coner 23:  
 Rx : 
 05 05 05 05 05 05 05 05 05 05 00 00 00 00 00 00 00 00 00 00
  --- exit callback 

 --- Excuting [7] ----gVar[5] 

[I2C] Current Role: CONTROLLER
 
 Coner 23:  
 Rx : 
 06 06 06 06 06 06 06 06 06 06 00 00 00 00 00 00 00 00 00 00
  --- exit callback 

 --- Excuting [8] ----gVar[6] 

[I2C] Current Role: CONTROLLER
 
 Coner 23:  
 Rx : 
 07 07 07 07 07 07 07 07 07 07 00 00 00 00 00 00 00 00 00 00
  --- exit callback 

 --- Excuting [9] ----gVar[7] 

[I2C] Current Role: CONTROLLER
 
 Coner 23:  
 Rx : 
 08 08 08 08 08 08 08 08 08 08 00 00 00 00 00 00 00 00 00 00
  --- exit callback 

 --- Excuting [10] ----gVar[8] 

[I2C] Current Role: CONTROLLER
 
 Coner 23:  
 Rx : 
 09 09 09 09 09 09 09 09 09 09 00 00 00 00 00 00 00 00 00 00
  --- exit callback 

 --- Excuting [11] ----gVar[9] 

[I2C] Current Role: CONTROLLER
 
 Coner 23:  
 Rx : 
 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 00 00 00 00 00 00 00 00 00 00
  --- exit callback 

 --- Excuting [12] ----gVar[10] 

[I2C] Current Role: CONTROLLER

[I2C] Switching role to TARGET...

 11111!

 2222!

 before deinit 
 after deinit [0]
 close result[0]
[I2C] C2C Handle closed!

[I2C] C2C Handle reopened successfully.

[I2C]4444

[I2C]6666

[I2C] Role switched to TARGET. RX armed.

 --- Excuting [13] ----gVar[11] 

[I2C] Current Role: TARGET

[I2C] Target RX armed and role set to TARGET.

 --- Excuting [14] ----gVar[11] 

[I2C] Current Role: TARGET

[I2C] Target RX armed and role set to TARGET.

 --- Excuting [15] ----gVar[11] 

[I2C] Current Role: TARGET

[I2C] Target RX armed and role set to TARGET.

 --- Excuting [16] ----gVar[11] 

[I2C] Current Role: TARGET

[I2C] Target RX armed and role set to TARGET.

 --- Excuting [17] ----gVar[11] 

[I2C] Current Role: TARGET

[I2C] Target RX armed and role set to TARGET.

 --- Excuting [18] ----gVar[11] 

[I2C] Current Role: TARGET

[I2C] Target RX armed and role set to TARGET.

 --- Excuting [19] ----gVar[11] 

[I2C] Current Role: TARGET

[I2C] Target RX armed and role set to TARGET.

[I2C] Switching role to CONTROLLER...

[I2C PROBE] Peer [7] NOT responding - Status = -1

 11111!

 2222!

 before deinit 
 after deinit [0]
 close result[0]
[I2C] C2C Handle closed!

[I2C] C2C Handle reopened successfully.

[I2C] Role switched to CONTROLLER. Ready to send/receive. peerProbe[0]

 --- Excuting [20] ----gVar[21] 

[I2C] Current Role: CONTROLLER
 
 Coner 23:  
 Rx : 
 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
  --- exit callback 

 --- Excuting [21] ----gVar[255] 

[I2C] Current Role: CONTROLLER
 
 Coner 23:  
 Rx : 
 14 14 14 14 14 14 14 14 14 14 00 00 00 00 00 00 00 00 00 00
  --- exit callback 

 --- Excuting [22] ----gVar[20] 

[I2C] Current Role: CONTROLLER
 
 Coner 23:  
 Rx : 
 15 15 15 15 15 15 15 15 15 15 00 00 00 00 00 00 00 00 00 00
  --- exit callback 

 --- Excuting [23] ----gVar[21] 

[I2C] Current Role: CONTROLLER
 
 Coner 23:  
 Rx : 
 16 16 16 16 16 16 16 16 16 16 00 00 00 00 00 00 00 00 00 00
  --- exit callback 

Starting QSPI Bootloader ... 

KPI_DATA: [BOOTLOADER_PROFILE] Boot Media       : NOR SPI FLASH 

KPI_DATA: [BOOTLOADER_PROFILE] Boot Media Clock : 80.000 MHz 

KPI_DATA: [BOOTLOADER_PROFILE] Boot Image Size  : 96 KB 

KPI_DATA: [BOOTLOADER_PROFILE] Cores present    : 

r5f0-0

KPI_DATA: [BOOTLOADER PROFILE] System_init                      :        371us 

KPI_DATA: [BOOTLOADER PROFILE] Drivers_open                     :         82us 

KPI_DATA: [BOOTLOADER PROFILE] LoadHsmRtFw                      :       8979us 

KPI_DATA: [BOOTLOADER PROFILE] Board_driversOpen                :         49us 

KPI_DATA: [BOOTLOADER PROFILE] CPU load                         :       2938us 

KPI_DATA: [BOOTLOADER PROFILE] SBL End                          :       5636us 

KPI_DATA: [BOOTLOADER_PROFILE] SBL Total Time Taken             :      18058us 



Image loading done, switching to application ...

[MCAN] Initializing...
[MCAN] Configuring FIFO Mode...
[MCAN-0] 62 Config complete. Mode = FIFO
[MCAN] Initialization complete.
[MCAN] Initializing...
[MCAN] Configuring FIFO Mode...
[MCAN-1] 62 Config complete. Mode = FIFO
[MCAN] Initialization complete.

 FSI_initTx : Successful 

 FSI_initRx : Successful 

 Top[1] Bottom[0] Card Pos[01] CtlrId[03] UniqueID[07]
 Top[1] Bottom[0] Card Pos[01] CtlrId[03] UniqueID[07]
[I2C] Switching role to TARGET...

 11111!

 2222!

 before deinit 
 after deinit [0]
 close result[0]
[I2C] C2C Handle closed!

[I2C] C2C Handle reopened successfully.

[I2C]4444

[I2C]6666

[I2C] Role switched to TARGET. RX armed.

[I2C Init] C2C Initialized. SelfAddr: 0x07, PeerAddr: 0x03

[I2C] First Window expired or skipped. CardPos 1 staying as TARGET... [1114]

[I2C] Switching role to TARGET...

 11111!

 2222!

 before deinit 
 after deinit [0]
 close result[0]
[I2C] C2C Handle closed!

[I2C] C2C Handle reopened successfully.

[I2C]4444

[I2C]6666

[I2C] Role switched to TARGET. RX armed.

[I2C] Current Role: TARGET

 --- Excuting [0] ----gVar[0] 

[I2C] Current Role: TARGET

[I2C] Target RX armed and role set to TARGET.
 
 Target :   Rx : 
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 Tx : 
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  --- exit callback 

 --- Excuting [1] ----gVar[0] 

[I2C] Current Role: TARGET

[I2C] Target RX armed and role set to TARGET.
 
 Target :   Rx : 
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 Tx : 
 01 01 01 01 01 01 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  --- exit callback 

 --- Excuting [2] ----gVar[1] 

[I2C] Current Role: TARGET

[I2C] Target RX armed and role set to TARGET.
 
 Target :   Rx : 
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 Tx : 
 02 02 02 02 02 02 02 02 02 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  --- exit callback 

 --- Excuting [3] ----gVar[2] 

[I2C] Current Role: TARGET

[I2C] Target RX armed and role set to TARGET.
 
 Target :   Rx : 
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 Tx : 
 03 03 03 03 03 03 03 03 03 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  --- exit callback 

 --- Excuting [4] ----gVar[3] 

[I2C] Current Role: TARGET

[I2C] Target RX armed and role set to TARGET.
 
 Target :   Rx : 
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 Tx : 
 04 04 04 04 04 04 04 04 04 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  --- exit callback 

 --- Excuting [5] ----gVar[4] 

[I2C] Current Role: TARGET

[I2C] Target RX armed and role set to TARGET.
 
 Target :   Rx : 
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 Tx : 
 05 05 05 05 05 05 05 05 05 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  --- exit callback 

 --- Excuting [6] ----gVar[5] 

[I2C] Current Role: TARGET

[I2C] Target RX armed and role set to TARGET.
 
 Target :   Rx : 
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 Tx : 
 06 06 06 06 06 06 06 06 06 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  --- exit callback 

 --- Excuting [7] ----gVar[6] 

[I2C] Current Role: TARGET

[I2C] Target RX armed and role set to TARGET.
 
 Target :   Rx : 
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 Tx : 
 07 07 07 07 07 07 07 07 07 07 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  --- exit callback 

 --- Excuting [8] ----gVar[7] 

[I2C] Current Role: TARGET

[I2C] Target RX armed and role set to TARGET.
 
 Target :   Rx : 
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 Tx : 
 08 08 08 08 08 08 08 08 08 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  --- exit callback 

 --- Excuting [9] ----gVar[8] 

[I2C] Current Role: TARGET

[I2C] Target RX armed and role set to TARGET.
 
 Target :   Rx : 
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 Tx : 
 09 09 09 09 09 09 09 09 09 09 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  --- exit callback 

 --- Excuting [10] ----gVar[9] 

[I2C] Current Role: TARGET

[I2C] Target RX armed and role set to TARGET.
 
 Target :   Rx : 
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 Tx : 
 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  --- exit callback 

 --- Excuting [11] ----gVar[10] 

[I2C] Current Role: TARGET

[I2C] Target RX armed and role set to TARGET.

[I2C] Switching role to CONTROLLER...

[I2C PROBE] Peer [3] NOT responding - Status = -1

 11111!

 2222!

 before deinit 
 after deinit [0]
 close result[0]
[I2C] C2C Handle closed!

[I2C] C2C Handle reopened successfully.

[I2C] Role switched to CONTROLLER. Ready to send/receive. peerProbe[0]

 --- Excuting [12] ----gVar[11] 

[I2C] Current Role: CONTROLLER

 --- Excuting [13] ----gVar[11] 

[I2C] Current Role: CONTROLLER

 --- Excuting [14] ----gVar[11] 

[I2C] Current Role: CONTROLLER

 --- Excuting [15] ----gVar[11] 

[I2C] Current Role: CONTROLLER

 --- Excuting [16] ----gVar[11] 

[I2C] Current Role: CONTROLLER

 --- Excuting [17] ----gVar[11] 

[I2C] Current Role: CONTROLLER

 --- Excuting [18] ----gVar[11] 

[I2C] Current Role: CONTROLLER

 --- Excuting [19] ----gVar[11] 

[I2C] Current Role: CONTROLLER

[I2C] Switching role to TARGET...

 11111!

 2222!

 before deinit 
 after deinit [0]
 close result[0]
[I2C] C2C Handle closed!

[I2C] C2C Handle reopened successfully.

[I2C]4444

[I2C]6666

[I2C] Role switched to TARGET. RX armed.

 --- Excuting [20] ----gVar[21] 

[I2C] Current Role: TARGET

[I2C] Target RX armed and role set to TARGET.
 
 Target :   Rx : 
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 Tx : 
 14 14 14 14 14 14 14 14 14 14 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  --- exit callback 

 --- Excuting [21] ----gVar[20] 

[I2C] Current Role: TARGET

[I2C] Target RX armed and role set to TARGET.
 
 Target :   Rx : 
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 Tx : 
 15 15 15 15 15 15 15 15 15 15 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  --- exit callback 

 --- Excuting [22] ----gVar[21] 

[I2C] Current Role: TARGET

[I2C] Target RX armed and role set to TARGET.
 
 Target :   Rx : 
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 Tx : 
 16 16 16 16 16 16 16 16 16 16 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  --- exit callback 

 --- Excuting [23] ----gVar[22] 

[I2C] Current Role: TARGET

[I2C] Target RX armed and role set to TARGET.
/*
 * Updated libI2C_C2C.c
 * Enhancements:
 * - Proper target-side RX arming
 * - Common callback usage
 * - Re-arming after reception
 * - Fully bidirectional HLD-based I2C C2C communication
 */

#include "libI2C_api.h"
#include <string.h>
#include "../hotStandBy.h"
#include "../2oo2Manager.h"
#include "../cardIdentity.h"
#include <kernel/dpl/SemaphoreP.h>

extern uint8_t gVar;

typedef struct
{
    volatile uint32_t I2C_ICOAR;
    volatile uint32_t I2C_ICIMR;
    volatile uint32_t I2C_ICSTR;
    volatile uint32_t I2C_ICCLKL;
    volatile uint32_t I2C_ICCLKH;
    volatile uint32_t I2C_ICCNT;
    volatile uint32_t I2C_ICDRR;
    volatile uint32_t I2C_ICSAR;
    volatile uint32_t I2C_ICDXR;
    volatile uint32_t I2C_ICMDR;
    volatile uint32_t I2C_ICIVR;
    volatile uint32_t I2C_ICEMDR;
    volatile uint32_t I2C_ICPSC;
    volatile uint32_t I2C_ICPID1;
    volatile uint32_t I2C_ICPID2;
    volatile uint32_t I2C_ICDMAC;
    volatile uint32_t I2C_I2C_RESERVED1;
    volatile uint32_t I2C_I2C_RESERVED2;
    volatile uint32_t I2C_ICPFUNC;
    volatile uint32_t I2C_ICPDIR;
    volatile uint32_t I2C_ICPDIN;
    volatile uint32_t I2C_ICPDOUT;
    volatile uint32_t I2C_ICPDSET;
    volatile uint32_t I2C_ICPDCLR;
    volatile uint32_t I2C_ICPDRV;
}I2C_REG;

#define I2C1   ((I2C_REG*)(I2C1_BASE_ADDRESS))

I2C_Handle gC2CI2CHandle = NULL;
I2C_Transaction gC2C_RxTxn = {0};

uint8_t tx_flag;
uint8_t rx_flag;

static u8 initC2CInit = FALSE;
static u8 isController = FALSE;
static u8 peerAvailable = FALSE;
static uint8_t cardUniqueId = 0;
static u8 ownAddress = 0;
static u8 peerAddress = 0;
static volatile u8 gI2CBusyFlag = I2C_BUSY_FLAG_CLEAR;



uint8_t gC2CTxBuf[MAX_TX_BUF] = {0};
uint32_t gC2CTxLength = 0U;
uint8_t gC2CRxBuf[MAX_RX_BUF] = {0};
uint32_t gC2CRxBufLgth = 0;
uint32_t actualReadCount = 0;
uint32_t actualWriteCount = 0;


#define APP_I2C_INT_MASK_ADRR_TARGET            (0x00000040U)
#define APP_I2C_INT_ADRR_TARGET                 (0x00000200U)

static void libI2C_reopenC2CHandle(void);
static void libI2C_disableInterrupt(uint32_t baseAddr, uint32_t intFlag);
static void libI2C_clearInterruptStatus(uint32_t baseAddr, uint32_t intFlag);
static int32_t libI2C_close(I2C_Handle handle);
static int32_t libI2C_lld_deInit(I2CLLD_Handle handle);
static void libI2C_ControllerDisable(uint32_t baseAddr);
static void libI2C_ControllerIntDisableEx(uint32_t baseAddr, uint32_t intFlag);

u8 *txI2CBuffer(void)
{
    return gC2CTxBuf;
}

u8 *rxI2CBuffer(void)
{
    return gC2CRxBuf;
}


u32 getC2CRxBuffLgth(void)
{
    return gC2CRxBufLgth;
}

u32 getC2CTxBuffLgth(void)
{
    return gC2CTxLength;
}

void setC2CTxBuffLgth(const u32 in)
{
    gC2CTxLength = in;
}

void setC2CRxBuffLgth(const u32 in)
{
    gC2CRxBufLgth = in;
}

#define SIMPLE
#ifdef SIMPLE
void I2C_Callback(I2C_Handle handle, I2C_Transaction *transaction, int32_t transferStatus)
{
    if(TRUE == isController)
    {
        CUSTOM_PRINT_DEBUG(" \n Coner 23:  \n");
        if (transferStatus == I2C_STS_SUCCESS)
        {
            //        if(rx_flag)
            if(transaction->readCount != 0)
            {
                CUSTOM_PRINT_DEBUG(" Rx : \n");
                printInHex(transaction->readBuf, transaction->readCount);

                u8 *buf = (u8 *)transaction->readBuf;
                                gVar = buf[0];
            }
            if(transaction->writeCount != 0)
            {
                CUSTOM_PRINT_DEBUG(" Tx : \n");
                printInHex(transaction->writeBuf, transaction->writeCount);
            }
            //            else
            //            {
            //                CUSTOM_PRINT("\n blunder [%s]",FUNC_NAME);
            //            }
        }
    }
    else
    {
        CUSTOM_PRINT_DEBUG(" \n Target :  ");

        if (transferStatus == I2C_STS_SUCCESS)
        {
            //        if(rx_flag)
            if((transaction->readCount != 0) && (transaction->readBuf != NULL))
            {
                CUSTOM_PRINT_DEBUG(" Rx : \n");
                printInHex(transaction->readBuf, 25);
            }

            if((transaction->writeCount != 0) && (transaction->writeBuf != NULL))
            {
                CUSTOM_PRINT_DEBUG(" Tx : \n");
                printInHex(transaction->writeBuf, 25);
                u8 *buf = (u8 *)transaction->writeBuf;
                gVar = buf[0];
            }
            //            else
            //            {
            //                CUSTOM_PRINT("\n blunder [%s]",FUNC_NAME);
            //            }
        }


    }


    HwiP_clearInt(handle->hwAttrs->intNum);
    HwiP_enableInt(handle->hwAttrs->intNum);
    CUSTOM_PRINT("  --- exit callback \n");
}

#else


void I2C_Callback(I2C_Handle handle, I2C_Transaction *transaction, int32_t transferStatus)
{
    if(TRUE == isController)
    {
        CUSTOM_PRINT_DEBUG(" \n Controller :  ");
        if (transferStatus == I2C_STS_SUCCESS)
        {
            if((transaction->readBuf !=NULL) && (transaction->writeBuf ==NULL ))
            {

                CUSTOM_PRINT_DEBUG(" Rx : Total_Bytes[%d] :  ",transaction->readCount);
                //printInHex(((u8 *)transaction->readBuf), transaction->readCount);
                ST_I2C_APP_HDR *hdr = (ST_I2C_APP_HDR *)&transaction->readBuf[0];
                u16 dataLgth = hdr->length - sizeof(ST_I2C_APP_HDR) -2U; // 2 is for crcs

                CUSTOM_PRINT_DEBUG(" [%s :%d] \n ",getI2CMsgString(hdr->msgId),dataLgth);
                switch(hdr->msgId)
                {
                case I2C_MSG_ID_HEALTH_HEARTBEAT:
                {
                    handleReceivedHotStandbyMessage(&transaction->readBuf[sizeof(ST_I2C_APP_HDR)],dataLgth);
                    break;
                }
                case I2C_MSG_ID_LOCO_DATA_SYNC_RESP:
                {
                    handleRcvdLocoDataRespMsg(&transaction->readBuf[sizeof(ST_I2C_APP_HDR)],dataLgth);
                    break;
                }
                default:
                    CUSTOM_PRINT("\n Invalid I2C MsgId \n");
                    break;
                }
            }
            else
            {
                ST_I2C_APP_HDR *hdr = (ST_I2C_APP_HDR *)&transaction->writeBuf[0];
                CUSTOM_PRINT_DEBUG(" Tx \t [%s :%d] -->Success \n ",getI2CMsgString(hdr->msgId),transaction->writeCount);
            }
        }
    }
    else
    {
        CUSTOM_PRINT_DEBUG(" \n Target :  ");
        //        if(rx_flag)
        if(transaction->readCount != 0)
        {
            //            CUSTOM_PRINT_DEBUG(" Rx \t Total_Bytes[%d] : ", actualReadCount);
            CUSTOM_PRINT_DEBUG(" Rx \t Total_Bytes[%d] : ", transaction->readCount);
            rx_flag=0;
            //printInHex(((u8 *)transaction->readBuf),actualReadCount);
            ST_I2C_APP_HDR *hdr = (ST_I2C_APP_HDR *)&transaction->readBuf[0];
            u16 dataLgth = hdr->length - sizeof(ST_I2C_APP_HDR) -2U; // 2 is for crc
            // crc valdiation can be done here

            CUSTOM_PRINT_DEBUG(" [%s(%d) :%d] \n ",getI2CMsgString(hdr->msgId),hdr->msgId,dataLgth);
            switch(hdr->msgId)
            {
            case I2C_MSG_ID_HEALTH_HEARTBEAT:
            {
                handleReceivedHotStandbyMessage(&transaction->readBuf[sizeof(ST_I2C_APP_HDR)],dataLgth);
                gC2CTxLength =  hdr->length;
                prepareTargetHeartbeatMsg(&gC2CTxBuf[0],&gC2CTxLength);
                break;
            }
            case I2C_MSG_ID_LOCO_DATA_SYNC_REQ:
            {
                actualWriteCount = 0;
                gC2CTxLength =  2123;
                fillSyncLocoDataInI2CTxBuff(&gC2CTxBuf[0],&gC2CTxLength);
                break;
            }
            case I2C_MSG_ID_LOCO_DATA_SYNC_RESP:
            {
                handleRcvdLocoDataRespMsg(&transaction->readBuf[sizeof(ST_I2C_APP_HDR)],dataLgth);
                break;
            }
            default:
                CUSTOM_PRINT("\n Invalid I2C MsgId \n");
                break;
            }
            actualReadCount = I2C_INVALID_RcTx_LGTH;
        }
        else if(transaction->writeCount != 0)
        {
            tx_flag = 0;
            ST_I2C_APP_HDR *hdr = (ST_I2C_APP_HDR *)&transaction->writeBuf[0];
            CUSTOM_PRINT_DEBUG(" Tx  \t [%s :%d] -->Success \n ",getI2CMsgString(hdr->msgId),actualWriteCount);
            actualWriteCount = I2C_INVALID_RcTx_LGTH;
        }
        else
        {
            CUSTOM_PRINT("\n blunder [%s]",FUNC_NAME);
        }

        libI2C_armTargetRx();
    }
    HwiP_clearInt(handle->hwAttrs->intNum);
    HwiP_enableInt(handle->hwAttrs->intNum);
}

#endif

#ifdef OLD_INIT
void libI2C_initC2C(const uint8_t selfId)
{

    cardUniqueId = selfId;
    libI2C_patchOwnAddress(cardUniqueId);

    gC2CI2CHandle = gI2cHandle[MY_CONFIG_I2C_INTERCARD_COMM];

    if (cardUniqueId == 3U)
    {
        peerCardId = 7U;
        isController = TRUE;
        peerAvailable = TRUE; // Assume peer is available for now
        ownAddress = cardUniqueId;
        peerAddress = 7U;
    }
    else if (cardUniqueId == 7U)
    {

        peerCardId = 3U;
        isController = FALSE;
        peerAvailable = TRUE; // Assume peer is available for now
        ownAddress = cardUniqueId;
        peerAddress = 3U;



#ifdef Old
        //        I2C_Transaction_init(&gC2C_RxTxn);
        gC2C_RxTxn.readBuf      = gC2CRxBuf;
        gC2C_RxTxn.readCount    = sizeof(gC2CRxBuf);

        gC2C_RxTxn.controllerMode=0;
        gC2C_RxTxn.writeBuf=gC2CTxBuf;
        gC2C_RxTxn.writeCount=sizeof(gC2CTxBuf);
        I2C_transfer(gC2CI2CHandle, &gC2C_RxTxn);
#else
        libI2C_armTargetRx();
#endif

    }
    else
    {
        peerCardId = 0xFFU;
        isController = FALSE;
        peerAvailable = FALSE; // Assume peer is available for now
        CUSTOM_PRINT("\n[WARNING] Unknown card ID 0x%02X. Defaulting to target.", selfId);
    }
}
#else

void libI2C_initC2C(const uint8_t selfId)
{
    cardUniqueId = selfId;

    ownAddress = cardUniqueId;//translateI2CAddress(selfId);

    libI2C_patchOwnAddress(ownAddress);

    gC2CI2CHandle = gI2cHandle[MY_CONFIG_I2C_INTERCARD_COMM];

    peerAddress = (selfId == T_CARD1_ADDR) ? T_CARD2_ADDR : T_CARD1_ADDR;

    /*
    if(CardId_isMasterCtrl() == TRUE)
    {
        peerAddress = (selfId == T_CARD1_ADDR) ? T_CARD2_ADDR : T_CARD1_ADDR;
        peerAddress = translateI2CAddress(peerAddress);
    }
    else if(CardId_isSlaveCtrl() == TRUE)
    {
        peerAddress = (selfId == B_CARD1_ADDR) ? B_CARD2_ADDR : B_CARD1_ADDR;
        peerAddress = translateI2CAddress(peerAddress);
    }
    else
    {

    }
     */


    peerAvailable = FALSE;

    libI2C_switchRoleToTarget();

    CUSTOM_PRINT("\n[I2C Init] C2C Initialized. SelfAddr: 0x%02X, PeerAddr: 0x%02X\n", ownAddress, peerAddress);
}

#endif

void libI2C_targetPrepareTxData(const u8 *data, u32 len)
{
    if ((len <= MAX_TX_BUF) && (data != NULL))
    {
        memcpy(gC2CTxBuf, data, len);
        gC2CTxLength = len;
    }
}

i32 libI2C_send(const u8 *txBuf, u32 length)
{
    i32 result = PEER_UNAVAILABLE;
    if ((txBuf == NULL) || (length == 0U))
    {
        CUSTOM_PRINT("\n Invalid Input Params in [%s] --> txBuf[%u] lgth[%d]\n",FUNC_NAME,
                     txBuf,length);
    }
    else
    {
        if (isController)
        {
            I2C_Transaction txn = {0};
            I2C_Transaction_init(&txn);
            txn.targetAddress = peerAddress; //
            txn.writeBuf = (void *)txBuf;
            txn.writeCount = length;
            txn.readBuf = NULL;
            txn.readCount = 0U;
            txn.controllerMode = 1;
            txn.timeout = MY_I2C_TRANSACTION_TIMEOUT;

            i32 status = I2C_transfer(gC2CI2CHandle, &txn);
            result = (status == I2C_STS_SUCCESS) ? (i32)length : status;
        }
        else
        {
            CUSTOM_PRINT("\n This is not controller I2C \n");
        }
    }
    return result;
}

i32 libI2C_receive(u8 *rxBuf, u32 length)
{
    i32 result = PEER_UNAVAILABLE;
    if ((rxBuf == NULL) || (length == 0U))
    {
        CUSTOM_PRINT("\n Invalid Input Params in [%s] --> rxBuffPtr[%u] lgth[%d]\n",FUNC_NAME,
                     rxBuf,length);
    }
    else
    {
        if (isController)
        {
            I2C_Transaction txn = {0};
            I2C_Transaction_init(&txn);
            txn.targetAddress = peerAddress;
            txn.writeBuf = NULL;

            txn.readBuf = rxBuf;
            txn.readCount = length;
            txn.controllerMode = TRUE;
            txn.timeout = MY_I2C_TRANSACTION_TIMEOUT;

            i32 status = I2C_transfer(gC2CI2CHandle, &txn);
            result = (status == I2C_STS_SUCCESS) ? (i32)length : status;
        }
        else
        {
            CUSTOM_PRINT("\n This is not controller I2C \n");
        }
    }
    return result;
}

u8 libI2C_probePeer(void)
{
    if (gC2CI2CHandle == NULL)
    {
        CUSTOM_PRINT("\n[I2C PROBE] I2C Handle is NULL.\n");
        return FALSE;
    }

    int32_t status = I2C_probe(gC2CI2CHandle, peerAddress);

    if (status == I2C_STS_SUCCESS)
    {
        CUSTOM_PRINT("\n[I2C PROBE] Peer [%d] acknowledged - READY\n",peerAddress);
        peerAvailable = TRUE;
    }
    else
    {
        CUSTOM_PRINT("\n[I2C PROBE] Peer [%d] NOT responding - Status = %d\n", peerAddress,status);
        peerAvailable = FALSE;
    }

    return peerAvailable;
}


u8 libI2C_healthCheckUpdate(void)
{
    static u8 consecutiveFailures = 0U;
    u8 peerAlive = libI2C_probePeer();

    if (peerAlive == FALSE)
    {
        consecutiveFailures++;

        if (consecutiveFailures >= 3U)
        {
            // Promote to controller if not already
            if (!isController)
            {
                isController = TRUE;
                CUSTOM_PRINT("\n[C2C] Peer not responding. Promoting to controller role.");
            }
        }
    }
    else
    {
        consecutiveFailures = 0U;
    }

    return peerAlive;
}

u8 isI2CController(void)
{
    return isController;
}

void libI2C_patchOwnAddress(const u8 myId)
{
    gC2CI2CHandle = gI2cHandle[MY_CONFIG_I2C_INTERCARD_COMM];

    if (gC2CI2CHandle != NULL)
    {
        I2C_HwAttrs *nonConstHwAttrs = (I2C_HwAttrs *)(gC2CI2CHandle->hwAttrs);
        nonConstHwAttrs->ownTargetAddr = myId;
        I2C1_BASE_ADDRESS = myId;
    }
}

void libI2C_armTargetRx(void)
{
    isController = FALSE;   // Ensure we are in TARGET mode

    memset(gC2CRxBuf, 0, sizeof(gC2CRxBuf));
    memset(&gC2C_RxTxn, 0, sizeof(gC2C_RxTxn));

    gC2C_RxTxn.readBuf = gC2CRxBuf;
    gC2C_RxTxn.readCount = sizeof(gC2CRxBuf);
    gC2C_RxTxn.controllerMode = 0;
    gC2C_RxTxn.writeBuf = gC2CTxBuf;
    gC2C_RxTxn.writeCount = sizeof(gC2CTxBuf);

    I2C_transfer(gC2CI2CHandle, &gC2C_RxTxn);
    CUSTOM_PRINT("\n[I2C] Target RX armed and role set to TARGET.\n");
}

#define SIMPLE
#ifdef SIMPLE

void libI2C_startupRoleDetection(uint8_t cardPos, uint32_t firstTimeoutMs, uint32_t secondTimeoutMs)
{
    uint32_t startTime = nowTickMs();
    uint32_t elapsedTime = 0U;

    if (cardPos == 0U)
    {
        CUSTOM_PRINT("\n[I2C] First Window expired or skipped. CardPos 0 promoting to CONTROLLER... [%u]\n", nowTickMs());
        //                        isController = TRUE;
        libI2C_switchRoleToController();
    }
    else
    {
        CUSTOM_PRINT("\n[I2C] First Window expired or skipped. CardPos 1 staying as TARGET... [%u]\n", nowTickMs());
        //                        isController = FALSE;
        //                        libI2C_armTargetRx();
        libI2C_switchRoleToTarget();
    }

    elapsedTime = secondTimeoutMs - (nowTickMs()-startTime);
    delay_ms(elapsedTime);

}

#else

#define ENABLE_FIRST_WINDOW
#define ENABLE_THIRD_WINDOW
#define ALLOW_TARGET_PROMOTION
void libI2C_startupRoleDetection(uint8_t cardPos, uint32_t firstTimeoutMs, uint32_t secondTimeoutMs)
{
    uint32_t startTime = nowTickMs();
    uint32_t elapsedTime = 0U;
    const uint32_t checkIntervalMs = 200U;
    uint8_t peerDetectedInFirstWindow = FALSE;

#ifdef ENABLE_FIRST_WINDOW

    CUSTOM_PRINT("\n[I2C] First Window: Waiting for peer... Start Time [%u]\n", nowTickMs());

    while (elapsedTime < firstTimeoutMs)
    {
        if (getPeerHealthStatus() == HEALTHY)
        {
            CUSTOM_PRINT("\n[I2C] Peer detected in First Window. Staying as TARGET.\n");
            peerDetectedInFirstWindow = TRUE;
            break;
        }

        delay_ms(checkIntervalMs);
        elapsedTime += checkIntervalMs;
    }
#endif

    // Step 2 � Role Assignment if peer NOT detected in First Window
    if (peerDetectedInFirstWindow == FALSE)
    {
        if (cardPos == 0U)
        {
            CUSTOM_PRINT("\n[I2C] First Window expired or skipped. CardPos 0 promoting to CONTROLLER... [%u]\n", nowTickMs());
            //                        isController = TRUE;
            libI2C_switchRoleToController();
        }
        else
        {
            CUSTOM_PRINT("\n[I2C] First Window expired or skipped. CardPos 1 staying as TARGET... [%u]\n", nowTickMs());
            //                        isController = FALSE;
            //                        libI2C_armTargetRx();
            libI2C_switchRoleToTarget();
        }

#ifdef ENABLE_THIRD_WINDOW
        // Step 3 � Second Wait Window: Post-role actions
        elapsedTime = 0U;

        if (isI2CController())
        {
            CUSTOM_PRINT("\n[I2C] Controller: Sending heartbeat during Second Window... [%u]\n", nowTickMs());

            u8 i = 0;
            while (elapsedTime < secondTimeoutMs)
            {
                sendHotStandbyHeartbeat();
                //                CUSTOM_PRINT("[I2C] Controller Becon [%d] Time [%u]\n", i++, nowTickMs());

                if (getPeerHealthStatus() == HEALTHY)
                {
                    CUSTOM_PRINT("\n[I2C] Controller: Peer detected during Second Window. Continuing as CONTROLLER.\n");
                    break;
                }
                delay_ms(checkIntervalMs);
                elapsedTime += checkIntervalMs;
            }

        }
        else
        {
            CUSTOM_PRINT("\n[I2C] Target: Waiting for peer during Second Window... [%u]\n", nowTickMs());

            u8 i = 0;
            while (elapsedTime < secondTimeoutMs)
            {
                //                CUSTOM_PRINT("[I2C] Target Becon [%d] Time [%u]\n", i++, nowTickMs());

                if (getPeerHealthStatus() == HEALTHY)
                {
                    CUSTOM_PRINT("\n[I2C] Target: Peer detected during Second Window. Staying as TARGET.\n");
                    break;
                }

                delay_ms(checkIntervalMs);
                elapsedTime += checkIntervalMs;
            }

#ifdef ALLOW_TARGET_PROMOTION
            if (getPeerHealthStatus() != HEALTHY)
            {
                CUSTOM_PRINT("\n[I2C] Target: Peer not detected after Second Window. Promoting to CONTROLLER... [%u]\n", nowTickMs());
                libI2C_switchRoleToController();
            }
#endif
        }
#endif
    } // step 2 end


    // Step 4 � Final Sync Delay
    {
        uint32_t totalTimeTaken = nowTickMs() - startTime;
        uint32_t fixedTotalWait = firstTimeoutMs + secondTimeoutMs + 1000U;

        if (totalTimeTaken < fixedTotalWait)
        {
            delay_ms(fixedTotalWait - totalTimeTaken);
        }

        CUSTOM_PRINT("\n[I2C] Role Detection Complete. Total Time: [%u]\n", nowTickMs() - startTime);
    }
}
#endif

void libI2C_switchRoleToController(void)
{
    CUSTOM_PRINT("\n[I2C] Switching role to CONTROLLER...\n");

    u8 res = libI2C_probePeer();

    libI2C_reopenC2CHandle();    // Close and reopen handle cleanly

    //    I2C_deinit();
    //     I2C_init();
    //     Drivers_i2cOpenHld();


    isController = TRUE;
    libI2C_patchOwnAddress(cardUniqueId);
    CUSTOM_PRINT("\n[I2C] Role switched to CONTROLLER. Ready to send/receive. peerProbe[%d]\n",res);
}

static void libI2C_reopenC2CHandle(void)
{
    if (NULL == gC2CI2CHandle)
    {
        CUSTOM_PRINT("\n[I2C] C2C Handle Already Closed!\n");
    }
    else
    {
        CUSTOM_PRINT_DEBUG("\n 11111!\n");
        I2C_Object *object = (I2C_Object*)gC2CI2CHandle->object;
        object->headPtr = NULL; // this is way around, forcing it NULL to reset
        object->tailPtr = NULL;
        object->currentTransaction = NULL;
        object->i2cLldHandle->currentMsg = NULL; // fallback
        //        object->i2cLldHandle->args = NULL; // fallback

        CUSTOM_PRINT_DEBUG("\n 2222!\n");
        int32_t result = libI2C_close(gC2CI2CHandle);

        CUSTOM_PRINT_DEBUG("\n close result[%d]",result);

        delay_ms(20);
        // Step 1: Disable all interrupts
        HW_WR_REG32(I2C1 + 0x04, 0x00000000); // I2C_ICIMR

        // Step 2: Reset internal I2C state machine
        HW_WR_REG32(I2C1 + 0x24, HW_RD_REG32(I2C1 + 0x24) & ~(1U << 5));  // Clear IRS
        delay_ms(20);
        HW_WR_REG32(I2C1 + 0x24, HW_RD_REG32(I2C1 + 0x24) | (1U << 5));   // Set IRS

        // Step 3: Clear any lingering interrupt flags
        HW_WR_REG32(I2C1 + 0x08, 0xFFFFFFFF);  // I2C_ICSTR

        delay_ms(10);

        if(I2C_SUCCESS == result)
        {
            CUSTOM_PRINT_DEBUG("\n[I2C] C2C Handle closed!\n");
            gC2CI2CHandle = NULL;
            gI2cHandle[MY_CONFIG_I2C_INTERCARD_COMM] = NULL;

            gI2cHandle[MY_CONFIG_I2C_INTERCARD_COMM] = I2C_open(MY_CONFIG_I2C_INTERCARD_COMM, &gI2cParams[MY_CONFIG_I2C_INTERCARD_COMM]);
            gC2CI2CHandle = gI2cHandle[MY_CONFIG_I2C_INTERCARD_COMM];

            if (gC2CI2CHandle == NULL)
            {
                CUSTOM_PRINT("\n[I2C] C2C Handle reopen FAILED!\n");
            }
            else
            {
                CUSTOM_PRINT("\n[I2C] C2C Handle reopened successfully.\n");
            }
        }
        else
        {
            CUSTOM_PRINT_DEBUG("\n[I2C] C2C Handle close Failed....!\n");
        }
    }
}


void libI2C_switchRoleToTarget(void)
{
    CUSTOM_PRINT("\n[I2C] Switching role to TARGET...\n");
    libI2C_reopenC2CHandle();    // Close and reopen handle cleanly
    CUSTOM_PRINT("\n[I2C]4444\n");

    //    I2C_deinit();
    //    I2C_init();
    //    Drivers_i2cOpenHld();

    isController = FALSE;
    libI2C_patchOwnAddress(cardUniqueId);
    CUSTOM_PRINT("\n[I2C]6666\n");
    //libI2C_armTargetRx();
    CUSTOM_PRINT("\n[I2C] Role switched to TARGET. RX armed.\n");
}

void libI2C_printCurrentRole(void)
{
    if (isController)
    {
        CUSTOM_PRINT("\n[I2C] Current Role: CONTROLLER\n");
    }
    else
    {
        CUSTOM_PRINT("\n[I2C] Current Role: TARGET\n");
    }
}


static void libI2C_disableInterrupt(uint32_t baseAddr, uint32_t intFlag)
{
    CSL_I2cRegsOvly i2cRegs = (CSL_I2cRegsOvly)baseAddr;
    i2cRegs->ICIMR &= ~intFlag;
}

static void libI2C_clearInterruptStatus(uint32_t baseAddr, uint32_t intFlag)
{
    CSL_I2cRegsOvly i2cRegs = (CSL_I2cRegsOvly)baseAddr;
    i2cRegs->ICSTR = intFlag;
}

i32 libI2C_sendCommandAndReceive(const u8 *cmdBuf, u32 cmdLen, u8 *respBuf, u32 respLen)
{
    i32 result = I2C_ERROR_GENERIC;

    if (!isController)
    {
        CUSTOM_PRINT("\n[I2C] Not in CONTROLLER mode. Cannot send+receive.\n");
        result = PEER_UNAVAILABLE;
    }
    else if ((NULL == cmdBuf) || (0U == cmdLen) || (NULL == respBuf) || (0U == respLen))
    {
        CUSTOM_PRINT("\n[I2C] Invalid parameters for send+receive.\n");
        result = I2C_ERROR_INVALID;
    }
    else
    {
        I2C_Transaction txn = {0};
        I2C_Transaction_init(&txn);

        txn.targetAddress = peerAddress;
        txn.writeBuf = (void *)cmdBuf;
        txn.writeCount = cmdLen;
        txn.readBuf = respBuf;
        txn.readCount = respLen;
        txn.controllerMode = TRUE;
        txn.timeout = MY_I2C_TRANSACTION_TIMEOUT;

        i32 status = I2C_transfer(gC2CI2CHandle, &txn);

        if (I2C_STS_SUCCESS == status)
        {
            result = (i32)respLen;
        }
        else
        {
            CUSTOM_PRINT("\n[I2C] Send+Receive transaction failed. Status = %d\n", status);
            result = status;
        }
    }

    return result;
}

i8* getI2CMsgString(const u8 msgId)
{
    i8 *retStr = (i8 *)"Invalid I2C Msg";

    switch(msgId)
    {
    case I2C_MSG_ID_HEALTH_HEARTBEAT:
        retStr = (i8 *)"HEALTHY";
        break;
    case I2C_MSG_ID_LOCO_DATA_SYNC_REQ:
        retStr = (i8 *)"I2C_SYNC_REQ";
        break;
    case I2C_MSG_ID_LOCO_DATA_SYNC_RESP:
        retStr = (i8 *)"I2C_SYNC_RESP";
        break;
    default:
        break;
    }

    return retStr;
}



void setI2CBusyFlag4C2C(void)
{
    gI2CBusyFlag = I2C_BUSY_FLAG_SET;
}

void clearI2CBusyFlag4C2C(void)
{
    gI2CBusyFlag = I2C_BUSY_FLAG_CLEAR;
}

u8 getI2CBusyFlagSet4C2C(void)
{
    u8 firstRead = gI2CBusyFlag;
    delay_ms(1U);
    //    RAW_DELAY(200);
    u8 secondRead = gI2CBusyFlag;

    if (firstRead == secondRead)
    {
        return firstRead;
    }
    else
    {
        return I2C_BUSY_FLAG_SET;  // Treat as busy if inconsistent
    }
}

u8 isI2Cinit4C2CSuccess(void)
{
    return initC2CInit;
}

void setI2Cinit4C2CSuccess(void)
{
    initC2CInit = TRUE;
}

u8 translateI2CAddress(const u8 in)
{
    u8 result = 0xFF;
    switch(in)
    {
    case 0x03U:
        result = 0x03;
        break;
    case 0x00U:
        result = 0x01;
        break;
    case 0x07U:
        result = 0x07;
        break;
    case 0x04U:
        result = 0x04;
        break;
    default:
        CUSTOM_PRINT("\n Blunder [%s]",FUNC_NAME);
        break;
    }
    return result;
}

#define LIBI2C_INT_MASK_ARBITRATION_LOST       (CSL_I2C_ICIMR_AL_MASK)
#define LIBI2C_INT_MASK_NO_ACK                 (CSL_I2C_ICIMR_NACK_MASK)
#define LIBI2C_INT_MASK_ADRR_READY_ACESS       (CSL_I2C_ICIMR_ARDY_MASK)
#define LIBI2C_INT_MASK_RECV_READY             (CSL_I2C_ICIMR_ICRRDY_MASK)
#define LIBI2C_INT_MASK_TRANSMIT_READY         (CSL_I2C_ICIMR_ICXRDY_MASK)
#define LIBI2C_INT_MASK_STOP_CONDITION         (CSL_I2C_ICIMR_SCD_MASK)
#define LIBI2C_INT_MASK_ADRR_TARGET            (CSL_I2C_ICIMR_AAS_MASK)

#define LIBI2C_ALL_INTS_MASK                   (   LIBI2C_INT_MASK_ARBITRATION_LOST   |   \
        LIBI2C_INT_MASK_NO_ACK             |   \
        LIBI2C_INT_MASK_ADRR_READY_ACESS   |   \
        LIBI2C_INT_MASK_RECV_READY         |   \
        LIBI2C_INT_MASK_TRANSMIT_READY     |   \
        LIBI2C_INT_MASK_STOP_CONDITION     |   \
        LIBI2C_INT_MASK_ADRR_TARGET            \
)

static int32_t libI2C_lld_deInit(I2CLLD_Handle handle)
{
    int32_t                 status = I2C_STS_SUCCESS;
    I2CLLD_Object           *object = NULL;

    /* Input parameter validation */
    if (handle != NULL)
    {
        /* Get the pointer to the object */
        object = (I2CLLD_Object*)handle;

        /* Check to see if a I2C transaction is in progress */
        if (object->currentMsg == NULL)
        {

            /* Mask I2C interrupts */
            libI2C_ControllerIntDisableEx(object->baseAddr, LIBI2C_ALL_INTS_MASK);

            /* Disable the I2C Controller */
            libI2C_ControllerDisable(object->baseAddr);

            object->state = I2C_STATE_RESET;
        }
        else
        {
            status = I2C_STS_ERR;
        }
    }
    else
    {
        status = I2C_STS_ERR_INVALID_PARAM;
    }
    return status;
}
static void libI2C_ControllerIntDisableEx(uint32_t baseAddr, uint32_t intFlag)
{
    CSL_I2cRegsOvly i2cRegs = (CSL_I2cRegsOvly)baseAddr;
    i2cRegs->ICIMR &= ~intFlag;
}

static void libI2C_ControllerDisable(uint32_t baseAddr)
{
    /* Put I2C module in reset */
    CSL_I2cRegsOvly i2cRegs = (CSL_I2cRegsOvly)baseAddr;
    i2cRegs->ICMDR &= ~CSL_I2C_ICMDR_IRS_MASK;
}

static int32_t libI2C_close(I2C_Handle handle)
{
    I2C_Object *object = NULL;
    I2C_HwAttrs const *hwAttrs = NULL;
    int32_t status = I2C_ERROR_GENERIC;

    /* Input parameter validation */
    if (handle != NULL)
    {
        /* Get the pointer to the object */
        object = (I2C_Object*)handle->object;
        hwAttrs = (I2C_HwAttrs const *)handle->hwAttrs;

        /* Check to see if a I2C transaction is in progress */
        if (object->headPtr == NULL)
        {
            CUSTOM_PRINT_DEBUG("\n before deinit ");
            int32_t res1 = libI2C_lld_deInit(object->i2cLldHandle);
            CUSTOM_PRINT_DEBUG("\n after deinit [%d]",res1);

            if(res1 == I2C_STS_SUCCESS)
            {
                status = I2C_SUCCESS;
            }
            else
            {
                CUSTOM_PRINT_DEBUG("\n lld handle close error [%d]",res1);
                status = I2C_ERROR_GENERIC;
            }
            ASSERT(status == SystemP_SUCCESS);

            if (true == hwAttrs->enableIntr)
            {
                /* Destruct the Hwi */
                (void)HwiP_destruct(&object->hwiObj);
            }

            /* Destruct the instance lock */
            (void)SemaphoreP_destruct(&object->mutex);

            if (I2C_MODE_BLOCKING == object->i2cParams.transferMode)
            {
                /* Destruct the transfer completion lock */
                (void)SemaphoreP_destruct(&object->transferComplete);
            }

            object->isOpen = (bool)false;
            status = I2C_SUCCESS;
        }
        //        SemaphoreP_post(&gI2cDrvObj.lockObj);
    }
    else
    {

    }
    return status;
}
/*
 * testRoleManager.c
 *
 *  Created on: 14-Jul-2025
 *      Author: admin7
 */
#include "testC2C_I2C.h"
#include "cardIdentity.h"
#include "syncManager.h"
#include "FSI/fsi_api.h"
#include "2oo2Manager.h"
#include "hotStandBy.h"


extern u8 gVar;

volatile static u32 val = 0;

static void prepareTgtTxBuffer(void);

static void prepareTgtTxBuffer()
{
    memset(txI2CBuffer(),val,10);
}

void roleManagerTest(void)
{
    static u16 count = 1;

    initCardIdentity();

    printCardDetails();

    initCardPositionForBottomController();

    printCardDetails();

    //    syncPointInit();

    delay_ms(1000);
    libI2C_initC2C(CardId_getUniqueId());
    libI2C_startupRoleDetection(CardId_getCardPosition(), 10000, 6000);
    libI2C_printCurrentRole();


    while(1)
    {
        CUSTOM_PRINT("\n --- Excuting [%d] ----gVar[%d] \n", val,gVar);
        libI2C_printCurrentRole();

        u32 t1 = nowTickMs();

        if(TRUE != isI2CController())
        {
            libI2C_armTargetRx();
        }
        if(TRUE == isI2CController())
        {
            libI2C_receive(rxI2CBuffer(), 20);
        }
        else
        {
            prepareTgtTxBuffer();
        }

        val++;

        if(gVar == 10)
        {
            if(TRUE != isI2CController())
            {
                libI2C_switchRoleToController();
            }
            else
            {
                libI2C_switchRoleToTarget();
            }
            gVar = 11;
        }

        if(val == 20)
        {
            if(TRUE != isI2CController())
            {
                libI2C_switchRoleToController();
            }
            else
            {
                libI2C_switchRoleToTarget();
            }
            gVar = 21;
        }

        u32 t2 = nowTickMs() - t1;
        if(t2>2000)
        {
            CUSTOM_PRINT("\n check this our");
        }
        else
        {
            delay_ms(2000-t2);
        }
    }

#ifdef TEST123
    delay_ms(1000);

    setI2Cinit4C2CSuccess();
    while(1)
    {
        u32 t1 = nowTickMs();
        u16 val16Bit = 0x0FFF;

        CUSTOM_PRINT("\n ------------------------------------- For Count Cycle [%d]", count);
        libI2C_printCurrentRole();
        printHotStandbyStatusSummary();
        //
        //        if(TRUE == isI2CController())
        //        {
        //            libI2C_probePeer();
        //        }



        if (ACTIVE == getSelfActiveStatus())
        {
            val16Bit = 0x0FFE;
        }
        else if(STANDBY == getSelfActiveStatus())
        {
            val16Bit = 0x0F7F;
        }
        else if(NOT_APPLICABLE == getSelfActiveStatus())
        {
            val16Bit = 0x0DFF;
        }
        else
        {

        }

        if(count%2)
        {
            val16Bit |= 0xF000;
        }
        else
        {
            val16Bit |= 0x7000;
        }
        toHandleLEDAnd7SegmentDsiplay(0x00000075U, val16Bit);
        toHandleLEDAnd7SegmentDsiplay(0x00000076U, val16Bit);


        if(TRUE == isI2Cinit4C2CSuccess())
        {
            monitorPeerHeartBeat();
            monitorActiveStandbyStatus();

            if((ACTIVE == getSelfActiveStatus()) && (FALSE == isI2CController()))
            {
                //                CUSTOM_PRINT("\n switching to controller form target \n.....");
                libI2C_switchRoleToController();
            }
        }
        else
        {
            CUSTOM_PRINT("\n Not sending heart Beat \n");
        }


        printCardDetails();


#ifdef DONT_PRINT
        locoDataSyncTest();


        if((count % 20) == 0)
        {
            CUSTOM_PRINT("\n Loco Data :\n");
            u8 *buff = getLocoBuffer();
            for(u8 i = 0;i<(1500/100);i = i+100)
            {
                printInHex(&buff[i], 100);
                CUSTOM_PRINT("\n");
            }
        }
#endif
        count++;
        val++;


        u32 t2 = nowTickMs() - t1;
        if(t2>2000)
        {
            CUSTOM_PRINT("\n check this our");
        }
        else
        {
            delay_ms(2000-t2);
        }
    }
#endif
}

void locoDataSyncTest(void)
{
    u32 t1 = nowTickMs();

    if (I2C_BUSY_FLAG_CLEAR == getI2CBusyFlagSet4C2C())
    {
        setI2CBusyFlag4C2C();
        reqForSyncLocoDataI2C();
        txSyncLocoData();
        clearI2CBusyFlag4C2C();
    }
    else
    {
        CUSTOM_PRINT(" \n I2c C2c is busy in sync data \n");
    }


    u32 t2 = nowTickMs()-t1;

    if(t2>1000)
    {
        CUSTOM_PRINT("\n check this \n");
    }
    else
    {
        delay_ms(1000-t2);
    }
}

Requirement:

  • Two AM2634-based cards communicate using I2C.

  • Only one card acts as the controller (master) and the other as the target (slave) at any point.

  • The roles can switch dynamically at runtime.

  • Communication is bidirectional:

    • Controller sends commands or requests.

    • Target receives, processes, and responds

So for this , 

Initially, when both cards power up, they both act as I2C targets (slaves). Based on their physical position or ID, one of them later becomes an I2C controller (master) and the other remains a target.

To detect whether another card is present or not, the system uses two mechanisms:

  1. Heartbeat message over I2C:
    The controller sends a heartbeat message every 2 seconds.
    The target responds with a heartbeat reply.

  2. GPIO-based connection:
    A GPIO pin is toggled continuously.
    If the peer card is present, this toggling is detected by the other card.

Role Switch Logic:

  • If a card does not receive any heartbeat from a controller for a defined time period, it switches its role from target to controller.

  • If a card is already acting as a controller and starts receiving heartbeat messages from another controller, it demotes itself and switches back to being a target.

  • A card will remain a target even if it has a lower position ID, as long as it continues to receive valid heartbeat messages from a controller.

Current Status:

  • This logic has been successfully validated over CAN protocol. Roles switch correctly as per the expected logic.

  • However, over I2C:

    • Sometimes the role switch works 1 or 2 times and then fails.

    • In some cases, no callback is triggered after switching roles.

    • Sometimes it does not work at all.

  • The issue seems to be related to the I2C transaction not being cleared or the driver not resetting properly.

Additional Notes:

  • Code file (libI2C_C2C.c) and log files (master.txt and vcc.txt) are attached for analysis.

  • The issue is isolated to I2C communication and switching; the same logic works fine over CAN.

    /*
     * Updated libI2C_C2C.c
     * Enhancements:
     * - Proper target-side RX arming
     * - Common callback usage
     * - Re-arming after reception
     * - Fully bidirectional HLD-based I2C C2C communication
     */
    
    #include "libI2C_api.h"
    #include <string.h>
    #include "../hotStandBy.h"
    #include "../2oo2Manager.h"
    #include "../cardIdentity.h"
    #include <kernel/dpl/SemaphoreP.h>
    
    extern uint8_t gVar;
    
    typedef struct
    {
        volatile uint32_t I2C_ICOAR;
        volatile uint32_t I2C_ICIMR;
        volatile uint32_t I2C_ICSTR;
        volatile uint32_t I2C_ICCLKL;
        volatile uint32_t I2C_ICCLKH;
        volatile uint32_t I2C_ICCNT;
        volatile uint32_t I2C_ICDRR;
        volatile uint32_t I2C_ICSAR;
        volatile uint32_t I2C_ICDXR;
        volatile uint32_t I2C_ICMDR;
        volatile uint32_t I2C_ICIVR;
        volatile uint32_t I2C_ICEMDR;
        volatile uint32_t I2C_ICPSC;
        volatile uint32_t I2C_ICPID1;
        volatile uint32_t I2C_ICPID2;
        volatile uint32_t I2C_ICDMAC;
        volatile uint32_t I2C_I2C_RESERVED1;
        volatile uint32_t I2C_I2C_RESERVED2;
        volatile uint32_t I2C_ICPFUNC;
        volatile uint32_t I2C_ICPDIR;
        volatile uint32_t I2C_ICPDIN;
        volatile uint32_t I2C_ICPDOUT;
        volatile uint32_t I2C_ICPDSET;
        volatile uint32_t I2C_ICPDCLR;
        volatile uint32_t I2C_ICPDRV;
    }I2C_REG;
    
    #define I2C1   ((I2C_REG*)(I2C1_BASE_ADDRESS))
    
    I2C_Handle gC2CI2CHandle = NULL;
    I2C_Transaction gC2C_RxTxn = {0};
    
    uint8_t tx_flag;
    uint8_t rx_flag;
    
    static u8 initC2CInit = FALSE;
    static u8 isController = FALSE;
    static u8 peerAvailable = FALSE;
    static uint8_t cardUniqueId = 0;
    static u8 ownAddress = 0;
    static u8 peerAddress = 0;
    static volatile u8 gI2CBusyFlag = I2C_BUSY_FLAG_CLEAR;
    
    
    
    uint8_t gC2CTxBuf[MAX_TX_BUF] = {0};
    uint32_t gC2CTxLength = 0U;
    uint8_t gC2CRxBuf[MAX_RX_BUF] = {0};
    uint32_t gC2CRxBufLgth = 0;
    uint32_t actualReadCount = 0;
    uint32_t actualWriteCount = 0;
    
    
    #define APP_I2C_INT_MASK_ADRR_TARGET            (0x00000040U)
    #define APP_I2C_INT_ADRR_TARGET                 (0x00000200U)
    
    static void libI2C_reopenC2CHandle(void);
    static void libI2C_disableInterrupt(uint32_t baseAddr, uint32_t intFlag);
    static void libI2C_clearInterruptStatus(uint32_t baseAddr, uint32_t intFlag);
    static int32_t libI2C_close(I2C_Handle handle);
    static int32_t libI2C_lld_deInit(I2CLLD_Handle handle);
    static void libI2C_ControllerDisable(uint32_t baseAddr);
    static void libI2C_ControllerIntDisableEx(uint32_t baseAddr, uint32_t intFlag);
    
    u8 *txI2CBuffer(void)
    {
        return gC2CTxBuf;
    }
    
    u8 *rxI2CBuffer(void)
    {
        return gC2CRxBuf;
    }
    
    
    u32 getC2CRxBuffLgth(void)
    {
        return gC2CRxBufLgth;
    }
    
    u32 getC2CTxBuffLgth(void)
    {
        return gC2CTxLength;
    }
    
    void setC2CTxBuffLgth(const u32 in)
    {
        gC2CTxLength = in;
    }
    
    void setC2CRxBuffLgth(const u32 in)
    {
        gC2CRxBufLgth = in;
    }
    
    #define SIMPLE
    #ifdef SIMPLE
    void I2C_Callback(I2C_Handle handle, I2C_Transaction *transaction, int32_t transferStatus)
    {
        if(TRUE == isController)
        {
            CUSTOM_PRINT_DEBUG(" \n Coner 23:  \n");
            if (transferStatus == I2C_STS_SUCCESS)
            {
                //        if(rx_flag)
                if(transaction->readCount != 0)
                {
                    CUSTOM_PRINT_DEBUG(" Rx : \n");
                    printInHex(transaction->readBuf, transaction->readCount);
    
                    u8 *buf = (u8 *)transaction->readBuf;
                                    gVar = buf[0];
                }
                if(transaction->writeCount != 0)
                {
                    CUSTOM_PRINT_DEBUG(" Tx : \n");
                    printInHex(transaction->writeBuf, transaction->writeCount);
                }
                //            else
                //            {
                //                CUSTOM_PRINT("\n blunder [%s]",FUNC_NAME);
                //            }
            }
        }
        else
        {
            CUSTOM_PRINT_DEBUG(" \n Target :  ");
    
            if (transferStatus == I2C_STS_SUCCESS)
            {
                //        if(rx_flag)
                if((transaction->readCount != 0) && (transaction->readBuf != NULL))
                {
                    CUSTOM_PRINT_DEBUG(" Rx : \n");
                    printInHex(transaction->readBuf, 25);
                }
    
                if((transaction->writeCount != 0) && (transaction->writeBuf != NULL))
                {
                    CUSTOM_PRINT_DEBUG(" Tx : \n");
                    printInHex(transaction->writeBuf, 25);
                    u8 *buf = (u8 *)transaction->readBuf;
                    gVar = buf[0];
                }
                //            else
                //            {
                //                CUSTOM_PRINT("\n blunder [%s]",FUNC_NAME);
                //            }
            }
    
    
        }
    
    
        HwiP_clearInt(handle->hwAttrs->intNum);
        HwiP_enableInt(handle->hwAttrs->intNum);
        CUSTOM_PRINT("  --- exit callback \n");
    }
    
    #else
    
    
    void I2C_Callback(I2C_Handle handle, I2C_Transaction *transaction, int32_t transferStatus)
    {
        if(TRUE == isController)
        {
            CUSTOM_PRINT_DEBUG(" \n Controller :  ");
            if (transferStatus == I2C_STS_SUCCESS)
            {
                if((transaction->readBuf !=NULL) && (transaction->writeBuf ==NULL ))
                {
    
                    CUSTOM_PRINT_DEBUG(" Rx : Total_Bytes[%d] :  ",transaction->readCount);
                    //printInHex(((u8 *)transaction->readBuf), transaction->readCount);
                    ST_I2C_APP_HDR *hdr = (ST_I2C_APP_HDR *)&transaction->readBuf[0];
                    u16 dataLgth = hdr->length - sizeof(ST_I2C_APP_HDR) -2U; // 2 is for crcs
    
                    CUSTOM_PRINT_DEBUG(" [%s :%d] \n ",getI2CMsgString(hdr->msgId),dataLgth);
                    switch(hdr->msgId)
                    {
                    case I2C_MSG_ID_HEALTH_HEARTBEAT:
                    {
                        handleReceivedHotStandbyMessage(&transaction->readBuf[sizeof(ST_I2C_APP_HDR)],dataLgth);
                        break;
                    }
                    case I2C_MSG_ID_LOCO_DATA_SYNC_RESP:
                    {
                        handleRcvdLocoDataRespMsg(&transaction->readBuf[sizeof(ST_I2C_APP_HDR)],dataLgth);
                        break;
                    }
                    default:
                        CUSTOM_PRINT("\n Invalid I2C MsgId \n");
                        break;
                    }
                }
                else
                {
                    ST_I2C_APP_HDR *hdr = (ST_I2C_APP_HDR *)&transaction->writeBuf[0];
                    CUSTOM_PRINT_DEBUG(" Tx \t [%s :%d] -->Success \n ",getI2CMsgString(hdr->msgId),transaction->writeCount);
                }
            }
        }
        else
        {
            CUSTOM_PRINT_DEBUG(" \n Target :  ");
            //        if(rx_flag)
            if(transaction->readCount != 0)
            {
                //            CUSTOM_PRINT_DEBUG(" Rx \t Total_Bytes[%d] : ", actualReadCount);
                CUSTOM_PRINT_DEBUG(" Rx \t Total_Bytes[%d] : ", transaction->readCount);
                rx_flag=0;
                //printInHex(((u8 *)transaction->readBuf),actualReadCount);
                ST_I2C_APP_HDR *hdr = (ST_I2C_APP_HDR *)&transaction->readBuf[0];
                u16 dataLgth = hdr->length - sizeof(ST_I2C_APP_HDR) -2U; // 2 is for crc
                // crc valdiation can be done here
    
                CUSTOM_PRINT_DEBUG(" [%s(%d) :%d] \n ",getI2CMsgString(hdr->msgId),hdr->msgId,dataLgth);
                switch(hdr->msgId)
                {
                case I2C_MSG_ID_HEALTH_HEARTBEAT:
                {
                    handleReceivedHotStandbyMessage(&transaction->readBuf[sizeof(ST_I2C_APP_HDR)],dataLgth);
                    gC2CTxLength =  hdr->length;
                    prepareTargetHeartbeatMsg(&gC2CTxBuf[0],&gC2CTxLength);
                    break;
                }
                case I2C_MSG_ID_LOCO_DATA_SYNC_REQ:
                {
                    actualWriteCount = 0;
                    gC2CTxLength =  2123;
                    fillSyncLocoDataInI2CTxBuff(&gC2CTxBuf[0],&gC2CTxLength);
                    break;
                }
                case I2C_MSG_ID_LOCO_DATA_SYNC_RESP:
                {
                    handleRcvdLocoDataRespMsg(&transaction->readBuf[sizeof(ST_I2C_APP_HDR)],dataLgth);
                    break;
                }
                default:
                    CUSTOM_PRINT("\n Invalid I2C MsgId \n");
                    break;
                }
                actualReadCount = I2C_INVALID_RcTx_LGTH;
            }
            else if(transaction->writeCount != 0)
            {
                tx_flag = 0;
                ST_I2C_APP_HDR *hdr = (ST_I2C_APP_HDR *)&transaction->writeBuf[0];
                CUSTOM_PRINT_DEBUG(" Tx  \t [%s :%d] -->Success \n ",getI2CMsgString(hdr->msgId),actualWriteCount);
                actualWriteCount = I2C_INVALID_RcTx_LGTH;
            }
            else
            {
                CUSTOM_PRINT("\n blunder [%s]",FUNC_NAME);
            }
    
            libI2C_armTargetRx();
        }
        HwiP_clearInt(handle->hwAttrs->intNum);
        HwiP_enableInt(handle->hwAttrs->intNum);
    }
    
    #endif
    
    #ifdef OLD_INIT
    void libI2C_initC2C(const uint8_t selfId)
    {
    
        cardUniqueId = selfId;
        libI2C_patchOwnAddress(cardUniqueId);
    
        gC2CI2CHandle = gI2cHandle[MY_CONFIG_I2C_INTERCARD_COMM];
    
        if (cardUniqueId == 3U)
        {
            peerCardId = 7U;
            isController = TRUE;
            peerAvailable = TRUE; // Assume peer is available for now
            ownAddress = cardUniqueId;
            peerAddress = 7U;
        }
        else if (cardUniqueId == 7U)
        {
    
            peerCardId = 3U;
            isController = FALSE;
            peerAvailable = TRUE; // Assume peer is available for now
            ownAddress = cardUniqueId;
            peerAddress = 3U;
    
    
    
    #ifdef Old
            //        I2C_Transaction_init(&gC2C_RxTxn);
            gC2C_RxTxn.readBuf      = gC2CRxBuf;
            gC2C_RxTxn.readCount    = sizeof(gC2CRxBuf);
    
            gC2C_RxTxn.controllerMode=0;
            gC2C_RxTxn.writeBuf=gC2CTxBuf;
            gC2C_RxTxn.writeCount=sizeof(gC2CTxBuf);
            I2C_transfer(gC2CI2CHandle, &gC2C_RxTxn);
    #else
            libI2C_armTargetRx();
    #endif
    
        }
        else
        {
            peerCardId = 0xFFU;
            isController = FALSE;
            peerAvailable = FALSE; // Assume peer is available for now
            CUSTOM_PRINT("\n[WARNING] Unknown card ID 0x%02X. Defaulting to target.", selfId);
        }
    }
    #else
    
    void libI2C_initC2C(const uint8_t selfId)
    {
        cardUniqueId = selfId;
    
        ownAddress = cardUniqueId;//translateI2CAddress(selfId);
    
        libI2C_patchOwnAddress(ownAddress);
    
        gC2CI2CHandle = gI2cHandle[MY_CONFIG_I2C_INTERCARD_COMM];
    
        peerAddress = (selfId == T_CARD1_ADDR) ? T_CARD2_ADDR : T_CARD1_ADDR;
    
        /*
        if(CardId_isMasterCtrl() == TRUE)
        {
            peerAddress = (selfId == T_CARD1_ADDR) ? T_CARD2_ADDR : T_CARD1_ADDR;
            peerAddress = translateI2CAddress(peerAddress);
        }
        else if(CardId_isSlaveCtrl() == TRUE)
        {
            peerAddress = (selfId == B_CARD1_ADDR) ? B_CARD2_ADDR : B_CARD1_ADDR;
            peerAddress = translateI2CAddress(peerAddress);
        }
        else
        {
    
        }
         */
    
    
        peerAvailable = FALSE;
    
        libI2C_switchRoleToTarget();
    
        CUSTOM_PRINT("\n[I2C Init] C2C Initialized. SelfAddr: 0x%02X, PeerAddr: 0x%02X\n", ownAddress, peerAddress);
    }
    
    #endif
    
    void libI2C_targetPrepareTxData(const u8 *data, u32 len)
    {
        if ((len <= MAX_TX_BUF) && (data != NULL))
        {
            memcpy(gC2CTxBuf, data, len);
            gC2CTxLength = len;
        }
    }
    
    i32 libI2C_send(const u8 *txBuf, u32 length)
    {
        i32 result = PEER_UNAVAILABLE;
        if ((txBuf == NULL) || (length == 0U))
        {
            CUSTOM_PRINT("\n Invalid Input Params in [%s] --> txBuf[%u] lgth[%d]\n",FUNC_NAME,
                         txBuf,length);
        }
        else
        {
            if (isController)
            {
                I2C_Transaction txn = {0};
                I2C_Transaction_init(&txn);
                txn.targetAddress = peerAddress; //
                txn.writeBuf = (void *)txBuf;
                txn.writeCount = length;
                txn.readBuf = NULL;
                txn.readCount = 0U;
                txn.controllerMode = 1;
                txn.timeout = MY_I2C_TRANSACTION_TIMEOUT;
    
                i32 status = I2C_transfer(gC2CI2CHandle, &txn);
                result = (status == I2C_STS_SUCCESS) ? (i32)length : status;
            }
            else
            {
                CUSTOM_PRINT("\n This is not controller I2C \n");
            }
        }
        return result;
    }
    
    i32 libI2C_receive(u8 *rxBuf, u32 length)
    {
        i32 result = PEER_UNAVAILABLE;
        if ((rxBuf == NULL) || (length == 0U))
        {
            CUSTOM_PRINT("\n Invalid Input Params in [%s] --> rxBuffPtr[%u] lgth[%d]\n",FUNC_NAME,
                         rxBuf,length);
        }
        else
        {
            if (isController)
            {
                I2C_Transaction txn = {0};
                I2C_Transaction_init(&txn);
                txn.targetAddress = peerAddress;
                txn.writeBuf = NULL;
    
                txn.readBuf = rxBuf;
                txn.readCount = length;
                txn.controllerMode = TRUE;
                txn.timeout = MY_I2C_TRANSACTION_TIMEOUT;
    
                i32 status = I2C_transfer(gC2CI2CHandle, &txn);
                result = (status == I2C_STS_SUCCESS) ? (i32)length : status;
            }
            else
            {
                CUSTOM_PRINT("\n This is not controller I2C \n");
            }
        }
        return result;
    }
    
    u8 libI2C_probePeer(void)
    {
        if (gC2CI2CHandle == NULL)
        {
            CUSTOM_PRINT("\n[I2C PROBE] I2C Handle is NULL.\n");
            return FALSE;
        }
    
        int32_t status = I2C_probe(gC2CI2CHandle, peerAddress);
    
        if (status == I2C_STS_SUCCESS)
        {
            CUSTOM_PRINT("\n[I2C PROBE] Peer [%d] acknowledged - READY\n",peerAddress);
            peerAvailable = TRUE;
        }
        else
        {
            CUSTOM_PRINT("\n[I2C PROBE] Peer [%d] NOT responding - Status = %d\n", peerAddress,status);
            peerAvailable = FALSE;
        }
    
        return peerAvailable;
    }
    
    
    u8 libI2C_healthCheckUpdate(void)
    {
        static u8 consecutiveFailures = 0U;
        u8 peerAlive = libI2C_probePeer();
    
        if (peerAlive == FALSE)
        {
            consecutiveFailures++;
    
            if (consecutiveFailures >= 3U)
            {
                // Promote to controller if not already
                if (!isController)
                {
                    isController = TRUE;
                    CUSTOM_PRINT("\n[C2C] Peer not responding. Promoting to controller role.");
                }
            }
        }
        else
        {
            consecutiveFailures = 0U;
        }
    
        return peerAlive;
    }
    
    u8 isI2CController(void)
    {
        return isController;
    }
    
    void libI2C_patchOwnAddress(const u8 myId)
    {
        gC2CI2CHandle = gI2cHandle[MY_CONFIG_I2C_INTERCARD_COMM];
    
        if (gC2CI2CHandle != NULL)
        {
            I2C_HwAttrs *nonConstHwAttrs = (I2C_HwAttrs *)(gC2CI2CHandle->hwAttrs);
            nonConstHwAttrs->ownTargetAddr = myId;
            I2C1_BASE_ADDRESS = myId;
        }
    }
    
    void libI2C_armTargetRx(void)
    {
        isController = FALSE;   // Ensure we are in TARGET mode
    
        memset(gC2CRxBuf, 0, sizeof(gC2CRxBuf));
        memset(&gC2C_RxTxn, 0, sizeof(gC2C_RxTxn));
    
        gC2C_RxTxn.readBuf = gC2CRxBuf;
        gC2C_RxTxn.readCount = sizeof(gC2CRxBuf);
        gC2C_RxTxn.controllerMode = 0;
        gC2C_RxTxn.writeBuf = gC2CTxBuf;
        gC2C_RxTxn.writeCount = sizeof(gC2CTxBuf);
    
        I2C_transfer(gC2CI2CHandle, &gC2C_RxTxn);
        CUSTOM_PRINT("\n[I2C] Target RX armed and role set to TARGET.\n");
    }
    
    #define SIMPLE
    #ifdef SIMPLE
    
    void libI2C_startupRoleDetection(uint8_t cardPos, uint32_t firstTimeoutMs, uint32_t secondTimeoutMs)
    {
        uint32_t startTime = nowTickMs();
        uint32_t elapsedTime = 0U;
    
        if (cardPos == 0U)
        {
            CUSTOM_PRINT("\n[I2C] First Window expired or skipped. CardPos 0 promoting to CONTROLLER... [%u]\n", nowTickMs());
            //                        isController = TRUE;
            libI2C_switchRoleToController();
        }
        else
        {
            CUSTOM_PRINT("\n[I2C] First Window expired or skipped. CardPos 1 staying as TARGET... [%u]\n", nowTickMs());
            //                        isController = FALSE;
            //                        libI2C_armTargetRx();
            libI2C_switchRoleToTarget();
        }
    
        elapsedTime = secondTimeoutMs - (nowTickMs()-startTime);
        delay_ms(elapsedTime);
    
    }
    
    #else
    
    #define ENABLE_FIRST_WINDOW
    #define ENABLE_THIRD_WINDOW
    #define ALLOW_TARGET_PROMOTION
    void libI2C_startupRoleDetection(uint8_t cardPos, uint32_t firstTimeoutMs, uint32_t secondTimeoutMs)
    {
        uint32_t startTime = nowTickMs();
        uint32_t elapsedTime = 0U;
        const uint32_t checkIntervalMs = 200U;
        uint8_t peerDetectedInFirstWindow = FALSE;
    
    #ifdef ENABLE_FIRST_WINDOW
    
        CUSTOM_PRINT("\n[I2C] First Window: Waiting for peer... Start Time [%u]\n", nowTickMs());
    
        while (elapsedTime < firstTimeoutMs)
        {
            if (getPeerHealthStatus() == HEALTHY)
            {
                CUSTOM_PRINT("\n[I2C] Peer detected in First Window. Staying as TARGET.\n");
                peerDetectedInFirstWindow = TRUE;
                break;
            }
    
            delay_ms(checkIntervalMs);
            elapsedTime += checkIntervalMs;
        }
    #endif
    
        // Step 2 � Role Assignment if peer NOT detected in First Window
        if (peerDetectedInFirstWindow == FALSE)
        {
            if (cardPos == 0U)
            {
                CUSTOM_PRINT("\n[I2C] First Window expired or skipped. CardPos 0 promoting to CONTROLLER... [%u]\n", nowTickMs());
                //                        isController = TRUE;
                libI2C_switchRoleToController();
            }
            else
            {
                CUSTOM_PRINT("\n[I2C] First Window expired or skipped. CardPos 1 staying as TARGET... [%u]\n", nowTickMs());
                //                        isController = FALSE;
                //                        libI2C_armTargetRx();
                libI2C_switchRoleToTarget();
            }
    
    #ifdef ENABLE_THIRD_WINDOW
            // Step 3 � Second Wait Window: Post-role actions
            elapsedTime = 0U;
    
            if (isI2CController())
            {
                CUSTOM_PRINT("\n[I2C] Controller: Sending heartbeat during Second Window... [%u]\n", nowTickMs());
    
                u8 i = 0;
                while (elapsedTime < secondTimeoutMs)
                {
                    sendHotStandbyHeartbeat();
                    //                CUSTOM_PRINT("[I2C] Controller Becon [%d] Time [%u]\n", i++, nowTickMs());
    
                    if (getPeerHealthStatus() == HEALTHY)
                    {
                        CUSTOM_PRINT("\n[I2C] Controller: Peer detected during Second Window. Continuing as CONTROLLER.\n");
                        break;
                    }
                    delay_ms(checkIntervalMs);
                    elapsedTime += checkIntervalMs;
                }
    
            }
            else
            {
                CUSTOM_PRINT("\n[I2C] Target: Waiting for peer during Second Window... [%u]\n", nowTickMs());
    
                u8 i = 0;
                while (elapsedTime < secondTimeoutMs)
                {
                    //                CUSTOM_PRINT("[I2C] Target Becon [%d] Time [%u]\n", i++, nowTickMs());
    
                    if (getPeerHealthStatus() == HEALTHY)
                    {
                        CUSTOM_PRINT("\n[I2C] Target: Peer detected during Second Window. Staying as TARGET.\n");
                        break;
                    }
    
                    delay_ms(checkIntervalMs);
                    elapsedTime += checkIntervalMs;
                }
    
    #ifdef ALLOW_TARGET_PROMOTION
                if (getPeerHealthStatus() != HEALTHY)
                {
                    CUSTOM_PRINT("\n[I2C] Target: Peer not detected after Second Window. Promoting to CONTROLLER... [%u]\n", nowTickMs());
                    libI2C_switchRoleToController();
                }
    #endif
            }
    #endif
        } // step 2 end
    
    
        // Step 4 � Final Sync Delay
        {
            uint32_t totalTimeTaken = nowTickMs() - startTime;
            uint32_t fixedTotalWait = firstTimeoutMs + secondTimeoutMs + 1000U;
    
            if (totalTimeTaken < fixedTotalWait)
            {
                delay_ms(fixedTotalWait - totalTimeTaken);
            }
    
            CUSTOM_PRINT("\n[I2C] Role Detection Complete. Total Time: [%u]\n", nowTickMs() - startTime);
        }
    }
    #endif
    
    void libI2C_switchRoleToController(void)
    {
        CUSTOM_PRINT("\n[I2C] Switching role to CONTROLLER...\n");
    
        u8 res = libI2C_probePeer();
    
        libI2C_reopenC2CHandle();    // Close and reopen handle cleanly
    
        //    I2C_deinit();
        //     I2C_init();
        //     Drivers_i2cOpenHld();
    
    
        isController = TRUE;
        libI2C_patchOwnAddress(cardUniqueId);
        CUSTOM_PRINT("\n[I2C] Role switched to CONTROLLER. Ready to send/receive. peerProbe[%d]\n",res);
    }
    
    static void libI2C_reopenC2CHandle(void)
    {
        if (NULL == gC2CI2CHandle)
        {
            CUSTOM_PRINT("\n[I2C] C2C Handle Already Closed!\n");
        }
        else
        {
    
            CUSTOM_PRINT_DEBUG("\n 11111!\n");
            I2C_Object *object = (I2C_Object*)gC2CI2CHandle->object;
            object->headPtr = NULL; // this is way around, forcing it NULL to reset
            object->tailPtr = NULL;
            object->currentTransaction = NULL;
            object->i2cLldHandle->currentMsg = NULL; // fallback
            //        object->i2cLldHandle->args = NULL; // fallback
    
            CUSTOM_PRINT_DEBUG("\n 2222!\n");
            int32_t result = libI2C_close(gC2CI2CHandle);
    
            CUSTOM_PRINT_DEBUG("\n close result[%d]",result);
    
            delay_ms(20);
            // Step 1: Disable all interrupts
            HW_WR_REG32(I2C1 + 0x04, 0x00000000); // I2C_ICIMR
    
            // Step 2: Reset internal I2C state machine
            HW_WR_REG32(I2C1 + 0x24, HW_RD_REG32(I2C1 + 0x24) & ~(1U << 5));  // Clear IRS
            delay_ms(20);
            HW_WR_REG32(I2C1 + 0x24, HW_RD_REG32(I2C1 + 0x24) | (1U << 5));   // Set IRS
    
            // Step 3: Clear any lingering interrupt flags
            HW_WR_REG32(I2C1 + 0x08, 0xFFFFFFFF);  // I2C_ICSTR
    
            delay_ms(10);
    
            if(I2C_SUCCESS == result)
            {
                CUSTOM_PRINT_DEBUG("\n[I2C] C2C Handle closed!\n");
                gC2CI2CHandle = NULL;
                gI2cHandle[MY_CONFIG_I2C_INTERCARD_COMM] = NULL;
    
                gI2cHandle[MY_CONFIG_I2C_INTERCARD_COMM] = I2C_open(MY_CONFIG_I2C_INTERCARD_COMM, &gI2cParams[MY_CONFIG_I2C_INTERCARD_COMM]);
                gC2CI2CHandle = gI2cHandle[MY_CONFIG_I2C_INTERCARD_COMM];
    
                if (gC2CI2CHandle == NULL)
                {
                    CUSTOM_PRINT("\n[I2C] C2C Handle reopen FAILED!\n");
                }
                else
                {
                    CUSTOM_PRINT("\n[I2C] C2C Handle reopened successfully.\n");
                }
            }
            else
            {
                CUSTOM_PRINT_DEBUG("\n[I2C] C2C Handle close Failed....!\n");
            }
        }
    }
    
    
    void libI2C_switchRoleToTarget(void)
    {
        CUSTOM_PRINT("\n[I2C] Switching role to TARGET...\n");
        libI2C_reopenC2CHandle();    // Close and reopen handle cleanly
    
    
        //    I2C_deinit();
        //    I2C_init();
        //    Drivers_i2cOpenHld();
    
        isController = FALSE;
        libI2C_patchOwnAddress(cardUniqueId);
        //libI2C_armTargetRx();
        CUSTOM_PRINT("\n[I2C] Role switched to TARGET. RX armed.\n");
    }
    
    void libI2C_printCurrentRole(void)
    {
        if (isController)
        {
            CUSTOM_PRINT("\n[I2C] Current Role: CONTROLLER\n");
        }
        else
        {
            CUSTOM_PRINT("\n[I2C] Current Role: TARGET\n");
        }
    }
    
    
    static void libI2C_disableInterrupt(uint32_t baseAddr, uint32_t intFlag)
    {
        CSL_I2cRegsOvly i2cRegs = (CSL_I2cRegsOvly)baseAddr;
        i2cRegs->ICIMR &= ~intFlag;
    }
    
    static void libI2C_clearInterruptStatus(uint32_t baseAddr, uint32_t intFlag)
    {
        CSL_I2cRegsOvly i2cRegs = (CSL_I2cRegsOvly)baseAddr;
        i2cRegs->ICSTR = intFlag;
    }
    
    i32 libI2C_sendCommandAndReceive(const u8 *cmdBuf, u32 cmdLen, u8 *respBuf, u32 respLen)
    {
        i32 result = I2C_ERROR_GENERIC;
    
        if (!isController)
        {
            CUSTOM_PRINT("\n[I2C] Not in CONTROLLER mode. Cannot send+receive.\n");
            result = PEER_UNAVAILABLE;
        }
        else if ((NULL == cmdBuf) || (0U == cmdLen) || (NULL == respBuf) || (0U == respLen))
        {
            CUSTOM_PRINT("\n[I2C] Invalid parameters for send+receive.\n");
            result = I2C_ERROR_INVALID;
        }
        else
        {
            I2C_Transaction txn = {0};
            I2C_Transaction_init(&txn);
    
            txn.targetAddress = peerAddress;
            txn.writeBuf = (void *)cmdBuf;
            txn.writeCount = cmdLen;
            txn.readBuf = respBuf;
            txn.readCount = respLen;
            txn.controllerMode = TRUE;
            txn.timeout = MY_I2C_TRANSACTION_TIMEOUT;
    
            i32 status = I2C_transfer(gC2CI2CHandle, &txn);
    
            if (I2C_STS_SUCCESS == status)
            {
                result = (i32)respLen;
            }
            else
            {
                CUSTOM_PRINT("\n[I2C] Send+Receive transaction failed. Status = %d\n", status);
                result = status;
            }
        }
    
        return result;
    }
    
    i8* getI2CMsgString(const u8 msgId)
    {
        i8 *retStr = (i8 *)"Invalid I2C Msg";
    
        switch(msgId)
        {
        case I2C_MSG_ID_HEALTH_HEARTBEAT:
            retStr = (i8 *)"HEALTHY";
            break;
        case I2C_MSG_ID_LOCO_DATA_SYNC_REQ:
            retStr = (i8 *)"I2C_SYNC_REQ";
            break;
        case I2C_MSG_ID_LOCO_DATA_SYNC_RESP:
            retStr = (i8 *)"I2C_SYNC_RESP";
            break;
        default:
            break;
        }
    
        return retStr;
    }
    
    
    
    void setI2CBusyFlag4C2C(void)
    {
        gI2CBusyFlag = I2C_BUSY_FLAG_SET;
    }
    
    void clearI2CBusyFlag4C2C(void)
    {
        gI2CBusyFlag = I2C_BUSY_FLAG_CLEAR;
    }
    
    u8 getI2CBusyFlagSet4C2C(void)
    {
        u8 firstRead = gI2CBusyFlag;
        delay_ms(1U);
        //    RAW_DELAY(200);
        u8 secondRead = gI2CBusyFlag;
    
        if (firstRead == secondRead)
        {
            return firstRead;
        }
        else
        {
            return I2C_BUSY_FLAG_SET;  // Treat as busy if inconsistent
        }
    }
    
    u8 isI2Cinit4C2CSuccess(void)
    {
        return initC2CInit;
    }
    
    void setI2Cinit4C2CSuccess(void)
    {
        initC2CInit = TRUE;
    }
    
    u8 translateI2CAddress(const u8 in)
    {
        u8 result = 0xFF;
        switch(in)
        {
        case 0x03U:
            result = 0x03;
            break;
        case 0x00U:
            result = 0x01;
            break;
        case 0x07U:
            result = 0x07;
            break;
        case 0x04U:
            result = 0x04;
            break;
        default:
            CUSTOM_PRINT("\n Blunder [%s]",FUNC_NAME);
            break;
        }
        return result;
    }
    
    #define LIBI2C_INT_MASK_ARBITRATION_LOST       (CSL_I2C_ICIMR_AL_MASK)
    #define LIBI2C_INT_MASK_NO_ACK                 (CSL_I2C_ICIMR_NACK_MASK)
    #define LIBI2C_INT_MASK_ADRR_READY_ACESS       (CSL_I2C_ICIMR_ARDY_MASK)
    #define LIBI2C_INT_MASK_RECV_READY             (CSL_I2C_ICIMR_ICRRDY_MASK)
    #define LIBI2C_INT_MASK_TRANSMIT_READY         (CSL_I2C_ICIMR_ICXRDY_MASK)
    #define LIBI2C_INT_MASK_STOP_CONDITION         (CSL_I2C_ICIMR_SCD_MASK)
    #define LIBI2C_INT_MASK_ADRR_TARGET            (CSL_I2C_ICIMR_AAS_MASK)
    
    #define LIBI2C_ALL_INTS_MASK                   (   LIBI2C_INT_MASK_ARBITRATION_LOST   |   \
            LIBI2C_INT_MASK_NO_ACK             |   \
            LIBI2C_INT_MASK_ADRR_READY_ACESS   |   \
            LIBI2C_INT_MASK_RECV_READY         |   \
            LIBI2C_INT_MASK_TRANSMIT_READY     |   \
            LIBI2C_INT_MASK_STOP_CONDITION     |   \
            LIBI2C_INT_MASK_ADRR_TARGET            \
    )
    
    static int32_t libI2C_lld_deInit(I2CLLD_Handle handle)
    {
        int32_t                 status = I2C_STS_SUCCESS;
        I2CLLD_Object           *object = NULL;
    
        /* Input parameter validation */
        if (handle != NULL)
        {
            /* Get the pointer to the object */
            object = (I2CLLD_Object*)handle;
    
            /* Check to see if a I2C transaction is in progress */
            if (object->currentMsg == NULL)
            {
    
                /* Mask I2C interrupts */
                libI2C_ControllerIntDisableEx(object->baseAddr, LIBI2C_ALL_INTS_MASK);
    
                /* Disable the I2C Controller */
                libI2C_ControllerDisable(object->baseAddr);
    
                object->state = I2C_STATE_RESET;
            }
            else
            {
                status = I2C_STS_ERR;
            }
        }
        else
        {
            status = I2C_STS_ERR_INVALID_PARAM;
        }
        return status;
    }
    static void libI2C_ControllerIntDisableEx(uint32_t baseAddr, uint32_t intFlag)
    {
        CSL_I2cRegsOvly i2cRegs = (CSL_I2cRegsOvly)baseAddr;
        i2cRegs->ICIMR &= ~intFlag;
    }
    
    static void libI2C_ControllerDisable(uint32_t baseAddr)
    {
        /* Put I2C module in reset */
        CSL_I2cRegsOvly i2cRegs = (CSL_I2cRegsOvly)baseAddr;
        i2cRegs->ICMDR &= ~CSL_I2C_ICMDR_IRS_MASK;
    }
    
    static int32_t libI2C_close(I2C_Handle handle)
    {
        I2C_Object *object = NULL;
        I2C_HwAttrs const *hwAttrs = NULL;
        int32_t status = I2C_ERROR_GENERIC;
    
        /* Input parameter validation */
        if (handle != NULL)
        {
            /* Get the pointer to the object */
            object = (I2C_Object*)handle->object;
            hwAttrs = (I2C_HwAttrs const *)handle->hwAttrs;
    
            /* Check to see if a I2C transaction is in progress */
            if (object->headPtr == NULL)
            {
                CUSTOM_PRINT_DEBUG("\n before deinit ");
                int32_t res1 = libI2C_lld_deInit(object->i2cLldHandle);
                CUSTOM_PRINT_DEBUG("\n after deinit [%d]",res1);
    
                if(res1 == I2C_STS_SUCCESS)
                {
                    status = I2C_SUCCESS;
                }
                else
                {
                    CUSTOM_PRINT_DEBUG("\n lld handle close error [%d]",res1);
                    status = I2C_ERROR_GENERIC;
                }
                ASSERT(status == SystemP_SUCCESS);
    
                if (true == hwAttrs->enableIntr)
                {
                    /* Destruct the Hwi */
                    (void)HwiP_destruct(&object->hwiObj);
                }
    
                /* Destruct the instance lock */
                (void)SemaphoreP_destruct(&object->mutex);
    
                if (I2C_MODE_BLOCKING == object->i2cParams.transferMode)
                {
                    /* Destruct the transfer completion lock */
                    (void)SemaphoreP_destruct(&object->transferComplete);
                }
    
                object->isOpen = (bool)false;
                status = I2C_SUCCESS;
            }
            //        SemaphoreP_post(&gI2cDrvObj.lockObj);
        }
        else
        {
    
        }
        return status;
    }
    
    /*
     * testRoleManager.c
     *
     *  Created on: 14-Jul-2025
     *      Author: admin7
     */
    #include "testC2C_I2C.h"
    #include "cardIdentity.h"
    #include "syncManager.h"
    #include "FSI/fsi_api.h"
    #include "2oo2Manager.h"
    #include "hotStandBy.h"
    
    
    extern u8 gVar;
    
    volatile static u32 val = 0;
    
    static void prepareTgtTxBuffer(void);
    
    static void prepareTgtTxBuffer()
    {
        memset(txI2CBuffer(),val,10);
    }
    
    void roleManagerTest(void)
    {
        static u16 count = 1;
    
        initCardIdentity();
    
        printCardDetails();
    
        initCardPositionForBottomController();
    
        printCardDetails();
    
        //    syncPointInit();
    
        delay_ms(1000);
        libI2C_initC2C(CardId_getUniqueId());
        libI2C_startupRoleDetection(CardId_getCardPosition(), 10000, 6000);
        libI2C_printCurrentRole();
    
    
        while(1)
        {
            CUSTOM_PRINT("\n --- Excuting [%d] ---- \n", val);
            libI2C_printCurrentRole();
    
            u32 t1 = nowTickMs();
    
            if(TRUE != isI2CController())
            {
                libI2C_armTargetRx();
            }
            if(TRUE == isI2CController())
            {
                libI2C_receive(rxI2CBuffer(), 20);
            }
            else
            {
                prepareTgtTxBuffer();
            }
    
            val++;
    
            if(val == 10)
            {
                if(TRUE != isI2CController())
                {
                    libI2C_switchRoleToController();
                }
                else
                {
                    libI2C_switchRoleToTarget();
                }
                gVar = 11;
            }
    
            if(val == 20)
            {
                if(TRUE != isI2CController())
                {
                    libI2C_switchRoleToController();
                }
                else
                {
                    libI2C_switchRoleToTarget();
                }
                gVar = 21;
            }
    
            u32 t2 = nowTickMs() - t1;
            if(t2>2000)
            {
                CUSTOM_PRINT("\n check this our");
            }
            else
            {
                delay_ms(2000-t2);
            }
        }
    
    #ifdef TEST123
        delay_ms(1000);
    
        setI2Cinit4C2CSuccess();
        while(1)
        {
            u32 t1 = nowTickMs();
            u16 val16Bit = 0x0FFF;
    
            CUSTOM_PRINT("\n ------------------------------------- For Count Cycle [%d]", count);
            libI2C_printCurrentRole();
            printHotStandbyStatusSummary();
            //
            //        if(TRUE == isI2CController())
            //        {
            //            libI2C_probePeer();
            //        }
    
    
    
            if (ACTIVE == getSelfActiveStatus())
            {
                val16Bit = 0x0FFE;
            }
            else if(STANDBY == getSelfActiveStatus())
            {
                val16Bit = 0x0F7F;
            }
            else if(NOT_APPLICABLE == getSelfActiveStatus())
            {
                val16Bit = 0x0DFF;
            }
            else
            {
    
            }
    
            if(count%2)
            {
                val16Bit |= 0xF000;
            }
            else
            {
                val16Bit |= 0x7000;
            }
            toHandleLEDAnd7SegmentDsiplay(0x00000075U, val16Bit);
            toHandleLEDAnd7SegmentDsiplay(0x00000076U, val16Bit);
    
    
            if(TRUE == isI2Cinit4C2CSuccess())
            {
                monitorPeerHeartBeat();
                monitorActiveStandbyStatus();
    
                if((ACTIVE == getSelfActiveStatus()) && (FALSE == isI2CController()))
                {
                    //                CUSTOM_PRINT("\n switching to controller form target \n.....");
                    libI2C_switchRoleToController();
                }
            }
            else
            {
                CUSTOM_PRINT("\n Not sending heart Beat \n");
            }
    
    
            printCardDetails();
    
    
    #ifdef DONT_PRINT
            locoDataSyncTest();
    
    
            if((count % 20) == 0)
            {
                CUSTOM_PRINT("\n Loco Data :\n");
                u8 *buff = getLocoBuffer();
                for(u8 i = 0;i<(1500/100);i = i+100)
                {
                    printInHex(&buff[i], 100);
                    CUSTOM_PRINT("\n");
                }
            }
    #endif
            count++;
            val++;
    
    
            u32 t2 = nowTickMs() - t1;
            if(t2>2000)
            {
                CUSTOM_PRINT("\n check this our");
            }
            else
            {
                delay_ms(2000-t2);
            }
        }
    #endif
    }
    
    void locoDataSyncTest(void)
    {
        u32 t1 = nowTickMs();
    
        if (I2C_BUSY_FLAG_CLEAR == getI2CBusyFlagSet4C2C())
        {
            setI2CBusyFlag4C2C();
            reqForSyncLocoDataI2C();
            txSyncLocoData();
            clearI2CBusyFlag4C2C();
        }
        else
        {
            CUSTOM_PRINT(" \n I2c C2c is busy in sync data \n");
        }
    
    
        u32 t2 = nowTickMs()-t1;
    
        if(t2>1000)
        {
            CUSTOM_PRINT("\n check this \n");
        }
        else
        {
            delay_ms(1000-t2);
        }
    }
    

  • This test setup is meant to verify that switching works before integrating the final logic.

    Problem Description:

    • Dynamic I2C role switching is not consistent — sometimes it happens correctly, but other times it fails.

    • On the target side, the writeCount and readCount fields of the I2C transaction structure are not getting updated with the actual transferred values.

    • Instead, these fields retain their initialized values, even after the transaction is complete.

  • Using AM263x MCU+ SDK  10.00.00, mcu_plus_sdk_am263x_10_00_00_35 version