注册 登录
电子工程世界-论坛 返回首页 EEWORLD首页 频道 EE大学堂 下载中心 Datasheet 专题
zgdwn的个人空间 https://home.eeworld.com.cn/space-uid-436810.html [收藏] [复制] [分享] [RSS]
日志

基于MDK的S3C2410.S代码分析

已有 5208 次阅读2012-7-30 11:36 |个人分类:ARM学习笔记|

使用的是S2C2410A.S启动代码,配置过程中可以通过MDK软件的界面进行配置,相应选项打勾,打勾的区别体现在代码模块的开关量上,比如内存控制模块要使用,当打上勾时,相应代码的MC_SETUP1,启动代码执行相应的配置。否则,不执行。下面把有钩的代码粘贴如下:

; *** Startup Code (executed after Reset) ***

; Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs

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            ; when I bit is set, IRQ is disabled

F_Bit           EQU     0x40            ; when F bit is set, FIQ is disabled

UND_Stack_Size  EQU     0x00000000

SVC_Stack_Size  EQU     0x00000008

ABT_Stack_Size  EQU     0x00000000

FIQ_Stack_Size  EQU     0x00000000

IRQ_Stack_Size  EQU     0x00000080

USR_Stack_Size  EQU     0x00000400

Stack_Size      EQU     (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \

                         FIQ_Stack_Size + IRQ_Stack_Size + USR_Stack_Size)

                AREA    STACK, NOINIT, READWRITE, ALIGN=3

Stack_Mem       SPACE   Stack_Size

Stack_Top       EQU     Stack_Mem + Stack_Size

Heap_Size       EQU     0x00000000

                AREA    HEAP, NOINIT, READWRITE, ALIGN=3

Heap_Mem        SPACE   Heap_Size

; Clock Management definitions

CLK_BASE        EQU     0x4C000000      ; Clock Base Address

LOCKTIME_OFS    EQU     0x00            ; LOCKTIME Offset

MPLLCON_OFS     EQU     0x04            ; MPLLCON Offset

UPLLCON_OFS     EQU     0X08            ; UPLLCON Offset

CLKCON_OFS      EQU     0x0C            ; CLKCON Offset

CLKSLOW_OFS     EQU     0x10            ; CLKSLOW Offset

CLKDIVN_OFS     EQU     0X14            ; CLDKIVN Offset

CAMDIVN_OFS     EQU     0X18            ; CAMDIVN Offset

CLK_SETUP       EQU     1//同下

MPLLCON_Val     EQU     0x0005C080

UPLLCON_Val     EQU     0x00028080

CLKCON_Val      EQU     0x0007FFF0

CLKSLOW_Val     EQU     0x00000004

LOCKTIME_Val    EQU     0x00FFFFFF

CLKDIVN_Val     EQU     0X00000000

;Interrupt  definitions

INTOFFSET          EQU    0X4A000014                      ;Address of Interrupt offset Register

IntVT_SETUP      EQU     1 //同下

IntVTAddress    EQU     0x33FFFF20

; Watchdog Timer definitions

WT_BASE         EQU     0x53000000      ; WT Base Address

WTCON_OFS       EQU     0x00            ; WTCON Offset

WTDAT_OFS       EQU     0x04            ; WTDAT Offset

WTCNT_OFS       EQU     0x08            ; WTCNT Offset

WT_SETUP        EQU     1 //同下

WTCON_Val       EQU     0x00008021

WTDAT_Val       EQU     0x00008000

; Memory Controller definitions

MC_BASE         EQU     0x48000000      ; Memory Controller Base Address

;// <e> Memory Controller

MC_SETUP        EQU     1        //值都是相同的,就这个开关量不同。

BANKCON0_Val    EQU     0x00000700

BANKCON1_Val    EQU     0x00000700

BANKCON2_Val    EQU     0x00000700

BANKCON3_Val    EQU     0x00000700

BANKCON4_Val    EQU     0x00000700

BANKCON5_Val    EQU     0x00000700

