📄 fullrtos.asm
字号:
mov A,_CurTask ; Save the Task Number
add A,#((_TaskStart XOR 0FFh) + 1)
swap A ; Put the Task Number in the Correct Format
mov @R1,A ; Into R0 of the Previous Task
mov IE,#08Fh ; Enable Interrupts
ret
RTOSStartTaskNo: ; No Task is Available
dec R1 ; Point to R0
dec R1
mov @R1,#0FFh ; Mark that Nothing was Available
mov R0,_CurTask ; Get the Pointer to the Current Task Set
ajmp _RTOSExecuteTask ; Now, Start up the Task
_RTOSNextTask: ; Jump to the Next Active Task
push IE ; Save the Context Registers
clr IE.7 ; Disable Global Interrupts
push ACC
push PSW
push 0
push 1
push 2
mov R0,_CurTask ; Save the Stack Pointer
inc R0
inc R0
mov @R0,SP
_RTOSNextTaskDo: ; Assume that Ints are off and
; Context Registers are Saved
mov R0,_CurTask ; Start at the Current Task
mov R1,#_TaskEnd ; Find the Next Highest Task to Execute
mov R2,#0FFh
ajmp _RTOSNextTaskInc ; Jump to the Next Task
_RTOSNextTaskLoop:
mov A,R0
xrl A,_CurTask ; Have We Looped Through them All?
jz _RTOSExecuteTask
_RTOSNextTaskInc: ; Increment to the Next Task
cjne R0,#_TaskEnd,_RTOSNextTaskSkip
mov R0,#(_TaskStart - _TIBSize) ; Yes, Start at Beginning of the Buffer
_RTOSNextTaskSkip: ; Point to the Next Task
mov A,#_TIBSize
add A,R0
mov R0,A
cjne @R0,#0,_RTOSNextTaskLoop ; Jump Around and Do the Loop Again
inc R0 ; Point to the Next Task
mov A,@R0
dec R0
clr C
subb A,R2
jnc _RTOSNextTaskLoop ; Same or Lower Priority
add A,R2 ; New Task
mov R2,A ; Save the New Priority
mov A,R0 ; Save the New Task Information Block
mov R1,A
ajmp _RTOSNextTaskLoop
_RTOSExecuteTask: ; Start the Task Executing
mov _CurTask,R1 ; Save the Current Task Pointer
inc R1 ; Get the Tasks Stack Pointer
inc R1
mov SP,@R1
pop 2 ; Restore the Context Registers
pop 1
pop 0
pop PSW
pop ACC
pop IE
reti
_RTOSAckMsg: ; Acknowledge the Task Message
swap A ; Get the Offset to the Task to Ack
add A,#_TaskStart
mov R0,A
mov A,_CurTask ; Get the Current Task
add A,#((_TaskStart XOR 0FFh) + 1) ; Figure Out it's Number
swap A
orl A,#_TIBSize ; Make Sure in the Correct Format
xrl A,@R0 ; Is the Task Waiting for the Current one?
jnz _RTOSAckMsgEnd ; Nope, Just End
mov @R0,#0 ; Yes it is, Allow it to Execute
_RTOSAckMsgEnd:
ret
_RTOSReadMsg: ; Read the Message from the Task in A
swap A ; Get the Offset to the Task to Ack
add A,#_TaskStart
mov R0,A
mov A,_CurTask ; Get the Current Task
add A,#((_TaskStart XOR 0FFh) + 1) ; Figure Out it's Number
swap A
orl A,#010h ; Make Sure in the Correct Format
xrl A,@R0 ; Is the Task Waiting for the Current one?
mov R1,A
mov A,#0FFh ; Assume it will fail
cjne R1,#0,_RTOSReadMsgEnd ; Task doesn't have a Message, Return - in ACC
inc R0 ; Now, Figure out Where the Message is
inc R0
mov A,@R0 ; Get the Task's Stack Pointer
add A,#0FEh ; Get the Value in the Sending Task's R1
mov R0,A ; Get the Value in the Task's R1 Stack Value
mov A,@R0 ; Return the Value in R0 in the Accumulator
_RTOSReadMsgEnd:
ret
_RTOSSendMsg: ; Send the Message to the Task
push IE ; Save all the Registers
clr IE.7
push ACC
push PSW
push 0
push 1
push 2
mov R0,_CurTask ; Save the Current Stack Pointer
inc R0
inc R0
mov @R0,SP
swap A ; Get the Task Address
add A,#_TaskStart
mov R1,A
cjne @R1,#%00100000,_RTOSNextTaskDo ; Jump to the Next Task
mov @R1,#0 ; Enable Task Sending to
ajmp _RTOSNextTaskDo ; Jump to the Next Task
_RTOSWaitMsg: ; Waiting for a Message, See if Something There First
push IE ; Save all the Registers
clr IE.7
push ACC
push PSW
push 0
push 1
push 2
mov R0,_CurTask ; Save the Stack Pointer
inc R0
inc R0
mov @R0,SP
mov R0,#(_TaskStart - _TIBSize)
mov A,_CurTask
add A,#((_TaskStart XOR 0FFh) + 1)
swap A
orl A,#010h ; "A" has Message to Find
_RTOSWaitMsgLoop: ; See if Any Tasks Are Sending to Current
xrl A,@R0 ; Do we Have a Task Sending to This one?
jz _RTOSWaitMsgHere ; If Zero, then "Yes"
xrl A,@R0 ; Restore the Accumulator
xch A,R0
add A,#010h ; Add 10 to the Task Pointer
xch A,R0
cjne R0,#_TaskEnd,_RTOSWaitMsgLoop ; Try the Next Task
mov R0,_CurTask ; Else, Mark the Task as Blocking
mov @R0,#%00100000
ajmp _RTOSNextTaskDo
_RTOSWaitMsgHere: ; Something is Waiting on the Message
mov R0,_CurTask ; Reset the Task as Executable
mov @R0,#0
ajmp _RTOSNextTaskDo
_RTOSMain: ; RTOS Initialization Code
mov _Semaphore,#00Fh ; Clear the Semaphores (Set the bits)
mov R0,#_TaskStart ; Mark the Tasks as NOT Executing
_RTOSMainLoop:
mov @R0,#0FFh ; Mark the Task as NOT Available
mov A,#_TIBSize ; Point to the Next Task
add A,R0
mov R0,A
cjne A,#_TaskEnd,_RTOSMainLoop ; At the Last Task Block?
mov @R0,#0 ; Yes, Mark that the Task can Run
mov _CurTask,R0 ; Note that it is the Current Task
inc R0 ; Point to the Data in Memory
mov @R0,#0FFh ; AlwaysTask Lowest Priority
inc R0
inc R0
mov @R0,#(_AlwaysTask AND 255)
inc R0
mov @R0,#(_AlwaysTask SHR 8)
mov SP,R0 ; Save the Task's Stack Pointer
mov IE,#%10001111 ; Enable all Interrupts
ret ; Jump to the _AlwaysTask
; Always Executable Task
_AlwaysTask: ; The Always Available Task
StartTask (Application,#080h) ; Start the Application Task
_AlwaysTaskLoop: ; Loop Here Forever
NextTask ; Look at the Next Task
ajmp _AlwaysTaskLoop ; Loop Around (with Interrupts Enabled)
; ##### - Put in "$include app.asm" Load Here
; Define Sample Application
AppCtr EQU 011h ; Application Counter
TimeCtr EQU 012h ; Time Interval Counter
App2Task EQU 013h ; Task 2 Number
App3Task EQU 014h ; Task 3 Number
Application: ; Simple Test Application
StartTask (App2,#000h) ; Start a Second Task with an Interrupt Handler
mov App2Task,R0
StartTask (App3,#0C0h) ; Start the Second, Display Task
mov App3Task,R0
EndTask ; End this Task
App2: ; Second Task
mov CKCON,#%00001000 ; Use Internal /4 Clock for Timer0
mov TMOD,#%00000001 ; Timer0 - Uses Internal Clock
; - Run in Mode 1
mov TCON,#%00010000 ; Start Timer0 running
mov AppCtr,#0 ; Use Address 011h as the Data Byte
mov TimeCtr,#15 ; Set the Counter for a One Second Loop
Application_Loop: ; Loop Around Here
WaitInt(1) ; Wait for the Interrupt
djnz TimeCtr,Application_Loop ; Wait for the Counter to Count to 1 Second
SendMsg(App3Task,#AppCtr) ; Send the Message to App3
inc AppCtr ; Increment the Output Value
mov TimeCtr,#15 ; Reload the Counter
ajmp Application_Loop
App3: ; Wait for Messages from App2
WaitMsg ; Wait for a Message
ReadMsg(App2Task) ; Read the Message from Task 1
mov R0,A ; Read and Output the Message
mov A,@R0
cpl A ; Invert the Data Before Displaying
mov P1,A
AckMsg(App2Task) ; Acknowledge the Message
ajmp App3
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -