欢迎光临散文网 会员登陆 & 注册

嵌入式rust中RISCV单片机PAC库生成

2023-07-19 18:50 作者:billy_mo  | 我要投稿

        本次尝试生成CH32V103的PAC(其实github上有现成的了),自己生成的目的是探索怎么生成PAC,以便在没有现成PAC的芯片上自己生成并使用rust编程。

嵌入式rust中,生成PAC需要用到对应芯片的SVD文件,以及svd2rust工具。

一,准备工作

1,假设已经安装好了rust的开发环境(这个去网上看怎么安装,很容易),可以使用cago来安装svd2rust.

2,准备芯片对应的svd文件,这个一般可以从芯片厂家获取到。而我取了个巧,去支持这个芯片的现有开发环境中找。比如CH32V103的官方推荐开发环境是MounRiver Studio,电脑安装了它后,在其安装路径的MounRiver_Studio\template\wizard\WCH\RISC-V\CH32V103\NoneOS中,就有CH32V103xx.svd

二,生成PAC库

    打开终端,切换到打算存放PAC库的路径,执行命令:

cargo new ch32v103pac --lib

会在执行命令的目录下自动生成一个ch32v103pac文件夹(这个名字可以自己取),文件夹下有一些内容,这是cargo为我们生成的lib库相关文件,如下图:

注:src下也还有东西,只不过不是我们需要的,可以删除。


接下来把准备好的svd文件(CH32V103xx.svd)放到自动生成的ch32v103pac文件夹中,在ch32v103pac文件夹中通过svd2rust工具处理svd文件,

执行命令:svd2rust --target=riscv -i .\CH32V103xx.svd

命令中--target=riscv指明目标是riscv(CH32V103xx就是riscv的),如果不指明,似乎默认就会认为是cortex-m的。

命令执行后生成了一些文件:

其中lib.rs就是对应的库,这个文件包含了很多东西,而且打开看看可以发现,即使你rust学得很好,里面的代码看起来也很费解,乱七八糟的,而且芯片所有外设都在里面。


接下来要用form工具整理一下lib.rs,并且把芯片的外设一个一个归类好。

安装form工具:cargo install form

先删除自动生成的src目录(因为其内不是我们想要的内容)。然后执行:

form -i .\lib.rs -o src

这个命令通过上面生成的lib.rs,生成了一系列内容,并且输出到src(src被我们删了,这个命令会又自动生成)。到此,自动生成的lib.rs已经不再需要,可以把它删了。

进到src看可以发现里面按芯片的外设分类了,并且生成了很多代码,其实这些内容都来自之前自动生成的lib.rs,随便打开一个看看,依旧是乱七八糟。

接下来用cargo的格式化工具处理它们,执行命令:cargo fmt

注意:没有切入src目录,还是在原来的库根目录执行命令。

执行完后,代码被格式化好了,就比较好阅读了:

继续,

为库添加依赖,因为芯片是基于riscv的,上面只是生成了芯片外设(比如定时器,adc)之类的,riscv内核有其核心内容。所以要添加riscv的一些依赖,如运行时环境。这些不需要自己写,只要是riscv内核的,通用。

打开目录下的cargo.toml文件,添加如下内容:

[dependencies]

critical-section = { version = "1.0", optional = true }

bare-metal = "1.0.0"

riscv = "0.10.0"

vcell = "0.1.0"

riscv-rt = { optional = true, version = "0.11.0" }


[build-dependencies]

svd2rust = { version = "0.29", default-features = false }


[features]

default = ["rt"]

rt = ["dep:riscv-rt"]


到这里,这个单片机的PAC就算完成了,那到底正不正常呢,接下来得试试。


三,验证

为了测试生成的PAC是否正常,我们写一个应用例程来测试它。

回到ch32v103pac同级的目录下(路径不一定要同级,只是为了方便应用例程引用PAC),执行cargo new testpac --bin

进入testpac,在目录下新建一个.cargo文件夹,注意文件夹名字前面是有个.的,再在.cargo里面建立一个config文件,加入如下内容:

# .cargo/config

[target.risCV32imac-unknown-none-elf]

rustflags = [

  "-C", "link-arg=-Tmemory.x",

]


[build]

target = "risCV32imac-unknown-none-elf"



我们要用cargo来管理这个工程,cargo会去工程下的这个文件夹里面的config获取一些配置,所以我们建立了它。

例如:"-C", "link-arg=-Tmemory.x",指明一个连接脚本memory.x,名字看就是和内存有关的。target = "risCV32imac-unknown-none-elf"指明要用risCV32imac-unknown-none-elf编译,因为这个单片机的内核是risCV32imac的。

当然,risCV32imac-unknown-none-elf要安装,使用rustup target add risCV32imac-unknown-none-elf即可安装。

继续。。。。。

上面提到memory.x,就类似单片机以前的连接脚本,指明芯片ram有多大,rom有多少,把它们分成什么数据段,bss段之类的,接下来我们在应用例程的工程根目录创建这个文件,并写入内容:

/* GD32VF103C8 */

MEMORY

{

FLASH : ORIGIN = 0x08000000, LENGTH = 64k

RAM : ORIGIN = 0x20000000, LENGTH = 20k

}


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);

同pac库一样,应用例程也添加依赖,比如PAC库就是应用例程的依赖项,打开应用例程下从cargo.toml,加入如下内容:

[dependencies]

# use pac with critical-section features

critical-section = { version = "1.0", optional = true }

ch32v103pac = { path = "../ch32v103pac", features = ["rt", "critical-section"]}


riscv = { version = "0.10.1",features = ["critical-section-single-hart"]}

panic-halt = "0.2.0"

riscv-rt = "0.11.0"


[profile.release]

codegen-units = 1 # better optimizations

debug = true # symbols are nice and they don't increase the size on Flash

lto = true # better optimizations 

上图截图中,红框处就是生成的PAC库,通过相对路径引用到。

打开src下的main.rs,编写一下代码,引用到PAC里面的内容:

编译应用例程

cargo build

注意,编译的时候,会下载相关依赖,需要网络,而且有可能下载失败,失败的话重新执行上面的命令。

编译完成显示如下:

可以看到,提示了Finished了,其中有个警告是因为我们定义了一个per,但是没有使用它。

到此,我们应用了生成的PAC库内容,并且能顺利编译。然而,我们的应用例程实际没有操作硬件,生成的PAC库到底能不能操作硬件呢,去main函数里面尝试点灯吧!!!!

值得一提的是,PAC库毕竟还是寄存器级别的封装,要像更好用,还要在其上继续封装出HAL库。


提两点:

1,上面生成的内容不太会用,可以生成帮助文档,在工程根目录执行cargo doc --open,执行后,在根目录的target目录里会出现一个doc文件夹:

cargo doc会帮我们生成工程中相关内容的使用文档,后面的--open是生成后顺便打开的意思,也可以不加--open,生成后自己去打开(使用网页浏览器打开的)


2,单片机需要hex或者bin来烧录,上面编译没有生成这类文件,需要使用命令来生成bin文件:cargo objcopy --target risCV32imac-unknown-none-elf --release -- -O binary app.bin

执行完没有错误(依旧提示了那个未使用的警告),并且在项目根目录给我们生成了一个app.bin了


嵌入式rust中RISCV单片机PAC库生成的评论 (共 条)

分享到微博请遵守国家法律