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.

TMS320F28035: Cputimer0

Part Number: TMS320F28035
Other Parts Discussed in Thread: DRV8312,

Now i use CCS to connect to a DRV8312 EVM board. I configure CPU timer2, and give PRD to 299.

void InitDRVSysBCPUTimer2(void)
{
// Initialize internal variables used in this function


// Step 3.5 Interrupts that are used in DRV system are re-madpped to
// ISR functions found in each module
EALLOW; // This is needed to write to EALLOW protected register
PieVectTable.TINT2 = &cpu_timer2_isr;
EDIS; // This is needed to disable write to EALLOW protected registers

// Step 4. Initialize all the Device Peripherals:
// DRVInitCpuTimers(); // For this example, only initialize the Cpu Timers
// Initialize timer period to maximum:
CpuTimer2Regs.PRD.all = 0xFFFFFFFF;
// Initialize pre-scale counter to divide by 1 (SYSCLKOUT):
CpuTimer2Regs.TPR.all = 0;
CpuTimer2Regs.TPRH.all = 0;
// Make sure timer is stopped:
CpuTimer2Regs.TCR.bit.TSS = 1;
// Reload all counter register with period value:
CpuTimer2Regs.TCR.bit.TRB = 1;
// Reset interrupt counters:
CpuTimer2.InterruptCount = 0;
// Configure CPU-Timer 0 to interrupt every 5 us:
//60MHz CPU Freq, 5 us Period (in uSeconds)
// DRVConfigCpuTimer(&CpuTimer0, 120, 5);

CpuTimer2Regs.PRD.all = 100;// Counter decrements PRD+1 times each period

// Set pre-scale counter to divide by 1 (SYSCLKOUT):
CpuTimer2Regs.TPR.all = 0;
CpuTimer2Regs.TPRH.all = 0;

// Initialize timer control register:
CpuTimer2Regs.TCR.bit.TSS = 1; // 1 = Stop timer, 0 = Start/Restart Timer
CpuTimer2Regs.TCR.bit.TRB = 1; // 1 = reload timer
CpuTimer2Regs.TCR.bit.SOFT= 0;
CpuTimer2Regs.TCR.bit.FREE= 0; // Timer Free Run Enabled
CpuTimer2Regs.TCR.bit.TIE =1; // 0 = Disable/ 1 = Enable Timer Interrupt


// Reset interrupt counter:
CpuTimer2.InterruptCount = 0;


// Step 5. Initialize user variables in each module

// Step 6. Configure registers in each module:

// Step 7. Enable interrupts in PIE for each module:
// Do not need to configure PIE for cputimer1
IER |= M_INT14; // Enable CPU Interrupt 2
// Step 8. Wait for each interrupts in each module;


}

I configure PLL as

#define DSP28_PLLCR 12 // 60 MHz devices [60 MHz = (10MHz * 12)/2]
#define DSP28_DIVSEL 2 // Enable /2 for SYSCLKOUT

I create a cpu timer 2 interrupt and
__interrupt void cpu_timer2_isr(void)
{

CpuTimer1.InterruptCount++;
TOGGLEGPIOFlag();
CpuTimer2Regs.TCR.bit.TIF = 1; /* Clear interrupt flag (TIF) for CPU timer2 */

}

In TOGGLEGPIOFlag() function, i toggle GPIO22

void TOGGLEGPIOFlag(void)
{
EALLOW;
GpioCtrlRegs.GPAPUD.bit.GPIO22 = 0; // Enable internal pull up resistor on GPIO22 (Default is disable)
GpioDataRegs.GPATOGGLE.bit.GPIO22 = 1; // Toggle output
GpioCtrlRegs.GPAMUX2.bit.GPIO22 = 0; // Configure GPIO22 as general input and output (default)
GpioCtrlRegs.GPADIR.bit.GPIO22 = 1; // Configure GPIO22 as output
EDIS;
}

In this case, i should have 5 us period, but i only have 6.4 us.a

I try to configure PRD to 100, and period is also 6.4 us. I try to configure PRD to 600, and period is 10 us. That means if I want period is more than 6.4 us, it is ok. But if I want period is less than 6.4 us, it is not ok.

