Você precisa definir PICO_SDK_PATH no ambiente ou passá-lo para cmake com -DPICO_SDK_PATH=/path/to/pico-sdk
. Para usar recursos como assinatura ou hash, você precisará certificar-se de que o submódulo mbedtls no SDK esteja em check-out - isso pode ser feito executando-o no diretório do SDK.
git submodule update --init lib/mbedtls
Você também precisa instalar libusb-1.0
.
Use sua ferramenta de pacote favorita para instalar dependências. Por exemplo, no Ubuntu:
sudo apt install build-essential pkg-config libusb-1.0-0-dev cmake
Em seguida, basta construir como um projeto CMake normal:
mkdir build
cd build
cmake ..
make
No Linux você pode adicionar regras do udev para executar o picotool sem sudo:
sudo cp udev/99-picotool.rules /etc/udev/rules.d/
Baixe libUSB aqui https://libusb.info/
defina a variável de ambiente LIBUSB_ROOT para o diretório de instalação.
mkdir build
cd build
cmake -G "NMake Makefiles" ..
nmake
Baixe libUSB aqui https://libusb.info/
defina a variável de ambiente LIBUSB_ROOT para o diretório de instalação.
mkdir build
cd build
cmake ..
make
Não há necessidade de baixar o libusb separadamente ou definir LIBUSB_ROOT
.
pacman -S $MINGW_PACKAGE_PREFIX-{toolchain,cmake,libusb}
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=$MINGW_PREFIX
cmake --build .
O Raspberry Pi Pico SDK (pico-sdk) versão 2.0.0 e superior usa picotool
para fazer a conversão de ELF para UF2 anteriormente tratada pela ferramenta elf2uf2
no SDK. O SDK também usa picotool
para fazer hash e assinar binários.
Embora o SDK possa baixar o picotool sozinho por projeto, se você tiver vários projetos ou configurações de construção, é preferível instalar uma única cópia do picotool
localmente. Isso pode ser feito simplesmente com make install
ou cmake --install .
; o SDK usará esta versão instalada por padrão.
Como alternativa, você pode instalar em um caminho personalizado por meio de:
cmake -DCMAKE_INSTALL_PREFIX=$MY_INSTALL_DIR -DPICOTOOL_FLAT_INSTALL=1 ..
Para que o SDK encontre picotool
neste caminho personalizado, você precisará definir a variável picotool_DIR
em seu projeto, definindo a variável de ambiente picotool_DIR
, passando -Dpicotool_DIR=$MY_INSTALL_DIR/picotool
ao seu comando cmake
ou adicionando set(picotool_DIR $MY_INSTALL_DIR/picotool)
para seu arquivo CMakeLists.txt.
picotool
é uma ferramenta para trabalhar com binários RP2040/RP2350 e interagir com dispositivos RP2040/RP2350 quando eles estão no modo BOOTSEL. (A partir da versão 1.1 do picotool
também é possível interagir com dispositivos que não estão no modo BOOTSEL, mas que usam suporte USB stdio do Raspberry Pi Pico SDK usando o argumento -f
do picotool
).
Nota para documentação adicional, consulte 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
Observe que os comandos que não atuam em arquivos exigem que um dispositivo no modo BOOTSEL esteja conectado.
Há suporte para informações binárias no SDK que permite armazenar facilmente informações compactas que picotool
pode encontrar (consulte a seção Informações binárias abaixo). O comando info serve para ler essas informações.
As informações podem ser lidas de um ou mais dispositivos conectados no modo BOOTSEL ou de um arquivo. Este arquivo pode ser um arquivo ELF, UF2 ou 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
Observe que os argumentos -f variam ligeiramente para plataformas Windows vs macOS/Unix.
por exemplo
$ picotool info Nome da informação do programa: hello_world features: stdout para 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 Nome da informação do programa: hello_world features: stdout para UART
Informações do pino fixo 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 permite configurar as informações binárias em um dispositivo, se for configurável. Especificamente, você pode configurar bi_ptr_int32
e 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
permite que você grave dados de um arquivo no dispositivo (seja gravando em flash ou em 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
por exemplo
$ picotool load blink.uf2
Loading into Flash: [==============================] 100%
save
permite salvar um intervalo de RAM, o programa em flash ou um intervalo explícito de flash do dispositivo em um arquivo BIN ou 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
por exemplo, primeiro olhando o que está no dispositivo...
$ picotool info
Program Information
name: lcd_1602_i2c
web site: https://github.com/raspberrypi/pico-examples/tree/HEAD/i2c/lcd_1602_i2c
... salvando-o em um arquivo ...
$ picotool save spoon.uf2
Saving file: [==============================] 100%
Wrote 51200 bytes to spoon.uf2
... e olhando o arquivo:
$ 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
permite que você assine e/ou faça hash de um binário para rodar no RP2350.
Por padrão, ele apenas assinará o binário, mas isso pode ser configurado com os argumentos --hash
e --no-sign
.
Sua chave de assinatura deve ser da curva secp256k1 , no formato PEM. Você pode criar um arquivo .PEM com:
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
permite criptografar e assinar um binário para uso no RP2350. Por padrão, ele assinará o binário criptografado, mas isso pode ser configurado de forma semelhante ao picotool sign
.
O binário criptografado terá a seguinte estrutura:
A chave AES deve ser fornecida como um arquivo .bin da chave AES de 256 bits a ser usada para criptografia.
$ 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
Os comandos partition
permitem interagir com as tabelas de partição em dispositivos RP2350 e também criá-las.
$ 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
Este comando permite criar tabelas de partição e incorporá-las adicionalmente no loop de bloco de arquivos ELF (por exemplo, para bootloaders). Por padrão, todas as tabelas de partição têm hash e você também pode assiná-las.
$ 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)
Os comandos uf2
permitem a criação de UF2s e cam fornecem informações quando o download do UF2 falhou.
Este comando substitui a funcionalidade elf2uf2 que estava anteriormente no Raspberry Pi Pico SDK. Ele tentará detectar automaticamente o ID da família, mas se isso falhar, você poderá especificar um manualmente com o argumento --family
.
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)
Este comando lê as informações em um dispositivo sobre o motivo da falha no download do UF2. Ele só fornecerá informações se o download mais recente falhar.
$ 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
Os comandos otp
são para interagir com a memória OTP RP2350. Eles não estão disponíveis em dispositivos RP2040, pois o RP2040 não possui OTP.
Observe que a memória OTP é programável uma vez, o que significa que uma vez que um bit foi alterado de 0 para 1, ele não pode ser alterado novamente. Portanto, deve-se ter cuidado ao usar esses comandos, pois eles correm o risco de bloquear seu dispositivo RP2350. Por exemplo, se você definir SECURE_BOOT_ENABLE, mas não definir uma chave de inicialização e desativar a interface PICOBOOT, seu dispositivo ficará inutilizável.
Para os comandos list
, set
, get
e load
, você pode definir seu próprio layout OTP em um arquivo JSON e passá-lo com o argumento -i
. Essas linhas serão adicionadas às linhas padrão durante a análise.
$ 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)
Esses comandos irão definir/obter linhas específicas de OTP. Por padrão, eles escreverão/lerão todas as linhas redundantes, mas isso pode ser substituído pelo argumento -c
Este comando permite carregar um intervalo de linhas OTP no dispositivo. A fonte pode ser um arquivo binário ou um arquivo JSON, como aquele gerado por picotool sign
. Por exemplo, se desejar assinar um binário e depois testar a inicialização segura com ele, você pode executar o seguinte conjunto de comandos:
$ 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
Este comando permite a etiqueta branca OTP, que define a configuração USB usada pelo dispositivo no modo BOOTSEL. Isso pode ser configurado a partir de um arquivo JSON, cujo exemplo está em 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
...
Este comando executará um binário em seu dispositivo para definir as permissões OTP, pois elas não são diretamente acessíveis a partir picotool
devido às configurações de permissões padrão necessárias para corrigir a errata XXX no RP2350. Como ele executa um binário, o binário precisa ser assinado se a inicialização segura estiver habilitada. O binário imprimirá o que está fazendo no uart, que pode ser configurado usando os argumentos de configuração do UART. Você pode definir suas permissões OTP em um arquivo json, um exemplo disso está em 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.
As informações binárias são localizáveis pela máquina e geralmente consumíveis pela máquina. Digo geralmente porque qualquer pessoa pode incluir qualquer informação, e podemos diferenciá-la das nossas, mas cabe a eles tornar seus dados autodescritivos.
Observe que certamente adicionaremos mais informações binárias ao longo do tempo, mas eu gostaria de ter um conjunto básico mínimo incluído na maioria dos binários desde o lançamento!!
Esta informação é muito útil quando você pega um Pico e não sabe o que tem nele!
As informações básicas incluem
A informação binária é autodescritiva/extensível, portanto os programas podem incluir informações das quais o picotool não tem conhecimento (por exemplo, MicroPython inclui uma lista de bibliotecas integradas)
Isso certamente é útil quando você tem um executável chamado 'hello_world.elf', mas esqueceu para qual placa ele foi criado ...
As atribuições de pinos estáticos (fixos) podem ser registradas no binário de forma muito compacta:
$ 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
Isso é muito útil se você deseja modificar parâmetros em um binário, sem precisar recompilá-lo.
$ picotool config -s name Jane
name = "Billy"
setting name -> "Jane"
As informações binárias são declaradas no programa por macros (macros distorcidas vis); para o exemplo dos pinos:
$ 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
... há uma linha na função 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 ));
Os dois números de pinos e a função UART são armazenados e, em seguida, decodificados em seus nomes de função reais (UART1 TX etc.) por picotool. O bi_decl_if_func_used
garante que as informações binárias sejam incluídas apenas se a função que contém for chamada.
Da mesma forma, o código do vídeo contém algumas linhas como esta:
bi_decl_if_func_used ( bi_pin_mask_with_name ( 0x1f << ( PICO_SCANVIDEO_COLOR_PIN_BASE + PICO_SCANVIDEO_DPI_PIXEL_RSHIFT ), "Red 0-4" ));
Para o exemplo de configuração, você coloca a linha
bi_decl ( bi_ptr_string ( 0x1111 , 0x3333 , name , "Billy" , 128 ));
em seu código, que criará a variável de nome para você imprimir posteriormente. Os parâmetros são a tag, o ID, o nome da variável, o valor padrão e o comprimento máximo da string.
printf ( "Name is %sn" , name );
As coisas são projetadas para desperdiçar o mínimo de espaço possível, mas você pode desligar tudo com a variável do pré-processador PICO_NO_BINARY_INFO=1
. Além disso, qualquer código SDK que insira informações binárias pode ser excluído separadamente por sua própria variável de pré-processador.
Você precisa
#include "pico/binary_info.h"
Basicamente, você usa bi_decl(bi_blah(...))
para inclusão incondicional da informação binária blá, ou bi_decl_if_func_used(bi_blah(...))
para informações binárias que podem ser removidas se a função envolvente não estiver incluída no binário por o vinculador (pense em --gc-sections
)
Há um monte de bi_ macros nos cabeçalhos
#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 ) ...
que fazem uso de macros subjacentes, por exemplo
#define bi_program_url ( url ) bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_PROGRAM_URL, url)
NOTA: É fácil esquecer de incluí-los em bi_decl
etc., então um esforço foi feito (às custas de muitos gatinhos) para fazer a compilação falhar com uma mensagem de erro útil se você fizer isso.
Por exemplo, tentando compilar
bi_1pin_with_name ( 0 , "Toaster activator" );
dá
/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
Você pode usar
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" )
Observe que todos eles são passados como argumentos de linha de comando para a compilação; portanto, se você planeja usar aspas, novas linhas, etc., poderá ter mais sorte definindo via bi_decl no código.
MicroPython e CircuitPython, eventualmente o SDK e outros podem suportar um ou mais dispositivos de armazenamento em flash. Já temos macros para defini-los, embora o picotool ainda não faça nada com eles... mas backup/restauração/cópia de arquivo e até mesmo montagem de fusível no futuro podem ser interessantes.
Sugiro que marquemos estes agora...
Isso é o que tenho agora em mente (na época)
#define bi_block_device ( _tag , _name , _offset , _size , _extra , _flags )
com os dados entrando
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 ;
e
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
};
A execução de comandos com -f/F
requer a execução de código compatível no dispositivo. A definição de código compatível para fins de binários compilados usando o pico-sdk é um código que
-f/F
não funcionará - em vez disso, você pode definir a definição de compilação PICO_ENTER_USB_BOOT_ON_EXIT
para reinicializar e ficar acessível ao picotool assim que seu código terminar a execução, por exemplo, com target_compile_definitions( PRIVATE PICO_ENTER_USB_BOOT_ON_EXIT=1)
stdio_init_all()
e você tem pico_enable_stdio_usb( 1)
em seu arquivo CMakeLists.txt, então você atende a este requisito (veja o exemplo hello_usb) Se você pressionar Ctrl + C no meio de uma operação longa, o libusb parece ficar um pouco confuso, o que significa que não podemos desbloquear nosso bloqueio de gravações USB MSD (nós os desativamos para que o usuário não o faça). pisar nos próprios dedos). Simplesmente executar picotool info
novamente irá desbloqueá-lo corretamente na próxima vez (ou você pode reiniciar o dispositivo).