【龙芯1c库】上电初始化汇编代码start.S注解(pmon类似)

本文详细解析了龙芯1c库上电初始化的汇编代码start.S,涵盖了从反汇编工具的使用、异常入口点、地址空间划分到汇编代码的逐行解释。文章指出,上电后第一条执行的指令位于ROM的0xBFC00000地址,初始化完成后会清零BEV寄存器。同时,介绍了如何将固件从ROM拷贝到内存,以及汇编代码在设置SPI、PLL、时钟、调试串口、内存和CACHE方面的初始化操作。
摘要由CSDN通过智能技术生成
参考pmon源码,将start.S、Makefile和链接脚本移植到裸机程序,实现纯粹的真正的裸机程序。这样就不再需要pmon,上电后直接运行裸机程序。

本文涉及的异常和地址空间的相关知识,需要结合《龙芯1c的芯片手册》、《see mips run》和《北京龙芯的龙芯1c开发板手册》。这几个文档都已经放到龙芯1c库的git上了,最新最完整的代码也请移步到git查看。龙芯1c库的git地址是https://gitee.com/caogos/OpenLoongsonLib1c

背景知识

使用mipsel-linux-objdump反汇编

为什么需要使用反汇编

为什么这里首先讨论使用objdump反汇编呢?可能大家习惯了仿真,单步调试。很少单独使用反汇编。可是目前龙芯1c是不能仿真和单步调试的(至少目前我不知道),所以手动反汇编就有必要了,通过查看反汇编,可以很清楚的查看程序的运行流程,可以看到上电后CPU运行的第一条汇编指令是什么。
举个例子吧,在调试上电初始化这部分汇编程序的过程中,发现汇编源码和pmon中的差不多,可是串口没有打印helloworld。经过一番排除,最后用objdump反汇编发现,链接后执行的第一条语句不是汇编,而是c程序。原因是ld链接时,c文件放在了依赖文件列表的前面,改为汇编文件在前面,就可以了。

怎样反汇编

为了能在反汇编的结果中同步显示源码,在编译时,需要增加选项” -g ”,
例如“make cfg all tgt=rom DEBUG=-g”,
使用mipsel-linux-objdump反汇编,
例如
root@ubuntu:/home/develop/loongson1-pmon-master/Targets/LS1X/compile/ls1c# mipsel-linux-objdump -S pmon.gdb > /mnt/hgfs/VmShare/pmon-gdb-objdump.S
比如,pmon反汇编后,得到如下内容

pmon.gdb:     file format elf32-tradlittlemips


Disassembly of section .text:

80010000 <_ftext>:
80010000:	40806000 	mtc0	zero,$12
80010004:	40806800 	mtc0	zero,$13
80010008:	3c080040 	lui	t0,0x40
8001000c:	40886000 	mtc0	t0,$12
80010010:	3c1d8001 	lui	sp,0x8001
80010014:	27bdc000 	addiu	sp,sp,-16384
80010018:	3c1c800c 	lui	gp,0x800c
8001001c:	279c6cf0 	addiu	gp,gp,27888
80010020:	3c08bfe8 	lui	t0,0xbfe8
80010024:	24090017 	li	t1,23
80010028:	a1090004 	sb	t1,4(t0)
8001002c:	24090005 	li	t1,5
80010030:	a1090006 	sb	t1,6(t0)
80010034:	3c04bfd0 	lui	a0,0xbfd0
80010038:	348411c0 	ori	a0,a0,0x11c0
8001003c:	8c850040 	lw	a1,64(a0)
80010040:	34a50001 	ori	a1,a1,0x1
80010044:	ac850040 	sw	a1,64(a0)
80010048:	041101b9 	bal	80010730 <locate>
8001004c:	00000000 	nop
	...

反汇编结果是如何与源码一一对应的

这里主要讨论一下,反汇编得到的汇编代码,与start.S中的汇编代码的对应关系

左边为start.S中的汇编源码,右边为反汇编的结果。图中用线将其一一对应了。

异常入口点(CP0的SR寄存器的BEV)

上电运行的第一条指令在什么地方,地址是多少

mips系列cpu的异常和中断是两个不同的概念,中断一般指外设中断,所有外设中断共用一个异常入口,即外设中断是一种特定类型的异常。《龙芯1c的芯片手册》中目前几乎没怎么讲这部分内容,而《see mips run》中却讲得很详细,专门用一章来讲异常。
本文不是要讨论上电初始化那部分汇编代码吗?怎么这里研究异常呢?在mips系列cpu上,上电(冷复位)也属于一种异常,异常入口固定为ROM入口点0xBFC00000,如下图

《龙芯1c的芯片手册》中也有对应描述,如下

图中,明确说了,根据系统启动方式将内存地址0xBFC00 0000 -- )XBFCF FFFF映射到SPI或NAND,即从地址0xBFC0 0000处取出的指令,就是SPI或NAND的地址0处的指令。也是上电后运行的第一条指令。

刚上电时,把BEV置1

截图中,讲清楚了,在cpu刚上电时,cache还未初始化之前,只能使用不经过cache的kseg1。

初始化完成后,把BEV清零

(内存,cache等)初始化完成后,就可以使用cache了,通过把协处理器0的SR寄存器中的BEV清零,使所有异常入口从ROM入口点(0xBFC0 0000)改为RAM入口点(BASE + 0x180),其中BASE为寄存器EBase的值。《see mips run》中的描述为

Pmon中对应的代码为

地址空间的划分

see mips run中关于程序地址空间的划分情况

see mips run中kseg0和kseg1的详细描述

因为kseg0(0x8000 0000 - 0x9fff ffff)和kseg1(0xa000 0000 - 0xBfff ffff)实际上是映射到低端同一块512M的物理地址上,只是kseg1不需要cache,而kseg0必须等cache初始化后才能使用。
所以,把固件拷贝到kseg1上,等等于拷贝到了kseg0上。

龙芯1c芯片手册中关于地址空间分配的描述

链接时的起始地址(代码段的首地址)

标号start的值为0x80010000

代码段是从0x8001 0000处开始的,初始化完成后,异常入口改为RAM入口,即BASE+0x180=0x8000 0000+0x180

栈空间在什么地方

在代码段之前有0x4000大小的栈空间,代码如下<

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值