This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28069: C2000 I2C ISR not updating interrupt source

Part Number: TMS320F28069


Hello,

I have a very simple Matlab 2020b simulink with a single SystemObject block. This block simply calls some hand code which does some I2C transactions. My hand code works as expected when I run it on a 28069 launchpad. However when I run the same I2C code using Simulink Code generation on my 28069 custom board, the code does not work as expected.

The issue is that the I2C interrupt source always returns 0 when my I2C ISR is called. I expect the source to be I2C_ARDY_ISRC or I2C_NACK_ISRC.


}

Uint8 i2cdrvCmdCheckSlavePresent(
        Uint8 slaveAddr,
        Uint32 timeoutMs)
{
    Uint8 isSuccess = !i2cdrvIsBusy();
    if (isSuccess)
    {
        m_state = I2CDRVSTATE_BUSY;
        ...

        I2caRegs.I2CSAR = slaveAddr;
        // Enable ARDY and NACK interrupts
        I2caRegs.I2CIER.all = 0x0006;
        // Mode -> FREE, STT, MST, TRX, RM, IRS all set.
        I2caRegs.I2CMDR.all = 0x66A0;
    }

    return isSuccess;
}

static void _init(void)
{
    // Put in reset
    I2caRegs.I2CMDR.all = 0x0000;

    // Add our interrupt handler to vector table
    EALLOW;
    PieVectTable.I2CINT1A = &_i2cInt1AISR;
    EDIS;
    // Enable I2C interrupts in the PIE: Group 8 interrupt 1 and 2
    PieCtrlRegs.PIEIER8.bit.INTx1 = 1;
    //PieCtrlRegs.PIEIER8.bit.INTx2 = 1;
    // Enable CPU INT8 which is connected to PIE group 8
    IER |= M_INT8;

    // Set our own address
    I2caRegs.I2COAR = 0x0001;

    // Clocks
    I2caRegs.I2CPSC.all = CLK_PRESCALE;
    I2caRegs.I2CCLKL = CLK_LOW;
    I2caRegs.I2CCLKH = CLK_HIGH;

    // Disable all ints
    I2caRegs.I2CIER.all = 0x0000;

    // Take out of reset
    I2caRegs.I2CMDR.bit.IRS = 1;
}

// I2C-1A Interrupt - handles the basic I2C
static interrupt void _i2cInt1AISR(void)
{
    // Read interrupt source
     Uint16 intSrc = I2caRegs.I2CISRC.all; //this is always returning 0. it should return I2C_NACK_ISRC or I2C_ARDY_ISRC

    switch(intSrc)
    { .... }
}

I think I2caRegs.I2CISRC is not being updated because by the time the ISR is called the I2C module is in reset mode. Using the debugger I see that at the end of the i2cdrvCmdCheckSlavePresent() function the reset mode is off and interrupts are enabled.

When I enter i2cInt1AISR() I see that the I2C module is in reset. When I run this I2C hand code on the launchpad, I2caRegs.I2CMDR.bit.IRS is always 1.

Could the I2C module entering reset mode be why the interrupt source always returns 0? Or could the module clock freq, or SDCLK period in my init function be the cause of this?

