前两天猴子先偷偷把之前编完的执行档拿来验证,
今天来把 Cross Compiler 的部分补完。
有些夥伴没接触过嵌入式系统,
可能不了解什麽是 Cross Compile,
初学者在写程序的时候,
通常都是编译环境和执行环境在同一个平台上。
例如:在自己电脑(x86)上写 C 语言程序、编译、执行,
就算从别台电脑把程序拿来执行,也同样是在 x86 的电脑上面。
但是学过底层运作方式的夥伴就会知道,
实际上不同的电脑支援的指令是不一样的,
就算同样是 x86 ,也会因为型号的不同而不同(ex: sse 指令集),
导致 A 电脑编译出来的执行档在 B 电脑上面无法执行。
简单来说就是当开发环境(写程序、编译的电脑)和执行环境(执行的电脑)不一样的时候,
就需要输出执行环境能运作的执行档,才能放到要执行的平台上执行,
也就是刚刚提到的 Cross Compile。
最常见的就是在 x86 (桌上型电脑)上面开发 ARM (手机)平台上的软件,
像 Linux 在桌上型电脑上可能 2 个小时就可以编译完,
在 Raspberry Pi 上面大概按下编译就可以睡到隔天,
光编译的时间差就会导致开发效率的低落,
更别说 x86 平台上丰富的软件支援了。
说了那麽多,
Cross Compile 的流程除了执行环境以外,其实跟一般开发流程一模一样,
关键的地方在於如何取得 Cross Compiler,
下面就是怎麽取得在 x86 上面运作,输出 RISC-V 执行档的 Cross Compiler 流程。
$git clone https://github.com/riscv/riscv-gnu-toolchain
$cd riscv-gnu-toolchain && git submodule update -i -r
$sudo apt-get install autoconf automake autotools-dev curl python3 libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev
rv32i
以及 ilp32
(32-bit soft-float) 的 abi,/home/user/Desktop/code/rv32i-ilp32-gnu-toolchain
//in riscv-gnu-toolchain folder
$./configure --prefix=/home/user/Desktop/code/rv32i-ilp32-gnu-toolchain --with-arch=rv32i --with-abi=ilp32
$make
//wait for loooooooooooong time
Makefile
中指定 Toolchain 路径//console
$make test
//Makefile
...
export PATH=$PATH:/home/user/Desktop/code/rv32i-ilp32-gnu-toolchain/bin
CC= riscv32-unknown-elf-gcc
test: test.c
$(CC) $< -o test
...
github 页面 Tag: ITDay29
昨晚误会 gcc 编译出来的执行档有 Memory Access Misalignment,
还以为自己对环境的运作了解的不够深入,
讲了大半天的 LOAD/STORE Exception 规范,该不会全错?!
冷静下来追查才发现是误会一场,猴子吓猴子果然是最可怕的!
Memory Access Misalignment 的问题是因为参考 RISC-V-TLM 的输出,
回推 x2
初始值为 0x3FFFFdF + 32
= 0x3FFFFFF
,
把 stack 位置设定为 0x3FFFFFF
导致的问题,改成 0x40000
就OK了!
//RISC-V-TLM output
time 0 s: PC: 0x10054. time 0 s: ADDI: x2 + -32 -> x2(0x3ffffdf)
//cpu.cpp
register_file->set_value_integer(REGISTER_INTERFACE::x2, 0x40000);
因为 gcc 编译出来的是 ELF 格式,目前 Simulator 还不支援,
我们支援的 Intel HEX 格式需要用 objcopy 工具,
刚刚编 Toolchain 的时候也有一起做出来。
//Makefile
CROSS_COMPILE ?= riscv32-unknown-elf-
CC= $(CROSS_COMPILE)gcc
CFLAGS = -Wall -I. -O0 -nostdlib -march=rv32i -mabi=ilp32 --entry main
SRC= test
TARGET= binary
export PATH:=/home/user/Desktop/code/rv32i-ilp32-gnu-toolchain/bin:${PATH}
all: $(addsuffix .o, $(SRC))
$(CROSS_COMPILE)objcopy -Oihex $< $(TARGET).hex
readelf -a $<
%.o: %.c
$(CC) $(CFLAGS) $< -o $@
clean:
-rm *.o *.hex
咦?!
这次可以从 readelf 印出来的资讯找到 main
起始位置为 0x10054
,
该不会我误会 RISC-V-TLM 了吧!
明天再来研究看看 Intel HEX Format 的 segmentation 是不是真的要 * 16
。
//RISCV-SIM/test
$make
...
Symbol table '.symtab' contains 13 entries:
...
9: 00010054 32 FUNC GLOBAL DEFAULT 1 main
...
上面的疑问先放一边,
今天和猴子一起来享受执行第一个程序的成就感吧,
一样从 Cpu 设定 Simulator 起始执行位置为 0x1054
,
再把刚刚编出来的 binary.hex 放到 simulator 旁边执行!
//cpu.cpp
...
register_file->set_pc(0x1054);
register_file->set_value_integer(REGISTER_INTERFACE::x2, 0x40000);
while(true) {
step();
wait(delay);
}
...
//RISCV-SIM
$make run
...
current_pc: 0x1054 target_pc: 0x1058 ADDI 2 16 2 rs1Value: 0x3fff0 rs2Value: 0x0 rdValue: 0x3fff0 immValue: 0xfffffff0
current_pc: 0x1058 target_pc: 0x105c SW 2 8 12 rs1Value: 0x3fff0 rs2Value: 0x0 rdValue: 0x0 immValue: 0xc
current_pc: 0x105c target_pc: 0x1060 ADDI 2 16 8 rs1Value: 0x3fff0 rs2Value: 0x0 rdValue: 0x40000 immValue: 0x10
current_pc: 0x1060 target_pc: 0x1064 ADDI 0 0 15 rs1Value: 0x0 rs2Value: 0x0 rdValue: 0x0 immValue: 0x0
current_pc: 0x1064 target_pc: 0x1068 ADDI 15 0 10 rs1Value: 0x0 rs2Value: 0x0 rdValue: 0x0 immValue: 0x0
current_pc: 0x1068 target_pc: 0x106c LW 2 12 8 rs1Value: 0x3fff0 rs2Value: 0x0 rdValue: 0x0 immValue: 0xc
current_pc: 0x106c target_pc: 0x1070 ADDI 2 16 2 rs1Value: 0x40000 rs2Value: 0x0 rdValue: 0x40000 immValue: 0x10
current_pc: 0x1070 target_pc: 0x0 JALR 1 0 0 rs1Value: 0x0 rs2Value: 0x0 rdValue: 0x0 immValue: 0x0
INVALID: Opcode :0
Illegal Instruction, end simulation!
exception!
成功!
自己编译 Cross Compiler 就是这麽简单~
最近几天在网站上看了有管git的资料, 发现了 "连猴子都能懂的Git指南" 就...
大纲 昨天完成了header的下半部分,今天的任务就要来完成header的上半部分 —— Navig...
图片来源 延续昨日的结论, 从整体的目标设定结果来看, 其实可以明显分成三个类型, 即(1)技术面...
第 22 天 ! 当我们资料项下传递的时候, 会发现, component 的阶层越深, 传递资讯会...
反弹球 ( 乒乓球 ) 教学原文参考:反弹球 ( 乒乓球 ) 这篇文章会介绍,如何在 Scratch...