Timer on Hydra RLP

Hi.

I need to implement sleep(int µs) function with precision of microseconds (±2µs). Busy wait is good enough for me, so while() loop ready some clock would be fine.
First I thought of Slow Clock but it’s only 32 kHz so it’s too slow for required precision.
Now I understand that the CPU have 12 MHz clock (Main Clock) but I couldn’t understand how to set timer connected to this clock and how to read it.

Anyone have any ideas? How can I set main clock or implement sleep with such precision in some other way?

Thanks!

P.S. Please note that I’m talking about RLP mode.

Just to be sure, you will use the timer within your RLP code not C#? Otherwise it will not work as calling the RLP method will take more time.

Like

C#:
{
MyRLPMethod.Invoke(…);
}

c:
MyRLP Method(…)
{
Do something
Delayus();
Do something else

return;
}
Delayus()
{
}

or in other words, what exactly are you trying to accomplish at the end?

Yes, I’m using the timer within the RLP code.

I’m (almost) not using C# in my program. All the code is in RLP (lite). So the clock would be fine.
At this point I’m using some for() in order to be “stuck” for some time, but it’s precision is very bad.
I’m sure there’s some more elegant way to do it :slight_smile:

Ok good that would work. Did you look at the timer code on Hydra’s firmware. You can almost just copy/paste and you will be good to go.

Hmm… amazing idea :smiley: But I would never get to it myself. I’ll try.

Thanks!

AT91_TIMER.CPP is the right place to read?

Yes I think

@ Stargazer - Sometime ago I provided a RLPLite implementation of the SignalGenerator on the Hydra. That code makes extensive use of the AT91 timers. Since that is already RLPLite that might help.

https://www.ghielectronics.com/community/codeshare/entry/638

Specifically take a look at the RLP1.c file in the Native folder.

OK, I think I get it to work.

My clock init looks like this:


void clockInit(void)
{
	// Enable timer 1 & 2 peripheral clock
  AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC2);
  
  // Disable the timer and the interrupts
  AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKDIS;
  AT91C_BASE_TC2->TC_IDR = 0xffffffff;
  
  // Clear the interrupt status bit
  (void)AT91C_BASE_TC2->TC_SR;
  
  // Set timer divider 
  AT91C_BASE_TC2->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK;
  
  // Enable and reset the timer
  AT91C_BASE_TC2->TC_CCR = (AT91C_TC_CLKEN | AT91C_TC_SWTRG);
}

And then the sleep like this:


 #define MAX_CLK 13000
void sleep(UINT32 sleepTicks)
{
	UINT16 targetClock;
	UINT32 i = 20;
	
	if(sleepTicks < 4)
	{
		i = sleepTicks;
		for(; i > 0; i--){}
		return;
	}
	
	//Reset timer
	AT91C_BASE_TC2->TC_CCR = (AT91C_TC_SWTRG);

	while(sleepTicks > (MAX_CLK+3))
	{
		//set delay interval
		//5 timer ticks = 100ns
		//10 timer ticks deduced to compensate for context switch
		targetClock = ((AT91C_BASE_TC2->TC_CV) + (MAX_CLK * 5) - i);
		
		i = 10;
		
		//empty loop (busy wait) untill timer expires (reaches target timer)
		do{}while(targetClock > AT91C_BASE_TC2->TC_CV);
		
		sleepTicks -= MAX_CLK;
			
		//Reset timer
		AT91C_BASE_TC2->TC_CCR = (AT91C_TC_SWTRG);
	}
	
	targetClock = ((AT91C_BASE_TC2->TC_CV) + (sleepTicks*5) - 20);
	
	//empty loop (busy wait) untill timer expires (reaches target timer)
	do{}while(targetClock > AT91C_BASE_TC2->TC_CV);
}

Working pretty well. For TICK input < 5 it’s not that accurate, but higher I got good slepp accurasy (±10ns).

Few questions:

  1. I saw that if I’m using AT91C_BASE_TC0, the code wouldn’t return to managed code. Any ideas why?
  2. Is it possible to init two different clocks (like TC1 and TC2) with different dividers? For some reason it didn’t work well for me, the second clock wouldn’t work as expected (looks like didn’t reset on AT91C_TC_SWTRG).

THANKS FOR THE HELP!

@ Stargazer - TImer 0 on the AT91 is used by NETMF so if you fiddle with that then the system is likely to go into an indeterminate state. As for using 2 timers at the same time, there should not be an issue, but I have not looked at the firmware for the AT91 for a very long time, but I am almost certain only timer 0 was used by netmf. As soon as I get a gap I will check the firmware.