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

📄 os_cpu_a.a51

📁 我移植的uCos 2.86 版本,可以在单片51上运行,在AT89C51ED2上测试过.
💻 A51
字号:

$NOMOD51
; 
; The uC/OS II port for Dallas 80C390 on Keil C51 V7
;
; Ported date:     Dec 2, 2003
; By:              Stuart Wright (swright@jiskoot.com)
; Target platform: Keil C51 V7.07 and above 

; Based on port for 8051 by John X. Liu, China, (johnxliu@163.com)

	NAME	OS_CPU_A_ASM

; ?C_XBP is the simulated external stack pointer in large mode, but its origianal
; declare makes it can not be used in c files, so redeclare it in this module 
; insteading of the old one
	PUBLIC	?C_XBP, C_XBP					;

	EXTRN   CODE(_?C_OSCtxSw)
	EXTRN	DATA (?C_IBP)

	PUBLIC	LoadCtx, STACK_START, _?OSCtxSw, _?KCOSCtxSw

#include "reg52.h"

; Declare the external stack pointer by ourself, so that we can use it freely.
; you know, in the name of '?C_XBP' it can not be used in c modules but in the 
; name of 'C_XBP' it can do.
DT?C_XBP	SEGMENT	DATA
		RSEG	DT?C_XBP
?C_XBP:					; These two labels point to the same address
C_XBP:					;
	DS	2

; Declare a label 'Stack' in the hardware stack segment so that we know where it begins.
?STACK		SEGMENT		IDATA
		RSEG	?STACK
STACK_START:
	DS	1

LoadXBP	MACRO
		;MOV 	DPX,#0
		MOV	DPH, C_XBP
		MOV	DPL, C_XBP+1
	ENDM

SaveXBP MACRO
		PUSH	IE
		CLR	EA
		MOV	C_XBP,   DPH
		MOV	C_XBP+1, DPL
		POP	IE
	ENDM

LoadREG	MACRO   REG
		MOVX	A,   @DPTR
		MOV	REG, A
	ENDM

SaveREG MACRO   REG
		MOV	A,	REG
		MOVX	@DPTR,  A
	ENDM

; The PUSHA now emulates the pushing sequence what Keil C does.
PUSHR	MACRO
;		IRP	REG,	<ACC, B, DPX, DPH, DPL, DPX1, DPH1, DPL1, DPS, PSW, 0, 1, 2, 3, 4, 5, 6, 7> ;Code for two DPTR's
		;IRP	REG,	<ACC, B, DPX, DPH, DPL, PSW, 0, 1, 2, 3, 4, 5, 6, 7> ;Code for one DPTR ; Code for one DPTR
		IRP	REG,	<ACC, B, DPH, DPL, PSW, 0, 1, 2, 3, 4, 5, 6, 7> ;Code for one DPTR ; Code for one DPTR
		PUSH	REG
		ENDM
	ENDM

POPR	MACRO
;		IRP	REG,	<7, 6, 5, 4, 3, 2, 1, 0, PSW, DPS, DPL1, DPH1, DPX1, DPL, DPH, DPX, B, ACC> ;Code for two DPTR's
		;IRP	REG,	<7, 6, 5, 4, 3, 2, 1, 0, PSW, DPL, DPH, DPX, B, ACC> ;Code for one DPTR ; Code for one DPTR
		IRP	REG,	<7, 6, 5, 4, 3, 2, 1, 0, PSW, DPL, DPH, B, ACC> ;Code for one DPTR ; Code for one DPTR
		POP	REG
		ENDM
	ENDM

; Load context from the external stack pointed by C_XBP
	PUBLIC 	 LoadCtx
PR?LoadCtx      SEGMENT CODE
	RSEG	PR?LoadCtx
LoadCtx:

;  C_IBP=*C_XBP++;
	LoadXBP
	LoadREG	?C_IBP
	INC  	DPTR
;  I_BP=C_IBP;
	MOV  	R0,A
;  while(I_BP)
//	MOV  	A,I_BP
	JZ   	LC_1
;  	{
;  	*I_BP++=*C_XBP++;
LC_0:
	LoadREG @R0
	INC  	DPTR
	INC  	R0
	MOV 	A,R0
	JNZ		LC_0
LC_1:
;  SP=*C_XBP++;
	LoadREG SP
	INC DPTR
;  I_BP=SP;
	MOV  	R0,A 
	XRL		A,#LOW(STACK_START-2) 
	JZ		LC_3
LC_2:
;  while(I_BP!=STACK_BOTTOM)			
;	MOV  	A,I_BP
	;CJNE	R0,#LOW(STACK_START-1),LC_3
;  	{
;  	*I_BP--=*C_XBP++;
	LoadREG  	@R0
	INC 	DPTR
	DEC 	R0
;  	}
	CJNE	R0,#LOW(STACK_START-2),LC_2
;  }
LC_3:
	;CJNE    R0, #LOW (_?STACK_START-1), LC_1		;
	SaveXBP					; after the hardware stack has been popped,
						; the external stack pointer should be adjusted

RestoreCtx:
WANTFASTER	EQU	1
$IF	WANTFASTER
	POP	PSW				; A little bit dangerous but it works. C is PSW.7 and EA is IE.7
	MOV	EA, C				; They are at the same bit location of a byte.
$ELSE
	POP	ACC				; Safe way to do the same thing.
	RLC	A				;
	MOV	EA, C				;
$ENDIF
						; Now that the context has been loaded into hardware
 	POPR					; stack, what we need do is just popping them upto registers.
						;

	RET					; Now everything is ready, a RET will bring the task to run.

; Task level context switch entry point, which is intended to be called by task gracefully. 
_?OSCtxSw:
	PUSHR					; Save current context first into hardware stack
	PUSH	IE

_?KCOSCtxSw:					; Now begin pushing hardware stack to external one
	LoadXBP
	;   C_XBP=(unsigned int)C_XBP-((SP-STACK_BOTTOM)-(unsigned char)C_IBP+1+1);
	MOV  	A,SP
	CLR		C
	SUBB	A,#LOW(STACK_START-2)
	CLR		C
	SUBB	A,?C_IBP
	INC		ACC			;for SP
	INC		ACC			;for C_IBP
	XCH		A,DPL
	CLR		C
	SUBB	A,DPL
	XCH		A,DPL
	CLR 	A
	XCH		A,DPH
	SUBB	A,DPH
	XCH		A,DPH
	SaveXBP
;   *(C_XBP++)=(unsigned char)C_IBP;  
	SaveREG ?C_IBP
	INC		DPTR	
;   while(C_IBP)
	MOV		R0,?C_IBP
	MOV  	A,R0
	JZ   	C_S1
C_S0:
;  	{
;  	*(C_XBP++)=*(C_IBP++);pop(C_IBP)  //由于从相反方向填入堆栈,所以写入方式相反
	SaveREG @R0
	INC  	R0
	INC		DPTR
	MOV  	A,R0
	JZ   	C_S1
	SJMP	C_S0
;  	}
;   *(C_XBP++)=SP; 
C_S1:	
	SaveREG SP
	INC		DPTR 
	MOV		R0,A
CS_2:
;   while(SP!=STACK_BOTTOM)
	XRL  	A,#LOW(STACK_START-2)
	JZ   	CS_4
;  	{
;  	*(C_XBP++)=*(unsigned char idata *)(SP--);
CS_3:			
	SaveREG @R0
	INC		DPTR
	DEC		R0
;  	}
	CJNE	R0,#LOW(STACK_START-2),CS_3
;  }
CS_4:
	LJMP	_?C_OSCtxSw			; 

	END

⌨️ 快捷键说明

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