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.

TMS320F2800137: CPU Timer Interrupt Won't Trigger

Part Number: TMS320F2800137
Other Parts Discussed in Thread: SYSCONFIG, C2000WARE

Tool/software:

Hello TI,

I am trying to get a CPU Timer working for a modbus library. I am following timer_ex1_cputimers_sysconfig example.

The CPU Timer is tested in main(),

void main(void)
{
    //Vars
    //Modbus
    eMBErrorCode eStatus;
    
    //
    // Initialize device clock and peripherals
    //
    Device_init();

    //
    // Disable pin locks and enable internal pull-ups.
    //
    Device_initGPIO();

    //
    // Initialize PIE and clear PIE registers. Disables CPU interrupts.
    //
    Interrupt_initModule();

    //
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    //
    Interrupt_initVectorTable();

    //
    // Disable sync(Freeze clock to PWM as well). GTBCLKSYNC is applicable
    // only for multiple core devices. Uncomment the below statement if
    // applicable.
    //
    // SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_GTBCLKSYNC);
    //SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);

    //
    // PinMux and Peripheral Initialization
    //
    Board_init();

    //
    // Enable sync and clock to PWM
    //
    //SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);

    //
    // C2000Ware Library initialization
    //
    C2000Ware_libraries_init();

    //
    // Enable Global Interrupt (INTM) and real time interrupt (DBGM)
    //
    EINT;
    ERTM;
    
    xMBPortTimersInit( 20 );
    vMBPortTimersEnable( );
    while(1)
    {
        
    }
}

