前些天写过,我在学ARM的过程中,虽然看了书,对ARM的体系结构有了了解,可是当我实际想操作操作,写个程序的时候,却发现,真正的启动文件里面,还有很多书里面没有讲过的东西,看不懂。
为了弄懂这些看不懂的部分的含义,让自己真正能做到可以自己写程序,我把ADS带的英文帮助文件仔仔细细看了一遍,这才算明白一点了,前两天自己说现在把STARTUP.S里面所有的东西都弄明白了,其实也不是,但是大部分算是明白了。
下面就是我写的STARTUP.S程序,贴在这里,说一下我对各部分的理解吧。文件中的注释是我当时加的,现在加的说明我用颜色区别开。程序主要参考了KEIL的启动文件,所以像堆栈设置等部分,方法也和KEIL的一样。
; A startup file for ARM by myself
; defination for mode (used for change work mode to setup stack)
MODE_USR EQU 0X10
MODE_FIQ EQU 0X11
MODE_IRQ EQU 0X12
MODE_SVC EQU 0X13
MODE_ABT EQU 0X17
MODE_UND EQU 0X1B
MODE_SYS EQU 0X1F
I_BIT EQU 0X80 ; I bit set to 1 to disable IRQ
F_BIT EQU 0X40 ; F bit set to 1 to disable FIQ
; defination of stack size
UND_StackSize EQU 0X00*4
SVC_StackSize EQU 0X02*4
ABT_StackSize EQU 0X00*4
FIQ_StackSize EQU 0X20*4
IRQ_StackSize EQU 0X20*4
USR_StackSize EQU 0X100*4
ISR_StackSize EQU (UND_StackSize + SVC_StackSize + ABT_StackSize + \
FIQ_StackSize + IRQ_StackSize)
这个ISR_StackSize就是指所有中断程序的堆栈的尺寸之和,用来在后面计算堆栈top地址用的
AREA STACK, NOINIT, READWRITE, ALIGN=4
USR_Stack space USR_StackSize 定义堆栈的空间,usr在下面,isr的在上面
USR_StackTop space ISR_StackSize
StackTop 在这里放个标号,以获得堆栈顶部的地址
Heap_Size EQU 0x100 heap好像主要是给c程序动态分配的内存使用的,如果不用 malloc, new, printf一类的,好像也可以不要(我的理解,不一定对阿)
AREA HEAP, NOINIT, READWRITE, ALIGN=4
__heap_base
Heap_Mem SPACE Heap_Size
__heap_limit
AREA RESET, CODE, READONLY
ENTRY
CODE32
Vectors LDR PC, Reset_addr
LDR PC, Undef_addr
LDR PC, SWI_addr
LDR PC, PAbt_addr
LDR PC, DAbt_addr
NOP ; RESERVED VECTOR
LDR PC, [PC, #-0X0FF0] ; FOR VIC, FOR NORMAL USE LDR PC, IRQ_addr
LDR PC, FIQ_addr
Reset_addr dcd Reset_handler
Undef_addr dcd Undef_handler
SWI_addr dcd SWI_handler
PAbt_addr dcd PAbt_handler
DAbt_addr dcd DAbt_handler
FIQ_addr dcd FIQ_handler
Undef_handler b Undef_handler
SWI_handler b SWI_handler
PAbt_handler b PAbt_handler
DAbt_handler b DAbt_handler
FIQ_handler b FIQ_handler
EXPORT Reset_handler
Reset_handler LDR R0,=StackTop 先把r0设置为stack的top address
MSR CPSR_c, #MODE_UND :OR: I_BIT :OR: F_BIT ; ENTER UNDEFINED MODE
MOV SP, R0 ; SET SP TO THE TOP OF IT'S STACK
SUB R0, R0, #UND_StackSize ; CALCULATE THE NEXT STACK'S TOP
MSR CPSR_c, #MODE_SVC :OR: I_BIT :OR: F_BIT
MOV SP, R0
SUB R0, R0, #SVC_StackSize 每设置完一种模式的堆栈,就减去,已得到下一种堆栈的top地址
MSR CPSR_c, #MODE_ABT :OR: I_BIT :OR: F_BIT
MOV SP, R0
SUB R0, R0, #ABT_StackSize
MSR CPSR_c, #MODE_FIQ :OR: I_BIT :OR: F_BIT
MOV SP, R0
SUB R0, R0, #FIQ_StackSize
MSR CPSR_c, #MODE_IRQ :OR: I_BIT :OR: F_BIT
MOV SP, R0
SUB R0, R0, #IRQ_StackSize
MSR CPSR_c, #MODE_USR ; NO I/F BIT SETTING
MOV SP, R0
SUB SL, R0, #USR_StackSize ; SET SL THE BOTTOM OF USER STACK, I DON'T KNOW WHAT IT MEAN 这里我有点不明白,谁能给说一下啊?
IMPORT __main __main是c环境的一个库函数,可以完成一些初始化的工作,然后跳转到用户的main()
B __main
IMPORT __use_two_region_memory 如果stack和heap在内存里分成了两段地址,就要用这个标志告诉编译器
EXPORT __user_initial_stackheap 如果使用了scatter文件来控制链接,则必须重载__user_initial_stackheap函数,否则编译器找不到heap的起始地址
__user_initial_stackheap
LDR R0, = __heap_base 为什么这么写,我也不知道,还请明白人指点一下吧。
BX LR
END