Rem A real-time scheduling
excercition for upgrading BASCOM to real-real time.
Rem
*************************************************************************
Rem 18 september 2000, the birth, by ceasarean, of Bascom
multitasking.
Rem Keep it SIMMple, non-preemptive
Const Nbr_tasks = 4 'Looks enough for now
Dim Task_resume_1(nbr_tasks) As Byte 'save resume address here
Dim Task_resume_2(nbr_tasks) As Byte 'save resume address here
Dim Task_status(nbr_tasks) As Byte 'status of task/metaphore's
Dim Current_task As Byte 'Task that is active
Dim Work_byte As Byte
Rem
*************************************************************************
Dim Example As Byte
Dim T3count As Byte
Dim T4count As Byte
Rem
*************************************************************************
'( What is it, well a table of resume addresses and a
status byte indicating if
Resume Is Wanted Or Indicating What The Task Is Waiting
For (reason For Suspend)
In fact thats all.
Metaphores Can Be Manipulated By Other Tasks Or From
Interrupt Routines.
Metaphores And Sram Are Absolutely Not Protected Against
Access , So Know
What You Are Doing.
Task Are Scheduled Robin Around (1 , 2 , 3 , 4 , 1 , 2 , 3
, 4 , 1 , 2 , 3.etc)
Other Policies Are Possible , Give Task 1 Priority (1 , 2
, 1 , 3 , 1 Etc)
Note That In This Case The Minimal Examples Given In The
Tasks Do Not Work,
So Becarefull When Fiddling Around With These Things.
As The Tasks Have No Private Stack Space (would Be Nice ,
But Little Resources),
Suspension Always Has To Be Initiated When Stack Is Not In
Use (so To Be
Concrete , No Suspend Invocation In A Subroutine).
')
Init_task_list:
Rem Init resume addresses, challenge : how to get them.
Answer : Play Dirty
Rem The task address is revealed by the gosub, which
pushes the resume address
Rem on the stack. We pop it up and save it.It does not win
a beaty contest,but.
'Iniialization of task start
addresses---------------------------------------
Goto Task1 'task 1 will direct issue a gosub
' to init_task_1,
revealing resume
' address
Init_task_1: 'Invoked as gosub, but never returns !
$asm
pop R16
sts {work_byte},r16
$end Asm
Task_resume_1(1) = Work_byte 'store
first pop
$asm
pop R16
sts {work_byte},R16
$end Asm
Task_resume_2(1) = Work_byte 'store
second pop
Task_status(1) = 0 'Not suspended
Rem 'End
NEVER return, stack clean !
Rem
*************************************************************************
Goto Task2
Init_task_2:
$asm
pop R16
sts {work_byte},r16
$end Asm
Task_resume_1(2) = Work_byte 'store first pop
$asm
pop R16
sts {work_byte},R16
$end Asm
Task_resume_2(2) = Work_byte 'store
second pop
Task_status(2) = 0 'Not suspended
Rem 'End
NEVER return
Rem *************************************************************************
Goto Task3
Init_task_3:
$asm
pop R16
sts {work_byte},r16
$end Asm
Task_resume_1(3) = Work_byte 'store
first pop
$asm
pop R16
sts {work_byte},R16
$end Asm
Task_resume_2(3) = Work_byte 'store
second pop
Task_status(3) = 0 'Not suspended
Rem 'End
NEVER return
Rem
*************************************************************************
Goto Task4
Init_task_4:
$asm
pop R16
sts {work_byte},r16
$end Asm
Task_resume_1(4) = Work_byte 'store
first pop
$asm
pop R16
sts {work_byte},R16
$end Asm
Task_resume_2(4) = Work_byte 'store
second pop
Task_status(4) = 0 'Not suspended
Rem 'End fall through to scheduler
Rem
*************************************************************************
Rem
*************************************************************************
'Here the scheduler starts.
Scheduler: 'Work assigner
For Current_task = 1 To Nbr_tasks 'Cycle through robin around fashion
If Task_status(current_task) <> 0 Then 'Waiting for something ?
Goto Scheduler_next 'YES, waiting for something
Else 'Prepare Return = resume address
Work_byte = Task_resume_2(current_task) 'Look sharp, reverse order
$asm
lds r16,{work_byte}
push r16
$end Asm
Work_byte = Task_resume_1(current_task) 'Look sharp, reverse order
$asm
lds r16,{work_byte}
push r16
$end Asm
End If 'Simmple
Return 'Crazy code isn't it ?
'....................back after task initiated
suspension....................
'Assume (or beware) that current_task is untouched .
'............................................................................
Task_suspend: 'Entered by a GOSUB !
$asm
pop r16
sts {work_byte},R16
$end Asm
Task_resume_1(current_task) = Work_byte 'store first pop
$asm
pop R16
sts {work_byte},r16
$end Asm
Task_resume_2(current_task) = Work_byte 'store second pop
' Thats
all, folks
Scheduler_next:
Next Current_task 'Check next task
Goto Scheduler 'ad infinitum
Rem
*************************************************************************
'( When a task thinks there is nothing to do, it suspends
itself . It calls
This Routine By Gosub , That Means The Resume Address Is
On Stack. This Address
Is Saved. The Task Identifier Is Act_task. Initially
Straigth Forward
Implemented Without Any Sophistication.
')
Rem **************************Task
1*****************************************
Task1: 'Entrypoint task 1 for setup
Gosub Init_task_1 'use this label only in setup
Rem *************************************************************************
Task1_loop: 'Real start task 1
'Do something
Example = Example + 1 'Whatever
'And give other tasks a chance (non pre-emptive system, so
necessary)
Gosub Task_suspend 'Temporarely goodbye
'Do again something
Task_status(4) = 1 'stop task 4 (status not 0!)
Goto Task1_loop
Rem
*************************************************************************
Rem *************************************************************************
Rem **************************Task
2*****************************************
Task2: 'Entrypoint task 1 for setup
Gosub Init_task_2 'use this label only in setup
Rem
*************************************************************************
Task2_loop: 'Real start task 1
'Do something
Testcondition:
If Example <> 1 Then
Gosub Task_suspend 'Wait for example to become 1
Goto Testcondition 'RTOS does not save processor status
Rem 'bits
Else
Task_status(4) = 0 'task2:task4 runs 255;1 (if1,2,3,4!)
Gosub Task_suspend 'give 4 a chance to run
End If
Goto Task2_loop
Rem
*************************************************************************
Rem *************************************************************************
Rem ******************************task 3
************************************
Task3: 'Entrypoint task 3
Gosub Init_task_3
Rem
*************************************************************************
Task3_loop: 'Real start task 3
T3count = T3count + 1
Gosub Task_suspend 'Temporarely goodbye
Goto Task3_loop
Rem
*************************************************************************
Rem *************************************************************************
Rem ***************************** task 4 *******************************
Task4: 'Entrypoint task 4
Gosub Init_task_4
Rem *************************************************************************
Task4_loop: 'Real start task 4
T4count = T4count + 1
Example = 250 't2:t4 now 6:1
Gosub Task_suspend 'Temporarely goodbye
Goto Task4_loop
Rem
*************************************************************************
Rem
*************************************************************************
End