xMBPortTimersInit( 20 );
Configures the CPU Timer,
BOOL
xMBPortTimersInit( USHORT usTim1Timerout50us )
{
    EALLOW;

    CPUTimer_setEmulationMode(myCPUTIMER0_BASE, CPUTIMER_EMULATIONMODE_STOPAFTERNEXTDECREMENT);
	CPUTimer_setPreScaler(myCPUTIMER0_BASE, 0U);
    //Set the period for the MB Library.
	CPUTimer_setPeriod(myCPUTIMER0_BASE, 120U);

	CPUTimer_enableInterrupt(myCPUTIMER0_BASE);
	CPUTimer_stopTimer(myCPUTIMER0_BASE);

	CPUTimer_reloadTimerCounter(myCPUTIMER0_BASE);

    Interrupt_register(myCPUTIMER0_BASE, &prvvTIMERExpiredISR);
	Interrupt_enable(myCPUTIMER0_BASE);
	
    EDIS;

    return TRUE;
}
vMBPortTimersEnable();
Enables the timer,
inline void
vMBPortTimersEnable(  )
{
    EALLOW;
    CPUTimer_startTimer(myCPUTIMER0_BASE);
    EDIS;
}
The interrupt is never called,
inline void
vMBPortTimersDisable(  )
{
    EALLOW;
    CPUTimer_stopTimer(myCPUTIMER0_BASE);
    EDIS;
}
I can't seem to figure out why the interrupt is never called. I have put a break point there and execution never stops.
Do you have any advice on how to debug this further?
Thanks,
Allan
  • Hello,

    Let me look into this and get back to you.

    Best Regards,

    Delaney

  • Hello,

    Can you check and verify in the CCS register view that the IER and PIEIER flags for the CPU timer interrupt is enabled? And that the INTM bit is cleared?

    Best Regards,

    Delaney

  • Hi Delaney,

    ==================================================================

    For the MODBUS implementation

    ==================================================================

    I checked the IER and PIEIER flags for CPUTimer0.

    For the IER register everything is zero and never changes. Even after calling BOOL xMBPortTimersInit(). 

    All other PIEIERx registers are zero.

    The INTM bit is cleared.

    ==========================================

    timer_cputimers_example_sysconfig

    ==========================================

    Running the example code does change INT1,

    Running the example code also changes PIEIER1 -> INTx7.

    INTM is clear and remains clear.

    Thanks,

    Allan

  • Hello, 

    Delaney is currently out of office and will get back to you early next week when she is back. Thank you for your patience.

    Best Regards,

    Aishwarya

  • Hi Allan,

    I apologize for the delay. One other thing I should've mentioned - can you verify that you have "Continuous Refresh" toggled on in the CCS window when you are checking the register values? This will make sure they are always being updated properly.

    If the first values are the same as the first screenshots even with Continous Refresh toggled on, the PIEIER and the IER would be the problem. In order for an interrupt to propagate to the CPU, the PIEIER of the INT needs to be 1 (enabled), the PIEACK for the group needs to be 0 (enabled), the IER for the group needs to be 1 (enabled), the global INTM needs to be 0 (enabled).

    Best Regards,

    Delaney

  • Hi Delaney,

    Yes I am sure auto refresh was enabled during both sets of register values.

    Thanks,

    Allan

  • Hi Allan,

    I will have another response back to you tomorrow.

    Best Regards,

    Delaney 

  • Hi Allan,

    Thank you for clarifying. It sounds like the issue is with the MODBUS library then since the configurations in that software layer aren't enabling the interrupt properly. Is this library provided by TI (and if so, can you provide the path in C2000ware)?

    Best Regards,

    Delaney

  • Hi Delaney,

    The modbus library I am using is an open source library called FreeModBus. It is not provided by TI. 

    I was able to fix the issue with the interrupt handler not getting called by creating a new project that does not use the SysCfg tool.

    By not using the SysCfg tool I had to configure everything for the timer manually,

    xMBPoirtTImersInit changed to,

    BOOL xMBPortTimersInit( USHORT usTim1Timerout50us )
    {
        EALLOW;
        Interrupt_register(INT_TIMER0, &prvvTIMERExpiredISR);
        initCPUTimer0();
    
        uint32_t count = 50U*usTim1Timerout50us;
        
        configCPUTimer0(DEVICE_SYSCLK_FREQ, count);
    
        CPUTimer_enableInterrupt(CPUTIMER0_BASE);
        Interrupt_enable(INT_TIMER0);
        CPUTimer_startTimer(CPUTIMER0_BASE);
        EDIS;
        return TRUE;
    }

    vMBPortTimersEnable()

    inline void
    vMBPortTimersEnable(  )
    {
        EALLOW;
        CPUTimer_startTimer(CPUTIMER0_BASE);
        EDIS;
    }

    vMBPortTimersDisable(  )
    inline void
    vMBPortTimersDisable(  )
    {
        EALLOW;
        CPUTimer_stopTimer(CPUTIMER0_BASE);
        EDIS;
    }
    
    __interrupt void prvvTIMERExpiredISR( void )
    __interrupt void prvvTIMERExpiredISR( void )
    {
        // Acknowledge this interrupt to receive more interrupts from group 1
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);
        //ModBus functionc all to notify the protocol stack that the timer has expired.
        ( void )pxMBPortCBTimerExpired(  );
    }
    
    The timer is configured with direct calls to the driverlib.
    void initCPUTimer0()
    {
        //0. Initialize timer period to maximum
        CPUTimer_setPeriod(CPUTIMER0_BASE, 0xFFFFFFFF);
    
        //1. Initialize pre-scale counter to divide by 1 (SYSCLKOUT)
        CPUTimer_setPreScaler(CPUTIMER0_BASE, 0);
    
        //2 Make sure timer is stopped
        CPUTimer_stopTimer(CPUTIMER0_BASE);
    
        //3. Reload all counter register with period value
        CPUTimer_reloadTimerCounter(CPUTIMER0_BASE);
    }
    void configCPUTimer0(float freq, float period)
    {
        uint32_t temp;
        uint32_t cpuTimer = CPUTIMER0_BASE;
        //
        // Initialize timer period:
        //
        temp = (uint32_t)((freq / 1000000) * period);
        CPUTimer_setPeriod(cpuTimer, temp - 1);
    
        //
        // Set pre-scale counter to divide by 1 (SYSCLKOUT):
        //
        CPUTimer_setPreScaler(cpuTimer, 0);
    
        //
        // Initializes timer control register. The timer is stopped, reloaded,
        // free run disabled, and interrupt enabled.
        // Additionally, the free and soft bits are set
        //
        CPUTimer_stopTimer(cpuTimer);
        CPUTimer_reloadTimerCounter(cpuTimer);
        CPUTimer_setEmulationMode(cpuTimer,
                                  CPUTIMER_EMULATIONMODE_STOPAFTERNEXTDECREMENT);
        CPUTimer_enableInterrupt(cpuTimer);
    }