[Rust on SF102] 安路科技 SF1 FPGA 系列评测 (一)- Hello rust!
[复制链接]
本帖最后由 musiclee 于 2023-2-24 22:52 编辑
本帖为 《Rust on SF102》 系列评估文章的开篇,本系列目的是探索在安路科技 SF102 DEMO 板上编写和运行 rust 程序的方案,验证对各种外设的访问控制。对基本的 FPGA 开发仅做简单介绍,内容重点聚焦于 rust 交叉环境的搭建、rust 工程的创建与配置、rust代码编写、外部接口的扩展,以及对应的 FPGA HDL代码编写和测试评估。
SF102 DEMO 板非常适合快速的嵌入式原型开发,相比其他厂商的同类产品,安路科技的 SF1 系列 PSOC 有其突出的特点:
- 内嵌支持 RV32IMCA 指令集的 RISC-V 硬核,高达 160MHz 主频。
- 具备 6K 可编程逻辑资源,且与 RISC-V 硬核高效互连。
- 内置两个四通道 MIPI 硬核提供高达 17.6Gbps 带宽的 MIPI数据收发能力。
- 集成一个 DSC解码模块,符合最新的 VESA DSC 1.2a 标准。
- 2x64Mb 200MHz 存储器+硬核控制器。
上述主要特点使得 SF1 系列芯片非常适合开发视频类嵌入式产品以及各种便携式终端设备。SF102 DEMO 板是一块精简的原型评估板,其主要功能如下图所示:
接下来就不放一般的开箱图了,直入主题,先写一个简单的代码点亮 LED, 验证基本的软件流程。
安路科技开发环境安装
下载安路给的资料包 链接: 提取码:1w3h。
资料包比较大,按照里面的说明安装好 TD 和 FutureDynasty 两个软件,分别用于开发 FPGA 和 RISC-V 工程。
用 TD 创建 FPGA 项目点亮 LED
打开TD软件, 新建项目如图
输入项目名,并选择对应的芯片型号
编写一个简单的顶层 Verilog 源码文件(SF1Top.v):
`timescale 1ns/1ps
module SF1Top (
output led1,
output led2,
output led3,
input clk,
input reset
);
reg [21:0] counter;
assign led1 = counter[19];
assign led2 = counter[20];
assign led3 = counter[21];
always @(posedge clk or posedge reset) begin
if(reset) begin
counter <= 22'h0;
end else begin
counter <= (counter + 22'h000001);
end
end
endmodule
编写约束文件(td1.adc), 具体引脚分配参考 sf1s60cg121i_demo_board_v21.pdf :
set_pin_assignment { clk } { LOCATION = D7; }
set_pin_assignment { led1 } { LOCATION = J4; }
set_pin_assignment { led2 } { LOCATION = J5; }
set_pin_assignment { led3 } { LOCATION = H5; }
set_pin_assignment { reset } { LOCATION = H3; }
项目结构如下图
运行综合和布局布线,然后下载编译好的 bit 流:
正常下载成功后,按下按键 KEY0 即可触发 3 个 LED 不同速率的闪烁, 如下图:
FPGA LED 简单验证工程源码:
td1.zip
(574.13 KB, 下载次数: 0)
用 rust 点亮 LED
由于本系列重点是探索 SF1 系列芯片的 rust 开发方案,因此不会用到原厂的 FutureDynasty 软件。此处仅参考资料包中现成的示例工程,稍加更改验证其 RISC-V 硬核的常规开发流程。
安装 rust 开发编译环境
rust 开发环境安装很简单,参考 https://www.rust-lang.org/zh-CN/ 安装好基本 rust 环境()包括 cargo),然后安装 SF1 需要的交叉编译工具:
# rustup target list 查看可安装的交叉编译工具
rustup target add riscv32imac-unknown-none-elf
# 安装必要的工具
cargo install cargo-binutils
rustup component add llvm-tools-preview
cargo install cargo-generate
从模板创建简单工程
cargo generate --git https://github.com/riscv-rust/riscv-rust-quickstart
修改相关文件如下:
src/main.rs
#![no_std]
#![no_main]
extern crate panic_halt;
use riscv_rt::entry;
use riscv::asm::delay;
use core::ptr::{write_volatile,read_volatile};
const DELAY_COUNT: u32 = 0x10000;
const MISC_BASE_ADDRESS: u32 = 0xE0000000;
const CLOCKCTL_ADDRESS: u32 = MISC_BASE_ADDRESS + 0x10;
const CLOCKCTL: *mut u32 = CLOCKCTL_ADDRESS as *mut u32;
const GPIO_BASE_ADDRESS: u32 = 0xE0020000;
const GPIO_IN_EN_ADDRESS: u32 = GPIO_BASE_ADDRESS + 0x00000004;
const GPIO_OUT_EN_ADDRESS: u32 = GPIO_BASE_ADDRESS + 0x00000008;
const GPIO_OUT_ADDRESS: u32 = GPIO_BASE_ADDRESS + 0x0000000c;
const GPIO_IN_EN : *mut u32 = GPIO_IN_EN_ADDRESS as *mut u32;
const GPIO_OUT_EN : *mut u32 = GPIO_OUT_EN_ADDRESS as *mut u32;
const GPIO_OUT : *mut u32 = GPIO_OUT_ADDRESS as *mut u32;
#[entry]
fn main() -> ! {
unsafe {
write_volatile(CLOCKCTL, 0x83);
write_volatile(GPIO_IN_EN, read_volatile(GPIO_IN_EN) & 0xfffffffb);
write_volatile(GPIO_OUT_EN, read_volatile(GPIO_OUT_EN) | 0x00000004);
loop {
write_volatile(GPIO_OUT, read_volatile(GPIO_OUT) | 0x00000004);
delay(DELAY_COUNT);
write_volatile(GPIO_OUT, read_volatile(GPIO_OUT) & 0xfffffffb);
delay(DELAY_COUNT);
}
}
}
cargo/config
[target.riscv32imac-unknown-none-elf]
rustflags = [
"-C", "link-arg=-Tmemory.x",
"-C", "link-arg=-Tlink.x"
]
[build]
target = "riscv32imac-unknown-none-elf"
添加 memory.x 文件
MEMORY
{
flash : ORIGIN = 0x000E0000, LENGTH = 4M
ilm : ORIGIN = 0x08000000, LENGTH = 8K
ram : ORIGIN = 0x20000000, LENGTH = 8K
}
REGION_ALIAS("REGION_TEXT", flash);
REGION_ALIAS("REGION_RODATA", flash);
REGION_ALIAS("REGION_DATA", ram);
REGION_ALIAS("REGION_BSS", ram);
REGION_ALIAS("REGION_HEAP", ram);
REGION_ALIAS("REGION_STACK", ram);
项目结构如图:
编译并生成 hex 文件
cargo build --release
cargo objcopy --release -- -O ihex oledtest.hex
从资料包示例(TN810_SF102开发板应用例程使用指南.zip)中 打开 oled_screen_display\td_project 项目,综合布局布线,然后打开下载对话框,如图配置好FPGA位流和之前生成的 hex 代码文件。
点击 run 下载到开发板中,下载成功后,可看到右上角 LED 开始闪烁, 至此第一个 rust 程序成功运行!
rust 项目源代码:
oledtest.zip
(6.18 KB, 下载次数: 0)
下一贴将探索编写 rust 代码通过串口收发数据。
|