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

📄 l51_bank.a51

📁 UPSD单片机的LCD显示器汉字驱动程序
💻 A51
字号:
;=============================================================================
; File:  L51_BANK.A51
; Date:  Sep 1994
;   By:  FL
; Modif:  20.01.96 - SWB
;         15.07.03 - FL
;=============================================================================
; This module is used by LX51 to execute CODE bank switches, and comes in two 
; parts.  The first part is the common bridge to user's routines located in
; extended (banked) address areas. This section may be altered to suit your 
; particular hardware needs.
;
; NOTE:  Only the macro named SWITCH_BANK is to be modified by the user!
;-----------------------------------------------------------------------------
;                  * * * Important * * *
; The bank switching mechanism can be used in two modes:
;    * The "standard mode" for bank switching uses the external stack 
;      of the COMPACT and LARGE models to store the 3 additional 
;      bytes needed for each inter-bank call.
;    * The PL/M mode pushes those 3 bytes on the internal stack
;
; Although the PL/M mode provides a faster bank switch time, most 
; applications running in banked mode are short of internal RAM. 
; Consequently the use of the standard mode is usually the best
; solution and is assumed in this module.
;
; To use the PL/M mode:
;    * "PLM" has to be defined (using the set/equ commands), or in the 
;      command line when assembling this file.  For example:
;           MA51  L51_BANK.A51 SET(PLM)
;    * Then "XOPT(PLM)" has to be in the command line when invoking
;      LX51.  For example:
;           LX51  func1.obj, func2.obj,... XOPT(PLM) ...
;
;=============================================================================
; NOTE :
;   if you do not use the PL/M mode and there is in your project some functions
; that have two generic pointers as first parameters, those parameters will be
; passed in R1-R2-R3 for the first one and R0-R4-R5 for the second one. Then if
; at least one call of those functions needs a bank switch, you have to
; uncomment the following line:
;               $SET(TWO_PARAMS_SIZE_3_INREG=1)
;   This will change the bank switching procedure to save R0 register.
;=============================================================================
$nodb
$nolines
$MOD51
NAME ?BANK?SWITCHING

; include Turbolite_hardware.h

;=============================================================================
; NOTE:  DO NOT change the name of these two segments.  They are required by
; the L51 bank mode management facility.
;-----------------------------------------------------------------------------

?BANK?SWITCH		SEGMENT 	CODE
?DT?BANK?SWITCH 	SEGMENT		DATA

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

EXTRN 		DATA(SPX)	;external stack pointer

;-----------------------------------------------------------------------------
;
; The following two public declarations are not required, but are useful
; for the simulator/debugger.
;
;-----------------------------------------------------------------------------
PUBLIC		__SWITCH__0
PUBLIC  		__SWITCH__1
PUBLIC		?B_CURRENTBANK


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


;=============================================================================
;
; This is the switching-macro.  This is normally the only place where 
; changes need to be made to permit adaptation to the switch logic of 
; the target system.
;
;-----------------------------------------------------------------------------
;NOTE - Code has been edited so that Ride will not keep changing it.

	SWITCH_BANK	macro

CSIOP_AD equ      7F00H    ; Edit to match PSDsoft CSIOP addr
RPAGE    equ      0E0H

mov      DPTR, #(CSIOP_AD+RPAGE)
mov      A, ?B_CURRENTBANK
movx     @DPTR,A

	endm
;-----------------------------------------------------------------------------
;
;
;=============================================================================
;
;
;=============================================================================

rseg ?DT?BANK?SWITCH
	?B_CURRENTBANK:	ds	 1

;=============================================================================
rseg ?BANK?SWITCH

	XCALL:		; common code to switch to destination bank.
$if (PLM)
		;=======================================================================
		; -------------------------- PLM mode ----------------------------------
		;=======================================================================
		; The RETURN address is pushed onto the hardware (internal) stack
		; Historically, this mode is called "PLM" because it has been developed
		; in 1989 for some programmers using the PLM programming language.  
		; It can be used with RC51 while the parameters of the destination 
		; function are NOT PUSHED! Indeed, this mode allows faster switches, but 
		; it modifies the stack frame.  
		; Note that the RC51 "printf" function cannot be called in PLM mode.  
		;=======================================================================
			; Save the current bank ID to restore it after returning from dest
			push	?B_CURRENTBANK
			xch   A,B
			mov	?B_CURRENTBANK,A	
			; Change the return address for RET_ADDR
			mov	A,#low(RET_ADDR)
			push	ACC
			mov	A,#high(RET_ADDR)
			push	ACC
			; Prepare the indirect JUMP (push lowPC, push HighPC, RET)
			push	DPL
			push	DPH
			;**************************************
			SWITCH_BANK		; switch to the new bank
			;**************************************
			mov   A,B		; original ACC content is restored. 