I set a read watchpoint on I2caRegs.I2CMDR.bit.IRS so see what is writing to that register. Only the _init() function should be writing to I2CMDR. For some reason with the watchpoint attached, the ISR always correctly shows the interrupt source to be NACK or ARDY. 

  • Mashrur,

    Can you clarify if the simulink implementation works OK on the 28069 LP, or anytime simulink is involved you have the above issue.  Conversely does your hand code in CCS work on your custom  PCB?

    The fact that you get into I2C ISR, even when there is no bit set in the I2CISRC, means that they were enabled.  The INTCODE is cleared on a system read, so I'm wondering if there is some default action from Simulink doing this(and possibly taking the I2C into reset).

    Best,

    Matthew

  • I have not run the simulink generated code on the launchpad. I will try doing that and see what happens. Nor have I run the hand code in CSS on my custom PCB. 

    I did notice that if I make hand edits to the simulink code I am able to reach the ISR and the interrupt source show NACK or NRDY. My I2C transaction is initialized by the _process1ms function:

    void _process1ms(void)
    {
    // Process I2C
    i2cdrvProcess();
    
    // Process Component Authentication
    sedrvProcess();
    }

    In the simulink generated code (see ert_main.c), _process1ms is called ever time step through the timer0 interrupt. Here the SystemObjectTest_step() is the step function for my simulink model while SysObj_iMEC() is the step function for my SystemObject block in the model.

     If I modify ert_main.c to explicitly call _process1ms() using a simple timer 1 scheduler I am able to reach _i2cInt1AISR() with the correct interrupt source. See ert_main_handedits.c to see what I mean. In this hand editted simulink code, process1ms() is commented out from the SysObj_iMEC() function.

    /*
     * File: ert_main.c
     *
     * Code generated for Simulink model 'SystemObjectTest_HandEdit'.
     *
     * Model version                  : 2.440
     * Simulink Coder version         : 9.4 (R2020b) 29-Jul-2020
     * C/C++ source code generated on : Thu Jan 27 07:29:02 2022
     *
     * Target selection: ert.tlc
     * Embedded hardware selection: Texas Instruments->C2000
     * Code generation objectives:
     *    1. Debugging
     *    2. Traceability
     * Validation result: Not run
     */
    
    #include "SystemObjectTest_HandEdit.h"
    #include "rtwtypes.h"
    
    #include "control.h"
    #include "i2cdrv.h"
    #include "sedrv.h"
    
    volatile int IsrOverrun = 0;
    static boolean_T OverrunFlag = 0;
    
    static void _processLoop(void)
    {
        // Setup for process calls
        // NOTE: Offset so they don't all fire on the same loop
        Uint32 currTimeMs = tmrdrvGetUptimeMs();
        Uint32 next1msTimeMs = currTimeMs;
        Uint32 next5msTimeMs = currTimeMs + 5;
        Uint32 next10msTimeMs = currTimeMs + 10 + 1;
        Uint32 next100msTimeMs = currTimeMs + 100 + 1 + 1;
    
        for (;;)
        {
            currTimeMs = tmrdrvGetUptimeMs(); //uses timer1
    
            // 1ms
            if (currTimeMs >= next1msTimeMs)
            {
                ++next1msTimeMs;
                _process1ms();
            }
    
            // 5ms
            if (currTimeMs >= next5msTimeMs)
            {
                next5msTimeMs += 5;
                //_process5ms();
            }
    
            // 10ms
            if (currTimeMs >= next10msTimeMs)
            {
                next10msTimeMs += 10;
                //_process10ms();
            }
    
            // 100ms
            if (currTimeMs >= next100msTimeMs)
            {
                next100msTimeMs += 100;
                //_process100ms();
            }
        }
    }
    
    void rt_OneStep(void)
    {
      /* Check for overrun. Protect OverrunFlag against preemption */
      if (OverrunFlag++) {
        IsrOverrun = 1;
        OverrunFlag--;
        return;
      }
    
      enableTimer0Interrupt();
      SystemObjectTest_HandEdit_step();
    
      /* Get model outputs here */
      disableTimer0Interrupt();
      OverrunFlag--;
    }
    
    volatile boolean_T stopRequested;
    volatile boolean_T runModel;
    int main(void)
    {
      float modelBaseRate = 0.001;
      float systemClock = 90;
    
      /* Initialize variables */
      stopRequested = false;
      runModel = false;
      c2000_flash_init();
      init_board();
    
    #ifdef MW_EXEC_PROFILER_ON
    
      config_profilerTimer();
    
    #endif
    
      ;
      bootloaderInit();
      ((void) 0);
      SystemObjectTest_HandEdit_initialize();
      globalInterruptDisable();
      configureTimer0(modelBaseRate, systemClock);
      runModel = true;
      enableTimer0Interrupt();
      globalInterruptEnable();
      while (runModel) {
          _processLoop();
      }
    
      /* Disable rt_OneStep() here */
    
      /* Terminate model */
      SystemObjectTest_HandEdit_terminate();
      globalInterruptDisable();
      return 0;
    }
    
    /*
     * File trailer for generated code.
     *
     * [EOF]
     */
    
    /*
     * File: ert_main.c
     *
     * Code generated for Simulink model 'SystemObjectTest'.
     *
     * Model version                  : 2.440
     * Simulink Coder version         : 9.4 (R2020b) 29-Jul-2020
     * C/C++ source code generated on : Thu Jan 27 07:52:01 2022
     *
     * Target selection: ert.tlc
     * Embedded hardware selection: Texas Instruments->C2000
     * Code generation objectives:
     *    1. Debugging
     *    2. Traceability
     * Validation result: Not run
     */
    
    #include "SystemObjectTest.h"
    #include "rtwtypes.h"
    
    volatile int IsrOverrun = 0;
    static boolean_T OverrunFlag = 0;
    void rt_OneStep(void)
    {
      /* Check for overrun. Protect OverrunFlag against preemption */
      if (OverrunFlag++) {
        IsrOverrun = 1;
        OverrunFlag--;
        return;
      }
    
      enableTimer0Interrupt();
      SystemObjectTest_step();
    
      /* Get model outputs here */
      disableTimer0Interrupt();
      OverrunFlag--;
    }
    
    volatile boolean_T stopRequested;
    volatile boolean_T runModel;
    int main(void)
    {
      float modelBaseRate = 0.001;
      float systemClock = 90;
    
      /* Initialize variables */
      stopRequested = false;
      runModel = false;
      c2000_flash_init();
      init_board();
    
    #ifdef MW_EXEC_PROFILER_ON
    
      config_profilerTimer();
    
    #endif
    
      ;
      bootloaderInit();
      ((void) 0);
      SystemObjectTest_initialize();
      globalInterruptDisable();
      configureTimer0(modelBaseRate, systemClock);
      runModel = true;
      enableTimer0Interrupt();
      globalInterruptEnable();
      while (runModel) {
      }
    
      /* Disable rt_OneStep() here */
    
      /* Terminate model */
      SystemObjectTest_terminate();
      globalInterruptDisable();
      return 0;
    }
    
    /*
     * File trailer for generated code.
     *
     * [EOF]
     */
    

  • I did run my code that runs correctly on the launchpad on my custom PCB. The ISR is called correctly every time, I2caRegs.I2CMDR.bit.IRS is 1 every time, the interrupt source is updated correctly.

    I agree, something in the simulink code must be updating the I2CMDR register and reading from I2CISRC. However using watchpoint I can't figure where or what piece of code is causing this issue.

  • Mashrur,

    I'm going to see if I can loop in the MW team to take a look at this and comment.

    Best,

    Matthew