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

📄 ucos51a.asm

📁 8051的UCOS实时操作系统(源代码)
💻 ASM
字号:
; ===========================================================================
; $Id: ucos51a.asm,v 1.19 1997/07/18 12:34:47 gianpi Exp $
;
; Description:
;	uC/OS-51 - Assembler functions for 8051
;
; Author[s]:
;	Gianpaolo Macario	<gianpi@geocities.com>
;
; Language:
;	BSO-Tasking ASM51 v4.0r0
; ===========================================================================

$CASE

$INCLUDE(..\MODEL)
$INCLUDE(..\MONITOR)

	NAME    UCOS51A

	; Make LINK51 complain if memory models are mixed up
	EXTRN	CODE(%MODEL)	

	; Warning: the following extern must match
	; with ucos51c.h, ucos.h:
	;
	extrn   data(_OSTCBCur)
	extrn   data(_OSTCBHighRdy)
	extrn	code(_?OSIntEnter)
	extrn	code(_?OSIntExit)

?STACK  SEGMENT IDATA
        RSEG    ?STACK
OSStack:
        ds  	40h
OSStkStart	idata OSStack-1       ; TBD: Should use __STKSTART
        ;;extrn   idat(__STKSTART)

OSFRAMESIZE	equ 16

; -------------------------------------------------------------------------
; Macros
;
; Save current task context
;
%*DEFINE (SAVE_ALL)
(
	push	psw		
	push	acc
	push	b
	push	dpl
	push	dph
	mov	a,r0
	push	acc
	mov	a,r1
	push	acc
	mov	a,r2
	push	acc
	mov	a,r3
	push	acc
	mov	a,r4
	push	acc
	mov	a,r5
	push	acc
	mov	a,r6
	push	acc
	mov	a,r7
	push	acc
	push	sp
)

; Simulate lcall @revectab[vecnum]
;
%*DEFINE (LCALL_VEC(vecnum)) LOCAL here
(
	mov	dptr, #revectab + (2 * %vecnum)
	movx	a, @dptr
	xch	a, b
	inc	dptr
	movx	a, @dptr
	mov	dph, b
	mov	dpl, a
	mov	a, #low %here
	push	acc
	mov	a, #high %here
	push	acc
	clr	a
	jmp	@a+dptr
%here:
)

; Restore registers and exit
;
%*DEFINE (REST_ALL)
(
	pop 	acc		; SP: discard it
	pop 	acc		; R7
	mov 	r7, a
	pop 	acc		; R6
	mov	r6, a
	pop 	acc		; R5
	mov 	r5, a
	pop 	acc		; R4
	mov 	r4, a
	pop 	acc		; R3
	mov 	r3, a
	pop 	acc		; R2
	mov 	r2, a
	pop 	acc		; R1
	mov 	r1, a
	pop 	acc		; R0
	mov 	r0, a
	pop	dph
	pop	dpl
	pop 	b		; B
	pop 	acc		; ACC
	pop 	psw		; PSW
)

%*DEFINE (UCOS51_ISR(vecnum, label))
(
	public	%label
%label:
	%SAVE_ALL
	lcall	_?OSIntEnter
	%LCALL_VEC(%vecnum)
	lcall	_?OSIntExit
	ljmp	popall3	
)

; -------------------------------------------------------------------------
; Start Multitasking
;
; 	void OSStartHighRdy(void)

UCOS51A_OSSTARTHIGHRDY_PR   SEGMENT CODE
	RSEG    UCOS51A_OSSTARTHIGHRDY_PR
	public  _?OSStartHighRdy

_?OSStartHighRdy:
	mov 	dph, _OSTCBHighRdy+0	; Get highest prio. task
	mov 	dpl, _OSTCBHighRdy+1	

	mov 	_OSTCBCur+0, dph	; OSTCBCur = OSTCBHighRdy
	mov 	_OSTCBCur+1, dpl

	movx	a, @dptr		; stk = OSTCBCur->StkPtr
	mov	r0, a
	inc	dptr
	movx	a, @dptr
	mov	r1, a			; R0,1 = stk

	mov	dph, r0
	mov	dpl, r1
	movx	a, @dptr		; Get User Stack Ptr (*stk)

	add 	a, #OSFRAMESIZE
	mov 	r5, a			; R5 = #bytes to copy
	mov 	r4, a			; R4 = count

	mov 	a, dpl
	clr	c
	subb 	a, r5
	mov 	r3, a
	mov 	a, dph
	subb 	a, #0
	mov 	r2, a			; R2,R3 = srcptr - 1

	mov	dph, r2
	mov	dpl, r3			; DPTR = srcptr - 1

	; Copy R5 bytes from *stk to OSStack

	mov     a, #OSStkStart       ; R1 = destptr - 1
	mov 	R1, a

