riscv引导程序及仿真记录

3 篇文章 0 订阅
2 篇文章 0 订阅

1.riscv基本的寄存器列表

这里只关注32个通用寄存器x0-x31

 2.引导程序代码

# 1 "iriscvboot.casm"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "iriscvboot.casm"

###define 0x52080000 0
# 29 "iriscvboot.casm"
 .section .text
 .org 0x0

_th0_reset:
 l.j _th0_main
 l.nop

_LOOP:
 l.j _LOOP   	

## === version info start at 0x80 ==
 .org 0x80
 .global _pack_version
 .global _build_date
 .global _api_version
_pack_version:
 .word 0x0171
_svn_version:
 .word 0x0367ad3
_build_date:
 .word 0x07e60701
_api_version:
 .word 0x0180
_silicon_version:
 .word 1000
## === version info end ===
###################################################################

_th0_main:
 l.addi x2,x0,0x0
 l.addi x3,x0,0x0
 l.addi x4,x0,0x0
 l.addi x5,x0,0x0
 l.addi x6,x0,0x0
 l.addi x7,x0,0x0
 l.addi x8,x0,0x0
 l.addi x9,x0,0x0
 l.addi x10,x0,0x0
 l.addi x11,x0,0x0
 l.addi x12,x0,0x0
 l.addi x13,x0,0x0
 l.addi x14,x0,0x0
 l.addi x15,x0,0x0
 l.addi x16,x0,0x0
 l.addi x17,x0,0x0
 l.addi x18,x0,0x0
 l.addi x19,x0,0x0
 l.addi x20,x0,0x0
 l.addi x21,x0,0x0
 l.addi x22,x0,0x0
 l.addi x23,x0,0x0
 l.addi x24,x0,0x0
 l.addi x25,x0,0x0
 l.addi x26,x0,0x0
 l.addi x27,x0,0x0
 l.addi x28,x0,0x0
 l.addi x29,x0,0x0
 l.addi x30,x0,0x0
 l.addi x31,x0,0x0
 l.lui  x2,0x52086


_init_cmem_done_th0:
 l.jal _mymain
 l.j _LOOP 

 3.引导代码含义,及相关指令。

.section .text表示下面的代码链接时放在.text段,.org设置当前代码的地址偏移(相对于链接时指定定.text段的起始地址)。

接下来定义了标签_th0_reset,riscv执行时从这儿开始执行指令,l.j  _th0_main表示跳转到
_th0_main标签处,
_th0_reset:
 l.j _th0_main
 l.nop

_th0_main标签处,连续的l.addi 指令可以理解为对32个通用寄存器的清操作。

但是注意 l.lui  x2,0x52086指令指定了sp寄存器(栈指针)的,开始地址。(lui 指令将 20 位立即数的值左移 12 位(低 12 位补 0)成为一个 32 位数,将此数写 回寄存器 x2 中。)

