上一次说到怎么样运行起来,现在接着上次再进行分析下去。在locate的程序,如下:
locate:
la s0,start
subu s0,ra,s0
and s0,0xffff0000
li t0,SR_BOOT_EXC_VEC
mtc0 t0,COP_0_STATUS_REG
mtc0 zero,COP_0_CAUSE_REG
.set noreorder
li bonito,PHYS_TO_UNCACHED(BONITO_REG_BASE)
…
bal 1f
nop
/* bonito endianess */
BONITO_BIC(BONITO_BONPONCFG,BONITO_BONPONCFG_CPUBIGEND)
BONITO_BIC(BONITO_BONGENCFG,BONITO_BONGENCFG_BYTESWAP|BONITO_BONGENCFG_MSTRBYTESWAP)
BONITO_BIS(BONITO_BONPONCFG, BONITO_BONPONCFG_IS_ARBITER)
…
EXIT_INIT(0)
#define Init_Op 0
#define Init_A0 4
#define Init_A1 8
#define Init_A2 12
#define Init_Size 16
1: move a0,ra
reginit: /* local name */
lw t3, Init_Op(a0)
lw t0, Init_A0(a0)
and t4,t3,OP_MASK
/*
* EXIT(STATUS)
*/
bne t4, OP_EXIT, 8f
nop
move v0,t0
b .done
nop
…
跳到locate里執行的,首先计算跳转时代码的长度,保存s0。接着把物理地址保存到bonito寄存器,后面又通过bal 1f跳到后面的1标号地方运行。
在1标号的地方,取跳转时压入的RA寄存器的值,然后通过寄存器相对寻址的方式,取得跳转指令后面保存的参数,并保存到t3,t0寄存器。后面就运行bne t4, OP_EXIT, 8f这句了,在这里作是否初始化寄存器完成的判断,如果没有完成,就会跳到后面8标号处运行,然后经历一系列的设置后,直到OP_EXIT标志出现。看到前面有一行EXIT_INIT(0),这里就是说这个数据结构已经结构了,它的宏定义如下:
#define EXIT_INIT(status) \
.word OP_EXIT,(status);\
.word 0,0
所以在最后一项的数据记录读取后,总是能退出这个初始化循环的,接着就会跳到.done这个标号里运行。
接着看一下这段代码又有什么事情好做,代码如下:
.done:
bal superio_init
nop
bal initserial
nop
PRINTSTR("\r\nPMON2000 MIPS Initializing. Standby...\r\n")
PRINTSTR("ERRORPC=")
mfc0 a0, COP_0_ERROR_PC
bal hexserial
nop
PRINTSTR(" CONFIG=")
mfc0 a0, COP_0_CONFIG
bal hexserial
nop
PRINTSTR("\r\n")
PRINTSTR(" PRID=")
mfc0 a0, COP_0_PRID
bal hexserial
nop
PRINTSTR("\r\n")
/* 蔡军生 2006-12-29 于深圳*/
在这段程序里,主要做了两件大事情,一是初始化南桥芯片VIA686B,一是初始化串口输出。初始化VIA686B是调用子函数superio_init实现的。初始化串口是调用子函数initserial实现的。为了尽快地从串口输出调试信息,所以要先初始化VIA686B芯片,才能输出信息出来。由于VIA686B芯片包括所有外面接口的功能,比如串口,PS2,USB,并口,还有软盘等等。只能从串口输出字符,就已经是成功的第一步了。在嵌入式的软件开发中,调试软件是最难的,只能根据芯片的管脚电平,或者串口发些调信息出来。使用管脚调试,最简单的办法,就是加一个指示灯,这也叫“点灯大法”。只要串口能输出字符串后,使用串口调试就成为基本的方法了。后面,输出三个CP0寄存器的值,第一个寄存器是出错信息,第二个寄存器是CP0配置信息,第三个寄存器是CP0处理器的ID信息。
下一次再分析怎么么样初始化VIA686B和串口。 查看本文来源