picotool

repository·master·Indexed 21 days ago

https://github.com/raspberrypi/picotool

A command-line utility for interacting with Raspberry Pi RP2040 and RP2350 series devices. It is primarily used for managing binaries and interacting with devices in BOOTSEL mode, with capabilities for loading, saving, verifying, and erasing flash memory, as well as managing RP2350 OTP memory, partition tables, and binary signing via the seal command.

Tokens
27.4K
Snippets
95
Records
134
Agent score
75%

What's inside picotool

  1. Overview of picotool

    master

    picotool is a utility for interacting with RP2040 and RP2350 devices. It is primarily used to work with binaries and interact with devices when they are in BOOTSEL mode.

    Starting from version 1.1, you can also interact with devices that are not in BOOTSEL mode by using the -f (or --force) argument, provided the device is running code that supports USB stdio from the Raspberry Pi Pico SDK.

  2. What is ooFatFs and how does it differ from FatFs?

    master

    ooFatFs is an object-oriented modification of the FatFs Generic FAT File System Module by ChaN.

    In the standard FatFs, functions often rely on global state. In ooFatFs, all functions are modified to take a pointer to the filesystem state as their first argument (or indirectly via a file or directory structure).

    This architectural change provides two primary benefits:

    1. Multiple Filesystems: You can create multiple, independent FAT filesystems within a single application.
    2. Composition: It allows you to combine this driver with other filesystem types more easily.
  3. Interact with embedded block devices using `bdev` commands

    master

    The bdev command group is used to interact with block devices in Flash. You can target a block device by using binary info or by specifying a specific partition. These commands support both littlefs and fatfs filesystems.

    Available subcommands:

    • ls: List contents of the block device.
    • mkdir: Create a directory on the block device.
    • cp: Copy files to or from the block device. Use the :filename syntax to refer to files on the device (e.g., :main.py).
    • rm: Delete a file or an empty directory on the block device.
    • cat: Print the contents of a file on the block device.
    • format: Format the block device (warning: may result in data loss).
    picotool bdev ls
  4. Interacting with RP2350 OTP Memory

    master

    The otp commands allow interaction with the One-Time-Programmable (OTP) memory on RP2350 devices.

    WARNING: OTP is One-Time-Programmable. Once a bit is changed from 0 to 1, it cannot be changed back. Incorrect use of these commands (e.g., enabling secure boot without a boot key or disabling the PICOBOOT interface) can brick your RP2350 device.

    Note: These commands are not available on RP2040 devices as they lack OTP memory.

  5. Select OTP rows and fields

    master

    When using get, set, load, or list commands, you can target specific parts of the OTP using a selector.

    Row Selectors:

    • ROW_NAME: Select a whole row by its name.
    • ROW_NUMBER: Select a whole row by its number.
    • PAGE:PAGE_ROW_NUMBER: Select a whole row by its page and its number within that page.

    Field/Bit Selectors (using a ROW_SEL from above):

    • ROW_SEL.FIELD_NAME: Select a specific field within a row by name.
    • ROW_SEL.n-m: Select a range of bits within a row.
    • ROW_SEL.n: Select a single bit within a row.
    • .FIELD_NAME: Select any row's field by name.

    Multi-selection:

    • Use * or a blank for PAGE or PAGE_ROW_NUMBER to select multiple rows.
  6. Include binary information in your C program

    master

    To make your program's metadata (like name, version, or pin maps) discoverable by picotool, you must include the binary info header and use specific macros.

    Key Concepts:

    • #include "pico/binary_info.h" is required.
    • Use bi_decl(...) for unconditional inclusion.
    • Use bi_decl_if_func_used(...) to ensure information is only included if the containing function is actually used in the binary (allowing the linker to strip it if unused).

    Common Macros:

    • bi_program_name(name)
    • bi_program_description(description)
    • bi_program_version_string(version_string)
    • bi_1pin_with_func(p0, func), bi_2pins_with_func(p0, p1, func), etc.
    • bi_pin_mask_with_name(pmask, label)
    • bi_decl(bi_ptr_string(tag, id, var_name, default_val, max_len)) for configurable strings.
    # Example: Declaring a configurable string named 'name'
    bi_decl(bi_ptr_string(0x1111, 0x3333, name, "Billy", 128));
    
    // Usage in code
    printf("Name is %s\n", name);
  7. Set program metadata via CMake

    master

    Instead of using C macros, you can set basic program information directly in your CMakeLists.txt using the following functions. These are passed as command-line arguments during compilation.

    pico_set_program_name(foo "not foo")
    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")
  8. Load OTP rows from a file

    master

    Use picotool otp load to load a range of OTP rows from a file (binary or JSON) and verify them.

    • Binary files: Data is 4 bytes/row (MSB is ignored).
    • ECC files: Data is 2 bytes/row.

    Example Workflow (Secure Boot Test):

    # 1. Sign the ELF and generate an otp.json
    picotool seal --sign hello_world.elf hello_world.signed.elf private.pem otp.json
    # 2. Load the signed binary
    picotool load hello_world.signed.elf
    # 3. Load the OTP configuration
    picotool otp load otp.json
    # 4. Reboot
    picotool reboot
    picotool otp load [-r] [-e] [-s <row>] [-i <filename>] <filename> [-t <type>] [device-selection]
  9. Install WinUSB driver for RP2040 on Windows using Zadig

    master

    To communicate with an RP2040 in BOOTSEL mode on Windows, you must install the WinUSB driver using Zadig:

    1. Download and run Zadig.
    2. Select RP2 Boot (Interface 1) from the dropdown menu.
    3. Select WinUSB as the target driver.
    4. Click Install Driver.

    Note: This is only required for RP2040 devices.