Forums

C6713 Timer problem

Started by Simone Winkler February 10, 2005
Hello,

I am using the C6713 DSP from TI. I'm trying to implement a timer.
I use Timer1 by manually programming it (not inside the DSP-BIOS, but with a 
timer handle).
The only thing I insert into the DSP-BIOS is the Timer function (At HWI 15, 
I insert the function that the timer shall enter after it finishes to 
count). I enabled to use the dispatcher with "self" for the interrupt mask.

The problem is now:
At its first run, the timer enters issues an interrupt after the right 
period, but the next time it enters the function is only about 900 clock 
cycles later but not at the value in the period register that I entered.
To solve that, I tried to set the counter value to zero every time it enters 
the function (by using the function Timer_setCount, but not even the value 
of the counter is set.

Can you help me?

The code i use is the following:

#include "bios.h"
#include <csl.h>
[...]

static TIMER_Handle hTimer1;
static Uint32 TimerEventId;
[...]

/*----------------------------------------------------------------------------*/
static Uint32 TimerControl = TIMER_CTL_RMK( /* Timer control register 
(CTL)*/
  TIMER_CTL_INVINP_NO, /* TINP inverter control(INVINP). Only affects 
operation
                       if CLKSRC =0.
                       TIMER_CTL_INVINP_NO  - Uninverted TINP drives timer
                       TIMER_CTL_INVINP_YES - inverted TINP drives timer */

  TIMER_CTL_CLKSRC_CPUOVR4,/* Timer input clock source (CLKSRC)
                             TIMER_CTL_CLKSRC_CPUOVR4 - CPU clock /4*/

  TIMER_CTL_CP_CLOCK, /* Clock/pulse mode(CP)
                        TIMER_CTL_CP_PULSE - Pulse mode.TSTAT is active one
                        CPU clock after the timer reaches the timer
                        period.PWID determines when it goes inactive.*/

  TIMER_CTL_HLD_YES, /* Hold(HLD). Counter may be read or written regardless 
of
                     HLD value.
                     TIMER_CTL_HLD_YES - Counter is disabled and held in
                     current value.
                     TIMER_CTL_HLD_NO - COunter is allowed to count.   */

  TIMER_CTL_GO_NO, /* Go bit(GO). Resets and starts the timer counter.
                   TIMER_CTL_GO_NO - No effects on the timer.
                   TIMER_CTL_GO_YES - if HLD =1, the counter register
                   is zeroed and begins counting on next clock. */
  TIMER_CTL_PWID_ONE, /* Pulse width(PWID). Only used in pulse mode.
                      TIMER_CTL_PWID_ONE - TSTAT goes inactive one timer
                      input clock cycle after the timer counter value
                      equals the timer period value.
                      TIMER_CTL_PWID_TWO -  TSTAT goes inactive one timer
                      input clock cycle after the timer counter value
                      equals the timer period value.*/

  TIMER_CTL_DATOUT_0, /* Data output (DATOUT).
                      TIMER_CTL_DATOUT_0 - If FUNC  =0,the DATOUT is
                      driven on TOUT.
                      TIMER_CTL_DATOUT_1 - If FUNC =1,The DATOUT is driven
                      on TOUT after inversion by INVOUT.           */

  TIMER_CTL_INVOUT_NO, /* TOUT inverter control (INVOUT)
                       TIMER_CTL_INVOUT_NO - Uninverted TSTAT drives TOUT
                       TIMER_CTL_INVOUT_YES - Inverted TSTAT drives TOUT.*/
                       TIMER_CTL_FUNC_GPIO /* Function of TOUT pin(FUNC).
                       TIMER_CTL_FUNC_GPIO - TOU is a general purpose
                       output pin
                       TIMER_CTL_FUNC_TOUT - TOUT is a timer output pin  */

);

void DDS_Timer(void) {

   //TIMER_setCount(hTimer1,0x0);

[....]function to be done

   count++;
}

void main(void) {

    init_module(0);
    EMIF_config(&emifCfg0);
    set_module_cfg (CFG_CPLD_nRESET);

    CSL_init();

    /* Open TIMER1 device, and reset them to power-on default state */
    hTimer1 = TIMER_open(TIMER_DEV1, TIMER_OPEN_RESET);

    /* Obtain the event ID for the timer device */
    TimerEventId = TIMER_getEventId(hTimer1);

    //IRQ_setVecs(vectors);     /* point to the IRQ vector table */
    IRQ_globalEnable();       /* Globally enable interrupts       */
    IRQ_nmiEnable();          /* Enable NMI interrupt             */

    /* Map TIMER events to physical interrupt number */
    IRQ_map(TimerEventId, 15);

    /* Reset the timer events */
    IRQ_reset(TimerEventId);


    /* Enable the timer events(events are disabled while resetting) */
    IRQ_enable(TimerEventId);

[....]


    T=((double)rate*(double)nstep/(double)nsample); //seconds

    /* Configure the timer devices */
    TIMER_configArgs(hTimer1,
    TimerControl, /* use predefined control value  */
    (unsigned int)(T*56250000.),   /* set period                    */
    0x00000000    /* start count value at zero     */
    );

    TIMER_start(hTimer1);

} 


"Simone Winkler" <simone.winkler@gmx.at> wrote in
news:420b743f$0$11094$3b214f66@aconews.univie.ac.at: 

Hi Simone:

I never had any problems with the Timer functionality for either
the 6711 or the 6713. I pretty much developed that Timer handling 
code straight from the TI CSL documentation. I'm not really sure
what you are doing here, but I'll just show you a small snippet
of what I did - and it sure seems to work.


    /* The configuration structure for the Timer.. */
    TIMER_Config	timerCfg0 =
    {
        //
        // This a bit of a pain in the butt - we need to
        // make sure that the clock is set to internal (CPU) source..
        // I'm not crazy about wading thru all of these bits..
        TIMER_CTL_RMK(
            TIMER_CTL_INVINP_DEFAULT,
            TIMER_CTL_CLKSRC_CPUOVR4,	// Internal clock...
            TIMER_CTL_CP_DEFAULT,
            TIMER_CTL_HLD_DEFAULT,
            TIMER_CTL_GO_DEFAULT,
            TIMER_CTL_PWID_DEFAULT,
            TIMER_CTL_DATOUT_DEFAULT,
            TIMER_CTL_INVOUT_DEFAULT,
            TIMER_CTL_FUNC_DEFAULT ),
        /* Period Register (PRD) */
        (BTIMER_NUM_MSEC_PER_TICK * ( SYSTEM_CLOCK / 1000UL )) / 4UL,
        0x00000000,			/* Counter Register (CNT) */
    };

    if( bTimerOpened == TRUE )
    {
        // We've already opened the timer..
        return 1;
    }

    	//
	// The CSL version...
	//

	hTimer0 = TIMER_open( TIMER_DEV0, TIMER_OPEN_RESET );
	if( hTimer0 == INV )
	{
		// The open function returned a bad result.. 
		return -1;
	}
	
	TIMER_config( hTimer0, &timerCfg0 );

	// 
	// Set up the interrupts for Timer 0
	//

	IRQ_nmiEnable();
	IRQ_globalEnable();

	// Clear the Timer0 flag in ICR, clears the IER 
    	// corresponding flag..
	IRQ_reset(IRQ_EVT_TINT0);		

	// The following 2 macros seem redundant... included here 
	// bacause that's what the TI docs suggest...
	IRQ_disable(IRQ_EVT_TINT0);		// Clear the Timer0 flag 
    	    	    	    	    	    	    	// in IER
							// (it returns what was 
    	    	    	    	    	    	    	//set in IER)..

	IRQ_clear(IRQ_EVT_TINT0);		// Clear the Timer0 flag 
    	    	    	    	    	    	    	// in ICR..

	IRQ_enable(IRQ_EVT_TINT0);

	/* Clear the timer flag (bTimerIntFlag). */
	bTimerIntFlag = FALSE;

	// Kick off the timer...
	// The HLD of the ctl register is released, and the GO 
    	// bit is set..
	TIMER_start( hTimer0 );

    bTimerOpened = TRUE;

    return 0;


Offhand, one of the differences I see is that I use the CSL define
for the Timer event (IRQ_EVT_TINT0), whereas you use Event ID obtained
from the TIMER_getEventID() call (and I am using DEV0, not DEV1, BTW). 
Outside of that, I don't know. I do know that the section of code I 
had did come mostly from the CSL manual, and it never gave me any 
problems.

Hope this helps..

George



> Hello, > > I am using the C6713 DSP from TI. I'm trying to implement a timer. > I use Timer1 by manually programming it (not inside the DSP-BIOS, but > with a timer handle). > The only thing I insert into the DSP-BIOS is the Timer function (At > HWI 15, I insert the function that the timer shall enter after it > finishes to count). I enabled to use the dispatcher with "self" for > the interrupt mask. >
Simone,

I suspect you may be doing something wrong such as writing to the CNT 
register while it is actually running in which case you can end up with an 
indeterminate state for CNT and maybe get the results you're seeing.

How are you measuring this in order to know that it is wrong?

Please post your intended period along with the actual period(s) you are 
seeing.  Also, if you're modifying any of the registers at run-time you 
could put that code here too.

Brad

"Simone Winkler" <simone.winkler@gmx.at> wrote in message 
news:420b743f$0$11094$3b214f66@aconews.univie.ac.at...
> Hello, > > I am using the C6713 DSP from TI. I'm trying to implement a timer. > I use Timer1 by manually programming it (not inside the DSP-BIOS, but with > a timer handle). > The only thing I insert into the DSP-BIOS is the Timer function (At HWI > 15, I insert the function that the timer shall enter after it finishes to > count). I enabled to use the dispatcher with "self" for the interrupt > mask. > > The problem is now: > At its first run, the timer enters issues an interrupt after the right > period, but the next time it enters the function is only about 900 clock > cycles later but not at the value in the period register that I entered. > To solve that, I tried to set the counter value to zero every time it > enters the function (by using the function Timer_setCount, but not even > the value of the counter is set. > > Can you help me? > > The code i use is the following: > > #include "bios.h" > #include <csl.h> > [...] > > static TIMER_Handle hTimer1; > static Uint32 TimerEventId; > [...] > > /*----------------------------------------------------------------------------*/ > static Uint32 TimerControl = TIMER_CTL_RMK( /* Timer control register > (CTL)*/ > TIMER_CTL_INVINP_NO, /* TINP inverter control(INVINP). Only affects > operation > if CLKSRC =0. > TIMER_CTL_INVINP_NO - Uninverted TINP drives timer > TIMER_CTL_INVINP_YES - inverted TINP drives timer */ > > TIMER_CTL_CLKSRC_CPUOVR4,/* Timer input clock source (CLKSRC) > TIMER_CTL_CLKSRC_CPUOVR4 - CPU clock /4*/ > > TIMER_CTL_CP_CLOCK, /* Clock/pulse mode(CP) > TIMER_CTL_CP_PULSE - Pulse mode.TSTAT is active one > CPU clock after the timer reaches the timer > period.PWID determines when it goes inactive.*/ > > TIMER_CTL_HLD_YES, /* Hold(HLD). Counter may be read or written > regardless of > HLD value. > TIMER_CTL_HLD_YES - Counter is disabled and held in > current value. > TIMER_CTL_HLD_NO - COunter is allowed to count. */ > > TIMER_CTL_GO_NO, /* Go bit(GO). Resets and starts the timer counter. > TIMER_CTL_GO_NO - No effects on the timer. > TIMER_CTL_GO_YES - if HLD =1, the counter register > is zeroed and begins counting on next clock. */ > TIMER_CTL_PWID_ONE, /* Pulse width(PWID). Only used in pulse mode. > TIMER_CTL_PWID_ONE - TSTAT goes inactive one timer > input clock cycle after the timer counter value > equals the timer period value. > TIMER_CTL_PWID_TWO - TSTAT goes inactive one timer > input clock cycle after the timer counter value > equals the timer period value.*/ > > TIMER_CTL_DATOUT_0, /* Data output (DATOUT). > TIMER_CTL_DATOUT_0 - If FUNC =0,the DATOUT is > driven on TOUT. > TIMER_CTL_DATOUT_1 - If FUNC =1,The DATOUT is driven > on TOUT after inversion by INVOUT. */ > > TIMER_CTL_INVOUT_NO, /* TOUT inverter control (INVOUT) > TIMER_CTL_INVOUT_NO - Uninverted TSTAT drives TOUT > TIMER_CTL_INVOUT_YES - Inverted TSTAT drives TOUT.*/ > TIMER_CTL_FUNC_GPIO /* Function of TOUT pin(FUNC). > TIMER_CTL_FUNC_GPIO - TOU is a general purpose > output pin > TIMER_CTL_FUNC_TOUT - TOUT is a timer output pin */ > > ); > > void DDS_Timer(void) { > > //TIMER_setCount(hTimer1,0x0); > > [....]function to be done > > count++; > } > > void main(void) { > > init_module(0); > EMIF_config(&emifCfg0); > set_module_cfg (CFG_CPLD_nRESET); > > CSL_init(); > > /* Open TIMER1 device, and reset them to power-on default state */ > hTimer1 = TIMER_open(TIMER_DEV1, TIMER_OPEN_RESET); > > /* Obtain the event ID for the timer device */ > TimerEventId = TIMER_getEventId(hTimer1); > > //IRQ_setVecs(vectors); /* point to the IRQ vector table */ > IRQ_globalEnable(); /* Globally enable interrupts */ > IRQ_nmiEnable(); /* Enable NMI interrupt */ > > /* Map TIMER events to physical interrupt number */ > IRQ_map(TimerEventId, 15); > > /* Reset the timer events */ > IRQ_reset(TimerEventId); > > > /* Enable the timer events(events are disabled while resetting) */ > IRQ_enable(TimerEventId); > > [....] > > > T=((double)rate*(double)nstep/(double)nsample); //seconds > > /* Configure the timer devices */ > TIMER_configArgs(hTimer1, > TimerControl, /* use predefined control value */ > (unsigned int)(T*56250000.), /* set period */ > 0x00000000 /* start count value at zero */ > ); > > TIMER_start(hTimer1); > > } >
Hi,

I tried to use your code... no changes. :(

Simone 


> I suspect you may be doing something wrong such as writing to the CNT > register while it is actually running in which case you can end up with an > indeterminate state for CNT and maybe get the results you're seeing.
Actually I don't write to the CNT register. I once tried to reset it to zero with every entering into the timer function, but that did not work.
> > How are you measuring this in order to know that it is wrong?
with the profiler. It works for the first timer period, but then its only a maximum period of 1000 clock cycles that the timer counts. I can also watch the registers, and I can see, that the cnt register is not at zero or at FFFF... when I enter the function.
> Please post your intended period along with the actual period(s) you are > seeing. Also, if you're modifying any of the registers at run-time you > could put that code here too.
I don't modify any registers at run-time...except that I'm using the EMIF. My intended period is programmable, at the moment I try to implement about 340 ms (19327352 clock cycles at 225 MHz). What i get is a number of clock cycles that is always smaller than 1000. As I said, it WORKS FINE for one period, but not for more than one. :( Where's the problem?? I'm already quite in a hurry, because it's one of the last details that does not work. :((( Simone Thank you for every suggestion!
"Simone Winkler" <simone.winkler@gmx.at> wrote in message 
news:420cadf0$0$11352$3b214f66@aconews.univie.ac.at...

>> How are you measuring this in order to know that it is wrong? > > with the profiler. It works for the first timer period, but then its only > a maximum period of 1000 clock cycles that the timer counts. > I can also watch the registers, and I can see, that the cnt register is > not at zero or at FFFF... when I enter the function.
I wouldn't use the profiler to do this. It puts in a bunch of breakpoints behind the scene to stop and start the CPU core at all the functions you're profiling. The timer, however, keeps on running (i.e. it doesn't halt at breakpoints). What you may be seeing is that the timer is actually firing off periods at the proper rate but it looks wrong in the profiler because the CPU keeps being stopped and started. Bottom line, don't use the profiler to do this. The best way to measure this is using a scope. Either probe the timer output pin or else toggle a GPIO pin every time you get into the your ISR. I imagine you'll find it's already working right. It's probably just the way you're using the profiler that's making it look like it's not working right. Brad
"Simone Winkler" <simone.winkler@gmx.at> wrote in news:420cac6c$0$11868
$3b214f66@aconews.univie.ac.at:

Hi Simone:

I'm stumped then, sorry..
The only thing I'd ask you to try or check on is:

(1). Somewhere at the start of main(), you should be doing:

    	CSL_init();

    	IRQ_setVecs(vectors);

    	[BTW, I noticed that in your original example, you had the 
    	 IRQ_setVecs(vectors) statement commented out. Was there
    	 a problem with it?]

(2). Check to see if there aren't any other places in the code
     path where you could be inadvertently calling IRQ_globalDisable()
     or IRQ_disable(IRQ_EVT_TINT0) or TIMER_close(hTimer0)

(3). Just for sanity sake, and I've done this before, try writing a
     small program that <ONLY> handles the timer interrupt. By
     narrowing down the scope, I can usually find my problem with a
     particular component easier than with a program a program that
     does more than one thing.

Well, that's about it - the other things I'd suggest, but you've
probably also tried, is to take a look at TI's web site, look for
all of their application reports related to handling the Timer 
through CSL. In the meantime, you might also want to place a call
to your TI field application engineer - they may not know precisely
where to look, but they might be able to steer you to another apps
engineer at TI who does know.

I sincerely hope this helps. Keep me posted.

George


> Hi, > > I tried to use your code... no changes. :( > > Simone > >
"Simone Winkler" <simone.winkler@gmx.at> writes:

> Hello, > > I am using the C6713 DSP from TI. I'm trying to implement a timer. > I use Timer1 by manually programming it (not inside the DSP-BIOS, but with a > timer handle). > The only thing I insert into the DSP-BIOS is the Timer function (At HWI 15, > I insert the function that the timer shall enter after it finishes to > count). I enabled to use the dispatcher with "self" for the interrupt mask. >
If you have DSP-BIOS "installed" with your app, it does tend to mess with one of the timers IIRC. Can you use the other one? Cheers, Martin -- martin.j.thompson@trw.com TRW Conekt, Solihull, UK http://www.trw.com/conekt
> The best way to measure this is using a scope. Either probe the timer > output pin or else toggle a GPIO pin every time you get into the your ISR. > I imagine you'll find it's already working right. It's probably just the > way you're using the profiler that's making it look like it's not working > right.
You were right, it gave the right time interval.....:) If only always the problems were that easy... Simone