1:做嵌入式bootloader开发也有一段时间了,今天终于重构了自己的第一个代码,主要目的用来测试,并验证stage1的启动,为后续开发增加点信息。从开始的毫无头绪,到现在自己写的这个代码。感觉上还是很有成就。
硬件环境:开发板:恒丰锐科 HF2410A +3.5"触摸屏
CPU:S3C2410AL ARMArray20t
存储器:
1. 64M(32M*2) SDRAM(K4S561632H-UC75)
2. 64M Nand Flash (KF1208)
一个总线扩展接口。
2个串口输出
JTAG调试接口
软件环境:
XP+VMware+RH linux Array+Source Insight
stage1:软件架构参考下图
软件大体分为三部分:主代码区、调用子函数代码区、数据区
/*
* vivi/arch/s3c2410/head.S:
*
* bootloader stage1
*
* modify by forl on 2008/3/14
*/
#include "config.h"
#include "linkage.h"
#include "machine.h"
.text
/*
**********************************************
*
*code Area
*
**********************************************
*/
/*
***********************************************
*
* Exception vector table
*
***********************************************
*/
.globl _start
_start: b Reset
b undefined_instruction
b software_interrupt
b prefetch_abort
b data_abort
b not_used
b irq
b fiq
/*
**************************************************
*
*the actual reset code
*
**************************************************
*/
Reset:
/*disable watch dog timer*/
mov r1, #0x53000000
mov r2, #0x0
str r2, [r1]
/*disable all interrupts*/
mov r1, #0x4A000000
mov r2, #0xffffffff
str r2, [r1, #0x08]
ldr r2, =0x7ff
str r2, [r1, #0x1C]
/* initialise system clocks*/
mov r1, #0x4C000000
mvn r2, #0xff000000
str r2, [r1, #0x00]
@ 1:2:4
mov r1, #0x4C000000
mov r2, #0x3
str r2, [r1, #0x14]
mrc p15, 0, r1, c1, c0, 0 @ read ctrl register
orr r1, r1, #0xc0000000 @ Asynchronous
mcr p15, 0, r1, c1, c0, 0 @ write ctrl register
@ now, CPU clock is 200 Mhz
mov r1, #0x4C000000
ldr r2, mpll_200mhz
str r2, [r1, #0x04]
/*
*********************
*
*initialise memory
*
*********************
*/
bl memsetup
bl led_memsetup
/*
*********************
*
* SDRAM test
*
*********************
*/
bl memtest
bl led_memtest
/*
*********************
*
*initialise uart 0
*
*********************
*/
bl init_uart @独立用c函数完成
bl led_init_uart
/*
*********************
*
*copy vivi to SDRAM
*
*********************
*/
bl copy_myself
bl led_copy_myself
/*
*********************
*
*jump to ram
*
*********************
*/
ldr r1, =on_the_ram
add pc, r1, #0
nop
nop
1: b 1b @ infinite loop
on_the_ram:
@ get read to call C functions
ldr sp, DW_STACK_START @ setup stack pointer
mov fp, #0 @ no previous frame, so fp=0
mov a2, #0 @ set argv to NULL
bl led_main
bl main @ call main
mov pc, #0x000 @ otherwise, reboot
/*
***********************************************************
*
* End VIVI head
*
***********************************************************
*/
/*
***********************************************************
*
* sub program
*
************************************************************
*/
/* initialise memory*/
/* initialise SDRAM*/
memsetup:
mov r1, #0x48000000
adrl r2, mem_cfg_val
add r3, r1, #52
1: ldr r4, [r2], #4
str r4, [r1], #4
cmp r1, r3
bne 1b
/*
***********************************************************
*
* copy_myself: copy vivi to ram
*
************************************************************
*/
copy_myself:
mov r10, lr
/*initialise NAND flash*/
mov r1, #0x4E000000
ldr r2, =0xf830 @ initial value
str r2, [r1, #0x00]
ldr r2, [r1, #0x00]
bic r2, r2, #0x800 @ enable chip
str r2, [r1, #0x00]
mov r2, #0xff @ RESET command
strb r2, [r1, #0x40]
mov r3, #0 @ wait
1: add r3, r3, #0x1
cmp r3, #0xa
blt 1b
2: ldr r2, [r1, #0x10] @ wait ready
tst r2, #0x1
beq 2b
ldr r2, [r1, #0x00]
orr r2, r2, #0x800 @ disable chip
str r2, [r1, #0x00]
/*get read to call C functions (for nand_read())*/
ldr sp, DW_STACK_START @ setup stack pointer
mov fp, #0 @ no previous frame, so fp=0
@ copy vivi to RAM
ldr r0, =VIVI_RAM_BASE
mov r1, #0x0
mov r2, #0x20000
bl nand_read_ll
cmp r0, #0x0
beq ok_nand_read
/*bad nand read*/
bad_nand_read:
bl led_bad_nand_read
1: b 1b @ infinite loop
/*ok nand read*/
ok_nand_read:
/*verify 0x000-0x400 and 0x33f0000-0x33f0400*/
mov r0, #0
ldr r1, =0x33f00000
mov r2, #0x400 @ 4 bytes * 1024 = 4K-bytes
go_next:
ldr r3, [r0], #4
ldr r4, [r1], #4
teq r3, r4
bne notmatch
subs r2, r2, #4
beq done_nand_read
bne go_next
notmatch:
bl led_notmatch
1: b 1b
/* done nand read to ram*/
done_nand_read:
mov lr, r10
mov pc, lr
/*
*******************************************************
*
*Simple memory test function
*
*******************************************************
*/
memtest:
mov r10, lr
/* check the first 1MB of BLOB_START in increments of 4k */
mov r7, #0x1000
mov r6, r7, lsl #8 /* 4k
关于led测试:
在开发板上有四个led灯 D2、D3、D4、D5查看开发板原理图,其与GPIO的GPF[4:7]
一一对应。利用写GPF[4:7]的值来调试查看程序的运行。对于延时程序可以利用S3C2410自带的硬件计时器,亦可软件实现(本人所采用)
调试stage1过程中D2、D3、D4、D5依次顺序点亮,最后全亮,其对应的程序运行点如下:
D2
memsetup
D3
memtest
D4
init_uart
D5
copy_myself
D2,D3,D4,D5
main
上面这个可以自己设置,个性化的东西。
调试:
这是个很花时间的过程,一个小小的问题都会导致整个过程从来。而用JTAG烧写程序看程序运行状态的方法实在笨的不行。又占PC资源,又慢。所以开始编译时一定要小心。特别是注意不要转入某个循环不出来(因为这种情况交叉编译是能通过的),这点要注意保存程序指针。
我就陷入过其中,检查不出来,不得不用设置多个led点的方法看其出错地点,然后去修改。
开始写程序,没有初始化串口(开始以为在第二阶段初始化),结果bootloader运行正常,没有启动信息输出,着实郁闷了我。
调试是个痛快的过程,有耐心的可以试下,以上的程序我已经过验证,pass。^_^
后记:
关于bootloader stage1 程序的具体分析,包括硬件如何正确初始化,如何设置正确的寄存器的值,还有一些程序的理解在我的另一篇文章中有过详细而?嗦的描述。可供耐心的人参考~~网址如下
http://blog.chinaunix.net/u1/58203/showart_48Array453.html
下一步要做的是完成Stage2的结构分析,构建自己的bootloader stage2 然后加强其网络功能。期待ING