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