Code for multiprogram II

9 examples with code and digital analyzer images

digital pins

  • DI0 : high when dummy task is running

  • DI1 : high when task is running

  • DI2 : high when task2 is running (not all examples has a task2)

  • DI3: high when task is in critical region (not in alle examples)

  • DI4: high when task is in critical region (not in alle examples)

Src folder list: here

k01 - one periodic task

task runs in a loop:

  1. Eating 10 msec of CPU time

  2. Sleep for 30 ticks of 1 msec (set on k_init)

 

code for k1

You can oberserve that

  1. task(DIO 1) is running approx every 40 msec andd eating 10 msec of time.

    1. high indicates running

  2. When task is not active then dummytask (DIO 0) takes over

k02 Two tasks

In K02 both tasks (task(DIO 1) and task2( DIO 2) is

  1. both running an endless loop

  2. is active all time

  3. krnl has timer running at 1 msec (k_init)

  4. task and task2 has same priority so

    1. round robbing between them is every 1 msec

  5. and dummytask (DIO 0) will never run bq task and task2 will use all available time

 

code for k2

Observe

  1. dummytask(DIO 0) is never runnnig

  2. task and task2 (DIO 1 and DIO 2) is sharing CPU every 1 msec (round robbin)

k03 Two tasks, same priority, eat and sleep

Two tasks: task(DIO 1) and task2 (DIO 2)

  1. Endless loop where they

    1. Eat 10/3 msec of CPU time

    2. Sleep 30/20 msec

  2. Utilization of CPU is approx 1040 + 3/23 = 0.38

  3. Leaving 72% of time to dummtask (DIO 0)

 

code for k3

You may observe

  1. Endless loop where they

    1. Eat 10/3 msec of CPU time

    2. Sleep 30/20 msec

  2. Utilization of CPU is approx 1040 + 3/23 = 0.38

  3. Leaving 72% of time to dummtask (DIO 0)

  4. when task and task2 both wnat to use CPU they will round robbin every 1 msec bq they have same priority

    1. See that at approx -33 smec to -27msec or so - at the arrow

  5. A rough estimation of worst case duration for eating time for the tasks will be

    1. task 10msec+3msec=13msec (approx the situation on the figure) bq task2 will max runs one time during task eating time

    2. task2 duration is 3 msec and round robbin with task will prolong task will those 3 msec, and prolong task2 with 3 msec as well in this situation

k04 - as k03 but task has higher priority than task2

Two tasks: task(DIO 1) and task2 (DIO 2)

  1. Endless loop where they

    1. Eat 10/3 msec of CPU time

    2. Sleep 30/20 msec

  2. Utilization of CPU is approx 1040 + 3/23 = 0.38

  3. Leaving 72% of time to dummtask (DIO 0)

 

code for k4

You may observe

  1. Endless loop where they

    1. Eat 10/3 msec of CPU time

    2. Sleep 30/20 msec

  2. Utilization of CPU is approx 1040 + 3/23 = 0.38

  3. Leaving 72% of time to dummtask (DIO 0)

  4. when task and task2 both want to use CPU they will NOT do round robbin but task (DIO 1) will run to end bq task has higher priority than task2

  5. See at arrows where task becomes active and task2 is missing CPU and will get it after second arrow where task has eaten 10 msec of time

  6. So task will runs as alone in the world bq of highest priority in system and task2 will suffer and loosing CPU to task when requested even if task2 is active.

  7. So deadlines will vary for task2 but not for task.

  8. Worst case duration for task is teh duration for all loops and will be 3 msec

  9. Worstcase duration for task2 to execute 3 msec eating will be 3msec + 10msec. The 10 msec comning from waiting on CPU from task.

  10. A total different situation from k03.

INCLIMG

k05 Two tasks fighting for critical region

  1. Critical section implemented by a pair og k_wait and k_signal

  2. Pin 8 to 12 used for indication of who is running and which task is inside the region

    1. pin 8 (DIO 0) - Dummytask (task nr 0

    2. pin 9 (DIO 1) task (task nr 1)

    3. pin 10 (DIO 2) task2 (task nr 2)

    4. pin 11 (DIO 3) task inside region

    5. pin 12 (DIO 4) task2 inside region

  1. Some dirty code for fast pin togling. On Uno pin 8,9,10,.. is from PORTB bit 0,1,2,…

  2. If you are using a MEGA PORTA may be better. pin layout

Interrupt is disabled during PORTB manipulation to ensure it is carried out atomic.

Each task is eating time inside and outside the critical region

 

code for k5

  1. pin 8 (DIO 0) - Dummytask (task nr 0

  2. pin 9 (DIO 1) task (task nr 1)

  3. pin 10 (DIO 2) task2 (task nr 2)

  4. pin 11 (DIO 3) task inside region

  5. pin 12 (DIO 4) task2 inside region

Each task is eating time inside and outside the critical region

Some observations for task2:

  1. At approx -12msec task2 is eating 3msec inside critical region

  2. At approx -9msec task2 is leaving critical region and sleep for 1 msec

  3. At approx -8 msec task2 is eating 1 msec

  4. At approx -7 msec task2 sleep for 20 msec

  5. At approx 23 msec task2 wake up loop to top of while and get critical region at once

  6. and repeat as above

What did happen at -40 msec ? Seems that

  1. before -40 msec is task inside critical region and task is waiting outside

  2. As soon as task release critical region task2 enter the region.

k06 - as k05 but task2 has lower priority than task

Task has higher priority than task2

  1. task will take CPU when needed

    1. At approx 22 msec task take CPU after a 1msec sleep after critical region

    2. And the stay inside the region is prolonged for task2

 

code for k6

  1. Observe at approx 22 msec that task taskes CPU bq task has higher priority than task2

  2. Which prolongs the stay of task inside the critical region (Seen on DIO 4) at 24msec

k09 One task running fixed samplingsfrequency

A sempaphore get attached a krnl timer which signal to the semaphore every 10 tick * 1msec

The task do only wait by the semaphore and when the sempahore gets a krnl kick (signal) at regular intervals

  1. task is released form the semaphore

  2. eat 3 msec

  3. loop to top and wait again to next sample time

Can be used for control loops like

void task()
{
  int res;

  k_set_sem_timer(sem1, 10); // krnl signals every 10 msec

  while (1) {
    res = k_wait(sem1, 0); // knock knock at sem1. timeout = 0 means forever
    ADC(); // measure input
    controlAlg();
    DAC(); actuate output
  }
}

 

code for k9

  1. You can see that task is running very regular every 10 msec

k10 two task sampling

Debugging on pins has been modified so

  1. DIO3 is high when task is eating CPU time after leaving k_wait

  2. DIO4 is high when task2 is eating CPU time after leaving k_wait

  3. task and task2 has same priority

  4. task is eating 4 msec every 15 msec

  5. task2 is eating 3 msec every 10 msec

 

code for k10

Debugging on pins has been modified so

  1. DIO3 is high when task is eating CPU time after leaving k_wait

  2. DIO4 is high when task2 is eating CPU time after leaving k_wait

  3. task and task2 has same priority

  4. task is eating 4 msec every 15 msec

  5. task2 is eating 3 msec every 10 msec

So we can observe that due to round robbing and same priority eat time is prolonged from time to time for both tasks.

k11 as k10 except task has higher priority taht task2

Now task has highest prority which means it will always get CPU

 

code for k11

  1. DIO3 is high when task is eating CPU time after leaving k_wait

  2. DIO4 is high when task2 is eating CPU time after leaving k_wait

  3. task and task2 has same priority

  4. task is eating 4 msec every 15 msec

  5. task2 is eating 3 msec every 10 msec

Observe

  1. that DIO 4 might be high for longer that 3 msec

  2. that DIO 3 is always 4 msec bq task just takes CPU due to priority

  3. See at -13 msec for task2 we have 3 msec eat and the same at -8 msec.

  4. Might be that -13msec is delayed bq task is running from -17msec to -13msec

  5. I guess task2 would like to had CPU at -17msec but task takes it

  6. So we have jitter on task2

CONCLUSION

Multitasking is very difficult to understand, estimate and debug


k01 to k11 image first next link to code

a/k01/k01.ino

 

a/k02/k02.ino

 

a/k03/k03.ino

 

a/k04/k04.ino

 

a/k05/k05.ino

 

a/k06/k06.ino

 

a/k07/k07.ino

 

a/k08/k08.ino

 

a/k09/k09.ino

 

a/k10/k10.ino

 

a/k11/k11.ino