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,069 Views

Hello.  

I’ve got a problem with simple interrupt from interval timer in uC/OS-II 

 

System frequency is 75Mhz. There are PIO and timer. It makes strobe. Duration 10 ms. Here it is: 

// global variablesint err; // handler static void handle_timer(void* context) { IOWR_ALTERA_AVALON_TIMER_CONTROL(timer_base, ALTERA_AVALON_TIMER_CONTROL_STOP_MSK); //disable interrupt IOWR_ALTERA_AVALON_TIMER_STATUS(timer_base, 0); //clear flag IOWR_ALTERA_AVALON_PIO_DATA(PIO_BASE, 1); timer_exit(); err = 1; return; } // set handler void timer_init(alt_u32 _base, alt_u32 _interrupt, alt_u32 _irq) { timer_base = _base; timer_interrupt = _interrupt; timer_irq = _irq; alt_ic_irq_disable (timer_interrupt, timer_irq);//disable interrupt alt_ic_isr_register(timer_interrupt, timer_irq, handle_timer, NULL, NULL); break; return; } // reset / set timeout void timer_set_period(alt_u32 timer_period) { timer_period = HIGHT_RES_TIMER_LOAD_VALUE * timer_period; IOWR_ALTERA_AVALON_TIMER_PERIODL(timer_base, timer_period&ALTERA_AVALON_TIMER_PERIODL_MSK); //write timer period l IOWR_ALTERA_AVALON_TIMER_PERIODH(timer_base, (timer_period>>16)&ALTERA_AVALON_TIMER_PERIODH_MSK); //write timer period h return; } // start counting void timer_start(void) { IOWR_ALTERA_AVALON_TIMER_CONTROL(timer_base, ALTERA_AVALON_TIMER_CONTROL_STOP_MSK); //stop timer, disable interrupt IOWR_ALTERA_AVALON_TIMER_STATUS(timer_base, 0); //clear flag IOWR_ALTERA_AVALON_TIMER_CONTROL(timer_base, ( ALTERA_AVALON_TIMER_CONTROL_ITO_MSK | ALTERA_AVALON_TIMER_CONTROL_START_MSK)); //start timer, enable interrupt return; } // pause counting void timer_stop(void) { IOWR_ALTERA_AVALON_TIMER_CONTROL(timer_base, ALTERA_AVALON_TIMER_CONTROL_STOP_MSK); //stop timer, disable interrupt IOWR_ALTERA_AVALON_TIMER_STATUS(timer_base, 0); //clear flag return; } // timer deactivation void timer_exit(void) { IOWR_ALTERA_AVALON_TIMER_CONTROL(timer_base, ALTERA_AVALON_TIMER_CONTROL_STOP_MSK); //stop timer, disable interrupt IOWR_ALTERA_AVALON_TIMER_STATUS(timer_base, 0); //clear flag alt_ic_irq_disable (timer_interrupt, timer_irq);//disable interrupt return; } // timer usage int foo(void) { int nop; err = 0; /*A*/ IOWR_ALTERA_AVALON_PIO_DATA(PIO_BASE, 0); //set PIO /*B*/ timer_init(HIGHT_RES_TIMER_BASE, HIGHT_RES_TIMER_IRQ_INTERRUPT_CONTROLLER_ID, HIGHT_RES_TIMER_IRQ); /*C*/ timer_set_period(10); /*D*/ timer_start(); while(err == 0) {nop=0;} //waiting for timer timer_exit(); return 1; }  

 

Timer’s description from system.h /* * hight_res_timer configuration * */# define ALT_MODULE_CLASS_hight_res_timer altera_avalon_timer# define HIGHT_RES_TIMER_ALWAYS_RUN 0# define HIGHT_RES_TIMER_BASE 0x1003520# define HIGHT_RES_TIMER_COUNTER_SIZE 32# define HIGHT_RES_TIMER_FIXED_PERIOD 0# define HIGHT_RES_TIMER_FREQ 75000000u# define HIGHT_RES_TIMER_IRQ 1# define HIGHT_RES_TIMER_IRQ_INTERRUPT_CONTROLLER_ID 0# define HIGHT_RES_TIMER_LOAD_VALUE 74ull# define HIGHT_RES_TIMER_MULT 1.0E-6# define HIGHT_RES_TIMER_NAME "/dev/hight_res_timer"# define HIGHT_RES_TIMER_PERIOD 1.0# define HIGHT_RES_TIMER_PERIOD_UNITS "us"# define HIGHT_RES_TIMER_RESET_OUTPUT 0# define HIGHT_RES_TIMER_SNAPSHOT 1# define HIGHT_RES_TIMER_SPAN 32# define HIGHT_RES_TIMER_TICKS_PER_SEC 1000000u# define HIGHT_RES_TIMER_TIMEOUT_PULSE_OUTPUT 0  

 

I debugged this code and it works perfectly. 

My project became more complicated and I had to use uC/OS-II. 

This part of code is very simple and has no changes but it works very strange. Duration of strobe became about 30 ms!  

 

After some manipulation with code I found out that functions of setting timer on are very slow.  

I put line A between lines C and D. It makes duration of strobe about 16 ms. 

 

why simple register’s writing become slow? what should i do to make it working faster?
0 Kudos
11 Replies
Altera_Forum
Honored Contributor II
895 Views

Hi, What do you want to see ? 

Are timer interruptions happening at equal period : to verify the accuracy. If this is the answer, you go to the wrong way. 

or how many time does Nios take to initialize the timer ?  

 

Your program starts and stops at the first timer interrupt. 

 

Maybe I misunderstood something.
0 Kudos
Altera_Forum
Honored Contributor II
895 Views

Ohh. I apologize for the confusing post. English is not my native language. 

 

I'd like to get strobe with a duration 10ms. And I got it without uC. Timer initialization takes about 250ns without uC. 

But when I use uC it takes about 20ms to initialize timer. 

I want to make it faster than 20ms. 

I also want to understand why it takes 20ms to write 7 registers.
0 Kudos
Altera_Forum
Honored Contributor II
895 Views

How do you measure the strobe ? You power up the board and start a chronometer until your "err=1" happens ? 

uC/OS has its own initialization that shall take time. 

 

Do you want your board to start very fast ? Why such a constraint. 

OR do you want your board to "produce" a regular strobe ? which is more usual. I think you want THIS. 

 

 

You code is hard to understand. 

static void handle_timer(void* context) { IOWR_ALTERA_AVALON_TIMER_CONTROL(timer_base, ALTERA_AVALON_TIMER_CONTROL_STOP_MSK); //disable interrupt IOWR_ALTERA_AVALON_TIMER_STATUS(timer_base, 0); //clear flag IOWR_ALTERA_AVALON_PIO_DATA(PIO_BASE, 1); // <----------------------This is THE stobe signal, I think timer_exit(); // <--------------------- ?????????? ----------------- you are in an interrupt routine, so it should be as short as possible and easy to read err = 1; return; }  

 

Your code doesn't do what you expect (I am 95% sure). I suggest to rewrite the code. 

Keep in mind the algorithm of what you expect. 

 

Regards
0 Kudos
Altera_Forum
Honored Contributor II
895 Views

I measure strobe with oscilloscope.  

 

I describe behavior of my code 

In main function (int foo(void)) I set strob signal in high level by  

IOWR_ALTERA_AVALON_PIO_DATA(PIO_BASE, 0); //set PIO 

(cause I has inverter on ouput pin). 

 

Then init timer to 10ms, and start it.  

Enter endless loop and wait for interrupt. I expect it takes 10ms to get interrupt. But it takes much longer because init functions work so slow in uC.  

In interrupt handler I deactivate srobe and timer. 

IOWR_ALTERA_AVALON_PIO_DATA(PIO_BASE, 1); 

timer_exit();  

That’s all.  

 

Time to exec  

timer_exit(); err=1; 

and following instructions doesn’t meters because I measure time between 

 

--- Quote Start ---  

IOWR_ALTERA_AVALON_PIO_DATA(PIO_BASE, 0); 

--- Quote End ---  

 

and  

 

--- Quote Start ---  

IOWR_ALTERA_AVALON_PIO_DATA(PIO_BASE, 1); 

--- Quote End ---  

0 Kudos
Altera_Forum
Honored Contributor II
895 Views

So, the question is : why writing to a register is so slooooooooooooooooow with uc/os ?  

Probably the scheduler, other interrupts... something linked to uC/OS. 

 

My questions : Do you really matters of the duration of writing to an interrupt register ? 

AS said before : do you want to verify the accuracy of the timer OR do you want to minimize time for the board to be initialized ?
0 Kudos
Altera_Forum
Honored Contributor II
895 Views

I am satisfied with the accuracy of the timer. It works perfect - proved experimentally. 

 

 

--- Quote Start ---  

... something linked to uC/OS. 

--- Quote End ---  

 

:) I got it. But there are no other interrupts with higher priority and no other treads(tasks) ...  

 

I want to be sure that delay of timer initialization functions is constant, so it can be considered when calculating the timeout (timer init value).  

 

