891|4

1535

帖子

2

资源

五彩晶圆(初级)

安路SparkRoad开发板测评(8) MCU 软核 RISC-V程序编写 [复制链接]

  前面我已经推测出来,Agile RISC-V软核的程序是放在当中的BRAM IP内的,以32-bit字为单位,复位后从BRAM的99(十进制)开始运行。入口地址换算成字节地址是0x18C.

  初始化BRAM的方式用.mif文件比较方便,所以我对cpu_gate.v再略作修改,将四个EG_LOGIC_BRAM模块参数INIT_FILE分别改为 ”init1.mif”,”init2.mif”,”init3.mif”,”init4.mif”,不再将数据以字符串方式嵌在.v文件内。

mifinit.png

  作为准备工作,我还需要编写一个将RISC-V编译器生成的.bin文件转换为.mif文件的工具。因为这个用途特殊,需要将32位字拆成四个字节分散到四个文件内。用C编写一个:

212308svuzwwoijkncuem5.png

 

  第一个测试程序,测试循环是否能够执行:

212308i2fx25lsfsbb5i3e.png

 

  编译指令:riscv gcc -c -O2 -march=rv32i -mabi=ilp32 test0.c

  生成ELF文件:riscv ld -Ttext 0x18c test0.o -o test0.elf

  反汇编查看编译结果:riscv objdump -d test0.elf

test0.elf:     file format elf32-littleriscv

Disassembly of section .text:

0000018c <_start>:
 18c:   00100693                li      a3,1
 190:   00200713                li      a4,2
 194:   00300793                li      a5,3
 198:   00000013                nop
 19c:   10002023                sw      zero,256(zero) # 100 <_start-0x8c>
 1a0:   10d02223                sw      a3,260(zero) # 104 <_start-0x88>
 1a4:   10e02423                sw      a4,264(zero) # 108 <_start-0x84>
 1a8:   10f02623                sw      a5,268(zero) # 10c <_start-0x80>
 1ac:   fedff06f                j       198 <_start+0xc>

 

  GCC编译说明:因为不知道Agile RISC-V实现的指令集,使用最基础的32位指令架构,用 -march=rv32i指定。链接时候不需要任何其它代码,为了将 _start入口地址定在0x18c,将.text段地址指定为0x18c.

  生成.bin文件:riscv objcopy -Obinary test0.elf test0.bin

2022-05-07 19:02 36    test0.bin

         1 个文件 36 字节

  程序一共9条指令,每条指令4字节。为了将这9条指令放到RAM的0x18c地址处,需要在生成.mif文件的时候从第99个字节开始放程序内容。上面我贴的转换程序中已经做了处理。

  例如,生成的init1.mif文件内容如下

DEPTH=1024;
WIDTH=8;
ADDRESS_RADIX=UNS;
DATA_RADIX=HEX;

CONTENT BEGIN
0 : 00;
1 : 00;
2 : 00;
3 : 00;
…省略若干行…
97 : 00;
98 : 00;
99 : 93;
100 : 13;
101 : 93;
102 : 13;
103 : 23;
104 : 23;
105 : 23;
106 : 23;
107 : 6F;
END;

  将四个.mif文件复制到FPGA工程目录,重新综合,下载。观察运行效果:

 

  可以看到取指令地址从99开始,增加到107之后变到102,然后在102到107之间循环。这和我编写的代码中最后一条指令(0x1ac处)是跳转到0x198吻合。可以判定循环得到了正确执行。循环当中往0x100, 0x104, 0x108, 0x10c地址写了数,这个操作结果还无法验证。

 

  下一步,查找软核的外部总线地址在哪里。因为软核引出的bus_addr宽度是28-bit,数据为32-bit,地址范围是1GB. 先猜测外部总线地址是对齐到256MB边界的,也就是开始于0x10000000的整数倍这样的地址。写个程序尝试往某些地址写入,然后观看外部总线上的信号,如果有地址和数据输出以及有写信号,就能推断地址映射关系。

 

  第二个测试程序:

212308mmfhrggf60e0f6x3.png

  编译后反汇编代码:

Disassembly of section .text:

0000018c <_start>:
 18c:   01000613                li      a2,16
 190:   00000013                nop
 194:   00000793                li      a5,0
 198:   01c79713                slli    a4,a5,0x1c
 19c:   00578693                addi    a3,a5,5
 1a0:   00d72e23                sw      a3,28(a4)
 1a4:   00178793                addi    a5,a5,1
 1a8:   fec798e3                bne     a5,a2,198 <_start+0xc>
 1ac:   fe5ff06f                j       190 <_start+0x4>

  为了观察总线动作,连接到板子上的LED:

212308e21nocl8b2111bic.png

  运行效果:


 

  一个大循环中捕捉到四次总线总线写操作,通过LED指示的地址和数据,可以判断外部总线映射地址在0x80000000~0xBFFFFFFC范围,因为没有bit mask,只支持32位的读写。

这样就可以在程序中访问外部总线了,FPGA中可以编写硬件设备供程序操作。

 

  还需要判断一下软核中SRAM的地址。上面的程序中没有用到SRAM所以不知道其地址也没有问题。现在猜SRAM位于0x80000000以下的地址,先按128MB对齐的地址搜索一遍(一共16个地址),判断一下是否是可读写的地址:写的数和读回来的一致则认为存在SRAM. 使用外部总线输出指示找到的有效地址。

 

  第三个测试程序:

212308od0gnjnnytqzgjic.png

212308x6iy60ryofxr6rfz.jpg

  运行时候,写外部总线地址 1, 数据0x80. 因此程序中i=0 时发现了SRAM. 故SRAM位于地址0x0开始的地方。

 

  最后再用一个测试程序,将SRAM的内容读出来,写到外部总线,这样可以通过LED查看SRAM中的内容。读外部总线是读16个开关状态,通过开关选择要读的SRAM地址。

212308wyonjybucb6ojcmd.png

  反汇编代码:

Disassembly of section .text:

0000018c <_start>:
 18c:   00000793                li      a5,0
 190:   800006b7                lui     a3,0x80000
 194:   00f687b3                add     a5,a3,a5
 198:   0007a783                lw      a5,0(a5)
 19c:   0007c703                lbu     a4,0(a5)
 1a0:   00279793                slli    a5,a5,0x2
 1a4:   00f68633                add     a2,a3,a5
 1a8:   0ff77713                andi    a4,a4,255
 1ac:   00e62023                sw      a4,0(a2)
 1b0:   fe5ff06f                j       194 <_start+0x8>

 

  运行效果(将时钟加快了,提高响应速度)


 

  可以发现,SRAM的内容大部分都是0, 在0x18c地址,读到了0x93值,以及其它几个位置都和程序代码地址对应的数据一致。因此说明SRAM和存放程序的ROM是同一块存储,这也侧面验证了软核中使用双端口BRAM的目的:程序和数据使用同一RAM空间。

  知道了RAM的地址和程序地址,就可以编写复杂一点的程序了。

  这个MCU软核中还有GPIO和UART,以及外部中断输入功能。但是因为缺乏资料,很难去探测怎么使用。


回复

9723

帖子

21

资源

版主

不如试试picorv32,有人好像有人移植过。


回复

1990

帖子

2

资源

五彩晶圆(初级)

picorv32好像还有jtag接口,就不需要使用内置的方式写程序了


回复

1535

帖子

2

资源

五彩晶圆(初级)

弄pico risc-v就随便一块FPGA搞了,与本评测的目的不在一条线上。


回复

4

帖子

0

资源

一粒金砂(中级)

大佬好强,RISCV芯片目前可以使用的开发板不是很多


回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

最新文章 更多>>
    推荐帖子
    芯灵思SinlinxA33 SD卡烧写

    工具: 烧写软件:PhoenixCard 读卡器 镜像文件 按图示操作 392865 等待烧写完成 392864 ...

    PROTEL99SE的DDB项目如何在AD20中打开,感谢大家

    PROTEL99SE的DDB项目如何在AD20中打开,感谢大家

    华为MH5000-31

    哪位大佬有华为MH5000-31 M.2接口的芯片的原理图和PCB封装呀,可以发一下吗。

    分库:X-NUCLEO IKS01A3运动和环境传感器开发平台

    更新日期:2月1日 开发平台应用指南 / X-NUCLEO IKS01A3运动和环境传感器开发平台 分库: 1、523957 文档简介 ...

    求助DDS芯片(AD9833)不能输出波形

    使用51单片机,AD9833不能输出波形,但是测量输出引脚的电压却是正常的,为0.62V,AD9833数据手册上是输出电压为0.65V,但是就是 ...

    高端的DEBUG,往往只需要最朴素的测试方法

    作者:一博科技高速先生 黄刚 回顾下上篇文章我们的验证过程哈,首先我们已经知道了是由于我们原来的封装不能兼容 ...

    关闭
    站长推荐上一条 1/10 下一条

    About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

    站点相关: 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

    北京市海淀区知春路23号集成电路设计园量子银座1305 电话:(010)82350740 邮编:100191

    电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2022 EEWORLD.com.cn, Inc. All rights reserved
    快速回复 返回顶部 返回列表