Then, I try to a example in Control suite. Example_2803xCpuTimer. When I configure CPU timer2 to more than 4 us, it is ok. But if I configure CPU timer2 to 1, it can only output 4 us.

//###########################################################################
// Description:
//! \addtogroup f2803x_example_list
//! <h1>Cpu Timer (cpu_timer)</h1>
//!
//! This example configures CPU Timer0, 1, and 2 and increments
//! a counter each time the timer asserts an interrupt.
//!
//! \b Watch \b Variables \n
//! - CpuTimer0.InterruptCount
//! - CpuTimer1.InterruptCount
//! - CpuTimer2.InterruptCount
//
//###########################################################################
// $TI Release: F2803x C/C++ Header Files and Peripheral Examples V130 $
// $Release Date: May 8, 2015 $
// $Copyright: Copyright (C) 2009-2015 Texas Instruments Incorporated -
// http://www.ti.com/ ALL RIGHTS RESERVED $
//###########################################################################

#include "DSP28x_Project.h" // Device Headerfile and Examples Include File

// Prototype statements for functions found within this file.
__interrupt void cpu_timer0_isr(void);
__interrupt void cpu_timer1_isr(void);
__interrupt void cpu_timer2_isr(void);

void main(void)
{
// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the DSP2803x_SysCtrl.c file.
InitSysCtrl();

// Step 2. Initialize GPIO:
// This example function is found in the DSP2803x_Gpio.c file and
// illustrates how to set the GPIO to it's default state.
// InitGpio(); // Skipped for this example

// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
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 DSP2803x_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 DSP2803x_DefaultIsr.c.
// This function is found in DSP2803x_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.TINT0 = &cpu_timer0_isr;
PieVectTable.TINT1 = &cpu_timer1_isr;
PieVectTable.TINT2 = &cpu_timer2_isr;
EDIS; // This is needed to disable write to EALLOW protected registers

// Step 4. Initialize the Device Peripheral. This function can be
// found in DSP2803x_CpuTimers.c
InitCpuTimers(); // For this example, only initialize the Cpu Timers

// Configure CPU-Timer 0, 1, and 2 to interrupt every second:
// 60MHz CPU Freq, 1 second Period (in uSeconds)

ConfigCpuTimer(&CpuTimer0, 60, 1000000);
ConfigCpuTimer(&CpuTimer1, 60, 1000000);
ConfigCpuTimer(&CpuTimer2, 60, 1);

// 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 DSP2803x_CpuTimers.h), the
// below settings must also be updated.

CpuTimer0Regs.TCR.all = 0x4000; // Use write-only instruction to set TSS bit = 0
CpuTimer1Regs.TCR.all = 0x4000; // Use write-only instruction to set TSS bit = 0
CpuTimer2Regs.TCR.all = 0x4000; // Use write-only instruction to set TSS bit = 0

// Step 5. User specific code, enable interrupts:

// Enable CPU int1 which is connected to CPU-Timer 0, CPU int13
// which is connected to CPU-Timer 1, and CPU int 14, which is connected
// to CPU-Timer 2:
IER |= M_INT1;
IER |= M_INT13;
IER |= M_INT14;

// 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

// Step 6. IDLE loop. Just sit and loop forever (optional):
for(;;);
}

__interrupt void cpu_timer0_isr(void)
{
CpuTimer0.InterruptCount++;

// Acknowledge this interrupt to receive more interrupts from group 1
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}

__interrupt void cpu_timer1_isr(void)
{
CpuTimer1.InterruptCount++;
// The CPU acknowledges the interrupt.
EDIS;
}

__interrupt void cpu_timer2_isr(void)
{
EALLOW;
CpuTimer2.InterruptCount++;
// The CPU acknowledges the interrupt.

EALLOW;
GpioCtrlRegs.GPAPUD.bit.GPIO22 = 0; // Enable internal pull up resistor on GPIO22 (Default is disable)
GpioDataRegs.GPATOGGLE.bit.GPIO22 = 1; // Toggle output
GpioCtrlRegs.GPAMUX2.bit.GPIO22 = 0; // Configure GPIO22 as general input and output (default)
GpioCtrlRegs.GPADIR.bit.GPIO22 = 1; // Configure GPIO22 as output
EDIS;
}

//===========================================================================
// No more.
//===========================================================================


