Please help me get SAM E70 timer modules to work...

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

First of all, let me wish you all a Happy New Year.

 

Now, lets get to the topic.

 

I am using a SAM E70 Xplained Development Board & I some how managed to get its timer 0 - channel 0 working using the example code provided in Atmel Studio.

In our current project, we are supposed to use multiple timers to get the logic working. As per datasheet, there are 12 16-bit timer modules in SAM E70. So, I tried to get the code working for other timers. What I did was that, I changed all "TC0" in timers configurations to different timers along with their ISR.

 

The code compiled successfully, but the program refused to work.

There are only a few steps to configure timer module, but still I have got no idea where I have gone wrong.

 

Basic Timer Initialization

ul_sysclk=sysclk_get_cpu_hz();

pmc_enable_periph_clk(ID_TC0);

tc_find_mck_divisor(100,ul_sysclk,&ul_div,&ul_tcclks,ul_sysclk);

tc_init(TC0,0,ul_tcclks|TC_CMR_CPCTRG);

tc_write_rc(TC0,0,TC_IER_CPCS);

tc_start(TC0,0);

ISR

 

TC0_Handler(void)

{

volatile uint32_t ul_dummy;

ul_dummy=tc_get_status(TC0,0);

}

 

This code works perfectly & I am able to configure timer interrupt frequency.

 

But when I try to change the timer, it stops working.

This topic has a solution.

Silly beans are always silly
:)

Last Edited: Fri. Jan 13, 2017 - 08:42 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So this is the code which is working ? What about the code which is not working ?

SAME newbie

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

Yup, The above code works great.

I modified this by changing "Timer Instance", "ISR" & "Timer ID".

 

ie, ID_TC0, TC0, & TC0_Handler(void) to some other timer

 

Silly beans are always silly
:)

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

Sorry, could not get the time to check this... Have you found the solution ? If so, pls share the code. BTW: Is this post of any help :

https://community.atmel.com/forum/sam-e70-timer-counter-confusion?skey=E70%20timer
 

SAME newbie

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

Found this in the same70 headers and lwip stuff and it is running here on my side (breakpoint in handler is periodically hit). Maybe this is of some help...


TC3_IRQn             = 26, /**< 26 SAME70Q21 Timer/Counter 3 (TC3) */
#define ID_TC3    (26) /**< \brief Timer/Counter 3 (TC3) */

 
#ifdef _SAME70_TC1_INSTANCE_
void TC3_Handler    ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
#endif /* _SAME70_TC1_INSTANCE_ */

#ifdef _SAME70_TC1_INSTANCE_
        .pfnTC3_Handler    = (void*) TC3_Handler,    /* 26 Timer/Counter 3 */
#else
        .pvReserved26      = (void*) (0UL),          /* 26 Reserved */
#endif /* _SAME70_TC1_INSTANCE_ */

#if LWIP_STATS
// TC3 means TC1 channel 0.
void TC3_Handler(void)
{
	...
}

/**
 * \brief Enable TC1 channel 0 to trigger each second to compute GMAC stats.
 */
static void configure_timer_for_bandwidth_stats(void)
{
	pmc_enable_periph_clk(ID_TC3);		// Warning TC number is the channel not TC number.
										// Hence TC3 means TC1 channel 0.
	tc_init(TC1, 0,						// Init timer counter 1 channel 0.
			TC_CMR_WAVE |				// Waveform Mode is enabled.
			TC_CMR_CPCTRG |				// UP mode with automatic trigger on RC Compare
			TC_CMR_TCCLKS_TIMER_CLOCK5	// Use slow clock to avoid overflow.
	);

	tc_write_rc(TC1, 0, 32768);			// Load the highest possible value into TC.

	/* Configure TC interrupts for TC TC_CHANNEL_CAPTURE only */
	NVIC_SetPriority(TC3_IRQn, 0);		// TC3 means TC1 channel 0.
	NVIC_EnableIRQ(TC3_IRQn);			// TC3 means TC1 channel 0.
	tc_enable_interrupt(TC1, 0, TC_IER_CPCS);
	tc_start(TC1, 0);					// Start Timer counter 0 channel 0.
}
#endif

 

SAME newbie

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

Here is an example of using TC0 Channel 0 and TC1 Channel 1.     Based on the ASF GETTING_STARTED E70 XPLAINED example.

 

In main.c

