LAUNCHXL-F280049C: I2C code in 10ms ISR gives FIFO Timeout after changing some code in 250ms loop

Part Number: LAUNCHXL-F280049C
Other Parts Discussed in Thread: TCAL9539

i have I2c code in 10ms ISR and after 25 count i have 250ms loop where i read ADC data.

I have changed code in ADC read data fucntion in 250ms loop and after that i got I2C FIFO timeout that is in 10ms loop.

the below code is I2C read data code:

uint8_t TCAL9539_ReadRegister(uint32_t base, uint8_t slaveAddress, uint8_t reg, uint8_t *I2Cstatus)
{
    if(I2C_Error(base))
    {
        *I2Cstatus = I2CMCUError;
        return 0;
    }
     uint8_t data,i;
     uint8_t tempI2Cdata[2]={0};
     uint8_t Attempt= 0;
   /*  while(I2CisBusBusy(base) == 1)
     {
             Attempt++;
             DEVICE_DELAY_US(100);
             if(Attempt >= 5)
             {
                 *I2Cstatus=I2CBusyTimout;
                 //return 0;
             }
     }*/
     Attempt= 0;
     while(I2CgetStopConditionStatus(base) == 1)
     {
             Attempt++;
             DEVICE_DELAY_US(200);
             if(Attempt >= 5)
             {
                *I2Cstatus=I2CStopTimout;
                return 0;
             }
     }
     I2CenableFIFO(base);
     I2CsetConfig(base,I2C_CONTROLLER_SEND_MODE);
     I2CsetSlaveAddress(base,slaveAddress);
     I2CsetDataCount(base,1);
     I2CputData(base,reg);
     I2CsendStartCondition(base);
     Attempt= 0;
     while(I2CgetTxFIFOStatus(base))
     {
         Attempt++;
         DEVICE_DELAY_US(200);
         if(Attempt >= 5)
            {
             *I2Cstatus=I2CTxFifoTimout;
              return 0;
            }
     }
     I2CsetConfig(base, I2C_CONTROLLER_RECEIVE_MODE);
     I2CsetDataCount(base,2);
     I2CsendStartCondition(base);
     for(i=0;i<2;i++)
     {
         tempI2Cdata[i] = I2C_getData(base);
     }
     Attempt= 0;
     while(I2CgetRxFIFOStatus(base) != I2C_FIFO_RX2)
     {
         Attempt++;
         DEVICE_DELAY_US(200);
         if(Attempt >= 5)
            {
             *I2Cstatus =I2CRxFifoTimout;
              return 0;
            }
     }
     I2CsendStopCondition(base);
     Attempt= 0;
     while(I2CgetStopConditionStatus(base) == 0)
     {
         Attempt++;
         DEVICE_DELAY_US(200);
         if(Attempt >= 5)
         {
             *I2Cstatus =I2CStopTimout;
             return 0;
         }
     }
     data = (tempI2Cdata[0] & 0xFF) + ((tempI2Cdata[1] & 0xFF) << 8);

     *I2Cstatus =I2CSuccess;

     return data;// Send stop condition to end the write phase

}

The below code is ADC read data fucntion:
Before change:
float GetNT1000TempValue(float32_t SensorVoltage);
 ChargerData.AMB = GetNT1000TempValueAMB(AMB,10000.0f,100000.0f);

After change:
float GetNT1000TempValue(float32_t SensorVoltage,float RPULL,float R01,float gain,float pullupvolt);

ChargerData.AMB = GetNT1000TempValue(AMB,10000.0f,100000.0f,1.0f,3300.0f);

The above code is the only change where i have added 4 float variables and that has caused I2CRxFifoTimout in the I2C status and before change we got I2C status as I2CSuccess  in the 10ms loop.

we have stack size of 0x400 out of which we have used only 0x200 which we got to know form the map file.

