您需要在环境中设置 PICO_SDK_PATH ,或使用-DPICO_SDK_PATH=/path/to/pico-sdk
将其传递给 cmake 。要使用签名或散列等功能,您需要确保 SDK 中的 mbedtls 子模块已签出 - 这可以通过从 SDK 目录运行它来完成。
git submodule update --init lib/mbedtls
您还需要安装libusb-1.0
。
使用您最喜欢的打包工具来安装依赖项。例如,在 Ubuntu 上:
sudo apt install build-essential pkg-config libusb-1.0-0-dev cmake
然后像普通的 CMake 项目一样构建:
mkdir build
cd build
cmake ..
make
在 Linux 上,您可以添加 udev 规则以便无需 sudo 即可运行 picotool:
sudo cp udev/99-picotool.rules /etc/udev/rules.d/
从这里下载 libUSB https://libusb.info/
将 LIBUSB_ROOT 环境变量设置为安装目录。
mkdir build
cd build
cmake -G "NMake Makefiles" ..
nmake
从这里下载 libUSB https://libusb.info/
将 LIBUSB_ROOT 环境变量设置为安装目录。
mkdir build
cd build
cmake ..
make
无需单独下载 libusb 或设置LIBUSB_ROOT
。
pacman -S $MINGW_PACKAGE_PREFIX-{toolchain,cmake,libusb}
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=$MINGW_PREFIX
cmake --build .
Raspberry Pi Pico SDK (pico-sdk) 版本 2.0.0 及更高版本使用picotool
来执行以前由 SDK 中的elf2uf2
工具处理的 ELF 到 UF2 转换。 SDK 还使用picotool
对二进制文件进行哈希和签名。
虽然 SDK 可以为每个项目单独下载 picotool,但如果您有多个项目或构建配置,最好在本地安装picotool
的单个副本。这可以通过make install
或cmake --install .
; SDK 将默认使用此安装版本。
或者,您可以通过以下方式安装到自定义路径:
cmake -DCMAKE_INSTALL_PREFIX=$MY_INSTALL_DIR -DPICOTOOL_FLAT_INSTALL=1 ..
为了让 SDK 在此自定义路径中找到picotool
,您需要在项目中设置picotool_DIR
变量,方法是设置picotool_DIR
环境变量、将-Dpicotool_DIR=$MY_INSTALL_DIR/picotool
传递给cmake
命令,或者添加set(picotool_DIR $MY_INSTALL_DIR/picotool)
到您的 CMakeLists.txt 文件。
picotool
是一个用于处理 RP2040/RP2350 二进制文件并在 RP2040/RP2350 设备处于 BOOTSEL 模式时与它们交互的工具。 (从picotool
版本 1.1 开始,还可以与未处于 BOOTSEL 模式但使用 Raspberry Pi Pico SDK 的 USB stdio 支持的设备进行交互,方法是使用picotool
的-f
参数)。
有关其他文档的说明,请参阅 https://rptl.io/pico-get-started
$ picotool help
PICOTOOL:
Tool for interacting with RP2040/RP2350 device(s) in BOOTSEL mode, or with an RP2040/RP2350 binary
SYNOPSIS:
picotool info [-b] [-p] [-d] [--debug] [-l] [-a] [device-selection]
picotool info [-b] [-p] [-d] [--debug] [-l] [-a] [-t ]
picotool config [-s ] [-g ] [device-selection]
picotool config [-s ] [-g ] [-t ]
picotool load [-p] [-n] [-N] [-u] [-v] [-x] [-t ] [-o ] [device-selection]
picotool encrypt [--quiet] [--verbose] [--hash] [--sign] [-t ] [-o ] [-t ] [-t ] [] [-t ]
picotool seal [--quiet] [--verbose] [--hash] [--sign] [--clear] [-t ] [-o ] [-t ] [] [-t ] [] [-t ] [--major ] [--minor ] [--rollback [..]]
picotool link [--quiet] [--verbose] [-t ] [-t ] [-t ] [] [-t ] [-p]
picotool save [-p] [device-selection]
picotool save -a [device-selection]
picotool save -r [device-selection]
picotool verify [device-selection]
picotool reboot [-a] [-u] [-g ] [-c ] [device-selection]
picotool otp list|get|set|load|dump|permissions|white-label
picotool partition info|create
picotool uf2 info|convert
picotool version [-s] []
picotool coprodis [--quiet] [--verbose] [-t ] [-t ]
picotool help []
COMMANDS:
info Display information from the target device(s) or file.
Without any arguments, this will display basic information for all connected RP2040 devices in BOOTSEL mode
config Display or change program configuration settings from the target device(s) or file.
load Load the program / memory range stored in a file onto the device.
encrypt Encrypt the program.
seal Add final metadata to a binary, optionally including a hash and/or signature.
link Link multiple binaries into one block loop.
save Save the program / memory stored in flash on the device to a file.
verify Check that the device contents match those in the file.
reboot Reboot the device
otp Commands related to the RP2350 OTP (One-Time-Programmable) Memory
partition Commands related to RP2350 Partition Tables
uf2 Commands related to UF2 creation and status
version Display picotool version
coprodis Post-process coprocessor instructions in dissassembly files.
help Show general help or help for a specific command
Use "picotool help " for more info
请注意,不作用于文件的命令需要连接处于 BOOTSEL 模式的设备。
SDK 中支持二进制信息,可以轻松存储picotool
可以找到的紧凑信息(请参阅下面的二进制信息部分)。 info 命令用于读取此信息。
该信息可以从 BOOTSEL 模式下的一个或多个连接的设备中读取,也可以从文件中读取。该文件可以是 ELF、UF2 或 BIN 文件。
$ picotool help info
INFO:
Display information from the target device(s) or file.
Without any arguments, this will display basic information for all connected RP2040 devices in BOOTSEL mode
SYNOPSIS:
picotool info [-b] [-p] [-d] [--debug] [-l] [-a] [device-selection]
picotool info [-b] [-p] [-d] [--debug] [-l] [-a] [-t ]
OPTIONS:
Information to display
-b, --basic
Include basic information. This is the default
-p, --pins
Include pin information
-d, --device
Include device information
--debug
Include device debug information
-l, --build
Include build attributes
-a, --all
Include all information
TARGET SELECTION:
To target one or more connected RP2040 device(s) in BOOTSEL mode (the default)
--bus
Filter devices by USB bus number
--address
Filter devices by USB device address
--vid
Filter by vendor id
--pid
Filter by product id
--ser
Filter by serial number
-f, --force
Force a device not in BOOTSEL mode but running compatible code to reset so the command can be executed. After executing the
command (unless the command itself is a 'reboot') the device will be rebooted back to application mode
-F, --force-no-reboot
Force a device not in BOOTSEL mode but running compatible code to reset so the command can be executed. After executing the
command (unless the command itself is a 'reboot') the device will be left connected and accessible to picotool, but without the
RPI-RP2 drive mounted
To target a file
The file name
-t
Specify file type (uf2 | elf | bin) explicitly, ignoring file extension
请注意,Windows 与 macOS / Unix 平台的 -f 参数略有不同。
例如
$ picotool info 程序信息名称:hello_world 功能:stdout 转 UART
$ picotool info -a
Program Information
name: hello_world
features: stdout to UART
binary start: 0x10000000
binary end: 0x1000606c
Fixed Pin Information
20: UART1 TX
21: UART1 RX
Build Information
build date: Dec 31 2020
build attributes: Debug build
Device Information
flash size: 2048K
ROM version: 2
$ picotool info -bp 程序信息名称:hello_world 功能:stdout 到 UART
固定引脚信息 20:UART1 TX 21:UART1 RX
$ picotool info -a lcd_1602_i2c.uf2
File lcd_1602_i2c.uf2:
Program Information
name: lcd_1602_i2c
web site: https://github.com/raspberrypi/pico-examples/tree/HEAD/i2c/lcd_1602_i2c
binary start: 0x10000000
binary end: 0x10003c1c
Fixed Pin Information
4: I2C0 SDA
5: I2C0 SCL
Build Information
build date: Dec 31 2020
Config 允许您配置设备上的二进制信息(如果可配置)。具体来说,您可以配置bi_ptr_int32
和bi_ptr_string
。
$ picotool help config
CONFIG:
Display or change program configuration settings from the target device(s) or file.
SYNOPSIS:
picotool config [-s ] [-g ] [device-selection]
picotool config [-s ] [-g ] [-t ]
OPTIONS:
Variable name
New value
-g
Filter by feature group
TARGET SELECTION:
To target one or more connected RP2040 device(s) in BOOTSEL mode (the default)
--bus
Filter devices by USB bus number
--address
Filter devices by USB device address
--vid
Filter by vendor id
--pid
Filter by product id
--ser
Filter by serial number
-f, --force
Force a device not in BOOTSEL mode but running compatible code to reset so the command can be executed. After executing the
command (unless the command itself is a 'reboot') the device will be rebooted back to application mode
-F, --force-no-reboot
Force a device not in BOOTSEL mode but running compatible code to reset so the command can be executed. After executing the
command (unless the command itself is a 'reboot') the device will be left connected and accessible to picotool, but without the
RPI-RP2 drive mounted
To target a file
The file name
-t
Specify file type (uf2 | elf | bin) explicitly, ignoring file extension
$ picotool config
n = 5
name = "Billy"
nonconst_pins:
default_pin = 3
default_name = "My First Pin"
$ picotool config -g nonconst_pins
nonconst_pins:
default_pin = 3
default_name = "My First Pin"
$ picotool config -s name Jane
name = "Billy"
setting name -> "Jane"
$ picotool config
n = 5
name = "Jane"
nonconst_pins:
default_pin = 3
default_name = "My First Pin"
load
允许您将文件中的数据写入设备(写入闪存或 RAM)
$ picotool help load
LOAD:
Load the program / memory range stored in a file onto the device.
SYNOPSIS:
picotool load [--ignore-partitions] [--family ] [-p ] [-n] [-N] [-u] [-v] [-x] [-t ] [-o
] [device-selection]
OPTIONS:
Post load actions
--ignore-partitions
When writing flash data, ignore the partition table and write to absolute space
--family
Specify the family ID of the file to load
family id to use for load
-p, --partition
Specify the partition to load into
partition to load into
-n, --no-overwrite
When writing flash data, do not overwrite an existing program in flash. If picotool cannot determine the size/presence of the
program in flash, the command fails
-N, --no-overwrite-unsafe
When writing flash data, do not overwrite an existing program in flash. If picotool cannot determine the size/presence of the
program in flash, the load continues anyway
-u, --update
Skip writing flash sectors that already contain identical data
-v, --verify
Verify the data was written correctly
-x, --execute
Attempt to execute the downloaded file as a program after the load
File to load from
The file name
-t
Specify file type (uf2 | elf | bin) explicitly, ignoring file extension
BIN file options
-o, --offset
Specify the load address for a BIN file
Load offset (memory address; default 0x10000000)
Target device selection
--bus
Filter devices by USB bus number
--address
Filter devices by USB device address
--vid
Filter by vendor id
--pid
Filter by product id
--ser
Filter by serial number
-f, --force
Force a device not in BOOTSEL mode but running compatible code to reset so the command can be executed. After executing the
command (unless the command itself is a 'reboot') the device will be rebooted back to application mode
-F, --force-no-reboot
Force a device not in BOOTSEL mode but running compatible code to reset so the command can be executed. After executing the
command (unless the command itself is a 'reboot') the device will be left connected and accessible to picotool, but without the
RPI-RP2 drive mounted
例如
$ picotool load blink.uf2
Loading into Flash: [==============================] 100%
save
允许您将 RAM 范围、闪存中的程序或闪存中的明确范围从器件保存到 BIN 文件或 UF2 文件。
$ picotool help save
SAVE:
Save the program / memory stored in flash on the device to a file.
SYNOPSIS:
picotool save [-p] [device-selection]
picotool save -a [device-selection]
picotool save -r [device-selection]
OPTIONS:
Selection of data to save
-p, --program
Save the installed program only. This is the default
-a, --all
Save all of flash memory
-r, --range
Save a range of memory. Note that UF2s always store complete 256 byte-aligned blocks of 256 bytes, and the range is expanded
accordingly
The lower address bound in hex
The upper address bound in hex
Source device selection
--bus
Filter devices by USB bus number
--address
Filter devices by USB device address
--vid
Filter by vendor id
--pid
Filter by product id
--ser
Filter by serial number
-f, --force
Force a device not in BOOTSEL mode but running compatible code to reset so the command can be executed. After executing the
command (unless the command itself is a 'reboot') the device will be rebooted back to application mode
-F, --force-no-reboot
Force a device not in BOOTSEL mode but running compatible code to reset so the command can be executed. After executing the
command (unless the command itself is a 'reboot') the device will be left connected and accessible to picotool, but without the
RPI-RP2 drive mounted
File to save to
The file name
-t
Specify file type (uf2 | elf | bin) explicitly, ignoring file extension
例如,首先查看设备上的内容...
$ picotool info
Program Information
name: lcd_1602_i2c
web site: https://github.com/raspberrypi/pico-examples/tree/HEAD/i2c/lcd_1602_i2c
...将其保存到文件中...
$ picotool save spoon.uf2
Saving file: [==============================] 100%
Wrote 51200 bytes to spoon.uf2
...并查看文件:
$ picotool info spoon.uf2
File spoon.uf2:
Program Information
name: lcd_1602_i2c
web site: https://github.com/raspberrypi/pico-examples/tree/HEAD/i2c/lcd_1602_i2c
seal
允许您对二进制文件进行签名和/或散列以在 RP2350 上运行。
默认情况下,它只会对二进制文件进行签名,但这可以使用--hash
和--no-sign
参数进行配置。
您的签名密钥必须适用于secp256k1曲线,采用 PEM 格式。您可以使用以下命令创建 .PEM 文件:
openssl ecparam -name secp256k1 -genkey -out private.pem
$ picotool help seal
SEAL:
Add final metadata to a binary, optionally including a hash and/or signature.
SYNOPSIS:
picotool seal [--quiet] [--verbose] [--hash] [--sign] [--clear] [-t ] [-o ] [-t ] [] [-t
] [] [-t ] [--major ] [--minor ] [--rollback [..]]
OPTIONS:
--quiet
Don't print any output
--verbose
Print verbose output
--major
Add Major Version
--minor
Add Minor Version
--rollback [..]
Add Rollback Version
Configuration
--hash
Hash the file
--sign
Sign the file
--clear
Clear all of SRAM on load
File to load from
The file name
-t
Specify file type (uf2 | elf | bin) explicitly, ignoring file extension
BIN file options
-o, --offset
Specify the load address for a BIN file
Load offset (memory address; default 0x10000000)
File to save to
The file name
-t
Specify file type (uf2 | elf | bin) explicitly, ignoring file extension
Key file
The file name
-t
Specify file type (pem) explicitly, ignoring file extension
File to save OTP to (will edit existing file if it exists)
The file name
-t
Specify file type (json) explicitly, ignoring file extension
encrypt
允许您对二进制文件进行加密和签名以在 RP2350 上使用。默认情况下,它将对加密的二进制文件进行签名,但可以与picotool sign
类似地进行配置。
加密的二进制文件将具有以下结构:
AES 密钥必须以 256 位 AES 密钥的 .bin 文件形式提供,以用于加密。
$ picotool help encrypt
ENCRYPT:
Encrypt the program.
SYNOPSIS:
picotool encrypt [--quiet] [--verbose] [--hash] [--sign] [-t ] [-o ] [-t ] [-t ]
[] [-t ]
OPTIONS:
--quiet
Don't print any output
--verbose
Print verbose output
Signing Configuration
--hash
Hash the encrypted file
--sign
Sign the encrypted file
File to load from
The file name
-t
Specify file type (uf2 | elf | bin) explicitly, ignoring file extension
BIN file options
-o, --offset
Specify the load address for a BIN file
Load offset (memory address; default 0x10000000)
File to save to
The file name
-t
Specify file type (uf2 | elf | bin) explicitly, ignoring file extension
AES Key
The file name
-t
Specify file type (bin) explicitly, ignoring file extension
Signing Key file
The file name
-t
Specify file type (pem) explicitly, ignoring file extension
partition
命令允许您与 RP2350 设备上的分区表交互并创建分区表。
$ picotool help partition info
PARTITION INFO:
Print the device's partition table.
SYNOPSIS:
picotool partition info -m [device-selection]
OPTIONS:
-m [device-selection]
$ picotool partition info
un-partitioned_space : S(rw) NSBOOT(rw) NS(rw), uf2 { absolute }
partitions:
0(A) 00002000->00201000 S(rw) NSBOOT(rw) NS(rw), id=0000000000000000, "A", uf2 { rp2350-arm-s, rp2350-riscv }, arm_boot 1, riscv_boot 1
1(B w/ 0) 00201000->00400000 S(rw) NSBOOT(rw) NS(rw), id=0000000000000001, "B", uf2 { rp2350-arm-s, rp2350-riscv }, arm_boot 1, riscv_boot 1
$ picotool partition info -m rp2350-arm-s
un-partitioned_space : S(rw) NSBOOT(rw) NS(rw), uf2 { absolute }
partitions:
0(A) 00002000->00201000 S(rw) NSBOOT(rw) NS(rw), id=0000000000000000, "A", uf2 { rp2350-arm-s, rp2350-riscv }, arm_boot 1, riscv_boot 1
1(B w/ 0) 00201000->00400000 S(rw) NSBOOT(rw) NS(rw), id=0000000000000001, "B", uf2 { rp2350-arm-s, rp2350-riscv }, arm_boot 1, riscv_boot 1
Family id 'rp2350-arm-s' can be downloaded in partition 0:
00002000->00201000
此命令允许您创建分区表,并另外将它们嵌入到 ELF 文件的块循环中(例如,用于引导加载程序)。默认情况下,所有分区表都经过哈希处理,您也可以对它们进行签名。
$ picotool help partition create
PARTITION CREATE:
Create a partition table from json
SYNOPSIS:
picotool partition create [--quiet] [--verbose] [-t ] [-t ] [[-o ] [--family ]]
[] [-t ] [[--sign ] [-t ] [--no-hash] [--singleton]] [[--abs-block] []]
OPTIONS:
--quiet
Don't print any output
--verbose
Print verbose output
partition table JSON
The file name
-t
Specify file type (json) explicitly, ignoring file extension
output file
The file name
-t
Specify file type (uf2 | elf | bin) explicitly, ignoring file extension
UF2 output options
-o, --offset
Specify the load address for UF2 file output
Load offset (memory address; default 0x10000000)
--family
Specify the family if for UF2 file output
family id for UF2 (default absolute)
embed partition table into bootloader ELF
The file name
-t
Specify file type (elf) explicitly, ignoring file extension
Partition Table Options
--sign
The file name
-t
Specify file type (pem) explicitly, ignoring file extension
--no-hash
Don't hash the partition table
--singleton
Singleton partition table
Errata RP2350-E9 Fix
--abs-block
Enforce support for an absolute block
absolute block location (default to 0x10ffff00)
uf2
命令允许创建 UF2,并且 cam 在 UF2 下载失败时提供信息。
此命令替换了 Raspberry Pi Pico SDK 中之前的 elf2uf2 功能。它将尝试自动检测家庭 ID,但如果失败,您可以使用--family
参数手动指定家庭 ID。
picotool help uf2 convert
UF2 CONVERT:
Convert ELF/BIN to UF2.
SYNOPSIS:
picotool uf2 convert [--quiet] [--verbose] [-t ] [-t ] [-o ] [--family ]
[[--abs-block] []]
OPTIONS:
--quiet
Don't print any output
--verbose
Print verbose output
File to load from
The file name
-t
Specify file type (uf2 | elf | bin) explicitly, ignoring file extension
File to save UF2 to
The file name
-t
Specify file type (uf2) explicitly, ignoring file extension
Packaging Options
-o, --offset
Specify the load address
Load offset (memory address; default 0x10000000 for BIN file)
UF2 Family options
family id for UF2
Errata RP2350-E9 Fix
--abs-block
Add an absolute block
absolute block location (default to 0x10ffff00)
此命令读取设备上有关 UF2 下载失败原因的信息。仅当最近的下载失败时,它才会提供信息。
$ picotool help uf2 info
UF2 INFO:
Print info about UF2 download.
SYNOPSIS:
picotool uf2 info [device-selection]
OPTIONS:
Target device selection
--bus
Filter devices by USB bus number
--address
Filter devices by USB device address
--vid
Filter by vendor id
--pid
Filter by product id
--ser
Filter by serial number
-f, --force
Force a device not in BOOTSEL mode but running compatible code to reset so the command can be executed. After executing the
command (unless the command itself is a 'reboot') the device will be rebooted back to application mode
-F, --force-no-reboot
Force a device not in BOOTSEL mode but running compatible code to reset so the command can be executed. After executing the
command (unless the command itself is a 'reboot') the device will be left connected and accessible to picotool, but without the
RPI-RP2 drive mounted
otp
命令用于与 RP2350 OTP 内存交互。它们在 RP2040 设备上不可用,因为 RP2040 没有 OTP。
请注意,OTP 存储器是一次性可编程的,这意味着一旦一位从 0 更改为 1,就无法改回原来的状态。因此,使用这些命令时应谨慎,因为它们可能会导致 RP2350 设备变砖。例如,如果您设置了 SECURE_BOOT_ENABLE 但没有设置启动键,并禁用 PICOBOOT 接口,那么您的设备将无法使用。
对于list
、 set
、 get
和load
命令,您可以在 JSON 文件中定义自己的 OTP 布局,并使用-i
参数传递该布局。解析时这些行将添加到默认行。
$ picotool help otp
OTP:
Commands related to the RP2350 OTP (One-Time-Programmable) Memory
SYNOPSIS:
picotool otp list [-p] [-n] [-i ] [..]
picotool otp get [-c ] [-r] [-e] [-n] [-i ] [device-selection] [-z] [..]
picotool otp set [-c ] [-r] [-e] [-i ] [-z] [device-selection]
picotool otp load [-r] [-e] [-s ] [-i ] [-t ] [device-selection]
picotool otp dump [-r] [-e] [device-selection]
picotool otp permissions [-t ] [--led ] [--hash] [--sign] [] [-t ] [device-selection]
picotool otp white-label -s [-t ] [device-selection]
SUB COMMANDS:
list List matching known registers/fields
get Get the value of one or more OTP registers/fields (RP2350 only)
set Set the value of an OTP row/field (RP2350 only)
load Load the row range stored in a file into OTP and verify. Data is 2 bytes/row for ECC, 4 bytes/row for raw. (RP2350 only)
dump Dump entire OTP (RP2350 only)
permissions Set the OTP access permissions (RP2350 only)
white-label Set the white labelling values in OTP (RP2350 only)
这些命令将设置/获取 OTP 的特定行。默认情况下,它们将写入/读取所有冗余行,但这可以使用-c
参数覆盖
此命令允许将一系列 OTP 行加载到设备上。源可以是二进制文件,也可以是 JSON 文件,例如picotool sign
输出的文件。例如,如果您希望对二进制文件进行签名,然后使用它测试安全启动,则可以运行以下命令集:
$ picotool sign hello_world.elf hello_world.signed.elf private.pem otp.json
$ picotool load hello_world.signed.elf
$ picotool otp load otp.json
$ picotool reboot
此命令允许 OTP 白标,这会设置设备在 BOOTSEL 模式下使用的 USB 配置。这可以从 JSON 文件进行配置,示例位于 Sample-wl.json 中。
$ picotool help otp white-label
OTP WHITE-LABEL:
Set the white labelling values in OTP
SYNOPSIS:
picotool otp white-label -s [-t ] [device-selection]
OPTIONS:
File with white labelling values
The file name
-t
Specify file type (json) explicitly, ignoring file extension
Target device selection
--bus
Filter devices by USB bus number
--address
Filter devices by USB device address
--vid
Filter by vendor id
--pid
Filter by product id
--ser
Filter by serial number
-f, --force
Force a device not in BOOTSEL mode but running compatible code to reset so the command can be executed. After executing the
command (unless the command itself is a 'reboot') the device will be rebooted back to application mode
-F, --force-no-reboot
Force a device not in BOOTSEL mode but running compatible code to reset so the command can be executed. After executing the
command (unless the command itself is a 'reboot') the device will be left connected and accessible to picotool, but without the
RPI-RP2 drive mounted
$ picotool otp white-label -s 0x100 ../sample-wl.json
Setting attributes 20e0
0x2e8b, 0x000e, 0x0215, 0x0c09, 0x1090, 0x200c, 0x2615, 0x20e0, 0x310b, 0x3706, 0x3a04, 0x3c04, 0x3e21, 0x4f15, 0x5a0a, 0x5f0a, 0x007a, 0x00df, 0x6c34, 0xd83c, 0xdf4c, 0x0020, 0x0054, 0x0065, 0x0073, 0x0074, 0x0027, 0x0073,
0x0020, 0x0050, 0x0069, 0x0073, 0x6554, 0x7473, 0x5220, 0x3250, 0x3533, 0x3f30, 0x6f6e, 0x6e74, 0x6365, 0x7365, 0x6173, 0x6972, 0x796c, 0x6e61, 0x6d75, 0x6562, 0x0072, 0x6554, 0x7473, 0x6950, 0x4220, 0x6f6f, 0x0074, 0x6554,
0x7473, 0x6950, 0x794d, 0x6950, 0x3876, 0x3739, 0x7468, 0x7074, 0x3a73, 0x2f2f, 0x7777, 0x2e77, 0x6172, 0x7073, 0x6562, 0x7272, 0x7079, 0x2e69, 0x6f63, 0x2f6d, 0x656e, 0x7377, 0x002f, 0x6f53, 0x656d, 0x4e20, 0x7765, 0x2073,
0x6241, 0x756f, 0x2074, 0x7453, 0x6675, 0x0066, 0x794d, 0x5420, 0x7365, 0x2074, 0x6950, 0x5054, 0x2d49, 0x5052, 0x3332, 0x3035,
$ picotool reboot -u
$ lsusb -v -s 1:102
Bus 001 Device 102: ID 2e8b:000e zß水? Test's Pis Test RP2350?
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.10
bDeviceClass 0
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor 0x2e8b
idProduct 0x000e
bcdDevice 2.15
iManufacturer 1 zß水? Test's Pis
iProduct 2 Test RP2350?
iSerial 3 notnecessarilyanumber
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 0x0037
bNumInterfaces 2
bConfigurationValue 1
iConfiguration 0
bmAttributes 0xc0
Self Powered
MaxPower 64mA
...
此命令将在您的设备上运行二进制文件以设置 OTP 权限,因为由于修复 RP2350 上的勘误表 XXX 所需的默认权限设置,无法从picotool
直接访问这些权限。由于它运行二进制文件,因此如果启用了安全启动,则需要对二进制文件进行签名。二进制文件将打印它通过 UART 执行的操作,可以使用 UART 配置参数进行配置。您可以在 json 文件中定义 OTP 权限,sample-permissions.json 中有一个示例。
$ picotool help otp permissions
OTP PERMISSIONS:
Set the OTP access permissions
SYNOPSIS:
picotool otp permissions [-t ] [--led ] [--hash] [--sign] [] [-t ] [device-selection]
OPTIONS:
File to load permissions from
The file name
-t
Specify file type (json) explicitly, ignoring file extension
--led
LED Pin to flash; default 25
Signing Configuration
--hash
Hash the executable
--sign
Sign the executable
Key file
The file name
-t
Specify file type (pem) explicitly, ignoring file extension
Target device selection
--bus
Filter devices by USB bus number
--address
Filter devices by USB device address
--vid
Filter by vendor id
--pid
Filter by product id
--ser
Filter by serial number
-f, --force
Force a device not in BOOTSEL mode but running compatible code to reset so the command can be executed. After executing the
command (unless the command itself is a 'reboot') the device will be rebooted back to application mode
-F, --force-no-reboot
Force a device not in BOOTSEL mode but running compatible code to reset so the command can be executed. After executing the
command (unless the command itself is a 'reboot') the device will be left connected and accessible to picotool, but without the
RPI-RP2 drive mounted
$ picotool otp permissions --sign private.pem --tx 46 ../sample-permissions.json
Picking file ./xip_ram_perms.elf
page10
page10 = 0
setting page10 -> 4063233
page11
page11 = 0
setting page11 -> 4128781
page12
page12 = 0
setting page12 -> 4128781
tx_pin = 0
setting tx_pin -> 46
Loading into XIP RAM: [==============================] 100%
>>> using flash update boot of 13ffc000
The device was rebooted to start the application.
二进制信息是机器可定位的并且通常是机器消耗的。我说一般是因为任何人都可以包含任何信息,我们可以从我们的信息中辨别出来,但这取决于他们是否让他们的数据自我描述。
请注意,随着时间的推移,我们肯定会添加更多的二进制信息,但我希望从发布起就获得大多数二进制文件中包含的最小核心集!
当您拿起 Pico 但不知道上面有什么时,此信息非常方便!
基本信息包括
二进制信息是自描述/可扩展的,因此程序可以包含 picotool 不知道的信息(例如 MicroPython 包含内置库的列表)
当您有一个名为“hello_world.elf”的可执行文件但您忘记了它是为哪个主板构建的时,这当然很方便......
静态(固定)引脚分配可以以非常紧凑的形式记录在二进制文件中:
$ picotool info --pins sprite_demo.elf
File sprite_demo.elf:
Fixed Pin Information
0-4: Red 0-4
6-10: Green 0-4
11-15: Blue 0-4
16: HSync
17: VSync
18: Display Enable
19: Pixel Clock
20: UART1 TX
21: UART1 RX
如果您希望能够修改二进制文件中的参数而无需重新编译它,那么这非常方便。
$ picotool config -s name Jane
name = "Billy"
setting name -> "Jane"
二进制信息在程序中通过宏声明(Vile Warped Macros);对于引脚示例:
$ picotool info --pins sprite_demo.elf
File sprite_demo.elf:
Fixed Pin Information
0-4: Red 0-4
6-10: Green 0-4
11-15: Blue 0-4
16: HSync
17: VSync
18: Display Enable
19: Pixel Clock
20: UART1 TX
21: UART1 RX
... setup_default_uart
函数中有一行:
bi_decl_if_func_used ( bi_2pins_with_func ( PICO_DEFAULT_UART_RX_PIN , PICO_DEFAULT_UART_TX_PIN , GPIO_FUNC_UART ));
存储两个引脚号和 UART 功能,然后由 picotool 解码为其实际功能名称(UART1 TX 等)。 bi_decl_if_func_used
确保仅在调用包含函数时才包含二进制信息。
同样,视频代码包含如下几行:
bi_decl_if_func_used ( bi_pin_mask_with_name ( 0x1f << ( PICO_SCANVIDEO_COLOR_PIN_BASE + PICO_SCANVIDEO_DPI_PIXEL_RSHIFT ), "Red 0-4" ));
对于配置示例,您将行
bi_decl ( bi_ptr_string ( 0x1111 , 0x3333 , name , "Billy" , 128 ));
到您的代码中,然后它将创建名称变量供您随后打印。参数包括标签、ID、变量名称、默认值和最大字符串长度。
printf ( "Name is %sn" , name );
设计目的是浪费尽可能少的空间,但您可以使用预处理器变量PICO_NO_BINARY_INFO=1
关闭所有内容。此外,任何插入二进制信息的 SDK 代码都可以通过其自己的预处理器变量单独排除。
你需要
#include "pico/binary_info.h"
基本上,您可以使用bi_decl(bi_blah(...))
无条件包含二进制信息 blah,或者使用bi_decl_if_func_used(bi_blah(...))
来获取二进制信息,如果封闭函数未包含在二进制文件中,则可能会删除这些信息链接器(想想--gc-sections
)
标题中有一堆 bi_ 宏
#define bi_binary_end ( end ) ...
#define bi_program_name ( name ) ...
#define bi_program_description ( description ) ...
#define bi_program_version_string ( version_string ) ...
#define bi_program_build_date_string ( date_string ) ...
#define bi_program_url ( url ) ...
#define bi_program_feature ( feature ) ...
#define bi_program_build_attribute ( attr ) ...
#define bi_1pin_with_func ( p0 , func ) ...
#define bi_2pins_with_func ( p0 , p1 , func ) ...
#define bi_3pins_with_func ( p0 , p1 , p2 , func ) ...
#define bi_4pins_with_func ( p0 , p1 , p2 , p3 , func ) ...
#define bi_5pins_with_func ( p0 , p1 , p2 , p3 , p4 , func ) ...
#define bi_pin_range_with_func ( plo , phi , func ) ...
#define bi_pin_mask_with_name ( pmask , label ) ...
#define bi_pin_mask_with_names ( pmask , label ) ...
#define bi_1pin_with_name ( p0 , name ) ...
#define bi_2pins_with_names ( p0 , name0 , p1 , name1 ) ...
#define bi_3pins_with_names ( p0 , name0 , p1 , name1 , p2 , name2 ) ...
#define bi_4pins_with_names ( p0 , name0 , p1 , name1 , p2 , name2 , p3 , name3 ) ...
它利用底层宏,例如
#define bi_program_url ( url ) bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_PROGRAM_URL, url)
注意:很容易忘记将它们包含在bi_decl
等中,因此如果您这样做,我们会尽力(以大量小猫为代价)使构建失败并显示一些有用的错误消息。
例如,尝试编译
bi_1pin_with_name ( 0 , "Toaster activator" );
给出
/home/graham/dev/mu/pico_sdk/src/common/pico_binary_info/include/pico/binary_info/code.h:17:55: error: '_error_bi_is_missing_enclosing_decl_261' undeclared here (not in a function)
17 | #define __bi_enclosure_check_lineno_var_name __CONCAT(_error_bi_is_missing_enclosing_decl_,__LINE__)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
... more macro call stack of doom
您可以使用
pico_set_program_name(foo "not foo" ) # as "foo" would be the default
pico_set_program_description(foo "this is a foo" )
pico_set_program_version(foo "0.00001a" )
pico_set_program_url(foo "www.plinth.com/foo" )
请注意,所有这些都作为命令行参数传递给编译,因此如果您计划使用引号、换行符等,您可能会更好地通过代码中的 bi_decl 进行定义。
MicroPython 和 CircuitPython,最终 SDK 和其他可能支持闪存中的一个或多个存储设备。我们已经有了宏来定义这些,尽管 picotool 还没有对它们做任何事情...但是备份/恢复/文件复制,甚至未来的熔断安装可能会很有趣。
我建议我们现在标记这些......
这就是我现在(当时)的想法
#define bi_block_device ( _tag , _name , _offset , _size , _extra , _flags )
数据进入
typedef struct __packed _binary_info_block_device {
struct _binary_info_core core ;
bi_ptr_of ( const char ) name ; // optional static name (independent of what is formatted)
uint32_t offset ;
uint32_t size ;
bi_ptr_of ( binary_info_t ) extra ; // additional info
uint16_t flags ;
} binary_info_block_device_t ;
和
enum {
BINARY_INFO_BLOCK_DEV_FLAG_READ = 1 << 0 , // if not readable, then it is basically hidden, but tools may choose to avoid overwriting it
BINARY_INFO_BLOCK_DEV_FLAG_WRITE = 1 << 1 ,
BINARY_INFO_BLOCK_DEV_FLAG_REFORMAT = 1 << 2 , // may be reformatted..
BINARY_INFO_BLOCK_DEV_FLAG_PT_UNKNOWN = 0 << 4 , // unknown free to look
BINARY_INFO_BLOCK_DEV_FLAG_PT_MBR = 1 << 4 , // expect MBR
BINARY_INFO_BLOCK_DEV_FLAG_PT_GPT = 2 << 4 , // expect GPT
BINARY_INFO_BLOCK_DEV_FLAG_PT_NONE = 3 << 4 , // no partition table
};
使用-f/F
运行命令需要在设备上运行兼容的代码。就使用 pico-sdk 编译的二进制文件而言,兼容代码的定义是:
-f/F
重新启动将不起作用 - 相反,您可以将编译定义PICO_ENTER_USB_BOOT_ON_EXIT
设置为在代码完成执行后重新启动并可访问 picotool,例如使用target_compile_definitions( PRIVATE PICO_ENTER_USB_BOOT_ON_EXIT=1)
stdio_init_all()
并且您的 CMakeLists.txt 文件中有pico_enable_stdio_usb( 1)
那么您就满足此要求(请参阅 hello_usb 示例)如果您在长时间操作中按 ctrl+c,那么 libusb 似乎会有点混乱,这意味着我们无法解锁 USB MSD 写入的锁定(我们已将其关闭,因此用户无法解锁)踩到自己的脚趾)。只需再次运行picotool info
即可在下次正确解锁(或者您可以重新启动设备)。