Problems using TCC0 on SAM D11 as counter

1 post / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I want to setup TCC0 on a SAM D11 as a microsecond counter (in AS7). I have Clock Generator 4 outputting a 16MHz signal as the clock source of TCC0 with a prescaler of 16. So I set it up thinking I could read the COUNT register before and after a point in my code to time the code execution in microseconds...

void TCC0_init_As_us_Counter(void) {
	PM->APBCMASK.reg |= PM_APBCMASK_TCC0;	// Enable APB clock for TCC0

	// Enable TCC0 Generic Clock to use GCLKGEN 4 (16MHz)
	GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(TCC0_GCLK_ID) |
		GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(4);

	// Set TCC0 for Free Running, 1us tick (1MHz)
	TCC0->CTRLA.reg = TCC_CTRLA_PRESCALER_DIV16 | TCC_CTRLA_PRESCSYNC_GCLK;
	TCC0->WAVE.reg = TCC_WAVE_WAVEGEN_NFRQ;	// Normal Frequency
	TCC0->PER.reg = 0xFFFF;			        // Use as 16-bit counter
	TCC0->COUNT.reg = 0;	        // Initialize count to 0
	TCC0->CTRLA.bit.ENABLE = 1;	    // Enable TCC0
}

I naively thought I could just get my times using something like:

		uint16_t time_val1, time_val2, CodeExecutionTime;

		time_val1 = TCC0->COUNT.reg;
		// Code to be timed
		time_val2 = TCC0->COUNT.reg;
		CodeExecutionTime = (int16_t)(time_val2 - time_val1);

Just as I have done on AVRs. However, the above code always returns a result of 0 (even for long code segments).

Aha! Synchronization... (I think).

 

I have gone through MANY code revisions, but none seem to be providing believable results, for example:

uint16_t time_val1, time_val2, CodeExecutionTime;

TCC0->CTRLBSET.reg = TCC_CTRLBSET_CMD_READSYNC;
while (TCC0->SYNCBUSY.bit.COUNT);
time_val1 = TCC0->COUNT.reg;
TCC0->CTRLBSET.reg = TCC_CTRLBSET_CMD_READSYNC;
while (TCC0->SYNCBUSY.bit.COUNT);
time_val2 = TCC0->COUNT.reg;
CodeExecutionTime = (int16_t)(time_val2 - time_val1);

This gives me results, but they are not reasonable. 5mS for for the above code! (I don't think so. And yes I admit it, I have NO idea what I am doing!)

 

I have been able to make these kinds of measurement using TC1, but I need TC1 and TC2 for another purpose.

I am thinking I may be able to use "Software Event" to cause a capture into the CCx register(s). (However, having never used the event system, it is a bit daunting.)

Or a simple START/STOP, but I have not found a good way to do this.

 

Any suggestions greatly appreciated!

 

Edit: fixed some typos.

David (aka frog_jr)

Last Edited: Sun. Jul 10, 2016 - 11:47 AM