SDRAM例程:
从Nand Flash启动CPU时,CPU会自动将Nand Flash开始的4K数据复制到4KB的内部Ram中(起始地址0),然后地址0开始执行。
本例程先用汇编设置好SDRAM,将程序从内部Ram复制到SDRAM,然后跳转到SDRAM执行。
源代码包括sdram.S、gpio.c、s3c2440.h,编译为二进制文件后烧写到NandFlash运行。
sdram.S如下:
1.@*****************************************
2.@ File name : sdram.S
3.@ Project name: sdram
4.@ Author : Bob
5.@ Date : 2011-7-9
6.@ Description : 设置SDRAM,将steppingstone中的程序复制到sdram,然后跳转到sdram执行。
7.@*****************************************
8.
9..data
10..equ MEM_CTL_BASE, 0x48000000 @ 存储器控制器的寄存器首地址
11..equ SDRAM_BASE, 0x30000000 @ sdram的起始地址
12.
13..text
14..global _start
15._start:
16. bl disable_watch_dog
17. bl memsetup
18. bl copy_steppingstone_to_sdram
19. ldr pc, =on_sdram @ 跳转到on_sdram,这是sdram中的地址
20.
21.on_sdram:
22. ldr sp, =0x34000000 @设置栈
23. bl main
24.halt_loop:
25. b halt_loop
26.
27.@ 禁止watch dog
28.disable_watch_dog:
29. mov r1, #0x53000000 @ watch dog 寄存器的地址
30. mov r2, #0x0
31. str r2, [r1]
32. mov pc, lr @返回
33.
34.@ 将steppingstone的内容全部复制到sdram
35.copy_steppingstone_to_sdram:
36. mov r1, #0 @ r1存放steppingstone的起始地址
37. ldr r2, =SDRAM_BASE @ r2存放sdram的起始地址
38. mov r3, #4*1024 @ steppingstone的大小时4KB
39.1:
40. ldr r4, [r1],#4 @ 从steppingstone中读取4Byte,[r1]->r4,r1=r1+4
41. str r4, [r2],#4 @ 将4Byte复制到sdram,r4->[r2],r2=r2+4
42. cmp r1, r3 @ 判断是否复制完4KB,r1等于4*1023时,复制结束
43. bne 1b @ 如果不相等,跳回1处
44. mov pc, lr @ 返回
45.
46.@ 设置存储器控制器的寄存器
47.memsetup:
48. mov r1, #MEM_CTL_BASE @ r1存放存储器控制器的寄存器首地址
49. adrl r2, mem_cfg_val @ r2存放mem_cfg_val的起始地址
50. add r3, r1,#52 @ r3=r1+52,r3存放mem_cfg_val的结束地址,有13个寄存器,13*4=52
51.1:
52. ldr r4, [r2],#4
53. str r4, [r1],#4
54. cmp r1, r3
55. bne 1b
56. mov pc, lr
57.
58.@ 存储器控制器的13个寄存器的值
59..align 4 @ 以下数据都以4Byte对齐
60.mem_cfg_val:
61. .long 0x22011110 @ BWSCON
62. .long 0x00000700 @ BANKCON0
63. .long 0x00000700 @ BANKCON1
64. .long 0x00000700 @ BANKCON2
65. .long 0x00000700 @ BANKCON3
66. .long 0x00000700 @ BANKCON4
67. .long 0x00000700 @ BANKCON5
68. .long 0x00018005 @ BANKCON6
69. .long 0x00018005 @ BANKCON7
70. .long 0x008c07a3 @ REFRESH
71. .long 0x000000b1 @ BANKSIZE
72. .long 0x00000030 @ MRSRB6
73. .long 0x00000030 @ MRSRB6
说明:
ldr:
当第二个操作数前面没有“=”时,表示内存访问指令,从内存中读取4Byte数据到寄存器,语法格式如下:
ldr{条件} 目的寄存器, 存储器地址
如果第二个操作数前面有“=”,表示大范围地址读取伪指令,用于加载32位的立即数或一个地址到指定寄存器,语法格式如下:
ldr 目的寄存器, =32位立即数/地址
str:
内存访问指令,从源寄存器将一个32位数据传送到存储器中,语法格式如下:
str{条件} 源寄存器, 存储器地址
adrl r2, mem_cfg_val:
adrl是中等范围地址读取伪指令,将基于pc相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中,在汇编编译器编译源程序时,adrl伪指令被编译器替换成两条合适的指令。若不能用两条指令实现,则产生错误,编译失败。这条代码会替换为:
30000050: e28f2018 add r2, pc, #24 ; 0x18
30000054: e1a00000 nop (mov r0,r0)
adrl伪指令格式:
adrl{cond} register, expr
地址表达式expr的取值范围:
当地址值是字节对齐时,其取指范围为: -64K~64K;
当地址值是字对齐时,其取指范围为: -256K~256K;
nop:
空操作伪指令,在汇编是替换成ARM中的空操作,例如mov r0, r0
cmp:
比较指令,格式如下:
cmp{条件} 操作数1, 操作数2
用与将一个寄存器的内容和另一寄存器的内容或立即数进行比较,然后更新CPSR中条件标志位的值,标志位表示操作数1和操作数2的关系(大于、小于、相等)。
bne 1b:
b(跳转指令)+ne(条件:不相等),如果CPSR的Z位为0(不相等),就跳转到后面的1标号处。
b表示向后搜索,已经执行过的代码为‘后’;
f表示向前搜索,还未执行的代码为‘前’。
mov pc, lr
从子程序返回。lr为子程序链接寄存器(r14),当执行bl子程序调用指令时,lr会备份pc(程序计数器r15)。
.align
指定对齐方式,gnu汇编命令都以一个点开头。
.equ
赋值命令,格式如下:
.equ symbol, expression
设置symbol的值为expression。
.long
定义一个4Byte的数据。