1、1、 MDK S3C2440 启动代码简单分析ARM 启动代码相当于我们电脑的 BIOS,也就是 ARM 启动时对处理器的一些初始化及嵌入式系统硬件的一些初始化。由于它直接面对处理器内核和硬件控制器进行编程,一般都是用汇编语言。一般包括:中断向量表,初始化存储器系统,初始化堆栈,初始化有特殊要求的断口,设备初始化,变量初始化等。;/*/;/*S3C2440A.S: Startup file for Samsung S3C440A */;/*/;/* */ ;/*/;/*This file is part of the uVision/ARM development tools. */;/*Co
2、pyright (c) 2005-2006 Keil Software. All rights reserved. */;/*This software may only be used under the terms of a valid, current, */;/*end user licence from KEIL for a compatible version of KEIL software */;/*development tools. Nothing else gives you the right to use this software. */;/*/;下面这些参数是与
3、CPSR 状态寄存器有关;这里各个模式的参数是由寄存器 CPSR 的模式位设置 M4:0得来的,;比如这里的用户模式,CPSR 的 M4:0设置为 10000 就是 0x10。;Mode_USR - 用户模式,正常程序执行模式,用于应用程序;Mode_FIQ -快速中断模式,一般用于高速数据传输和通道处理。;Mode_IRQ -外部中断模式,一般用于通用的中断处理。;Mode_SVC - 管理模式,供操作系统使用的一种保护模式。;Mode_ABT - 数据访问中止模式,用于虚拟存储用存储保护;Mode_UND - 未定义指令中止模式,当未定义指令执行时进入此模式。;Mode_SYS - 系统模
4、式,用于特权级的操作系统任务。;I_Bit -如果 I 位被置 1,则外部中断被禁止(IRQ isdisabled);F_Bit - 如果 F 位被置 1,则快速中断被禁止(FIQ isdisabled);-Mode_USR EQU 0x10Mode_FIQ EQU 0x11Mode_IRQ EQU 0x12Mode_SVC EQU 0x13Mode_ABT EQU 0x17Mode_UND EQU 0x1BMode_SYS EQU 0x1FI_Bit EQU 0x80 ; when Ibit is set, IRQ is disabledF_Bit EQU 0x40 ; when Fbit
5、is set, FIQ is disabled;- Stack Configuration-;下面这些主要是栈配置,系统的栈空间设定;UND_Stack_Size - 未定义模式的栈大小;SVC_Stack_Size - 管理模式的栈大小;ABT_Stack_Size - 数据访问终止模式的栈大小;FIQ_Stack_Size - 快速中断模式的栈大小;IRQ_Stack_Size - 中断模式的栈大小;USR_Stack_Size - 用户模式的栈大小;ISR_Stack_Size - 总堆栈的大小,也就是所有模式下堆栈相加-UND_Stack_Size EQU 0x00000000SVC_
6、Stack_Size EQU 0x00000008ABT_Stack_Size EQU 0x00000000FIQ_Stack_Size EQU 0x00000000IRQ_Stack_Size EQU 0x00000080USR_Stack_Size EQU 0x00000400ISR_Stack_Size EQU (UND_Stack_Size + SVC_Stack_Size +ABT_Stack_Size + FIQ_Stack_Size +IRQ_Stack_Size);-;AREA - 是一个伪指令,用于段定义。ARM 的汇编程序由段组成,段是相对独立的指令或数据单位,每个段由 A
7、REA 伪指令定义,并定义段的属性。;STACK - AREA 指令的一个参数,定义段名称;NOINIT - AREA 指令的一个参数 ,指定本数据段仅仅保留了内在单元,而将句初始值写入内存单元,也即将内存单元值初始化为 0;READWRITE- 指定本段为可读可写,数据段默认为 READWRITE。; READWRITE(读写) 、READONLY (只读);ALIGN - 是一个伪指令,指定对齐方式。ALIGN n 指令的对齐值有两种方案,即 n 或 2n,这里采用第二种方案即指定后面的指令 8 字节对齐。;ATPCS 规定数据栈必须为 FD 类型,并且对数据栈的操作时 8 字节对齐的;下
8、面这句话意思是:开辟一个堆栈段,段名字为 STACK,定义为可读可写,将内存单元初始化为 0,;-AREA STACK, NOINIT, READWRITE, ALIGN=3;-;SPACE- 伪指令,用于分配一块内存单元,并用 0 初始化,与%同义;其指令格式为:; lable SPACE expr;lable- 内存起始地址标号 expr - 所要分配的内存字节数 ;-Stack_Mem SPACE USR_Stack_Size ;堆栈内存起始地址标号_initial_sp SPACE ISR_Stack_Size ;汇编代码的地址标号Stack_Top ;堆栈段内容结束,在这里放个标号,
9、用来获得堆栈顶部地址Heap_Size EQU 0x00000000 ;定义堆大小设置;开辟一个名字为 HEAP 可读可写,不初始化内存单的内存单元。AREA HEAP, NOINIT, READWRITE, ALIGN=3_heap_base ;堆的基址Heap_Mem SPACE Heap_Size ;堆内存起始地址标号_heap_limit ;堆结束;-内存初始化定义-;在一些应用系统中除了扩展 Flash,RAM 挂接在外部存储器接口上外,可能还有其它;的外设挂接在外部存储器接口上,不同外设的操作时序什么的都是不一样的,所以;在使用这些外设之前必须初始化连接这些外设存储器接口。这里因为
10、没扩展,所以;只定义一个片上内存基地址。;-IRAM_BASE EQU 0x40000000 ;片上 SRAM 的基地址,即内存基地址;-看门狗初始化定义-;看门狗在防止程序跑飞,进入无限死循环时起着重要作用。有些应用可能用不上;看门狗功能,也可能有些应用会用到外部看门狗。在这个时候内部看门狗必须禁;止,所以有时候会在初始化时将内部看门狗禁止,当以后应用用到时再开启它。;看门狗定时器包括三个寄存器:;WTCON- 看门狗控制寄存器,设定看门狗定时器模式;WTDAT- 看门狗数据寄存器,用于设定超时宽度;WTCNT- 看门狗计数寄存器,里面存放的是看门狗定时器当前值;WT_BASE - 看门狗定
11、时器基地址;WTCON_OFS- 看门狗控制寄存器偏移地址,相对于基址;WTDAT_OFS- 看门狗数据寄存器偏移地址,相对于基址;WTCNT_OFS- 看门狗计数寄存器偏移地址,相对于基址;WT_SETUP - 看门狗设置;WTCON_Val- 看门狗控制寄存器设置,关闭看门狗;WTDAT_Val- 看门狗数据寄存器设置,初始值即为 0x8000;-WT_BASE EQU 0x53000000 ; WatchdogTimer Base AddressWTCON_OFS EQU 0x00 ; Watchdog Timer Control RegisterOffsetWTDAT_OFS EQU
12、0x04 ; Watchdog Timer DataRegister OffsetWTCNT_OFS EQU 0x08 ; Watchdog Timer CountRegister OffsetWT_SETUP EQU 0WTCON_Val EQU 0x00000000WTDAT_Val EQU 0x00008000;-时钟与电源管理定义-;S3C2440A 中的时钟控制逻辑可以产生必须的时钟信号,包括 CPU 的 FCLK,AHB 总线的;HCLK 以及 APB 总线外设的 PCLK 3C2440A 内部有两个锁相环(PLL):一个提供 FCLK,;HCLK 及 PCLK,另一个专用于 US
13、B 模块(48MHz).;CLOCK_BASE - 时钟基地址;LOCKTIME_OFS- 锁相环锁定时间计数寄存器偏移地址,相对于基址;MPLLCON_OFS - MPLL 配置寄存器偏移地址,相对于基址,主时钟源 PLL;UPLLCON_OFS - UPLL 配置寄存器偏移地址,相对于基址,USB 时钟源 PLL;CLKCON_OFS - 时钟控制寄存器偏移地址,相对于基址;CLKSLOW_OFS - 时钟减慢控制寄存器偏移地址,相对于基址;CLKDIVN_OFS - 时钟分频器控制寄存器偏移地址,相对于基址;CAMDIVN_OFS - 摄像头时钟分频器控制寄存器偏移地址,相对于基址,UP
14、LL 提供;CLOCK_SETUP - 时钟设置;LOCKTIME_Val- PLL 锁定时间计数器值;MPLLCON_Val - MPLL 配置寄存器值;UPLLCON_Val - UPLL 配置寄存器值;CLKCON_Val - 时钟配置寄存器值;CLKSLOW_Val - 时钟减慢控制寄存器值;CLKDIVN_Val - 时钟分频控制寄存器值;CAMDIVN_Val - 摄像头分频控制寄存器值;-CLOCK_BASE EQU 0x4C000000 ; ClockBase AddressLOCKTIME_OFS EQU 0x00 ; PLL Lock Time CountRegister
15、OffsetMPLLCON_OFS EQU 0x04 ; MPLL ConfigurationRegister OffsetUPLLCON_OFS EQU 0x08 ; UPLL ConfigurationRegister OffsetCLKCON_OFS EQU 0x0C ; ClockGenerator Control Reg OffsetCLKSLOW_OFS EQU 0x10 ; Clock SlowControl Register OffsetCLKDIVN_OFS EQU 0x14 ; Clock Divider ControlRegister OffsetCAMDIVN_OFS
16、EQU 0x18 ;Camera Clock Divider Register OffsetCLOCK_SETUP EQU 0LOCKTIME_Val EQU 0x0FFF0FFFMPLLCON_Val EQU 0x00043011UPLLCON_Val EQU 0x00038021CLKCON_Val EQU 0x001FFFF0CLKSLOW_Val EQU 0x00000004CLKDIVN_Val EQU 0x0000000FCAMDIVN_Val EQU 0x00000000;-存储控制器设置定义 -;下面这些都是一些关于存储控制器的地址宏定义;MC_BASE - 存储控制器基地址;
17、BWSCON_OFS - 总线宽度和等待控制寄存器偏移地址;BANKCON0_OFS- BANK1 控制寄存器偏移地址; .; .;BANKCON7_OFS- BANK7 控制寄存器偏移地址;REFRESH_OFS - DRAM/SDRAM 刷新控制寄存器偏移地址;BANKSIZE_OFS- 可调的 bank 大小寄存器偏移地址;MRSRB6_OFS - bank6 模式控制寄存器偏移地址;MRSRB7_OFS - bank7 模式控制寄存器偏移地址;MC_SETUP - 存储器控制寄存器设置;BWSCON_Val - 写入总线宽度和等待控制寄存值;BANKCON0_Val- 写入 Blank
18、0 的值; .; .;BANKCON7_Val- 写入 BANK7 的值;REFRESH_Val - 写入 DRAM/SDRAM 刷新控制寄存的值;BANKSIZE_Val- 写入可调的 bank 大小寄存的值;MRSRB6_Val - 写入 bank6 模式控制寄存器的值;MRSRB7_Val - 写入 bank7 模式控制寄存器的值;-MC_BASE EQU 0x48000000 ; MemoryController Base AddressBWSCON_OFS EQU 0x00 ; Bus Width and WaitStatus Ctrl OffsetBANKCON0_OFS EQU
19、0x04 ; Bank 0 ControlRegister OffsetBANKCON1_OFS EQU 0x08 ; Bank 1 ControlRegister OffsetBANKCON2_OFS EQU 0x0C ; Bank 2 ControlRegister OffsetBANKCON3_OFS EQU 0x10 ; Bank 3Control Register OffsetBANKCON4_OFS EQU 0x14 ; Bank 4Control Register OffsetBANKCON5_OFS EQU 0x18 ;Bank 5 Control Register Offse
20、tBANKCON6_OFS EQU 0x1C ; Bank 6Control Register OffsetBANKCON7_OFS EQU 0x20 ;Bank 7 Control Register OffsetREFRESH_OFS EQU 0x24 ; SDRAM RefreshControl Register OffsetBANKSIZE_OFS EQU 0x28 ; Flexible Bank Size Register OffsetMRSRB6_OFS EQU 0x2C ; Bank 6 ModeRegister OffsetMRSRB7_OFS EQU 0x30 ; Bank 7
21、Mode Register OffsetMC_SETUP EQU 1BWSCON_Val EQU 0x22000000BANKCON0_Val EQU 0x00000700BANKCON1_Val EQU 0x00000700BANKCON2_Val EQU 0x00000700BANKCON3_Val EQU 0x00000700BANKCON4_Val EQU 0x00000700BANKCON5_Val EQU 0x00000700BANKCON6_Val EQU 0x00018005BANKCON7_Val EQU 0x00018005REFRESH_Val EQU 0x008404F
22、3BANKSIZE_Val EQU 0x00000032MRSRB6_Val EQU 0x00000020MRSRB7_Val EQU 0x00000020;-I/O 端口宏定义-;GPA_BASE - 端口 A 基地址; .;GPJ_BASE - 端口 J 基地址;GPCON_OFS - 端口配置寄存器偏移地址;GPDAT_OFS - 端口数据寄存器偏移地址;GPUP_OFS - 端口上拉寄存器偏移地址;GP_SETUP - 端口设置;GPA_SETUP - 端口 A 配置;GPACON_Val- 写入端口 A 配置寄存器的值; .; .;GPJ_SETUP - 端口 J 配置;GPJCON
23、_Val- 写入端口 J 配置寄存器的值;GPJUP_Val - 写入端口 J 上拉寄存器的值;-GPA_BASE EQU 0x56000000 ; GPA BaseAddressGPB_BASE EQU 0x56000010 ; GPB BaseAddressGPC_BASE EQU 0x56000020 ; GPC BaseAddressGPD_BASE EQU 0x56000030 ; GPD BaseAddressGPE_BASE EQU 0x56000040 ; GPE BaseAddressGPF_BASE EQU 0x56000050 ; GPF BaseAddressGPG_B
24、ASE EQU 0x56000060 ; GPG BaseAddressGPH_BASE EQU 0x56000070 ; GPH BaseAddressGPJ_BASE EQU 0x560000D0 ; GPJ BaseAddressGPCON_OFS EQU 0x00 ;Control Register OffsetGPDAT_OFS EQU 0x04 ; DataRegister OffsetGPUP_OFS EQU 0x08 ;Pull-up Disable Register OffsetGP_SETUP EQU 1;-;端口 A 配置;-GPA_SETUP EQU 0GPACON_V
25、al EQU 0x000003FF;-;端口 B 配置;-GPB_SETUP EQU 0GPBCON_Val EQU 0x00000000GPBUP_Val EQU 0x00000000 ;-;端口 C 配置;-GPC_SETUP EQU 0GPCCON_Val EQU 0x00000000GPCUP_Val EQU 0x00000000;-;端口 D 配置;-GPD_SETUP EQU 0GPDCON_Val EQU 0x00000000GPDUP_Val EQU 0x00000000;-;端口 E 配置;-GPE_SETUP EQU 0GPECON_Val EQU 0x00000000GP
26、EUP_Val EQU 0x00000000;-;端口 F 配置;-GPF_SETUP EQU 0GPFCON_Val EQU 0x00000000GPFUP_Val EQU 0x00000000;-;端口 G 配置;-GPG_SETUP EQU 0GPGCON_Val EQU 0x00000000GPGUP_Val EQU 0x00000000;-;端口 H 配置;-GPH_SETUP EQU 0GPHCON_Val EQU 0x00000000GPHUP_Val EQU 0x00000000 ;-;端口 J 配置;-GPJ_SETUP EQU 0GPJCON_Val EQU 0x00000
27、000GPJUP_Val EQU 0x00000000;-;PRESERVE8- 伪指令,指示当前文件请求堆栈为 8 字节对齐。; 汇编程序数据 8 字节对齐,c 和汇编有 8 位对齐的要求 .;-PRESERVE8;-;存储区设定和程序入口点;启动代码必须连接到第一个地址才能运行;下面这句话的意思是:; 声明一个名为 RESET 的代码段, 属性为只读;-AREA RESET, CODE, READONLYARM ;ARM 模式运行程序;- ;IMPORT- 相当于 C 语言中的关键字 extern; 指当前的符号在其他源文件中定义的,在本源文件中可能引用该符号.;EXPORT- 相当于 C
28、 语言中的关键字 global; 声明一个符号可以被其它文件引用.相当于声明了一个全局变量;下面这几句话是的意思是:; 如果定义了_EVAL 这个变量,引用 RO 输出区的字节长度与 RW 输出区的字节长度;注意:;ARM 连接器定义了一些包含$的符号。这些符号及其他所有包含$的名称都是 ARM 的;保留字。这些符号被用于指定域的基地址,输出段的基地址和输入段的基地址及其;大小。我们可以自己的汇编语言程序中引用这些符号地址,把它们用作可重定位的;地址,也可能在 C 或 C+代码中使用 extern 关键字来引用它们。这个可以查看 uVision;Help 的 Region-relatedsym
29、bols 这一节。;-IF :LNOT:DEF:_EVAL ;逻辑判断是否定义了_EVAL 这个变量IMPORT |Image$ER_ROM1$RO$Length|IMPORT |Image$RW_RAM1$RW$Length|ENDIF;-; 异常向量,映射到地址 0,必须使用绝对寻址方式,子程序用无限循环方式;实现可以被修改。;-Vectors LDR PC, Reset_Addr ;将复位地址装载到程序指针,即复位 LDR PC, Undef_Addr ;未定义指令LDR PC, SWI_Addr ;软件中断LDR PC, PAbt_Addr ;中止(预取)LDR PC, DAbt_Ad
30、dr ;中止(数据)IF :DEF:_EVAL ;如果定义了_EVAL 变量DCD 0x4000 ;分配 2k 空间ELSE ;否则分配空间大小为 RO 输出区的字节;长度与 RW 输出区的字节长度之和DCD |Image$ER_ROM1$RO$Length|+|Image$RW_RAM1$RW$Length|ENDIFLDR PC, IRQ_Addr ;外部中断LDR PC, FIQ_Addr ;快速中断IF :DEF:_RTX ;如果定义了_RTXIMPORT SWI_Handler ;则定义中断子程序IMPORT IRQ_Handler_RTX ;定义快速中断子程序ENDIF;-;下面这
31、几句的任务是把各个子程序的入口地址分配给相应的地址变量;-Reset_Addr DCD Reset_Handler ;复位子程序入口地址赋值给 Reset_AddrUndef_Addr DCD Undef_Handler ;未定义子程序入口地址赋值给 Undef_Addr SWI_Addr DCD SWI_Handler ;中断子程序入口地址赋值给 SWI_AddrPAbt_Addr DCD PAbt_Handler ;中止(预存)子程序入口地址赋给 PAbt_AddrDAbt_Addr DCD DAbt_Handler ;中止(数据) 子程序入口地址赋给 DAbt_AddrDCD 0 ;保留
32、地址 IF :DEF:_RTX ;如果定义了_RTXIRQ_Addr DCD IRQ_Handler_RTX ;快速中断子程序入口地址给 IRQ_AddrELSEIRQ_Addr DCD IRQ_Handler ;否则把 IRQ_Handler 入口地址给 IRQ_AddrENDIFFIQ_Addr DCD FIQ_Handler ;快速中断入口地址给 FIQ_Addr;-;这些子程序都是用无限循环方式实现的可以被修改。;-Undef_Handler B Undef_Handler ;跳转到Undef_Handler,还是在这个地方IF :DEF:_RTX ;如果定义了 DEF:_RTX,在此
33、等待中断ELSESWI_Handler B SWI_Handler ;否则跳转到软件中断ENDIFPAbt_Handler B PAbt_Handler ;中止(预存)子程DAbt_Handler B DAbt_Handler ;中止( 数据)子程;-;外部中断子程序; 如果函数标有 PROC 与 ENDP,但没有 FRAMEPUSH 或 FRAME POP,则堆栈作用量;假定为 0.这意味着无需手动添加 FRAMEPUSH 0 或 FRAMEPOP 0;- IRQ_Handler PROCEXPORT IRQ_Handler WEAK ;声明一个全局变量,并且其它;同名符优先于本符号被引用B . ;跳转到当前地址即在此等待“.”代表当前指令地址ENDPFIQ_Handler ;快速中断子程序 B FIQ_Handler;-;复位子程序;-EXPORT Reset_Handler ; 声明一个全局变量Reset_Handler ;-;配置看门狗;前面已经初始化 WT_SETUP = 0,要想执行下面的程序需将 WT_SETUP 置 1;-