Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++

Interval Timer Problem

Altera_Forum
Honored Contributor II
2,786 Views

Hi, 

 

I got a system with an interval timer. Now I want to use it to to count how long the time is between two positiv flanks. But the counter won't start. 

My code: 

 

int count_timeH=0; int count_timeL=0; IOWR_ALTERA_AVALON_TIMER_PERIODH(SYS_CLK_TIMER_BASE,0x0); IOWR_ALTERA_AVALON_TIMER_PERIODL(SYS_CLK_TIMER_BASE,0x0); //start the counter IOWR_ALTERA_AVALON_TIMER_CONTROL(SYS_CLK_TIMER_BASE,0x04); printf("Control : %x\n",IORD_ALTERA_AVALON_TIMER_CONTROL(SYS_CLK_TIMER_BASE)); printf("Status: %x\n", IORD_ALTERA_AVALON_TIMER_STATUS(SYS_CLK_TIMER_BASE)); count_timeL= IORD_ALTERA_AVALON_TIMER_SNAPL(SYS_CLK_TIMER_BASE); printf("SnapL : %d\n", count_timeL); count_timeH= IORD_ALTERA_AVALON_TIMER_SNAPH(SYS_CLK_TIMER_BASE); printf("SnapH : %d\n", count_timeH); //wait till the FAD gives back the right frequency int j; for ( j = 0; j < 2; ++j) { push_The_Button(FAD_CLOCK_BASE); printf("Flanke Nummer %d \n", j); } //stop the counter IOWR_ALTERA_AVALON_TIMER_CONTROL(SYS_CLK_TIMER_BASE,0x08); printf("Status: %x\n", IORD_ALTERA_AVALON_TIMER_STATUS(SYS_CLK_TIMER_BASE)); count_timeL= IORD_ALTERA_AVALON_TIMER_SNAPL(SYS_CLK_TIMER_BASE); printf("SnapL : %d\n", count_timeL); count_timeH= IORD_ALTERA_AVALON_TIMER_SNAPH(SYS_CLK_TIMER_BASE); printf("SnapH : %d\n", count_timeH);And the registers contents are: 

 

Control : 0 Status: 1 SnapL : 9216 SnapH : 3286019 Knopf drücken! Flanke Nummer 0 Knopf drücken! Flanke Nummer 1 Status: 0 SnapL : 9216 SnapH : 3154947So how you can see in the code I just start counting but the control register still is "0". Why the content doesn't cange? 

And from which registers I can read my countsize? 

 

Thanks in advance for your help!
0 Kudos
13 Replies
Altera_Forum
Honored Contributor II
965 Views

First of all you write 0 to period registers. This means setting the timer to one clock period, which makes no sense. Did you instantiate a fixed period timer or full featured? 

 

Secondly, the correct procedure for getting actual timer count is writing to one of the snap register: the write data is ignored but the timer will latch the current 32bit value into snapshot registers. Then read the latched value. 

 

You always get 0 from the control register because start and stop bits are write only.
0 Kudos
Altera_Forum
Honored Contributor II
965 Views

Thanks for the help cris! 

I choosed the full featured. 

It works now. 

 

Regards!
0 Kudos
Altera_Forum
Honored Contributor II
965 Views

Hi, 

 

it works but now i recognized that the time doesn't fit to the value I astimated if I tested the time calculation. I adjusted ms for the time but my results are something like 60ms if I touch the bottun in 1 second twice. What is wrong? 

 

Thanks in advance!
0 Kudos
Altera_Forum
Honored Contributor II
965 Views

Although I'm not sure I understand what your problem exactly is, I advance two hypothesis: 

 

1. 

You must debounce the button contact which is possibly generating fake signal commutations. 

 

2. 

The measured interval is longer than the timer period, then the timer overflows and you get a shorter estimated time. 

What's your system frequency and what's the timer period? 

If you want to use the timer only in this free running way, you should program the period to the highest value, namely 0xffff ffff
0 Kudos
Altera_Forum
Honored Contributor II
965 Views

