📄 fullrtos.asm
字号:
; FullRTOS - Full RTOS Version
;
;
; This is a "Full" Real Time Operating System for the 8051. This operating
; system allows tasks to call a single subroutine and global interrupt
; enabling in Tasks.
;
; The Operating System Interfaces are the same as "RTOSLite". Note that each
; Task primarily works out of Bank 0.
;
; This Code Loads in "App.asm" and executes it starting at
; "Application".
;
; Each Task Data Block is set as up to 16 bytes, saved in Scratchpad RAM.
; The Task Data Blocks Start at Address 040h and can have either 4 or 12
; tasks in Total (4 for a "Typical" 8051 with 128 Bytes of Scratchpad RAM
; (although this can be increased up to 7 by changing the Start Address)
; and 12 to 15 for a device with 256 bytes of Scratchpad RAM).
;
; Data is defined as follows:
;
; Address Function
; 0 Task Information Byte
; 1 Task Priority Byte
; 2 Stack Pointer End
; 3-15 Task Stack Information
;
; The End of the Task Stack Information is:
;
; Offset Byte
; -7 Low Byte of Program Counter
; -6 High Byte of Program Counter
; -5 IE Register
; -4 Accumulator
; -3 PSW Register
; -2 R0 Register
; -1 R1 Register
; 0 R2 Register
;
; Each Task can call one subroutine before the Operating System
; is Invoked.
;
; NOTE:
;
; 1. Currently Executing Task Recorded in RS0/RS1 of PSW
; 2. The Task Block Bank Register is defined as:
; Bit Function
; 7 0
; 00000000 Task Can Execute
; 0001nnnn Sent Message to Task "nnnn", Waiting for Ack
; 00100000 Waiting for a Message
; 010000ii Waiting for Interrupt Number
; 11111111 No Task Loaded for Register Bank
; 3. The Task's Priority Determines which Tasks Execute Next.
;
;
; The following Operations have been included (as Macros which
; may call the mainline):
;
; Function Input Output Data Comments
;
; SendMsg Acc = Ptr to Msg in Scratchpad Block until the Message is
; Acknowledged
;
; WaitMsg Wait Until A Task has
; a Message for Current
;
; ReadMsg Task # Acc = Pointer to Msg Return Non-Zero if
; Acc = 0 if No Msg Message is being sent
; to the Current Task
; From the Task
;
; AckMsg Task # Acknowledge the Message
; from the Specific Task
;
; StartTask R1/R2 = Task Addr Start the Specified Task
; Acc = Task # (with the address)
; Acc = -1 if Nothing Available
; R0 - Priority
;
; EndTask Have the Task End itself
;
; NextTask Jump to the Next Executable
; Task
;
; WaitInt Int # Wait for the Given Interrupt
;
; GetSem Semaphore # Wait for the Semaphore to
; become Available
;
; RelSem Semaphore # Release the Semaphore
;
; Myke Predko
; 98.03.11
;
; Hardware Notes:
; Operation of the RTOS is dependant on the Application
; Constant Declarations
; - These are to be changed for Different MCUs
_TaskStart EQU 030h ; Tasks Start at 030h
_TaskEnd EQU 070h
_TIBSize EQU 010h ; Size of Each Task Information Block
; Variable Declarations
_Semaphore EQU 020h ; The Semaphore Byte
_CurTask EQU 004h ; Index of the Currently Executing Task
; RTOS Function Macros
MACRO NextTask ; Let the Next Task Execute
acall _RTOSNextTask
ENDMAC
MACRO EndTask ; End the Current Task
mov R0,_CurTask ; Point to the Current Task
mov @R0,#0FFh ; Mark in the Task Block that the Task has Ended
acall _RTOSNextTask
ENDMAC
MACRO StartTask (Task,Priority) ; Start the New Task
mov R2,#(Task AND 255)
mov R1,#(Task SHR 8)
mov R0,Priority
acall _RTOSStartTask ; Task Number in R0 (or -1)
ENDMAC
MACRO WaitInt(Number) ; Wait for the Specific Interrupt Number
mov R0,_CurTask ; Get the Pointer to the Task
mov @R0,#(040h + Number)
acall _RTOSNextTask ; Now, Start Waiting for the Other Tasks
ENDMAC
MACRO RelSem(Number) ; Release the Semaphore Number
setb Number ; Just Set the Semaphone Number
ENDMAC
MACRO GetSem(Number) ; Get the Semaphore
@_RTOSGetSem: ; Loop Back Here for Each Semaphore
jnb Number,@_RTOSGetSemGot ; Semaphore Gotten
acall _RTOSNextTask ; Wait for the Next Task
ajmp @_RTOSGetSem ; Try to get the Semaphore Again
@_RTOSGetSemGot: ; Have the Semaphore
ENDMAC
MACRO AckMsg(Number) ; Acknowledge the Message from Task #
mov A,Number
acall _RTOSAckMsg
@_RTOSAckMsg:
ENDMAC
MACRO ReadMsg(Number) ; Read the Message from the Task
mov A,Number
acall _RTOSReadMsg
ENDMAC
MACRO SendMsg(Task,Ptr) ; Send the Message Pointed to
mov R0,_CurTask ; Point to the Current Task
mov A,Task
orl A,#%00010000
mov @R0,A
anl A,#(%00010000 XOR 0FFh); Load the Accumulator with the Task Number
mov R0,Ptr ; Pointer can be Value or Address
acall _RTOSSendMsg
ENDMAC
MACRO WaitMsg ; Wait for the Message to be Send
acall _RTOSWaitMsg
ENDMAC
; Mainline
org 0 ; Execution Starts Here
ajmp _RTOSMain ; Jump to the RTOS Initialization Code
; Interrupt Handlers
org 0003h ; Int 0 - _Int0 Interrupt
push IE ; Save the Interrupt Register
push ACC ; Save the Accumulator
mov A,#%01000000
ajmp _RTOSInt ; Handle the Interrupt
org 000Bh ; Int 1 - Timer0 Interrupt
push IE
push ACC ; Save the Accumulator
mov A,#%01000001
ajmp _RTOSInt ; Handle the Interrupt
org 0013h ; Int 2 - _Int1 Interrupt
push IE
push ACC ; Save the Accumulator
mov A,#%01000010
ajmp _RTOSInt ; Handle the Interrupt
org 001Bh ; Int 3 - Timer1 Interrupt
push IE
push ACC ; Save the Accumulator
mov A,#%01000011 ; Set the Interrupt Number
_RTOSInt: ; Handle the Interrupt Reqests
clr IE.7 ; Disable Global Interrupts
push PSW ; Save the Task's Context Information
push 0 ; All Tasks run out of Bank 0 Primarily
push 1
push 2
mov R1,A ; Save the Interrupt Number
mov R0,_CurTask ; Get the Pointer to the Current Task
inc R0 ; Point to the SP Byte
inc R0
mov @R0,SP ; Save the Stack Pointer
mov R0,#_TaskStart ; Now, Look for Tasks Waiting for the Interrupt
_RTOSIntLoop:
mov A,R1 ; Get the Interrupt Number
xrl A,@R0 ; Do we Have a Match at This Task?
jnz _RTOSIntLoopSkip
mov @R0,A ; Yes, Mark it as able to Execute
; (Load with the Zero in "A")
_RTOSIntLoopSkip:
mov A,#_TIBSize ; Point to the Next Task
add A,R0
mov R0,A
cjne A,#_TaskEnd,_RTOSIntLoop
ajmp _RTOSNextTaskDo ; It's not, Jump to the Next Task Code
_RTOSStartTask: ; Start the Specified Task
push IE ; Save the Context Registers
clr IE.7
push ACC
push PSW
push 0
push 1
push 2
mov R1,_CurTask ; Keep track of where we are.
inc R1
inc R1
mov @R1,SP ; Save the Stack Pointer
mov R1,SP ; Save the Stack Pointer for Later
mov R0,#(_TaskStart - _TIBSize) ; Get Address of the First Task
_RTOSStartTaskLoop: ; Now, Loop Around Looking for an Available Task
mov A,R0
add A,#_TIBSize ; Look at the Next Task
mov R0,A
add A,#((_TaskEnd XOR 0FFh) + 1)
jz RTOSStartTaskNo ; Don't have a Task to Put it in, End
cjne @R0,#0FFh,_RTOSStartTaskLoop ; Jump if Task Not Available
mov @R0,#0 ; Enable the Task to Run
mov _CurTask,R0 ; Save the Current Task Address
mov A,R0 ; Now, Set up the Task
inc A
inc A
mov SP,A ; Have a New Stack Pointer
mov A,@R1 ; Put the Return Address on the Stack
push ACC
dec R1
mov A,@R1
push ACC
dec R1
inc R0
mov A,@R1 ; Save the Task's Priority
mov @R0,A
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -