www.pudn.com > MP3DIY.rar > L51_BANK.A51
$NOMOD51 NOLINES
$NOCOND
;------------------------------------------------------------------------------
; This file is part of the BL51 / L251 Banked Linker/Locater package
; Copyright (c) 1988-1999 Keil Elektronik GmbH and Keil Software, Inc.
; Version 2.0 (Code and Variable Banking for 8051 based Derivatives)
;------------------------------------------------------------------------------
;************************ Configuration Section *******************************
?B_NBANKS EQU 16 ; Define max. Number of Banks *
; ; The following values are allowed: 2, 4, 8, 16, 32 *
; ; the max. value for ?B_BANKS is 32 *
; *
?B_MODE EQU 0 ; 0 for Bank-Switching via 8051 Port *
; ; 1 for Bank-Switching via XDATA Port *
; ; 4 for user-provided bank switch code *
; *
?B_RTX EQU 0 ; 0 for applications without RTX-51 FULL *
; ; 1 for applications using RTX-51 FULL *
; *
?B_VAR_BANKING EQU 0 ; Enable Variable Banking in XDATA and CODE memory *
; ; 0 Variable Banking is disabled *
; ; 1 XDATA and CODE banking with same address lines *
; ; 2 XDATA uses a different banking port *
; *
IF ?B_VAR_BANKING <> 0; *
;-----------------------------------------------------------------------------*
; if ?B_VAR_BANKING is enabled define the following values *
; *
?B_COMMON_XRAM EQU 0 ; Specify if your hardware has uses XDATA RAM *
; ; 0 no common RAM: complete 64KB XDATA is banked *
; ; 1 all XDATA variables are located to common RAM *
; *
?B_INTR_ACCESS EQU 0 ; 0 unlimited access to XDATA memory in interrupts *
; ; 1 interupts access to XDATA variables is allowed *
; ; after call to ToDo *
; *
;-----------------------------------------------------------------------------*
ENDIF; *
; *
IF ?B_MODE = 0; *
;-----------------------------------------------------------------------------*
; if ?BANK?MODE is 0 define the following values *
; For Bank-Switching via 8051 Port define Port Address / Bits *
; *
ROMPAGE DATA 9AH ; I/O Port Address *
; *
?B_PORT EQU ROMPAGE ; default is P1 *
?B_FIRSTBIT EQU 0 ; default is Bit 0 *
;-----------------------------------------------------------------------------*
ENDIF; *
; *
IF ?B_MODE = 1; *
;-----------------------------------------------------------------------------*
; if ?BANK?MODE is 1 define the following values *
; For Bank-Switching via XDATA Port define XDATA Port Address / Bits *
?B_XDATAPORT EQU 0FFFFH ; default is XDATA Port Address 0FFFFH *
?B_FIRSTBIT EQU 0 ; default is Bit 0 *
;-----------------------------------------------------------------------------*
ENDIF; *
; *
IF ?B_MODE = 4; *
;-----------------------------------------------------------------------------*
; if ?BANK?MODE is 4 define the following switch macros *
; For bank switching via user-provided bank switch code you must define for *
; each memory bank a own macro which contains the bank switch code. The *
; following example shows how to use the I/O lines P1.4 and P1.7 for bank *
; switching. Since you can select just 4 banks with two address lines, just *
; four macros are defined. The number of macros must conform with the number *
; ?B_NBANKS number, i.e. for an application with 16 memory banks you must *
; define 16 macros. *
; *
; IMPORTANT NOTE: each SWITCH macro must generate the same code size, *
; otherwise the BANKSWITCH code does not work correctly. *
; *
P1 DATA 90H ; I/O Port Address *
; *
SWITCH0 MACRO ; Switch to Memory Bank #0 *
CLR P1.4 ; Clear Port 1 Bit 4 *
CLR P1.7 ; Clear Port 1 Bit 7 *
ENDM *
; *
SWITCH1 MACRO ; Switch to Memory Bank #0 *
SETB P1.4 ; Set Port 1 Bit 4 *
CLR P1.7 ; Clear Port 1 Bit 7 *
ENDM *
; *
SWITCH2 MACRO ; Switch to Memory Bank #0 *
CLR P1.4 ; Clear Port 1 Bit 4 *
SETB P1.7 ; Set Port 1 Bit 7 *
ENDM *
; *
SWITCH3 MACRO ; Switch to Memory Bank #0 *
SETB P1.4 ; Set Port 1 Bit 4 *
SETB P1.7 ; Set Port 1 Bit 7 *
ENDM *
; *
;-----------------------------------------------------------------------------*
ENDIF; *
; *
;******************************************************************************
; *
; THEORY OF OPERATION *
; ------------------- *
; The section below describes the code generated by BL51 or L251 and the *
; operation of the L51_BANK.A51 module. BL51/L251 generates for each *
; function that is located in a code memory bank and called from the common *
; area or a different code bank and entry into the INTRABANK CALL TABLE. The *
; INTRABANK CALL TABLE is located in the SEGMENT ?BANK?SELECT and listed in *
; the Linker MAP file. The entries in that TABLE have the following format: *
; *
; ?FCT?1: MOV DPTR,#FCT ; Load Address of target FCT *
; JMP ?B_BANKn ; Switch to Bank and Jump to Target Code *
; *
; Instead of directly calling the function FCT, the Linker changes the entry *
; to ?FCT?1. This entry selects the bank where the function FCT is located *
; and calls that function via the routines defined in this L51_BANK.A51 file. *
; The L51_BANK.A51 file contains two sets of functions for each bank: *
; *
; ?B_BANKn is a routine which saves the entry of the ?B_SWITCHn function *
; for the current active bank on the STACK and switches to the *
; bank 'n'. Then it jumps to the address specified by the DPTR *
; register. It is allowed to modify the following registers in *
; the ?B_BANKn routine: A, B, R0, DPTR, PSW *
; *
; ?B_SWITCHn is a function which selects the bank 'n'. This function is *
; used at the end of a user function to return to the calling *
; code bank. Only the following registers may be altered in the *
; ?B_SWITCHn function: R0, DPTR *
; *
; The current active bank is stored in ?B_CURRENTBANK. RTX-51 uses this *
; variable to restore the code bank after a task switch. To get correct *
; results, ?B_CURRENTBANK must be set to the code bank before the hardware *
; switch is done, or the code banking sequences must be interrupt protected. *
;******************************************************************************
NAME ?BANK?SWITCHING
PUBLIC ?B_NBANKS, ?B_MODE, ?B_CURRENTBANK, ?B_MASK
PUBLIC ?B_FACTOR
; Standard SFR Symbols required in L51_BANK.A51
ACC DATA 0E0H
B DATA 0F0H
DPL DATA 82H
DPH DATA 83H
; generate Mask and Bank Number Information
IF ?B_NBANKS <= 2
MASK EQU 00000001B
ELSEIF ?B_NBANKS <= 4
MASK EQU 00000011B
ELSEIF ?B_NBANKS <= 8
MASK EQU 00000111B
ELSEIF ?B_NBANKS <= 16
MASK EQU 00001111B
ELSE
MASK EQU 00011111B
ENDIF
IF ?B_MODE = 0 ;**************************************************************
?B_FACTOR EQU 1 SHL ?B_FIRSTBIT
?B_MASK EQU MASK SHL ?B_FIRSTBIT
BANKN MACRO N
BANK&N EQU N SHL ?B_FIRSTBIT
ENDM
CNT SET 0
REPT ?B_NBANKS
BANKN %CNT
CNT SET CNT+1
ENDM
?B_CURRENTBANK EQU ?B_PORT
; Convert Bank No in Accu to Address * 8
IF ?B_FIRSTBIT = 0
CONVBANKNO MACRO
SWAP A
RR A
ENDM
ENDIF
IF ?B_FIRSTBIT = 1
CONVBANKNO MACRO
RL A
RL A
ENDM
ENDIF
IF ?B_FIRSTBIT = 2
CONVBANKNO MACRO
RL A
ENDM
ENDIF
IF ?B_FIRSTBIT = 3
CONVBANKNO MACRO
ENDM
ENDIF
IF ?B_FIRSTBIT = 4
CONVBANKNO MACRO
RR A
ENDM
ENDIF
IF ?B_FIRSTBIT = 5
CONVBANKNO MACRO
RR A
RR A
ENDM
ENDIF
IF ?B_FIRSTBIT = 6
CONVBANKNO MACRO
SWAP A
RL A
ENDM
ENDIF
IF ?B_FIRSTBIT = 7
CONVBANKNO MACRO
SWAP A
ENDM
ENDIF
SELECT MACRO N
LOCAL XLABEL, YLABEL
PUBLIC ?B_BANK&N
?B_BANK&N:
MOV A,?B_CURRENTBANK
ANL A,#?B_MASK
;; CJNE A,#BANK&N,XLABEL
;; CLR A
;; JMP @A+DPTR
;;
;;XLABEL:
CONVBANKNO ; Convert Bank Number to Address
PUSH ACC
MOV A,#HIGH ?BANK?SWITCH
PUSH ACC
;;YLABEL:
PUSH DPL
PUSH DPH
LJMP ?B_SWITCH&N
ENDM
?BANK?SELECT SEGMENT CODE
RSEG ?BANK?SELECT
CNT SET 0
REPT ?B_NBANKS
SELECT %CNT
CNT SET CNT+1
ENDM
SWITCH MACRO N
ORG N * 8
PUBLIC ?B_SWITCH&N
?B_SWITCH&N:
IF ?B_RTX = 0
IF N <> 0
ORL ?B_CURRENTBANK,#?B_MASK
ENDIF
IF N <> (?B_NBANKS-1)
ANL ?B_CURRENTBANK,#(BANK&N OR NOT ?B_MASK)
ENDIF
RET
ELSE
IF N = 0
ANL ?B_CURRENTBANK,#(BANK&N OR NOT ?B_MASK)
ELSEIF N <> (?B_NBANKS-1)
MOV R0,A
MOV A,#(BANK&N OR NOT ?B_MASK)
LJMP SWITCHBNK
ELSE
ORL ?B_CURRENTBANK,#?B_MASK
RET
ENDIF
ENDIF
ENDM
?BANK?SWITCH SEGMENT CODE PAGE
RSEG ?BANK?SWITCH
CNT SET 0
REPT ?B_NBANKS
SWITCH %CNT
CNT SET CNT+1
ENDM
IF ?B_RTX = 1
SWITCHBNK: PUSH IE
CLR EA
ORL ?B_CURRENTBANK, #?B_MASK
ANL ?B_CURRENTBANK, A
POP IE
MOV A,R0
RET
ENDIF
ENDIF ; close block IF ?B_MODE = 0 *******************************************
IF ?B_MODE = 1 ;***************************************************************
?B_FACTOR EQU 1 SHL ?B_FIRSTBIT
?B_MASK EQU MASK SHL ?B_FIRSTBIT
BANKN MACRO N
BANK&N EQU N SHL ?B_FIRSTBIT
ENDM
CNT SET 0
REPT ?B_NBANKS
BANKN %CNT
CNT SET CNT+1
ENDM
?C_INITSEG SEGMENT CODE ; Segment for Variable Initialization
RSEG ?C_INITSEG
DB 01H ; IData
DB ?B_CURRENTBANK ; Init Current Bank
DB 0 ; Set to Zero
DB 41H ; XData
DW ?B_XDATAPORT ; Init XDATA Port
DB 0 ; Set to Zero
PUBLIC ?B_XDATAPORT
?BANK?DATA SEGMENT DATA
RSEG ?BANK?DATA
?B_CURRENTBANK: DS 1
IF ?B_RTX = 1 OR ?B_NBANKS > 16
; Convert Bank No in Accu to Address * 8
IF ?B_FIRSTBIT = 0
CONVBANKNO MACRO
SWAP A
RR A
ENDM
ENDIF
IF ?B_FIRSTBIT = 1
CONVBANKNO MACRO
RL A
RL A
ENDM
ENDIF
IF ?B_FIRSTBIT = 2
CONVBANKNO MACRO
RL A
ENDM
ENDIF
IF ?B_FIRSTBIT = 3
CONVBANKNO MACRO
ENDM
ENDIF
IF ?B_FIRSTBIT = 4
CONVBANKNO MACRO
RR A
ENDM
ENDIF
IF ?B_FIRSTBIT = 5
CONVBANKNO MACRO
RR A
RR A
ENDM
ENDIF
IF ?B_FIRSTBIT = 6
CONVBANKNO MACRO
SWAP A
RL A
ENDM
ENDIF
IF ?B_FIRSTBIT = 7
CONVBANKNO MACRO
SWAP A
ENDM
ENDIF
ENDIF
IF ?B_RTX = 0 AND ?B_NBANKS <= 16
; Convert Bank No in Accu to Address * 16
IF ?B_FIRSTBIT = 0
CONVBANKNO MACRO
SWAP A
ENDM
ENDIF
IF ?B_FIRSTBIT = 1
CONVBANKNO MACRO
SWAP A
RR A
ENDM
ENDIF
IF ?B_FIRSTBIT = 2
CONVBANKNO MACRO
RL A
RL A
ENDM
ENDIF
IF ?B_FIRSTBIT = 3
CONVBANKNO MACRO
RL A
ENDM
ENDIF
IF ?B_FIRSTBIT = 4
CONVBANKNO MACRO
ENDM
ENDIF
IF ?B_FIRSTBIT = 5
CONVBANKNO MACRO
RR A
ENDM
ENDIF
IF ?B_FIRSTBIT = 6
CONVBANKNO MACRO
RR A
RR A
ENDM
ENDIF
IF ?B_FIRSTBIT = 7
CONVBANKNO MACRO
SWAP A
RL A
ENDM
ENDIF
ENDIF
SELECT MACRO N
LOCAL XLABEL, YLABEL
PUBLIC ?B_BANK&N
?B_BANK&N:
MOV A,?B_CURRENTBANK
ANL A,#?B_MASK
;; CJNE A,#BANK&N,XLABEL
;; SJMP YLABEL
;;XLABEL:
CONVBANKNO ; Convert Bank Number to Address
PUSH ACC
MOV A,#HIGH ?BANK?SWITCH
PUSH ACC
;;YLABEL:
PUSH DPL
PUSH DPH
LJMP ?B_SWITCH&N
ENDM
?BANK?SELECT SEGMENT CODE
RSEG ?BANK?SELECT
CNT SET 0
REPT ?B_NBANKS
SELECT %CNT
CNT SET CNT+1
ENDM
SWITCH MACRO N
IF ?B_RTX = 0 AND ?B_NBANKS <= 16
ORG N * 16
PUBLIC ?B_SWITCH&N
?B_SWITCH&N:
MOV R0,A
MOV A,#BANK&N
MOV DPTR,#?B_XDATAPORT
MOV ?B_CURRENTBANK,A
MOVX @DPTR,A
MOV A,R0
RET
ENDIF
IF ?B_RTX = 1 OR ?B_NBANKS > 16
ORG N * 8
PUBLIC ?B_SWITCH&N
?B_SWITCH&N:
MOV R0,A
MOV A,#BANK&N
LJMP SWITCHNOW
ENDIF
ENDM
?BANK?SWITCH SEGMENT CODE PAGE
RSEG ?BANK?SWITCH
CNT SET 0
REPT ?B_NBANKS
SWITCH %CNT
CNT SET CNT+1
ENDM
IF ?B_RTX = 1 OR ?B_NBANKS > 16
SWITCHNOW: MOV DPTR,#?B_XDATAPORT
IF ?B_RTX = 0
MOV ?B_CURRENTBANK,A
MOVX @DPTR,A
ELSE
;;; PUSH IE
;;; CLR EA
MOV ?B_CURRENTBANK,A
MOVX @DPTR,A
;;; POP IE
ENDIF
MOV A,R0
RET
ENDIF
ENDIF ; close block IF ?B_MODE = 1 *******************************************
IF ?B_MODE = 4 ;**************************************************************
?B_FACTOR EQU 0 ; Dummy Declarations
?B_FIRSTBIT EQU 0
?B_MASK EQU MASK
?BANK?DATA SEGMENT DATA
RSEG ?BANK?DATA
?B_CURRENTBANK: DS 1
BANK MACRO N
PUBLIC ?B_BANK&N
?B_BANK&N:
PUSH ?B_CURRENTBANK
MOV A,#HIGH ?BANK?SWITCH
PUSH ACC
PUSH DPL
PUSH DPH
ENDM
SWITCH MACRO N
PUBLIC ?B_SWITCH&N
?B_SWITCH&N:
MOV ?B_CURRENTBANK,#LOW ?B_SWITCH&N
SWITCH&N
RET
ENDM
?BANK?SWITCH SEGMENT CODE PAGE
RSEG ?BANK?SWITCH
; Generate ?B_SWITCHn functions
CNT SET 0
REPT ?B_NBANKS
BANK %CNT
SWITCH %CNT
CNT SET CNT+1
ENDM
IF (HIGH ?BANK?SWITCH) <> (HIGH $)
ERROR BANK SWITCH CODE EXCEEDS 256 BYTES
ENDIF
;---- Initialization of ?B_CURRENTBANK and execution of SWITCH0:
?C_C51STARTUP?1 SEGMENT CODE
RSEG ?C_C51STARTUP?1
CLR A
MOV ?B_CURRENTBANK,A ; Init Current Bank
SWITCH0 ; Execute SWITCH0 Macro
COMMON_XDATA MACRO ; Switch back to common XDATA bank
SWITCH1 ; Switch to XDATA Bank 1
ENDM
ENDIF ; close block IF ?B_MODE = 4 *******************************************
RSEG ?BANK?SELECT
;************************ SWITCHBANK FUNCTION *******************************
; *
; SWITCHBANK allows use of bank-switching for C programs *
; *
; prototype: extern switchbank (unsigned char bank_number); *
; *
;******************************************************************************
PUBLIC _SWITCHBANK
_SWITCHBANK: MOV A,R7
IF ?B_VAR_BANKING <> 0 ;******************************************************
SJMP _SWITCHBANK_A
PUBLIC ?C_VBANKING
PUBLIC ?B_VAR_BANKING
PUBLIC ?B_COMMON_XRAM
PUBLIC ?B_INTR_ACCESS
C_VBANKING:
IF ?B_COMMON_XRAM = 0
IF ?B_INTR_ACCESS = 0
JBC EA,ENA_Intr ; Check EA and disable interrupts
CALL SWITCH_VBANK ; Switch to XDATA bank and make access
COMMON_XDATA ; Switch back to common XDATA bank
RET
ENA_Intr: CALL SWITCH_VBANK ; Switch to XDATA bank and make access
COMMON_XDATA ; Switch back to common XDATA bank
BSET EA ; If EA was 1 enable interrupts again
RET
ELSE
CALL SWITCH_VBANK ; Switch to XDATA bank and make access
COMMON_XDATA ; Switch back to common XDATA bank
RET
ENDIF
ENDIF
SWITCH_VBANK: PUSH DPL
PUSH DPH
PUSH ACC
MOV A,R3
IF ?B_VARBANKING = 2
JB ACC.7,CONST_BANKING
ENDIF
CONST_BANKING: ANL A,#MASK
ENDIF ; close block IF ?B_VAR_BANKING <> 0 ***********************************
IF ?B_MODE = 0 ;**************************************************************
_SWITCHBANK_A: SWAP A
RR A
MOV DPTR,#?BANK?SWITCH
JMP @A+DPTR
ENDIF ; close block IF ?B_MODE = 0 *******************************************
IF ?B_MODE = 1 ;***************************************************************
_SWITCHBANK_A:
IF ?B_NBANKS > 16 OR ?B_RTX = 1
SWAP A
RR A
ENDIF
IF ?B_NBANKS <= 16 AND ?B_RTX = 0
SWAP A
ENDIF
MOV DPTR,#?BANK?SWITCH
JMP @A+DPTR
ENDIF ; close block IF ?B_MODE = 1 *******************************************
IF ?B_MODE = 4 ;**************************************************************
S_ENTRY MACRO N
DB ?B_SWITCH&N
ENDM
_SWITCHBANK_A:
ADD A,#switch_tab+3-$
MOVC A,@A+PC
MOV DPTR,#?BANK?SWITCH
JMP @A+DPTR
switch_tab:
CNT SET 0
REPT ?B_NBANKS
S_ENTRY %CNT
CNT SET CNT+1
ENDM
ENDIF ; close block IF ?B_MODE = 4 *******************************************
END