BANKCON6_Val    EQU     0x00018008

BANKCON7_Val    EQU     0x00018008

BWSCON_Val      EQU     0x00000000

REFRESH_Val     EQU     0x00ac0000

BANKSIZE_Val    EQU     0x00000000

MRSRB6_Val      EQU     0x00000020

MRSRB7_Val      EQU     0x00000000

;// </e> End of MC

; I/O Ports definitions

PIO_BASE        EQU     0x56000000      ; PIO Base Address

PCONA_OFS       EQU     0x00            ; PCONA Offset

PCONB_OFS       EQU     0x10            ; PCONB Offset

PCONC_OFS       EQU     0x20            ; PCONC Offset

PCOND_OFS       EQU     0x30            ; PCOND Offset

PCONE_OFS       EQU     0x40            ; PCONE Offset

PCONF_OFS       EQU     0x50            ; PCONF Offset

PCONG_OFS       EQU     0x60            ; PCONG Offset

PCONH_OFS       EQU     0x70            ; PCONH Offset

PCONJ_OFS       EQU     0xD0            ; PCONJ Offset

PUPB_OFS        EQU     0x18            ; PUPB Offset

PUPC_OFS        EQU     0x28            ; PUPC Offset

PUPD_OFS        EQU     0x38            ; PUPD Offset

PUPE_OFS        EQU     0x48            ; PUPE Offset

PUPF_OFS        EQU     0x58            ; PUPF Offset

PUPG_OFS        EQU     0x68            ; PUPG Offset

PUPH_OFS        EQU     0x78            ; PUPH Offset

PUPJ_OFS        EQU     0xD8            ; PUPJ Offset

;// <e> I/O Configuration

PIO_SETUP       EQU     1 //与没有勾的区别。

PIOA_SETUP      EQU     0

PCONA_Val       EQU     0x000003FF

PIOB_SETUP      EQU     0

PCONB_Val       EQU     0x000007FF

PUPB_Val        EQU     0x00000000 

PIOC_SETUP      EQU     0

PCONC_Val       EQU     0xAAAAAAAA

PUPC_Val        EQU     0x00000000

PIOD_SETUP      EQU     0

PCOND_Val       EQU     0x00000000

PUPD_Val        EQU     0x00000000

PIOE_SETUP      EQU     0

PCONE_Val       EQU     0x00000000

PUPE_Val        EQU     0x00000000

PIOF_SETUP      EQU     1//这个竟然是相同的。

PCONF_Val       EQU     0x0000511A

PUPF_Val        EQU     0x00000000

PIOG_SETUP      EQU     0

PCONG_Val       EQU     0x00000000

PUPG_Val        EQU     0x00000000

PIOH_SETUP      EQU     0

PCONH_Val       EQU     0x000007FF

PUPH_Val        EQU     0x00000000 

                PRESERVE8

                

AREA    RESET, CODE, READONLY

                ARM

Vector 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, IRQ_Addr

                LDR     PC, FIQ_Addr

                IF      IntVT_SETUP <> 0

;Interrupt Vector Table Address                

HandleEINT0   EQU    IntVTAddress           

HandleEINT1   EQU    IntVTAddress +4

HandleEINT2   EQU    IntVTAddress +4*2

HandleEINT3   EQU    IntVTAddress +4*3

HandleEINT4_7   EQU    IntVTAddress +4*4

HandleEINT8_23    EQU    IntVTAddress +4*5

HandleReserved   EQU    IntVTAddress +4*6

HandleBATFLT   EQU    IntVTAddress +4*7

HandleTICK   EQU    IntVTAddress +4*8

HandleWDT   EQU    IntVTAddress +4*9

HandleTIMER0    EQU    IntVTAddress +4*10

HandleTIMER1    EQU    IntVTAddress +4*11

HandleTIMER2    EQU    IntVTAddress +4*12

HandleTIMER3    EQU    IntVTAddress +4*13

