ARMBoot-1.1.0 在 mini2440 开发板上的移植 之稻草人手记
< snallieATtomDOTcom >
作为U-boot的鼻祖-ARMboot以其小巧玲珑(代码压缩包仅有400K多),但又麻雀虽小,五脏俱全,不失为研究U-boot的第一步,
而且在ARMboot中处处还能看到U-boot的影子。好啦,开始我们的移植之旅吧。
移植目标: 驱动串口;驱动网络芯片dm9000;实现内核的下载(uImage);实现启动 Linux kernel(zImage),实现Nand Flash启动
移植版本: ARMboot-1.1.0
ARMboot在哪: http://www.sourceforge.net/projects/armboot
交叉编译器: arm-linux-gcc 2.95.3 (在该版本下可以一次编译成功,所以采用该版本的交叉编译器)
开发板配置: RAM:64MB,Nor:2MB,Nand:64MB,Processor:Samsung S3C2440网卡芯片:dm9000
操作系统环境: RedHat Linux 9.0
环境查看:
编译器:
[root@arms root]# arm-linux-gcc -v
Reading specs from /usr/local/arm/2.95.3/lib/gcc-lib/arm-linux/2.95.3/specs
gcc version 2.95.3 20010315 (release)
源代码包:
[root@arms arms]# ls -l
total 428
-rw-r--r-- 1 root root 431099 Feb 25 2007 armboot-1.1.0.tgz
解压源码包:
[root@arms arms]# tar zxvf armboot-1.1.0.tgz
进入源码目录:(之后的所用工作均在该目录下完成)
[root@arms arms]# cd armboot-1.1.0
[root@arms armboot-1.1.0]#
armboot-1.1.0已经支持smdk2410开发板,该开发板和mini2440有一定的相似性,我们在
在SMDK2410开发板的基础上进行移植。
测试smdk2410是否能通过编译:
[root@arms armboot-1.1.0]# make distclean; make smdk2410_config ; make all
通过编译,查看生成的文件如下:
[root@arms armboot-1.1.0]# ls -altr
-rwxr-xr-x 1 root root 224812 May 24 08:43 armboot.srec
-rw-r--r-- 1 root root 28391 May 24 08:43 armboot.map
-rw-r--r-- 1 root root 210779 May 24 08:43 armboot.hex
-rwxr-xr-x 1 root root 74916 May 24 08:43 armboot.bin
-rwxr-xr-x 1 root root 91185 May 24 08:43 armboot
其中的armboot.bin即为最终的可以烧写到NandFlash的文件,由于代码还需修改,现在这个文件还不能适应mini2440的开发板环境,
上面的过程只是验证了smdk2410的配置即程序文件可以在arm-linux-gcc 2.95.3顺利编译通过,我们还需对代码做进一步的修改使得
其可以运行在到MINI2440上。
下面开始进行MINI2440的移植,为便于查看,将所涉及到的代码的行首都加了行号标示。
*************************************************************************************************************************************************
** 初步移植,复制关于SMDK2410的全部文件,并做相应地修改,在smdk2410的基础上构建MINI2440的代码环境
*************************************************************************************************************************************************
0) 清除上面的编译结果:
[root@arms armboot-1.1.0]# make distclean
1) 复制smdk2410_config的配置文件(注:所有板子的配置文件均在include/configs下)
[root@arms armboot-1.1.0]# cp include/configs/config_smdk2410.h include/configs/config_mini2440.h
复制完成后在config_mini2440.h做一个简单的修改标记-该变提示符:(建议:修改时先做做备份-即注释掉原来的代码,而后改成新的),
可用如下的sed 命令直接修改(用sed脚本修改只可执行1遍,切勿多次执行!)
[root@arms armboot-1.1.0]# sed -i'~' -e "/^/(#define/tCFG_PROMPT..*/)/ {N; s//(..*/)/n//1 snallie, `date +%F_%H%M%S_%a`/n/1 snallie, `date +%F_%H%M%S_%a`/n/g; s/SMDK2410/ARMboot@MINI2440/2 }" include/configs/config_mini2440.h
或者用vi进行全屏幕编辑修改:
[root@arms armboot-1.1.0]# vi +99 include/configs/config_mini2440.h
具体修改的位置为:
改
99 #define CFG_PROMPT "SMDK2410 # " /* Monitor Command Prompt */
为:
99 //#define CFG_PROMPT "SMDK2410 # " /* Monitor Command Prompt */ // snallie, 2011-05-24_090111_Tue
100 #define CFG_PROMPT "ARMboot@MINI2440 # " /* Monitor Command Prompt */ // snallie, 2011-05-24_090111_Tue
2) 拷贝smdk2410的板级的程序文件为mini2440
[root@arms armboot-1.1.0]# cp -a board/smdk2410/ board/mini2440
3) 修改mini2440的板级的Makefile,文件位置在 board/mini2440/Makefile
改
28 OBJS := smdk2410.o flash.o env.o
为:
28 # OBJS := smdk2410.o flash.o env.o # snallie, 2011-05-24_091150_Tue
29 OBJS := mini2440.o flash.o env.o # snallie, 2011-05-24_091150_Tue
可用如下的sed 命令直接修改:(用sed脚本修改只可执行1遍,切勿多次执行!)
[root@arms armboot-1.1.0]# sed -i'~' -e "/^/(OBJS/t:= smdk2410.o..*/)/ {N; s//(..*/)/n/# /1 # snallie, `date +%F_%H%M%S_%a`/n/1 # snallie, `date +%F_%H%M%S_%a`/n/g; s/smdk2410/mini2440/2 }" board/mini2440/Makefile
或者用vi进行全屏幕编辑修改:
[root@arms armboot-1.1.0]# vi +28 board/mini2440/Makefile
4) 修改mini2440的板级的文件名,涉及文件为 board/mini2440/smdk2410.c
[root@arms armboot-1.1.0]# mv board/mini2440/smdk2410.c board/mini2440/mini2440.c
5) 修改顶层的Makefile:找到smdk2410_config,仿照smdk2410_config,添加mini2440_config,如下:
200 smdk2410_config : unconfig
201 @echo "Configuring for $(@:_config=) Board..." ; /
202 cd include ; /
203 echo "ARCH = arm" > config.mk ; /
204 echo "BOARD = smdk2410" >>config.mk ; /
205 echo "CPU = arm920t" >>config.mk ; /
206 echo "#include <configs/config_$(@:_config=).h>" >config.h
207
208 # snallie, 2011-05-24_091758_Tue
209 mini2440_config : unconfig
210 @echo "Configuring for $(@:_config=) Board..." ; /
211 cd include ; /
212 echo "ARCH = arm" > config.mk ; /
213 echo "BOARD = mini2440" >>config.mk ; /
214 echo "CPU = arm920t" >>config.mk ; /
215 echo "#include <configs/config_$(@:_config=).h>" >config.h
216
可用如下的sed 命令直接修改:(用sed脚本修改只可执行1遍,切勿多次执行!)
[root@arms armboot-1.1.0]# sed -i'~' -e "/smdk2410/,+7 {N;N;N;N;N;N;N; s//(..*/)/n/(..*/)/n/(..*/)/n/(..*/)/n/(..*/)/n/(..*/)/n/(..*/)/n/&/n# snallie, `date +%F_%H%M%S_%a`/n/1/n/2/n/3/n/4/n/5/n/6/n/7/n/g;s/smdk2410/mini2440/3;s/smdk2410/mini2440/3 } " -e "/backup/,/gtar/ {N;N;N; s//(..*/)/n/(..*/)/n/(..*/)/n/#/1/n#/2/n#/3/n/n# snallie, `date +%F_%H%M%S_%a`/n/1/n/2/n/3/n/g; s//"/([^/n]*/)/(/.tar/.gz/)//"+/$/$F-gk-%Y%m%d_%H%M%S/2/2 } " -e "/^armboot.bin/ {N;N;N; s//(..*/)/n/(..*/)/n/(..*/)/n//1/n/2/n# snallie, `date +%F_%H%M%S_%a`/n#/3/n/g }" Makefile
或者用vi进行全屏幕编辑修改:
[root@arms armboot-1.1.0]# vi +200 Makefile
注意:用vi手工修改时候,Makefile中的新添的210~215行的行首为制表符(TAB键),而不是空格,若输入的是空格,则编译出错
6) 程序的版本号有误,修改:include/version.h
改:
28 #define ARMBOOT_VERSION "ARMboot 1.0.2"
为:
28 //#define ARMBOOT_VERSION "ARMboot 1.0.2"
29 #define ARMBOOT_VERSION "ARMboot 1.1.0" // snallie, 2011-05-24_093229_Tue
可用如下的sed 命令直接修改:(用sed脚本修改只可执行1遍,切勿多次执行!)
[root@arms armboot-1.1.0]# sed -i'~' -e "/1.0.2/ {N; s//(..*/)/n//1/n/1/g; s/1.0.2/"/1.1.0/"/t snallie, `date +%F_%H%M%S_%a`/n/2;}" include/version.h
或者用vi进行全屏幕编辑修改
[root@arms armboot-1.1.0]# vi +28 include/version.h
7) 关于SMDK2410的全部文件复制完成,编译测试:
[root@arms armboot-1.1.0]# make distclean; make mini2440_config; make all
通过编译!
*************************************************************************************************************************************************
** 进一步的移植,完成目标中的全部工作:驱动串口;驱动网络芯片dm9000;实现内核的下载(uImage);实现启动 Linux kernel(zImage),实现Nand Flash启动
*************************************************************************************************************************************************
mini2440板配置初步完成,下面进行具体的移植工作,由于SMDK2410 的代码和MINI2440板子略有出入,SMDK2410代码认为程序是直接在NOR或RAM中运行,
而我们的代码最终是烧写到NandFlash中的,可NandFlash不具有片上执行代码的能力,所以程序启动的第一步就是要将整个的程序从NandFlash中搬移到RAM中,
即TEXT_BASE(配置在board/mini2440/config.mk文件中)的起始地址上去。另外SAMSUNG的S3C2440的处理器在系统启动时候会自动将NandFlash的前4K的代码
移动到内部的4K大小的称为Steppingstone的SRAM中运行,所以搬移用的代码必须放到程序映像的头部的4K的范围内,否则不能正常启动。综上所述,对SMDK2410
代码的改造主要为:实现代码的搬移工作,并将搬移用的代码放到程序映像的头部的4K的范围内;而后要驱动串口,这样我们才能获取到程序的运行时的输出状态
信息,串口驱动不起来等于是瞎子一样,所以串口驱动很重要,有了串口还可通过串口下载小体积的代码;在这之后再驱动网络芯片,实现网络下载代码,启动内核等等。
查看SMDK2410的代码,知道和CPU相关的代码通过在include/configs/config_smdk2410.h的宏定义CONFIG_S3C2410进行控制,和开发板SMDK2410相关的代码通过
在include/configs/config_smdk2410.h的宏定义CONFIG_SMDK2410进行控制,如下所示:
#define CONFIG_S3C2410 1 /* in a SAMSUNG S3C2410 SoC */
#define CONFIG_SMDK2410 1 /* on an SAMSUNG SMDK2410 Board */
顺着这个线索,我们看看在原有的SMDK2410的代码有那些和CONFIG_S3C2410和CONFIG_SMDK2410的代码,以及它们分布在那些文件中:
和CONFIG_S3C2410相关的:
[root@arms armboot-1.1.0]# grep -rHn CONFIG_S3C2410 *
cpu/arm920t/interrupts.c:36:#elif defined(CONFIG_S3C2410)
cpu/arm920t/serial.c:25:#elif defined(CONFIG_S3C2410)
cpu/arm920t/start.S:134:#elif defined(CONFIG_S3C2410)
cpu/arm920t/start.S:153:#if defined(CONFIG_S3C2410)
include/configs/config_smdk2410.h:43:#define CONFIG_S3C2410 1 /* in a SAMSUNG S3C2410 SoC */
和CONFIG_SMDK2410相关的:
[root@arms armboot-1.1.0]# grep -rHn CONFIG_SMDK2410 *
cpu/arm920t/serial.c:45:#elif defined(CONFIG_SMDK2410)
include/configs/config_smdk2410.h:44:#define CONFIG_SMDK2410 1 /* on an SAMSUNG SMDK2410 Board */
看程序的连接脚本: board/mini2440/armboot.lds
33 .text :
34 {
35 cpu/arm920t/start.o (.text)
36 *(.text)
37 }
知道程序的入口在cpu/arm920t/start.S上(现在U-boot中的该文件还保持着原有的风格)
查看该文件,知道整个程序的主要调用顺序为:
cpu_init_crit-> memsetup(在board/mini2440/memsetup.S中)
->start_armboot (在common/board.c中)
void start_armboot(void)进行了一系列的初始化工作,最后就进入
for (;;) {
main_loop(&bd);
}
主要是接受串口命令,分析并执行命令的循环中。
*************************************************************************************************************************************************
** 各个相关文件的修改 (为了便于说明,代码加了行号(所有新修改的代码均有snallie字样的注释,以示区别,并在代码段的下方对应中文注释说明)
*************************************************************************************************************************************************
cpu/arm920t/start.S的修改
1 /*
2 * armboot - Startup Code for ARM920 CPU-core
3 *
4 * Copyright (c) 2001 Marius Gr鰃er <mag@sysgo.de>
5 * Copyright (c) 2002 Alex Z黳ke <azu@sysgo.de>
6 * Copyright (c) 2002 Gary Jennejohn <gj@denx.de>
7 *
8 * See file CREDITS for list of people who contributed to this
9 * project.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of
14 * the License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24 * MA 02111-1307 USA
25 */
26
27
28
29 #include "config.h"
30 #include "version.h"
31
32
33 /*
34 *************************************************************************
35 *
36 * Jump vector table as in table 3.1 in [1]
37 *
38 *************************************************************************
39 */
40
41
42 .globl _start
43 _start: b reset
44 ldr pc, _undefined_instruction
45 ldr pc, _software_interrupt
46 ldr pc, _prefetch_abort
47 ldr pc, _data_abort
48 ldr pc, _not_used
49 ldr pc, _irq
50 ldr pc, _fiq
51
52 _undefined_instruction: .word undefined_instruction
53 _software_interrupt: .word software_interrupt
54 _prefetch_abort: .word prefetch_abort
55 _data_abort: .word data_abort
56 _not_used: .word not_used
57 _irq: .word irq
58 _fiq: .word fiq
59
60 .balignl 16,0xdeadbeef
61
62
63 /*
64 *************************************************************************
65 *
66 * Startup Code (reset vector)
67 *
68 * do important init only if we don't start from memory!
69 * relocate armboot to ram
70 * setup stack
71 * jump to second stage
72 *
73 *************************************************************************
74 */
75
76 /*
77 * CFG_MEM_END is in the board dependent config-file (configs/config_BOARD.h)
78 */
79 _TEXT_BASE:
80 .word TEXT_BASE
81
82 .globl _armboot_start
83 _armboot_start:
84 .word _start
85
86 /*
87 * Note: armboot_end is defined by the (board-dependent) linker script
88 */
89 .globl _armboot_end
90 _armboot_end:
91 .word armboot_end
92
93 // start of snallie
94 .globl _bss_start
95 _bss_start:
96 .word __bss_start
97
98 .globl _bss_end
99 _bss_end:
100 .word armboot_end
101 // end of snallie
/*
* 94~100行 为新加入的代码,定义了2个全局变量,_bss_start和_bss_end,记录未初始化段的起止地址,其中的
* __bss_start和armboot_end 是在连接脚本 board/mini2440/armboot.lds 中定义的,后面309~317行用_bss_start
* 和_bss_end来进行未初始化段数据的初始清零工作。
*/
102
103 /*
104 * _armboot_real_end is the first usable RAM address behind armboot
105 * and the various stacks
106 */
107 .globl _armboot_real_end
108 _armboot_real_end:
109 .word 0x0badc0de
110
111 #ifdef CONFIG_USE_IRQ
112 /* IRQ stack memory (calculated at run-time) */
113 .globl IRQ_STACK_START
114 IRQ_STACK_START:
115 .word 0x0badc0de
116
117 /* IRQ stack memory (calculated at run-time) */
118 .globl FIQ_STACK_START
119 FIQ_STACK_START:
120 .word 0x0badc0de
121 #endif
122
123
124 /*
125 * the actual reset code
126 */
127
128 reset:
129 /*
130 * set the cpu to SVC32 mode
131 */
132 mrs r0,cpsr
133 bic r0,r0,#0x1f
134 orr r0,r0,#0xd3
135 msr cpsr,r0
136
137 /* turn off the watchdog */
138 #if defined(CONFIG_S3C2400)
139 #define pWTCON 0x15300000
140 /* Interupt-Controller base addresses */
141 #define INTMSK 0x14400008
142 /* clock divisor register */
143 #define CLKDIVN 0x14800014
144 #elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440) // snallie
/* 144行 S3C2410和S3C2440的Watchdog以及中断屏蔽寄存器的地址相同,所以加入 || defined(CONFIG_S3C2440) 的判断 */
145 #define pWTCON 0x53000000
146 /* Interupt-Controller base addresses */
147 #define INTMSK 0x4A000008
148 #define INTSUBMSK 0x4A00001C
149 /* clock divisor register */
150 #define CLKDIVN 0x4C000014
151 #endif
152
153 // snallie
154 #define CLK_CTL_BASE 0x4C000000 /* tekkaman */
155 #define MDIV_405 0x7f << 12 /* tekkaman */
156 #define PSDIV_405 0x21 /* tekkaman */
157 #define MDIV_200 0xa1 << 12 /* tekkaman */
158 #define PSDIV_200 0x31 /* tekkaman */
159 // end of snallie
/* 154~158行引入tekkaman 的几个关于时钟除数因子的定义 */
160
161 ldr r0, =pWTCON
162 mov r1, #0x0
163 str r1, [r0]
164
165 /*
166 * mask all IRQs by setting all bits in the INTMR - default
167 */
168 mov r1, #0xffffffff
169 ldr r0, =INTMSK
170 str r1, [r0]
171 #if defined(CONFIG_S3C2410)
172 ldr r1, =0x3ff
173 ldr r0, =INTSUBMSK
174 str r1, [r0]
175 #endif
176
177 // start of snallie
178 #if defined(CONFIG_S3C2440)
179 ldr r1, =0x7ff
180 ldr r0, =INTSUBMSK
181 str r1, [r0]
182 #endif
183 // end of snallie
/*
* 178~183 为适应S3C2440中断屏蔽位寄存器的设置,事实上,S3C2440处理器复位后屏蔽全部的外部中断
* 168~183段的代码完全可以省略掉,为保持代码的完整行和历史风格,将其保留
*/
184
185 // start of snallie, SMDK2410 boot from NOR flash!
186 #if defined(CONFIG_S3C2410)
187 /* FCLK:HCLK:PCLK = 1:2:4 */
188 /* default FCLK is 120 MHz ! */
189 ldr r0, =CLKDIVN
190 mov r1, #3
191 str r1, [r0]
192
193 /*
194 * we do sys-critical inits only at reboot,
195 * not when booting from ram!
196 */
197 #ifdef CONFIG_INIT_CRITICAL
198 bl cpu_init_crit
199 #endif
200
201 relocate:
202 /*
203 * relocate armboot to RAM
204 */
205 adr r0, _start /* r0 <- current position of code */
206 ldr r2, _armboot_start
207 ldr r3, _armboot_end
208 sub r2, r3, r2 /* r2 <- size of armboot */
209 ldr r1, _TEXT_BASE /* r1 <- destination address */
210 add r2, r0, r2 /* r2 <- source end address */
211
212 /*
213 * r0 = source address
214 * r1 = target address
215 * r2 = source end address
216 */
217 copy_loop:
218 ldmia r0!, {r3-r10}
219 stmia r1!, {r3-r10}
220 cmp r0, r2
221 ble copy_loop
222
223 #if 0
224 /* try doing this stuff after the relocation */
225 ldr r0, =pWTCON
226 mov r1, #0x0
227 str r1, [r0]
228
229 /*
230 * mask all IRQs by setting all bits in the INTMR - default
231 */
232 mov r1, #0xffffffff
233 ldr r0, =INTMR
234 str r1, [r0]
235
236 /* FCLK:HCLK:PCLK = 1:2:4 */
237 /* default FCLK is 120 MHz ! */
238 ldr r0, =CLKDIVN
239 mov r1, #3
240 str r1, [r0]
241 /* END stuff after relocation */
242 #endif
243
244 /* set up the stack */
245 ldr r0, _armboot_end
246 add r0, r0, #CONFIG_STACKSIZE
247 sub sp, r0, #12 /* leave 3 words for abort-stack */
248
249 ldr pc, _start_armboot
250
251 _start_armboot: .word start_armboot
252 #endif
253 // end of snallie
/*
* 187~251 这段设置时钟和代码搬移即跳转的部分不适合MINI2440, 通过条件编译将其跳过:在 include/configs/config_mini2440.h
* 中我们将取消CONFIG_S3C2410的宏定义,取而代之的是定义CONFIG_S3C2440这个宏,所以187~251将在预处理时候被视为空
*/
/*
* 257~323部分为新修改的代码,以适应S3C2440 ,在 include/configs/config_mini2440.h 定义了CONFIG_S3C2440这个宏,
* 所以这段代码被编译
*/
254
255 // start of snallie, mini2440 boot from NAND flash
256 //#if defined(CONFIG_S3C2440) && defined(CONFIG_MINI2440)
257 #if defined(CONFIG_S3C2440)
258 /* FCLK:HCLK:PCLK = 1:4:8 */
259 ldr r0, =CLKDIVN
260 mov r1, #5
261 str r1, [r0]
262
263 mrc p15, 0, r1, c1, c0, 0
264 orr r1, r1, #0xc0000000
265 mcr p15, 0, r1, c1, c0, 0
266
267 mov r1, #CLK_CTL_BASE
268 mov r2, #MDIV_405 /* MPLL=405MHZ */
269 add r2, r2, #PSDIV_405
270 str r2, [r1, #0x04] /* MPLLCON tekkaman */
/*
* 259~270部分为设定工作时钟频率
*/
271
272 /*
273 * we do sys-critical inits only at reboot,
274 * not when booting from ram!
275 */
276 adr r0, _start /* r0 <- current position of code */ // snallie
277 ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ // snallie
278 cmp r0, r1 /* don't reloc during debug */ // snallie
279 blne cpu_init_crit // snallie
/* 判断代码的执行位置,以确定是否进行CPU的初始化:
* 276行为伪指令,工作是取_start这个标号的运行时的地址,277行取_TEXT_BASE单元中的一个字的数据
* 278行判断二者是否相等,若是不等则跳转到cpu_init_crit,进行CPU的初始化工作。
* 说明:这四条指令主要是为了是代码可以同时适应烧写到Flash运行和下载绝对地址TEXT_BASE处运行:
* (1)当烧写到Flash运行时候,这段代码的运行的起始地址为0x00000000,这时候_TEXT_BASE总是存储
* 常量TEXT_BASE(配置在board/mini2440/config.mk),比较后两者不等,表明是从Flash中启动的
* 所以要进行CPU等的初始化工作。
* (2)当代码是在下载绝对地址TEXT_BASE处运行时,_start的值和_TEXT_BASE中存放的值是相等的,
* 表明是在代码测试阶段时下载运行的,所以不必进行CPU等的初始化工作。
*/
280
281 /* set up the stack */ // snallie
282 ldr r0, _armboot_end // snallie
283 add r0, r0, #CONFIG_STACKSIZE // snallie
284 sub sp, r0, #12 /* leave 3 words for abort-stack */ // snallie
/*
* 在306行要调用C的函数
* int CopyCode2Ram(unsigned long start_addr, unsigned char *buf, int size)
* 进行代码的读出工作,所以282~284设定了一段堆栈,位于代码的下方(即程序代码部分的高地址部分),参见后面的
* 内存映像图。
*/
285
286 relocate:
287 /*
288 * relocate armboot to RAM
289 */
290 adr r0, _start /* r0 <- current position of code */
291 ldr r1, _TEXT_BASE /* r1 <- destination address */
292 cmp r0, r1 /* test if we run from flash or RAM */
293 beq call_start_armboot // snallie
/*
* 290~293行代码:在要搬移代码前,先判断代码是从Flash中开始运行的还是下载绝对地址TEXT_BASE处运行的,若是下载运行的,则
* 不必搬移,直接到call_start_armboot,否则进行代码的搬移。具体原因和对276行的注释相同。
*/
294 ldr r2, _armboot_start
295 ldr r3, _armboot_end
296 sub r2, r3, r2 /* r2 <- size of armboot */
/* 294~296行代码:求一下代码的长度,存放在r2寄存器中 */
297
298 /*
299 * r0 = source address
300 * r1 = target address
301 * r2 = size of armboot
302 */
303 // snallie, CopyCodeFromFlashToRam
304 // int CopyCode2Ram(unsigned long start_addr, unsigned char *buf, int size)
305 /*args:r0:source,r1:dest,r2:size*/
306 bl CopyCode2Ram //snallie, CopyCode2Ram.o must be linked within s3c24x0's steppingzone
/*
* 306行调用C的函数进行代码的搬移,ARM处理器下,汇编程序给C函数传递参数的方式为:参数个数小于4个时候,通过
* r0,r1,r2,r3,分别存放4个参数,若多于4个则其余的通过堆栈传递,这里CopyCode2Ram只有3个参数,分别放到
* r0,r1,r2中,r0存放代码在Flash上的开始地址,这里为0x00000000, r1存放代码搬移的起始地址TEXT_BASE(当前设定为0x31F00000),
* r2存放代码的大小
*/
307
308 call_start_armboot: // snallie
/*
* 准备跳转的start_armboot() 函数,309~317行将BSS段的全部数据清零,
* BSS存放的是未初始化的数据,包括外部的未初始化全局数据,函数内部的未初始化的静态变量等,均存放在BSS段中,
* 对于编译好的在操作系统下运行的C代码,这些段中的数据在C程序启动是会由编译器调用一段常规的启动例程进行清零的工作,
* 在这里我们的代码是独立运行的,不依赖于操作系统,我们要直接做这个工作。309~317 这段代码进行BSS段的全部数据清零工作。
* BSS段的数据在启动时清零的工作很重要(只可进行初始时候的一次清零处理!),不做清零处理,则程序运行时候会出现异常情况。
*/
309 clear_bss: // clear bss segment ,!! important !!, snallie
310 ldr r0, _bss_start /* find start of bss segment */
311 ldr r1, _bss_end /* stop here */
312 mov r2, #0x00000000 /* clear */
313
314 clbss_l:str r2, [r0] /* clear loop... */
315 add r0, r0, #4
316 cmp r0, r1
317 ble clbss_l // clear bss segment ,!! important !!, snallie
318
319 ldr pc, _start_armboot // snallie, call start_armboot(), and start.S ends here
/* 319行将跳转到start_armboot()函数,定义在 common/board.c中,此后start.S便完成其使命*/
320
321 _start_armboot: .word start_armboot
322
323 #endif
324 // end of snallie
325
326 /*
327 *************************************************************************
328 *
329 * CPU_init_critical registers
330 *
331 * setup important registers
332 * setup memory timing
333 *
334 *************************************************************************
335 */
336
337
338 cpu_init_crit:
339 /*
340 * flush v4 I/D caches
341 */
342 mov r0, #0
343 mcr p15, 0, r0, c7, c7, 0 // flush v3/v4 cache
344 mcr p15, 0, r0, c8, c7, 0 // flush v4 TLB
345
346 /*
347 * disable MMU stuff and caches
348 */
349 mrc p15, 0, r0, c1, c0, 0
350 bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
351 bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
352 orr r0, r0, #0x00000002 @ set bit 2 (A) Align
353 orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache // snallie
/* 353 加入设定指令Cache */
354 mcr p15, 0, r0, c1, c0, 0
355
356
357 /*
358 * before relocating, we have to setup RAM timing
359 * because memory timing is board-dependend, you will
360 * find a memsetup.S in your board directory.
361 */
362 mov ip, lr
363 bl memsetup
364 mov lr, ip
365
366 mov pc, lr
367
368
369
370
371 /*
372 *************************************************************************
373 *
374 * Interrupt handling
375 *
376 *************************************************************************
377 */
378
379 @
380 @ IRQ stack frame.
381 @
382 #define S_FRAME_SIZE 72
383
384 #define S_OLD_R0 68
385 #define S_PSR 64
386 #define S_PC 60
387 #define S_LR 56
388 #define S_SP 52
389
390 #define S_IP 48
391 #define S_FP 44
392 #define S_R10 40
393 #define S_R9 36
394 #define S_R8 32
395 #define S_R7 28
396 #define S_R6 24
397 #define S_R5 20
398 #define S_R4 16
399 #define S_R3 12
400 #define S_R2 8
401 #define S_R1 4
402 #define S_R0 0
403
404 #define MODE_SVC 0x13
405 #define I_BIT 0x80
406
407 /*
408 * use bad_save_user_regs for abort/prefetch/undef/swi ...
409 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
410 */
411
412 .macro bad_save_user_regs
413 sub sp, sp, #S_FRAME_SIZE
414 stmia sp, {r0 - r12} @ Calling r0-r12
415 add r8, sp, #S_PC
416
417 ldr r2, _armboot_end
418 add r2, r2, #CONFIG_STACKSIZE
419 sub r2, r2, #8
420 ldmia r2, {r2 - r4} @ get pc, cpsr, old_r0
421 add r0, sp, #S_FRAME_SIZE @ restore sp_SVC
422
423 add r5, sp, #S_SP
424 mov r1, lr
425 stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_r
426 mov r0, sp
427 .endm
428
429 .macro irq_save_user_regs
430 sub sp, sp, #S_FRAME_SIZE
431 stmia sp, {r0 - r12} @ Calling r0-r12
432 add r8, sp, #S_PC
433 stmdb r8, {sp, lr}^ @ Calling SP, LR
434 str lr, [r8, #0] @ Save calling PC
435 mrs r6, spsr
436 str r6, [r8, #4] @ Save CPSR
437 str r0, [r8, #8] @ Save OLD_R0
438 mov r0, sp
439 .endm
440
441 .macro irq_restore_user_regs
442 ldmia sp, {r0 - lr}^ @ Calling r0 - lr
443 mov r0, r0
444 ldr lr, [sp, #S_PC] @ Get PC
445 add sp, sp, #S_FRAME_SIZE
446 subs pc, lr, #4 @ return & move spsr_svc into cpsr
447 .endm
448
449 .macro get_bad_stack
450 ldr r13, _armboot_end @ setup our mode stack
451 add r13, r13, #CONFIG_STACKSIZE @ resides at top of normal stack
452 sub r13, r13, #8
453
454 str lr, [r13] @ save caller lr / spsr
455 mrs lr, spsr
456 str lr, [r13, #4]
457
458 mov r13, #MODE_SVC @ prepare SVC-Mode
459 @ msr spsr_c, r13
460 msr spsr, r13
461 mov lr, pc
462 movs pc, lr
463 .endm
464
465 .macro get_irq_stack @ setup IRQ stack
466 ldr sp, IRQ_STACK_START
467 .endm
468
469 .macro get_fiq_stack @ setup FIQ stack
470 ldr sp, FIQ_STACK_START
471 .endm
472
473 /*
474 * exception handlers
475 */
476 .align 5
477 undefined_instruction:
478 get_bad_stack
479 bad_save_user_regs
480 bl do_undefined_instruction
481
482 .align 5
483 software_interrupt:
484 get_bad_stack
485 bad_save_user_regs
486 bl do_software_interrupt
487
488 .align 5
489 prefetch_abort:
490 get_bad_stack
491 bad_save_user_regs
492 bl do_prefetch_abort
493
494 .align 5
495 data_abort:
496 get_bad_stack
497 bad_save_user_regs
498 bl do_data_abort
499
500 .align 5
501 not_used:
502 get_bad_stack
503 bad_save_user_regs
504 bl do_not_used
505
506 #ifdef CONFIG_USE_IRQ
507
508 .align 5
509 irq:
510 get_irq_stack
511 irq_save_user_regs
512 bl do_irq
513 irq_restore_user_regs
514
515 .align 5
516 fiq:
517 get_fiq_stack
518 /* someone ought to write a more effiction fiq_save_user_regs */
519 irq_save_user_regs
520 bl do_fiq
521 irq_restore_user_regs
522
523 #else
524
525 .align 5
526 irq:
527 get_bad_stack
528 bad_save_user_regs
529 bl do_irq
530
531 .align 5
532 fiq:
533 get_bad_stack
534 bad_save_user_regs
535 bl do_fiq
536
537 #endif
538
539 .align 5
540 .globl reset_cpu
541 reset_cpu:
542 mov ip, #0
543 mcr p15, 0, ip, c7, c7, 0 @ invalidate cache
544 mcr p15, 0, ip, c8, c7, 0 @ flush TLB (v4)
545 mrc p15, 0, ip, c1, c0, 0 @ get ctrl register
546 bic ip, ip, #0x000f @ ............wcam
547 bic ip, ip, #0x2100 @ ..v....s........
548 mcr p15, 0, ip, c1, c0, 0 @ ctrl register
549 mov pc, r0
board/mini2440/memsetup.S 的修改
1 /*
2 * Memory Setup stuff - taken from blob memsetup.S
3 *
4 * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) and
5 * Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl)
6 *
7 * Modified for the Samsung SMDK2410 by
8 * (C) Copyright 2002
9 * David Mueller, ELSOFT AG, <d.mueller@elsoft.ch>
10 *
11 * See file CREDITS for list of people who contributed to this
12 * project.
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License as
16 * published by the Free Software Foundation; either version 2 of
17 * the License, or (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
27 * MA 02111-1307 USA
28 */
29
30
31
32 #include "config.h"
33 #include "version.h"
34
35
36 /* some parameters for the board */
37
38 /*
39 *
40 * Taken from linux/arch/arm/boot/compressed/head-s3c2410.S
41 *
42 * Copyright (C) 2002 Samsung Electronics SW.LEE <hitchcar@sec.samsung.com>
43 *
44 */
45
46 #define BWSCON 0x48000000
47
48 /* BWSCON */
49 #define DW8 (0x0)
50 #define DW16 (0x1)
51 #define DW32 (0x2)
52 #define WAIT (0x1<<2)
53 #define UBLB (0x1<<3)
54
55 #define B1_BWSCON (DW32)
56 #define B2_BWSCON (DW16)
57 #define B3_BWSCON (DW16 + WAIT + UBLB)
58 #define B4_BWSCON (DW16)
59 #define B5_BWSCON (DW16)
60 #define B6_BWSCON (DW32)
61 #define B7_BWSCON (DW32)
62
63 /* BANK0CON */
64 #define B0_Tacs 0x0 /* 0clk */
65 #define B0_Tcos 0x0 /* 0clk */
66 #define B0_Tacc 0x7 /* 14clk */
67 #define B0_Tcoh 0x0 /* 0clk */
68 #define B0_Tah 0x0 /* 0clk */
69 #define B0_Tacp 0x0
70 #define B0_PMC 0x0 /* normal */
71
72 /* BANK1CON */
73 #define B1_Tacs 0x0 /* 0clk */
74 #define B1_Tcos 0x0 /* 0clk */
75 #define B1_Tacc 0x7 /* 14clk */
76 #define B1_Tcoh 0x0 /* 0clk */
77 #define B1_Tah 0x0 /* 0clk */
78 #define B1_Tacp 0x0
79 #define B1_PMC 0x0
80
81 #define B2_Tacs 0x0
82 #define B2_Tcos 0x0
83 #define B2_Tacc 0x7
84 #define B2_Tcoh 0x0
85 #define B2_Tah 0x0
86 #define B2_Tacp 0x0
87 #define B2_PMC 0x0
88
89 #define B3_Tacs 0x0 /* 0clk */
90 #define B3_Tcos 0x3 /* 4clk */
91 #define B3_Tacc 0x7 /* 14clk */
92 #define B3_Tcoh 0x1 /* 1clk */
93 #define B3_Tah 0x0 /* 0clk */
94 #define B3_Tacp 0x3 /* 6clk */
95 #define B3_PMC 0x0 /* normal */
96
97 #define B4_Tacs 0x0 /* 0clk */
98 #define B4_Tcos 0x0 /* 0clk */
99 #define B4_Tacc 0x7 /* 14clk */
100 #define B4_Tcoh 0x0 /* 0clk */
101 #define B4_Tah 0x0 /* 0clk */
102 #define B4_Tacp 0x0
103 #define B4_PMC 0x0 /* normal */
104
105 #define B5_Tacs 0x0 /* 0clk */
106 #define B5_Tcos 0x0 /* 0clk */
107 #define B5_Tacc 0x7 /* 14clk */
108 #define B5_Tcoh 0x0 /* 0clk */
109 #define B5_Tah 0x0 /* 0clk */
110 #define B5_Tacp 0x0
111 #define B5_PMC 0x0 /* normal */
112
113 #define B6_MT 0x3 /* SDRAM */
114 #define B6_Trcd 0x1
115 #define B6_SCAN 0x1 /* 9bit */
116
117 #define B7_MT 0x3 /* SDRAM */
118 #define B7_Trcd 0x1 /* 3clk */
119 #define B7_SCAN 0x1 /* 9bit */
120
121 /* REFRESH parameter */
122 #define REFEN 0x1 /* Refresh enable */
123 #define TREFMD 0x0 /* CBR(CAS before RAS)/Auto refresh */
124 #define Trp 0x0 /* 2clk */
125 #define Trc 0x3 /* 7clk */
126 #define Tchr 0x2 /* 3clk */
127 #define REFCNT 1113 /* period=15.6us, HCLK=60Mhz, (2048+1-15.6*60) */
128 /**************************************/
129
130 _TEXT_BASE:
131 .word TEXT_BASE
132
133 .globl memsetup
134 memsetup:
135 /* memory control configuration */
136 /* make r0 relative the current location so that it */
137 /* reads SMRDATA out of FLASH rather than memory ! */
138 ldr r0, =SMRDATA
139 ldr r1, _TEXT_BASE
140 sub r0, r0, r1
141 ldr r1, =BWSCON /* Bus Width Status Controller */
142 add r2, r0, #13*4
143 0:
144 ldr r3, [r0], #4
145 str r3, [r1], #4
146 cmp r2, r0
147 bne 0b
148
149 /* everything is fine now */
150 mov pc, lr
151
152 .ltorg
153 /* the literal pools origin */
154 #if defined(CONFIG_SMDK2410) // snallie
155 SMRDATA:
156 .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
157 .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
158 .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
159 .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
160 .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
161 .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
162 .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
163 .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
164 .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
165 .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
166 .word 0x32
167 .word 0x30
168 .word 0x30
169 #endif // snallie
/* 将 155~169行的内容通过条件编译取消掉 ,直接使用 172~203 行的部分,以适应MINI2440开发板 */
170
171 // start of snallie
172 #if defined(CONFIG_MINI2440)
173 SMRDATA:
174 .word 0x2211d110
175 .word 0x00000700
176 .word 0x00000700
177 .word 0x00000700
178 .word 0x0001c740
179 .word 0x00000700
180 .word 0x0001c740
181 .word 0x00018005
182 .word 0x00018005
183 .word 0x008e0459
184 .word 0x000000b2
185 .word 0x00000030
186 .word 0x00000030
187
188 // snallie, Sun Feb 6 10:09:44 HKT 2011
189 // .word 0x22111112
190 // .word 0x00000700
191 // .word 0x00000700
192 // .word 0x00000700
193 // .word 0x00000700
194 // .word 0x00000700
195 // .word 0x00000700
196 // .word 0x00018009
197 // .word 0x00018009
198 // .word 0x008e04eb
199 // .word 0x000000b2
200 // .word 0x00000030
201 // .word 0x00000030
202
203 #endif
204 // end of snallie
/* 170~204行为MINI2440开发板关于存储器控制的配置数据 */
//
board/mini2440/armboot.lds 的修改
1 /*
2 * (C) Copyright 2002
3 * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
4 *
5 * See file CREDITS for list of people who contributed to this
6 * project.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
22 */
23
24 OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
25 /*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
26 OUTPUT_ARCH(arm)
27 ENTRY(_start)
28 SECTIONS
29 {
30 . = 0x00000000;
31
32 . = ALIGN(4);
33 .text :
34 {
35 cpu/arm920t/start.o (.text)
36 board/mini2440/memsetup.o (.text) /* snallie */
37 board/mini2440/boot_init.o (.text) /* snallie */
/*
* 36~37行控制将start.o,memsetup.o,boot_init.o 放在程序映像的前4K的部分,
* 不放在这里则程序的初始化部分将得不到运行,boot_init.o有boot_init.c编译而来,是新引入的文件,后面有说明
*/
38 *(.text)
39 }
40
41 . = ALIGN(4);
42 .rodata : { *(.rodata) }
43
44 . = ALIGN(4);
45 .data : { *(.data) }
46
47 . = ALIGN(4);
48 .got : { *(.got) }
49
50 . = ALIGN(4);
51 __bss_start = .; /* snallie */
/* 51行定义了一个新的符号地址,供cpu/arm920t/start.S 中的第95行使用,以便记录BSS段的起始地址 */
52 .bss : { *(.bss) }
53
54 armboot_end = .;
55 }
/
新引入一个boot_init.c,在MINI2440的配套盘上的u-boot-1.1.6中可找到,
放到 board/mini2440 目录下,(随之还引入几个相关文件随后进行说明)并作少许改动如下:
1 //#include <common.h> // snallie
2 //#include <s3c2410.h> // snallie
3 #include <s3c2410a.h> // snallie
/*
* 第1行的common.h用不到,去掉,ARMboot-1.1.0中已经有了一个s3c2410.h,但是不适合boot_init.c 使用,
* 去掉,引入一个新的s3c2410a.h 供boot_init.c使用,该文件只改这些。主要是cpu/arm920t/start.S中调用了
* 这个文件中的int CopyCode2Ram(unsigned long start_addr, unsigned char *buf, int size)
*/
4
5 #define GSTATUS1 (*(volatile unsigned int *)0x560000B0)
6 #define BUSY 1
7
8 /* 供外部调用的函数 */
9 void nand_init_ll(void);
10 void nand_read_ll(unsigned char *buf, unsigned long start_addr, int size);
11
12 /* NAND Flash操作的总入口, 它们将调用S3C2410或S3C2440的相应函数 */
13 static void nand_reset(void);
14 static void wait_idle(void);
15 static void nand_select_chip(void);
16 static void nand_deselect_chip(void);
17 static void write_cmd(int cmd);
18 static void write_addr(unsigned int addr);
19 static unsigned char read_data(void);
20
21 /* S3C2410的NAND Flash处理函数 */
22 static void s3c2410_nand_reset(void);
23 static void s3c2410_wait_idle(void);
24 static void s3c2410_nand_select_chip(void);
25 static void s3c2410_nand_deselect_chip(void);
26 static void s3c2410_write_cmd(int cmd);
27 static void s3c2410_write_addr(unsigned int addr);
28 static unsigned char s3c2410_read_data(void);
29
30 /* S3C2440的NAND Flash处理函数 */
31 static void s3c2440_nand_reset(void);
32 static void s3c2440_wait_idle(void);
33 static void s3c2440_nand_select_chip(void);
34 static void s3c2440_nand_deselect_chip(void);
35 static void s3c2440_write_cmd(int cmd);
36 static void s3c2440_write_addr(unsigned int addr);
37 static unsigned char s3c2440_read_data(void);
38
39 /* S3C2410的NAND Flash操作函数 */
40
41 /* 复位 */
42 static void s3c2410_nand_reset(void)
43 {
44 s3c2410_nand_select_chip();
45 s3c2410_write_cmd(0xff); // 复位命令
46 s3c2410_wait_idle();
47 s3c2410_nand_deselect_chip();
48 }
49
50 /* 等待NAND Flash就绪 */
51 static void s3c2410_wait_idle(void)
52 {
53 int i;
54 S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;
55
56 volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFSTAT;
57 while(!(*p & BUSY))
58 for(i=0; i<10; i++);
59 }
60
61 /* 发出片选信号 */
62 static void s3c2410_nand_select_chip(void)
63 {
64 int i;
65 S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;
66
67 s3c2410nand->NFCONF &= ~(1<<11);
68 for(i=0; i<10; i++);
69 }
70
71 /* 取消片选信号 */
72 static void s3c2410_nand_deselect_chip(void)
73 {
74 S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;
75
76 s3c2410nand->NFCONF |= (1<<11);
77 }
78
79 /* 发出命令 */
80 static void s3c2410_write_cmd(int cmd)
81 {
82 S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;
83
84 volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFCMD;
85 *p = cmd;
86 }
87
88 /* 发出地址 */
89 static void s3c2410_write_addr(unsigned int addr)
90 {
91 int i;
92 S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;
93 volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFADDR;
94
95 *p = addr & 0xff;
96 for(i=0; i<10; i++);
97 *p = (addr >> 9) & 0xff;
98 for(i=0; i<10; i++);
99 *p = (addr >> 17) & 0xff;
100 for(i=0; i<10; i++);
101 *p = (addr >> 25) & 0xff;
102 for(i=0; i<10; i++);
103 }
104
105 /* 读取数据 */
106 static unsigned char s3c2410_read_data(void)
107 {
108 S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;
109
110 volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFDATA;
111 return *p;
112 }
113
114 /* S3C2440的NAND Flash操作函数 */
115
116 /* 复位 */
117 static void s3c2440_nand_reset(void)
118 {
119 s3c2440_nand_select_chip();
120 s3c2440_write_cmd(0xff); // 复位命令
121 s3c2440_wait_idle();
122 s3c2440_nand_deselect_chip();
123 }
124
125 /* 等待NAND Flash就绪 */
126 static void s3c2440_wait_idle(void)
127 {
128 int i;
129 S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;
130 volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFSTAT;
131
132 while(!(*p & BUSY))
133 for(i=0; i<10; i++);
134 }
135
136 /* 发出片选信号 */
137 static void s3c2440_nand_select_chip(void)
138 {
139 int i;
140 S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;
141
142 s3c2440nand->NFCONT &= ~(1<<1);
143 for(i=0; i<10; i++);
144 }
145
146 /* 取消片选信号 */
147 static void s3c2440_nand_deselect_chip(void)
148 {
149 S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;
150
151 s3c2440nand->NFCONT |= (1<<1);
152 }
153
154 /* 发出命令 */
155 static void s3c2440_write_cmd(int cmd)
156 {
157 S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;
158
159 volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFCMD;
160 *p = cmd;
161 }
162
163 /* 发出地址 */
164 static void s3c2440_write_addr(unsigned int addr)
165 {
166 int i;
167 S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;
168 volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFADDR;
169
170 *p = addr & 0xff;
171 for(i=0; i<10; i++);
172 *p = (addr >> 9) & 0xff;
173 for(i=0; i<10; i++);
174 *p = (addr >> 17) & 0xff;
175 for(i=0; i<10; i++);
176 *p = (addr >> 25) & 0xff;
177 for(i=0; i<10; i++);
178 }
179
180 /* 读取数据 */
181 static unsigned char s3c2440_read_data(void)
182 {
183 S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;
184 volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFDATA;
185 return *p;
186 }
187
188
189 /* 在第一次使用NAND Flash前,复位一下NAND Flash */
190 static void nand_reset(void)
191 {
192 /* 判断是S3C2410还是S3C2440 */
193 if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
194 {
195 s3c2410_nand_reset();
196 }
197 else
198 {
199 s3c2440_nand_reset();
200 }
201 }
202
203 static void wait_idle(void)
204 {
205 /* 判断是S3C2410还是S3C2440 */
206 if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
207 {
208 s3c2410_wait_idle();
209 }
210 else
211 {
212 s3c2440_wait_idle();
213 }
214 }
215
216 static void nand_select_chip(void)
217 {
218 int i;
219
220 /* 判断是S3C2410还是S3C2440 */
221 if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
222 {
223 s3c2410_nand_select_chip();
224 }
225 else
226 {
227 s3c2440_nand_select_chip();
228 }
229
230 for(i=0; i<10; i++);
231 }
232
233 static void nand_deselect_chip(void)
234 {
235 /* 判断是S3C2410还是S3C2440 */
236 if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
237 {
238 s3c2410_nand_deselect_chip();
239 }
240 else
241 {
242 s3c2440_nand_deselect_chip();
243 }
244 }
245
246 static void write_cmd(int cmd)
247 {
248 /* 判断是S3C2410还是S3C2440 */
249 if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
250 {
251 s3c2410_write_cmd(cmd);
252 }
253 else
254 {
255 s3c2440_write_cmd(cmd);
256 }
257 }
258 static void write_addr(unsigned int addr)
259 {
260 /* 判断是S3C2410还是S3C2440 */
261 if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
262 {
263 s3c2410_write_addr(addr);
264 }
265 else
266 {
267 s3c2440_write_addr(addr);
268 }
269 }
270
271 static unsigned char read_data(void)
272 {
273 /* 判断是S3C2410还是S3C2440 */
274 if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
275 {
276 return s3c2410_read_data();
277 }
278 else
279 {
280 return s3c2440_read_data();
281 }
282 }
283
284 /* 初始化NAND Flash */
285 void nand_init_ll(void)
286 {
287 S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;
288 S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;
289
290 #define TACLS 0
291 #define TWRPH0 3
292 #define TWRPH1 0
293
294 /* 判断是S3C2410还是S3C2440 */
295 if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
296 {
297 /* 使能NAND Flash控制器, 初始化ECC, 禁止片选, 设置时序 */
298 s3c2410nand->NFCONF = (1<<15)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);
299 }
300 else
301 {
302 /* 设置时序 */
303 s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
304 /* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */
305 s3c2440nand->NFCONT = (1<<4)|(1<<1)|(1<<0);
306 }
307
308 /* 复位NAND Flash */
309 nand_reset();
310 }
311
312
313 #define NAND_SECTOR_SIZE 512
314 #define NAND_BLOCK_MASK (NAND_SECTOR_SIZE - 1)
315
316 /* 读函数 */
317 void nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)
318 {
319 int i, j;
320
321 if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {
322 return ; /* 地址或长度不对齐 */
323 }
324
325 /* 选中芯片 */
326 nand_select_chip();
327
328 for(i=start_addr; i < (start_addr + size);) {
329 /* 发出READ0命令 */
330 write_cmd(0);
331
332 /* Write Address */
333 write_addr(i);
334 wait_idle();
335
336 for(j=0; j < NAND_SECTOR_SIZE; j++, i++) {
337 *buf = read_data();
338 buf++;
339 }
340 }
341
342 /* 取消片选信号 */
343 nand_deselect_chip();
344
345 return ;
346 }
347
348 int bBootFrmNORFlash(void)
349 {
350 volatile unsigned int *pdw = (volatile unsigned int *)0;
351 unsigned int dwVal;
352
353 /*
354 * 无论是从NOR Flash还是从NAND Flash启动,
355 * 地址0处为指令"b Reset", 机器码为0xEA00000B,
356 * 对于从NAND Flash启动的情况,其开始4KB的代码会复制到CPU内部4K内存中,
357 * 对于从NOR Flash启动的情况,NOR Flash的开始地址即为0。
358 * 对于NOR Flash,必须通过一定的命令序列才能写数据,
359 * 所以可以根据这点差别来分辨是从NAND Flash还是NOR Flash启动:
360 * 向地址0写入一个数据,然后读出来,如果没有改变的话就是NOR Flash
361 */
362
363 dwVal = *pdw;
364 *pdw = 0x12345678;
365 if (*pdw != 0x12345678)
366 {
367 return 1;
368 }
369 else
370 {
371 *pdw = dwVal;
372 return 0;
373 }
374 }
375
376 int CopyCode2Ram(unsigned long start_addr, unsigned char *buf, int size)
377 {
378 unsigned int *pdwDest;
379 unsigned int *pdwSrc;
380 int i;
381
382 if (bBootFrmNORFlash())
383 {
384 pdwDest = (unsigned int *)buf;
385 pdwSrc = (unsigned int *)start_addr;
386 /* 从 NOR Flash启动 */
387 for (i = 0; i < size / 4; i++)
388 {
389 pdwDest[i] = pdwSrc[i];
390 }
391 return 0;
392 }
393 else
394 {
395 /* 初始化NAND Flash */
396 nand_init_ll();
397 /* 从 NAND Flash启动 */
398 nand_read_ll(buf, start_addr, (size + NAND_BLOCK_MASK)&~(NAND_BLOCK_MASK));
399 return 0;
400 }
401 }
402
403 static inline void delay (unsigned long loops)
404 {
405 __asm__ volatile ("1:/n"
406 "subs %0, %1, #1/n"
407 "bne 1b":"=r" (loops):"0" (loops));
408 }
409
410 /* S3C2440: Mpll = (2*m * Fin) / (p * 2^s), UPLL = (m * Fin) / (p * 2^s)
411 * m = M (the value for divider M)+ 8, p = P (the value for divider P) + 2
412 */
413 #define S3C2440_MPLL_400MHZ ((0x5c<<12)|(0x01<<4)|(0x01))
414 #define S3C2440_MPLL_200MHZ ((0x5c<<12)|(0x01<<4)|(0x02))
415 #define S3C2440_MPLL_100MHZ ((0x5c<<12)|(0x01<<4)|(0x03))
416 #define S3C2440_UPLL_96MHZ ((0x38<<12)|(0x02<<4)|(0x01))
417 #define S3C2440_UPLL_48MHZ ((0x38<<12)|(0x02<<4)|(0x02))
418 #define S3C2440_CLKDIV (0x05) // | (1<<3)) /* FCLK:HCLK:PCLK = 1:4:8, UCLK = UPLL/2 */
419 #define S3C2440_CLKDIV188 0x04 /* FCLK:HCLK:PCLK = 1:8:8 */
420 #define S3C2440_CAMDIVN188 ((0<<8)|(1<<9)) /* FCLK:HCLK:PCLK = 1:8:8 */
421
422 /* S3C2410: Mpll,Upll = (m * Fin) / (p * 2^s)
423 * m = M (the value for divider M)+ 8, p = P (the value for divider P) + 2
424 */
425 #define S3C2410_MPLL_200MHZ ((0x5c<<12)|(0x04<<4)|(0x00))
426 #define S3C2410_UPLL_48MHZ ((0x28<<12)|(0x01<<4)|(0x02))
427 #define S3C2410_CLKDIV 0x03 /* FCLK:HCLK:PCLK = 1:2:4 */
428 void clock_init(void)
429 {
430 S3C24X0_CLOCK_POWER *clk_power = (S3C24X0_CLOCK_POWER *)0x4C000000;
431
432 /* support both of S3C2410 and S3C2440, by www.arm9.net */
433 if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
434 {
435 /* FCLK:HCLK:PCLK = 1:2:4 */
436 clk_power->CLKDIVN = S3C2410_CLKDIV;
437
438 /* change to asynchronous bus mod */
439 __asm__( "mrc p15, 0, r1, c1, c0, 0/n" /* read ctrl register */
440 "orr r1, r1, #0xc0000000/n" /* Asynchronous */
441 "mcr p15, 0, r1, c1, c0, 0/n" /* write ctrl register */
442 :::"r1"
443 );
444
445 /* to reduce PLL lock time, adjust the LOCKTIME register */
446 clk_power->LOCKTIME = 0xFFFFFFFF;
447
448 /* configure UPLL */
449 clk_power->UPLLCON = S3C2410_UPLL_48MHZ;
450
451 /* some delay between MPLL and UPLL */
452 delay (4000);
453
454 /* configure MPLL */
455 clk_power->MPLLCON = S3C2410_MPLL_200MHZ;
456
457 /* some delay between MPLL and UPLL */
458 delay (8000);
459 }
460 else
461 {
462 /* FCLK:HCLK:PCLK = 1:4:8 */
463 clk_power->CLKDIVN = S3C2440_CLKDIV;
464
465 /* change to asynchronous bus mod */
466 __asm__( "mrc p15, 0, r1, c1, c0, 0/n" /* read ctrl register */
467 "orr r1, r1, #0xc0000000/n" /* Asynchronous */
468 "mcr p15, 0, r1, c1, c0, 0/n" /* write ctrl register */
469 :::"r1"
470 );
471
472 /* to reduce PLL lock time, adjust the LOCKTIME register */
473 clk_power->LOCKTIME = 0xFFFFFFFF;
474
475 /* configure UPLL */
476 clk_power->UPLLCON = S3C2440_UPLL_48MHZ;
477
478 /* some delay between MPLL and UPLL */
479 delay (4000);
480
481 /* configure MPLL */
482 clk_power->MPLLCON = S3C2440_MPLL_400MHZ;
483
484 /* some delay between MPLL and UPLL */
485 delay (8000);
486 }
487 }
488
新引入s3c2410a.h 放到include下, 内容如下,不需任何修改
include/s3c2410a.h
1 /*
ARMBoot-1.1.0 在 mini2440 开发板上的移植 之稻草人手记
最新推荐文章于 2021-06-20 10:15:32 发布
本文档详细记录了将ARMBoot 1.1.0移植到mini2440开发板的步骤,包括移植目标、版本、开发环境和具体移植操作。移植涉及驱动串口、网络芯片dm9000、内核下载和启动Linux kernel。通过修改配置文件、代码文件以及添加个性化启动信息,最终实现从NandFlash启动。
摘要由CSDN通过智能技术生成