Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[General] Problem with multithreading

Status
Not open for further replies.

kunal5959

Junior Member level 3
Joined
Jul 26, 2011
Messages
31
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Activity points
1,644
I wanted to implement a simple multithreading code on my ATMEGA128A prtototype board where 4 different tasks would be regulated in a time window such that each thread/ task occors only for a defined period. The task is to set the PORTB6 in one thread and then clear in second and the set and clear again in next threads. Now i am using AVR studio and C language..

I actually used two different programs one introducing delay(_delay_ms(2)) in thread/TASK 1 and other without delay in THread/TASK 1.

i do not understand why the setting of the LED to On or off differs when I use delay_ms(2) as shown in the code.i expected that the 2 ms delay_ms in the code would be ignored while the timer has to run the thread 1 only for 1.4 ms.

Since OCR is set to 1 TIMER0 interrupt is called every 139 us~140us.. I am using a timer counter in my code such that each thread is called at 10x140us,,20X140us,,30X140us,,40X140us...

The (1) Oscilloscope Pic shows the toggling without delay and
The (2) Oscill pic shows toggling without a delay.. pic with (1.4,2.8,4.2,5.6)as measured time diff

(1) is the ideal case as it satisfies Toggle duration of (Thread 1->1.4 ms,Thread 2->2.8ms,Thread 3->4.2ms&Thread 4->5.6ms) accordin to my calculation..
(2) (Thread 1->2.8 ms,Thread 2->1.4ms,Thread 3->4.2ms&Thread 4->5.6ms) this is absurd bcos i expected that the 2 ms delay_ms in the code would be ignored while the timer has to run the thread 1 only for 1.4 ms..??

can anyone help me in understand how the interrupt handles the threads in the second case????


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <stdio.h>
#include <util/delaynew.h>
 
/* function declaration */
unsigned long int frequencygenerator(unsigned long int a);
# define F_CPU 1830000UL
 
volatile int thread=4,s,t=10;
int main (void)
{   
  s=0;
   DDRA=0xFF;
   DDRE=0xFF;
   DDRB =0xFF; // Set LED as output
 
   
 /**** this timer initialisation of TIMER0 is uused to activate the Timer counters that will be used for TIMING SYNC in main programm**/         
   TIMSK|=(1<<OCIE0);//
   OCR0   = 1;
   TCCR0|=(1<<CS00)|(1<<CS02)|(1<<WGM01)|(1<<COM00);//////CTC mode Prescaler set to 128 so that  every 139 us timer0 interrupt is called.
 
   
 
sei();
   while(1){  
       
       
       // THREAD 1 ===========================================
    if(thread == 1){
  PORTB|=(1<<PORTB6);
   _delay_ms(2);  // this delay is used in only 2nd case...1st case is without delay instruction.
          }
     // THREAD 2 ===========================================
    if (thread == 2){
  PORTB&=~(1<<PORTB6);
  
   
             }
      if (thread == 3){
  PORTB|=(1<<PORTB6);
             }
        if (thread == 4){
  PORTB&=~(1<<PORTB6);
             }
             
   }
}
ISR(TIMER0_COMP_vect)
{
            s=s+1;//// each +1 counter adds 139 us to the OCR counter
 
    if(s==t)  {
      
      if (thread==4){
            thread=1;
            t=10; ////// t=10 implies 10 * 139 us is waiting time 
      }else if (thread==1){
          
          thread=2;
          t=20;       ////// t=20 implies 20 * 139 us is waiting time 
      }else if(thread==2) {  
             thread =3;
             t=30;}  ////// t=30 implies 30 * 139 us is waiting time 
       else {thread=4;
             t=40;}    ////// t=40 implies 40 * 139 us is waiting time 
       
      s=0;
      }
}


 
Last edited:

i expected that the 2 ms delay_ms in the code would be ignored while the timer has to run the thread 1 only for 1.4 ms.
The opposite is true. Your interrupt controlled "thread" semaphore is ignored as long as delay_ms() is executed.

The lessest you must do is to return to the scheduler when executing a delay. Means you need a multitasking-aware delay function and a different scheme to switch between threads.
 

Actually my main aim was to write a code where i can control 4 threads such that each thread has a timeout.. After a defined amount of time the a TIMING handler skips to another thread even if the thread takes more time than the defined one.

I thought timer interrupt are the only solution....Can you suggest how to TIMEOUT different threads in the main loop??
 

I presume you won't implement true context switching, so you need to give execution periodically back to the scheduler.
 

Thanks for the information FvM. i will read more articles on Task scheduling. It seems a major use of Task scheduling in implementing RTOS.. I hope i get some idea how to implement my idea there...Thanks again.
 

Hello!

I'm not familiar with the avr environment and therefore I don't know what _delay_ms does.
I mean, I know it's a delay, but how does it delay? Does it simply eat CPU cycles?

I'm doing all my programs multithreaded, and in the latest I have in the pipeline, there are
20+ possible threads.

The embedded world is really a world of clock saving. So in case your delay function simply
eats cycles, rewrite it. Here is how to do with a simple example. Suppose you have some 1 ms
"tick" that calls a periodical process. If your 2ms cycles eater is in this time slot, you will loose
the next tick, and possibly a third one. What you should do is as follows. We will suppose that
you have a timeout variable:

Code C - [expand]
1
2
3
4
5
6
7
8
9
last_function_before_timeout();
    if(timeout > 0) {
        timeout--;
        return;
    }
    else {
        timeout = 2; // Will delay the next function of 2 ms
    }
    first_function after timeout();



As you can see, when your timeout is needed, you simply set a variable, which takes a few
clock cycles only instead of 40 000 cycles in case your processor works at 20 MHz.

FvM mentioned context switching. Indeed, saving the context and restoring the next takes a lot
of clock cycles. So the best is just to avoid context saving.
If you have a thread that needs to be in real-time (e.g. audio sampling) then promote it to master
thread. All the process will run around and you should ensure that any function you write
fits into a single time slot or at least can be split.
If you follow these 2 rules (never eat cycles idling, fit all functions in a single time slot):
- Your code will be simpler, cleaner with less "what if"s
- Your real-time characteristics will be guaranteed whatever happens.
- As your data thread is master, you will never loose a single sample.

Dora.
 

These days, freeRTOS is becoming a quasi standard for multi-tasking on small embedded systems below the full featured OS (e.g. linux) level. Ports for AVR are included in the recent version. https://www.freertos.org/index.html

Reviewing the task concept of freeRTOS should be at least instructive for your own work.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top