有人预言,RISC-V或将是继Intel和Arm之后的第三大主流处理器体系。欢迎访问全球首家只专注于RISC-V单片机行业应用的中文网站
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
本帖最后由 新ちゃん 于 2020-8-29 14:35 编辑
如何建立自己的RISC-V编译环境–C_Code?
1.RISC-V编译环境框架这是我RISC-V编译环境的架构: - build case common toolchain
复制代码
一级目录 | 二级目录 | 说明 | build | - | xx.hex、xx.bin、xx.dump & xx.elf生成的目录。 | - | Makefile | 编译脚本。 | - | test | 生成文件,根据test.c生成的xx.hex、xx.bin、xx.dump & xx.elf | project | - | 各个目录的源代码。 | - | test | 放test项目的全部H文件&C文件。 | common | - | 各个项目公用的文件。 | - | encoding.h | /riscv-tests/env目录中的H文件。 | - | program.ld | 类似/riscv-tests/benchmarks/common/test.ld的文件,用于链接物理地址、汇编和C语言代码。 | - | program.S | 最底层的汇编。 | toolchain | - | 工具链。我在/riscv-tools/riscv-gnu-toolchain/的工具链上提取了对我有用的部分。 |
2.各目录内容介绍
2.1 toolchain:工具链目录我不打算介绍,如果有不明白的,可以看我的这个博客:
rocket-chip工具链的编译与使用
2.2 project:这个目录就是放你的项目代码的。每个项目建立一个目录。在这个例子中,我放的是test目录,test的源代码如下(修改于/riscv-tests/benchmarks/vvadd): - #define U32 *(volatile unsigned int *)
- #define DATA_SIZE 100
- int input1_data[DATA_SIZE] =
- {
- 41, 833, 564, 187, 749, 350, 132, 949, 584, 805, 621, 6, 931, 890, 392, 694, 961, 110, 116, 296,
- 426, 314, 659, 774, 319, 678, 875, 376, 474, 938, 539, 569, 203, 280, 759, 606, 511, 657, 195, 81,
- 267, 229, 337, 944, 902, 241, 913, 826, 933, 985, 195, 960, 566, 350, 649, 657, 181, 111, 859, 65,
- 288, 349, 141, 905, 886, 264, 576, 979, 761, 241, 478, 499, 403, 222, 444, 721, 676, 317, 224, 937,
- 288, 119, 615, 606, 389, 351, 455, 278, 367, 358, 584, 62, 985, 403, 346, 517, 559, 908, 775, 255
- };
- int input2_data[DATA_SIZE] =
- {
- 454, 335, 1, 989, 365, 572, 64, 153, 216, 140, 210, 572, 339, 593, 898, 228, 12, 883, 750, 646,
- 500, 436, 701, 812, 981, 150, 696, 564, 272, 258, 647, 509, 88, 703, 669, 375, 551, 936, 592, 569,
- 952, 800, 584, 643, 368, 489, 328, 313, 592, 388, 543, 649, 979, 997, 814, 79, 208, 998, 629, 847,
- 704, 997, 253, 715, 430, 415, 538, 700, 4, 494, 100, 864, 693, 416, 296, 285, 620, 78, 351, 540,
- 646, 169, 527, 289, 796, 801, 720, 758, 745, 92, 989, 271, 853, 788, 531, 222, 461, 241, 358, 332
- };
- //--------------------------------------------------------------------------
- // handle_trap function
- void handle_trap()
- {
- while(1);
- }
- //--------------------------------------------------------------------------
- // test function
- void test( int n, int a[], int b[])
- {
- int i;
- for ( i = 0; i < n; i++ )
- U32(0x20800000+4*i) = a[i] + b[i];
- }
- //--------------------------------------------------------------------------
- // Main
- void main()
- {
- test( DATA_SIZE, input1_data, input2_data);
- }
复制代码
2.3 common:这个目录比较重要,而且改动的地方比较多。
2.3.1 encoding.h:这个目录不解释,就是RISC-V各重要CSR寄存器的定义。
2.3.2 program.ld:这个文件是修改于/riscv-tests/benchmarks/common/test.ld。 - 修改点:
- 1)修改了代码的启始地址。
- /* text: test code section */
- . = 0x80000000;
- 2)去除了这个一大段的空白空间。
- /*. = ALIGN(0x1000);*/
复制代码
2.3.3 program.S:这个文件改动比较大(修改于/riscv-tests/benchmarks/common/crt.S),这个文件改动需要注意以下几点:
1)扩展名必须为大写的S,大写的S可以使gcc自动识别汇编程序中的C预处理命令,像#include、#define、#ifdef、 #endif等,也就是说,使用gcc进行编译,你可以在汇编程序中使用C的预处理命令。
2)因为我生成的rocket-chip是不使用浮点的,不使用虚拟内存,不使用ROCC的,所以很多内容我直接删改了,而且栈和异常入口都是根据我生成的rocket-chip来设定的,大家可以根据自己的情况进行修改。 - 代码:
- #include "encoding.h"
- #define LREG lw
- #define SREG sw
- #define REGBYTES 4
-
- .section ".text.init"
- .globl _start
- _start:
- #####我是注释,下面的操作是清除32个通用寄存器。
- li x1, 0
- li x2, 0
- li x3, 0
- li x4, 0
- li x5, 0
- li x6, 0
- li x7, 0
- li x8, 0
- li x9, 0
- li x10,0
- li x11,0
- li x12,0
- li x13,0
- li x14,0
- li x15,0
- li x16,0
- li x17,0
- li x18,0
- li x19,0
- li x20,0
- li x21,0
- li x22,0
- li x23,0
- li x24,0
- li x25,0
- li x26,0
- li x27,0
- li x28,0
- li x29,0
- li x30,0
- li x31,0
- #####我是注释,下面的操作是配置异常入口,异常入口为trap_entry这个标志。
- # initialize trap vector
- la t0, trap_entry
- csrw mtvec, t0
- # initialize global pointer
- .option push
- .option norelax
- la gp, __global_pointer$
- .option pop
- #####我是注释,下面的操作是配置栈的地址。
- li sp, 0x80F00000
-
- #####我是注释,下面的操作跳到我test项目中的main函数中。
- j main
- #####我是注释,下面的是trap_entry这个函数的内容,申请栈空间,压栈,保存
- #####mcasue&mepc,跳到handle_trap函数中(上面的test.c有这个函数),处理完后
- #####还原MSTATUS_MPP的模式,出栈,跳出trap_entry函数。
- .align 2
- trap_entry:
- addi sp, sp, -272
- SREG x1, 1*REGBYTES(sp)
- SREG x2, 2*REGBYTES(sp)
- SREG x3, 3*REGBYTES(sp)
- SREG x4, 4*REGBYTES(sp)
- SREG x5, 5*REGBYTES(sp)
- SREG x6, 6*REGBYTES(sp)
- SREG x7, 7*REGBYTES(sp)
- SREG x8, 8*REGBYTES(sp)
- SREG x9, 9*REGBYTES(sp)
- SREG x10, 10*REGBYTES(sp)
- SREG x11, 11*REGBYTES(sp)
- SREG x12, 12*REGBYTES(sp)
- SREG x13, 13*REGBYTES(sp)
- SREG x14, 14*REGBYTES(sp)
- SREG x15, 15*REGBYTES(sp)
- SREG x16, 16*REGBYTES(sp)
- SREG x17, 17*REGBYTES(sp)
- SREG x18, 18*REGBYTES(sp)
- SREG x19, 19*REGBYTES(sp)
- SREG x20, 20*REGBYTES(sp)
- SREG x21, 21*REGBYTES(sp)
- SREG x22, 22*REGBYTES(sp)
- SREG x23, 23*REGBYTES(sp)
- SREG x24, 24*REGBYTES(sp)
- SREG x25, 25*REGBYTES(sp)
- SREG x26, 26*REGBYTES(sp)
- SREG x27, 27*REGBYTES(sp)
- SREG x28, 28*REGBYTES(sp)
- SREG x29, 29*REGBYTES(sp)
- SREG x30, 30*REGBYTES(sp)
- SREG x31, 31*REGBYTES(sp)
- csrr a0, mcause
- csrr a1, mepc
- SREG a1, 32*REGBYTES(sp)
- mv a2, sp
- jal handle_trap
- LREG a1, 32*REGBYTES(sp)
- csrw mepc, a1
- # Remain in M-mode after eret
- li t0, MSTATUS_MPP
- csrs mstatus, t0
- LREG x1, 1*REGBYTES(sp)
- LREG x2, 2*REGBYTES(sp)
- LREG x3, 3*REGBYTES(sp)
- LREG x4, 4*REGBYTES(sp)
- LREG x5, 5*REGBYTES(sp)
- LREG x6, 6*REGBYTES(sp)
- LREG x7, 7*REGBYTES(sp)
- LREG x8, 8*REGBYTES(sp)
- LREG x9, 9*REGBYTES(sp)
- LREG x10, 10*REGBYTES(sp)
- LREG x11, 11*REGBYTES(sp)
- LREG x12, 12*REGBYTES(sp)
- LREG x13, 13*REGBYTES(sp)
- LREG x14, 14*REGBYTES(sp)
- LREG x15, 15*REGBYTES(sp)
- LREG x16, 16*REGBYTES(sp)
- LREG x17, 17*REGBYTES(sp)
- LREG x18, 18*REGBYTES(sp)
- LREG x19, 19*REGBYTES(sp)
- LREG x20, 20*REGBYTES(sp)
- LREG x21, 21*REGBYTES(sp)
- LREG x22, 22*REGBYTES(sp)
- LREG x23, 23*REGBYTES(sp)
- LREG x24, 24*REGBYTES(sp)
- LREG x25, 25*REGBYTES(sp)
- LREG x26, 26*REGBYTES(sp)
- LREG x27, 27*REGBYTES(sp)
- LREG x28, 28*REGBYTES(sp)
- LREG x29, 29*REGBYTES(sp)
- LREG x30, 30*REGBYTES(sp)
- LREG x31, 31*REGBYTES(sp)
- addi sp, sp, 272
- mret
- .section ".tdata.begin"
- .globl _tdata_begin
- _tdata_begin:
- .section ".tdata.end"
- .globl _tdata_end
- _tdata_end:
- .section ".tbss.end"
- .globl _tbss_end
- _tbss_end:
复制代码
2.4 bulid:这个目录最主要的是Makefile脚本,用于调用工具链编译project。我只贴部分代码,是生成elf的代码,生成bin、hex和dump的方法大家参考/riscv-tests/benchmarks/Makefile。
部分代码: - #--------------------------------------------------------------------
- # author : xhunter
- # data : 2019.4.2
- # name : project compiler for rocket-chip
- #--------------------------------------------------------------------
- proj_name ?= test
- #--------------------------------------------------------------------
- # Build rules
- #--------------------------------------------------------------------
- RISCV_PREFIX ?= ../toolchain/bin/riscv32-unknown-elf-
- RISCV_GCC ?= $(RISCV_PREFIX)gcc
- RISCV_GCC_OPTS ?= -DPREALLOCATE=1 -mcmodel=medany -static -std=gnu99 -O2 -ffast-math -fno-common -fno-builtin-printf
- RISCV_LINK_OPTS ?= -static -nostdlib -nostartfiles -lm -lgcc -T ../common/program.ld
- SOURCE_FILE ?= -I ../common/*.h ../common/*.S ../project/$(proj_name)/*.c
- #--------------------------------------------------------------------
- # Object
- #--------------------------------------------------------------------
- default:
- make all
- elf:
- $(RISCV_GCC) $(RISCV_GCC_OPTS) -o $(proj_name)/$(proj_name).elf $(SOURCE_FILE) $(RISCV_LINK_OPTS)
-
- all: elf
复制代码本篇完,感谢关注:RISC-V单片机中文网 |