在以0x20000000覆盖他们的引导加载程序之前,我将其转储并确保您拥有它的良好副本,或者也许他们在其网站上拥有一个副本.然后,您可以将链接描述文件更改为0x20000000.在我亲自进行操作之前,我将分解并检查他们的引导加载程序,以了解它在做什么,是否值得保留等.他们的文字说可修改"我在hifive1板上割了risc-v齿,但是已经转向sim开源内核,hifive板非常昂贵.我还制作了一个最小的PCB,放下了一些零件,只用完了ram等,但是我的主板太小了,我没有回去再试一次,他们的论坛上对PCB工作的支持很少,并且他们的文档还有一些不足之处.我认为,当普遍可用的修订版时,我会选择其中之一.等着瞧.祝你好运.关键是那里有很多内核,您可以使用verilator或其他仿真器进行仿真,并查看发生的一切,并且您不能砌成砖块,也不能抽烟,因为它是Sims.注意rv32ic riscv32-none-elf-as -march=rv32ic -mabi=ilp32 novectors.s -o novectors.oriscv32-none-elf-gcc -march=rv32ic -mabi=ilp32 -Wall -O2 -nostdlib -nostartfiles -ffreestanding -c notmain.c -o notmain.oriscv32-none-elf-ld novectors.o notmain.o -T memmap -o notmain.elfriscv32-none-elf-objdump -D notmain.elf > notmain.listriscv32-none-elf-objcopy notmain.elf -O binary notmain.bin,您会看到它在尽可能的地方使用了压缩的指令20010000 <_start>:20010000: 80004137 lui x2,0x8000420010004: 00a000ef jal x1,2001000e <notmain>20010008: 9002 ebreak2001000a: a001 j 2001000a <_start+0xa>2001000c <dummy>:2001000c: 8082 ret2001000e <notmain>:2001000e: 1141 addi x2,x2,-1620010010: c422 sw x8,8(x2)20010012: c606 sw x1,12(x2)20010014: 4401 li x8,020010016: 8522 mv x10,x820010018: 3fd5 jal 2001000c <dummy>2001001a: 0405 addi x8,x8,12001001c: bfed j 20010016 <notmain+0x8>编写自己的仿真器也很容易.取决于您要如何逐步学习该平台.掌握指令集,工具链,特定芯片及其外围设备的掌握程度.您绝对希望riscv.org中的risc-v文档与内核支持的版本,大量内部内核寄存器和内容以及指令集相匹配.如果您想做自己的事情,以及有关芯片的入门和芯片文档.如果您想在他们的沙箱中玩游戏并使用一些第三方库,那么您需要学习他们的沙箱并在他们的沙箱中玩游戏,而不是自己做.看来您想做自己的事.请注意,我使用的是手动生成的gnu主线来源的gcc/binutils当前版本.riscv32-none-elf-gcc --versionriscv32-none-elf-gcc (GCC) 9.2.0Copyright (C) 2019 Free Software Foundation, Inc.This is free software; see the source for copying conditions. There is NOwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.riscv32-none-elf-as --versionGNU assembler (GNU Binutils) 2.32Copyright (C) 2019 Free Software Foundation, Inc.This program is free software; you may redistribute it under the terms ofthe GNU General Public License version 3 or later.This program has absolutely no warranty.This assembler was configured for a target of `riscv32-none-elf'.上面的代码在几年前与原始的hifive1配合良好,并且这种样式通常适用于gnu的主要版本,并且我已将此工具链与其他riscv内核一起使用,因此,即使您的riscv内核较旧,它也仍然可以工作.最重要的是将arch(-march)与内核支持的指令集进行匹配,或者所有内核至少应支持rv32i子集,并且压缩和乘法并不总是受支持.我的第一块板的openocd配置文件adapter_khz 10000interface ftdiftdi_device_desc "Dual RS232-HS"ftdi_vid_pid 0x0403 0x6010ftdi_layout_init 0x0008 0x001bftdi_layout_signal nSRST -oe 0x0020 -data 0x0020set _CHIPNAME riscvjtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x10e31913set _TARGETNAME $_CHIPNAME.cputarget create $_TARGETNAME riscv -chain-position $_TARGETNAME$_TARGETNAME configure -work-area-phys 0x80000000 -work-area-size 10000 -work-area-backup 1flash bank onboard_spi_flash fespi 0x20000000 0 0 0 $_TARGETNAMEinit在一个终端/窗口中打开openocd -f riscv.cfg,然后在另一个终端/窗口中打开telnet localhost 4444.现在,就您要询问的gnu汇编程序的细微差别而言,或者甚至最好使用尽可能少的特定于汇编程序/工具链的东西,因为它可能会更改和/或有一天您可能会更改工具. YMMV gnu工具无法从墙上的洞中得知该板.您可以向gnu工具介绍处理器核心体系结构,并在链接描述文件中告知内存映射.您的代码直接或间接(如果使用别人的引导程序和链接程序脚本)必须与处理器内核的引导属性相匹配,无论它是sifive或某些arm内核,mips或x86等的risc-v.是否有矢量表,是否在某个地址执行,等等.在上述情况下,它们的引导程序会跳转到0x20010000,因此您需要将第一条指令放在0x20010000上,这是通过将该指令作为引导源中的第一条指令来完成的,并且如果没有在链接描述文件中指定,请先将该对象放在ld命令行上,并在试图在硬件上运行该对象之前检查一下反汇编以确认其是否有效.我使用的riscv内核没有向量表,要进行重置,它们只是在某个地址开始执行.因此,如果没有预引导程序跳转到您,则将使用相同的方法.对于不是risc-v的其他体系结构,如果是跳转到地址对象还是向量表对象,则用于板/平台的程序的构造将有所不同.现在说,如果您使用的是他们的沙箱,那么这是一个沙箱问题,而不是gnu工具链问题.主板文档和/或网站在其文档中表示,主板在您发现内存映射的FE310-G002文档中使用了FE310-G002芯片.它还表明这是一个risc-v架构,从那里您可以进入riscv.org基础并获得该架构的文档,该文档将告诉您它是如何启动的.然后回到FE310-G002,它会告诉您从MSEL引脚进行的引导过程.您需要检查原理图.因此,现实是他们的文档确实通过提供您需要提供给gnu的信息来告诉您如何指示这是一个引导加载程序.说...需要/需要一些实验.可以/很容易编写一个简单的位置无限循环,为0x00000000构建,但根据其文档在0x20010000处加载,并与openocd一起检查程序计数器以查看它是否确实基于0x20010000.由此,您可以假设最终在出厂时,主板通过任何MSEL选择都可以通过其引导加载程序进入您的引导加载程序.嗯:上电时,内核的重置向量为0x1004.进一步说明每个MSEL表带选项的不同第一指令地址.因此,如果您要接管他们的引导程序,并根据说明文件将其替换为您自己的引导程序,则您将链接为0x20000000并在其中具有入口点.编辑就拿到我的rev b版.您可以查看入门指南,以了解如何指定板子使用他们的沙箱.但这不是必需的,如果您有(gnu)支持rv32i或更多您可以构建的rv32imac的工具链没有其他外部依赖项的程序.工具链本身并不了解一块板,也不知道一块板. sifive文档说:在SPI Flash(0x20000000)开始时,HiFive1 Rev B板附带了可修改的引导加载程序.该程序执行结束时,核心跳到代码的主要用户部分0x20010000.这就是我们需要的关键信息,还有内存映射中内存映射的内存地址空间,用于部分0x80000000 0x4000字节的sram. novectors.s .globl _start_start: lui x2,0x80004 jal notmain j ..globl dummydummy: ret.globl PUT32PUT32: sw x11,(x10) ret.globl GET32GET32: lw x10,(x10) ret notmain.c void PUT32( unsigned int, unsigned int);unsigned int GET32 ( unsigned int );void dummy ( unsigned int );#define GPIOBASE 0x10012000#define GPIO_VALUE (GPIOBASE+0x00)#define GPIO_INPUT_EN (GPIOBASE+0x04)#define GPIO_OUTPUT_EN (GPIOBASE+0x08)#define GPIO_PORT (GPIOBASE+0x0C)#define GPIO_PUE (GPIOBASE+0x10)#define GPIO_OUT_XOR (GPIOBASE+0x40)int notmain ( void ){ unsigned int rx; PUT32(GPIO_OUTPUT_EN,(1<<19)|(1<<21)|(1<<22)); PUT32(GPIO_PORT,(1<<19)|(1<<21)|(1<<22)); PUT32(GPIO_OUT_XOR,0); while(1) { PUT32(GPIO_PORT,(1<<19)|(1<<21)|(1<<22)); for(rx=0;rx<2000000;rx++) dummy(rx); PUT32(GPIO_PORT,0); for(rx=0;rx<2000000;rx++) dummy(rx); } return(0);}内存映射MEMORY{ rom : ORIGIN = 0x20010000, LENGTH = 0x1000 ram : ORIGIN = 0x80000000, LENGTH = 0x4000}SECTIONS{ .text : { *(.text*) } > rom .rodata : { *(.rodata*) } > rom .bss : { *(.bss*) } > ram}构建riscv32-none-elf-as -march=rv32imac -mabi=ilp32 novectors.s -o novectors.oriscv32-none-elf-gcc -march=rv32imac -mabi=ilp32 -Wall -O2 -nostdlib -nostartfiles -ffreestanding -c notmain.c -o notmain.oriscv32-none-elf-ld novectors.o notmain.o -T memmap -o notmain.elfriscv32-none-elf-objdump -D notmain.elf > notmain.listriscv32-none-elf-objcopy notmain.elf -O ihex notmain.hexriscv32-none-elf-objcopy notmain.elf -O binary notmain.bin现在,从理论上讲,您可以使用他们谈论的riscv64-unknown-elf,即使他们想针对rv32而不是rv64进行构建.我也可以尝试. notmain.list Disassembly of section .text:20010000 <_start>:20010000: 80004137 lui x2,0x8000420010004: 010000ef jal x1,20010014 <notmain>20010008: a001 j 20010008 <_start+0x8>2001000a <dummy>:2001000a: 8082 ret2001000c <PUT32>:2001000c: c10c sw x11,0(x10)2001000e: 8082 ret20010010 <GET32>:20010010: 4108 lw x10,0(x10)20010012: 8082 ret20010014 <notmain>:20010014: 1141 addi x2,x2,-1620010016: c04a sw x18,0(x2)20010018: 10012937 lui x18,0x100122001001c: 00890513 addi x10,x18,8 # 10012008 <_start-0xfffdff8>20010020: 006805b7 lui x11,0x68020010024: c606 sw x1,12(x2)20010026: c226 sw x9,4(x2)20010028: c422 sw x8,8(x2)2001002a: 37cd jal 2001000c <PUT32>2001002c: 00c90513 addi x10,x18,1220010030: 006805b7 lui x11,0x68020010034: 3fe1 jal 2001000c <PUT32>20010036: 04090513 addi x10,x18,642001003a: 4581 li x11,02001003c: 001e84b7 lui x9,0x1e820010040: 37f1 jal 2001000c <PUT32>20010042: 0931 addi x18,x18,1220010044: 48048493 addi x9,x9,1152 # 1e8480 <_start-0x1fe27b80>20010048: 006805b7 lui x11,0x6802001004c: 854a mv x10,x182001004e: 3f7d jal 2001000c <PUT32>20010050: 4401 li x8,020010052: 8522 mv x10,x820010054: 0405 addi x8,x8,120010056: 3f55 jal 2001000a <dummy>20010058: fe941de3 bne x8,x9,20010052 <notmain+0x3e>2001005c: 4581 li x11,02001005e: 854a mv x10,x1820010060: 3775 jal 2001000c <PUT32>20010062: 4401 li x8,020010064: 8522 mv x10,x820010066: 0405 addi x8,x8,120010068: 374d jal 2001000a <dummy>2001006a: fe941de3 bne x8,x9,20010064 <notmain+0x50>2001006e: bfe9 j 20010048 <notmain+0x34>在尝试将程序加载到设备上之前,请务必进行检查,对于出厂时的此板/芯片,出厂时所需的入门代码,novectors的第一条说明必须为0x20010000.是的. notmain.hex :020000042001D9:1000000037410080EF00000101A082800CC1828096:100010000841828041114AC0372901101305890027:10002000B705680006C626C222C4CD371305C9002D:10003000B7056800E13F130509048145B7841E0038:10004000F137310993840448B70568004A857D3F3C:10005000014422850504553FE31D94FE81454A85F0:1000600075370144228505044D37E31D94FEE9BF31:0400000520010000D6:00000001FF将notmain.hex复制到已安装的HiFive介质.现在,这花了我一两个小时的时间,试图在我开始时找出十六进制文件,但是在这里它不起作用.下载了他们通过挖出的sdk而发现的elf2hex,但这似乎是对fpga工作的不利切线.弄清楚了,他们正在做的只是riscv ... objcopy -O ihex,就像我尝试过的那样,尝试了一次.现在就可以了.我收到了一个fail.txt文件,说它之前无法连接到CPU.不知道我做了什么或没有做这项工作.理论上,您可以将十六进制文件剪切并粘贴到上面,然后保存并复制.为什么没有人提供十六进制文件示例,您必须正确安装75项特殊的东西并运行构建,而不是在此提供带有中间文件的完整示例.我肯定会在该平台的示例中做到这一点.至少是上面的一个.上述内容将使其闪烁为白色",而不是其彩虹导致的闪烁模式.定期开和关.请注意,LED在修订板上的相同GPIO线上,引导加载程序所到达的地址与修订b 0x20010000不在同一地址0x20400000.因此,只要更改一次内存映射,就可以为开发板构建相同的版本.如果您或读者希望拥有一个修订版,请回溯到修订版,它是经过修改的openocd,在撰写本文时,它位于github riscv用户riscv-openocd项目中.正常的./bootstrap、./configure来获取工具,并且在tcl目录中有上面显示的riscv openocd配置文件interface ftdiftdi_device_desc "Dual RS232-HS"ftdi_vid_pid 0x0403 0x6010是密钥,rev2板lsusb:Bus 001 Device 018: ID 1366:1051 SEGGER,并且对openocd配置文件中的pid/vid值没有任何影响.导致阅读更多的入门手册.I am trying to create a boot program for RISC-V based boards.I am following this guide, and adapting it for riscv.osdevThe problem I'm having is translating this instruction.times 510 -( $ - $$ ) db 0The best I could think of is to just fill 63ish lines of this .8byte 0But this doesn't seem very feasible.Here is the Full code.############################################ Boot Init ############################################.section .textstart: # begins the program nop # the do nothing instruction j start # loops back to start# Todo:: figure out the size of the np and j instruction# The intent of this portion is to fill the remaning bin file with 0's up until the last two bytes.section .rodata .4byte 0 # size of start instructions + this .8byte 0 # begins the zero's, currently 510 byte .8byte 0 # repeat 60ish times .8byte 0x0000000000aa55 # fills the last two bytes with the universal # 55aa to indicate boot programEDITI am using the gcc toolchain for risc. Found here. I am using the .rept directive. Here is the updated code.############################################ Boot Init ############################################start: # begins the program nop # the do nothing instruction j start # loops back to start# Todo:: figure out the size of the np and j instruction# The intent of this portion is to fill the file with 0's up until the last few bytes .rept 63 .8byte 0 .endr .4byte 0 # size of start instructions + this .8byte 0 # begins the zero's, currently 510 byte .8byte 0 .8byte 0x0000000000aa55 # fills the last two bytes with the universal # 55aa to indicate boot programThe hex dump is below:00000000 01 00 fd bf 00 00 00 00 00 00 00 00 00 00 00 00 |................|00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|*00000210 55 aa 00 00 00 00 00 00 |U.......|00000218Here is where I can see that I messed up the endianness of the code obviously.However, I have a new question. What the heck is going on with the left column of the hex dump?? I understand that the * means its filled to 0. However the line goes 0 to 10 then from 210 to 218 why did it increase by 10 first, then 8 at the end? why do i have a blank line (218)?EDITNo need to tell me about the line numbering, I realized now its hex.So the last question remains. How do I indicate to this board that the program is a boot program. Is there a magic number? I could not find any indication on any of their documentation. 解决方案 I have an original hifive1 board. For the original board the getting started guide says this:The HiFive1 Board is shipped with a modifiable boot loader at the beginning of SPI Flash (0x20000000). At the end of this program's execution the core jumps to the main user portion of code at 0x20400000.For the rev b board it says this:The HiFive1 Rev B Board is shipped with a modifiable boot loader at the beginning of SPI Flash (0x20000000). At the end of this program's execution the core jumps to the main user portion of code at 0x20010000.Both chips show 0x80000000 for ram and 0x20000000 for (external) flash. Assume that is the interface where they put the flash on the rev B board.First program.novectors.s.globl _start_start: lui x2,0x80004 jal notmain sbreak j ..globl dummydummy: retnotmain.cvoid dummy ( unsigned int );int notmain ( void ){ unsigned int ra; for(ra=0;;ra++) dummy(ra); return(0);}memmapMEMORY{ ram : ORIGIN = 0x80000000, LENGTH = 0x4000}SECTIONS{ .text : { *(.text*) } > ram .rodata : { *(.rodata*) } > ram .bss : { *(.bss*) } > ram}buildriscv32-none-elf-as -march=rv32i -mabi=ilp32 novectors.s -o novectors.oriscv32-none-elf-gcc -march=rv32i -mabi=ilp32 -Wall -O2 -nostdlib -nostartfiles -ffreestanding -c notmain.c -o notmain.oriscv32-none-elf-ld novectors.o notmain.o -T memmap -o notmain.elfriscv32-none-elf-objdump -D notmain.elf > notmain.listriscv32-none-elf-objcopy notmain.elf -O binary notmain.binIn theory you can use riscv32-whatever-whatever (riscv32-unknown-elf, etc). As this code is generic enough. Also note I am using the minimal rv32i, you can probably use rv32imac.Check the disassembly:Disassembly of section .text:80000000 <_start>:80000000: 80004137 lui x2,0x8000480000004: 010000ef jal x1,80000014 <notmain>80000008: 00100073 ebreak8000000c: 0000006f j 8000000c <_start+0xc>80000010 <dummy>:80000010: 00008067 ret80000014 <notmain>:80000014: ff010113 addi x2,x2,-16 # 80003ff0 <notmain+0x3fdc>80000018: 00812423 sw x8,8(x2)8000001c: 00112623 sw x1,12(x2)80000020: 00000413 li x8,080000024: 00040513 mv x10,x880000028: fe9ff0ef jal x1,80000010 <dummy>8000002c: 00140413 addi x8,x8,180000030: ff5ff06f j 80000024 <notmain+0x10>Being rv32i it is all 32 bit instructions and that is fine. This program is intended to be loaded into ram and run there with a debugger, I use openocd and telnet in.Trying 127.0.0.1...Connected to localhost.Escape character is '^]'.Open On-Chip DebuggerThenhaltload_image notmain.elfresume 0x80000000in the telnet window.Then you can halt again.80000024: 00040513 mv x10,x880000028: fe9ff0ef jal x1,80000010 <dummy>8000002c: 00140413 addi x8,x8,180000030: ff5ff06f j 80000024 <notmain+0x10>You can examine either x8 or x10 to see that it counted:resumehaltand examine the registers again they should have incremented. First program running, moving on.Second program use this linker script instead:memmapMEMORY{ rom : ORIGIN = 0x20010000, LENGTH = 0x4000 ram : ORIGIN = 0x80000000, LENGTH = 0x4000}SECTIONS{ .text : { *(.text*) } > rom .rodata : { *(.rodata*) } > rom .bss : { *(.bss*) } > ram}examine disassembly.Disassembly of section .text:20010000 <_start>:20010000: 80004137 lui x2,0x8000420010004: 010000ef jal x1,20010014 <notmain>20010008: 00100073 ebreak2001000c: 0000006f j 2001000c <_start+0xc>20010010 <dummy>:20010010: 00008067 ret20010014 <notmain>:20010014: ff010113 addi x2,x2,-16 # 80003ff0 <notmain+0x5fff3fdc>20010018: 00812423 sw x8,8(x2)2001001c: 00112623 sw x1,12(x2)20010020: 00000413 li x8,020010024: 00040513 mv x10,x820010028: fe9ff0ef jal x1,20010010 <dummy>2001002c: 00140413 addi x8,x8,120010030: ff5ff06f j 20010024 <notmain+0x10>It appears to be position independent so it should have just worked as was with the other linker script but best to use the correct addresses.My notes say:flash protect 0 64 last offprogram notmain.elf verifyresume 0x20010000And now you should be able to reset or power cycle the board, connect with openocd in a way that doesn't reset (or does if you wish) and then you don't need to load anything it should have run their bootloader that then launched your bootloader at that address (jumped to it as they mention). Examine r8 or r10 (r10 for this abi is the first parameter passed, so even if your gcc builds using something other than r8, r10 should still reflect the counter) resume, halt, reg, resume, halt, reg ...Before overwriting their bootloader at 0x20000000 I would dump it and make sure you have a good copy of it, and or perhaps they have a copy on their website. Then you can change the linker script to 0x20000000. Before I would do that personally I would disassemble and examine their bootloader and find out what if anything it is doing, is it worth keeping, etc. Their text says "modifiable"I cut my risc-v teeth on the hifive1 board, but have moved on to sim open source cores, the hifive boards are pretty expensive. I also made a minimal pcb and put down some sifive parts, was going to only run out of ram, etc, but my board was too minimal and I didn't go back and try again, little support on their forums for pcb work and their docs left something to be desired. I assume when the rev b boards are generally available Ill pick one up. will see. good luck.The point being there are a number of cores out there that you can sim with verilator or other and see everything going on, and you can't brick nor let smoke out because it is a sim.Note rv32icriscv32-none-elf-as -march=rv32ic -mabi=ilp32 novectors.s -o novectors.oriscv32-none-elf-gcc -march=rv32ic -mabi=ilp32 -Wall -O2 -nostdlib -nostartfiles -ffreestanding -c notmain.c -o notmain.oriscv32-none-elf-ld novectors.o notmain.o -T memmap -o notmain.elfriscv32-none-elf-objdump -D notmain.elf > notmain.listriscv32-none-elf-objcopy notmain.elf -O binary notmain.binand you can see it uses the compressed instructions where it can20010000 <_start>:20010000: 80004137 lui x2,0x8000420010004: 00a000ef jal x1,2001000e <notmain>20010008: 9002 ebreak2001000a: a001 j 2001000a <_start+0xa>2001000c <dummy>:2001000c: 8082 ret2001000e <notmain>:2001000e: 1141 addi x2,x2,-1620010010: c422 sw x8,8(x2)20010012: c606 sw x1,12(x2)20010014: 4401 li x8,020010016: 8522 mv x10,x820010018: 3fd5 jal 2001000c <dummy>2001001a: 0405 addi x8,x8,12001001c: bfed j 20010016 <notmain+0x8>Also it is pretty easy to write your own emulator. Depends on how you want to stage learning this platform. How much is mastering the instruction set vs the toolchain vs a specific chip and its peripherals.You definitely want the risc-v documents from riscv.org that match the version supported by the core, lots of internal core registers and stuff plus the instruction set(s). As well as the getting started and the chip doc for the chip in question, if you want to do your own thing. If you want to play in one of their sandboxes and use some third party libraries, then you need to learn their sandbox and play in their sandbox rather than do your own thing. Looks like you are wanting to do your own thing.Note I am using the current version of gcc/binutils from gnu mainline sources, hand built.riscv32-none-elf-gcc --versionriscv32-none-elf-gcc (GCC) 9.2.0Copyright (C) 2019 Free Software Foundation, Inc.This is free software; see the source for copying conditions. There is NOwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.riscv32-none-elf-as --versionGNU assembler (GNU Binutils) 2.32Copyright (C) 2019 Free Software Foundation, Inc.This program is free software; you may redistribute it under the terms ofthe GNU General Public License version 3 or later.This program has absolutely no warranty.This assembler was configured for a target of `riscv32-none-elf'.The above code worked fine years ago against the original hifive1 and this style tends to work for major revs of gnu and I have used this toolchain against other riscv cores, so even if yours is older it should still work. The most important thing is matching the arch (-march) to the instruction sets supported by the core, or at least a subset rv32i should be supported by all cores, compressed and multiply and such are not always supported.My openocd config file for the first boardadapter_khz 10000interface ftdiftdi_device_desc "Dual RS232-HS"ftdi_vid_pid 0x0403 0x6010ftdi_layout_init 0x0008 0x001bftdi_layout_signal nSRST -oe 0x0020 -data 0x0020set _CHIPNAME riscvjtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x10e31913set _TARGETNAME $_CHIPNAME.cputarget create $_TARGETNAME riscv -chain-position $_TARGETNAME$_TARGETNAME configure -work-area-phys 0x80000000 -work-area-size 10000 -work-area-backup 1flash bank onboard_spi_flash fespi 0x20000000 0 0 0 $_TARGETNAMEinitopenocd -f riscv.cfg in one terminal/window then telnet localhost 4444 in another.Now as far as the gnu assembler nuances you are asking about see the gnu assembler, or even better use as little assembler/toolchain specific stuff as you can as it may change and/or you may change tools some day. YMMVThe gnu tools don't know this board from a hole in the wall. you tell the gnu tools about the processor core architecture and in the linker script the memory map. Your code, directly or indirectly (if you use someone elses bootstrap and linker script) must match the boot properties of the processor core be it a risc-v from sifive or some arm core or mips or x86, etc.Vector table or not, execute at some address, etc. In the above case their bootloader jumps to 0x20010000 so you need to put the first instruction at 0x20010000 which is done by having that instruction be the first one in the bootstrap source, and if not specified in the linker script by having that object first on the ld command line, and by examining the disassembly to confirm it worked before ever attempting to run it on the hardware.The riscv cores I have used don't have a vector table, for reset they simply start execution at some address. So you would use the same approach if you didn't have a pre-bootloader jump to you. For other architectures not risc-v the construction of the program for the board/platform would vary if it is a jump to an address thing vs a vector table thing.Now saying that, if you are using their sandbox then this is a sandbox question not a gnu toolchain question.It is in their documentation the board documentation and/or website indicates that the rev b board uses the FE310-G002 chip in the FE310-G002 documentation you find the memory map. It also indicates this is a risc-v architecture and from that you go to the riscv.org foundation and get the documentation for that architecture which tells you how it boots. And back in the FE310-G002 it tells you the boot process from the MSEL pins. Which you would need to examine the schematics. So the reality is their documentation does tell you how to indicate that this is a bootloader program, by providing the information you need to give to gnu.Saying that...some experimenting is desired/required. It is possible/easy to write a simple position infinite loop, build for 0x00000000 but load at 0x20010000 based on their documentation and come in with openocd to examine the program counter to see if it really is 0x20010000 based. From that you can assume that ultimately as shipped the board works its way through their bootloader into yours through whatever MSEL selection.Hmmm:On power-on, the core’s reset vector is 0x1004 .And it goes further to indicate the different first instruction addresses for each of the MSEL strap options. So if you were to take over their bootloader and replace it with your own based on the documentation you would link for 0x20000000 and have the entry point there.EditJust got my rev b board.You can look at the getting started guide to see how to specify the boardusing their sandbox. But that is not required, if you have a (gnu)toolchain that supports rv32i or more than that rv32imac you can buildprograms with no other outside dependencies.The toolchain itself doesn't know one board from another, one chip from another.The sifive documentation says:The HiFive1 Rev B Board is shipped with a modifiable boot loader at the begnning of SPI Flash (0x20000000). At the end of this program’s execution the core jumps to the main user portion of code at 0x20010000.And that is the critical information we need, plus the address space for memory in the memory map for the part 0x80000000 0x4000 bytes of sram.novectors.s.globl _start_start: lui x2,0x80004 jal notmain j ..globl dummydummy: ret.globl PUT32PUT32: sw x11,(x10) ret.globl GET32GET32: lw x10,(x10) retnotmain.cvoid PUT32( unsigned int, unsigned int);unsigned int GET32 ( unsigned int );void dummy ( unsigned int );#define GPIOBASE 0x10012000#define GPIO_VALUE (GPIOBASE+0x00)#define GPIO_INPUT_EN (GPIOBASE+0x04)#define GPIO_OUTPUT_EN (GPIOBASE+0x08)#define GPIO_PORT (GPIOBASE+0x0C)#define GPIO_PUE (GPIOBASE+0x10)#define GPIO_OUT_XOR (GPIOBASE+0x40)int notmain ( void ){ unsigned int rx; PUT32(GPIO_OUTPUT_EN,(1<<19)|(1<<21)|(1<<22)); PUT32(GPIO_PORT,(1<<19)|(1<<21)|(1<<22)); PUT32(GPIO_OUT_XOR,0); while(1) { PUT32(GPIO_PORT,(1<<19)|(1<<21)|(1<<22)); for(rx=0;rx<2000000;rx++) dummy(rx); PUT32(GPIO_PORT,0); for(rx=0;rx<2000000;rx++) dummy(rx); } return(0);}memmapMEMORY{ rom : ORIGIN = 0x20010000, LENGTH = 0x1000 ram : ORIGIN = 0x80000000, LENGTH = 0x4000}SECTIONS{ .text : { *(.text*) } > rom .rodata : { *(.rodata*) } > rom .bss : { *(.bss*) } > ram}buildriscv32-none-elf-as -march=rv32imac -mabi=ilp32 novectors.s -o novectors.oriscv32-none-elf-gcc -march=rv32imac -mabi=ilp32 -Wall -O2 -nostdlib -nostartfiles -ffreestanding -c notmain.c -o notmain.oriscv32-none-elf-ld novectors.o notmain.o -T memmap -o notmain.elfriscv32-none-elf-objdump -D notmain.elf > notmain.listriscv32-none-elf-objcopy notmain.elf -O ihex notmain.hexriscv32-none-elf-objcopy notmain.elf -O binary notmain.binNow in theory you can use the riscv64-unknown-elf they talk about even though they want to build for rv32 not rv64. I can try that too.notmain.listDisassembly of section .text:20010000 <_start>:20010000: 80004137 lui x2,0x8000420010004: 010000ef jal x1,20010014 <notmain>20010008: a001 j 20010008 <_start+0x8>2001000a <dummy>:2001000a: 8082 ret2001000c <PUT32>:2001000c: c10c sw x11,0(x10)2001000e: 8082 ret20010010 <GET32>:20010010: 4108 lw x10,0(x10)20010012: 8082 ret20010014 <notmain>:20010014: 1141 addi x2,x2,-1620010016: c04a sw x18,0(x2)20010018: 10012937 lui x18,0x100122001001c: 00890513 addi x10,x18,8 # 10012008 <_start-0xfffdff8>20010020: 006805b7 lui x11,0x68020010024: c606 sw x1,12(x2)20010026: c226 sw x9,4(x2)20010028: c422 sw x8,8(x2)2001002a: 37cd jal 2001000c <PUT32>2001002c: 00c90513 addi x10,x18,1220010030: 006805b7 lui x11,0x68020010034: 3fe1 jal 2001000c <PUT32>20010036: 04090513 addi x10,x18,642001003a: 4581 li x11,02001003c: 001e84b7 lui x9,0x1e820010040: 37f1 jal 2001000c <PUT32>20010042: 0931 addi x18,x18,1220010044: 48048493 addi x9,x9,1152 # 1e8480 <_start-0x1fe27b80>20010048: 006805b7 lui x11,0x6802001004c: 854a mv x10,x182001004e: 3f7d jal 2001000c <PUT32>20010050: 4401 li x8,020010052: 8522 mv x10,x820010054: 0405 addi x8,x8,120010056: 3f55 jal 2001000a <dummy>20010058: fe941de3 bne x8,x9,20010052 <notmain+0x3e>2001005c: 4581 li x11,02001005e: 854a mv x10,x1820010060: 3775 jal 2001000c <PUT32>20010062: 4401 li x8,020010064: 8522 mv x10,x820010066: 0405 addi x8,x8,120010068: 374d jal 2001000a <dummy>2001006a: fe941de3 bne x8,x9,20010064 <notmain+0x50>2001006e: bfe9 j 20010048 <notmain+0x34>Important to check before you try to load the program onto the device, our desired entry code, first instructions of novectors.s need to be at 0x20010000 for this board/chip as shipped (factory bootloader). And it is.notmain.hex:020000042001D9:1000000037410080EF00000101A082800CC1828096:100010000841828041114AC0372901101305890027:10002000B705680006C626C222C4CD371305C9002D:10003000B7056800E13F130509048145B7841E0038:10004000F137310993840448B70568004A857D3F3C:10005000014422850504553FE31D94FE81454A85F0:1000600075370144228505044D37E31D94FEE9BF31:0400000520010000D6:00000001FFCopy notmain.hex to the mounted HiFive media. Now this cost me an hour or two trying to figure out the hex file as I started, here, it didn't work. Downloaded their sdk dug through that found an elf2hex but that was a bad tangent that was for fpga work it appears. Figured it out and all they are doing is riscv...objcopy -O ihex just like I have, tried it one more time. And now it works. I was getting a fail.txt saying it couldn't connect to the cpu before. Don't know what I did or didn't do to make this work.In theory you can cut and paste the hex file above and save it and copy it. Why does nobody have an example hex file, you gotta have the 75 special things installed right and run a build rather than also provide here is a complete example with intermediate files. I certainly will do this in my examples for this platform. Or at least the one above.Instead of their rainbow led blinking pattern, the above will make it blink "white" on and off at a regular rate.Note LEDs are on the same GPIO lines on the rev a board, the bootloader lands on a different address 0x20400000 than the rev b 0x20010000. So the same can be built for the rev a board with that one memmap change.If you or the reader wants to go back to a rev a if they have one it is a modified openocd, which at the time of this writing is at github riscv user riscv-openocd project. the normal ./bootstrap, ./configure, make to get the tools and in the tcl dir there is the riscv openocd config file shown aboveinterface ftdiftdi_device_desc "Dual RS232-HS"ftdi_vid_pid 0x0403 0x6010was the key, the rev2 board lsusb:Bus 001 Device 018: ID 1366:1051 SEGGERand no hits on those pid/vid values in the openocd config files. Leading to reading more of the getting started manual. 这篇关于在RISC-V中创建启动程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云! 08-29 05:38