copystk1:
	inc 	dptr
	inc 	R1
	movx 	a, @dptr
	mov 	@R1, a
	djnz 	R4, copystk1

	; Now R1 is the new task SP
	mov 	sp, r1

	; Pop all user register from task stack
popall:
	%REST_ALL
	setb	ea		; Enable interrupts again
	ret			; PCH,PCL (DBG: was reti!)

; -------------------------------------------------------------------------
; Perform a context switch (from task level)
;
;	void OSCtxSw(void)

UCOS51A_OSCTXSW_PR   SEGMENT CODE
	RSEG    UCOS51A_OSCTXSW_PR
	public  _?OSCtxSw

_?OSCtxSw:
	%SAVE_ALL

	mov 	dph, _OSTCBCur+0	; Save stack ptr in TCB
	mov 	dpl, _OSTCBCur+1

	movx	a, @dptr		; stk = OSTCBCur->StkPtr
	mov	r0, a
	inc	dptr
	movx	a, @dptr
	mov	r1, a			; R0,1 = stk (40B2)

	mov	dph, r0
	mov	dpl, r1
	movx	a, @dptr		; ? 3A

	add	a, #OSFRAMESIZE		; ? 04 + 10 = 14
	mov	r2, a			; R2 = *stk - #OSSTACK + #OSFRAMESIZE

	mov	a, r1
	clr	c
	subb	a, r2
	mov	dpl, a
	mov	a, r0
	subb	a, #0
	mov	dph, a			; ? DPTR = 409E
	
	; DPTR now points to the beginning of the user stack-1

	mov	a, sp
	clr	c
    	subb    a, #OSStkStart
	mov	r5, a			; R5 = #bytes to copy
	mov	r4, a			; R4 = count

	; Copy R5 bytes from OSStack to stk
	mov a, #OSStkStart
	mov	R1, a			; R1= #OSStack - 1

savestk2:
	inc	r1
	inc	dptr
	mov	a, @r1
	movx	@dptr, a
	djnz	R4, savestk2
	;
	mov	a, r1
	clr	c
	subb	a, #OSStkStart
	clr	c
	subb	a, #OSFRAMESIZE
	;
	movx	@dptr, a		; Fix SP in user stack
	mov	r0, dph			; R0,1 = stk
	mov	r1, dpl
	;
	mov	dph, _OSTCBCur+0	; OSTCBCur->OSTCBStkPtr = stk
	mov	dpl, _OSTCBCur+1
	mov	a, r0
	movx	@dptr, a
	inc	dptr
	mov	a, r1
	movx	@dptr, a
	
	; Point to HI Prio. Task Rdy
	;
	ljmp    _?OSStartHighRdy

; -------------------------------------------------------------------------
; Perform a context switch (from an ISR)
;
;	void OSIntCtxSw(void)

UCOS51A_OSINTCTXSW_PR   SEGMENT CODE
	RSEG    UCOS51A_OSINTCTXSW_PR
	public  _?OSIntCtxSw

_?OSIntCtxSw:
	; Ignore data in stack:
	;   - call to OSIntExit  (2 bytes)
	;   - call to OSIntCtxSw (2 bytes)
	;   - locals		 (0 bytes)
	mov	a, sp
	clr	c
	subb	a, #4
	mov	sp, a
	;
OSStHRr2:				; Modeled after OSStartHighRdy
	mov 	dph, _OSTCBHighRdy+0	; Get highest prio. task
	mov 	dpl, _OSTCBHighRdy+1	

	mov 	_OSTCBCur+0, dph	; OSTCBCur = OSTCBHighRdy
	mov 	_OSTCBCur+1, dpl

	movx	a, @dptr		; stk = OSTCBCur->StkPtr
	mov	r0, a
	inc	dptr
	movx	a, @dptr
	mov	r1, a			; R0,1 = stk

	mov	dph, r0
	mov	dpl, r1
	movx	a, @dptr		; Get User Stack Ptr (*stk)

	add 	a, #OSFRAMESIZE
	mov 	r5, a			; R5 = #bytes to copy
	mov 	r4, a			; R4 = count

	mov 	a, dpl
	clr	c
	subb 	a, r5
	mov 	r3, a
	mov 	a, dph
	subb 	a, #0
	mov 	r2, a			; R2,R3 = srcptr - 1

	mov	dph, r2
	mov	dpl, r3			; DPTR = srcptr - 1

	; Copy R5 bytes from *stk to OSStack
	mov     a, #OSStkStart       ; R1 = destptr - 1
	mov 	R1, a

copystk2:
	inc 	dptr
	inc 	R1
	movx 	a, @dptr
	mov 	@R1, a
	djnz 	R4, copystk2

	; Now R1 is the new task SP
	mov 	sp, r1

	; Pop all user register from task stack
