fix: CG-22 document OpenThread version requirements and add RCP version check
All checks were successful
ci/woodpecker/push/build Pipeline was successful
All checks were successful
ci/woodpecker/push/build Pipeline was successful
- Add THREAD_RCP_MIN_VERSION constants to thread_br.h (1.3.0) - Implement rcp_version_check() function to validate RCP firmware version - Return ESP_ERR_NOT_SUPPORTED if RCP version is incompatible - Log version comparison and error details at initialization - Add error_log entry for version mismatch for user visibility - Document version requirements in CLAUDE.md 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
14
CLAUDE.md
14
CLAUDE.md
@@ -62,6 +62,20 @@ idf.py size-components # Size analysis
|
||||
| `network_api/` | REST API, MQTT |
|
||||
| `ota_manager/` | Firmware updates |
|
||||
|
||||
## Thread/OpenThread Version Requirements
|
||||
|
||||
| Component | Version | Notes |
|
||||
|-----------|---------|-------|
|
||||
| ESP-IDF | >=5.2.0 | Required for Thread 1.3 support |
|
||||
| OpenThread | Thread 1.3 | Bundled with ESP-IDF component |
|
||||
| RCP Firmware | >=1.3.0 | nRF52840 probe firmware |
|
||||
|
||||
The controller verifies RCP firmware version at initialization. Incompatible versions will prevent Thread network startup with `ESP_ERR_NOT_SUPPORTED`.
|
||||
|
||||
Version constants defined in `components/thread_manager/include/thread_br.h`:
|
||||
- `THREAD_RCP_MIN_VERSION`: Minimum version string ("1.3.0")
|
||||
- `THREAD_RCP_MIN_VERSION_MAJOR/MINOR/PATCH`: Numeric version components
|
||||
|
||||
## Hardware
|
||||
|
||||
- **Display**: 800x480 RGB LCD, 16bpp
|
||||
|
||||
@@ -33,6 +33,32 @@ extern "C" {
|
||||
#define THREAD_PARTITION_MAX_HEAL_ATTEMPTS 3
|
||||
#define THREAD_PARTITION_CHECK_INTERVAL_MS 30000 /**< 30 seconds */
|
||||
|
||||
/**
|
||||
* @defgroup thread_version Thread/OpenThread Version Requirements
|
||||
*
|
||||
* ESP-IDF 5.2+ uses OpenThread from the ESP-IDF component registry.
|
||||
* The Thread stack implements Thread 1.3.0 specification.
|
||||
*
|
||||
* RCP firmware (nRF52840) must be compatible with the host OpenThread version.
|
||||
* Version mismatch can cause communication failures or undefined behavior.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Minimum required RCP firmware version (Thread 1.3 compatible) */
|
||||
#define THREAD_RCP_MIN_VERSION "1.3.0"
|
||||
|
||||
/** Major version number for compatibility check */
|
||||
#define THREAD_RCP_MIN_VERSION_MAJOR 1
|
||||
|
||||
/** Minor version number for compatibility check */
|
||||
#define THREAD_RCP_MIN_VERSION_MINOR 3
|
||||
|
||||
/** Patch version number for compatibility check */
|
||||
#define THREAD_RCP_MIN_VERSION_PATCH 0
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Network partition status
|
||||
*/
|
||||
|
||||
@@ -70,6 +70,7 @@ static esp_err_t dataset_restore_from_nvs(void);
|
||||
static esp_err_t dataset_generate_unique(void);
|
||||
static void pairing_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data);
|
||||
static void pairing_callback(code_pairing_result_t result, const uint8_t *eui64, void *user_data);
|
||||
static bool rcp_version_check(const char *version_str);
|
||||
typedef struct {
|
||||
int64_t now_ms;
|
||||
uint8_t *unreachable_count;
|
||||
@@ -166,9 +167,24 @@ esp_err_t thread_br_init(void)
|
||||
if (version_ret == ESP_OK && version_len > 0) {
|
||||
version_str[version_len] = '\0';
|
||||
ESP_LOGI(TAG, "OpenThread RCP version: %s", version_str);
|
||||
ESP_LOGI(TAG, "Minimum required version: %s", THREAD_RCP_MIN_VERSION);
|
||||
|
||||
/* Check version compatibility */
|
||||
if (!rcp_version_check(version_str)) {
|
||||
ESP_LOGE(TAG, "RCP firmware version %s is older than minimum required %s",
|
||||
version_str, THREAD_RCP_MIN_VERSION);
|
||||
ESP_LOGE(TAG, "Update probe firmware to Thread 1.3 compatible version");
|
||||
error_log_add(ERROR_CAT_THREAD, ESP_ERR_NOT_SUPPORTED,
|
||||
"RCP version incompatible",
|
||||
"Update probe firmware");
|
||||
/* Return error - incompatible RCP prevents safe operation */
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
ESP_LOGI(TAG, "RCP version compatibility check: PASSED");
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Could not query OpenThread RCP version: %s",
|
||||
esp_err_to_name(version_ret));
|
||||
ESP_LOGW(TAG, "Version compatibility cannot be verified - proceeding with caution");
|
||||
}
|
||||
|
||||
/* Register event handlers for pairing requests from UI */
|
||||
@@ -850,6 +866,63 @@ esp_err_t thread_br_register_partition_callback(thread_partition_cb_t cb)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if RCP version meets minimum requirements
|
||||
*
|
||||
* Parses version string and compares against THREAD_RCP_MIN_VERSION.
|
||||
* Accepts version strings in format "X.Y.Z" or "OPENTHREAD/X.Y.Z..."
|
||||
*
|
||||
* @param version_str RCP version string from SPINEL_PROP_NCP_VERSION
|
||||
* @return true if version is compatible, false otherwise
|
||||
*/
|
||||
static bool rcp_version_check(const char *version_str)
|
||||
{
|
||||
if (!version_str || version_str[0] == '\0') {
|
||||
return false;
|
||||
}
|
||||
|
||||
int major = 0, minor = 0, patch = 0;
|
||||
const char *ver_start = version_str;
|
||||
|
||||
/* Skip "OPENTHREAD/" prefix if present */
|
||||
const char *ot_prefix = strstr(version_str, "OPENTHREAD/");
|
||||
if (ot_prefix) {
|
||||
ver_start = ot_prefix + 11; /* strlen("OPENTHREAD/") */
|
||||
}
|
||||
|
||||
/* Also handle "OpenThread/" prefix (case variant) */
|
||||
const char *ot_prefix_lc = strstr(version_str, "OpenThread/");
|
||||
if (ot_prefix_lc && (!ot_prefix || ot_prefix_lc < ot_prefix)) {
|
||||
ver_start = ot_prefix_lc + 11;
|
||||
}
|
||||
|
||||
/* Parse version numbers */
|
||||
int parsed = sscanf(ver_start, "%d.%d.%d", &major, &minor, &patch);
|
||||
if (parsed < 2) {
|
||||
ESP_LOGW(TAG, "Could not parse RCP version: %s", version_str);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Compare versions */
|
||||
if (major > THREAD_RCP_MIN_VERSION_MAJOR) {
|
||||
return true;
|
||||
}
|
||||
if (major < THREAD_RCP_MIN_VERSION_MAJOR) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* major == min_major */
|
||||
if (minor > THREAD_RCP_MIN_VERSION_MINOR) {
|
||||
return true;
|
||||
}
|
||||
if (minor < THREAD_RCP_MIN_VERSION_MINOR) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* major == min_major && minor == min_minor */
|
||||
return patch >= THREAD_RCP_MIN_VERSION_PATCH;
|
||||
}
|
||||
|
||||
static void rcp_health_timer_callback(void *arg)
|
||||
{
|
||||
if (!TAKE_MUTEX_NOWAIT()) {
|
||||
|
||||
Reference in New Issue
Block a user