VisionFive2 裸机编程

目前在搓一整套从bootloader到kernel的东西作为业余项目,这里会记录一部分在VF2上的操作
由于工作比较繁忙,架构尽量抛弃现有架构,需要大量阅读论文和思考解决很多问题,所以推进极其之慢

4 Likes

跑在uboot之上的基础ELF内核

姑且将这个ELF文件称为内核吧

  1. 遵循裸机编程规范,抛弃所有依赖Linux的库,然后正常编译为riscv64的ELF文件
  2. 启动VF2,通过拨码开关,使VF2进入从Flash启动模式
  3. 连接uart串口到电脑,此时进入uboot后,打断,并进入uboot的shell,这里我使用minicom
sudo minicom -b 115200 -D /dev/ttyUSB0
  1. 使用uart串口传输编译好的内核文件(此时是uboot的shell)
loadx
  1. 此时界面会打印CCCCCCCC,等待通过modemx协议从串口接收数据,使用minicom快捷键Ctrl+A 然后Ctrl+Z 呼出菜单,选择modemx,然后就是选择文件等等,等待传输完成
  2. 传输完成后uboot会打印出load到的内存地址,默认是0xa0000000
  3. 下一步需要bootelf,来指定从我们加载的ELF文件启动,这里需要指定我们load文件的起始地址,也就是0xa0000000,具体用法请查看bootelf命令行参数的用法
  4. 成功从elf格式的内核启动
4 Likes

666,原来是bootelf,等我板子维修回来,就试试。

非常有想法呀,这里和ARM上bare-metal(裸机开放)的流程很相似呀。

提醒一下,U74-MC的L2 cache上电时默认以LIM模式工作,此时有接近2MB的片上ram可用(使用前需要清零被使用的区域要不然回报ECC错误);uboot spl目前就运行在lim中

2 Likes

老兄, github 有没有此项目?

的确可以运行。
StarFive # bootelf 0xa0000000
Unhandled exception: Load access fault
EPC: 00000000fffa2742 RA: 00000000fffa2774 TVAL: 00000073a800e4aa
EPC: 000000004025d742 RA: 000000004025d774 reloc adjusted

SP: 00000000ff734a00 GP: 00000000ff734e00 TP: 0000000000000001
T0: 00000000a0008000 T1: 00000000fff4628a T2: 0000000000000000
S0: f14027f3a800e4a2 S1: 00000000a0000000 A0: 00000000a0000000
A1: 00000000a0008000 A2: 0000000000000000 A3: 0000000000000000
A4: 00000000000097ba A5: 0000000000000080 A6: 0000000000000000
A7: 0000000000000000 S2: 0000000000000002 S3: 0000000000000008
S4: 0000000000000000 S5: 0000000000000002 S6: 0000000000000000
S7: 00000000ff7467b0 S8: 0000000000000000 S9: 0000000000000000
S10: 0000000000000000 S11: 0000000000000000 T3: 0000000000000000
T4: 0000000000000000 T5: 0000000000000000 T6: 00000000a0000000

Code: 69a2 6145 8082 7480 1793 0069 9426 943e (641c)

这是运行在u-boot和spi的基础上的,也就是说运行的ELF内核是在S模式以下,不如visionfive1来的痛快,可以直接运行在M模式下。尝试把xv6移植到visiofive1上运行,运行到main.c时会出现莫名其妙错误,全局初始化变量started在mhartid=1核上会看到意想不到的值,后面全局变量都有同样的问题,搞不明白,感觉走不下去了,望大侠们不惜指点。

这个exception是u-boot打印出来的,看起来是u-boot尝试在读取00000073a800e4aa 这个非法地址。你看一下你载入的这个elf是怎么样构成的

kernel.ld内容:
SECTIONS
{
/*

  • ensure that entry.S / _entry is at 0xa0000000,

*/

. = 0xa0000000;

.text : {
(.text .text.)
. = ALIGN(0x1000);
_trampoline = .;
*(trampsec)
. = ALIGN(0x1000);
ASSERT(. - _trampoline == 0x1000, “error: trampoline larger than one page”);
PROVIDE(etext = .);
}

.rodata : {
. = ALIGN(16);
“kernel.ld” 45L, 865C
1.这应该是个虚拟地址,根据kernel.ld连接脚本,地址是从0xa00000000开始,加载的kernel.bin.normal.out的文件大小32K左右,远远达不到00000073a800e4aa这个地址,uboot怎么会读取到这个地址的呢?

如果你是自己build u-boot的话,直接addr2line这两个地址就可以看出是u-boot哪一行代码出了问题