popall3:
	%REST_ALL
	setb	ea		; Enable interrupts again (?)
	reti			; PCH,PCL

; -------------------------------------------------------------------------
; Revector Hardware Interrupts
;
%IF( %EQS(%PAULMON,RAM) ) THEN (
INTVECT_LOC	EQU	8000h		; PAULMON-RAM
) ELSE (
	%IF( %EQS(%PAULMON,ROM)) THEN (
INTVECT_LOC	EQU	0000h		; PAULMON-ROM
	) ELSE (
INTVECT_LOC	EQU	0000h		; Application without monitor
	) FI
) FI

	CSEG	AT INTVECT_LOC+0003h	; IE0
	ljmp	__CIH00

	CSEG	AT INTVECT_LOC+000Bh	; TF0
	ljmp	__CIH01

	; CSEG	AT INTVECT_LOC+0013h	; IE1
	; ljmp	__CIH02

	; CSEG	AT INTVECT_LOC+001Bh	; TF1
	; ljmp	__CIH03

	CSEG	AT INTVECT_LOC+0023h	; RI_TI
	ljmp	__CIH04

	; CSEG	AT INTVECT_LOC+002Bh	; UNK5
	; ljmp	__CIH05

	; CSEG	AT INTVECT_LOC+0033h	; UNK6
	; ljmp	__CIH06

	; CSEG	AT INTVECT_LOC+003Bh	; UNK7
	; ljmp	__CIH07

; -------------------------------------------------------------------------
; Interrupt Service Routines

UCOS51A_ISR_PR	SEGMENT CODE
	RSEG	UCOS51A_ISR_PR

	; Interrupt 0 (INT_IE0) Service Routine
	%UCOS51_ISR(0, __CIH00)

	; Interrupt 1 (INT_TF0) Service Routine
	%UCOS51_ISR(1, __CIH01)

	; Interrupt 2 (INT_IE1) Service Routine
	%UCOS51_ISR(2, __CIH02)

	; Interrupt 3 (INT_TF1) Service Routine
	%UCOS51_ISR(3, __CIH03)

	; Interrupt 4 (INT_RI_TI) Service Routine
	%UCOS51_ISR(4, __CIH04)

	; Interrupt 5 (INT_UNK5) Service Routine
	%UCOS51_ISR(5, __CIH05)

	; Interrupt 6 (INT_UNK6) Service Routine
	%UCOS51_ISR(6, __CIH06)

	; Interrupt 7 (INT_UNK7) Service Routine
	%UCOS51_ISR(7, __CIH07)

; -------------------------------------------------------------------------
; Table of vectors in RAM
;
UCOS51A_XD   SEGMENT XDATA
	RSEG    UCOS51A_XD

revectab:
	ds	2	; vector of CIH00
	ds	2	; vector of CIH01
	ds	2	; vector of CIH02
	ds	2	; vector of CIH03
	ds	2	; vector of CIH04
	ds	2	; vector of CIH05
	ds	2	; vector of CIH07

; -------------------------------------------------------------------------
; Return current interrupt vector
;
; C prototype:
;	FUNC_PTR getvect(u_int8_t vecnum)
;
UCOS51A_GETVECT_PR   SEGMENT CODE
	RSEG    UCOS51A_GETVECT_PR
	public	_?getvect

_?getvect:
	mov	a, r7		; get vecnum
	anl	a, #07h		; just make sure
	rl	a		; multiply by 2

	mov	dph, #high revectab
	mov	dpl, #low  revectab

	add	a, dpl
	mov	dpl, a
	mov	a, dph
	addc	a, #0
	mov	dph, a		; dptr = #revectab + (2 * vecnum)

	movx	a, @dptr
	mov	r6, a		; High(result)
	inc	dptr
	movx	a, @dptr
	mov	r7, a		; Low(result)
	ret

; -------------------------------------------------------------------------
; Change interrupt vector
;
; C prototype:
;	void setvect(u_int8_t vecnum, FUNC_PTR newfunc)
;
UCOS51A_SETVECT_PR   SEGMENT CODE
	RSEG    UCOS51A_SETVECT_PR
	public	_?setvect

_?setvect:
	mov	a, r7		; get vecnum
	anl	a, #07h		; just make sure
	rl	a		; multiply by 2

	mov	dph, #high revectab
	mov	dpl, #low  revectab

	add	a, dpl
	mov	dpl, a
	mov	a, dph
	addc	a, #0
	mov	dph, a		; dptr = #revectab + (2 * vecnum)

	mov	a, r4		; High(newfunc)
	movx	@dptr, a
	inc	dptr
	mov	a, r5		; Low(newfunc)
	movx	@dptr, a
	ret

; -------------------------------------------------------------------------

; end of program

	end

⌨️ 快捷键说明

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