soc: raspberrypi: rpi_pico: Add support RpiPico binary info feature

Binary Info embeds program meta information in flash,
which can be viewed with RaspberryPi Pico's `picotool`.

Metadata is automatically collected from pinctrl.

It can be override by the Kconfig configurations, such as

```
CONFIG_RPI_PICO_BINARY_INFO_OVERRIDE_PROGRAM_NAME="my program name"
```

When this feature is enabled, pinctrl groups are restricted to
consisting of pins with a single rpi_pico function.
In other words, SPI's MISO and MOSI can be in the same group,
but I2C's SDA cannot be included in this group.
This is rarely an issue in normal use,
and can be resolved by dividing them into separate groups.

Signed-off-by: TOKITA Hiroshi <tokita.hiroshi@gmail.com>
This commit is contained in:
TOKITA Hiroshi
2023-02-01 09:04:21 +09:00
committed by Fabio Baltieri
parent e8a35bc567
commit 96b9b0f2df
8 changed files with 1537 additions and 0 deletions

View File

@@ -8,3 +8,16 @@ zephyr_sources(
)
zephyr_sources_ifdef(CONFIG_RPI_PICO_ROM_BOOTLOADER rom_bootloader.c)
zephyr_library_sources_ifdef(CONFIG_RPI_PICO_BINARY_INFO
binary_info.c
binary_info_pins.c
)
zephyr_linker_sources_ifdef(CONFIG_RPI_PICO_BINARY_INFO
ROM_START SORT_KEY 0x0binary_info_header binary_info_header.ld
)
zephyr_linker_sources_ifdef(CONFIG_RPI_PICO_BINARY_INFO
RODATA binary_info.ld
)

View File

@@ -0,0 +1,4 @@
# Copyright (c) 2025 TOKITA Hiroshi
# SPDX-License-Identifier: Apache-2.0
source "soc/raspberrypi/rpi_pico/common/Kconfig.*"

View File

