搜索
您的当前位置:首页C8051F120代码超过64K后的分页处理

C8051F120代码超过64K后的分页处理

来源:爱问旅游网
C8051F120代码超过64K后的分页处理(Keil uV5)

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)。

因篇幅问题不能全部显示,请点此查看更多更全内容

Top