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.

TMS320F28379D: CPU timer 0 for slave core (CPU2) not getting serviced

Part Number: TMS320F28379D
Other Parts Discussed in Thread: C2000WARE

I am using the same source code to initialize TIMER0 for both cores (CPU1 and CPU2). I am able to initialize, start and service the TIMER0 interrupt for CPU1 (master core) but for CPU2 (slave core), I see it always hitting the ISR for TIMER0 after the TIMER0 is started and Global Interrupts are enabled. I'm not sure why such different behavior is observed with same logic for different cores?

I am clear on the following:
1. Each core is having its timer instances (TIMER0, TIMER1 & TIMER2)
2. TIMER2 is dedicated for TI-RTOS (if used) and can be used as a normal timer module in case of a non-RTOS application.
3. There is no inter-dependency between CPU cores for their individual timer modules.

Device Interrupt Architecture (source TRM for TMS320F28379D (spruhm8i) by Texas Instruments)



Can someone please help me figure out what could be going wrong with TIMER0 of CPU2?

Regards.

Sumit Panse

  • Hi Sumit,

    I see it always hitting the ISR for TIMER0 after the TIMER0 is started and Global Interrupts are enabled

    Can you please provide more context behind this? The subject line states that Timer 0 on CPU2 is not serviced but here you are saying that the ISR is entered for TIMER0. Is the issue that the ISR is invoked right after you start the timer and not after the timer has finished counting?

    Best Regards,

    Marlyn

  • Hi Marlyn,

    Sorry, my bad for the subject line. Yes, you got it right, ISR is invoked right after timer is started.

    Regards,

    Sumit Panse

  • Hi Sumit,

    Thank you for the clarification! Are you using driverlib or bit field code?

    I modified the 'ipc_ex1_gpio_toggle' example found in C2000Ware to start timer0 at the same time in both CPU1/CPU2. The interrupt should occur every time the timer is finished: C:\ti\c2000\C2000Ware_4_00_00_00\device_support\f2837xd\examples\dual\ipc_gpio_toggle

    Could you please try this if you are using bitfield? If not, let me know and I can generate something in driverlib.

    CPU1:

    //
    // Included Files
    //
    #include "F28x_Project.h"
    #include "F2837xD_Ipc_drivers.h"
    
    __interrupt void cpu_timer0_isr(void);
    //
    // Main
    //
    void main(void)
    {
    //
    // Step 1. Initialize System Control:
    // PLL, WatchDog, enable Peripheral Clocks
    // This example function is found in the F2837xD_SysCtrl.c file.
    //
        InitSysCtrl();
    
    #ifdef _STANDALONE
    #ifdef _FLASH
        //
        // Send boot command to allow the CPU2 application to begin execution
        //
        IPCBootCPU2(C1C2_BROM_BOOTMODE_BOOT_FROM_FLASH);
    #else
        //
        // Send boot command to allow the CPU2 application to begin execution
        //
        IPCBootCPU2(C1C2_BROM_BOOTMODE_BOOT_FROM_RAM);
    #endif
    #endif
    
    //
    // Clear all __interrupts and initialize PIE vector table:
    //
       DINT;
    
    //
    // Initialize the PIE control registers to their default state.
    // The default state is all PIE __interrupts disabled and flags
    // are cleared.
    // This function is found in the F2837xD_PieCtrl.c file.
    //
       InitPieCtrl();
    
    //
    // Disable CPU __interrupts and clear all CPU __interrupt flags:
    //
       IER = 0x0000;
       IFR = 0x0000;
    
    //
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    // This will populate the entire table, even if the __interrupt
    // is not used in this example.  This is useful for debug purposes.
    // The shell ISR routines are found in F2837xD_DefaultIsr.c.
    // This function is found in F2837xD_PieVect.c.
    //
       InitPieVectTable();
    
    //
    // Interrupts that are used in this example are re-mapped to
    // ISR functions found within this file.
    //
       EALLOW;  // This is needed to write to EALLOW protected registers
       PieVectTable.TIMER0_INT = &cpu_timer0_isr;
       EDIS;    // This is needed to disable write to EALLOW protected registers
    
    //
    // Initialize the Device Peripheral. This function can be
    //         found in F2837xD_CpuTimers.c
    //
       InitCpuTimers();   // For this example, only initialize the Cpu Timers
    
    //
    // Configure CPU-Timer 0 to __interrupt every 500 milliseconds:
    // 60MHz CPU Freq, 50 millisecond Period (in uSeconds)
    //
       ConfigCpuTimer(&CpuTimer0, 60, 500000);
    
    //
    // To ensure precise timing, use write-only instructions to write to the entire
    // register. Therefore, if any of the configuration bits are changed in
    // ConfigCpuTimer and InitCpuTimers (in F2837xD_cputimervars.h), the below
    // settings must also be updated.
    //
       //CpuTimer0Regs.TCR.all = 0x4001;
    
    //
    // Enable CPU INT1 which is connected to CPU-Timer 0:
    //
       IER |= M_INT1;
    
    //
    // Enable TINT0 in the PIE: Group 1 __interrupt 7
    //
       PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
    
    //
    // Enable global Interrupts and higher priority real-time debug events:
    //
       EINT;   // Enable Global __interrupt INTM
       ERTM;   // Enable Global realtime __interrupt DBGM
    
       while (IpcRegs.IPCSTS.bit.IPC17 == 0);
       IpcRegs.IPCACK.bit.IPC17 = 1;
       CpuTimer0Regs.TCR.bit.TSS   = 0;
    
    //
    // Step 6. IDLE loop. Just sit and loop forever (optional):
    //
       for(;;);
    }
    
    //
    // cpu_timer0_isr - CPU Timer0 ISR that toggles GPIO32 once per 500ms
    //
    __interrupt void cpu_timer0_isr(void)
    {
       CpuTimer0.InterruptCount++;
    
       //
       // Acknowledge this __interrupt to receive more __interrupts from group 1
       //
       PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
    }
    
    //
    // End of file
    //

    CPU2:

    //
    // Included Files
    //
    #include "F28x_Project.h"
    #include "F2837xD_Ipc_drivers.h"
    
    __interrupt void cpu_timer0_isr(void);
    
    //
    // Main
    //
    void main(void)
    {
    //
    // Step 1. Initialize System Control:
    // PLL, WatchDog, enable Peripheral Clocks
    // This example function is found in the F2837xD_SysCtrl.c file.
    //
       // InitSysCtrl();
    
    
        //
        // Clear all __interrupts and initialize PIE vector table:
        //
           DINT;
    
        //
        // Initialize the PIE control registers to their default state.
        // The default state is all PIE __interrupts disabled and flags
        // are cleared.
        // This function is found in the F2837xD_PieCtrl.c file.
        //
           InitPieCtrl();
    
        //
        // Disable CPU __interrupts and clear all CPU __interrupt flags:
        //
           IER = 0x0000;
           IFR = 0x0000;
    
        //
        // Initialize the PIE vector table with pointers to the shell Interrupt
        // Service Routines (ISR).
        // This will populate the entire table, even if the __interrupt
        // is not used in this example.  This is useful for debug purposes.
        // The shell ISR routines are found in F2837xD_DefaultIsr.c.
        // This function is found in F2837xD_PieVect.c.
        //
           InitPieVectTable();
    
        //
        // Interrupts that are used in this example are re-mapped to
        // ISR functions found within this file.
        //
           EALLOW;  // This is needed to write to EALLOW protected registers
           PieVectTable.TIMER0_INT = &cpu_timer0_isr;
           EDIS;    // This is needed to disable write to EALLOW protected registers
    
        //
        // Initialize the Device Peripheral. This function can be
        //         found in F2837xD_CpuTimers.c
        //
           InitCpuTimers();   // For this example, only initialize the Cpu Timers
    
        //
        // Configure CPU-Timer 0 to __interrupt every 500 milliseconds:
        // 60MHz CPU Freq, 50 millisecond Period (in uSeconds)
        //
           ConfigCpuTimer(&CpuTimer0, 60, 500000);
    
        //
        // To ensure precise timing, use write-only instructions to write to the entire
        // register. Therefore, if any of the configuration bits are changed in
        // ConfigCpuTimer and InitCpuTimers (in F2837xD_cputimervars.h), the below
        // settings must also be updated.
        //
           //CpuTimer0Regs.TCR.all = 0x4001;
    
        //
        // Enable CPU INT1 which is connected to CPU-Timer 0:
        //
           IER |= M_INT1;
    
        //
        // Enable TINT0 in the PIE: Group 1 __interrupt 7
        //
           PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
    
        //
        // Enable global Interrupts and higher priority real-time debug events:
        //
           EINT;   // Enable Global __interrupt INTM
           ERTM;   // Enable Global realtime __interrupt DBGM
    
        IpcRegs.IPCSET.bit.IPC17    = 1;
        CpuTimer0Regs.TCR.bit.TSS   = 0;
        //
        // Step 6. IDLE loop. Just sit and loop forever (optional):
        //
           for(;;);
        }
    
        //
        // cpu_timer0_isr - CPU Timer0 ISR that toggles GPIO32 once per 500ms
        //
        __interrupt void cpu_timer0_isr(void)
        {
           CpuTimer0.InterruptCount++;
    
           //
           // Acknowledge this __interrupt to receive more __interrupts from group 1
           //
           PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
        }
    

    Best Regards,

    Marlyn