本文主要是介绍[嵌入式系统-38]:龙芯1B 开发学习套件 -8-启动过程详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
目录
一、启动程序的入口
二、初始化硬件浮点单元fpu
三、全局指针
四、设置系统栈
五、设置内存
六、设置Cache
七、配置协处理器
八、初始化TLB
一、启动程序的入口
-
FRAME(_start, sp, 0, ra)
:这一行是一个汇编宏,用于创建一个函数框架。_start
是函数的入口地址,sp
是栈指针,0
表示没有保存寄存器的空间,ra
是返回地址寄存器。 -
.set noreorder
:这个指令告诉汇编器不要重新排序指令。 -
#if (__mips_hard_float)
:这是一个条件编译指令,检查是否启用了硬件浮点运算。 -
li v0, SR_CU1
:将SR_CU1
的值加载到寄存器v0
中。 -
mtc0 v0, C0_SR
:将寄存器v0
的值写入 CP0 寄存器C0_SR
中。 -
#else
-
mtc0 zero, C0_SR /* clr IntMsks/ kernel/disabled mode */
-
#endif
-
nop
:空操作指令。 -
li v0, CAUSE_DC
:将CAUSE_DC
的值加载到寄存器v0
中。 -
mtc0 v0, C0_CAUSE
:将寄存器v0
的值写入 CP0 寄存器C0_CAUSE
中。 -
nop
:空操作指令。 -
lui v0, 0xFFFF
:将0xFFFF
的高 16 位加载到寄存器v0
中。 -
mtc0 v0, C0_COMPARE
:将寄存器v0
的值写入 CP0 寄存器C0_COMPARE
中。 -
nop
:空操作指令。
这段代码主要是针对 MIPS 架构的初始化设置。根据是否启用了硬件浮点运算,设置相应的寄存器值,清除软件中断和定时器中断。
二、初始化硬件浮点单元fpu
-
#if (__mips_hard_float)
:这是一个条件编译指令,检查是否启用了硬件浮点运算。 -
li t3, 0xAAAA5555
:将常数0xAAAA5555
加载到寄存器t3
中。 -
mtc1 t3, fp0
:将寄存器t3
的值写入浮点寄存器fp0
中。 -
mtc1 zero, fp1
:将寄存器zero
的值(0)写入浮点寄存器fp1
中。 -
mfc1 t0, fp0
:将浮点寄存器fp0
的值读取到通用寄存器t0
中。 -
mfc1 t1, fp1
:将浮点寄存器fp1
的值读取到通用寄存器t1
中。 -
nop
:空操作指令。 -
bne t0, t3, 1f
:如果寄存器t0
的值不等于t3
,则跳转到标签1f
处执行。 -
nop
:空操作指令。 -
bne t1, zero, 1f
:如果寄存器t1
的值不等于 0,则跳转到标签1f
处执行。 -
nop
:空操作指令。 -
ctc1 zero, fcr31
:将寄存器zero
的值写入浮点控制寄存器fcr31
中,即清除浮点控制状态寄存器。 -
j 2f
:无条件跳转到标签2f
处执行。 -
nop
:空操作指令。 -
li v0, 0x0
:将常数0x0
加载到寄存器v0
中。 -
mtc0 v0, C0_SR
:将寄存器v0
的值写入 CP0 寄存器C0_SR
中,即重置状态寄存器。 -
nop
:空操作指令。 -
2:
:标签2
,用于跳转。 -
#endif
:结束条件编译指令块。
这段代码主要用于检查是否存在浮点处理器(FPU),如果存在,则清除浮点控制状态寄存器,并重置状态寄存器。
三、全局指针
-
la gp, _gp
:将全局指针_gp
的地址加载到全局指针寄存器gp
中,用于初始化全局指针寄存器。 -
la v0, _fbss
:将未初始化数据段(bss段)的起始地址_fbss
加载到通用寄存器v0
中。 -
la v1, _end
:将未初始化数据段的结束地址_end
加载到通用寄存器v1
中。 -
3:
:标签3
,用于循环中的跳转。 -
sw zero, 0(v0)
:将寄存器zero
的值(0)存储到地址为v0
的内存位置,即清零未初始化数据段中的一个字。 -
bltu v0, v1, 3b
:如果v0
的值小于v1
的值,则跳转到标签3
处执行。这是一个无符号数比较分支指令,用于在清零未初始化数据段的过程中循环处理直到结束。 -
add v0, 4
:将寄存器v0
的值加上4,即增加一个字的大小,用于指向下一个未初始化数据段的地址。
这段代码的主要作用是初始化全局指针寄存器,并清零未初始化数据段(bss段)的内容,确保其在使用之前被正确初始化。
四、设置系统栈
-
la t0, _stack_end
: 将系统栈的结束地址_stack_end
加载到临时寄存器t0
中。 -
sub t0, t0, (4 * 4)
: 从系统栈的结束地址减去4个字(即16个字节)。这可能是为了留出一些空间用于栈帧或其他用途。“XXX overhead” 注释可能表示这个操作有一定的额外开销。 -
move sp, t0
: 将临时寄存器t0
中的值移动到栈指针寄存器sp
中,从而设置系统栈。 -
la a0, _RamSize
: 将 RAM 的大小_RamSize
加载到寄存器a0
中。
五、设置内存
-
jal set_memory_size
: 调用函数set_memory_size
,这可能是设置内存大小的函数。 -
nop
: 空操作指令,用于填充延时槽或优化。
六、设置Cache
-
jal config_cache
: 调用函数config_cache
,用于确定 D & I caches 的大小。 -
nop
: 空操作指令。 -
la a0, memory_cfg_struct
: 将内存配置结构体memory_cfg_struct
的地址加载到寄存器a0
中。 -
jal get_memory_conf
: 调用函数get_memory_conf
,可能用于填充内存配置结构体。 -
nop
: 空操作指令。 -
jal flush_cache
: 调用函数flush_cache
,用于初始化缓存。 -
nop
: 空操作指令。
七、配置协处理器
-
mfc0 v0, C0_CONFIG, 0
: 从协处理器0的配置寄存器中(特权级0)读取数据,将其存储到通用寄存器v0
中。 -
and v0, v0, ~CFG0_K0
: 将v0
的值与CFG0_K0
的按位取反值进行按位与操作,可能是为了清除特定位的设置。 -
or v0, v0, CFG_C_CACHABLE
: 将CFG_C_CACHABLE
的值与v0
进行按位或操作,可能是为了设置缓存为可缓存的模式。 -
mtc0 v0, C0_CONFIG, 0
: 将寄存器v0
的值写入到协处理器0的配置寄存器中(特权级0)。 -
nop
: 空操作指令。
这段代码的主要作用是设置系统栈、内存大小、缓存配置等,并进行一些与内存和缓存相关的初始化操作。
八、初始化TLB
/* Clear Translation Lookaside Buffer (TLB)
*/
jal init_tlb /* clear the tlb */
nop
/* End of CPU initialization, ready to start kernel
*/
move a0, zero /* Set argc passed to main */
jal bsp_start //C语言启动代码,不返回,
nop
/* Kernel has been shutdown, jump to the "exit" routine
*/
jal _sys_exit
move a0, v0 # pass through the exit code
1:
beq zero, zero, 1b
nop
.set reorder
ENDFRAME(_start)
这篇关于[嵌入式系统-38]:龙芯1B 开发学习套件 -8-启动过程详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!