$else
		;=======================================================================
		; -------------------------- Standard mode -----------------------------
		;=======================================================================
		; The RETURN address is pushed onto the EXTERNAL stack. This mode keeps 
		; the integrity of the stack frame. However, it makes the switch slower. 
		;=======================================================================
		$if (TWO_PARAMS_SIZE_3_INREG)
				;-----------------------------------------------------------------
				; A very special case occurs when at least one destination function
				; has two 3-byte parameters in register (e.g. R1R2R3 and R0R4R5).
				; In such a situation, R0 must be saved temporarily in the external
				; stack.
				;-----------------------------------------------------------------
								; prepare the external stack to receive 4 bytes:
								; return address (2 bytes), current bank (1 byte)
								; and temporarily R0
                        inc     SPX
                        inc     SPX
                        inc     SPX
                        inc     SPX
                        mov     A, SPX
                        xch     A, R0
                        movx    @R0, A
                        dec     R0
                        dec     R0
                        dec     R0
                        ; Move the return address onto the external stack
                        pop     ACC
                        movx    @R0, A
                        inc     R0
                        ; Move the return address onto the external stack
                        pop     ACC
                        movx    @R0,A
                        mov     A,?B_CURRENTBANK
                        inc     R0
                        ; Save the current bank onto the external stack
                        movx    @R0,A
                        mov     ?B_CURRENTBANK,B

								; Change the return address for RET_ADDR
                        mov     A,#low(RET_ADDR)
                        push    ACC
                        mov     A,#high(RET_ADDR)
                        push    ACC
								; Prepare the indirect JUMP (push lowPC, push HighPC, RET)
								push	DPL
								push	DPH
								;**************************************
								SWITCH_BANK		; switch to the new bank
								;**************************************	
                        inc     R0
                        movx    A, @R0
                        ; restore R0 (possible parameter for dest)
                        mov     R0, A
                        dec     SPX
		; ===================================================================
		$else 	;Standard case using external stack
		; ===================================================================
								inc	SPX
								mov	R0,SPX
                        ; Move the return address onto the external stack
                        pop     ACC
								movx 	@R0,A			
								inc	R0
								inc	SPX
                        ; Move the return address onto the external stack
								pop	ACC
								movx 	@R0,A
                        ; Save the current bank onto the external stack
								mov	A,?B_CURRENTBANK
								inc	R0
								inc	SPX
								movx 	@R0,A
								; Set the NEW current bank
								mov	?B_CURRENTBANK,B
								; Change the return address for RET_ADDR
								mov	A,#low(RET_ADDR)
								push	ACC
								mov	A,#high(RET_ADDR)
								push	ACC
								; Prepare the indirect JUMP (push lowPC, push HighPC, RET)
								push	DPL
								push	DPH
								;**************************************
								SWITCH_BANK		; switch to the new bank
								;**************************************	
		$endif
$endif			
		; ===================================================================
		__SWITCH__0:		;INDIRECT JUMP to the DESTINATION
						ret	
		; ===================================================================
	RET_ADDR:		
		; we return HERE from the destination
		; We have to restore the original (source) bank before returning to
		; the original return address
		; ===================================================================
$if (PLM)
		; simply pop the source bank. 
		; Return address is already on the internal stack
			pop	?B_CURRENTBANK	; old bank is restored
		; ===================================================================
$else	; Move from the external stack bothe the current bank and the address.
		; ===================================================================
			mov	R0,SPX
			movx	A,@R0		; old bank is restored
			mov	?B_CURRENTBANK,A
			dec	R0
			movx	A,@R0
			push	ACC
			dec	R0
			movx	A,@R0
			push	ACC
			dec	R0
			mov	SPX,R0		
$endif
			;**************************************	
			SWITCH_BANK		; restore old area
			;**************************************
	__SWITCH__1 :	ret
		
;=============================================================================
;*;
;*; The following section is put here for reference and to satisfy the 
;*; curiosity of those who feel the need to "know".  The section below 
;*; describes the code generated by L51 for each bank ( XBANK# ) area 
;*; declared, and one FCTk$i for each public declaration in that area.
;*;
;=============================================================================
;*;     ;Bank 1		----------------
;*;     XBANK1 :        mov     B,#1            ;HC980702 no modification for PL/M ; Note: use MOV R0,#1 ; if PL/M
;*;			ajmp	XCALL
;*;			
;*;	FCT1$1:		mov	DPTR,#PROG1$1
;*;			ajmp 	XBANK1
;*;
;*;	FCT1$2:		mov	DPTR,#PROG1$2
;*;			ajmp 	XBANK1
;*;     .....
;*;
;*;     ;Bank 2		----------------
;*;     XBANK2 :        mov     B,#2            ;HC980702 no modification for PL/M ; Note: use MOV R0,#2 ; if PL/M
;*;			ajmp	XCALL
;*;			
;*;	FCT2$1:		mov	DPTR,#PROG2$1
;*;			ajmp 	XBANK2
;*;	......
;=============================================================================
;************************ Configuration Section *******************************
; If your debugger does not support the ".LIS" script file that describes the *
; list of the banks, you should fill the following section. If you are using  *
; the Raisonance RIDE debugger, you do not need to fill this section.         *
;******************************************************************************
?B_NBANKS       EQU     8        ; Define max. Number of Banks (8-16-32)      *
?B_MODE         EQU     0        ; 0 for Bank-Switching via 8051 Port         *
?B_CURB         EQU     P1       ; where is defined the current bank          *
?B_MASK         EQU     7        ; define the significant bits                *
?B_PORT         EQU     P1       ; default is P1                              *
?B_FIRSTBIT     EQU     0        ; for ex. if P1.2 is the first signific. bit *
?B_XDATAPORT    EQU     00H      ; default is XDATA Port Address 0FFFFH       *
?BANKSTART      EQU     0000H    ; where the banks start (default 00)         *
?BANKEND        EQU     0FFFFH   ; where the banks end  (default 0ffffh)      *
;******************************************************************************
PUBLIC  ?B_NBANKS, ?B_MODE, ?B_MASK , ?B_XDATAPORT 
PUBLIC  ?BANKSTART, ?BANKEND, ?B_CURB, ?B_FIRSTBIT, ?B_PORT
;******************************************************************************


end

⌨️ 快捷键说明

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