We need to know why it has happened and the reason for it as well. Thank you.

  • Hi Harihara,

    Thank you for your patience while I was out of office. I will get back to you by tomorrow on this, thank you.

    Best Regards,

    Aishwarya

  • Harihara,

    Apologies for the delay. By adding more input variables to the function header, you are increasing the total time of the function, and it is exposing a race condition. In any case, you should be polling with I2CgetRxFIFOStatus() before reading the DRR with I2C_getData().

    Also, instead of uint8_t data, it should be uint16_t. The map file only shows the original statically allocated .stack size. Use the memory allocation tool to better understand the application memory usage.

    Best Regards,

    Aishwarya

  • Hi Aishwarya,

    uint8_t is defined as uint16_t in this controller.

    The below line is from the library of this controller
    typedef uint16_t uint8_t;
    typedef int16_t int8_t;


    In any case, you should be polling with I2CgetRxFIFOStatus() before reading the DRR with I2C_getData().
    We have also tried commenting it out 

    while(I2CgetRxFIFOStatus(base) != I2C_FIFO_RX2)
         {
             Attempt++;
             DEVICE_DELAY_US(200);
             if(Attempt >= 5)
                {
                 *I2Cstatus =I2CRxFifoTimout;
                  return 0;
                }
         }

    but still the effect is same with or without commenting.


    We have analyzed the memory allocation window and stack usage window as well. There is no exceeding of stack boundary. 

    I have used stack painting in the first line of main() fucntion and made all the stack section values as 0xAAAA and halted in the middle of the execution and checked the memory browser and approximately 72 bytes are left that are painted and all other values have changed to values and during execution all values are changing and there is no overflow.

    I tried increasing the stack size and there is no effect as well. In memory allocation we have used only 75 percent of the stack and 78 percent of the flash memory and our code runs on flash memory only.

    The below line is from linker file
       RAMM1           : origin = 0x000400, length = 0x000400     /* on-chip RAM block M1 */

    The below line is from map file 

                  ORIGIN    LENGTH
    .stack 1 00000400 00000200 

    I have attached linker file as well

    MEMORY
    {
    PAGE 0 :
    
       RAMM0           	: origin = 0x0000F5, length = 0x00030B
    
       RAMLS0          	: origin = 0x008000, length = 0x000800
       RAMLS1          	: origin = 0x008800, length = 0x000800
       RAMLS2      		: origin = 0x009000, length = 0x000800
       RAMLS3      		: origin = 0x009800, length = 0x000800
       RAMLS4      		: origin = 0x00A000, length = 0x000800
       RESET           	: origin = 0x3FFFC0, length = 0x000002
    
    #ifdef __TI_COMPILER_VERSION__
       #if __TI_COMPILER_VERSION__ >= 20012000
    GROUP {      /* GROUP memory ranges for crc/checksum of entire flash */
       #endif
    #endif
      /* BEGIN is used for the "boot to Flash" bootloader mode   */
    
       BEGIN           	: origin = 0x085000, length = 0x000002
       FLASH_TEXT       : origin = 0x085002, length = 0x009FFE
    
       /* Flash sectors */
       /* BANK 0 */
       //FLASH_BANK0_SEC0  : origin = 0x080002, length = 0x000FFE	/* on-chip Flash */
       //FLASH_BANK0_SEC1  : origin = 0x081000, length = 0x001000	/* on-chip Flash */
       //FLASH_BANK0_SEC2  : origin = 0x082000, length = 0x001000	/* on-chip Flash */
       //FLASH_BANK0_SEC3  : origin = 0x083000, length = 0x001000	/* on-chip Flash */
       //FLASH_BANK0_SEC4  : origin = 0x084000, length = 0x001000	/* on-chip Flash */
       //FLASH_BANK0_SEC5  : origin = 0x085000, length = 0x000FFE	/* on-chip Flash */
       //FLASH_BANK0_SEC6  : origin = 0x086000, length = 0x001000	/* on-chip Flash */
       //FLASH_BANK0_SEC7  : origin = 0x087000, length = 0x001000	/* on-chip Flash */
       //FLASH_BANK0_SEC8  : origin = 0x088000, length = 0x001000	/* on-chip Flash */
       //FLASH_BANK0_SEC9  : origin = 0x089000, length = 0x001000	/* on-chip Flash */
       //FLASH_BANK0_SEC10 : origin = 0x08A000, length = 0x001000	/* on-chip Flash */
       //FLASH_BANK0_SEC11 : origin = 0x08B000, length = 0x001000	/* on-chip Flash */
      // FLASH_BANK0_SEC12 : origin = 0x08C000, length = 0x001000	/* on-chip Flash */
     //  FLASH_BANK0_SEC13 : origin = 0x08D000, length = 0x001000	/* on-chip Flash */
    //   FLASH_BANK0_SEC14 : origin = 0x08E000, length = 0x001000	/* on-chip Flash */
       FLASH_BANK0_SEC15 : origin = 0x08F000, length = 0x001000	/* on-chip Flash */
    
       /* BANK 1 */
       FLASH_BANK1_SEC0  : origin = 0x090000, length = 0x001000	/* on-chip Flash */
       FLASH_BANK1_SEC1  : origin = 0x091000, length = 0x001000	/* on-chip Flash */
       FLASH_BANK1_SEC2  : origin = 0x092000, length = 0x001000	/* on-chip Flash */
       FLASH_BANK1_SEC3  : origin = 0x093000, length = 0x001000	/* on-chip Flash */
       FLASH_BANK1_SEC4  : origin = 0x094000, length = 0x001000	/* on-chip Flash */
       FLASH_BANK1_SEC5  : origin = 0x095000, length = 0x001000	/* on-chip Flash */
       FLASH_BANK1_SEC6  : origin = 0x096000, length = 0x001000	/* on-chip Flash */
       FLASH_BANK1_SEC7  : origin = 0x097000, length = 0x001000	/* on-chip Flash */
       FLASH_BANK1_SEC8  : origin = 0x098000, length = 0x001000	/* on-chip Flash */
       FLASH_BANK1_SEC9  : origin = 0x099000, length = 0x001000	/* on-chip Flash */
       FLASH_BANK1_SEC10 : origin = 0x09A000, length = 0x001000	/* on-chip Flash */
       FLASH_BANK1_SEC11 : origin = 0x09B000, length = 0x001000	/* on-chip Flash */
       FLASH_BANK1_SEC12 : origin = 0x09C000, length = 0x001000	/* on-chip Flash */
       FLASH_BANK1_SEC13 : origin = 0x09D000, length = 0x001000	/* on-chip Flash */
       FLASH_BANK1_SEC14 : origin = 0x09E000, length = 0x001000	/* on-chip Flash */
       FLASH_BANK1_SEC15 : origin = 0x09F000, length = 0x000FF0	/* on-chip Flash */
       FLASH_BANK1_SEC15_DO_NOT_USE     : origin = 0x09FFF0, length = 0x000010  /* Reserve and do not use for code as per the errata advisory "Memory: Prefetching Beyond Valid Memory" */
    
    #ifdef __TI_COMPILER_VERSION__
      #if __TI_COMPILER_VERSION__ >= 20012000
    }crc(_ccs_flash_checksum, algorithm=C28_CHECKSUM_16)
      #endif
    #endif
    
    PAGE 1 :
    
       BOOT_RSVD       : origin = 0x000002, length = 0x0000F3     /* Part of M0, BOOT rom will use this for stack */
       RAMM1           : origin = 0x000400, length = 0x000400     /* on-chip RAM block M1 */
    
       RAMLS5      : origin = 0x00A800, length = 0x000800
       RAMLS6      : origin = 0x00B000, length = 0x000800
       RAMLS7      : origin = 0x00B800, length = 0x000800
    
       RAMGS0      : origin = 0x00C000, length = 0x002000
       RAMGS1      : origin = 0x00E000, length = 0x002000
       RAMGS2      : origin = 0x010000, length = 0x002000
       RAMGS3      : origin = 0x012000, length = 0x002000
    }
    
    
    SECTIONS
    {
       codestart        : > BEGIN,     PAGE = 0, ALIGN(4)
       .text            : > FLASH_TEXT,  PAGE = 0, ALIGN(4)
       .cinit           : > FLASH_TEXT,     PAGE = 0, ALIGN(4)
       .pinit           : > FLASH_TEXT,     PAGE = 0, ALIGN(4)
       .switch          : > FLASH_TEXT,     PAGE = 0, ALIGN(4)
       .reset           : > RESET,     PAGE = 0, TYPE = DSECT /* not used, */
    
       .stack           : > RAMM1,     PAGE = 1
       .ebss            : > RAMLS5|RAMGS0,    PAGE = 1
       .esysmem         : > RAMLS5,    PAGE = 1
       .econst          : > FLASH_BANK0_SEC15,    PAGE = 0, ALIGN(4)
    
       ramgs0           : > RAMGS0,    PAGE = 1
       ramgs1           : > RAMGS1,    PAGE = 1
    
        .TI.ramfunc : {} LOAD = FLASH_TEXT,
                             RUN = RAMLS0 | RAMLS1 | RAMLS2 |RAMLS3,
                             LOAD_START(_RamfuncsLoadStart),
                             LOAD_SIZE(_RamfuncsLoadSize),
                             LOAD_END(_RamfuncsLoadEnd),
                             RUN_START(_RamfuncsRunStart),
                             RUN_SIZE(_RamfuncsRunSize),
                             RUN_END(_RamfuncsRunEnd),
                             PAGE = 0, ALIGN(4)
    
       /* crc/checksum section configured as COPY section to avoid including in executable */
       .TI.memcrc          : type = COPY
    
    }
    
    /*
    //===========================================================================
    // End of file.
    //===========================================================================
    */
    


    i have attached the memory allocation of the project as well.


    Thank you.





  • Harihara,

    To help rule out memory related issues, can you explicitly move the .stack to .TI.ramfunc or some larger RAM area to see if that fixes the issue?

    Quick clarification here, commenting out those lines of code isn't the same as polling BEFORE receiving the data. Please try that explicitly. 

    Is that the memory allocation while the project is running?

    Best Regards,

    Aishwarya

  • Hi Aishwarya,

    I have moved the .stack to some larger RAM area and it didn't fix the issue. I used the below RAM which is double of the previous memory.
       RAMLS7      : origin = 0x00B800, length = 0x000800

    I have also increased the stack memory but still it didn't work.

    We tried explicitly polling the Rx fifo before reading the data but the effect is the same.

    The memory allocation picture that I have uploaded is not during execution and I have checked the stack pointer while in debug mode it always stays in the stack memory region boundary only and it didn't overflow even in timer ISR or other interrrupts that we use.




  • Harihara,

    So, we haven't confirmed any stack overflow/corruption during runtime. Let me check with design team on this too.

    Best Regards,

    Aishwarya

  • Harihara,

    In addition, it looks like the controller is not receiving data. The target could be clock stretching as it's not receiving the proper data. Can you check if there is data available for the target to send to the controller?

    Best Regards,

    Aishwarya

  • Hi Aishwarya,

    There is data available for the target to send to the controller and I have checked it.

    The question is I have changed some function in the 250ms loop and it affects the I2C fucntion in 10ms loop how?

    After the change in the 250ms loop function(which i have shared in my initial post) I2C rx fifo timeout is being returned as the status if i revert the function back in the 250 ms loop then I2C status is I2C success why?

    If the target is clock stretching and it takes some time then how the change in the 250ms loop function affects it?

    I have shared the map file of the project with you in my first post as well. If you want other details of the project we can give you. 

    Thank you.


  • Harihara,

    Is it possible to use the original implementation since it works as expected? I would recommend doing so as there seems to be nothing wrong with the peripheral itself, just the timing probably. It is difficult for me to give you any answer with certainty without having your full HW/SW setup as I don't see this issue on my end. 

    If you want to further debug this, maybe you can add a GPIO toggle within the I2C ISR to measure the effect with the original vs new code to see if it's as expected.

    Best Regards,

    Aishwarya

  • Hi Aishwarya,

    Our intention is to find why a change in a function in 250ms loop affects the I2c function in 10ms.

    is it because the address of the fucntion changed in the new code that we have seen in the new generated map file?

    if you have any hunch regarding this do let us know so that we can provide the data of the hypothesis.

    Thank you.


  • Harihara,

    Please complete all the tests mentioned in earlier posts and look into this issue from your end. I have provided all the possible debug steps and issues that could happen from an I2C perspective. At this point, it may just be a general C programming related debug for which I have already provided some clues. 

    Best Regards,

    Aishwarya

  • Hi Aishwarya,

    I have tried and verified the steps you have told us.

    But how some change in a function  in 250ms affects other function in 10ms. Not even a single function is related to both the functions.

    is this because of reading instructions ?

    because the function's address has changed after changing the 250ms ADC function 

    before changing the 250ms function

    0008a7b6 _ReadInputPort0
    0008a715 _TCAL9539_ReadRegister
    0008c07c _GetMuxInput

    after changing the 250ms function

    0008a76c _ReadInputPort0
    0008a6cb _TCAL9539_ReadRegister
    0008c032 _GetMuxInput

    these three functions are being called in 10ms for I2C. So in my _TCAL9539_ReadRegister function  i gave only 100 microseconds of delay is this because it takes more time to read the instruction so it ends in the stop timeout status of the I2C.

    Refer  to the code i have provided above in my initial post.
    Thank you.

  • Harihara,

    I am still not clear if you have tried the debug methods above. As I mentioned already, you have to poll then read like this: 

    I2CsendStartCondition(base);
    
    Attempt = 0;
    while(I2CgetRxFIFOStatus(base) != I2C_FIFO_RX2)  // poll FIRST
    {
        Attempt++;
        DEVICE_DELAY_US(200);
        if(Attempt >= 5)
        {
            *I2Cstatus = I2CRxFifoTimout;
            return 0;
        }
    }
    
    for(i=0; i<2; i++)
        tempI2Cdata[i] = I2C_getData(base);  // read only after FIFO confirmed ready
    

    You only mentioned you commented out the following:

    If you have already made this change, then make sure you make a similar change when interfacing with TX FIFO, so poll I2CgetStatus() for the I2C_STS_BYTE_SENT flag or equivalent before issuing the repeated start. On every bus timeout/error, you should send a stop condition and reset the I2C module.

    I already explained this as well, but by modifying the functions you are changing the location of the functions, into a different 128-bit Flash alignment boundary. You can check your flash wait state/other configurations to probably see there are some wait state stalls that the I2C_getData function is being affected by. This is causing timing issues where the function is called BEFORE the I2C RX FIFO is populated. The subsequent while loop then times out because the FIFO is empty.

    Best Regards,

    Aishwarya