1. I use GPIO18 as XCLKOUT and configure XCLKOUTDIV as 2 (System Clock). I test GPIO18 with oscilloscope. And it is 60MHz. That means there is no problem for system clock.

2. I only toggle GPIO and clear cpu timer interrupt flag in the cpu timer interrupt. It can not more than 5 us.

I want to know what is this problem and what is the mininal value, CPU timer can output.

Thanks very much

  • Hi,

    Do do you have the other cpu timer interrupts disabled when you are trying this?

    Could you see how many clocks it is taking to reenter your cpu timer ISR using profiling while debugging? (Wiki on how to use profiling: processors.wiki.ti.com/.../Profiling_on_C28x_Targets) Also can you check how many clock cycles the ISR takes by itself?

    I'm not sure what the minimum period the cpu timers can output off the top of my head, but will post on here if I find out.

    Best,
    Kevin
  • Thanks very much for your advice.



    1. Yes. I have the other cpu timer interrupts disabled.

    2. I try to make two breakpoint as below. First, I run to the first break point. Then, I clear the profile clock. Then, I run the software to next break point. When I do something as below, it show profile time is 0. Do you know why?



    __interrupt void cpu_timer0_isr(void)

    {

    /********************************Code for test**********************************************************************************/

    CpuTimer0.InterruptCount++;


    TOGGLEGPIO22Flag();// Code for test

    // GpioDataRegs.GPATOGGLE.bit.GPIO22 = 1; // Toggle output

    CpuTimer0Regs.TCR.bit.TIF = 1; /* Clear interrupt flag (TIF) for CPU timer0 */

    PieCtrlRegs.PIEACK.bit.ACK1 = 1; /* Clear interrupt acknowledge PIEACK1 group for cpu timer0 interrupt */



    }



    And if I do something as below, it takes 16 cycles.

    __interrupt void cpu_timer0_isr(void)

    {

    /********************************Code for test**********************************************************************************/

    CpuTimer0.InterruptCount++;

    //TOGGLEGPIO22Flag();// Code for test

    GpioDataRegs.GPATOGGLE.bit.GPIO22 = 1; // Toggle output

    CpuTimer0Regs.TCR.bit.TIF = 1; /* Clear interrupt flag (TIF) for CPU timer0 */

    PieCtrlRegs.PIEACK.bit.ACK1 = 1; /* Clear interrupt acknowledge PIEACK1 group for cpu timer0 interrupt */



    }



    Best Regards
  • Hi,

    I can't see where your breakpoints are within your code. Are you measuring the number of cycles the ISR code takes or the number of cycles it takes to re-enter the ISR (therefore the ISR frequency)?

    Please check the second thing if you haven't already (ISR frequency). This will help us see if the ISR is actually running at your desired frequency and maybe it's the toggling of the gpio that's the issue.

    I don't think you should be seeing 0 cycles for either of these scenarios and that is somewhat surprising.

    Best,
    Kevin
  • I am very sorry for the bad picture. I update my question as below.  First, I set CPU timer interrupt every 5 us.

    If I use a function to toggle gpio, and I set break point as below. It takes 0 cycle. And there is only one sentence in the function

    And you can see the time is 6.48ms

    And if I use GpioDataRegs.GPATOGGLE.bit.GPIO22=1 to toggle GPIO. It takes 16 cycles. 

    In this case, you can see the time is from 4.8 ms to 5.4 ms

    So if I can call a function in cpu timer interrupt, the cpu timer can not interrupt every 5 us. Do you think I can call a function in an interrupt function? 

  • Hi,

    Yes, you can call a function within a cpu timer interrupt. You will want to make sure your function does not take too long to where it messes up your cpu timer interrupt frequency (I.E. the function cannot take more cycles than the ISR cycle period).

    I replicated your test using a TMS320F28035 ControlCard and the cpu_timer example program. I did not see the problem you were having, the cpu_timer could interrupt at 1us toggling a GPIO to check. Toggling the gpio by itself took 2 cycles and the gpio toggle function you mentioned took 13 cycles (Not 0 cycles like you said).

    You must also remember that toggling the gpio in your ISR and scoping the pin will show half the frequency you are actually experiencing. Enter the ISR to toggle on the gpio and enter the ISR again to toggle off the gpio for a full cycle.

    Hope this helps,
    Kevin