Raspberry Pi 推出了搭载全新RP2350微控制器的Pico 2。
RP2350是一款有趣的微控制器单元(MCU)。它拥有两个核心,这两个核心中的一个或两个都可以配置为Arm Cortex-M33或Hazard3 RISC-V。但本文将忽略RISC-V功能。
Pico 2并非唯一一款搭载Cortex-M33微控制器的开发板,但我相信它是全球范围内最便宜且最容易购买的一款。然而,从编程的角度来看,与其他如STM32H5系列的Arm Cortex-M33 MCU相比,Pico 2有一个主要的不同点:RP2350拥有一个(固定的)启动ROM,这为其提供了额外的功能。这带来的影响是,RP2350会首先执行其启动ROM,而不是用户应用程序。此外,我认为为了支持RP2350的特性(如版本控制、A/B版本、安全启动、签名镜像),引入了块(以及分区表)的概念。分区表是可选的,但使用块是必须的。因此,虽然一个用C编写的简单裸机应用程序可以使用Arm GNU工具链进行编译(Pico SDK提供了RP2350 CMSIS支持),但它无法直接在RP2350上执行,因为它缺少描述镜像所需的(元数据)块。
在Pico SDK构建系统中,所需的块在和pico-sdk/src/rp2_common/pico_crt0/embedded_end_block.inc.S中定义。这些是包含一些ifdefs的汇编源文件,这些文件中定义的数据被放入一个名为.embedded_block的段中。然后,这个块根据pico-sdk/src/rp2_common/pico_crt0/rp2350中的链接器描述脚本嵌入到镜像中。
用户应用程序二进制文件的元数据所需的最小块在RP2350数据手册的第5.9.5节“最小可行镜像元数据”中进行了描述。这些元数据存储在一个名为IMAGE_DEF的块中,该块包含两个项目:PICOBIN_BLOCK_ITEM_1BS_IMAGE_TYPE和PICOBIN_BLOCK_ITEM_2BS_LAST。每个块都需要一个类型为LAST的项目作为最后一个项目,这意味着这个最小块实际上只包含一个有意义的项目(IMAGE_TYPE)。镜像类型项目包含以下关于镜像的信息:
- 镜像是可执行的(IMAGE_TYPE_EXE)
- 镜像在安全模式下运行(EXE_SECURITY_S)
- 镜像针对Arm架构(EXE_CPU_ARM)
- 镜像针对RP2350(EXE_CHIP_RP2350)
这个块长20字节,应该位于加载到闪存的二进制文件的前4KB内。这是启动ROM代码找到它的方式。
上述所有信息(EXE、ARM、RP2350)除了一个(SECURITY_S)之外都应该很明显,但你可能会问为什么它在安全模式下运行。原因是RP2350的安全扩展始终启用(不能像STM32 MCU那样禁用)。启动ROM在安全模式下运行,并正常跳转到用户应用程序,因此(至少最初)用户应用程序也应该在安全模式下运行。之后,用户应用程序可以根据需要配置安全性。
由于通常将向量表保存在闪存镜像的开头,并且向量表小于4KB,因此将这个20字节长的块放在向量表之后是有意义的。与Pico SDK构建系统类似,这个块可以很容易地在汇编源文件中创建,并使用链接器描述脚本链接到正确的位置。
我创建了一个非常简单的LED闪烁项目,没有使用Pico SDK构建系统。可以在GitHub上的rp2350-bare-metal-build找到该项目。
https://github.com/metebalci/rp2350-bare-metal-build
原文链接: https://metebalci.com/blog/using-a-pico2-rp2350-without-the-pico-sdk-build-system/