⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 prog43.asm

📁 主要是8051源代码
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;  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 + -