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

📄 fullrtos.asm

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