📄 prog43.asm
字号:
; FullRTOS - Digital Clock/Thermometer using FullRTOS
;
;
; This Application implements a Real Time Clock and Thermometer,
; outputting the data onto an LCD Display and updating the clock
; using a button input.
;
; The Tasks Implemented are:
; Application/TmrInitTask - Initialize/Start Up the Timer Interrupt and Load
; Other Tasks
; LCDTask - Execute the Command Passed to it
; ClockTask - Real Time Clock Task
; TemperatureTask - Task Used for Checking Temperature
;
;
; Myke Predko
; 98.04.28
;
; Hardware Notes:
; DS80C320 Running at 4 MHz
; LCD Data Bits are on P3
; LCD.6 - "E" Clock on P1.7
; LCD.5 - "RW" Pin on P1.5
; LCD.4 - "RS" Pin on P1.4
; Time Set Button - on P1.0
; Temperature Pin - P1.0
; 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
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 Variables
LCDTask EQU 010h ; LCDTask Number
TimeTask EQU 011h ; Time Task Number
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -