View previous topic :: View next topic |
Author |
Message |
m_embedded
Joined: 10 Oct 2012 Posts: 18
|
Writing optimized interrupt programing? |
Posted: Thu Nov 01, 2012 5:33 am |
|
|
Hi all,
I'm just trying to do three tasks, which should be activated in different time schedules, for example:
task 0 - should be activated every 1 seconds
task 1 - should be activated every 2 seconds
task 3 - should be activated every 15 seconds
I have tried some thing like this
Code: |
timer isr
{
disable Timer Inter;
if(1secCnt<=1)
1secCnt++;
if(2secCnt<=2)
2secCnt++;
if(15secCnt<=14)
15secCnt++;
enable Timer Inter;
}
and in while
while(1)
{
if(1secCnt>=1)
{
task0
1secCnt=0;
}
if(2secCnt>=2)
{
task1
2secCnt=0;
}
if(15secCnt>=14)
{
task2
15secCnt=0;
}
}
|
By using this method I could not be able to achieve the time constrain that i have specified.
I need some experts help to achieve this thing, so anybody can help me to make this thing happen... |
|
|
Lemosek
Joined: 15 Oct 2011 Posts: 36
|
|
Posted: Thu Nov 01, 2012 7:15 am |
|
|
Hello,
You must use software timers like :
Code: |
#INT_TIMER1
void t1_interrupt(void){
int16 x;
x=Timer1;
if(x) Timer1 = --x;
x=Timer2;
if(x) Timer2 = --x;
if(++ms10_cnt>99){
ms10_cnt=0;
if(++s1_cnt>59)s1_cnt=0;
}
set_timer1(6250);
} |
Next in main:
Code: |
SETUP_TIMER_1(T1_INTERNAL||T1_DIV_BY_8); //tick 1,6us
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
set_timer1(6250); //interrupt 10ms
while(1)
{
if(s1!=s1_cnt) {
//callback task 1
if(!(s1_cnt%2)){
//callback task 2
}
if(!(s1_cnt%15)){
//callback task 3
}
s1=s1_cnt;
}
}
|
This code will be working only if you write Your task function not blocking (don't use delay_ms function) for delay You can use software timers (like Timer1).
Best regards
R.L. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19544
|
|
Posted: Thu Nov 01, 2012 10:00 am |
|
|
Could also be done with the RTOS. With the same limitation.
I'd guess the fundamental problem is that the tasks _are_ blocking.
If so, then you need to rethink the tasks. Each needs to exit ASAP, and possibly use a state machine to control what it does. Then sequence through it's jobs while still allowing the loop to keep executing.
This is the key bit of writing multitasking applications on a single threaded/cored processor.....
Best Wishes |
|
|
m_embedded
Joined: 10 Oct 2012 Posts: 18
|
|
Posted: Thu Nov 01, 2012 10:02 pm |
|
|
Ttelmah wrote: | Could also be done with the RTOS. With the same limitation.
I'd guess the fundamental problem is that the tasks _are_ blocking.
If so, then you need to rethink the tasks. Each needs to exit ASAP, and possibly use a state machine to control what it does. Then sequence through it's jobs while still allowing the loop to keep executing.
This is the key bit of writing multitasking applications on a single threaded/cored processor.....
Best Wishes |
Can you give me few hints to implement this. (need to rethink the tasks. Each needs to exit ASAP, and possibly use a state machine to control what it does. Then sequence through it's jobs while still allowing the loop to keep executing). |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Fri Nov 02, 2012 3:07 am |
|
|
How much jitter can you afford to have on the timings for each task?
Mike
EDIT
Suppose you broke each one second period into say ten time slots. 0-99ms, 100-199ms etc.
Only allow:-
Task0 to execute during the 0-99ms slot.
Task1 during 100-199ms etc.
Provided that each task took less than 100ms, they would not compete for time with the others, and could operate within ms of the required intervals. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19544
|
|
Posted: Fri Nov 02, 2012 4:42 am |
|
|
As a sort of 'non complete imaginary example of how to do events at intervals', try looking at the following:
Code: |
int16 ticks=1;
#INT_TIMERx
void ticker(void) {
//program up a timer to call this at perhaps 100* per second
ticks++;
}
#define LED1 PIN_B0
#define LED2 PIN_B1
void main(void) {
enum {idle,operation_1, operation_2,wait} doing=idle;
//initialise hardware etc. here.
//including timer and interrupts
do {
switch (doing) {
state idle:
if (ticke<100) break;
state++;
break;
state operation_1:
//Here we have reached one second
output_high(LED1);
if (ticks<200) break;
state++;
break;
state operation_2:
//Two seconds
output_high(LED2);
if (ticks<400) break;
state++;
break;
state wait:
output_low(LED1);
output_low(LED2);
if (ticks<15000) break;
ticks=1;
state=idle;
break;
}
} while (TRUE);
}
|
Now, this waits 1 second, then turns on LED1. Waits another second, then turns on LED2, then waits two more seconds, and turns both LED's off, then waits 11 seconds, and starts again.
Each job is short, just changing what has to change at the time. If you want something done an interval later, then is done by watching for the count reaching the next value. If you need (for instance) to do a whole sequence of operations at intervals, these can just be new states. If the individual states are quick, then the loop is executing quickly, and the states don't interfere with one anther.
Best Wishes |
|
|
|