keil提供的啟動代碼解析(STARTUP.A51)
程序清單1.1 AT89C51啟動代碼
本文引用地址:http://m.butianyuan.cn/article/201611/318640.htm$NOMOD51 //不使用51默認(rèn)的特殊功能寄存器
;
; This file is part of the C51 Compiler package
; Copyright (c) 1988-2002 Keil Elektronik GmbH and Keil Software, Inc.
;
; STARTUP.A51: This code is executed after processor reset.
; 說的很清楚,該代碼會在處理器上電復(fù)位后首先執(zhí)行
;
; To translate this file use A51 with the following invocation:
;
; A51 STARTUP.A51
;
; To link the modified STARTUP.OBJ file to your application use the following
; BL51 invocation:
;
; BL51
; BL51是Keil使用的鏈接器(Linker),這是命令行的使用格式
;
;
; User-defined Power-On Initialization of Memory
; 下面將定義一些與存儲器初始化相關(guān)的符號常量,與ICCAVR相比,Keil把符號常量顯式聲明出來更容易理解。
; With the following EQU statements the initialization of memory
; at processor reset can be defined:
;
; ; the absolute start-address of IDATA memory is always 0
IDATALEN EQU 80H ; the length of IDATA memory in bytes.
;IDDATALEN指片內(nèi)128字節(jié)RAM,I指internal
XDATASTART EQU 0H ; the absolute start-address of XDATA memory
XDATALEN EQU 0H ; the length of XDATA memory in bytes.
; XDATA指片外SRAM空間,X指external
PDATASTART EQU 0H ; the absolute start-address of PDATA memory
PDATALEN EQU 0H ; the length of PDATA memory in bytes.
; PDATA指程序存儲器,p指program
; Notes: The IDATA space overlaps physically the DATA and BIT areas of the
; 8051 CPU. At minimum the memory space occupied from the C51
; run-time routines must be set to zero.
; 注意:8051 CPU的寄存器空間和存儲器空間并不是統(tǒng)一編址的,而是通過指令來區(qū)分,所以不同的存儲區(qū)的地址可能重疊(overlap)
;
;
; Reentrant Stack Initilization
;
; The following EQU statements define the stack pointer for reentrant
; functions and initialized it:
; Keil C默認(rèn)情況不是用堆棧來傳遞參數(shù)的,所以造成函數(shù)不可重入(可重入概念參看線程安全和可重入函數(shù)一節(jié))。Keil要求用戶顯示聲明函數(shù)是否具有可重入屬性,以便為C函數(shù)調(diào)用初始化棧。
; Stack Space for reentrant functions in the SMALL model.
IBPSTACK EQU 0 ; set to 1 if small reentrant is used.
IBPSTACKTOP EQU 0FFH+1 ; set top of stack to highest location+1.
;
; Stack Space for reentrant functions in the LARGE model.
XBPSTACK EQU 0 ; set to 1 if large reentrant is used.
XBPSTACKTOP EQU 0FFFFH+1; set top of stack to highest location+1.
;
; Stack Space for reentrant functions in the COMPACT model.
PBPSTACK EQU 0 ; set to 1 if compact reentrant is used.
PBPSTACKTOP EQU 0FFFFH+1; set top of stack to highest location+1.
;不同內(nèi)存模式下的堆棧。Keil 編譯器中有三種模式設(shè)置:
Small:所有的變量都放在內(nèi)部RAM區(qū)
Compact:所有變量在默認(rèn)情況下都會放在外部RAM的低256字節(jié)中(可由R0尋址)
Large:所有變量都放在外部RAM中(DPTR尋址)
這是由51處理器繁多的尋址模式導(dǎo)致的,不同的尋址模式有不同的效率
;
;
; Page Definition for Using the Compact Model with 64 KByte xdata RAM
;
; The following EQU statements define the xdata page used for pdata
; variables. The EQU PPAGE must conform with the PPAGE control used
; in the linker invocation.
;
PPAGEENABLE EQU 0 ; set to 1 if pdata object are used.
;
PPAGE EQU 0 ; define PPAGE number.
;
PPAGE_SFR DATA 0A0H ; SFR that supplies uppermost address byte
; (most 8051 variants use P2 as uppermost address byte)
;
;
; Standard SFR Symbols
ACC DATA 0E0H
B DATA 0F0H
SP DATA 81H
DPL DATA 82H
DPH DATA 83H
NAME ?C_STARTUP
?C_C51STARTUP SEGMENT CODE
?STACK SEGMENT IDATA
RSEG ?STACK
DS 1
EXTRN CODE (?C_START)
PUBLIC ?C_STARTUP
CSEG AT 0 //代碼段的起始點(diǎn)
?C_STARTUP: LJMP STARTUP1 //轉(zhuǎn)跳到STARTUP1程序區(qū)中去。
RSEG ?C_C51STARTUP
STARTUP1:
//IF ENDIF是條件編譯命令,只有當(dāng)條件為真時,才編譯代碼
IF IDATALEN <> 0 //如果有IDATA,則把IDATA區(qū)的數(shù)據(jù)清零,類似于清BSS區(qū)
MOV R0,#IDATALEN - 1
CLR A
IDATALOOP: MOV @R0,A
DJNZ R0,IDATALOOP
ENDIF
//如果有外部數(shù)據(jù)區(qū),則把外部數(shù)據(jù)區(qū)中從XDATASTART到XDATASTART+ XDATALEN的區(qū)域清零
//由于51的儲存區(qū)類型和編譯模型比較多,下面的代碼就是根據(jù)不同的配置把相應(yīng)的區(qū)域清零
IF XDATALEN <> 0
MOV DPTR,#XDATASTART
MOV R7,#LOW (XDATALEN)
IF (LOW (XDATALEN)) <> 0
MOV R6,#(HIGH (XDATALEN)) +1
ELSE
MOV R6,#HIGH (XDATALEN)
ENDIF
CLR A
XDATALOOP: MOVX @DPTR,A
INC DPTR
DJNZ R7,XDATALOOP
DJNZ R6,XDATALOOP
ENDIF
IF PPAGEENABLE <> 0
MOV PPAGE_SFR,#PPAGE
ENDIF
IF PDATALEN <> 0
MOV R0,#LOW (PDATASTART)
MOV R7,#LOW (PDATALEN)
CLR A
PDATALOOP: MOVX @R0,A
INC R0
DJNZ R7,PDATALOOP
ENDIF
IF IBPSTACK <> 0
EXTRN DATA (?C_IBP)
MOV ?C_IBP,#LOW IBPSTACKTOP
ENDIF
IF XBPSTACK <> 0
EXTRN DATA (?C_XBP)
MOV ?C_XBP,#HIGH XBPSTACKTOP
MOV ?C_XBP+1,#LOW XBPSTACKTOP
ENDIF
IF PBPSTACK <> 0
EXTRN DATA (?C_PBP)
MOV ?C_PBP,#LOW PBPSTACKTOP
ENDIF
//該處是初始化堆棧指針
MOV SP,#?STACK-1
; This code is required if you use L51_BANK.A51 with Banking Mode 4
; EXTRN CODE (?B_SWITCH0)
; CALL ?B_SWITCH0 ; init bank mechanism to code bank 0
LJMP ?C_START
END
從上面一段代碼,我們已經(jīng)發(fā)現(xiàn)了一些與ATmega8初始化代碼相同的操作:初始化堆棧和bss區(qū)。由于AT89C51的存儲空間和尋址模式比ATmega8復(fù)雜,所以初始代碼中增加了許多根據(jù)不同配置而進(jìn)行初始化的代碼
評論