HandleTIMER4    EQU    IntVTAddress +4*14

HandleUART2     EQU    IntVTAddress +4*15

HandleLCD    EQU    IntVTAddress +4*16

HandleDMA0   EQU    IntVTAddress +4*17

HandleDMA1   EQU    IntVTAddress +4*18

HandleDMA2   EQU    IntVTAddress +4*19

HandleDMA3   EQU    IntVTAddress +4*20

HandleMMC   EQU    IntVTAddress +4*21

HandleSPI0   EQU    IntVTAddress +4*22

HandleUART1   EQU    IntVTAddress +4*23

;HandleReserved   EQU    IntVTAddress +4*24

HandleUSBD   EQU    IntVTAddress +4*25

HandleUSBH   EQU    IntVTAddress +4*26

HandleIIC   EQU    IntVTAddress +4*27

HandleUART0    EQU    IntVTAddress +4*28

HandleSPI1    EQU    IntVTAddress +4*39

HandleRTC    EQU    IntVTAddress +4*30

HandleADC    EQU    IntVTAddress +4*31

IRQ_Entry

                sub sp,sp,#4       ;reserved for PC

            stmfd sp!,{r8-r9}

                

            ldr r9,=INTOFFSET

            ldr r9,[r9]

            ldr r8,=HandleEINT0

            add r8,r8,r9,lsl #2

            ldr r8,[r8]

            str r8,[sp,#8]

            ldmfd sp!,{r8-r9,pc}                

                

ENDIF

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

                DCD     0                      ; Reserved Address 

IRQ_Addr        DCD     IRQ_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

                

                IF      IntVT_SETUP <> 1

IRQ_Handler     B       IRQ_Handler

                ENDIF

                

                IF      IntVT_SETUP <> 0         ;<>”是判断不等于的意思。  

IRQ_Handler     B       IRQ_Entry

                ENDIF

                

FIQ_Handler     B       FIQ_Handler

; Memory Controller Configuration

                IF      MC_SETUP <> 0

MC_CFG

                DCD     BWSCON_Val

                DCD     BANKCON0_Val

                DCD     BANKCON1_Val

                DCD     BANKCON2_Val

                DCD     BANKCON3_Val

                DCD     BANKCON4_Val

                DCD     BANKCON5_Val

                DCD     BANKCON6_Val

                DCD     BANKCON7_Val

                DCD     REFRESH_Val

                DCD     BANKSIZE_Val

                DCD     MRSRB6_Val

                DCD     MRSRB7_Val

                ENDIF

; Clock Management Configuration

                IF      CLK_SETUP <> 0

CLK_CFG

                DCD     LOCKTIME_Val     

                DCD     CLKDIVN_Val 

                DCD     MPLLCON_Val 

                DCD     UPLLCON_Val 

                DCD     CLKSLOW_Val 

                DCD     CLKCON_Val 

                ENDIF 

; Reset Handler

                EXPORT  Reset_Handler

Reset_Handler   

                IF      WT_SETUP <> 0

                LDR     R0, =WT_BASE

                LDR     R1, =WTCON_Val

                LDR     R2, =WTDAT_Val

                STR     R2, [R0, #WTCNT_OFS]

                STR     R2, [R0, #WTDAT_OFS]

                STR     R1, [R0, #WTCON_OFS]

                ENDIF

                

                

                IF      CLK_SETUP <> 0         

                LDR     R0, =CLK_BASE            

                ADR     R8, CLK_CFG

                LDMIA   R8, {R1-R6}            

                STR     R1, [R0, #LOCKTIME_OFS]

                STR     R2, [R0, #CLKDIVN_OFS]  

                STR     R3, [R0, #MPLLCON_OFS] 

                STR     R4, [R0, #UPLLCON_OFS]  

                STR     R5, [R0, #CLKSLOW_OFS]

                STR     R6, [R0, #CLKCON_OFS]

                ENDIF                          

                                  

                IF      MC_SETUP <> 0

                ADR     R14, MC_CFG

                LDMIA   R14, {R0-R12}

                LDR     R14, =MC_BASE

                STMIA   R14, {R0-R12}

                ENDIF                         

                                

              

                IF      PIO_SETUP <> 0

                LDR     R14, =PIO_BASE

                IF      PIOA_SETUP <> 0

                LDR     R0, =PCONA_Val

                STR     R0, [R14, #PCONA_OFS]

                ENDIF

                IF      PIOB_SETUP <> 0

                LDR     R0, =PCONB_Val

                LDR     R1, =PUPB_Val

                STR     R0, [R14, #PCONB_OFS]

                STR     R1, [R14, #PUPB_OFS]

                ENDIF

                IF      PIOC_SETUP <> 0

                LDR     R0, =PCONC_Val

                LDR     R1, =PUPC_Val

                STR     R0, [R14, #PCONC_OFS]

                STR     R1, [R14, #PUPC_OFS]

                ENDIF

                IF      PIOD_SETUP <> 0

                LDR     R0, =PCOND_Val

                LDR     R1, =PUPD_Val

                STR     R0, [R14, #PCOND_OFS]

                STR     R1, [R14, #PUPD_OFS]

                ENDIF

                IF      PIOE_SETUP <> 0

                LDR     R0, =PCONE_Val

                LDR     R1, =PUPE_Val

                STR     R0, [R14, #PCONE_OFS]

                STR     R1, [R14, #PUPE_OFS]

                ENDIF

                IF      PIOF_SETUP <> 0

                LDR     R0, =PCONF_Val

                LDR     R1, =PUPF_Val

                STR     R0, [R14, #PCONF_OFS]

                STR     R1, [R14, #PUPF_OFS]

                ENDIF

                IF      PIOG_SETUP <> 0

                LDR     R0, =PCONG_Val

                LDR     R1, =PUPG_Val

                STR     R0, [R14, #PCONG_OFS]

                STR     R1, [R14, #PUPG_OFS]

                ENDIF

  

                IF      PIOH_SETUP <> 0

                LDR     R0, =PCONH_Val

                LDR     R1, =PUPH_Val

                STR     R0, [R14, #PCONH_OFS]

                STR     R1, [R14, #PUPH_OFS]

                ENDIF

               

                ENDIF

                

                

; Setup Stack for each mode

                LDR     R0, =Stack_Top

;  Enter Undefined Instruction Mode and set its Stack Pointer

                MSR     CPSR_c, #Mode_UND:OR:I_Bit:OR:F_Bit

                MOV     SP, R0

                SUB     R0, R0, #UND_Stack_Size

;  Enter Abort Mode and set its Stack Pointer

                MSR     CPSR_c, #Mode_ABT:OR:I_Bit:OR:F_Bit

                MOV     SP, R0

                SUB     R0, R0, #ABT_Stack_Size

;  Enter FIQ Mode and set its Stack Pointer

                MSR     CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bit

                MOV     SP, R0

                SUB     R0, R0, #FIQ_Stack_Size

;  Enter IRQ Mode and set its Stack Pointer

                MSR     CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit

                MOV     SP, R0

                SUB     R0, R0, #IRQ_Stack_Size

;  Enter Supervisor Mode and set its Stack Pointer

                MSR     CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit

                MOV     SP, R0

                SUB     R0, R0, #SVC_Stack_Size

;  Enter User Mode and set its Stack Pointer

                MSR     CPSR_c, #Mode_USR

                MOV     SP, R0

                SUB     SL, SP, #USR_Stack_Size

; Enter the C code

                IMPORT  __main

                LDR     R0, =__main

                BX      R0

; User Initial Stack & Heap

                AREA    |.text|, CODE, READONLY

                IMPORT  __use_two_region_memory

                EXPORT  __user_initial_stackheap

__user_initial_stackheap

                LDR     R0, =  Heap_Mem

                LDR     R1, =(Stack_Mem + USR_Stack_Size)

                LDR     R2, = (Heap_Mem +      Heap_Size)

                LDR     R3, = Stack_Mem

                BX      LR

                END

按照程序的分布,前面为各种变量的定义,后边为正式启动程序的开始。

前面各种变量的定义,根据程序的顺序主要包括几个部分:处理器的工作模式==>堆栈地址、尺寸的定义==>时钟寄存器及初始值的定义==>看门狗寄存器及其初始值定义==>内存控制器寄存器及其值定义==>端口寄存器及初始化值。

下面进行启动代码分析,一段段来。

PRESERVE8

AREA    RESET, CODE, READONLY

ARM

第一句的意思是指示当前数据栈是8字节对齐的。

    另外还有个REQUIRE8伪操作指示当前代码中要求数据栈8字节对齐。

AREA用来定义一个数据段或者代码段,可读写,按8字节对齐,不初始化为0

另外还有SPACE也用于分配一块内存单元,但是是用0初始化。

第二句也就不用说了,是定义一个RESET段,其属性就是只读了。

第三句:ARM,在书上着实没找到,网上的一篇说到说是:以ARM模式运行程序。暂且这样认为!!

1,接下来是Vector这个标号下边的内容。

首先是LDR PC,Reset_Addr;…………

看到此时的LDR PC,Reset_Addr…………,查了一下书,看到了LDR的两个功能:

A,从内存中读取32位字数据到通用寄存器当中,并且对数据进行一定的操作。

B, PC作为目标寄存器的时候,指令可以实现程序的跳转的功能。以取得的地址作为目标地址,从那开始执行。注意,在ARM v5及以上的版本中,地址值的bit[0]用来确定程序状态,为1的话,为Thumb指令,为0时为ARM指令。在之前的版本中,bits[1:0]常被忽略,执行ARM状态。所以执行第一句话的时候就跳到Reset_Addr处执行程序了,后面依次列推。

各个中断地址的定义了。比如:HandleEINT1   EQU    IntVTAddress +4

中断向量表的定义,而那个IntVTAddress    EQU     0x33FFFF20

另外还有个地址也注意下:INTOFFSET          EQU    0X4A000014 

IntVTAddress的地址为什么是这样了?!不是很明白??估计是硬件设计时就已经决定好了。为什么是这个地址了??

2然后是进入IRQ_Entry标号下的代码。在这个里边干的事为:

IRQ_Entry

                sub sp,sp,#4       ;reserved for PCsp - 4>sp

            stmfd sp!,{r8-r9}

                

            ldr r9,=INTOFFSET

            ldr r9,[r9]

            ldr r8,=HandleEINT0

            add r8,r8,r9,lsl #2

            ldr r8,[r8]

            str r8,[sp,#8]

            ldmfd sp!,{r8-r9,pc} 

分析如下图:

说明:首先假设SP指向12SP-4后往上走到8,然后执行指令stmfd sp!,{r8-r9},该指令的在8处存入r9的值,然后在4处存入r8的值(即保护现场)。执行

ldr r9,=INTOFFSETldrr9,[r9]把此时产生中断的偏移量存入r9中,然后add r8,r8,r9,lsl #2,及等价于r8 = IntVTAddress +4*nnr9里的值,即找到中断发生的地址,然后r8内的值(中断服务程序的起始地址)存入堆栈的12中,即指令:ldr r8,[r8]

str r8,[sp,#8]。最后是恢复现场,关键的指令ldmfd sp!,{r8-r9,pc};依次把r8r9的值返回去,同时,把PC指针指向中断服务程序的起始地址。

另外关于具体的指令解释,就得看《ARM体系结构与编程》——杜春雷。

接下来Reset_Addr      DCD     Reset_Handler;………………

以及Undef_Handler   B       Undef_Handler;…………之类的

我们都知道,发生中断时,硬件都是自动跳到一个地址,这个地址对应的是该中断类型,此时也不例外,程序刚开始时就有:LDR  PC,Reset_Handler;这句指令的地址便是0x0,所以当复位发生时,PC便指向了0x00,便从该地址开始执行复位程序。文件中除了Reset(后边有标号)与IRQ(即标号IRQ_Entry下的代码)引起的中断有程序外,其他都是Undef_Handler   B       Undef_Handler这样的无限循环。

DCDDCDU都是用于分配一段字内存单元,前者是字对齐的,后者不严格字对齐。

data1 DCD 1,5,20data1的值就为3个子单元,1,5,20.

  data2 DCD memaddr + 4;分配一个字单元,值为程序中标号memaddr加上四个字节。 

Reset_Addr      DCD     Reset_Handler的意思是为Reset_Addr分配一个字单元,其值为

Reset_Handle标号所对应的地址。

BBL指令,都是跳转到目标出执行指令,不同的是BL同时还将当前PC寄存器的值保存到LR寄存器中。

Undef_Handler   B       Undef_Handler ;中断处理程序的入口地址//B为跳转指令Undef_Handler为标号|| ??难道自己跳转到自己??事实是就是自己跳到自己,如果想不要死循环,有资料说这是可以人为修改添加代码的。

这样看来,进入中断的就清楚了。当有中断来的时候,PC跳到中断地址,即LDR PC,***_Addr;然后***_Addr放的是中断服务程序的地址。就可以执行中断服务程序了。

3下面是各个模块的配置了。以一个模块为例就能说明问题。

EXPORT  Reset_Handler

Reset_Handler   

                IF      WT_SETUP <> 0

                LDR     R0, =WT_BASE

                LDR     R1, =WTCON_Val

                LDR     R2, =WTDAT_Val

                STR     R2, [R0, #WTCNT_OFS]

                STR     R2, [R0, #WTDAT_OFS]

                STR     R1, [R0, #WTCON_OFS]

                ENDIF

首先,EXPORT 声明一个符号可以被其他文件引用。也就是下边标号Reset_Handler下的代码可以供其他文件使用。可见,这些初始化上后最先完成的。

其他过程就很easy了,先判断开关量是否满足条件,然后加载寄存器地址,然后把数据送给这些地址,仅此而已。通过这一部分,处理器的,时钟,看门狗,内存,IO口便初始化好了,当然可以通过软件界面来设置决定哪个模块要不要初始化。

4,这部分为设置各个模式下的堆栈地址。只要说明一部分就OK

; Setup Stack for each mode

                LDR     R0, =Stack_Top

;  Enter Undefined Instruction Mode and set its Stack Pointer

                MSR     CPSR_c, #Mode_UND:OR:I_Bit:OR:F_Bit

                MOV     SP, R0

                SUB     R0, R0, #UND_Stack_Size

先设置最开始的栈顶: LDR     R0, =Stack_Top,然后

MSR     CPSR_c, #Mode_ABT:OR:I_Bit:OR:F_Bit

MSR指令,用于将通用寄存器的内容或一个立即数传送到状态寄存器中。

CPSR_C,代表的是CPSR寄存器的bit[70];还有些其他的,看书了!!SUB指令,(书上写的很详细了),其实从这里就可以看出:配置完之后就是进入各模式,然后配置堆栈指针的初始指向地址。注意:每一个模式都有自己的SP指针,因此,RESET_HANDLER执行后的堆栈指针的地址分配便能知道了。

5,跳到主程序main();

; Enter the C code

                IMPORT  __main

                LDR     R0, =__main

                BX      R0

IMPORT __main

该语句是说明,__main在其他文件中定义,在这里引用。然后BX R0BX指令跳转到指令中指定的目标地址,BX {<cond>} <Rm>cond为条件,当没有时,无条件执行。

6,最后初始堆与栈

; User Initial Stack & Heap

                AREA    |.text|, CODE, READONLY

                IMPORT  __use_two_region_memory

                EXPORT  __user_initial_stackheap

__user_initial_stackheap

                LDR     R0, =  Heap_Mem

                LDR     R1, =(Stack_Mem + USR_Stack_Size)

                LDR     R2, = (Heap_Mem +      Heap_Size)

                LDR     R3, = Stack_Mem

                BX      LR

首先定义一个名为|.text|的段,这个段代表的是:|.text|表示C语言编译器产生的代码段或者是与C语言库相关的代码段,下边的语句都属于|.test|段,。

BX  LR,可以看出来(因为这个用于子程序的返回),__user_initial_stackheap下边的是这个函数的内容,然后在这个函数里把堆与栈的首地址或者末地址给寄存器,R0,1,2,3.IMPORT  __use_two_region_memory是告诉是一段模式,还是两端(包括堆,栈)模式!!这里显然是两段模式。

用来做什么了??不是很懂??有待进一步学习。。。

通过一篇博文《基于TQ2440ARM启动代码注释分析(基于MDK》有点懂了。

首先解决这个段是来干什么的??

用户设置堆栈程序(C外部接口:用于动态申请内存使用),通过这段程序,设置堆栈地址,即开辟的这个空间用来放用户程序中用于动态分配到的空间的,如new。其分配的图(两段模式与一段模式)如下:

说明:R0,R1,R2,R3中的返回值是由你使用的一段存储模式还是二段存储模式决定。
         1. 一段模式中R1R0大。R2R3被忽略了。
         2. 二段模式中R0R2用来初始化堆,R1R3用来初始化栈。R2 >= R0,R3 < R1

然后解决第二个问题:系统怎么调用__user_initial_stackheap这个函数来进行堆栈地址的赋值的??

1,没分散加载文件。系统默认通过|Image$$ZI$$limit|来调用的。

2,有分散加载文件。直接引用原文内容,说得很清楚了。

    默认情况下__user_initial_stackhep()使用的是符号|Image$$ZI$$limit|的值。这个符号在用户使用分散加载文件时不会产生。然而,C库提供了比较折中的方法:利用分散加载文件中的一些信息来执行这个函数。
        注意:
        如果你重新执行__user_initial_stackhep()函数,那么其他的库的执行将被忽略。
        选择使用一段存储模式:
        定义一段特殊的执行域在你的分散加载文件中。使用这种符号:ARM_LIB_STACKHEAP,并使用EMPTY 属性。 这样库管理器就选择了一个把这个域当作堆和栈合并在一起的__user_initial_stackhep()函数。在这个函数中使用了Image$$ARM_LIB_STACKHEAP$$BaseImage$$ARM_LIB_STACKHEAP$$ZI$$Limit符号
        选择使用二段存储模式:
        定义两个特殊的执行域再你的分散加载文件中。使用这两种符号:ARM_LIB_STACK, ARM_LIB_HEAP。并且两个段都要使用EMPTY属性。这样库管理器就会选择使用符号:Image$$ARM_LIB_HEAP$$Base mage$$ARM_LIB_STACK$$ZI$$ZI$$limitImage$$ARM_LIB_STACK$$BaseImage$$ARM_LIB_STACK$$ZI$$Limit__user_initial_stackhep()函数。
       例子:
       FLASH_LOAD 0x0000 0x00200000
       {
            VECTORS +0 0x400
            {
             * (:gdef:__vectab_stack_and_reset, +FIRST)
                ; 其他域可以放在这里
             }
             ;; 最高256 异常深度 (256*4bytes == 1024 == 0x400)
             CODE 0x400 FIXED
             {
                 * (+RO)
             }
             DATA 0x20000000 0x00200000
             {
                 * (+RW, +ZI)
             }
             ;; 堆开始于 1MB ,向高地址生长
             ARM_LIB_HEAP 0x20100000 EMPTY 0x100000-0x8000
             {}
             ;; 堆安排在 2MB RAM的最高地址处
             ;; 向低地址生长,空间为32KB
             ARM_LIB_STACK 0x20200000 EMPTY - 0x8000
             {}
    }

评论 (0 个评论)

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 注册

热门文章