使用gnu 编译picoRV32 c/asm 代码

小提示:

1,大家本身了解eclipse使用,也已经安装了gnu+eclipse环境,参考: http://blog.csdn.net/kuankuan02/article/details/79233442

2,同时下载了 picoRV32的 open source code:

https://github.com/cliffordwolf/picorv32

3,你要有硬件环境可以跑bin,我是有数字工程师提供了FPGA平台。

正文:

1,eclipse新建一个工程,选择RISC-V c project创建。使用gnu 编译picoRV32 c/asm 代码_第1张图片

2,然后加入你所下载的picoRV32_master/fireware里的c code,我下面简单介绍下ASM部分

start.s是启动代码以及trap处理代码,reset_vec 是开始,摆在0地址;后面.balign 16 对齐,因为picoRV32 trap地址在0x10,所以后面是trap处理代码。记住picoRV32 ASM 不要使用CSRs读写指令,CPU不认的。它的trap上下文切换所要用的stack是irq_regs定义的数据块,因为我的bin都是下载到flash中,所以给它加个.bss section属性,把它移到ram去。正好再提一下,系统stack是在ld脚本里申请的section,这个code是把系统stack和trap stack分开了,很多情况下都是用的同一个。它的技巧是自定义指令getq和setq来交换自定义寄存器q0~q3,每次trap都重新获取trap stack 指针,这是个很笨的上下文保存方法,大家只拿来先跑起来bin就好。启动代码还要注意的是.bss 必须清0,以及.data 必须搬入ram中,sp 赋值以后就可以开始进入c code了,输出个hello world。我的系统是uart输出,所以uart初始化也加到start.s中。

irq_regs:
	// registers are saved to this memory region during interrupt handling
	// the program counter is saved as register 0
	.fill 32,4

	// stack for the interrupt handler
	.fill 256,4
irq_stack:
3, picoRV32额外实现了一些指令,getqsetqretirq等等,具体内容可以到README.md查找。

这些指令gcc编译器是不认识的,我们不能用指令名字来使用它们,它们只能采用.word 0x1234abcd 样式的机器码方式把它们插入代码中,这在汇编代码里是可以实现的。(参考custom_ops.S)

4,对于bin的连接,最重要的就是ld脚本,这个跟不同系统的address mapping相关,由于一些原因这里无法展开说。

额外解释两个问题:

picoRV32为什么要自定义ISA呢?

因为它没有实现特权级文档里的CSRs状态寄存器(除了cycle counterinstruction-retired counter),而在trap/interrupt 响应的时候,有一些事情是需要额外寄存器协助处理。在这里picoRV32搭配了四个32bits寄存器用于Interrupt function,这就是我们之前介绍的custom interrupt controller

q0~q3四个寄存器:

q0 存储了interrupt return地址

q1 用于表示interrupt status bit

q2 q3 用于和通用寄存器进行数据交换

getq q[n]赋值到通用寄存器

setq 把通用寄存器值赋值到q[n]

retirq  返回到q0存储的地址执行,用于从interrupt返回

maskirq  可以操作interrupt mask register,用于屏蔽interrupt bit ,我把它用于中断开关控制了,就像ARM cpsr中的irq enable bit一样使用


系统在Trap/interrupt要做些什么?

None OS:正常流程下while(1) <>interrupt ,程序流程比较简单,代码只需实现save/restore/return

FreeRTOStask<>task task<>interruptinterrupt<>task,程序相对复杂,代码要把os port部分都实现掉

Trap:可以理解为一个硬件问题处理机制,当硬件自己处理不了的时候让CPU跳转到一个固定地址,让软件工程师写code去帮助硬件来处理它无法处理的状况,比如是interrupt/softinterrupt/exception等等。这些事情的判断就需要去读取各种CSRs,才能知道CPU为什么要跳转出来,同时记录CPU跳转时的地址处理完毕才能正确返回。

picoRV32上把这些都简化了,而且它的Trap约等于了interrupt,工程师可直接按interrupt的方式处理绝大部分状况。把返回地址赋值给q0,然后调用retirq就可以从interrupt返回到q0所保存的地址,这个操作同样适用于task间切换


关于FreeRTOS 和picoRV32间port我有实现好,但还没经过产品验证,暂时不能抛出来,我想肯定会有还未发现的bug,等产品出来后再介绍吧。



你可能感兴趣的:(picoRV32)