在最近的几篇文章中,我们一直在探索如何启动和运行微控制器的嵌入式应用。上次向大家介绍了Peripheral Access Crate的概念,它为特定微控制器的低级内存映射寄存器提供了一个安全、Rust友好的封装。在今天的文章中,我们将介绍如何使用svd2rust从微控制器供应商的SVD文件中生成您自己的Peripheral Access Crate。
svd2rust是一款生成安全且类型丰富的Rust代码的工具,用于与微控制器外设交互。它采用SVD(系统视图描述)文件(该文件描述了微控制器的寄存器和外设),并使用它来创建外设访问包(PAC)。此PAC提供Rust结构、常量和方法,以便方便安全地访问和配置硬件寄存器。
svd2rust的主要优势在于它消除了底层硬件编程中涉及的大量手动工作。生成强类型Rust API有助于防止常见错误,例如无效的寄存器访问或不正确的位域操作等。生成的代码与Rust的编译时检查无缝集成,确保了高可靠性。
对于嵌入式开发人员,svd2rust通过自动创建安全且直观的硬件界面简化了使用微控制器的过程。这可以加快开发速度并降低出现错误的可能性,让您可以专注于构建那些能使您的项目独一无二的功能。
请注意!对我而言,以下过程85%或更多的时间都是有效的,只有几次失败了,因为微控制器供应商提供的SVD文件格式不符合预期。在某些情况下,例如STM32部件,Rust社区创建了补丁文件,以便svd2rust工具可以充分处理这些文件。
您可以按照几个简单的步骤来创建PAC,让我们来一起看看这些步骤。
在安装软件包之前,确保Rust工具链是最新的通常是明智之举。要确保Rust已更新,只需在命令行运行以下命令:
rustup update
接下来,您需要安装svd2rust工具。在安装该工具之前,我建议您跳转到crates.io并查找svd2rust。它会告诉您有关最新版本的所有信息,为您提供更新日志,甚至有关如何安装svd2rust的说明。要安装它,请在命令行中输入:
cargo install svd2rust
(再次强调,cargo是我们的首选工具!)。
最终,我们会希望我们的PAC是一个可以包含在构建过程中的库。在创建PAC之前,请检查crates.io以查看是否有人已经为您的微控制器创建了PAC。然后您可以使用那个,而不必自己制作!(但并不总是这样)。
在Rust中创建库与创建所有新项目类似。例如,如果您想为STM32U575创建一个PAC,则可以使用以下命令:
cargo new stm32l475_pac –lib
在这里,我们使用Cargo创建一个新项目。该项目名为stm32l475_pac。我们不会就此止步,而是使用–lib告诉Cargo,我们要创建一个库项目。
创建新的库文件将为您提供类似于下图所示的目录结构,位于stm32l475_pac项目下。如您所见,cargo添加了几个文件来帮助我们开始创建PAC。
创建PAC项目后,将微控制器的svd文件复制并粘贴到项目的根目录中。完成后,您可以在命令行中使用以下命令运行svd2rust:
svd2rust -i <device>.svd
注意:确保将<device>替换为您的svd的文件名。
如果一切顺利,并且根据SVD文件,大约85%的情况下都会成功,您将获得如下结果:
您会发现svd2rust出色地创建了您想要的所有结构和内存访问API。不幸的是,您会发现它是在一个名为lib.rs的文件中生成了所有内容,该文件如下所示:
该文件完全无法阅读,格式也很糟糕。好在很容易将lib.rs拆分成一堆crate并清理源代码,我们将使用form和fmt来完成这项工作。
首先,安装form:
cargo install form
接下来,当我们创建PAC项目时,默认会创建一个src文件夹。让我们删除该文件夹,因为我们将在运行表单时创建一个新文件夹:
rm -rf src
form工具会将lib.rs拆分为单独的模块。我们可以使用以下命令执行此操作:
form -i lib.rs -o src/ && rm lib.rs
这里的意思是,我们要拆分lib.rs,将结果输出到src文件夹,当操作完成后,我们要删除lib.rs。
最后,我们要确保代码的可读性。我们可以使用rustfmt来做到这一点。rustfmt是一个命令行工具,它根据官方的Rust风格指南自动格式化Rust代码。它可以处理繁琐的格式化任务,例如缩进、间距和换行符,确保您的代码一致且易于阅读,而无需您费心思考。
rustfmt的目标是让Rust的代码库更加统一和易于维护。通过强制执行标准样式,它减少了代码审查期间关于格式的问题,让开发人员专注于代码的逻辑和功能。无论您是单独工作还是团队合作,rustfmt都有助于确保您的代码看起来专业并遵循最佳实践。
使用rustfmt很简单。只需输入以下内容即可格式化整个项目:
cargo fmt
现在您有一个PAC项目,其中的各个模块均按照Rust编码样式指南进行格式化。
Cargo.toml是Rust项目的核心配置文件,由Rust的软件包管理器和构建系统Cargo使用。它定义了Cargo构建、运行和管理项目所需的一切,包括项目名称、版本和作者等元数据,以及依赖项、构建配置文件和可选功能。Cargo.toml采用人性化易读的TOML格式组织,可作为项目结构和行为的蓝图,确保开发人员和项目工具的一致性和清晰度。
创建PAC时,我们需要将几个依赖项和功能添加到Cargo.toml文件中,以便我们可以在实时环境中使用它并成功编译我们的项目。在Cargo.toml中,我建议为您的PAC添加以下依赖项和功能:
[dependencies]
critical-section = { version = “1.1.2”, optional = true }
cortex-m = “0.7.7”
cortex-m-rt = { version = “0.7.3”, optional = true }
vcell = “0.1.3”
[features]
rt = [“cortex-m-rt/device”]
critical-section提供了一种在代码中创建关键部分的机制,使您可以在从多个上下文(例如中断服务例程(ISR)和主程序)访问共享资源时防止出现竞争条件并确保数据一致性。cortex-m提供对核心ARM Cortex-M功能的底层访问,例如特定于这些微控制器的寄存器和指令。
cortex-m-rt为ARM Cortex-M微控制器提供运行时支持,包括启动代码、链接脚本和中断向量表的定义。
vcell提供易失性单元类型,支持对内存映射外设寄存器进行安全的读写操作。rt是一个功能标志,通常用于有条件地编译需要运行时支持的应用部分,例如启动代码和中断处理。
终于!您现在可以编译PAC了!您可以像使用Cargo编译其他Rust项目一样进行编译;但是,在本例中,我们将使用-r选项进行编译以供发布:
cargo build -r
此模式可启用优化,使编译后的代码运行速度更快、体积更小,但编译时间比默认调试模式更长。发布模式:
如果一切按预期进行,您应该会在终端中看到类似以下的内容:
最后一步与构建PAC无关,即在您自己的项目中使用PAC!我们将在以后的文章中讨论执行此操作所需的步骤。
现在您已经了解了如何使用svd2rust为您的微控制器生成PAC,那么您就拥有了开发嵌入式Rust的强大工具。创建PAC不仅仅是获取代码,它还会为您的嵌入式应用构建一个安全、可靠的基础。
要继续您的旅程,以下是您现在可以采取的几个步骤:
在下一篇文章中,我们将深入探讨如何将新PAC集成到嵌入式Rust应用中,这样您就可以开始在实际项目中使用它了。敬请期待,祝您编程愉快!
(原文刊登于EDN姊妹网站Embedded,参考链接:Embedded Rust: Creating Peripheral Access Crates (PACs),由Ricardo Xie编译。)