My system frequency is 50MHz and I always start the counter with 0xffff ffff. I think is not important for me to debounce the button because I want to simulate a time mesurement. Later I will get the signal from an external uC.  

IF I read the snapL/snapH regs and do: 

 

 

--- Quote Start ---  

zwischen_speicher_vorher = IORD_ALTERA_AVALON_TIMER_SNAPH(SYS_CLK_TIMER_BASE)<<16; 

zwischen_speicher_vorher |=IORD_ALTERA_AVALON_TIMER_SNAPL(SYS_CLK_TIMER_BASE); 

--- Quote End ---  

then I should get the time of the following calculation: 

0xffff ffff - 0xf99cc997  

for example. But the solution is too big to be a time in "ms" because the number is something about "1.082139e+08 (ms)". I speak always about "ms" because I adjust it in QSYS for the interval timer.  

Now my questions are: 

1."Is the time interval different from the adjusted time interval?" 

2."Is the calculated number just the count width and not the time? "
0 Kudos
Altera_Forum
Honored Contributor II
965 Views

I think I have found a solution: 

 

--- Quote Start ---  

 

double count_timeH_before=0; 

double count_timeL_before=0; 

double count_timeH_after=0; 

double count_timeL_after=0; 

double total_time_steps=0; 

double calculated_frequency=0; 

alt_u32 count_step_before=0x0; 

alt_u32 count_step_after=0x0; 

 

//start address of the counter 

IOWR_ALTERA_AVALON_TIMER_PERIODH(SYS_CLK_TIMER_BASE,0xFFFF); 

IOWR_ALTERA_AVALON_TIMER_PERIODL(SYS_CLK_TIMER_BASE,0xFFFF); 

 

IOWR_ALTERA_AVALON_TIMER_CONTROL(SYS_CLK_TIMER_BASE,ALTERA_AVALON_TIMER_CONTROL_STOP_MSK); 

 

//total_time is in seconds but is measured in ms 

//the range depends on the frequency you want to have 

//while((total_time<=10) & (total_time>=5)){ //while((total_time<=0.001) & (total_time>=0.00065)){ 

 

//by writing to the snapregister you get the data from the counter 

IOWR_ALTERA_AVALON_TIMER_SNAPL(SYS_CLK_TIMER_BASE,0x1); 

IOWR_ALTERA_AVALON_TIMER_SNAPH(SYS_CLK_TIMER_BASE,0x2); 

 

//start the counter 

IOWR_ALTERA_AVALON_TIMER_CONTROL(SYS_CLK_TIMER_BASE,0x06); 

printf("Control : %x\n",IORD_ALTERA_AVALON_TIMER_CONTROL(SYS_CLK_TIMER_BASE)); 

printf("Status: %x\n", IORD_ALTERA_AVALON_TIMER_STATUS(SYS_CLK_TIMER_BASE)); 

count_timeL_before= IORD_ALTERA_AVALON_TIMER_SNAPL(SYS_CLK_TIMER_BASE); 

printf("SnapL : %e\n", count_timeL_before); 

count_timeH_before= IORD_ALTERA_AVALON_TIMER_SNAPH(SYS_CLK_TIMER_BASE); 

printf("SnapH : %e\n", count_timeH_before); 

count_step_before = IORD_ALTERA_AVALON_TIMER_SNAPH(SYS_CLK_TIMER_BASE)<<16; 

count_step_before |=IORD_ALTERA_AVALON_TIMER_SNAPL(SYS_CLK_TIMER_BASE); 

 

//wait till the FAD gives back the right frequency 

int j; 

