S3C2416裸机开发系列三_启动代码以及流水灯c代码
扫描二维码
随时随地手机看文章
启动代码是处理器上电复位后最先运行的一段代码。主要是用来把处理器初始化到一个确定的状态,为c运行环境作好准备。如设置异常向量表,初始化系统时钟,初始化外部内存,把用户代码拷贝到外部内存,初始化栈,清0全局变量区,静态变量区等。与体系结构相关的部分,只能用汇编来写。由于S3C2416/50/51目前在各个编译器中都还没有启动代码文件,因此笔者在MDK下主要参考S3C2440的启动代码来写一个S3C2416的启动代码。
1. 启动代码流程启动代码的内容,顺序等都没有特定的要求,只要能达到初始化c运行环境即可。这里笔者说明一下,编写的启动代码应该是地址无关的,即链接到任存储器地址都是可以运行的。如S3C2416在nand boot/Norboot时用户的第一条代码是在0x0处执行的,而在IROM boot时,用户的第一条代码是在0x40000000处执行的,启动代码对不同的启动模式都是要能正确运行的。此外,启动代码文件内容应该是板级无关的,不同的开发板,只要是同一处理器(S3C2416/50/51),启动代码文件都是适用的。即板级的代码如GPIO口的初始化不适合放在启动代码中实现。此处笔者只以笔者的启动代码思路来作讲解。
1.1. 异常向量表处理器在上电复位完成后,第一条代码进入的是异常向量表中对应的复位向量地址。对于arm,这个异常向量表的地址通常是0x00000000偏移处,如发生复位,则arm进入0x0处的复位向量地址,发生IRQ中断则进入0x18处的IRQ异常向量地址。异常向量表就是用来记录各个异常进入时的代码处理位置。
1.2. 关看门狗复位代码最先做的事应该是关看门狗,因为如果看门狗打开的话,在启动代码进行初始化过程中是无法喂狗的,可能造成处理器一直不停复位。
1.3. 关闭所有中断启动代码未完成时,各个状态都还不是确定的,如果有中断打开并引起中断异常,可能造成代码跑飞。
1.4. 初始化系统时钟一般来说,处理器复位后都是运行在一个较低速的时钟下,为加快启动,通常尽可能快地设置处理器的各个时钟。
1.5. 初始化外部内存除了Nor flash可以直接执行代码外,其它的代码存储器如nand flash、sd/mmc都是不能直接执行代码的。因此需要初始化外部内存,用来存储代码,变量。(本章节为避免复杂化,暂时不讲解,注释掉调用DDR2的初始化及用户代码的搬移)
1.6. 用户代码拷贝到外部内存对于代码存储在nand、sd/mmc等不能直接执行代码的存储器,初始代码是一定需要把用户代码从这些设备读入到特定的内存中执行的。而对于Nor flash可直接执行代码的存储器,通常为了提高性能,也是会把代码从Nor flash读出,在内存中执行的。
1.7. MMU初始化MMU的初始化不总是必须的,主要是为提高性能,开D-cache必须开MMU。如果是IROM SD/MMC或IROM NAND方式运行代码,用到了中断,则也必须开MMU,因为IROM启动在0x0地址处为IROM固化代码,需要对中断向量表重新映射到RAM。(本章节为避免复杂化,暂时不讲解,注释掉MMU的初始化)
1.8. 初始化栈不管是用汇编还是用c编写代码,栈是一定要分配及初始化的。arm7/arm9有七种工作模式,每种模式的栈均应该设置,最后是进入用户模式。
1.9. 跳转到c入口进入c入口之前是需要初始化c环境的,如清0全局变量、静态变量区等。此处为保持跟MDK的其它arm启动代码一致,直接跳转到__main,利用编译器的库函数来完成c环境的初始化,最后才是真正的用户main函数。启动代码完成后,最后是用绝对地址来跳转到c入口__main的。
2. 启动代码的实现笔者对启动代码都是有一定的注释,有些寄存器的设置是需要参考芯片数据手册,S3C2416数据手册,arm架构以及汇编语法学习笔者在之前的文章已给出相关资料的链接,欢迎下载学习。只要加入了启动代码,就可以任意用c语言来开发S3C2416了。
;/*******************************************************/
;/* s3c2416.s: start code forsamsung s3c2416/50/51(arm9) */
;/********************************************************/
; Clock setting(External Crystal12M):
; MPLLCLK = 800M, EPLLCLK = 96M
; ARMCLK = 400M, HCLK = 133M
; DDRCLK = 266M, SSMCCLK = 66M,PCLK = 66M
; HSMMC1 = 24M
; Standard definitions of Mode bitsand Interrupt (I & F) flags in PSRs
Mode_USR EQU0x10
Mode_FIQ EQU0x11
Mode_IRQ EQU0x12
Mode_SVC EQU0x13
Mode_ABT EQU0x17
Mode_UND EQU0x1B
Mode_SYS EQU0x1F
; when I bit is set, IRQ isdisabled
I_Bit EQU 0x80
; when F bit is set, FIQ isdisabled
F_Bit EQU 0x40
; Stack Configuration
UND_Stack_Size EQU0x00000020
SVC_Stack_Size EQU0x00000020
ABT_Stack_Size EQU0x00000020
FIQ_Stack_Size EQU0x00000100
IRQ_Stack_Size EQU0x00000400
USR_Stack_Size EQU0x00001000
ISR_Stack_Size EQU(UND_Stack_Size + SVC_Stack_Size +
ABT_Stack_Size+ FIQ_Stack_Size +
IRQ_Stack_Size)
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACEUSR_Stack_Size
__initial_sp SPACE ISR_Stack_Size
Stack_Top
; Heap Configuration
Heap_Size EQU0x00000200
AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem SPACEHeap_Size
__heap_limit
; Internal Memory Base Addresses
IRAM_BASE EQU0x40000000
; Watchdog Timer Base Address
WT_BASE EQU0x53000000
; Interrupt Register Base Address
INT_BASE EQU 0x4A000000
INTMSK1_OFS EQU 0x08
INTSUBMSK_OFS EQU 0x1C
INTMSK2_OFS EQU 0x48
; Clock Base Address
CLOCK_BASE EQU 0x4C000000
LOCKCON0_OFS EQU 0x00
LOCKCON1_OFS EQU 0x04
MPLLCON_OFS EQU 0x10
EPLLCON_OFS EQU 0x18
CLKSRC_OFS EQU 0x20
CLKDIV0_OFS EQU 0x24
CLKDIV1_OFS EQU 0x28
CLKDIV2_OFS EQU 0x2C
;----------------------- CODE-------------------------------------------
PRESERVE8
;Area Definition and Entry Point
;Startup Code must be linked first at Address at which it expects to run.
AREA RESET, CODE, READONLY
; ENTRY