@@ -0,0 +1,177 @@
# Copyright (c) 2024 TOKITA Hiroshi
# SPDX-License-Identifier: Apache-2.0
config RPI_PICO_BINARY_INFO
bool "Generate Raspberry Pi Pico binary info"
default y
help
Binary info is able to embed machine readable information with the binary in flash.
It can be read with picotool (https://github.com/raspberrypi/picotool).
Binary info is generated automatically when this option is enabled,
When this feature is enabled, pinctrl groups are restricted to consisting
of pins with a single rpi_pico function.
In other words, SPI's MISO and MOSI can be in the same group, but I2C's
SDA cannot be included in this group. This is rarely an issue in normal use,
and can be resolved by dividing them into separate groups.
if RPI_PICO_BINARY_INFO
config RPI_PICO_BINARY_INFO_PROGRAM_NAME
bool "Generate program_name in binary info"
default y
if RPI_PICO_BINARY_INFO_PROGRAM_NAME
config RPI_PICO_BINARY_INFO_OVERRIDE_PROGRAM_NAME
string "Override program_name in binary info"
depends on RPI_PICO_BINARY_INFO_PROGRAM_NAME
config RPI_PICO_BINARY_INFO_PROGRAM_NAME_OVERRIDDEN
bool
default RPI_PICO_BINARY_INFO_OVERRIDE_PROGRAM_NAME != ""
depends on RPI_PICO_BINARY_INFO_PROGRAM_NAME
endif
config RPI_PICO_BINARY_INFO_PROGRAM_URL
bool "Generate program_url in binary info"
default y
if RPI_PICO_BINARY_INFO_PROGRAM_URL
config RPI_PICO_BINARY_INFO_OVERRIDE_PROGRAM_URL
string "Override program_url in binary info"
depends on RPI_PICO_BINARY_INFO_PROGRAM_URL
config RPI_PICO_BINARY_INFO_PROGRAM_URL_OVERRIDDEN
bool
default RPI_PICO_BINARY_INFO_OVERRIDE_PROGRAM_URL != ""
depends on RPI_PICO_BINARY_INFO_PROGRAM_URL
endif
config RPI_PICO_BINARY_INFO_PROGRAM_DESCRIPTION
bool "Generate program_description in binary info"
default y
if RPI_PICO_BINARY_INFO_PROGRAM_DESCRIPTION
config RPI_PICO_BINARY_INFO_OVERRIDE_PROGRAM_DESCRIPTION
string "Override program_description in binary info"
depends on RPI_PICO_BINARY_INFO_PROGRAM_DESCRIPTION
config RPI_PICO_BINARY_INFO_PROGRAM_DESCRIPTION_OVERRIDDEN
bool
default RPI_PICO_BINARY_INFO_OVERRIDE_PROGRAM_DESCRIPTION != ""
depends on RPI_PICO_BINARY_INFO_PROGRAM_DESCRIPTION
endif
config RPI_PICO_BINARY_INFO_PROGRAM_BUILD_DATE
bool "Generate program_build_date in binary info"
default y
if RPI_PICO_BINARY_INFO_PROGRAM_BUILD_DATE
config RPI_PICO_BINARY_INFO_OVERRIDE_PROGRAM_BUILD_DATE
string "Override program_build_date in binary info"
depends on RPI_PICO_BINARY_INFO_PROGRAM_BUILD_DATE
config RPI_PICO_BINARY_INFO_PROGRAM_BUILD_DATE_OVERRIDDEN
bool
default RPI_PICO_BINARY_INFO_OVERRIDE_PROGRAM_BUILD_DATE != ""
depends on RPI_PICO_BINARY_INFO_PROGRAM_BUILD_DATE
endif
config RPI_PICO_BINARY_INFO_PROGRAM_VERSION_STRING
bool "Generate program_version_string in binary info"
default y
if RPI_PICO_BINARY_INFO_PROGRAM_VERSION_STRING
config RPI_PICO_BINARY_INFO_OVERRIDE_PROGRAM_VERSION_STRING
string "Override program_version_string in binary info"
depends on RPI_PICO_BINARY_INFO_PROGRAM_VERSION_STRING
config RPI_PICO_BINARY_INFO_PROGRAM_VERSION_STRING_OVERRIDDEN
bool
default RPI_PICO_BINARY_INFO_OVERRIDE_PROGRAM_VERSION_STRING != ""
depends on RPI_PICO_BINARY_INFO_PROGRAM_VERSION_STRING
endif
config RPI_PICO_BINARY_INFO_SDK_VERSION_STRING
bool "Generate sdk_version_string in binary info"
default y
if RPI_PICO_BINARY_INFO_SDK_VERSION_STRING
config RPI_PICO_BINARY_INFO_OVERRIDE_SDK_VERSION_STRING
string "Override sdk_version_string in binary info"
depends on RPI_PICO_BINARY_INFO_SDK_VERSION_STRING
config RPI_PICO_BINARY_INFO_SDK_VERSION_STRING_OVERRIDDEN
bool
default RPI_PICO_BINARY_INFO_OVERRIDE_SDK_VERSION_STRING != ""
depends on RPI_PICO_BINARY_INFO_SDK_VERSION_STRING
endif
config RPI_PICO_BINARY_INFO_PICO_BOARD
bool "Generate pico_board in binary info"
default y
if RPI_PICO_BINARY_INFO_PICO_BOARD
config RPI_PICO_BINARY_INFO_OVERRIDE_PICO_BOARD
string "Override pico_board in binary info"
depends on RPI_PICO_BINARY_INFO_PICO_BOARD
config RPI_PICO_BINARY_INFO_PICO_BOARD_OVERRIDDEN
bool
default RPI_PICO_BINARY_INFO_OVERRIDE_PICO_BOARD != ""
depends on RPI_PICO_BINARY_INFO_PICO_BOARD
endif
config RPI_PICO_BINARY_INFO_ATTRIBUTE_BUILD_TYPE
bool "Generate attribute_build_type in binary info"
default y
if RPI_PICO_BINARY_INFO_ATTRIBUTE_BUILD_TYPE
config RPI_PICO_BINARY_INFO_OVERRIDE_ATTRIBUTE_BUILD_TYPE
string "Override attribute_build_type in binary info"
depends on RPI_PICO_BINARY_INFO_ATTRIBUTE_BUILD_TYPE
config RPI_PICO_BINARY_INFO_ATTRIBUTE_BUILD_TYPE_OVERRIDDEN
bool
default RPI_PICO_BINARY_INFO_OVERRIDE_ATTRIBUTE_BUILD_TYPE != ""
depends on RPI_PICO_BINARY_INFO_ATTRIBUTE_BUILD_TYPE
endif
config RPI_PICO_BINARY_INFO_BOOT_STAGE2_NAME
bool "Generate boot_stage2_name in binary info"
default y
if RPI_PICO_BINARY_INFO_BOOT_STAGE2_NAME
config RPI_PICO_BINARY_INFO_OVERRIDE_BOOT_STAGE2_NAME
string "Override boot_stage2_name in binary info"
depends on RPI_PICO_BINARY_INFO_BOOT_STAGE2_NAME
config RPI_PICO_BINARY_INFO_BOOT_STAGE2_NAME_OVERRIDDEN
bool
default RPI_PICO_BINARY_INFO_OVERRIDE_BOOT_STAGE2_NAME != ""
depends on RPI_PICO_BINARY_INFO_BOOT_STAGE2_NAME
endif
config RPI_PICO_BINARY_INFO_PIN_CONFIGURATIONS
bool "Generate pin configuration info in binary info"
default y
endif

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 2023 TOKITA Hiroshi <tokita.hiroshi@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "binary_info.h"
extern uint32_t __rom_region_end;
bi_decl(bi_binary_end((intptr_t)&__rom_region_end));
#ifdef CONFIG_RPI_PICO_BINARY_INFO_PROGRAM_NAME
bi_decl(bi_program_name((uint32_t)BI_PROGRAM_NAME));
#endif
#if defined(CONFIG_RPI_PICO_BINARY_INFO_PROGRAM_VERSION_STRING)
bi_decl(bi_program_version_string((uint32_t)BI_PROGRAM_VERSION_STRING));
#endif
#ifdef CONFIG_RPI_PICO_BINARY_INFO_PROGRAM_DESCRIPTION
bi_decl(bi_program_description((uint32_t)BI_PROGRAM_DESCRIPTION));
#endif
#ifdef CONFIG_RPI_PICO_BINARY_INFO_PROGRAM_URL
bi_decl(bi_program_url((uint32_t)BI_PROGRAM_URL));
#endif
#ifdef CONFIG_RPI_PICO_BINARY_INFO_PROGRAM_BUILD_DATE
bi_decl(bi_program_build_date_string((uint32_t)BI_PROGRAM_BUILD_DATE));
#endif
#ifdef CONFIG_RPI_PICO_BINARY_INFO_PICO_BOARD
bi_decl(bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_PICO_BOARD,
(uint32_t)BI_PICO_BOARD));
#endif
#ifdef CONFIG_RPI_PICO_BINARY_INFO_SDK_VERSION_STRING
bi_decl(bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_SDK_VERSION,
(uint32_t)BI_SDK_VERSION_STRING));
#endif
#ifdef CONFIG_RPI_PICO_BINARY_INFO_BOOT_STAGE2_NAME
bi_decl(bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_BOOT2_NAME,
(uint32_t)BI_BOOT_STAGE2_NAME));
#endif
#ifdef CONFIG_RPI_PICO_BINARY_INFO_ATTRIBUTE_BUILD_TYPE
#ifdef CONFIG_DEBUG
bi_decl(bi_program_build_attribute((uint32_t)"Debug"));
#else
bi_decl(bi_program_build_attribute((uint32_t)"Release"));
#endif
#endif