for ( j = 0; j < 2; ++j) { 

push_The_Button(FAD_CLOCK_BASE); 

printf("Flanke Nummer %d \n", j); 

 

 

//printf("SnapH : %e\n", (double)IORD_ALTERA_AVALON_TIMER_SNAPH(SYS_CLK_TIMER_BASE)); 

//stop the counter 

IOWR_ALTERA_AVALON_TIMER_CONTROL(SYS_CLK_TIMER_BASE,0x8); 

 

//by writing to the snapregister you get the data from the counter 

IOWR_ALTERA_AVALON_TIMER_SNAPL(SYS_CLK_TIMER_BASE,0x1); 

 

count_timeL_after= IORD_ALTERA_AVALON_TIMER_SNAPL(SYS_CLK_TIMER_BASE); 

printf("SnapL : %x\n", IORD_ALTERA_AVALON_TIMER_SNAPL(SYS_CLK_TIMER_BASE)); 

count_timeH_after= IORD_ALTERA_AVALON_TIMER_SNAPH(SYS_CLK_TIMER_BASE); 

printf("SnapH : %x\n", IORD_ALTERA_AVALON_TIMER_SNAPH(SYS_CLK_TIMER_BASE)); 

 

count_step_after = IORD_ALTERA_AVALON_TIMER_SNAPH(SYS_CLK_TIMER_BASE)<<16; 

count_step_after =count_step_after|(IORD_ALTERA_AVALON_TIMER_SNAPL(SYS_CLK_TIMER_BASE)); 

 

total_time_steps= (count_step_before-count_step_after); 

printf("Zwischenergebnis:%e\n", total_time_steps); 

calculated_time= total_time_steps/(50000000); 

printf("Calculated_time: %e\n",calculated_time); 

calculated_frequency=1/calculated_time; 

printf("Frequenz: %e\n",calculated_frequency); 

--- Quote End ---  

This should be right. Isn't it?
0 Kudos
Altera_Forum
Honored Contributor II
965 Views

The timer always count the cycles of system clock, so you must divide the count by 50000 in order to convert in ms for a 50MHz clock.

0 Kudos
Altera_Forum
Honored Contributor II
965 Views

IIRC that timer 'device' is horrid to use! It is really a 16bit peripheral so access to all the 32bit registers become painful and require multiple cycles. 

 

I got our hw guys to add two 32bit up counters, one counts 'SYS_CLK', the other microseconds (divided down from SYS_CLK). These can be read in (about) 2 cycles and the differences used for timing intervals.
0 Kudos
Altera_Forum
Honored Contributor II
965 Views

Hi Cris, 

 

I changed my properties from the Interval Timer. I choose the Timeout period to "us" instead of "ms" and now my core doesn't work any more. If I change it back it works again.  

I changed it to "us" because I need to astimate a frequency over an "PIO" which is round about 1.2KHz. I tried it with the "ms" Timeout period and the messurement of the frequency was not right and also the result was randome. That means that the frequency which was measured was from 700MHZ to 1.14kHz and not the 1.2kHz. 

Do I need to change other setting to if I changed the Timeout period of the interval timer? 

 

Thanks in advance for the help!
0 Kudos
Altera_Forum
Honored Contributor II
965 Views

Do you use that timer only as a cycle counter or do you use it as the system timer for an OS or for any interrupt? 

As I said in a previous post, the interval timer always counts the cycles of the system clock: if you reduce the timeout period you DON'T improve timer resolution; on the contrary, you shorten the measurable time, since it resets to zero in a shorter time. 

If you use the code you posted above, you rather need a very long timeout period, greater than the maximum interval you are supposed to measure.
0 Kudos
Altera_Forum
Honored Contributor II
965 Views

Hi cris, 

 

I'm using it as a cycle counter.  

So I need to change the timeout period to 1sec instead of 1 msec if I want to measure a time round about 0.0008 sec. I also want to measure it exactly as possible. 

 

Thanks is advance for your answer!
0 Kudos
Altera_Forum
Honored Contributor II
965 Views

 

--- Quote Start ---  

 

I'm using it as a cycle counter.  

So I need to change the timeout period to 1sec instead of 1 msec if I want to measure a time round about 0.0008 sec.  

 

--- Quote End ---  

 

You definitely need a timeout period larger than the measured time. 

As I said above, if your timer is dedicated to the measuring task and doesn't serve other functions or peripherals, you can operate it freely. 

So, I suggest this: 

- set timeout period larger than the maximum expected interval to be measured 

- timer initialized in stopped status 

- reset and start the timer when you start your measure,  

- stop the timer at the end of measure 

- read the duration 

 

 

--- Quote Start ---  

 

I also want to measure it exactly as possible. 

 

--- Quote End ---  

 

This greatly depends on your application, namely how you perform the measurement: 

- poll a PIO or any other condition and start/stop/read the timer: poor precision, dependent from your polling rate, unless you can afford using the 100% of cpu time for the polling loop and don't execute any other task  

- use a irq triggered by start/stop conditions: common solution for greater system effinciency and good precision in the us range 

- use a hardware counter solution which automatically identifies start/end conditions and places the measurement in a register which you can read without effort: maximum precision at the expense of a slight increment in hw complexity (fpga resource usage)
0 Kudos
Altera_Forum
Honored Contributor II
965 Views

Hi cris, 

 

thanks for the help, now it works! I just setup the timeout period to "1sec" and changed a little bit of my code: 

 

 

--- Quote Start ---  

double count_The_Frequency() 

 

double total_time_steps=0; 

double calculated_time=0; 

double calculated_frequency=0; 

alt_u32 count_step_1=0x0; 

alt_u32 count_step_2=0x0; 

 

int a=0; 

 

//start address of the counter 

IOWR_ALTERA_AVALON_TIMER_PERIODH(SYS_CLK_TIMER_BASE,0xFFFF); 

IOWR_ALTERA_AVALON_TIMER_PERIODL(SYS_CLK_TIMER_BASE,0xFFFF); 

 

IOWR_ALTERA_AVALON_TIMER_CONTROL(SYS_CLK_TIMER_BASE,ALTERA_AVALON_TIMER_CONTROL_STOP_MSK); 

 

//total_time is in seconds but is measured in ms 

//the range depends on the frequency you want to have 

//while((total_time<=10) & (total_time>=5)){ //while((total_time<=0.001) & (total_time>=0.00065)){ 

 

//by writing to the snapregister you get the data from the counter 

IOWR_ALTERA_AVALON_TIMER_SNAPL(SYS_CLK_TIMER_BASE,0x1); 

IOWR_ALTERA_AVALON_TIMER_SNAPH(SYS_CLK_TIMER_BASE,0x2); 

 

//start the counter 

IOWR_ALTERA_AVALON_TIMER_CONTROL(SYS_CLK_TIMER_BASE,0x06); 

//wait till the FAD gives back the right frequency 

int j; 

for ( j = 0; j < 2; ++j) { 

push_The_Button(FAD_CLOCK_BASE); 

a=a+1; 

IOWR_ALTERA_AVALON_TIMER_SNAPL(SYS_CLK_TIMER_BASE,0x1); 

if(a==1){ 

count_step_1 = IORD_ALTERA_AVALON_TIMER_SNAPH(SYS_CLK_TIMER_BASE)<<16; 

count_step_1 =count_step_1|(IORD_ALTERA_AVALON_TIMER_SNAPL(SYS_CLK_TIMER_BASE)); 

if(a==2){ 

count_step_2 = IORD_ALTERA_AVALON_TIMER_SNAPH(SYS_CLK_TIMER_BASE)<<16; 

count_step_2 =count_step_2|(IORD_ALTERA_AVALON_TIMER_SNAPL(SYS_CLK_TIMER_BASE)); 

 

 

//printf("SnapH : %e\n", (double)IORD_ALTERA_AVALON_TIMER_SNAPH(SYS_CLK_TIMER_BASE)); 

//stop the counter 

IOWR_ALTERA_AVALON_TIMER_CONTROL(SYS_CLK_TIMER_BASE,0x8); 

 

//printf("1; %x\n", count_step_1); 

// printf("2: %x \n", count_step_2); 

 

total_time_steps= (count_step_1-count_step_2); 

 

calculated_time= total_time_steps/(50000000); 

 

calculated_frequency=1/calculated_time; 

 

// printf("Frequenz: %e\n", calculated_frequency); 

 

return calculated_frequency; 

--- Quote End ---  

0 Kudos
Reply