#define ID_TC0_0 ID_TC0
#define ID_TC0_1 ID_TC1
#define ID_TC0_2 ID_TC2
#define ID_TC1_0 ID_TC3
#define ID_TC1_1 ID_TC4
#define ID_TC1_2 ID_TC5
#define ID_TC2_0 ID_TC6
#define ID_TC2_1 ID_TC7
#define ID_TC2_2 ID_TC8
#define ID_TC3_0 ID_TC9
#define ID_TC3_1 ID_TC10
#define ID_TC3_2 ID_TC11

#define TC0_0_Handler TC0_Handler 
#define TC0_1_Handler TC1_Handler 
#define TC0_2_Handler TC2_Handler
#define TC1_0_Handler TC3_Handler
#define TC1_1_Handler TC4_Handler
#define TC1_2_Handler TC5_Handler
#define TC2_0_Handler TC6_Handler
#define TC2_1_Handler TC7_Handler
#define TC2_2_Handler TC8_Handler
#define TC3_0_Handler TC9_Handler
#define TC3_1_Handler TC10_Handler
#define TC3_2_Handler TC11_Handler 

next add handlers:

 

// [main_tc0_handler]
#ifndef BOARD_NO_LED_1
void TC0_0_Handler(void)
{
	volatile uint32_t ul_dummy;

	/* Clear status bit to acknowledge interrupt */
	ul_dummy = tc_get_status(TC0, 0);

	/* Avoid compiler warning */
	UNUSED(ul_dummy);

	printf("2 ");
}

void TC1_1_Handler(void)
{
	volatile uint32_t ul_dummy;

	/* Clear status bit to acknowledge interrupt */
	ul_dummy = tc_get_status(TC1, 1);

	/* Avoid compiler warning */
	UNUSED(ul_dummy);

	printf("3 ");
}
// [main_tc0_handler]

Note:  You need to comment out the #define BOARD_NO_LED_1  in conf_board.h

 

Then configure the timers:

 

static void configure_tc0_0(void)
{
	uint32_t ul_div;
	uint32_t ul_tcclks;
	uint32_t ul_sysclk = sysclk_get_cpu_hz();

	/* Configure PMC */
	pmc_enable_periph_clk(ID_TC0_0);


	/** Configure TC for a 4Hz frequency and trigger on RC compare. */
	tc_find_mck_divisor(4, ul_sysclk, &ul_div, &ul_tcclks, ul_sysclk);
	tc_init(TC0, 0, ul_tcclks | TC_CMR_CPCTRG);
	tc_write_rc(TC0, 0, (ul_sysclk / ul_div) / 4);

	/* Configure and enable interrupt on RC compare */
	NVIC_EnableIRQ((IRQn_Type) ID_TC0_0);
	tc_enable_interrupt(TC0, 0, TC_IER_CPCS);


	tc_start(TC0, 0);

}
static void configure_tc1_1(void)
{
	uint32_t ul_div;
	uint32_t ul_tcclks;
	uint32_t ul_sysclk = sysclk_get_cpu_hz();

	/* Configure PMC */
	pmc_enable_periph_clk(ID_TC1_1);


	/** Configure TC for a 8Hz frequency and trigger on RC compare. */
	tc_find_mck_divisor(8, ul_sysclk, &ul_div, &ul_tcclks, ul_sysclk);
	tc_init(TC1, 1, ul_tcclks | TC_CMR_CPCTRG);
	tc_write_rc(TC1, 1, (ul_sysclk / ul_div) / 8);

	/* Configure and enable interrupt on RC compare */
	NVIC_EnableIRQ((IRQn_Type) ID_TC1_1);
	tc_enable_interrupt(TC1, 1, TC_IER_CPCS);


	tc_start(TC1, 1);

}

and turn on the timers

 

	configure_tc0_0();
	configure_tc1_1();

 

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

Looks pretty straightforward to me. This leaves the questions to me

- what is wrong in the code of the thread owner

- what does the lwip's code author mean with the comment

// TC3 means TC1 channel 0

SAME newbie

Last Edited: Wed. Jan 4, 2017 - 10:55 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No Idea,

// TC3 means TC1 channel 0

Silly beans are always silly
:)

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

This code looks exactly like the one I have been working on.
 

Silly beans are always silly
:)

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

Am attaching the working project file using timer0 for reference.

Attachment(s): 

Silly beans are always silly
:)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2
// TC3 means TC1 channel 0

