s3c2440setup.s中的代码如下:
PRESERVE8AREA RESET,CODE,READONLYARM ;CODE32sdram_base EQU 0x30000000
cp_space EQU 4*1024ENTRY
start;init watchdogldr r0,=0x53000000mov r1,#0str r1,[r0];init memorybl memory_crl_init;copy code to sdrambl copytosdramldr pc,=0x30000018 ;跳转到sdRAM中执行,这条指令上面已经有了五条指令,所以这条指令在norflash;地址是0x14所以等价于在SDRAM中的0x30000014,跳到下一条指令则跳入sdram执行和程序;程序在SDram中运行,led的闪烁速度明显比在norflash要好的多ldr sp,=0x34000000 ;重新设置堆栈IMPORT led_blinkbl led_blink;;;;;;;;;;;;;;;;;;
memory_crl_initldr r0,=0x48000000 ;start address of memory_crl registerldr r1,=0x48000034 ;end address of memory_crl registeradr r2,memdata
memory_crl_loopldr r3,[r2],#4str r3,[r0],#4teq r0,r1 ; equal cmpbne memory_crl_loop ;not equal,b memorymov pc,lr
;;;;;;;;;;;;;;;;;
copytosdramldr r0,=0x0ldr r1,=sdram_base
cpldr r2,[r0],#4str r2,[r1],#4cmp r0, #cp_spacebne cpmov pc,lr
;;;;;;;;;;;;
memdataDCD 0x22000000 ;BWSCONDCD 0x00000700 ;BANKCON0 DCD 0x00000700 ;BANKCON1 DCD 0x00000700 ;BANKCON2 DCD 0x00000700 ;BANKCON3 DCD 0x00000700 ;BANKCON4 DCD 0x00000700 ;BANKCON5 DCD 0x00018005 ;BANKCON6 DCD 0x00018005 ;BANKCON7 DCD 0x008e07a3 ;REFRESH DCD 0x000000b1 ;BANKSIZE DCD 0x00000030 ;MRSRB6 DCD 0x00000030 ;MRSRB7END
delay.s代码如下:
;汇编指令延时程序 EXPORT delayAREA DELAY,CODE,READONLY ;该伪指令定义了一个代码段,段名为DELAY,属性只读;下面是延迟子程序
delaysub r0,r0,#1 ;r0=r0-1 cmp r0,#0x0 ;将r0的值与0相比较bne delay ;比较的结果不为0(r0不为0),继续调用delay,否则执行下一条语句mov pc, lr ;返回END ;程序结束符
led_blink.s代码如下:
EXPORT led_blinkIMPORT delay ;调用delay;;;;;;;;;;;;;;;;;AREA LED_BLINK,CODE,READONLYCODE32
led_blink proc ;定义函数led_blink;设置GPF为输出ldr r0,=0x56000050 ;config CONldr r1,=0x00005555str r1,[r0]
loopldr r0,=0x56000054 ;config DATmov r1,#0 ;低电平灯亮str r1,[r0]ldr r0,=0xfffbl delayldr r0,=0x56000054 ;config DATmov r1,#0xFF ;高电平灯灭str r1,[r0]ldr r0,=0xfff ;调用delaybl delayb loopENDP
上面三个文件均为arm的汇编文件,并在Keil for arm4中实验得到正确结果。也是我刚接触arm汇编指令的第一个完整的汇编代码。其功能可以简单的描述为,将sram或norflash中的0-4K的代码复制到SDram中,并跳转到SDram中执行调用闪灯程序。在s3c2440setup.s中主要完成一些初始化工作:关闭看门口,初始化堆栈,初始化存储控制器。cpu上电从0x0地址开始执行,这里应用最多的几个指令有bl:跳转指令,并存储断点地址到lr中,所以在执行完跳转内容后,总会有一句mov pc,lr恢复原来的状态。还有一个是ldr,这个指令是加载指令,从内存中加载数据到寄存器,加载的地址范围也比较大。str是存储指令,是将寄存器的数据存储到内存中。详细调用过程可以阅读代码。
这里写一下初始化过程,为什么要关闭看门狗,为什么要初始化堆栈,为什么要初始化存储控制器?
如左图,看门狗定时器控制寄存器在上电是初始化为使能复位信号,这样程序在执行的时候不停的产生复位信号。初始化堆栈的作用是存放断点,断点包括中断,和函数调用的时候产生,所以一般在进行函数调用和中断使能之前都要初始化堆栈。初始化存储控制器的原因是为了下载程序到存储器中,其中包括flash和ram。