1
工程设置
Device项设置:
Target项的设置:
Output项的设置:
Listing项的设置:
User项的设置:
C51项的设置:
A51项的设置:
BL51 Locate项的设置:
BL51 Misc项的设置:
Debug项的设置:
Utilities项的设置:
2 L51_BANK.A51文件设置
使用新华龙提供的代码分页例程的L51_BANK.A51文件,具体内容详见附录1—
—《L51_BANK.A51》;
其使用的是用户自定义的分页方式,即B_MODE 为4。
3 代码分组设置
工程建立好之后,新建4个分组,分别是Common、Bank1、Bank2、Bank3,或
者取其他的名字,但是要能使自己明白和记住那些程序是放在哪个程序块里的就可以。
Common组的选项设置:
其他的分项C51和A51默认即可!
Bank1组的选项设置:
其他的组Bank2和Bank3以此类推。
4 详细代码加载设置
首先将一些重要的驱动和启动文件放到Common组,即Bank0块内,注意不能使
该组编译后的代码超过32K。
注意:必须要将L51_BANK.A51和STARTUP.A51文件,以及Main.c文件加入该块!
其他文件加载到不同的Bank块内,也需要注意不能使该组编译后的代码超过32K。
加载完程序后,对项目工程进行编译:
会产生3个编译文件,分别是.B01、.B02、.B03。
此时,打开系统工程目录下的List文件夹下的.M51文件,找到
“* * * * * * * C O D E M E M O R Y * * * * * * *”段的内容,如果该段的起始内容是如下的杂乱无章的话,即表示Keil 软件对工程的代码的地址分配不好:
这样的话,即使编译通过,下载到芯片里面之后,程序的运行也会乱跳,并且无法执行。
所以要对其进行更精确的地址分配,打开工程的选项设置,选择“BL51 Locate”项,在Code后面,将需要特殊处理的函数、变量、模块等进行指定地址的分配。具体的分配格式详见附录2——Keil 中代码、变量、堆栈、函数定位方式:
再次对项目工程进行编译,再次查看.M51文件的
“* * * * * * * C O D E M E M O R Y * * * * * * *”段内容,会发现已经很整齐了:
至此,代码分页处理已经完成90%了,剩下的是如何批量生产时的代码烧写准备工作了。
5
程序烧写设置
代码的批量烧写要使用“Silicon Labs MCU Production Programmer”工具,
然后点击Program Menu选项的“Configure Programming Settings”,进行如下设置:
保存配置,然后点击“Accept Settings”,然后点击“Program Device”按钮,最后等待弹出如下所示信息,则表示写入完毕:
附录1——《L51_BANK.A51》
$NOMOD51 NOLINES $NOCOND
;------------------------------------------------------------------------------ ; This file is part of the BL51 / LX51 Banked Linker/Locater package
; Copyright (c) 1988 - 2000 Keil Elektronik GmbH and Keil Software, Inc. ; Version 2.08 (Code and Variable Banking for Classic 8051 Derivatives) ;------------------------------------------------------------------------------ ;************************ Configuration Section *******************************
?B_NBANKS EQU 4 ; 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 4 ; 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 *
; Note Variable Banking is only supported with the LX51 linker/locater * ; *
?B_RST_BANK EQU 0FFh ; specifies the active code bank number after CPU * ; ; Reset. Used to reduce the entries in the *
; ; INTERBANK CALL TABLE. The value 0xFF disables * ; ; this LX51 linker/locater optimization. *
; Note interbank call table optimization is only possible with LX51. * ; *
;-----------------------------------------------------------------------------* ; *
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 NOTES: *
; 1. Eeach SWITCH macro must generate the same code size, otherwise the * ; BANKSWITCH code does not work correctly. * ; 2. The bankswitch logic must be initialized before using it. Please add *
; the following two lines of code at the end of the STARTUP.A51 file: * ; : * ; EXTRN CODE (?B_SWITCH0)
; CALL ?B_SWITCH0 ; init bank mechanism to code bank 0 ; LJMP ?C_START ; line already exits at the end of file * ; : *
; 3. If you are using the RTX-51 real-time operating system this banking * ; mode cannot be used. * ; *
PSBANK DATA 0B1H ; PSBANK Address * ; *
SWITCH0 MACRO ; Switch to Memory Bank #0 * MOV PSBANK, #00h ; Set PSBANK * ENDM * ; *
SWITCH1 MACRO ; Switch to Memory Bank #1 * MOV PSBANK, #11h ; Set PSBANK * ENDM * ; *
SWITCH2 MACRO ; Switch to Memory Bank #2 * MOV PSBANK, #22h ; Set PSBANK * ENDM * ; *
SWITCH3 MACRO ; Switch to Memory Bank #3 * MOV PSBANK, #33h ; Set PSBANK * 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, ?B_RST_BANK
; Standard SFR Symbols required in L51_BANK.A51 ACC DATA 0E0H B DATA 0F0H DPL DATA 82H DPH DATA 83H IE DATA 0A8H EA BIT IE.7
; 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 =
4 ;**************************************************************
?B_FACTOR EQU 0 ; Dummy Declarations ?B_FIRSTBIT EQU 0 ?B_MASK EQU MASK
?BANK?SELECT SEGMENT CODE ?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 B_SWITCH_START EQU $
; Generate ?B_SWITCHn functions CNT SET 0
REPT ?B_NBANKS BANK %CNT SWITCH %CNT CNT SET CNT+1 ENDM
B_SWITCH_SIZE EQU $-B_SWITCH_START
IF (B_SWITCH_SIZE > 256)
__ERROR__ \"BANK SWITCH CODE BIGGER THAN 256 BYTES (reduce number of banks or macro code)\" ENDIF
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_MODE =
4 ;**************************************************************
S_ENTRY MACRO N
DB LOW ?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
附录2——Keil 中代码、变量、函数定位方式
使用BL51 Locate选项 格式说明:
?PR? 表示program 意思是 Executable program code(可执行程序段); ?CO?表示code意思是code变量; ?XD?表示xdata意思是xdata变量; ?ID?表示idata意思是idata变量; ?DT? 表示data意思是data变量; ?PD?表示pdata意思是pdata变量;
代码和函数定位:
比如在main.c中定义了一个MyFunc2函数,并且要将该函数定位到代码区C:0x2000,则从菜单中选择Project->Options for Target 'Target1',在弹出的对话框中选择BL51 Locate页,在下面的code栏中写上“?PR?MYFUNC2?MAIN(0x2000)”即可。
如果想定位某个模块内的多个或全部函数,也可以使用*通配符,如
“?PR?*?TEST (0x1200)”,什么意思呢,就是test文件中所有的程序定位到0x1200地址。
如果想定位其他文件怎么办?假设现在有一个test2.c文件我想把test2定位到0x2200开始的地方,只要稍微修改一下
“?PR?*?TEST(0x1200),?PR?*?TEST2(0x2200)“, 各位看官是否注意到那个逗号',',用‘,’把各个文件隔开。实际效果请自行实践,我就不再 一一列举。
变量定位:
比如将main.c中定义的所有data型的全局变量定位到数据区D:0x28开始的空间,则在下面的data栏中写上?DT?MAIN(0x28)即可;如果是idata型的变量,则在下面的idata栏中写上?ID?MAIN(0x28);如果是xdata,则在下面的xdata栏中写
上?XD?MAIN(0x28),如果是pdata,则在下面的pdata栏中写上?PD?MAIN(0x28)。
因篇幅问题不能全部显示,请点此查看更多更全内容