I think he is saying TC0,TC1,TC2, TC3.   Have slightly different meanings depending on the context.

 

There are 12 channels arranged as 3 channels each on timers TC0,TC1,TC2,TC3. Thus TC0 channel 0, TC0 channel 1, TC0 channel 2, TC1 channel 0 ...

 

Each channel has its own interrupt handler, in ASF these are named:  TC0, TC1,TC2,TC3,...TC11.  Thus the handler for TC1 Channel 0 is TC3_Handler.

 

Each channel also needs its own entry in the NVIC IRQ.

 

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

This code looks same as mine.

Then why is it not working?

crying

Silly beans are always silly
:)

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

I do agree with the fact that there are 12 timers on board.
But am confused seeing the below mentioned statement

3 channels each on timers TC0,TC1,TC2,TC3

as per the code suggested by jstampfl,

 

void TC1_1_Handler(void)
{
	volatile uint32_t ul_dummy;

	/* Clear status bit to acknowledge interrupt */
	ul_dummy = tc_get_status(TC1, 1);

	/* Avoid compiler warning */
	UNUSED(ul_dummy);

	printf("3 ");
}

static void configure_tc1_1(void)
{
	uint32_t ul_div;
	uint32_t ul_tcclks;
	uint32_t ul_sysclk = sysclk_get_cpu_hz();

	/* Configure PMC */
	pmc_enable_periph_clk(ID_TC1_1);

	/** Configure TC for a 8Hz frequency and trigger on RC compare. */
	tc_find_mck_divisor(8, ul_sysclk, &ul_div, &ul_tcclks, ul_sysclk);
	tc_init(TC1, 1, ul_tcclks | TC_CMR_CPCTRG);
	tc_write_rc(TC1, 1, (ul_sysclk / ul_div) / 8);

	/* Configure and enable interrupt on RC compare */
	NVIC_EnableIRQ((IRQn_Type) ID_TC1_1);
	tc_enable_interrupt(TC1, 1, TC_IER_CPCS);

	tc_start(TC1, 1);
}

I could see usage of

ID_TC1_1

and

TC1_1_Handler

 

Now moving on to my code, as per my observation,

in header file "same70q21.h" i could see timer declarations like TC0_Handler(). TC1_Handler(), ......., TC11_Handler()

Here I couldn't see any channel wise classifications.

 

Again, the issue could be observed on the peripheral interrupt ID.

in header file "same70q21.h" i could see timer ID definitions like ID_TC0. ID_TC1, ......., ID_TC11

Here too, I couldn't see any channel wise classifications.

 

Let me make a wild guess.
devil

I'll be back after doing some experiments on my board.

 

Truly speaking, ASF is really freaking me out.

sad

Silly beans are always silly
:)

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

Attaching the same70q21.h header file for reference.

smiley

Attachment(s): 

Silly beans are always silly
:)

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

Finally got things working.

like jstampfl said.

 

If I need to use TC1, channel 0, then peripheral ID & interrupt handler should be used for TC3.

 

Here is a working sample.

 

void TC3_Handler(void)
{
volatile uint32_t ul_dummy;

/* Clear status bit to acknowledge interrupt */
ul_dummy = tc_get_status(TC1, 0);

/* Avoid compiler warning */
UNUSED(ul_dummy);

ioport_toggle_pin_level(LED0_GPIO);
}

static void configure_tc(void)
{
uint32_t ul_div;
uint32_t ul_tcclks;
uint32_t ul_sysclk = sysclk_get_cpu_hz();

/* Configure PMC */
pmc_enable_periph_clk(ID_TC3);

/** Configure TC for a 4Hz frequency and trigger on RC compare. */
tc_find_mck_divisor(4, 150000000, &ul_div, &ul_tcclks, 150000000);
tc_init(TC1, 0, ul_tcclks | TC_CMR_CPCTRG);
tc_write_rc(TC1, 0, (150000000 / ul_div) / 4);

/* Configure and enable interrupt on RC compare */
NVIC_EnableIRQ((IRQn_Type) ID_TC3);
tc_enable_interrupt(TC1, 0, TC_IER_CPCS);

tc_start(TC1, 0);

}

Thank you guys for the support.

I also Thank the Atmel Support guys for helping me get this issue resolved.

 

IF anybody knows how to interface USB host in SAM E70, please respond to this link.

https://community.atmel.com/forum...

Silly beans are always silly
:)