.h8300h ;---------------------------------------------------------------; ; コオペレーティブなマルチタスク(これ以上単純なマルチタスクはない(^^;) ; ラウンドロビン/4タスク固定 ; タスク0(メインタスク)内 で SwitchTask をコールすると タスク 1 に切り替わる ; タスク1内 で SwitchTask をコールすると タスク 2 に切り替わる ; タスク2内 で SwitchTask をコールすると タスク 3 に切り替わる ; タスク3内 で SwitchTask をコールすると タスク 0 に切り替わる ; ; +-> タスク0(メインタスク) -> タスク1 -> タスク2 -> タスク3 -> ; | | ; +------------------------------------------------------------+ ; スタックは各タスクの必要量を確保すること ; 各タスクは,無限ループにすること ; 大きな配列は,static にしたほうが,安全である. ; ;使用方法 ; void main( void ) ; { ; InitMultiTask() ; //まず、初期化 ; InitTask1( Task1Loop, Task1Stack ) ; ; InitTask2( Task2Loop, Task2Stack ) ; ; InitTask3( Task3Loop, Task2Stack ) ; ; for(;;){ ; SwitchTask() ; ; . ; . ; . ; } ; } ; void Task1Loop( void ) ; { ; for(;;){ ; SwitchTask() ; ; . ; . ; . ; } ; } ; void Task2Loop( void ) ; { ; for(;;){ ; SwitchTask() ; ; . ; . ; . ; } ; } ; void Task3Loop( void ) ; { ; for(;;){ ; SwitchTask() ; ; . ; . ; . ; } ; } ;---------------------------------------------------------------; .global _InitMultiTask .global _SwitchTask .global _InitTask0 .global _InitTask1 .global _InitTask2 .global _InitTask3 .global _InitTask4 .global _InitTask5 .global _InitTask6 .global _TaskStackPointer ;****************************************************************************** ; マルチタスクシステムの初期化 void InitMultiTask( void ) ;****************************************************************************** _InitMultiTask: sub.b r0l,r0l mov.b r0l,@CurrentTaskNo rts ;****************************************************************************** ; タスクスイッチング void SwitchTask( void ) ;****************************************************************************** _SwitchTask: push.l er3 push.l er4 push.l er5 push.l er6 ;**************************** ; er0 = CurrentTaskNo * 2 ;**************************** sub.l er0,er0 mov.b @CurrentTaskNo,r0l ; add.l er0,er0 ;bra xx が2バイトの命令であるため2倍する add.l #TaskJumpTable,er0 ; jmp @er0 ;のいずれかにジャンプ TaskJumpTable: ;ジャンプテーブル bra Task0to1 bra Task1to2 bra Task2to3 bra Task3to4 bra Task4to5 bra Task5to6 bra Task6to0 Task0to1: mov.l sp,@Task0Sp mov.l @Task1Sp,sp bra EndOfTaskSw Task1to2: mov.l sp,@Task1Sp mov.l @Task2Sp,sp bra EndOfTaskSw Task2to3: mov.l sp,@Task2Sp mov.l @Task3Sp,sp bra EndOfTaskSw Task3to4: mov.l sp,@Task3Sp mov.l @Task4Sp,sp bra EndOfTaskSw Task4to5: mov.l sp,@Task4Sp mov.l @Task5Sp,sp bra EndOfTaskSw Task5to6: mov.l sp,@Task5Sp mov.l @Task6Sp,sp EndOfTaskSw: mov.b @CurrentTaskNo,r0l ;CurrentTaskNoをインクリメント add.b #1,r0l mov.b r0l,@CurrentTaskNo ReturnToTask: ;タスク切り替え処理終了 pop.l er6 pop.l er5 pop.l er4 pop.l er3 rts Task6to0: mov.l sp,@Task6Sp mov.l @Task0Sp,sp sub.b r0l,r0l ;CurrentTaskNo=0 mov.b r0l,@CurrentTaskNo bra ReturnToTask ;****************************************************************************** ; タスク0の初期化 void InitTask1( void(*func)(void),char* Stack) ; r0:program counter r1:stack ;****************************************************************************** _InitTask0: bsr SetStack mov.l er1,@Task0Sp rts ;****************************************************************************** ; タスク1の初期化 void InitTask1( void(*func)(void),char* Stack) ; r0:program counter r1:stack ;****************************************************************************** _InitTask1: bsr SetStack mov.l er1,@Task1Sp rts ;****************************************************************************** ; タスク2の初期化 ;****************************************************************************** _InitTask2: bsr SetStack mov.l er1,@Task2Sp rts ;****************************************************************************** ; タスク3の初期化 ;****************************************************************************** _InitTask3: bsr SetStack mov.l er1,@Task3Sp rts ;****************************************************************************** ; タスク4の初期化 ;****************************************************************************** _InitTask4: bsr SetStack mov.l er1,@Task4Sp rts ;****************************************************************************** ; タスク4の初期化 ;****************************************************************************** _InitTask5: bsr SetStack mov.l er1,@Task5Sp rts ;****************************************************************************** ; タスク4の初期化 ;****************************************************************************** _InitTask6: bsr SetStack mov.l er1,@Task6Sp rts ;****************************************************************************** ; スタックの内容(6ワード)を r0(PC) でセット(push PC × 6) ;****************************************************************************** SetStack: and.b #0xfe:8,r1l ;必ず偶数番地にする(馬鹿避け) mov.l er0,@-er1 ;r3,r4,r5,r6,pc の分 mov.l er0,@-er1 mov.l er0,@-er1 mov.l er0,@-er1 mov.l er0,@-er1 rts .global Task0Sp .section .data .align 2 _TaskStackPointer: Task0Sp: .space 4 Task1Sp: .space 4 Task2Sp: .space 4 Task3Sp: .space 4 Task4Sp: .space 4 Task5Sp: .space 4 Task6Sp: .space 4 CurrentTaskNo: .space 1 .end