I also want to minimize time to execute timer initialization functions, because it is longer than my strobe duration.
0 Kudos
Altera_Forum
Honored Contributor II
895 Views

So, you want your board to boot in less than 10 ms ?! or only the program ? 

 

I guess your board will be "hot inserted". High constraint you get. why such a constraint ? Maybe you have very good reason to hardly work on that. 

 

Please be aware that FPGA takes time to be configured with user logic and start running user program ? 

Written in Altera handbooks. 

 

Since your board has no routine that modify boot sequence (unlike Windows ;-)), and is deterministic, I think you can consider the boot time constant, but I would put high margin to be sure. 

To resume, You can't be sure that delay of timer initialization functions is constant because of bad luck, upset events, température, electromagnetic field, altitude, humidity............ 

 

"Starting the scheduler, reserve RAM space, checking configuration...." of uC/OS must be time consuming. 

 

Good luck
0 Kudos
Altera_Forum
Honored Contributor II
895 Views

I don't need board to boot in less than 10 ms. My board starts for a long time. And that is all right.  

 

I need to do something like this:https://www.alteraforum.com/forum/attachment.php?attachmentid=7682  

 

t1 - is first strobe with a duration 10ms, t2 - time to reinit and restart timer. 

To make stobe with duration 10ms I first init and start timer, and then set pioout1 up 

But I can't make t2=0, because  

 

void timer_start(void) { IOWR_ALTERA_AVALON_TIMER_CONTROL(timer_base, ALTERA_AVALON_TIMER_CONTROL_STOP_MSK); //stop timer, disable interrupt IOWR_ALTERA_AVALON_TIMER_STATUS(timer_base, 0); //clear flag IOWR_ALTERA_AVALON_TIMER_CONTROL(timer_base, ( ALTERA_AVALON_TIMER_CONTROL_ITO_MSK | ALTERA_AVALON_TIMER_CONTROL_START_MSK)); //start timer, enable interrupt return; } 

 

takes 6ms!  

I can set timer for 4ms it can help me get second strobe with 10ms duration, but it is dirty hack.  

 

maybe there is some optimization, and i should turn it on in bsp/hal configuration?
0 Kudos
Altera_Forum
Honored Contributor II
895 Views

1) 

If you want really hard real time, you can do this by using a counter with a pll on the clock. All in pure FPGA logic : no random external events (except upset events caused by radiations of course), very ultra deterministic, very easy to make... 

^^^ Very optimized !! :-) ultra low resources, quite robust, MTBF near MTBFof FPGA, ultra simple to design.... 

 

2) 

You can configure timer to produce interruptions at a fixed period : no need to stop and start by the software. 

 

Take the features of FPGA : programmable gate array. 

Else a computer (PC, MAC, rasberry...) would be sufficent ;-) 

 

 

3) optimisations of uc/OS : tedious work and may not be sufficient. 

 

(Mistake) 

 

--- Quote Start ---  

My board starts for a long time 

--- Quote End ---  

 

BUT your operating procedure show us that you measure the boot time + duration until first interruption. (Am I Right ?) 

You mismatch yourself OR I misunderstood/forgot something. 

I am very confused HERE NOW.
0 Kudos
Altera_Forum
Honored Contributor II
895 Views

I do not care about the boot time of my board, and the duration of the execution of other instructions. But at a certain moment NIOS' application must produce a series of strobes with various durations. But it does not produce them because timer init instructions get stuck in layers of HAL uC. I asked how to speed up their execution. And that’s all. 

 

It’s hard to realize this staff on FPGA logic because it works closely to other subprograms.  

I got that there is no any settings in bsp property to make writing to an interrupt register exec faster. 

I understand that I should work with timer like with pll. I should configure timer to produce interruptions at a fixed period, and count interruptions to produce strobes with longer duration. 

 

Thank you.
0 Kudos
Altera_Forum
Honored Contributor II
895 Views

To resume, you want to produce strobe with various durations. 

This strobe signal is on an OUTPUT FPGA pin (destination : other device) 

right ? 

 

If you want hard real time (I mean that durations are strictly constrained and if one time is missed then fatal error), I don't recommand using software interrupts, because of what you have seen. 

 

 

--- Quote Start ---  

It’s hard to realize this staff on FPGA logic because it works closely to other subprograms.  

--- Quote End ---  

 

To produce strobe at various duration is not hard. You can load the value to a external (but inside FPGA) counter which produce strobe. 

To load the value, just employ a PIO ins Qsys. 

 

 

could you describe more of your project ? could you give a basic algorithm and structure of this part of your project (moslty relation between strobe and (sub)program)? 

 

Not enough info to help you and still confusing.
0 Kudos
Reply