启动程序概要
启动程序,为用户的应用程序执行提供必要的准备。根据应用程序以及连接的不同,启动程序可以生成加载,模块和文件。
功能
执行内存初始化,系统ROM化处理,应用程序启动,退出处理。
- ROM化处理
C程序中定义的全局变量(external),静态变量(static),sreg变量的初始值,是保存在ROM中的。但是,对于ROM而言,这些值是不能被修改的。因此,需要把ROM上的这些值拷贝到RAM中。这就是ROM化处理,程序以这样的方式访问ROM,实际访问的是RAM上ROM的拷贝。
如下图所示,全局变量的初始值存储在ROM中@@R_INIT—-?R_INIT区内,上电后,需要把该区内的值复制到RAM中的@@INIT—-?INIT区内。
对于ROM,RAM中各区的符号定义如下:
构成
启动程序的构成包括:前处理,初始值设置,ROM化处理,调用main函数,后处理,ROM化处理中使用的level定义。
注1:如果使用标准库函数,最先执行库函数的相关处理。启动程序,源程序,文件的名称中,有n的文件,说明没有使用标准库相关的文件,没有n的文件,则使用了标准库。
注2:函数hdwinit中,用于初始化外设,需要用户定义。hdwinit的调用需要尽早进行,在main函数中也是可以的。如果用户没有定义hdwinit,该步操作没有任何动作直接返回。
cstart.asm和cstartn.asm的区别是cstart使用了库函数。
举例说明(panel sample例程)
NAME @cstart
; 前处理
$INCLUDE ( def.inc ) ; (1)用于设定库的类型
$INCLUDE ( macro.inc )
; (2)标准库函数开关
BRKSW EQU 1 ; brk , sbrk , calloc , free , malloc , realloc function use ;
EXITSW EQU 1 ; exit , atexit function use ; (2)当不需要使用相应的库函数时,将EQU的值改为0
RANDSW EQU 1 ; rand , srand function use ; (2)关闭相应开关,可以节省ROM资源
DIVSW EQU 1 ; div function use ; (2)默认全部打开
LDIVSW EQU 1 ; 1div function use
FLOATSW EQU 1 ; floating point variables use
STRTOKSW EQU 1 ; strtok function use
PUBLIC _@cstart , _@cend ; (3)使用标准库是定义的符号
$_IF ( BRKSW )
PUBLIC _@BRKADR , _@MEMTOP , _@MEMBTM
:
$ENDIF
EXTRN _main , _@STBEG , _hdwinit , _@MAA ; (4)外部符号声明,_@STBEG=栈的最后地址+1
$_IF ( EXITSW )
EXTRN _exit
$ENDIF
; (5)ROM化处理用【标签】声明,它们的定义在后处理中
EXTRN _?R_INIT , _?RLINIT , _?R_INIS , _?DATA , _?DATAL , _?DATS
@@DATA DSEG BASEP ; near ; (6)标准库使用的区
$_IF ( EXITSW )
_@FNCTBL : DS 4 * 32
_@FNCENT : DS 2
:
_@MEMTOP : DS 32
_@MEMBTM :
$ENDIF
;初始化
@@VECT00 CSEG AT 0 ; (1)复位向量表定义,复位后,指向cstart的首地址
DW _@cstart
@@LCODE CSEG BASE
_@cstart :
SEL RB0 ; (3)指定寄存器组,指向RB0
MOV A , #_@MAA ; (2)镜像区设定
MOV1 CY , A.0
MOV1 MAA , CY
MOVW SP , #LOWW _@STBEG ; SP <-stack begin address ; (4)设定栈顶地址,STBEG由连接器自动生成
CALL !!_hdwinit ; (5)调用硬件初始化函数
:
$_IF ( BRKSW OR EXITSW OR RANDSW OR FLOATSW )
CLRW AX
$ENDIF
:
; ROM化处理,把ROM中外部变量,sreg变量的初始值拷贝到RAM中。可被处理的变量有下面四类:
; char c = 1 ; (a)有初始值的全局变量
; int i ; (b)无初始值的全局变量,默认设置为0
; __sreg int si = 0 ; (c)有初始值的sreg变量
; __sreg char sc ; (d)无初始值得sreg变量,默认设置为0
; void main ( void ) {
; :
;}
; copy external variables having initial value
$_IF ( _ESCOPY )
MOV ES , #HIGHW _@R_INIT
$ENDIF
MOVW HL , #LOWW _@R_INIT
MOVW DE , #LOWW _@INIT
BR $LINIT2
LINIT1 :
$_IF ( _ESCOPY )
MOV A , ES : [ HL ]
$ELSE
MOV A , [ HL ]
$ENDIF
MOV [ DE ] , A
INCW HL
INCW DE
LINIT2 :
MOVW AX , HL
CMPW AX , #LOWW _?R_INIT
BNZ $LINIT1
; 启动main函数和后处理
CALL !!_main ; main ( ) ; ; (1)调用main函数
$_IF ( EXITSW )
CLRW AX
CALL !!_exit ; exit ( 0 ) ; ; (2)需要exit时,调用exit
$ENDIF
BR $$
;
_@cend :
; (3)ROM化处理所使用的【区,segment】【标签,label】的定义;【标签】是指各【区】的首地址
@@R_INIT CSEG UNIT64KP
_@R_INIT :
@@RLINIT CSEG UNIT64KP
_@RLINIT :
@@R_INIS CSEG UNIT64KP
_@R_INIS :
@@INIT DSEG BASEP
_@INIT :
@@INITL DSEG UNIT64KP
_@INITL :
@@DATA DSEG BASEP
_@DATA :
@@DATAL DSEG UNIT64KP
_@DATAL :
@@INIS DSEG SADDRP
_@INIS :
@@DATS DSEG SADDRP
_@DATS :
@@CALT CSEG CALLT0
@@CNST CSEG MIRRORP
@@CNSTL CSEG PAGE64KP
@@BITS BSEG
;
END
参考
[cc78k0rp.chm]