接着执行_init_cmem_done_th0标签处。此处就是我们定义的c程序的入口处。l.jal _mymain表示跳转到_mymain处,可以看下面c代码的汇编,其中会根据mymain函数创建_mymain标签。(jal 指令完成跳转并且将其下一条指令的 PC(即当前指令 PC+4)的值写入其结果寄存器 ra 中。注意:在实际的汇编程序编写中,跳转的目标往往使用汇编程序中的 label,汇编器 会自动根据 label 所在的地址计算出相对的偏移量赋予指令编码。

到_mymain中后就会执行c代码中内容了。 执行完c代码后,会根据ra寄存器的值返回来执行下一句,l.j _LOOP。这里是为了让riscv不乱跑,设置这个循环。

 4.c代码

C代码内容很简单,分别对0x1000这个地址写入次,第一次值100,第二次值0x202

void write32(int addr,int value) 
{
		int *addr_value;
		addr_value = (int*)addr;
		*addr_value = value;
}

void mymain()
{
	volatile int age=100;
	write32(0x1000,age);
	write32(0x1000,0x202);
}

C代码的汇编结果gcc -S:

	.file	"firmware.c"
	.option nopic
	.text
	.align	2
	.globl	_write32
	.type	_write32, @function
_write32:
	l.sw	a1,0(a0)
	l.ret
	.size	_write32, .-_write32
	.align	2
	.globl	_mymain
	.type	_mymain, @function
_mymain:
	l.add	sp,sp,-32
	l.li	a5,100
	l.sw	a5,12(sp)
	l.lw	a1,12(sp)
	l.li	a0,4096
	l.sw	ra,28(sp)
	call	_write32
	l.li	a1,514
	l.li	a0,4096
	call	_write32
	l.lw	ra,28(sp)
	l.add	sp,sp,32
	l.jr	ra
	.size	_mymain, .-_mymain
	.ident	"GCC: (GNU) 6.1.0"

5.链接

链接脚本

MEMORY
        {
        flash  : ORIGIN = 0x52040000, LENGTH = 0x00040000
        ram    : ORIGIN = 0x5b000000, LENGTH = 0x00006000
        glb    : ORIGIN = 0x52086000, LENGTH = 0x00032000
        rodata : ORIGIN = 0xa0000000, LENGTH = 0x00040000
        }
 
SECTIONS
{
      .text :
        {
        *(.text)
        } > flash
      .data :
        {
        *(.data)
        } > ram
      .bss :
        {
        *(.bss)
        } > ram

      .debug :
        {
        *(.debug_frame .zdebug_frame)
        *(.debug_abbrev)
        *(.debug_line)
        *(.debug_str)
        *(.debug_loc)
        *(.debug_macinfo)
        *(.debug_info)
        *(.debug_aranges)
        *(.debug_ranges)
        *(.comment)
        } > ram
      .rodata :
        {
        *(.rodata)
        } > rodata
}

链接结果,通过objdump工具进行反汇编注意使用-D选项,对所有段进行反汇编:


isp_firmware:     file format elf32-littleriscv


Disassembly of section .text:

52040000 <_th0_reset>:
52040000:	0940006f          	l.jal 	zero,52040094 <_th0_main>
52040004:	00000013          	l.addi 	zero,zero,0

52040008 <_LOOP>:
52040008:	0000006f          	l.jal 	zero,52040008 <_LOOP>
	...

52040080 <_pack_version>:
52040080:	00000171          	0x171

52040084 <_svn_version>:
52040084:	00367ad3          	l.fadd.s 	fs5,fa2,ft3

52040088 <_build_date>:
52040088:	07e60701          	0x7e60701

5204008c <_api_version>:
5204008c:	00000180          	0x180

52040090 <_silicon_version>:
52040090:	000003e8          	0x3e8

52040094 <_th0_main>:
52040094:	00000113          	l.addi 	sp,zero,0
52040098:	00000193          	l.addi 	gp,zero,0
5204009c:	00000213          	l.addi 	tp,zero,0
520400a0:	00000293          	l.addi 	t0,zero,0
520400a4:	00000313          	l.addi 	t1,zero,0
520400a8:	00000393          	l.addi 	t2,zero,0
520400ac:	00000413          	l.addi 	s0,zero,0
520400b0:	00000493          	l.addi 	s1,zero,0
520400b4:	00000513          	l.addi 	a0,zero,0
520400b8:	00000593          	l.addi 	a1,zero,0
520400bc:	00000613          	l.addi 	a2,zero,0
520400c0:	00000693          	l.addi 	a3,zero,0
520400c4:	00000713          	l.addi 	a4,zero,0
520400c8:	00000793          	l.addi 	a5,zero,0
520400cc:	00000813          	l.addi 	a6,zero,0
520400d0:	00000893          	l.addi 	a7,zero,0
520400d4:	00000913          	l.addi 	s2,zero,0
520400d8:	00000993          	l.addi 	s3,zero,0
520400dc:	00000a13          	l.addi 	s4,zero,0
520400e0:	00000a93          	l.addi 	s5,zero,0
520400e4:	00000b13          	l.addi 	s6,zero,0
520400e8:	00000b93          	l.addi 	s7,zero,0
520400ec:	00000c13          	l.addi 	s8,zero,0
520400f0:	00000c93          	l.addi 	s9,zero,0
520400f4:	00000d13          	l.addi 	s10,zero,0
520400f8:	00000d93          	l.addi 	s11,zero,0
520400fc:	00000e13          	l.addi 	t3,zero,0
52040100:	00000e93          	l.addi 	t4,zero,0
52040104:	00000f13          	l.addi 	t5,zero,0
52040108:	00000f93          	l.addi 	t6,zero,0
5204010c:	52086137          	l.lui 	sp,0x52086

52040110 <_init_cmem_done_th0>:
52040110:	010000ef          	l.jal 	ra,52040120 <_mymain>
52040114:	ef5ff06f          	l.jal 	zero,52040008 <_LOOP>

52040118 <_write32>:
52040118:	00b52023          	l.sw 	a1,0(a0)
5204011c:	00008067          	l.jalr 	zero,0(ra)

52040120 <_mymain>:
52040120:	fe010113          	l.addi 	sp,sp,-32 # 52085fe0 <_mymain+0x45ec0>
52040124:	06400793          	l.addi 	a5,zero,100
52040128:	00f12623          	l.sw 	a5,12(sp)
5204012c:	00c12583          	l.lw 	a1,12(sp)
52040130:	00001537          	l.lui 	a0,0x1
52040134:	00112e23          	l.sw 	ra,28(sp)
52040138:	fe1ff0ef          	l.jal 	ra,52040118 <_write32>
5204013c:	20200593          	l.addi 	a1,zero,514
52040140:	00001537          	l.lui 	a0,0x1
52040144:	fd5ff0ef          	l.jal 	ra,52040118 <_write32>
52040148:	01c12083          	l.lw 	ra,28(sp)
5204014c:	02010113          	l.addi 	sp,sp,32
52040150:	00008067          	l.jalr 	zero,0(ra)

Disassembly of section .debug:

5b000000 <.debug>:
5b000000:	3a434347          	l.fmsub.d 	ft6,ft6,ft4,ft7,rmm
5b000004:	4e472820          	0x4e472820
5b000008:	36202955          	l.c.setireg 	m18,m2,0x1b10
5b00000c:	302e312e          	0x302e312e
	...

 6.生成firmware

然后使用python脚本将,对应需要的段的地址和指令编码dump出来。使用的python脚本如下,输入文件是上面的反汇编结果:

#!/usr/bin/python

import sys
import re 

def replace_line(input_file, output_file): 
	input_f  = open(input_file, 'r')
	output_f = open(output_file, 'w')
	text=0;
	rodata=0;
	sdata=0;
	for line in input_f:
		line = line.rstrip() # removing right space
		#print(line)

		if("text" in line):
			text=1
			sdata=0
			rodata=0
		if("sdata" in line):
			sdata=1
			text=0
			rodata=0
		if("rodata" in line):
			rodata=1
			text=0
			sdata=0
		if(("debug" in line)):
			sdata=0;
			rodata=0;
			text=0;

		if (line.find('          	l.') != -1)&(text==1) : 
			line = line.replace (":", ",")
			words = line.split()
			output_f.write(words[0]+words[1]+'\n')

		if (re.findall(r'\d+:\s+\w+',line) != [])&(sdata==1) :  
			line = line.replace (":", ",")
			words = line.split()
			output_f.write(words[0]+words[1]+'\n')

		if (re.findall(r'\d+:\s+\w+',line) != [])&(rodata==1) :  
			line = line.replace (":", ",")
			words = line.split()
			output_f.write(words[0]+words[1]+'\n')



arg_list = sys.argv
print(arg_list[1])
print(arg_list[2])

if len(arg_list) != 3:
	print("need input file list")
	sys.exit()

replace_line(arg_list[1], arg_list[2])

dump出的firmware的文件如下,其中包含指令编码以及所放置的mem中的地址:

52040000,0940006f
52040004,00000013
52040008,0000006f
52040084,00367ad3
52040094,00000113
52040098,00000193
5204009c,00000213
520400a0,00000293
520400a4,00000313
520400a8,00000393
520400ac,00000413
520400b0,00000493
520400b4,00000513
520400b8,00000593
520400bc,00000613
520400c0,00000693
520400c4,00000713
520400c8,00000793
520400cc,00000813
520400d0,00000893
520400d4,00000913
520400d8,00000993
520400dc,00000a13
520400e0,00000a93
520400e4,00000b13
520400e8,00000b93
520400ec,00000c13
520400f0,00000c93
520400f4,00000d13
520400f8,00000d93
520400fc,00000e13
52040100,00000e93
52040104,00000f13
52040108,00000f93
5204010c,52086137
52040110,010000ef
52040114,ef5ff06f
52040118,00b52023
5204011c,00008067
52040120,fe010113
52040124,06400793
52040128,00f12623
5204012c,00c12583
52040130,00001537
52040134,00112e23
52040138,fe1ff0ef
5204013c,20200593
52040140,00001537
52040144,fd5ff0ef
52040148,01c12083
5204014c,02010113
52040150,00008067

 7.仿真结果

将上面dump出来的结果,进行仿真。结果如下所示。可以看见和C代码内容一样分别对0x1000这个地址写入次,第一次值100(0x64),第二次值0x202

pc指针的初始值值设置的是52040000,也就是.text的初始地址。

 

参考:

1.RISC-V架构与嵌入式开发快速入门

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值