View File

@@ -0,0 +1,149 @@
/*
* Copyright (c) 2025 TOKITA Hiroshi <tokita.hiroshi@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_SOC_RASPBERRYPI_RPI_PICO_COMMON_BINARY_INFO_H_
#define ZEPHYR_SOC_RASPBERRYPI_RPI_PICO_COMMON_BINARY_INFO_H_
#include <zephyr/kernel.h>
#include <zephyr/devicetree.h>
#include <zephyr/sys/util_macro.h>
#include <zephyr/dt-bindings/pinctrl/rpi-pico-pinctrl-common.h>
#include <soc.h>
#include <boot_stage2/config.h>
#include <pico/binary_info.h>
#include <version.h>
#ifdef CONFIG_RPI_PICO_BINARY_INFO_PROGRAM_NAME_OVERRIDDEN
#define BI_PROGRAM_NAME CONFIG_RPI_PICO_BINARY_INFO_OVERRIDE_PROGRAM_NAME
#else
#define BI_PROGRAM_NAME ""
#endif
#ifdef CONFIG_RPI_PICO_BINARY_INFO_PROGRAM_DESCRIPTION_OVERRIDDEN
#define BI_PROGRAM_DESCRIPTION CONFIG_RPI_PICO_BINARY_INFO_OVERRIDE_PROGRAM_DESCRIPTION
#else
#define BI_PROGRAM_DESCRIPTION ""
#endif
#ifdef CONFIG_RPI_PICO_BINARY_INFO_PROGRAM_URL_OVERRIDDEN
#define BI_PROGRAM_URL CONFIG_RPI_PICO_BINARY_INFO_OVERRIDE_PROGRAM_URL
#else
#define BI_PROGRAM_URL ""
#endif
#ifdef CONFIG_RPI_PICO_BINARY_INFO_PROGRAM_VERSION_STRING_OVERRIDDEN
#define BI_PROGRAM_VERSION_STRING CONFIG_RPI_PICO_BINARY_INFO_OVERRIDE_PROGRAM_VERSION_STRING
#else
#define BI_PROGRAM_VERSION_STRING STRINGIFY(BUILD_VERSION)
#endif
#ifdef CONFIG_RPI_PICO_BINARY_INFO_PICO_BOARD_OVERRIDDEN
#define BI_PICO_BOARD CONFIG_RPI_PICO_BINARY_INFO_OVERRIDE_PICO_BOARD
#else
#define BI_PICO_BOARD CONFIG_BOARD
#endif
#ifdef CONFIG_RPI_PICO_BINARY_INFO_SDK_VERSION_STRING_OVERRIDDEN
#define BI_SDK_VERSION_STRING CONFIG_RPI_PICO_BINARY_INFO_OVERRIDE_SDK_VERSION_STRING
#else
#define BI_SDK_VERSION_STRING "zephyr-" STRINGIFY(BUILD_VERSION)
#endif
#ifdef CONFIG_RPI_PICO_BINARY_INFO_PROGRAM_BUILD_DATE_OVERRIDDEN
#define BI_PROGRAM_BUILD_DATE CONFIG_RPI_PICO_BINARY_INFO_OVERRIDE_PROGRAM_BUILD_DATE
#else
#define BI_PROGRAM_BUILD_DATE __DATE__
#endif
#ifdef CONFIG_RPI_PICO_BINARY_INFO_BOOT_STAGE2_NAME_OVERRIDDEN
#define BI_BOOT_STAGE2_NAME CONFIG_RPI_PICO_BINARY_INFO_OVERRIDE_BOOT_STAGE2_NAME
#else
#define BI_BOOT_STAGE2_NAME PICO_BOOT_STAGE2_NAME
#endif
/* Utilities for pin encoding calculation */
#ifdef CONFIG_SOC_RP2040
#define MAX_PIN_ENTRIES 4
#define ENCODE_BASE_IDX 1
#define ENCODE_BYTES 5
#define ENCODE_PADDING 2
#define ENCODE_PINS_WITH_FUNC __bi_encoded_pins_with_func
#else
#define MAX_PIN_ENTRIES 6
#define ENCODE_BASE_IDX 1
#define ENCODE_BYTES 8
#define ENCODE_PADDING 0
#define ENCODE_PINS_WITH_FUNC __bi_encoded_pins_64_with_func
#endif
/* Get group-wide pin functions */
#define PIN_FUNC_OFFSET 3
#define PIN_FUNC(n, _, idx) ((DT_PROP_BY_IDX(n, pinmux, idx)) & RP2_ALT_FUNC_MASK)
#define PIN_GROUP_FUNC(n) (DT_FOREACH_PROP_ELEM_SEP(n, pinmux, PIN_FUNC, (|)))
#define PIN_GROUP_HEADER(n) (BI_PINS_ENCODING_MULTI | (PIN_GROUP_FUNC(n) << PIN_FUNC_OFFSET))
/* Encode the pins in a group */
#define PINMUX_COUNT(n) COND_CODE_1(DT_NODE_HAS_PROP(n, pinmux), (DT_PROP_LEN(n, pinmux)), (0))
#define PIN_NUM(n, idx) (((DT_PROP_BY_IDX(n, pinmux, idx)) >> RP2_PIN_NUM_POS) & RP2_PIN_NUM_MASK)
#define ENCODE_OFFSET(idx) (((idx + ENCODE_BASE_IDX) * ENCODE_BYTES) + ENCODE_PADDING)
#define ENCODE_PIN(n, idx) ((uint64_t)PIN_NUM(n, idx) << ENCODE_OFFSET(idx))
#define ENCODE_TERMINATE(n, i, end) ((((i) + 1) == (end)) ? ENCODE_PIN(n, i + 1) : 0)
#define ENCODE_EACH_PIN(n, p, i, end) \
(DT_PROP_HAS_IDX(n, p, i) ? ENCODE_PIN(n, i) : 0) | ENCODE_TERMINATE(n, i, end)
#define ENCODE_PIN_GROUP(n) \
DT_FOREACH_PROP_ELEM_SEP_VARGS(n, pinmux, ENCODE_EACH_PIN, (|), PINMUX_COUNT(n))
/*
* Macro for checking pin settings
* Checks that a group consists of a single pin-function.
*/
#define PIN_FUNC_IS(n, p, i, func) (PIN_FUNC(n, p, i) == func)
#define ALL_PINS_FUNC_IS_SAME(n) \
(DT_FOREACH_PROP_ELEM_SEP_VARGS(n, pinmux, PIN_FUNC_IS, (&&), PIN_GROUP_FUNC(n)))
/*
* Create binary info for pin-cfg group.
*/
#define DECLARE_PINCFG_GROUP(n) \
BUILD_ASSERT(PINMUX_COUNT(n) > 0, "Group must contain at least one pin"); \
BUILD_ASSERT(PINMUX_COUNT(n) <= MAX_PIN_ENTRIES, "Too many pins in group"); \
BUILD_ASSERT(ALL_PINS_FUNC_IS_SAME(n), "Group pins must share identical function"); \
bi_decl(ENCODE_PINS_WITH_FUNC(PIN_GROUP_HEADER(n) | ENCODE_PIN_GROUP(n)))
/*
* Scan pin-cfg and the groups it contains.
* Each enumerates its child elements, but since the same macro cannot be used within nesting,
* DT_FOREACH_CHILD_VARGS and DT_FOREACH_CHILD_SEP_VARGS are used accordingly.
*/
#define PINMUX_NUM_IF_MATCH_GROUP(node, g_idx) \
COND_CODE_1(IS_EQ(DT_NODE_CHILD_IDX(node), g_idx), (DT_PROP_LEN(node, pinmux)), ())
#define PINMUX_NUM_IF_MATCH_PINCFG(node, pcfg_idx, g_idx) \
COND_CODE_1(IS_EQ(DT_NODE_CHILD_IDX(node), pcfg_idx), \
(DT_FOREACH_CHILD_SEP_VARGS(node, PINMUX_NUM_IF_MATCH_GROUP, (), g_idx)), ())
#define PINMUX_NUM_OF_PINCFG_GROUP(node, pcfg_idx, g_idx) \
DT_FOREACH_CHILD_VARGS(node, PINMUX_NUM_IF_MATCH_PINCFG, pcfg_idx, g_idx)
#define BINARY_INFO_IF_MATCH_GROUP(node, g_idx) \
COND_CODE_1(IS_EQ(DT_NODE_CHILD_IDX(node), g_idx), (DECLARE_PINCFG_GROUP(node)), ())
#define BINARY_INFO_IF_MATCH_PINCFG(node, pcfg_idx, g_idx) \
COND_CODE_1(IS_EQ(DT_NODE_CHILD_IDX(node), pcfg_idx), \
(DT_FOREACH_CHILD_SEP_VARGS(node, BINARY_INFO_IF_MATCH_GROUP, (), g_idx)), ())
#define BINARY_INFO_FROM_PINCFG_GROUP(node, pcfg_idx, g_idx) \
COND_CODE_1(IS_EMPTY(PINMUX_NUM_OF_PINCFG_GROUP(node, pcfg_idx, g_idx)), (), \
(DT_FOREACH_CHILD_VARGS(node, BINARY_INFO_IF_MATCH_PINCFG, pcfg_idx, g_idx)))
#endif /* ZEPHYR_SOC_RASPBERRYPI_RPI_PICO_COMMON_BINARY_INFO_H_ */

View File

@@ -0,0 +1,11 @@
/*
* Copyright (c) 2023 TOKITA Hiroshi <tokita.hiroshi@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
. = ALIGN(4);
__binary_info_start = .;
KEEP(*(.binary_info.keep.*))
*(.binary_info.*)
__binary_info_end = .;

View File

@@ -0,0 +1,21 @@
/*
* Copyright (c) 2023 TOKITA Hiroshi <tokita.hiroshi@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <pico/binary_info/defs.h>
PROVIDE(binary_info_header = .);
LONG(BINARY_INFO_MARKER_START);
LONG(__binary_info_start);
LONG(__binary_info_end);
LONG(data_cpy_table);
LONG(BINARY_INFO_MARKER_END);
PROVIDE(__binary_info_data_cpy_table_default = .);
PROVIDE(data_cpy_table = __binary_info_data_cpy_table_default);
. = __binary_info_data_cpy_table_default;
LONG(0); /* sentinel */

File diff suppressed because it is too large Load Diff