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

📄 rtoslite.asm

📁 主要是8051源代码
💻 ASM
字号:
;  RTOSLite - Lite RTOS Version 
;
;  This Code Loads in "App.asm" and executes it starting at
;   "Application".  
;
;  Each Task is set in an individual Register Bank.  The 
;   Registers are defined as follows:
;
;  Register	Function
;  R0           Message Pointer/Index/Task Address/GP Register
;  R1		RTOS Request Number/Index/Task Address/GP Register
;  R2		GP Task Register/Task Address
;  R3		Task Block Information
;  R4		Low Byte of Return Address
;  R5		High Byte of Return Address
;  R6		Saved Accumulator
;  R7		Saved PSW
;
;  NOTE: 
;
;    1.  The Stack Pointer is set by the RTOS to address of "R3"
;    2.  No subroutines can be called from within the Tasks
;    3.  R2 should be used for Information that Doesn't Change
;    4.  Currently Executing Task Recorded in RS0/RS1 of PSW
;    5.  The Task Block Bank Register is defined as:
;        Bit	Function
;	 5    0
;	 000000 Task Can Execute
;	 1nn000 Sent Message to Task "nn", Waiting for Ack
;	 001xxx Waiting for a Message
;	 01iiii Waiting for Interrupt Number 
;	   0FFh No Task Loaded for Register Bank
;    6.  Task 3 is the always Available Task
;
;
;  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
;
;  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.01
;
;  Hardware Notes:
;  Operation of the RTOS is dependant on the Application

;  Variable Declarations
;  020h - the Semaphore Byte

;  RTOS Function Macros
MACRO NextTask			;  Let the Next Task Execute

  acall	 _RTOSNextTask

ENDMAC

MACRO EndTask			;  End the Current Task

  mov	 R3,#0FFh		;  Set Task Block that it has Ended

  acall	 _RTOSNextTask

ENDMAC

MACRO StartTask Task 		;  Start the New Task

  mov	 R0,#(Task AND 255)
  mov	 R1,#(Task SHR 8)

  acall	 _RTOSStartTask		;  Task Number in Acc (or -1)

ENDMAC

MACRO WaitInt(Number)		;  Wait for the Specific Interrupt Number

  mov	 R3,#(%00010000 OR (1 SHL Number))  ;  Wait for Specified Interrupt

  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(Task)		;  Acknowledge the Message from Task #

  mov	((Task * 8) + 3),#0	;  Tell the Task to Stop Waiting

ENDMAC

MACRO ReadMsg(Task)		;  Read the Message from the Task

  mov	 R0,#((Task SHL 3) + 3) ;  Make Sure the Correct Address

  acall	 _RTOSReadMsg

ENDMAC

MACRO SendMsg(Task,Ptr)	        ;  Send the Message Pointed to 

  mov	 R3,#(%00100000 OR (Task SHL 3))  ;  Block the Task

  mov	 R1,#((Task SHL 3) + 3)
  mov	 R0,#Ptr

  acall	 _RTOSSendMsg

ENDMAC

MACRO WaitMsg			;  Wait for the Message to be Send

  mov    R3,#%1000              ;  Make the Task Blocking

  acall	 _RTOSWaitMsg

ENDMAC


;  Mainline
 org 0                          ;  Execution Starts Here

  ajmp	 _RTOSMain		;  Jump to the RTOS Initialization Code

 org 0003h			;  _Int0 Interrupt

  clr	 IE.7			;  Disable Global Interrupts

  push	 ACC			;  Save the Accumulator

  mov	 A,#0FEh		;  Have Interrupt 0

  ajmp	 _RTOSInt		;  Handle the Interrupt

 org 000Bh			;  Timer0 Interrupt

  clr	 IE.7			;  Disable Global Interrupts

  push	 ACC			;  Save the Accumulator

  mov	 A,#0FDh		;  Have Timer 0 Interrupt

  ajmp	 _RTOSInt		;  Handle the Interrupt

 org 0013h			;  _Int1 Interrupt

  clr	 IE.7			;  Disable Global Interrupts

  push	 ACC			;  Save the Accumulator

  mov	 A,#0FBh		;  Have Interrupt 1

  ajmp	 _RTOSInt		;  Handle the Interrupt

 org 001Bh			;  Timer1 Interrupt

  clr	 IE.7			;  Disable Global Interrupts

  push	 ACC			;  Save the Accumulator

  mov	 A,#0F7h		;  Have Timer 1 Interrupt

_RTOSInt:			;  Handle the Interrupt Reqests

  anl	 IE,A			;  Disable the Requested Interrupt and Global Ints

  push	 PSW			;  Save the Task's PSW

  cpl	 A
  orl	 A,#%00010000		;  In "A", Have the Expected Interrupt Wait Value

  xrl	 A,3			;  Now, Is Task 0 Waiting for This?
  jnz	 _RTOSI1		;   No, Check Task 1
  xch 	 A,3			;  Mark that the Task Can Now Run

_RTOSI1:			;  Restore the Accumulator
  xrl	 A,3
  xrl	 A,00Bh                 ;  Check the Next Task
  jnz	 _RTOSI2		;  It's not, Check Task 2
  xch	 A,00Bh

_RTOSI2:			;  Restore the Accumulator
  xrl	 A,00Bh
  xrl	 A,013h
  jnz	 _RTOSDoNextTask	;  It's not, Jump to the Next Task Code
  xch	 A,013h                 ;  It is, Enable the Task
  ajmp	 _RTOSDoNextTask


_RTOSStartTask:			;  Start the Specified Task

  push	 ACC			;  Save the Context Information
  push	 PSW

  mov	 A,3			;  Look for a Task that's Available
  cjne	 A,#0FFh,_RTOSStartTask1  ;   If Task0 Not Available, Check Task1

  mov	 4,R0			;  Save the Task Starting Address
  mov	 5,R1

  mov    R6,#0

  clr	 A			;  Going to Have Task 0

  ajmp	 _RTOSStartTaskDo	;  Have the New Task

_RTOSStartTask1:		;  Check to See if Task1 Is Available

  mov	 A,00Bh
  cjne	 A,#0FFh,_RTOSStartTask2  ;  If Not Available, Check Task 2

  mov	 00Ch,R0		;  Save the Task Starting Address
  mov	 00Dh,R1

  mov    R6,#1

  mov	 A,#%00001000

  ajmp	 _RTOSStartTaskDo	;  Now, Start the New Task Executing

_RTOSStartTask2:		;  Check Task 2

  mov	 A,013h
  cjne	 A,#0FFh,_RTOSStartTaskNo  ;  No Task Available

  mov	 014h,R0		;  Save the Task Starting Address
  mov	 015h,R1

  mov	 R6,#2

  mov    A,#%00010000

_RTOSStartTaskDo:		;  Have the Task to Start up

  mov    PSW,A

  mov    R3,#0                  ;  Indicate that the Task Can Execute

  add	 A,#5			;  Convert the Value into a Stack Pointer
  mov	 SP,A

  ret				;  Start the Task Executing

_RTOSStartTaskNo:               ;  No Task is Available

  mov    R6,#0FFh               ;  Return -1

  ajmp   _RTOSExecuteTask       ;  Now, Start up the Task


_RTOSNextTask:			;  Jump to the Next Active Task

  push	 ACC			;  Save the Task Registers
  push	 PSW

_RTOSDoNextTask:		;  Now, Find the Next Task

  mov	 A,PSW			;  Which Task is Active?  
  add	 A,#%00001000		;  Just Increment the Bank Register
  anl	 A,#%00011000		;  Make Sure Task isn't > %00011000
  mov	 PSW,A

_RTOSDoNextTaskNextCheck:	;  Check the Task to See if it can Execute

  cjne	 R3,#0,_RTOSDoNextTask	;  If Task Information Block == 0, then Execute it

_RTOSExecuteTask:		;  Now, the Task can Start Executing

  mov	 A,PSW			;  Get the Correct Stack Pointer
  anl    A,#%00011000           ;  Get Rid of Extra Bits
  add	 A,#7			;  At the End of the Register Bank
  mov	 SP,A

  pop	 PSW			;  Restore the PSW
  pop	 ACC

  reti				;  Return Where Program Stopped

_RTOSReadMsg:			;  Read the Message from the Task in A

  mov    A,@R0                  ;  Get the Message Number

  xrl	 A,PSW			;  Do we Have a Match?
  anl	 A,#%00111000		;  Is It Waiting for This Task?
  xrl	 A,#%00100000

  jz	 _RTOSReadMsgHave	;  Yes, Have the Message

  clr	 A			;  Else, the Message isn't There

  ret

_RTOSReadMsgHave:		;  Have the Message, Return It

  dec    R0                     ;  Now, Point to the Actual Message
  dec    R0
  dec    R0

  mov	 A,@R0			;  R0 is Pointing to the Message Pointer of the Task
 
  ret				

_RTOSSendMsg:			;  Send the Message to the Task

  cjne	 @R1,#%1000,_RTOSNextTask  ;  If the Task ISN'T Waiting for the Message, Jump On

  mov	 @R1,#0			;  Yes, Free Up the Task

  ajmp	 _RTOSNextTask		;  Jump to the Next Active Task

_RTOSWaitMsg:			;  Waiting for a Message, See if Something There First

  mov	 A,3			;  See if Anything is Waiting to Send to This Task
  xrl	 A,PSW
  anl	 A,#%00111000
  xrl	 A,#%00100000
  jz	 _RTOSWaitMsgHave	;  Something is Sending to the Task

  mov	 A,00Bh
  xrl	 A,PSW
  anl	 A,#%00111000
  xrl	 A,#%00100000
  jz	 _RTOSWaitMsgHave

  mov	 A,013h
  xrl	 A,PSW
  anl	 A,#%00111000
  xrl	 A,#%00100000
  jnz	 _RTOSNextTask

_RTOSWaitMsgHave:               ;  Have the Message, Can Continue to Execute

  mov	 R3,#0			;  Can Start Executing Again

  ajmp	 _RTOSNextTask		;  See what is to Execute Next

_RTOSMain:			;  RTOS Initialization Code

  mov	 020h,#00Fh		;  Clear the Semaphores (Set them)

  mov	 003h,#0FFh		;  Mark the Tasks as Not Available
  mov	 00Bh,#0FFh
  mov	 013h,#0FFh

  mov	 01Bh,#000h		;  Setup Task 3 as "_AlwaysTask"

  mov	 SP,#01Dh		;  Setup the Stack to Start the Task

  setb	 PSW.3			;  Make Sure the Accumulator Knows 
  setb	 PSW.4			;   Where to get the Regiseters from

  clr	 A			;  Clear the Accumulator

  mov	 01Ch,#(_AlwaysTask AND 255)
  mov	 01Dh,#(_AlwaysTask SHR 8)

  ret				;  Jump to the _AlwaysTask 



_AlwaysTask:			;  The Always Available Task

  StartTask Application 	;  Start the Application Task

_AlwaysTaskLoop:		;  Loop Here Forever

  clr	 IE.7			;  Disable Global Interrupts

  NextTask			;  Look at the Next Task

  setb	 IE.7			;  Allows Interrupts to Happen

  ajmp	 _AlwaysTaskLoop	;  Loop Around (with Interrupts Enabled)


;  #### - Put in Test Application Code Here

Application:                    ;  Simple Test Application

  StartTask App2                ;  Start a Second Task

  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    021h,#0                ;  Use Address 21 as the Data Byte

  StartTask App3                ;  Start the Third Application

  mov    022h,#15               ;  Set the Counter for a One Second Loop

Application_Loop:               ;  Loop Around Here  

  setb   IE.1                   ;  Enable the Timer 0 Interrupt

  WaitInt(1)                    ;  Wait for the Interrupt

  djnz   022h,Application_Loop  ;  Wait for the Counter to Count to 1 Second   

  SendMsg(2,021h)

  inc    021h                   ;  Increment the Output Value

  mov    022h,#15               ;  Reload the Counter

  ajmp   Application_Loop

App3:                           ;  Wait for Messages from App2

  WaitMsg                       ;  Wait for a Message

  ReadMsg(1)                    ;  Read the Message from Task 0

  mov     R0,A                  ;  Read and Output the Message
  mov     A,@R0
  cpl     A                     ;  Invert the Data Before Displaying
  mov     P1,A

  AckMsg(1)                     ;  Acknowledge the Message

  ajmp     App3

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -