mirror of
https://github.com/vicliu624/trail-mate.git
synced 2026-08-28 05:24:08 +00:00
1485 lines
33 KiB
Markdown
1485 lines
33 KiB
Markdown
# 2026-06-09 C6 Phase Override
|
||
|
||
This section supersedes the older staged plan below for the current development
|
||
slice.
|
||
|
||
The current target is no longer "HostLink bring-up first, then decide whether
|
||
to build the C6 firmware". The current target is:
|
||
|
||
```text
|
||
1. Build the Trail-Mate ESP32-C6 companion firmware as the first full wireless
|
||
facade firmware.
|
||
2. Flash the C6 externally through its UART ROM bootloader path.
|
||
3. Boot the ESP32-P4 application normally.
|
||
4. Verify that P4 and C6 complete HostLink over SDIO.
|
||
5. Verify BLE, ESP-NOW, Wi-Fi management, and diagnostics as wireless surfaces.
|
||
```
|
||
|
||
External first flash is the validation route for this slice. Runtime slave OTA
|
||
and P4-forced recovery remain future capabilities and must not be treated as
|
||
available product behavior in this phase.
|
||
|
||
Current full-function C6 firmware means:
|
||
|
||
```text
|
||
Implemented on C6:
|
||
- HostLink HELLO / PING / CONFIG_SET / diagnostics routing over SDIO.
|
||
- BLE GAP/GATT facade for Meshtastic, MeshCore/NUS, and Trail-Mate private.
|
||
- BLE pairing/passkey enforcement as wireless access control only; PIN policy
|
||
still comes from P4 and C6 must not persist it as product identity.
|
||
- ESP-NOW raw Team transport send/receive facade.
|
||
- Wi-Fi management facade: scan, STA connect/disconnect/get IP, AP start/stop.
|
||
- C6 diagnostics and service state reports.
|
||
|
||
Still owned by P4:
|
||
- LoRa, MeshCore meaning, Meshtastic meaning, Team state, keys, NodeDB,
|
||
messages, GPS/maps/UI/storage, and all product configuration authority.
|
||
|
||
Not claimed in this slice:
|
||
- C6 runtime OTA.
|
||
- P4 forcing C6 into ROM bootloader.
|
||
- C6-side MeshCore/Meshtastic parsing.
|
||
- Wi-Fi data server or general TCP/UDP business bridge.
|
||
```
|
||
|
||
The C6 partition table uses a 4MB flash assumption with a single 3MB factory
|
||
app partition. This is intentional for the full wireless facade firmware. The
|
||
first validation firmware is flashed externally, so no OTA partitions are
|
||
reserved in this phase.
|
||
|
||
The external flash path requires a 3.3V USB-UART connection to C6 UART0 plus
|
||
the board's C6 BOOT/EN controls. A Qwiic-shaped connector that exposes
|
||
`3V3`, `C6_U0TXD`, `C6_U0RXD`, and `GND` is not a normal I2C Qwiic cable; it
|
||
needs a USB-UART adapter wired for UART, with GPIO9/BOOT held low during reset
|
||
to enter the ESP32-C6 ROM bootloader.
|
||
|
||
# Trail-Mate T-Display-P4 / ESP32-C6 Companion 固件开发方案
|
||
|
||
## 0. 总目标
|
||
|
||
为 Trail-Mate 的 T-Display-P4 目标开发一套自研 ESP32-C6 companion 固件,使 ESP32-C6 不再只是板厂无线固件,而是 Trail-Mate 的近场无线协处理器。
|
||
|
||
最终系统分工如下:
|
||
|
||
```text
|
||
ESP32-P4:
|
||
- Trail-Mate 主业务唯一真相源
|
||
- UI / 地图 / GPS / 存储 / LoRa / MeshCore / Meshtastic / Team Mode
|
||
- 管理所有业务配置、节点状态、频道、队伍、消息、密钥
|
||
- 通过 HostLink 控制 ESP32-C6
|
||
|
||
ESP32-C6:
|
||
- Wi-Fi / BLE / ESP-NOW / 近场无线入口
|
||
- BLE GATT Server
|
||
- ESP-NOW discovery / pairing transport
|
||
- P4-C6 数据桥
|
||
- 不拥有 Trail-Mate 主业务状态
|
||
```
|
||
|
||
核心原则:
|
||
|
||
```text
|
||
P4 owns meaning.
|
||
C6 owns wireless surfaces.
|
||
```
|
||
|
||
也就是:
|
||
|
||
```text
|
||
P4 负责“这条数据是什么意思”
|
||
C6 负责“这条数据通过 BLE / ESP-NOW / Wi-Fi 如何进出设备”
|
||
```
|
||
|
||
不得把 MeshCore、Meshtastic、Team Mode 的核心状态机搬到 C6。
|
||
|
||
---
|
||
|
||
## 1. 明确不做什么
|
||
|
||
C6 固件不得实现以下内容:
|
||
|
||
```text
|
||
1. 不管理 LoRa。
|
||
2. 不驱动 SX1262。
|
||
3. 不管理地图。
|
||
4. 不管理 GPS。
|
||
5. 不管理 NodeDB。
|
||
6. 不管理 MeshCore routing。
|
||
7. 不管理 Meshtastic routing。
|
||
8. 不管理 Channel / PSK / LoRa region。
|
||
9. 不管理 Team Mode 的最终队伍状态。
|
||
10. 不保存 Trail-Mate 主业务密钥。
|
||
11. 不作为第二套 Trail-Mate 业务系统。
|
||
```
|
||
|
||
C6 可以保存的状态只包括:
|
||
|
||
```text
|
||
1. BLE bond 信息。
|
||
2. C6 自身 NVS 配置,例如日志等级、调试开关。
|
||
3. 最近一次 P4 下发的无线 facade runtime config。
|
||
4. ESP-NOW 运行时 peer cache。
|
||
5. HostLink 会话状态。
|
||
```
|
||
|
||
C6 不允许保存的状态:
|
||
|
||
```text
|
||
1. Meshtastic channel key。
|
||
2. MeshCore private key。
|
||
3. Team key。
|
||
4. Trail-Mate 用户身份主密钥。
|
||
5. NodeDB。
|
||
6. 消息历史。
|
||
7. 地图缓存。
|
||
8. LoRa 配置的权威副本。
|
||
```
|
||
|
||
如果 BLE 或 ESP-NOW 需要使用某些临时密钥,必须由 P4 下发,C6 只在 RAM 中保存;除非 P4 明确发送 `ALLOW_PERSIST` 标志,否则 C6 不得写入 NVS。
|
||
|
||
---
|
||
|
||
## 2. 工程目录建议
|
||
|
||
在 Trail-Mate 仓库内新增 C6 companion 工程,而不是新建完全独立仓库。原因是 P4-C6 协议必须和 P4 固件同步演进。
|
||
|
||
推荐目录:
|
||
|
||
```text
|
||
trail-mate/
|
||
firmware/
|
||
c6_companion/
|
||
CMakeLists.txt
|
||
sdkconfig.defaults
|
||
partitions.csv
|
||
main/
|
||
app_main.c
|
||
tm_c6_config.h
|
||
tm_c6_tasks.c
|
||
components/
|
||
tm_hostlink/
|
||
include/tm_hostlink.h
|
||
tm_hostlink.c
|
||
tm_hostlink_frame.c
|
||
tm_hostlink_crc.c
|
||
tm_hostlink_sdio.c
|
||
tm_hostlink_uart_debug.c
|
||
tm_ble/
|
||
include/tm_ble.h
|
||
tm_ble.c
|
||
tm_ble_gap.c
|
||
tm_ble_gatt.c
|
||
tm_ble_profiles.c
|
||
tm_ble_meshtastic.c
|
||
tm_ble_meshcore.c
|
||
tm_ble_trailmate.c
|
||
tm_espnow/
|
||
include/tm_espnow.h
|
||
tm_espnow.c
|
||
tm_espnow_discovery.c
|
||
tm_espnow_pairing.c
|
||
tm_wifi/
|
||
include/tm_wifi.h
|
||
tm_wifi.c
|
||
tm_diag/
|
||
include/tm_diag.h
|
||
tm_diag.c
|
||
tm_proto/
|
||
include/tm_c6_proto.h
|
||
tm_c6_proto.c
|
||
src/
|
||
idf/
|
||
wireless_companion/
|
||
WirelessCompanion.hpp
|
||
C6Companion.hpp
|
||
C6Companion.cpp
|
||
C6HostLink.hpp
|
||
C6HostLink.cpp
|
||
C6Frame.hpp
|
||
C6Frame.cpp
|
||
C6BleBridge.hpp
|
||
C6BleBridge.cpp
|
||
C6EspNowBridge.hpp
|
||
C6EspNowBridge.cpp
|
||
C6WifiBridge.hpp
|
||
C6WifiBridge.cpp
|
||
```
|
||
|
||
如果现有工程中没有 `firmware/` 目录,可以使用:
|
||
|
||
```text
|
||
companion/esp32c6/
|
||
```
|
||
|
||
但无论使用哪个路径,P4 和 C6 必须共享同一份协议头文件生成源,避免协议漂移。
|
||
|
||
推荐共享协议源:
|
||
|
||
```text
|
||
shared/c6_link/tm_c6_protocol.yaml
|
||
shared/c6_link/generated/c/tm_c6_protocol.h
|
||
shared/c6_link/generated/cpp/TmC6Protocol.hpp
|
||
tools/gen_c6_protocol.py
|
||
```
|
||
|
||
协议头文件不要手写两份。
|
||
|
||
---
|
||
|
||
## 3. 构建系统
|
||
|
||
C6 companion 使用 ESP-IDF,不使用 Arduino。
|
||
|
||
新增构建命令:
|
||
|
||
```bash
|
||
idf.py -B build.c6_companion -C firmware/c6_companion set-target esp32c6
|
||
idf.py -B build.c6_companion -C firmware/c6_companion build
|
||
idf.py -B build.c6_companion -C firmware/c6_companion -p COMx flash
|
||
idf.py -B build.c6_companion -C firmware/c6_companion -p COMx monitor
|
||
```
|
||
|
||
Windows PowerShell 推荐增加脚本:
|
||
|
||
```text
|
||
tools/vscode/run_c6_task.ps1
|
||
```
|
||
|
||
参数:
|
||
|
||
```text
|
||
-Action build | flash | monitor | erase | menuconfig
|
||
-Port COMx
|
||
```
|
||
|
||
不要把 C6 flash 动作混进 P4 flash 动作中。P4 和 C6 必须可以分别构建、分别刷写、分别监控。
|
||
|
||
新增 VS Code task:
|
||
|
||
```text
|
||
C6 Companion: Reconfigure
|
||
C6 Companion: Build
|
||
C6 Companion: Flash
|
||
C6 Companion: Monitor
|
||
```
|
||
|
||
---
|
||
|
||
## 4. C6 固件总体模块
|
||
|
||
C6 固件由五个模块组成:
|
||
|
||
```text
|
||
tm_hostlink:
|
||
P4-C6 通信层
|
||
|
||
tm_ble:
|
||
BLE GAP / GATT / profile facade
|
||
|
||
tm_espnow:
|
||
ESP-NOW 发现、配对、短消息入口
|
||
|
||
tm_wifi:
|
||
Wi-Fi station / AP / provisioning / diagnostic
|
||
|
||
tm_diag:
|
||
日志、版本、运行状态、heap、任务状态、错误码
|
||
```
|
||
|
||
主任务拓扑:
|
||
|
||
```text
|
||
app_main
|
||
├─ init_nvs()
|
||
├─ init_event_loop()
|
||
├─ init_hostlink()
|
||
├─ wait_for_p4_hello()
|
||
├─ apply_runtime_config_from_p4()
|
||
├─ start_ble_if_enabled()
|
||
├─ start_espnow_if_enabled()
|
||
├─ start_wifi_if_enabled()
|
||
└─ start_diag_task()
|
||
```
|
||
|
||
所有 BLE / ESP-NOW / Wi-Fi 的 enable 状态默认关闭。C6 启动后必须等待 P4 下发配置。C6 不得在没有 P4 配置的情况下主动开启 Trail-Mate 业务广播。
|
||
|
||
唯一例外是调试模式:
|
||
|
||
```text
|
||
CONFIG_TM_C6_STANDALONE_DEBUG=y
|
||
```
|
||
|
||
该模式只允许用于开发板 bring-up,不允许作为 release 默认配置。
|
||
|
||
---
|
||
|
||
## 5. P4-C6 HostLink 协议
|
||
|
||
### 5.1 传输层
|
||
|
||
正式目标传输层:
|
||
|
||
```text
|
||
SDIO
|
||
```
|
||
|
||
原因:
|
||
|
||
```text
|
||
T-Display-P4 板级资料中 P4-C6 通信协议为 SDIO。
|
||
```
|
||
|
||
开发期间可以保留 UART debug transport,但必须满足以下条件:
|
||
|
||
```text
|
||
1. UART debug transport 只用于本地调试。
|
||
2. 默认 release 不启用。
|
||
3. 不能把 UART debug transport 写死成正式协议。
|
||
4. 所有上层模块只能依赖 tm_hostlink,不得直接依赖 SDIO 或 UART。
|
||
```
|
||
|
||
HostLink 传输接口:
|
||
|
||
```c
|
||
typedef struct {
|
||
esp_err_t (*init)(void);
|
||
esp_err_t (*send)(const uint8_t *data, size_t len, uint32_t timeout_ms);
|
||
esp_err_t (*recv)(uint8_t *data, size_t max_len, size_t *out_len, uint32_t timeout_ms);
|
||
esp_err_t (*reset)(void);
|
||
} tm_hostlink_transport_t;
|
||
```
|
||
|
||
P4 侧也必须有等价接口:
|
||
|
||
```cpp
|
||
class C6Transport {
|
||
public:
|
||
virtual bool begin() = 0;
|
||
virtual bool send(const uint8_t* data, size_t len, uint32_t timeoutMs) = 0;
|
||
virtual bool recv(uint8_t* data, size_t maxLen, size_t& outLen, uint32_t timeoutMs) = 0;
|
||
virtual void reset() = 0;
|
||
virtual ~C6Transport() = default;
|
||
};
|
||
```
|
||
|
||
### 5.2 帧格式
|
||
|
||
所有 P4-C6 消息都使用统一二进制帧。
|
||
|
||
帧头固定小端序:
|
||
|
||
```c
|
||
#define TM_C6_MAGIC 0x36434D54u // ASCII little-endian: "TMC6"
|
||
#define TM_C6_PROTO_VERSION 1
|
||
|
||
typedef struct __attribute__((packed)) {
|
||
uint32_t magic;
|
||
uint8_t version;
|
||
uint8_t header_len;
|
||
uint8_t frame_type;
|
||
uint8_t channel;
|
||
uint16_t flags;
|
||
uint16_t seq;
|
||
uint16_t ack;
|
||
uint16_t payload_len;
|
||
uint32_t crc32;
|
||
} tm_c6_frame_header_t;
|
||
```
|
||
|
||
字段定义:
|
||
|
||
```text
|
||
magic:
|
||
固定 0x36434D54
|
||
|
||
version:
|
||
初始为 1
|
||
|
||
header_len:
|
||
sizeof(tm_c6_frame_header_t)
|
||
|
||
frame_type:
|
||
见 5.3
|
||
|
||
channel:
|
||
见 5.4
|
||
|
||
flags:
|
||
bit0 = ACK_REQUIRED
|
||
bit1 = IS_ACK
|
||
bit2 = IS_FRAGMENT
|
||
bit3 = FRAGMENT_START
|
||
bit4 = FRAGMENT_END
|
||
bit5 = ERROR
|
||
bit6 = RESERVED
|
||
bit7 = RESERVED
|
||
|
||
seq:
|
||
发送方递增序号,0 可以跳过,从 1 开始
|
||
|
||
ack:
|
||
当 IS_ACK=1 时表示被确认的 seq
|
||
|
||
payload_len:
|
||
payload 字节数,不包括 header
|
||
|
||
crc32:
|
||
对 header 中 crc32 字段置 0 后的 header + payload 计算 CRC32
|
||
```
|
||
|
||
最大 payload:
|
||
|
||
```text
|
||
TM_C6_MAX_PAYLOAD = 1024
|
||
```
|
||
|
||
如果 BLE MTU、SDIO buffer 或内存条件要求更小,可以降低,但 P4 和 C6 必须通过 HELLO 协商。
|
||
|
||
禁止发送超过协商 `max_payload` 的单帧。
|
||
|
||
### 5.3 frame_type
|
||
|
||
```c
|
||
enum tm_c6_frame_type {
|
||
TM_C6_FRAME_HELLO = 0x01,
|
||
TM_C6_FRAME_HELLO_ACK = 0x02,
|
||
TM_C6_FRAME_PING = 0x03,
|
||
TM_C6_FRAME_PONG = 0x04,
|
||
TM_C6_FRAME_ACK = 0x05,
|
||
TM_C6_FRAME_ERROR = 0x06,
|
||
|
||
TM_C6_FRAME_CONFIG_SET = 0x10,
|
||
TM_C6_FRAME_CONFIG_GET = 0x11,
|
||
TM_C6_FRAME_CONFIG_REPORT = 0x12,
|
||
|
||
TM_C6_FRAME_BLE_UPLINK = 0x20,
|
||
TM_C6_FRAME_BLE_DOWNLINK = 0x21,
|
||
TM_C6_FRAME_BLE_EVENT = 0x22,
|
||
TM_C6_FRAME_BLE_CONTROL = 0x23,
|
||
|
||
TM_C6_FRAME_ESPNOW_UPLINK = 0x30,
|
||
TM_C6_FRAME_ESPNOW_DOWNLINK = 0x31,
|
||
TM_C6_FRAME_ESPNOW_EVENT = 0x32,
|
||
TM_C6_FRAME_ESPNOW_CONTROL = 0x33,
|
||
|
||
TM_C6_FRAME_WIFI_CONTROL = 0x40,
|
||
TM_C6_FRAME_WIFI_EVENT = 0x41,
|
||
TM_C6_FRAME_WIFI_DATA = 0x42,
|
||
|
||
TM_C6_FRAME_DIAG_REQUEST = 0x50,
|
||
TM_C6_FRAME_DIAG_REPORT = 0x51,
|
||
TM_C6_FRAME_LOG = 0x52
|
||
};
|
||
```
|
||
|
||
### 5.4 channel
|
||
|
||
```c
|
||
enum tm_c6_channel {
|
||
TM_C6_CH_CONTROL = 0x00,
|
||
TM_C6_CH_BLE_MESHTASTIC = 0x01,
|
||
TM_C6_CH_BLE_MESHCORE = 0x02,
|
||
TM_C6_CH_BLE_TRAILMATE = 0x03,
|
||
TM_C6_CH_ESPNOW_TEAM = 0x04,
|
||
TM_C6_CH_WIFI_MGMT = 0x05,
|
||
TM_C6_CH_WIFI_DATA = 0x06,
|
||
TM_C6_CH_DIAG = 0x07
|
||
};
|
||
```
|
||
|
||
不得使用一个“通用 BLE channel”承载所有协议。必须保留 channel id,让 P4 可以明确区分数据来自哪个无线入口。
|
||
|
||
### 5.5 启动握手
|
||
|
||
C6 启动后进入:
|
||
|
||
```text
|
||
WAIT_P4_HELLO
|
||
```
|
||
|
||
P4 启动后执行:
|
||
|
||
```text
|
||
1. reset C6, if board reset GPIO exists and is configured
|
||
2. init SDIO transport
|
||
3. send HELLO
|
||
4. wait HELLO_ACK
|
||
5. send CONFIG_SET
|
||
6. wait CONFIG_REPORT
|
||
7. start services
|
||
```
|
||
|
||
HELLO payload:
|
||
|
||
```c
|
||
typedef struct __attribute__((packed)) {
|
||
uint16_t proto_version_min;
|
||
uint16_t proto_version_max;
|
||
uint32_t p4_firmware_version;
|
||
uint32_t requested_features;
|
||
uint16_t preferred_mtu;
|
||
uint16_t max_payload;
|
||
} tm_c6_hello_t;
|
||
```
|
||
|
||
HELLO_ACK payload:
|
||
|
||
```c
|
||
typedef struct __attribute__((packed)) {
|
||
uint16_t selected_proto_version;
|
||
uint32_t c6_firmware_version;
|
||
uint32_t supported_features;
|
||
uint16_t selected_mtu;
|
||
uint16_t max_payload;
|
||
uint32_t c6_free_heap;
|
||
} tm_c6_hello_ack_t;
|
||
```
|
||
|
||
feature bits:
|
||
|
||
```c
|
||
#define TM_C6_FEATURE_BLE_MESHTASTIC (1u << 0)
|
||
#define TM_C6_FEATURE_BLE_MESHCORE (1u << 1)
|
||
#define TM_C6_FEATURE_BLE_TRAILMATE (1u << 2)
|
||
#define TM_C6_FEATURE_ESPNOW_TEAM (1u << 3)
|
||
#define TM_C6_FEATURE_WIFI_STA (1u << 4)
|
||
#define TM_C6_FEATURE_WIFI_AP (1u << 5)
|
||
#define TM_C6_FEATURE_DIAG_LOG (1u << 6)
|
||
```
|
||
|
||
如果 P4 请求的 feature C6 不支持,C6 不得失败启动。C6 应返回 supported_features,P4 根据 capability 降级 UI 和业务入口。
|
||
|
||
---
|
||
|
||
## 6. BLE 设计
|
||
|
||
### 6.1 BLE 总原则
|
||
|
||
C6 负责 BLE GAP / GATT;P4 负责 payload 语义。
|
||
|
||
C6 要实现三个 BLE facade:
|
||
|
||
```text
|
||
1. Meshtastic-compatible BLE facade
|
||
2. MeshCore-compatible BLE facade
|
||
3. Trail-Mate private BLE facade
|
||
```
|
||
|
||
三者必须独立 enable / disable。
|
||
|
||
不得把三个协议混进同一个 GATT characteristic。
|
||
|
||
### 6.2 BLE profile 配置
|
||
|
||
P4 下发:
|
||
|
||
```c
|
||
typedef struct __attribute__((packed)) {
|
||
uint8_t ble_enabled;
|
||
uint8_t meshtastic_enabled;
|
||
uint8_t meshcore_enabled;
|
||
uint8_t trailmate_enabled;
|
||
uint8_t pairing_mode;
|
||
uint8_t fixed_pin_enabled;
|
||
char fixed_pin[8];
|
||
char device_name[32];
|
||
uint16_t preferred_mtu;
|
||
} tm_c6_ble_config_t;
|
||
```
|
||
|
||
pairing_mode:
|
||
|
||
```c
|
||
enum tm_c6_pairing_mode {
|
||
TM_C6_PAIRING_DISABLED = 0,
|
||
TM_C6_PAIRING_RANDOM_PIN = 1,
|
||
TM_C6_PAIRING_FIXED_PIN = 2,
|
||
TM_C6_PAIRING_NO_PIN_DEBUG_ONLY = 3
|
||
};
|
||
```
|
||
|
||
release 固件不得默认使用 `TM_C6_PAIRING_NO_PIN_DEBUG_ONLY`。
|
||
|
||
### 6.3 Meshtastic BLE facade
|
||
|
||
C6 只做 transport,不解析 Meshtastic protobuf。
|
||
|
||
行为:
|
||
|
||
```text
|
||
Phone writes ToRadio bytes to Meshtastic GATT characteristic.
|
||
C6 wraps bytes into TM_C6_FRAME_BLE_UPLINK with channel TM_C6_CH_BLE_MESHTASTIC.
|
||
P4 receives bytes and passes them into existing Meshtastic Client API input path.
|
||
P4 produces FromRadio bytes.
|
||
P4 sends TM_C6_FRAME_BLE_DOWNLINK with channel TM_C6_CH_BLE_MESHTASTIC.
|
||
C6 notifies phone using Meshtastic GATT notify characteristic.
|
||
```
|
||
|
||
C6 禁止解析:
|
||
|
||
```text
|
||
MeshPacket
|
||
NodeInfo
|
||
Channel
|
||
Config
|
||
Position
|
||
User
|
||
```
|
||
|
||
C6 只允许知道:
|
||
|
||
```text
|
||
which connection
|
||
which characteristic
|
||
raw bytes
|
||
fragmentation state
|
||
notification queue state
|
||
```
|
||
|
||
### 6.4 MeshCore BLE facade
|
||
|
||
C6 只做 MeshCore companion transport bridge,不实现 MeshCore mesh 逻辑。
|
||
|
||
行为:
|
||
|
||
```text
|
||
MeshCore App writes bytes to MeshCore GATT characteristic.
|
||
C6 wraps bytes into TM_C6_FRAME_BLE_UPLINK with channel TM_C6_CH_BLE_MESHCORE.
|
||
P4 routes bytes to MeshCore adapter.
|
||
P4 returns MeshCore response bytes.
|
||
C6 notifies MeshCore App.
|
||
```
|
||
|
||
如果当前代码库中还没有 MeshCore BLE UUID / characteristic 定义,则实现时必须:
|
||
|
||
```text
|
||
1. 新增 tm_ble_meshcore.c。
|
||
2. 提供 compile-time disabled stub。
|
||
3. 在 tm_c6_ble_config_t 中保留 meshcore_enabled。
|
||
4. 当 meshcore_enabled=1 但 UUID 未配置时,C6 返回 TM_C6_ERROR_PROFILE_NOT_CONFIGURED。
|
||
5. 不得随意发明 MeshCore UUID。
|
||
```
|
||
|
||
### 6.5 Trail-Mate private BLE facade
|
||
|
||
Trail-Mate private BLE 用于 Trail-Mate 自己的 companion app、调试工具、配置工具。
|
||
|
||
推荐用途:
|
||
|
||
```text
|
||
1. 查看设备状态。
|
||
2. 查看 GPS 状态。
|
||
3. 查看 LoRa 状态。
|
||
4. 查看 C6 状态。
|
||
5. 修改非敏感 UI 配置。
|
||
6. 触发 Team Mode pairing。
|
||
7. 读取诊断日志。
|
||
```
|
||
|
||
Trail-Mate private BLE 不得绕过 P4 直接修改核心业务状态。所有写入必须转发给 P4,由 P4 决定是否接受。
|
||
|
||
---
|
||
|
||
## 7. ESP-NOW / Team Mode 设计
|
||
|
||
Team Mode 的业务核心在 P4。C6 只负责 ESP-NOW 发现和短消息传输。
|
||
|
||
### 7.1 ESP-NOW 数据流
|
||
|
||
```text
|
||
Nearby device sends ESP-NOW discovery packet.
|
||
C6 receives packet.
|
||
C6 wraps packet into TM_C6_FRAME_ESPNOW_UPLINK with channel TM_C6_CH_ESPNOW_TEAM.
|
||
P4 evaluates Team Mode business rule.
|
||
P4 sends response through TM_C6_FRAME_ESPNOW_DOWNLINK.
|
||
C6 sends ESP-NOW response.
|
||
```
|
||
|
||
### 7.2 C6 ESP-NOW 不得做的事情
|
||
|
||
C6 不得:
|
||
|
||
```text
|
||
1. 决定是否加入队伍。
|
||
2. 决定谁是 leader。
|
||
3. 生成最终 team key。
|
||
4. 保存 team key。
|
||
5. 修改队伍成员列表。
|
||
6. 触发 LoRa 消息。
|
||
```
|
||
|
||
C6 可以:
|
||
|
||
```text
|
||
1. 扫描附近 Trail-Mate 设备。
|
||
2. 广播 P4 下发的 discovery payload。
|
||
3. 接收 ESP-NOW payload。
|
||
4. 转发到 P4。
|
||
5. 根据 P4 指令发送 ESP-NOW response。
|
||
6. 维护短期 peer MAC cache。
|
||
```
|
||
|
||
### 7.3 ESP-NOW payload
|
||
|
||
C6 不理解 payload 内部格式。C6 只处理:
|
||
|
||
```c
|
||
typedef struct __attribute__((packed)) {
|
||
uint8_t peer_mac[6];
|
||
uint8_t rssi_valid;
|
||
int8_t rssi;
|
||
uint8_t payload_len;
|
||
uint8_t payload[240];
|
||
} tm_c6_espnow_packet_t;
|
||
```
|
||
|
||
如果 ESP-NOW payload 超过 240 字节,必须拒绝发送并向 P4 返回 `TM_C6_ERROR_PAYLOAD_TOO_LARGE`。
|
||
|
||
---
|
||
|
||
## 8. Wi-Fi 设计
|
||
|
||
Wi-Fi 分阶段实现。
|
||
|
||
### 8.1 Phase A:不实现 Wi-Fi,仅保留接口
|
||
|
||
第一版 C6 companion 以 BLE / ESP-NOW 为核心目标。Wi-Fi 可以先不实现,但必须在协议里保留:
|
||
|
||
```text
|
||
TM_C6_FEATURE_WIFI_STA
|
||
TM_C6_FEATURE_WIFI_AP
|
||
TM_C6_CH_WIFI_MGMT
|
||
TM_C6_CH_WIFI_DATA
|
||
TM_C6_FRAME_WIFI_CONTROL
|
||
TM_C6_FRAME_WIFI_EVENT
|
||
TM_C6_FRAME_WIFI_DATA
|
||
```
|
||
|
||
C6 如果不支持 Wi-Fi,则 HELLO_ACK 中不设置对应 feature bit。
|
||
|
||
P4 UI 必须显示:
|
||
|
||
```text
|
||
C6 Wi-Fi: unsupported by current companion firmware
|
||
```
|
||
|
||
而不是显示:
|
||
|
||
```text
|
||
Wi-Fi hardware missing
|
||
```
|
||
|
||
### 8.2 Phase B:Wi-Fi 管理能力
|
||
|
||
实现:
|
||
|
||
```text
|
||
1. scan
|
||
2. connect
|
||
3. disconnect
|
||
4. get_ip
|
||
5. softAP start/stop
|
||
6. Wi-Fi event report
|
||
```
|
||
|
||
P4 仍是配置源。C6 不保存 Wi-Fi SSID/password,除非 P4 明确要求。
|
||
|
||
### 8.3 Phase C:Wi-Fi 数据能力
|
||
|
||
可选实现 TCP/UDP bridge 或 HTTP diagnostic server。
|
||
|
||
注意:
|
||
|
||
```text
|
||
Wi-Fi 数据面不是第一阶段目标。
|
||
不要因为 Wi-Fi 数据面拖慢 BLE / ESP-NOW 的落地。
|
||
```
|
||
|
||
---
|
||
|
||
## 9. C6 内存和资源约束
|
||
|
||
C6 无 PSRAM。必须按小内存设备设计。
|
||
|
||
硬性限制:
|
||
|
||
```text
|
||
1. 不分配大 buffer。
|
||
2. 单个 HostLink payload 默认不超过 1024 字节。
|
||
3. BLE notify queue 默认不超过 8 个 packet。
|
||
4. ESP-NOW rx queue 默认不超过 8 个 packet。
|
||
5. 日志环形缓冲默认不超过 8KB。
|
||
6. 禁止在 C6 上保存消息历史。
|
||
7. 禁止在 C6 上保存 NodeDB。
|
||
8. 禁止在 C6 上保存地图、轨迹或文件。
|
||
```
|
||
|
||
推荐配置:
|
||
|
||
```c
|
||
#define TM_C6_HOSTLINK_RX_QUEUE_LEN 8
|
||
#define TM_C6_HOSTLINK_TX_QUEUE_LEN 8
|
||
#define TM_C6_BLE_NOTIFY_QUEUE_LEN 8
|
||
#define TM_C6_ESPNOW_RX_QUEUE_LEN 8
|
||
#define TM_C6_LOG_RING_SIZE 8192
|
||
#define TM_C6_MAX_PAYLOAD 1024
|
||
```
|
||
|
||
如果 heap 低于阈值:
|
||
|
||
```text
|
||
free_heap < 32KB
|
||
```
|
||
|
||
C6 必须上报 warning event:
|
||
|
||
```text
|
||
TM_C6_EVENT_LOW_MEMORY
|
||
```
|
||
|
||
如果 heap 低于:
|
||
|
||
```text
|
||
free_heap < 16KB
|
||
```
|
||
|
||
C6 必须停止接受新的 BLE write / ESP-NOW rx queue 入队,并返回 busy/error。
|
||
|
||
---
|
||
|
||
## 10. P4 固件必须调整的内容
|
||
|
||
按照这个方案,P4 固件必须调整。原因是 C6 不再是透明板厂无线固件,而是 Trail-Mate 的 wireless companion。P4 必须新增一个明确的 companion 抽象层。
|
||
|
||
### 10.1 新增 WirelessCompanion 抽象
|
||
|
||
新增接口:
|
||
|
||
```cpp
|
||
class WirelessCompanion {
|
||
public:
|
||
virtual bool begin() = 0;
|
||
virtual bool isPresent() const = 0;
|
||
virtual uint32_t capabilities() const = 0;
|
||
|
||
virtual bool configureBle(const BleCompanionConfig& config) = 0;
|
||
virtual bool configureEspNow(const EspNowCompanionConfig& config) = 0;
|
||
virtual bool configureWifi(const WifiCompanionConfig& config) = 0;
|
||
|
||
virtual bool sendBleDownlink(BleProfile profile, const uint8_t* data, size_t len) = 0;
|
||
virtual bool sendEspNow(const EspNowPacket& packet) = 0;
|
||
|
||
virtual void poll() = 0;
|
||
|
||
virtual ~WirelessCompanion() = default;
|
||
};
|
||
```
|
||
|
||
新增实现:
|
||
|
||
```cpp
|
||
class C6Companion final : public WirelessCompanion {
|
||
public:
|
||
bool begin() override;
|
||
bool isPresent() const override;
|
||
uint32_t capabilities() const override;
|
||
|
||
bool configureBle(const BleCompanionConfig& config) override;
|
||
bool configureEspNow(const EspNowCompanionConfig& config) override;
|
||
bool configureWifi(const WifiCompanionConfig& config) override;
|
||
|
||
bool sendBleDownlink(BleProfile profile, const uint8_t* data, size_t len) override;
|
||
bool sendEspNow(const EspNowPacket& packet) override;
|
||
|
||
void poll() override;
|
||
|
||
private:
|
||
C6HostLink link_;
|
||
uint32_t caps_ = 0;
|
||
bool present_ = false;
|
||
};
|
||
```
|
||
|
||
### 10.2 P4 不得直接假设本机有 BLE
|
||
|
||
T-Display-P4 目标中,BLE 不是 P4 本机 BLE,而是 C6 BLE facade。
|
||
|
||
因此 P4 侧代码必须区分:
|
||
|
||
```text
|
||
LocalBleAdapter:
|
||
用于 ESP32-S3 / nRF52 等本机有 BLE 的设备
|
||
|
||
C6BleAdapter:
|
||
用于 T-Display-P4,BLE 在 C6 上
|
||
```
|
||
|
||
新增枚举:
|
||
|
||
```cpp
|
||
enum class BleBackend {
|
||
None,
|
||
Local,
|
||
C6Companion
|
||
};
|
||
```
|
||
|
||
T-Display-P4 target 设置:
|
||
|
||
```cpp
|
||
BleBackend::C6Companion
|
||
```
|
||
|
||
普通 ESP32 / nRF52 目标保持原状。
|
||
|
||
### 10.3 P4 新增 BLE profile router
|
||
|
||
P4 必须根据 HostLink channel 把 C6 上来的 BLE 数据路由到不同业务模块:
|
||
|
||
```cpp
|
||
void onC6BleUplink(BleProfile profile, const uint8_t* data, size_t len) {
|
||
switch (profile) {
|
||
case BleProfile::Meshtastic:
|
||
meshtasticClientApi.handleToRadio(data, len);
|
||
break;
|
||
|
||
case BleProfile::MeshCore:
|
||
meshcoreCompanion.handleUplink(data, len);
|
||
break;
|
||
|
||
case BleProfile::TrailMate:
|
||
trailMatePrivateApi.handleBleRequest(data, len);
|
||
break;
|
||
}
|
||
}
|
||
```
|
||
|
||
P4 业务模块产生响应时:
|
||
|
||
```cpp
|
||
wirelessCompanion.sendBleDownlink(BleProfile::Meshtastic, data, len);
|
||
wirelessCompanion.sendBleDownlink(BleProfile::MeshCore, data, len);
|
||
wirelessCompanion.sendBleDownlink(BleProfile::TrailMate, data, len);
|
||
```
|
||
|
||
### 10.4 P4 新增 ESP-NOW Team Mode bridge
|
||
|
||
P4 新增:
|
||
|
||
```cpp
|
||
class TeamModeNearFieldBridge {
|
||
public:
|
||
void onEspNowDiscovery(const EspNowPacket& packet);
|
||
void sendDiscovery(const TeamDiscoveryPayload& payload);
|
||
void sendPairingResponse(const TeamPairingResponse& response);
|
||
};
|
||
```
|
||
|
||
C6 收到 ESP-NOW 后只转发,P4 负责 Team Mode 状态机。
|
||
|
||
现有 Team Mode 如果直接假设 ESP-NOW 在当前 MCU 上运行,需要改成:
|
||
|
||
```text
|
||
TeamModeCore
|
||
不依赖 ESP-NOW API
|
||
|
||
TeamModeTransport
|
||
抽象接口
|
||
|
||
LocalEspNowTransport
|
||
用于本机 Wi-Fi/BLE MCU
|
||
|
||
C6EspNowTransport
|
||
用于 T-Display-P4
|
||
```
|
||
|
||
接口:
|
||
|
||
```cpp
|
||
class TeamModeTransport {
|
||
public:
|
||
virtual bool startDiscovery(const TeamDiscoveryConfig& config) = 0;
|
||
virtual bool stopDiscovery() = 0;
|
||
virtual bool sendToPeer(const uint8_t mac[6], const uint8_t* data, size_t len) = 0;
|
||
virtual ~TeamModeTransport() = default;
|
||
};
|
||
```
|
||
|
||
### 10.5 P4 新增 C6 状态 UI
|
||
|
||
T-Display-P4 的设置页 / diagnostics 页需要新增:
|
||
|
||
```text
|
||
C6 Companion
|
||
- present / missing
|
||
- firmware version
|
||
- protocol version
|
||
- free heap
|
||
- supported features
|
||
- BLE enabled
|
||
- Meshtastic BLE enabled
|
||
- MeshCore BLE enabled
|
||
- Trail-Mate BLE enabled
|
||
- ESP-NOW Team enabled
|
||
- Wi-Fi supported / unsupported
|
||
- last error
|
||
```
|
||
|
||
如果 C6 不存在或协议不兼容,UI 必须显示明确错误:
|
||
|
||
```text
|
||
C6 companion not detected
|
||
C6 protocol mismatch
|
||
C6 firmware does not support requested BLE profile
|
||
C6 firmware does not support ESP-NOW Team Mode
|
||
```
|
||
|
||
不要静默隐藏。
|
||
|
||
### 10.6 P4 新增配置源
|
||
|
||
P4 是权威配置源。新增配置结构:
|
||
|
||
```cpp
|
||
struct C6CompanionSettings {
|
||
bool enabled = true;
|
||
|
||
struct {
|
||
bool enabled = true;
|
||
bool meshtasticEnabled = true;
|
||
bool meshcoreEnabled = true;
|
||
bool trailmateEnabled = true;
|
||
PairingMode pairingMode = PairingMode::FixedPin;
|
||
char fixedPin[8] = "123456";
|
||
char deviceName[32] = "TrailMate";
|
||
} ble;
|
||
|
||
struct {
|
||
bool enabled = false;
|
||
bool teamDiscoveryEnabled = false;
|
||
} espnow;
|
||
|
||
struct {
|
||
bool enabled = false;
|
||
bool staEnabled = false;
|
||
bool apEnabled = false;
|
||
} wifi;
|
||
};
|
||
```
|
||
|
||
T-Display-P4 启动时:
|
||
|
||
```cpp
|
||
C6CompanionSettings settings = loadFromP4Storage();
|
||
wirelessCompanion.begin();
|
||
wirelessCompanion.configureBle(settings.ble);
|
||
wirelessCompanion.configureEspNow(settings.espnow);
|
||
wirelessCompanion.configureWifi(settings.wifi);
|
||
```
|
||
|
||
C6 不从自己的 NVS 读取业务默认值。
|
||
|
||
---
|
||
|
||
## 11. 错误码
|
||
|
||
统一错误码:
|
||
|
||
```c
|
||
enum tm_c6_error_code {
|
||
TM_C6_OK = 0,
|
||
TM_C6_ERROR_BAD_MAGIC = 1,
|
||
TM_C6_ERROR_BAD_VERSION = 2,
|
||
TM_C6_ERROR_BAD_CRC = 3,
|
||
TM_C6_ERROR_PAYLOAD_TOO_LARGE = 4,
|
||
TM_C6_ERROR_UNSUPPORTED_FRAME = 5,
|
||
TM_C6_ERROR_UNSUPPORTED_CHANNEL = 6,
|
||
TM_C6_ERROR_UNSUPPORTED_FEATURE = 7,
|
||
TM_C6_ERROR_PROFILE_NOT_CONFIGURED = 8,
|
||
TM_C6_ERROR_NOT_CONNECTED = 9,
|
||
TM_C6_ERROR_QUEUE_FULL = 10,
|
||
TM_C6_ERROR_LOW_MEMORY = 11,
|
||
TM_C6_ERROR_TIMEOUT = 12,
|
||
TM_C6_ERROR_INTERNAL = 13
|
||
};
|
||
```
|
||
|
||
C6 返回 ERROR frame 时 payload:
|
||
|
||
```c
|
||
typedef struct __attribute__((packed)) {
|
||
uint16_t error_code;
|
||
uint16_t related_seq;
|
||
uint8_t related_frame_type;
|
||
uint8_t related_channel;
|
||
char message[64];
|
||
} tm_c6_error_t;
|
||
```
|
||
|
||
P4 必须把 ERROR frame 记录到日志,并更新 C6 diagnostics UI。
|
||
|
||
---
|
||
|
||
## 12. 开发阶段
|
||
|
||
### Phase 0:协议和空实现
|
||
|
||
目标:
|
||
|
||
```text
|
||
1. 添加 shared protocol 定义。
|
||
2. 添加 P4 C6Companion stub。
|
||
3. 添加 C6 companion ESP-IDF 工程。
|
||
4. C6 可以编译、刷写、启动。
|
||
5. P4 可以在没有 C6 时正常运行。
|
||
6. P4 diagnostics 显示 C6 missing。
|
||
```
|
||
|
||
验收:
|
||
|
||
```text
|
||
1. P4 build 通过。
|
||
2. C6 build 通过。
|
||
3. 不影响现有 tlora_pager / tdeck / gat562 构建。
|
||
4. T-Display-P4 在无 C6 companion 时不崩溃。
|
||
```
|
||
|
||
### Phase 1:HostLink bring-up
|
||
|
||
目标:
|
||
|
||
```text
|
||
1. P4 和 C6 完成 HELLO / HELLO_ACK。
|
||
2. P4 可以 PING,C6 返回 PONG。
|
||
3. C6 上报 firmware version / free heap。
|
||
4. P4 diagnostics 显示 C6 present。
|
||
```
|
||
|
||
Implementation note for the current Trail-Mate slice:
|
||
|
||
```text
|
||
P4 transport:
|
||
ESP-IDF esp_serial_slave_link over SDMMC slot 1.
|
||
|
||
C6 transport:
|
||
ESP-IDF esp_driver_sdio slave packet mode.
|
||
|
||
Present condition:
|
||
P4 sends HELLO, C6 returns HELLO_ACK, P4 sends PING, C6 returns PONG.
|
||
|
||
Failure condition:
|
||
P4 must continue booting and report missing/error with detail. It must not
|
||
mark C6 present from template logs, board capability, or factory firmware
|
||
assumptions.
|
||
|
||
OTA:
|
||
C6 image transfer is not part of this Phase 1 slice. Runtime slave OTA remains
|
||
gated on a present, versioned transport and a separately implemented image
|
||
write/verify/end sequence.
|
||
```
|
||
|
||
验收:
|
||
|
||
```text
|
||
1. 连续 ping 1000 次无 CRC 错误。
|
||
2. C6 reset 后 P4 能重新握手。
|
||
3. P4 reset 后 C6 能重新进入 WAIT_P4_HELLO。
|
||
4. 协议版本不匹配时显示明确错误。
|
||
```
|
||
|
||
### Phase 2:Trail-Mate private BLE
|
||
|
||
目标:
|
||
|
||
```text
|
||
1. C6 开启 Trail-Mate private BLE service。
|
||
2. 手机 BLE 调试工具可以连接。
|
||
3. 手机写入 private characteristic。
|
||
4. P4 收到 BLE_UPLINK。
|
||
5. P4 返回 BLE_DOWNLINK。
|
||
6. 手机收到 notify。
|
||
```
|
||
|
||
验收:
|
||
|
||
```text
|
||
1. 20 次连接/断开无死锁。
|
||
2. 1KB payload 可以分片传输。
|
||
3. notify queue 满时返回 backpressure,不丢失状态。
|
||
4. P4 UI 可显示 BLE connected / disconnected。
|
||
```
|
||
|
||
### Phase 3:Meshtastic BLE facade
|
||
|
||
目标:
|
||
|
||
```text
|
||
1. C6 暴露 Meshtastic-compatible BLE profile。
|
||
2. 手机 Meshtastic App 能发现设备。
|
||
3. App 写入的 ToRadio bytes 能到 P4。
|
||
4. P4 生成的 FromRadio bytes 能通知回 App。
|
||
```
|
||
|
||
验收:
|
||
|
||
```text
|
||
1. Meshtastic App 能连接。
|
||
2. 基本配置读取路径可通。
|
||
3. 文本消息发送路径可通。
|
||
4. 断线重连后不需要重启 P4 或 C6。
|
||
```
|
||
|
||
注意:
|
||
|
||
```text
|
||
如果 Meshtastic App 需要严格的 service UUID / characteristic UUID / advertisement 格式,必须从现有 Meshtastic 实现或项目内已有代码读取,不得猜测。
|
||
```
|
||
|
||
### Phase 4:MeshCore BLE facade
|
||
|
||
目标:
|
||
|
||
```text
|
||
1. C6 暴露 MeshCore companion profile。
|
||
2. MeshCore app 或调试工具能连接。
|
||
3. MeshCore uplink/downlink raw bytes 能通过 P4。
|
||
```
|
||
|
||
验收:
|
||
|
||
```text
|
||
1. MeshCore BLE profile 未配置 UUID 时,编译可通过但运行时返回 PROFILE_NOT_CONFIGURED。
|
||
2. 配置 UUID 后,MeshCore raw transport 可通。
|
||
3. 不影响 Meshtastic BLE profile。
|
||
```
|
||
|
||
### Phase 5:ESP-NOW Team Mode
|
||
|
||
目标:
|
||
|
||
```text
|
||
1. C6 可以发送 ESP-NOW discovery。
|
||
2. C6 可以接收 ESP-NOW discovery。
|
||
3. P4 Team Mode 可以通过 C6EspNowTransport 处理近场发现。
|
||
4. C6 不保存 team state。
|
||
```
|
||
|
||
验收:
|
||
|
||
```text
|
||
1. 两台设备可以互相发现。
|
||
2. P4 diagnostics 能看到 peer MAC / RSSI。
|
||
3. Team Mode 状态变化只发生在 P4。
|
||
4. C6 reset 后 Team Mode 状态不会在 C6 恢复,必须由 P4 重新下发。
|
||
```
|
||
|
||
### Phase 6:Wi-Fi 恢复
|
||
|
||
目标:
|
||
|
||
```text
|
||
1. C6 支持 Wi-Fi scan。
|
||
2. C6 支持 station connect。
|
||
3. C6 上报 IP。
|
||
4. P4 UI 可以显示 Wi-Fi 状态。
|
||
```
|
||
|
||
验收:
|
||
|
||
```text
|
||
1. BLE 开启时 Wi-Fi scan 不导致 BLE 断连。
|
||
2. Wi-Fi 连接失败有明确错误码。
|
||
3. Wi-Fi unsupported 时 P4 正确降级。
|
||
```
|
||
|
||
---
|
||
|
||
## 13. 回归测试要求
|
||
|
||
每次修改 C6 protocol 必须执行:
|
||
|
||
```text
|
||
1. P4 build: t_display_p4_tft
|
||
2. P4 build: t_display_p4_amoled
|
||
3. C6 build: esp32c6 companion
|
||
4. 至少一个现有 PlatformIO 主目标 build
|
||
5. HostLink frame encode/decode unit test
|
||
6. CRC error injection test
|
||
7. payload too large test
|
||
8. unsupported feature test
|
||
```
|
||
|
||
HostLink 单元测试至少覆盖:
|
||
|
||
```text
|
||
1. 正常 frame encode/decode。
|
||
2. magic 错误。
|
||
3. version 错误。
|
||
4. crc 错误。
|
||
5. payload_len 超限。
|
||
6. ACK_REQUIRED / IS_ACK。
|
||
7. channel routing。
|
||
8. fragment start/end。
|
||
```
|
||
|
||
---
|
||
|
||
## 14. 日志规范
|
||
|
||
C6 日志 tag:
|
||
|
||
```text
|
||
C6_MAIN
|
||
C6_HOSTLINK
|
||
C6_BLE
|
||
C6_BLE_MT
|
||
C6_BLE_MC
|
||
C6_BLE_TM
|
||
C6_ESPNOW
|
||
C6_WIFI
|
||
C6_DIAG
|
||
```
|
||
|
||
P4 日志 tag:
|
||
|
||
```text
|
||
P4_C6
|
||
P4_C6_LINK
|
||
P4_C6_BLE
|
||
P4_C6_ESPNOW
|
||
P4_C6_WIFI
|
||
P4_C6_DIAG
|
||
```
|
||
|
||
所有 HostLink 错误必须打印:
|
||
|
||
```text
|
||
seq
|
||
frame_type
|
||
channel
|
||
error_code
|
||
payload_len
|
||
free_heap if C6 side
|
||
```
|
||
|
||
禁止在日志中打印:
|
||
|
||
```text
|
||
1. channel key
|
||
2. team key
|
||
3. private key
|
||
4. fixed PIN
|
||
5. Wi-Fi password
|
||
```
|
||
|
||
---
|
||
|
||
## 15. Release 策略
|
||
|
||
P4 和 C6 必须有独立版本号,但需要协议兼容声明。
|
||
|
||
例如:
|
||
|
||
```text
|
||
Trail-Mate P4 firmware: 0.1.30
|
||
Trail-Mate C6 companion: 0.1.0
|
||
C6 protocol version: 1
|
||
```
|
||
|
||
P4 固件中维护兼容范围:
|
||
|
||
```cpp
|
||
#define TM_C6_PROTO_MIN 1
|
||
#define TM_C6_PROTO_MAX 1
|
||
```
|
||
|
||
C6 固件中维护兼容范围:
|
||
|
||
```c
|
||
#define TM_C6_PROTO_MIN 1
|
||
#define TM_C6_PROTO_MAX 1
|
||
```
|
||
|
||
如果协议不兼容:
|
||
|
||
```text
|
||
P4 不得继续启用 BLE / ESP-NOW。
|
||
P4 UI 显示 C6 protocol mismatch。
|
||
C6 保持 WAIT_P4_HELLO 或 SAFE_MODE。
|
||
```
|
||
|
||
---
|
||
|
||
## 16. 最终验收标准
|
||
|
||
第一版可接受目标:
|
||
|
||
```text
|
||
1. P4 和 C6 可以稳定握手。
|
||
2. P4 diagnostics 能显示 C6 状态。
|
||
3. Trail-Mate private BLE 可用。
|
||
4. Meshtastic BLE facade 可用或至少 raw path 可通。
|
||
5. MeshCore BLE facade 有明确 stub,不会误报可用。
|
||
6. ESP-NOW Team Mode transport 可跑最小发现流程。
|
||
7. C6 reset 不会拖死 P4。
|
||
8. P4 reset 后 C6 能重新连接。
|
||
9. 没有 C6 固件时,P4 仍可运行 LoRa / UI / GPS / 地图。
|
||
10. C6 不保存 Trail-Mate 主业务状态。
|
||
```
|
||
|
||
不作为第一版验收目标:
|
||
|
||
```text
|
||
1. 完整 Wi-Fi 数据面。
|
||
2. Web server。
|
||
3. OTA。
|
||
4. 文件传输。
|
||
5. C6 上的复杂协议解析。
|
||
6. C6 上的消息历史。
|
||
7. C6 上的 MeshCore / Meshtastic 核心实现。
|
||
```
|
||
|
||
---
|
||
|
||
## 17. 给编码 AI 的强制要求
|
||
|
||
实现时必须遵守以下规则:
|
||
|
||
```text
|
||
1. 不要把业务核心搬到 C6。
|
||
2. 不要让 C6 直接驱动 LoRa。
|
||
3. 不要让 C6 保存业务密钥。
|
||
4. 不要猜测 MeshCore UUID;没有来源就做 disabled stub。
|
||
5. 不要猜测 Meshtastic UUID;必须从项目已有实现或上游协议定义确认。
|
||
6. 不要让 T-Display-P4 的 P4 固件直接依赖本机 BLE。
|
||
7. T-Display-P4 的 BLE backend 必须是 C6Companion。
|
||
8. C6 所有无线服务必须由 P4 下发配置后才启动。
|
||
9. P4 没有检测到 C6 时必须降级运行,而不是崩溃。
|
||
10. 所有 P4-C6 数据都必须走 HostLink frame。
|
||
11. 所有 HostLink frame 必须校验 CRC。
|
||
12. 所有 HostLink channel 必须显式路由。
|
||
13. 所有错误必须可诊断。
|
||
14. 所有新增代码必须不破坏现有 tdeck / tlora_pager / gat562 构建。
|
||
```
|
||
|
||
---
|
||
|
||
# 总结
|
||
|
||
本方案不是把 ESP32-C6 做成第二个 Trail-Mate,而是把它做成 Trail-Mate 的无线边缘适配器。
|
||
|
||
最终边界:
|
||
|
||
```text
|
||
P4:
|
||
Trail-Mate domain core
|
||
|
||
C6:
|
||
BLE / ESP-NOW / Wi-Fi wireless facade
|
||
|
||
HostLink:
|
||
P4-C6 之间唯一可信数据通道
|
||
```
|
||
|
||
按照这个边界实现,Trail-Mate 可以同时支持 Meshtastic、MeshCore、Trail-Mate private companion、Team Mode,而不会把业务状态拆散到两颗 MCU 上。
|