SAMC21 32-bit timer not counting more than 16 bits.

Go To Last Post
14 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

SAMC21 Xplained Pro. AS6.2, ASF3.27

 

16-bit timer works fine, hits the overflow callback.  When I change to 32-bit only 16-bits of the counter is used.

 

I used the setup from the "TC UNIT TEST".

 

in the debugger screenshot to follow, you can see that TC0 is enabled & set to 32-bit.

 

This topic has a solution.
Last Edited: Thu. Oct 15, 2015 - 11:31 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

you PROBABLY still have the debug watch window displaying tc_test0_module.hw->COUNT16

the way that ASF seems to define peripherals with multiple "modes" has a different data structure for each mode "high up" in the structure, even if most of the registers are essentially parallel.  But when you finally get to COUNT.reg, it will be only 16 bits instead of 32.  (well, this explains the debug window only showing 16bits.  What's the indication in your code that it's only using 16 bits?)

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

When I print the value it is only a value that would fit iin 16-bits.

 

also note that on the right the i/o register for the 32 bit count only show values in the lower 16 bits.

Last Edited: Sun. Sep 20, 2015 - 09:39 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here is a picture of the output.  The top half is with a 16-bit counter and counting the overflows in a callback.

 

The bottom halt is the same program, only changed the timer counter size.

 

loop code:

 

		    port_pin_toggle_output_level(LED0_PIN);
			port_pin_toggle_output_level(PIN_d2);
			for (int xx = 0;xx < 48000000;xx++)
			{
				cntr++;
			}
			//cntr++;
			//snprintf(String, 10, "%d", cntr);
			//puts(String);
			looptime = ((tc_get_count_value(&tc_instance)));
			printf("Looptime is: %u\r\n",(unsigned int)looptime);
			printf("count  is: %d\r\n",cntr);
			printf("Overfl is: %d\r\n",overfl);
			overfl = 0;
			cntr = 0;

 

Last Edited: Sun. Sep 20, 2015 - 10:03 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am reasonably certain that the SAMc21 is not counting more than 16 bits.

 

Here is a screenshot of the debugger.  I have circled the items of note. In the upper left the debugger did enter the TC_COUNTER_SIZE_32BIT return.

 

In the lower left, the 32bit counter only has a 16bit value.

 

on the upper right, the mode is set to 32bit.

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Another screenshot of the debugger.

 

Upper left.  Assembly to load from counter into R3. 

 

On right see R3, only has a 16bit value.  Still can't get the 32bit value to show.

 

 

 

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Happy to say I found the problem.  In ASF tc.c there is an error on indexing into an array for values to be used setting up the MCLK timer for the slave TC.

 

In tc.c there is an error setting up the user interface clock in the MCLK for the slave TC

 

 

/* Enable the user interface clock in the MCLK */

system_apb_clock_set_mask((enum system_clock_apb_bus) inst_mclk_apbmask[instance*2],

inst_mclk_apbmask[2*instance+1]);

 

/* Enable the slave counter if counter_size is 32-bit */

if ((config->counter_size == TC_COUNTER_SIZE_32BIT) && (instance+1 < TC_INST_NUM))

{

/* Enable the user interface clock in the MCLK */

system_apb_clock_set_mask((enum system_clock_apb_bus) inst_mclk_apbmask[instance*2+1], (ERROR should be *2+2)

inst_mclk_apbmask[2*instance+2]); (ERROR should be +3)

}

 

The correct lines should be:

 

system_apb_clock_set_mask((enum system_clock_apb_bus) inst_mclk_apbmask[instance*2+2],

inst_mclk_apbmask[2*instance+3]);

 

 

Here is the array of MCLK APB mask bits for the different TC

 

/* Array of MCLK APB mask bit position for different TC instances */

uint32_t inst_mclk_apbmask[] = {SYSTEM_CLOCK_APB_APBC, MCLK_APBCMASK_TC0,

SYSTEM_CLOCK_APB_APBC, MCLK_APBCMASK_TC1,

SYSTEM_CLOCK_APB_APBC, MCLK_APBCMASK_TC2,

SYSTEM_CLOCK_APB_APBC, MCLK_APBCMASK_TC3,

SYSTEM_CLOCK_APB_APBC, MCLK_APBCMASK_TC4};

 

I must say that it is 2 for 2 on errors in the ASF Example code.  In the Tsens code and in the TC code.

Last Edited: Tue. Sep 29, 2015 - 01:40 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I know this is an old post, but I just want to point out the above is still an issue 2 years later in the most recent version of asf (3.35.1) to date and this fixed it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you for the information, they are very helpfull.

You also mentioned that there is a bug in tsens code also! Can you please say where is the bug, because I want to use internal temperature, but he values are not correct.

I suspect that there is something wrong with configuration of tsens, but for now I did not found the solution.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You also mentioned that there is a bug in tsens code also!

 

I think:

 

http://webcache.googleuserconten...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Samc21 does not have 32bit timer, you have to combine 2 timers in master slave operation to get 32bit counter. Its more than clear in the Datasheet:
Up to eight 16-bit Timer/Counters (TC), configurable as either (see Note): Note:  Maximum and minimum capture is only available in SAM C21N devices.–One 16-bit TC with compare/capture channels–One 8-bit TC with compare/capture channels–One 32-bit TC with compare/capture channels, by using two TCs

When you have such a custom functionality better use ASF4 with HRI interfaces to TC . You can set it up in 4lines :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

? This thread is about a bug in ASF 3 (looks fixed now), check post #7:

/* Enable the slave counter if counter_size is 32-bit */

/Lars

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Actually I just found it necessary to explicitly enable the clock for slave TC1 in my START-based design. This is ASF4 with Atmel Studio 7. So still not fixed.

/**
 * \brief Timer initialization function
 *
 * Enables Timer peripheral, clocks and initializes Timer driver
 */
static void TIMER_0_init(void)
{
	hri_mclk_set_APBCMASK_TC0_bit(MCLK);
	hri_mclk_set_APBCMASK_TC1_bit(MCLK);
	hri_gclk_write_PCHCTRL_reg(GCLK, TC0_GCLK_ID, CONF_GCLK_TC0_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));

	timer_init(&TIMER_0, TC0, _tc_get_timer());
}

The above is the START-generated initialization where I have added the call

 

 hri_mclk_set_ABCMASK_TC1_bit(MCLK);

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Another option is to configure both TC0 and TC1 in atmel start. The auto-generated code will add the 

 hri_mclk_set_ABCMASK_TC1_bit(MCLK);

This way

 void TIMER_0_CLOCK_init(void)
{
    hri_mclk_set_APBCMASK_TC0_bit(MCLK);
    hri_gclk_write_PCHCTRL_reg(GCLK, TC0_GCLK_ID, CONF_GCLK_TC0_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
}

void TIMER_1_CLOCK_init(void)
{
    hri_mclk_set_APBCMASK_TC1_bit(MCLK);
    hri_gclk_write_PCHCTRL_reg(GCLK, TC1_GCLK_ID, CONF_GCLK_TC1_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
}

This way you don't have to alter the atmel start code.