Add pico_unique_id library to host platform (#2751)

Fixes #2750
This commit is contained in:
Richard Hulme 2026-01-05 17:43:51 +00:00 committed by GitHub
parent 9d1b3c691d
commit 6665319aad
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 180 additions and 0 deletions

View file

@ -96,6 +96,7 @@ cc_library(
"//src/host/hardware_sync:__pkg__",
"//src/host/hardware_timer:__pkg__",
"//src/host/pico_platform:__pkg__",
"//src/host/pico_unique_id:__pkg__",
"//src/rp2040/boot_stage2:__pkg__",
"//src/rp2040/pico_platform:__pkg__",
"//src/rp2350/boot_stage2:__pkg__",

View file

@ -38,6 +38,7 @@ include (${CMAKE_DIR}/no_hardware.cmake)
pico_add_subdirectory(${HOST_DIR}/pico_stdio)
pico_add_subdirectory(${HOST_DIR}/pico_stdlib)
pico_add_subdirectory(${HOST_DIR}/pico_time_adapter)
pico_add_subdirectory(${HOST_DIR}/pico_unique_id)
unset(CMAKE_DIR)
unset(COMMON_DIR)

View file

@ -0,0 +1,13 @@
package(default_visibility = ["//visibility:public"])
cc_library(
name = "pico_unique_id",
srcs = ["unique_id.c"],
hdrs = ["include/pico/unique_id.h"],
includes = ["include"],
target_compatible_with = ["//bazel/constraint:host"],
deps = [
"//src/common/pico_base_headers",
"//src/host/pico_platform",
],
)

View file

@ -0,0 +1,8 @@
pico_add_library(pico_unique_id)
target_sources(pico_unique_id INTERFACE
${CMAKE_CURRENT_LIST_DIR}/unique_id.c
)
target_include_directories(pico_unique_id_headers SYSTEM INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
target_link_libraries(pico_unique_id_headers INTERFACE pico_base_headers)

View file

@ -0,0 +1,127 @@
/*
* Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _PICO_UNIQUE_ID_H
#define _PICO_UNIQUE_ID_H
#include "pico.h"
#ifdef __cplusplus
extern "C" {
#endif
/** \file pico/unique_id.h
* \defgroup pico_unique_id pico_unique_id
*
* \brief Unique device ID access API
*
* \if rp2040_specific
* RP2040 does not have an on-board unique identifier (all instances of RP2040
* silicon are identical and have no persistent state). However, RP2040 boots
* from serial NOR flash devices which have at least a 64-bit unique ID as a standard
* feature, and there is a 1:1 association between RP2040 and flash, so this
* is suitable for use as a unique identifier for an RP2040-based board.
*
* This library injects a call to the flash_get_unique_id function from the
* hardware_flash library, to run before main, and stores the result in a
* static location which can safely be accessed at any time via
* pico_get_unique_id().
*
* This avoids some pitfalls of the hardware_flash API, which requires any
* flash-resident interrupt routines to be disabled when called into.
* \endif
*
* \if rp2350_specific
* On boards using RP2350, the unique identifier is read from OTP memory on boot.
* \endif
*
* \if host_specific
* Host builds will return a fixed identifier starting with 0xA0 and incrementing
* by one for a total of PICO_UNIQUE_BOARD_ID_SIZE_BYTES bytes.
* The sequence can be changed by defining a project-specific version of
* pico_get_unique_board_id.
* \endif
*/
#define PICO_UNIQUE_BOARD_ID_SIZE_BYTES 8
/**
* \brief Unique board identifier
* \ingroup pico_unique_id
*
* This structure contains an array of PICO_UNIQUE_BOARD_ID_SIZE_BYTES identifier bytes suitable for
* holding the unique identifier for the device.
*
* \if rp2040_specific
* On an RP2040-based board, the unique identifier is retrieved from the external NOR flash device at boot,
* or for PICO_NO_FLASH builds the unique identifier is set to all 0xEE.
* \endif
*
* \if rp2350_specific
* On an RP2350-based board, the unique identifier is retrieved from OTP memory at boot.
* \endif
*
* \if host_specific
* The unique identifier is generated in pico_get_unique_board_id.
* \endif
*/
typedef struct {
uint8_t id[PICO_UNIQUE_BOARD_ID_SIZE_BYTES];
} pico_unique_board_id_t;
/*! \brief Get unique ID
* \ingroup pico_unique_id
*
* Get the unique 64-bit device identifier.
*
* \if rp2040_specific
* On an RP2040-based board, the unique identifier is retrieved from the external NOR flash device at boot,
* or for PICO_NO_FLASH builds the unique identifier is set to all 0xEE.
* \endif
*
* \if rp2350_specific
* On an RP2350-based board, the unique identifier is retrieved from OTP memory at boot.
* \endif
*
* \if host_specific
* Host builds set the unique identifier to a sequence starting with 0xA0 and incrementing by one for each byte.
* Replace this function with a project-specific version if a different identifier is required.
* \endif
*
* \param id_out a pointer to a pico_unique_board_id_t struct, to which the identifier will be written
*/
void pico_get_unique_board_id(pico_unique_board_id_t *id_out);
/*! \brief Get unique ID in string format
* \ingroup pico_unique_id
*
* Get the unique 64-bit device identifier formatted as a 0-terminated ASCII hex string.
*
* \if rp2040_specific
* On an RP2040-based board, the unique identifier is retrieved from the external NOR flash device at boot,
* or for PICO_NO_FLASH builds the unique identifier is set to all 0xEE.
* \endif
*
* \if rp2350_specific
* On an RP2350-based board, the unique identifier is retrieved from OTP memory at boot.
* \endif
*
* \if host_specific
* Host builds return a sequence starting with 0xA0 and incrementing by one for each byte.
* Replace pico_get_unique_board_id with a project-specific version if a different identifer is required.
* \endif
*
* \param id_out a pointer to a char buffer of size len, to which the identifier will be written
* \param len the size of id_out. For full serial, len >= 2 * PICO_UNIQUE_BOARD_ID_SIZE_BYTES + 1
*/
void pico_get_unique_board_id_string(char *id_out, uint len);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,30 @@
/*
* Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "pico/unique_id.h"
PICO_WEAK_FUNCTION_DEF(pico_get_unique_board_id)
void PICO_WEAK_FUNCTION_IMPL_NAME(pico_get_unique_board_id)(pico_unique_board_id_t *id_out) {
for (int i = 0; i < PICO_UNIQUE_BOARD_ID_SIZE_BYTES; i++) {
id_out->id[i] = 0xa0 + i;
}
}
PICO_WEAK_FUNCTION_DEF(pico_get_unique_board_id_string)
void PICO_WEAK_FUNCTION_IMPL_NAME(pico_get_unique_board_id_string)(char *id_out, uint len) {
assert(len > 0);
size_t i;
pico_unique_board_id_t id;
pico_get_unique_board_id(&id);
// Generate hex one nibble at a time
for (i = 0; (i < len - 1) && (i < PICO_UNIQUE_BOARD_ID_SIZE_BYTES * 2); i++) {
int nibble = (id.id[i/2] >> (4 - 4 * (i&1))) & 0xf;
id_out[i] = (char)(nibble < 10 ? nibble + '0' : nibble + 'A' - 10);
}
id_out[i] = 0;
}