From c681db059061bc0317b4e5a4fa307ce8243f36cb Mon Sep 17 00:00:00 2001
From: Wuchuyuan <1917507415@qq.com>
Date: Thu, 13 Aug 2026 12:23:41 +0800
Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=20usr=5Fmcu=5Fbridge?=
=?UTF-8?q?=EF=BC=9A=E6=8B=86=E6=88=90=20protocol/business=20=E5=88=86?=
=?UTF-8?q?=E5=B1=82=EF=BC=8C=E7=B2=BE=E7=AE=80=E4=B8=8A=E6=8A=A5=E4=B8=8E?=
=?UTF-8?q?=20UART=20=E8=B6=85=E6=97=B6=E9=80=BB=E8=BE=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
1、协议层迁入 protocol/,业务拆为 identity/pairing/link_status,mcu_bridge 收敛为薄门面
2、0x07 上报不再缓存重发,由 MCU 侧超时重发;模组只记 SN,网关 ACK 后回 0x08
3、APP 透传重试用尽后主动回 FAIL;UART ACK 等待统一为 MCU_UART_ACK_WAIT_MS=500ms
---
.gitignore | 3 +-
JBao_JL7016_MOD_FW/AC701N.cbp | 36 +-
JBao_JL7016_MOD_FW/Makefile | 13 +-
.../apps/usr_le_code/usr_le_product.h | 8 +-
.../usr_mcu_bridge/business/mcu_business.c | 109 ++
.../usr_mcu_bridge/business/mcu_business.h | 72 ++
.../usr_mcu_bridge/business/mcu_identity.c | 139 +++
.../usr_mcu_bridge/business/mcu_identity.h | 41 +
.../usr_mcu_bridge/business/mcu_link_status.c | 129 ++
.../usr_mcu_bridge/business/mcu_link_status.h | 53 +
.../usr_mcu_bridge/business/mcu_pairing.c | 108 ++
.../usr_mcu_bridge/business/mcu_pairing.h | 40 +
.../apps/usr_mcu_bridge/mcu_bridge.c | 1063 +----------------
.../apps/usr_mcu_bridge/mcu_bridge.h | 55 +-
.../usr_mcu_bridge/{ => protocol}/mcu_cmd.h | 27 +-
.../usr_mcu_bridge/{ => protocol}/mcu_frame.c | 0
.../usr_mcu_bridge/{ => protocol}/mcu_frame.h | 0
.../usr_mcu_bridge/protocol/mcu_protocol.c | 881 ++++++++++++++
.../usr_mcu_bridge/protocol/mcu_protocol.h | 83 ++
.../usr_mcu_bridge/{ => protocol}/mcu_uart.c | 2 +-
.../usr_mcu_bridge/{ => protocol}/mcu_uart.h | 2 +-
.../usr_mcu_bridge/{ => protocol}/mcu_util.c | 0
.../usr_mcu_bridge/{ => protocol}/mcu_util.h | 0
23 files changed, 1782 insertions(+), 1082 deletions(-)
create mode 100644 JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_business.c
create mode 100644 JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_business.h
create mode 100644 JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_identity.c
create mode 100644 JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_identity.h
create mode 100644 JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_link_status.c
create mode 100644 JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_link_status.h
create mode 100644 JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_pairing.c
create mode 100644 JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_pairing.h
rename JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/{ => protocol}/mcu_cmd.h (73%)
rename JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/{ => protocol}/mcu_frame.c (100%)
rename JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/{ => protocol}/mcu_frame.h (100%)
create mode 100644 JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/protocol/mcu_protocol.c
create mode 100644 JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/protocol/mcu_protocol.h
rename JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/{ => protocol}/mcu_uart.c (98%)
rename JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/{ => protocol}/mcu_uart.h (98%)
rename JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/{ => protocol}/mcu_util.c (100%)
rename JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/{ => protocol}/mcu_util.h (100%)
diff --git a/.gitignore b/.gitignore
index 637223f..242061c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
-PY32F040开发框架/*
\ No newline at end of file
+PY32F040开发框架/*
+.vscode/
\ No newline at end of file
diff --git a/JBao_JL7016_MOD_FW/AC701N.cbp b/JBao_JL7016_MOD_FW/AC701N.cbp
index 0cbc6c7..90dc304 100644
--- a/JBao_JL7016_MOD_FW/AC701N.cbp
+++ b/JBao_JL7016_MOD_FW/AC701N.cbp
@@ -175,6 +175,8 @@
+
+
@@ -761,19 +763,39 @@
-
-
+
+
-
-
+
+
-
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/JBao_JL7016_MOD_FW/Makefile b/JBao_JL7016_MOD_FW/Makefile
index 80160c8..9aebae2 100644
--- a/JBao_JL7016_MOD_FW/Makefile
+++ b/JBao_JL7016_MOD_FW/Makefile
@@ -249,6 +249,8 @@ INCLUDES := \
-Iapps/usr_le_code/thirdpart \
-Iapps/usr_le_code/thirdpart/mjson \
-Iapps/usr_mcu_bridge \
+ -Iapps/usr_mcu_bridge/protocol \
+ -Iapps/usr_mcu_bridge/business \
-I$(SYS_INC_DIR) \
@@ -614,9 +616,14 @@ c_SRC_FILES := \
cpu/br28/uart_dev.c \
cpu/br28/umidigi_chargestore.c \
apps/usr_mcu_bridge/mcu_bridge.c \
- apps/usr_mcu_bridge/mcu_frame.c \
- apps/usr_mcu_bridge/mcu_uart.c \
- apps/usr_mcu_bridge/mcu_util.c \
+ apps/usr_mcu_bridge/protocol/mcu_frame.c \
+ apps/usr_mcu_bridge/protocol/mcu_uart.c \
+ apps/usr_mcu_bridge/protocol/mcu_util.c \
+ apps/usr_mcu_bridge/protocol/mcu_protocol.c \
+ apps/usr_mcu_bridge/business/mcu_identity.c \
+ apps/usr_mcu_bridge/business/mcu_pairing.c \
+ apps/usr_mcu_bridge/business/mcu_link_status.c \
+ apps/usr_mcu_bridge/business/mcu_business.c \
apps/usr_le_code/ble_proto.c \
apps/usr_le_code/bleproto.c \
apps/usr_le_code/bleproto_packer.c \
diff --git a/JBao_JL7016_MOD_FW/apps/usr_le_code/usr_le_product.h b/JBao_JL7016_MOD_FW/apps/usr_le_code/usr_le_product.h
index 58cae62..11382d3 100644
--- a/JBao_JL7016_MOD_FW/apps/usr_le_code/usr_le_product.h
+++ b/JBao_JL7016_MOD_FW/apps/usr_le_code/usr_le_product.h
@@ -3,10 +3,12 @@
* @brief usr_le_code 产品身份配置接口(由 MCU 桥运行时填充)
* @author cyWu <1917507415@qq.com>
* @date 2026.08.03
- * @version V1.1.0
+ * @version V1.2.0
* @history
* - V1.0.0, 2026.08.03, cyWu, 首次发布
* - V1.1.0, 2026.08.06, cyWu, 改为非 const,由 mcu_bridge 从 MCU 0x02 写入
+ * - V1.2.0, 2026.08.12, cyWu, 改由 mcu_link 从 MCU 0x02 写入
+ * - V1.3.0, 2026.08.12, cyWu, 改由 business/mcu_identity 从 MCU 0x02 写入
******************************************************************************/
#ifndef __USR_LE_PRODUCT_H__
@@ -30,13 +32,13 @@ extern "C" {
/**
* @brief 产品类别码,对应 BLE 广播 prodcode(固定 4 字节 ASCII)
- * @note 由 mcu_bridge 从 MCU 身份应答取前 4 字节写入
+ * @note 由 business/mcu_identity 从 MCU 身份应答取前 4 字节写入
*/
extern uint8_t g_usr_le_prodcode[USR_LE_PRODCODE_LEN];
/**
* @brief 平台产品码,对应 BLE 广播 pcode(固定 6 字节 ASCII)
- * @note 由 mcu_bridge 从 MCU 身份应答取前 6 字节写入
+ * @note 由 business/mcu_identity 从 MCU 身份应答取前 6 字节写入
*/
extern uint8_t g_usr_le_pcode[USR_LE_PCODE_LEN];
diff --git a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_business.c b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_business.c
new file mode 100644
index 0000000..c2797d7
--- /dev/null
+++ b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_business.c
@@ -0,0 +1,109 @@
+/******************************************************************************
+ * @file mcu_business.c
+ * @brief 业务门面实现
+ * @author cyWu <1917507415@qq.com>
+ * @date 2026.08.12
+ * @version V1.0.0
+ * @history
+ * - V1.0.0, 2026.08.12, cyWu, 取代原 mcu_link,编排三个业务子模块
+ ******************************************************************************/
+
+#include "system/includes.h"
+#include "app_main.h"
+#include "mcu_business.h"
+#include "mcu_identity.h"
+#include "mcu_pairing.h"
+#include "mcu_link_status.h"
+#include "mcu_cmd.h"
+
+#define LOG_TAG_CONST APP
+#define LOG_TAG "[MCU_BIZ]"
+#define LOG_ERROR_ENABLE
+#define LOG_INFO_ENABLE
+#include "debug.h"
+
+/**
+ * @brief 初始化业务层
+ * @note 上电不强制配网;广播由 mcu_identity_on_ack 在身份就绪后按
+ * 配对状态触发(usr_ble_adv_init 内部决策)
+ */
+void mcu_business_init(void)
+{
+ mcu_identity_init();
+ mcu_pairing_init();
+ mcu_link_status_init();
+
+ usr_var.usr_goto_pair = 0;
+ usr_var.usr_adv_flag = 0;
+}
+
+/**
+ * @brief 周期处理
+ */
+void mcu_business_periodic(void)
+{
+ mcu_identity_periodic();
+ mcu_link_status_periodic();
+ mcu_pairing_periodic();
+}
+
+/**
+ * @brief 是否身份就绪
+ * @return 1/0
+ */
+uint8_t mcu_business_is_identity_ready(void)
+{
+ return mcu_identity_is_ready();
+}
+
+/**
+ * @brief 获取工作状态
+ * @return work_status
+ */
+uint8_t mcu_business_get_work_status(void)
+{
+ return mcu_link_status_get();
+}
+
+/**
+ * @brief 处理身份应答
+ * @param frame 完整帧
+ * @param len 长度
+ */
+void mcu_business_on_identity_ack(const uint8_t *frame, uint16_t len)
+{
+ mcu_identity_on_ack(frame, len);
+}
+
+/**
+ * @brief 处理配网请求
+ * @param mode 模式
+ * @param timeout_s 超时秒
+ */
+void mcu_business_on_pair_cfg(uint8_t mode, uint16_t timeout_s)
+{
+ mcu_pairing_start(mode, timeout_s);
+}
+
+/**
+ * @brief 配网成功
+ */
+void mcu_business_on_paired(void)
+{
+ usr_var.usr_goto_pair = 0;
+ mcu_pairing_stop();
+ mcu_link_status_set_phase(MCU_WS_CONFIGURED);
+ log_info("paired -> CONFIGURED");
+}
+
+/**
+ * @brief 配对清除
+ * @note 若正处于配网流程(phase==PAIRING),保持不变;
+ * 否则(例如单纯清空配对表)回到未配网空闲
+ */
+void mcu_business_on_pair_cleared(void)
+{
+ if (mcu_link_status_get_phase() != MCU_WS_PAIRING) {
+ mcu_link_status_set_phase(0);
+ }
+}
diff --git a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_business.h b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_business.h
new file mode 100644
index 0000000..cad777f
--- /dev/null
+++ b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_business.h
@@ -0,0 +1,72 @@
+/******************************************************************************
+ * @file mcu_business.h
+ * @brief 业务门面:协调身份 / 配网 / 连接状态三个业务子模块
+ * @author cyWu <1917507415@qq.com>
+ * @date 2026.08.12
+ * @version V1.0.0
+ * @history
+ * - V1.0.0, 2026.08.12, cyWu, 取代原 mcu_link,供协议层(mcu_protocol)
+ * 单点调用;协议层不直接依赖 identity/pairing/link_status 三个子模块
+ ******************************************************************************/
+
+#ifndef __MCU_BUSINESS_H__
+#define __MCU_BUSINESS_H__
+
+#include
+
+/*============================================================================*/
+/* 说明 */
+/* 本模块只做业务编排,不含具体状态;具体逻辑见: */
+/* mcu_identity.c —— 身份获取 */
+/* mcu_pairing.c —— 配网请求 / 超时 */
+/* mcu_link_status.c —— 连接状态位图(Bit0/1/2) */
+/* 须在协议任务(mcu_protocol_task)单一上下文中调用。 */
+/*============================================================================*/
+
+/**
+ * @brief 初始化业务层(身份 + 配网 + 连接状态)
+ */
+void mcu_business_init(void);
+
+/**
+ * @brief 周期处理:依次驱动身份 / 连接状态 / 配网三个子业务
+ */
+void mcu_business_periodic(void);
+
+/**
+ * @brief 是否已从 MCU 获取到设备身份
+ * @return 1=已就绪,0=未就绪
+ */
+uint8_t mcu_business_is_identity_ready(void);
+
+/**
+ * @brief 获取当前工作状态字节(命令 0x14 载荷)
+ * @return 工作状态 bitmap
+ */
+uint8_t mcu_business_get_work_status(void);
+
+/**
+ * @brief 处理 0x02 身份应答
+ * @param frame 完整帧
+ * @param len 长度
+ */
+void mcu_business_on_identity_ack(const uint8_t *frame, uint16_t len);
+
+/**
+ * @brief 处理已通过协议校验的 0x10 配网请求
+ * @param mode 1 或 2
+ * @param timeout_s 超时秒数,0 表示不超时
+ */
+void mcu_business_on_pair_cfg(uint8_t mode, uint16_t timeout_s);
+
+/**
+ * @brief 配网成功(AUTHSETUP 写对)
+ */
+void mcu_business_on_paired(void);
+
+/**
+ * @brief 配对信息被清除
+ */
+void mcu_business_on_pair_cleared(void);
+
+#endif /* __MCU_BUSINESS_H__ */
diff --git a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_identity.c b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_identity.c
new file mode 100644
index 0000000..30dda8b
--- /dev/null
+++ b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_identity.c
@@ -0,0 +1,139 @@
+/******************************************************************************
+ * @file mcu_identity.c
+ * @brief 身份业务实现
+ * @author cyWu <1917507415@qq.com>
+ * @date 2026.08.12
+ * @version V1.0.0
+ * @history
+ * - V1.0.0, 2026.08.12, cyWu, 从 mcu_link 拆出
+ ******************************************************************************/
+
+#include "system/includes.h"
+#include "mcu_identity.h"
+#include "mcu_protocol.h"
+#include "mcu_cmd.h"
+#include "mcu_util.h"
+#include "usr_le_api.h"
+#include "usr_le_product.h"
+
+#define LOG_TAG_CONST APP
+#define LOG_TAG "[MCU_ID]"
+#define LOG_ERROR_ENABLE
+#define LOG_DEBUG_ENABLE
+#define LOG_INFO_ENABLE
+#include "debug.h"
+
+/*============================================================================*/
+/* 私有宏 */
+/*============================================================================*/
+
+#define MCU_IDENTITY_RETRY_MS (1000u)
+#define MCU_IDENTITY_PAYLOAD_MIN (2 + 8 + 8 + 16 + 8) /* Ver+Cat+Prod+SN+Cap */
+
+/*============================================================================*/
+/* 公有变量:运行时可改写的产品身份(供 BLE 广播使用) */
+/*============================================================================*/
+
+uint8_t g_usr_le_prodcode[USR_LE_PRODCODE_LEN];
+uint8_t g_usr_le_pcode[USR_LE_PCODE_LEN];
+
+/*============================================================================*/
+/* 私有类型/变量 */
+/*============================================================================*/
+
+typedef struct {
+ uint8_t ready;
+ uint32_t last_tx_ms;
+} McuIdentity_t;
+
+static McuIdentity_t s_identity;
+
+/*============================================================================*/
+/* 公有函数 */
+/*============================================================================*/
+
+/**
+ * @brief 初始化身份业务状态
+ */
+void mcu_identity_init(void)
+{
+ memset(&s_identity, 0, sizeof(s_identity));
+ memset(g_usr_le_prodcode, 0, sizeof(g_usr_le_prodcode));
+ memset(g_usr_le_pcode, 0, sizeof(g_usr_le_pcode));
+}
+
+/**
+ * @brief 身份未就绪时每 1s 发 0x01
+ */
+void mcu_identity_periodic(void)
+{
+ uint32_t now;
+
+ if (s_identity.ready) {
+ return;
+ }
+
+ now = mcu_util_get_ms();
+ if ((now - s_identity.last_tx_ms) < MCU_IDENTITY_RETRY_MS) {
+ return;
+ }
+ s_identity.last_tx_ms = now;
+
+ if (mcu_protocol_send_cmd(MCU_CMD_GET_IDENTITY, NULL, 0) > 0) {
+ log_debug("identity req");
+ }
+}
+
+/**
+ * @brief 是否身份就绪
+ * @return 1/0
+ */
+uint8_t mcu_identity_is_ready(void)
+{
+ return s_identity.ready;
+}
+
+/**
+ * @brief 处理 0x02 身份应答
+ * @param frame 完整帧
+ * @param len 长度
+ * @note 载荷布局(Result 之后):Ver(2)+Category(8)+Product(8)+SN(16)+Cap(8)
+ */
+void mcu_identity_on_ack(const uint8_t *frame, uint16_t len)
+{
+ int i;
+
+ if (!frame || len < 7) {
+ return;
+ }
+ if (frame[6] != MCU_RESULT_OK) {
+ log_error("identity ack result=0x%02X", frame[6]);
+ return;
+ }
+ if (len < (7 + MCU_IDENTITY_PAYLOAD_MIN + 1)) {
+ log_error("identity ack too short %u", len);
+ return;
+ }
+
+ /* Category Code 在 Result(frame[6]) 后偏移 Ver(2),取前 4;
+ * Product Code 再后 Category(8),取前 6 */
+ memcpy(g_usr_le_prodcode, &frame[7 + 2], USR_LE_PRODCODE_LEN);
+ memcpy(g_usr_le_pcode, &frame[7 + 2 + 8], USR_LE_PCODE_LEN);
+
+ s_identity.ready = 1;
+
+ printf("identity ok prodcode:");
+ for (i = 0; i < USR_LE_PRODCODE_LEN; i++) {
+ printf("%c", g_usr_le_prodcode[i]);
+ }
+ printf("\n");
+ printf("identity ok pcode:");
+ for (i = 0; i < USR_LE_PCODE_LEN; i++) {
+ printf("%c", g_usr_le_pcode[i]);
+ }
+ printf("\n");
+
+ /* 身份就绪:强制协议层重推 0x14,并刷新广播(决策见 usr_ble_adv_init) */
+ mcu_protocol_invalidate_work_status_push();
+ usr_ble_adv_init();
+}
diff --git a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_identity.h b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_identity.h
new file mode 100644
index 0000000..80bc06f
--- /dev/null
+++ b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_identity.h
@@ -0,0 +1,41 @@
+/******************************************************************************
+ * @file mcu_identity.h
+ * @brief 身份业务:获取并持有 MCU 产品身份(prodcode/pcode)
+ * @author cyWu <1917507415@qq.com>
+ * @date 2026.08.12
+ * @version V1.0.0
+ * @history
+ * - V1.0.0, 2026.08.12, cyWu, 从 mcu_link 拆出,独立为身份业务模块
+ ******************************************************************************/
+
+#ifndef __MCU_IDENTITY_H__
+#define __MCU_IDENTITY_H__
+
+#include
+
+/**
+ * @brief 初始化身份业务状态
+ */
+void mcu_identity_init(void);
+
+/**
+ * @brief 周期处理:未就绪时每 1s 重发 0x01 身份请求
+ * @note 仅在协议任务上下文调用
+ */
+void mcu_identity_periodic(void);
+
+/**
+ * @brief 是否已从 MCU 获取到设备身份
+ * @return 1=已就绪,0=未就绪
+ */
+uint8_t mcu_identity_is_ready(void);
+
+/**
+ * @brief 处理 0x02 身份应答
+ * @param frame 完整帧
+ * @param len 长度
+ * @note 成功后写入 g_usr_le_prodcode/g_usr_le_pcode,并刷新 BLE 广播
+ */
+void mcu_identity_on_ack(const uint8_t *frame, uint16_t len);
+
+#endif /* __MCU_IDENTITY_H__ */
diff --git a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_link_status.c b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_link_status.c
new file mode 100644
index 0000000..b086ed1
--- /dev/null
+++ b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_link_status.c
@@ -0,0 +1,129 @@
+/******************************************************************************
+ * @file mcu_link_status.c
+ * @brief 连接状态业务实现
+ * @author cyWu <1917507415@qq.com>
+ * @date 2026.08.12
+ * @version V1.0.0
+ * @history
+ * - V1.0.0, 2026.08.12, cyWu, 从 mcu_link 拆出
+ ******************************************************************************/
+
+#include "system/includes.h"
+#include "app_main.h"
+#include "mcu_link_status.h"
+#include "mcu_identity.h"
+#include "mcu_cmd.h"
+#include "usr_le_api.h"
+
+#define LOG_TAG_CONST APP
+#define LOG_TAG "[MCU_LNK]"
+#define LOG_ERROR_ENABLE
+#define LOG_DEBUG_ENABLE
+#define LOG_INFO_ENABLE
+#include "debug.h"
+
+/*============================================================================*/
+/* 外部符号 */
+/*============================================================================*/
+
+extern u16 usr_get_conn_service(void);
+
+/*============================================================================*/
+/* 私有变量 */
+/*============================================================================*/
+
+typedef struct {
+ uint8_t work_status;
+ uint8_t last_ble_conn;
+} McuLinkStatus_t;
+
+static McuLinkStatus_t s_status;
+
+/*============================================================================*/
+/* 公有函数 */
+/*============================================================================*/
+
+/**
+ * @brief 初始化连接状态
+ */
+void mcu_link_status_init(void)
+{
+ memset(&s_status, 0, sizeof(s_status));
+}
+
+/**
+ * @brief 获取完整工作状态字节
+ * @return work_status
+ */
+uint8_t mcu_link_status_get(void)
+{
+ return s_status.work_status;
+}
+
+/**
+ * @brief 获取当前 Bit0/1/2 互斥过程态
+ * @return phase
+ */
+uint8_t mcu_link_status_get_phase(void)
+{
+ return (uint8_t)(s_status.work_status & MCU_WS_LINK_MASK);
+}
+
+/**
+ * @brief 设置 Bit0/1/2 互斥过程态
+ * @param phase 目标过程态
+ */
+void mcu_link_status_set_phase(uint8_t phase)
+{
+ s_status.work_status &= (uint8_t)~MCU_WS_LINK_MASK;
+ if (phase & MCU_WS_LINK_MASK) {
+ s_status.work_status |= (uint8_t)(phase & MCU_WS_LINK_MASK);
+ }
+}
+
+/**
+ * @brief 设置/清除 Bit6 OTA
+ * @param on 1/0
+ */
+void mcu_link_status_set_ota(uint8_t on)
+{
+ if (on) {
+ s_status.work_status |= MCU_WS_OTA_UPGRADING;
+ } else {
+ s_status.work_status &= (uint8_t)~MCU_WS_OTA_UPGRADING;
+ }
+}
+
+/**
+ * @brief 周期处理:轮询 BLE 连接,维护 Bit0/1/2,已配网断连时开回连广播
+ * @note - 配网中(phase==PAIRING)由配网业务维护,此处不覆盖
+ * - 已配网:已连接→CONFIGURED,未连接→RECONNECTING
+ * - Bit3~5 预留固定 0,不在此处更新
+ */
+void mcu_link_status_periodic(void)
+{
+ uint8_t conn = (usr_get_conn_service() != 0) ? 1 : 0;
+ uint8_t paired = usr_get_pair_flag();
+
+ if (conn != s_status.last_ble_conn) {
+ s_status.last_ble_conn = conn;
+
+ if (!conn && paired) {
+ /* 已配网断连:发回连广播(非绑定广播) */
+ usr_var.usr_goto_pair = 0;
+ if (mcu_identity_is_ready()) {
+ usr_ble_adv_init();
+ }
+ }
+ }
+
+ if (mcu_link_status_get_phase() == MCU_WS_PAIRING) {
+ return; /* 配网流程中不切换到回连/已配网 */
+ }
+
+ if (paired) {
+ mcu_link_status_set_phase(conn ? MCU_WS_CONFIGURED : MCU_WS_RECONNECTING);
+ } else {
+ mcu_link_status_set_phase(0); /* 未配网空闲 */
+ }
+}
diff --git a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_link_status.h b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_link_status.h
new file mode 100644
index 0000000..a0be37c
--- /dev/null
+++ b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_link_status.h
@@ -0,0 +1,53 @@
+/******************************************************************************
+ * @file mcu_link_status.h
+ * @brief 连接状态业务:工作状态位图(Bit0/1/2 互斥过程态 + OTA 位)
+ * @author cyWu <1917507415@qq.com>
+ * @date 2026.08.12
+ * @version V1.0.0
+ * @history
+ * - V1.0.0, 2026.08.12, cyWu, 从 mcu_link 拆出,独立为连接状态业务模块
+ ******************************************************************************/
+
+#ifndef __MCU_LINK_STATUS_H__
+#define __MCU_LINK_STATUS_H__
+
+#include
+
+/**
+ * @brief 初始化连接状态
+ */
+void mcu_link_status_init(void);
+
+/**
+ * @brief 周期处理:轮询 BLE 连接,维护 Bit0/1/2,已配网断连时触发回连广播
+ * @note 配网中(phase==PAIRING)时不会被本函数覆盖
+ */
+void mcu_link_status_periodic(void);
+
+/**
+ * @brief 获取完整工作状态字节(命令 0x14 载荷)
+ * @return work_status
+ */
+uint8_t mcu_link_status_get(void);
+
+/**
+ * @brief 获取当前 Bit0/1/2 互斥过程态
+ * @return MCU_WS_PAIRING / MCU_WS_CONFIGURED / MCU_WS_RECONNECTING / 0
+ */
+uint8_t mcu_link_status_get_phase(void);
+
+/**
+ * @brief 设置 Bit0/1/2 互斥过程态
+ * @param phase MCU_WS_PAIRING / MCU_WS_CONFIGURED / MCU_WS_RECONNECTING / 0
+ * @note 只改 Bit0/1/2,不影响 Bit6 OTA 等独立位
+ */
+void mcu_link_status_set_phase(uint8_t phase);
+
+/**
+ * @brief 设置/清除 Bit6 OTA 升级中
+ * @param on 1=置位,0=清除
+ * @note 预留给后续 OTA 模块调用
+ */
+void mcu_link_status_set_ota(uint8_t on);
+
+#endif /* __MCU_LINK_STATUS_H__ */
diff --git a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_pairing.c b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_pairing.c
new file mode 100644
index 0000000..6a6bae9
--- /dev/null
+++ b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_pairing.c
@@ -0,0 +1,108 @@
+/******************************************************************************
+ * @file mcu_pairing.c
+ * @brief 配网业务实现
+ * @author cyWu <1917507415@qq.com>
+ * @date 2026.08.12
+ * @version V1.0.0
+ * @history
+ * - V1.0.0, 2026.08.12, cyWu, 从 mcu_link 拆出
+ ******************************************************************************/
+
+#include "system/includes.h"
+#include "app_main.h"
+#include "mcu_pairing.h"
+#include "mcu_link_status.h"
+#include "mcu_cmd.h"
+#include "mcu_util.h"
+#include "usr_le_api.h"
+
+#define LOG_TAG_CONST APP
+#define LOG_TAG "[MCU_PAIR]"
+#define LOG_ERROR_ENABLE
+#define LOG_DEBUG_ENABLE
+#define LOG_INFO_ENABLE
+#include "debug.h"
+
+/*============================================================================*/
+/* 外部符号 */
+/*============================================================================*/
+
+extern void ble_trans_module_enable(u8 flag);
+
+/*============================================================================*/
+/* 私有变量 */
+/*============================================================================*/
+
+typedef struct {
+ uint16_t timeout_s;
+ uint32_t start_ms;
+} McuPairing_t;
+
+static McuPairing_t s_pairing;
+
+/*============================================================================*/
+/* 公有函数 */
+/*============================================================================*/
+
+/**
+ * @brief 初始化配网业务状态
+ */
+void mcu_pairing_init(void)
+{
+ memset(&s_pairing, 0, sizeof(s_pairing));
+}
+
+/**
+ * @brief 开始配网
+ * @param mode 模式(预留)
+ * @param timeout_s 超时秒数
+ */
+void mcu_pairing_start(uint8_t mode, uint16_t timeout_s)
+{
+ s_pairing.timeout_s = timeout_s;
+ s_pairing.start_ms = mcu_util_get_ms();
+ mcu_link_status_set_phase(MCU_WS_PAIRING);
+
+ log_info("pairing start mode=%u timeout=%u", mode, timeout_s);
+ usr_goto_pair_mode(); /* 清配对 + 置 usr_goto_pair + 发绑定广播 */
+}
+
+/**
+ * @brief 停止配网计时
+ */
+void mcu_pairing_stop(void)
+{
+ s_pairing.timeout_s = 0;
+}
+
+/**
+ * @brief 配网超时检测
+ */
+void mcu_pairing_periodic(void)
+{
+ uint32_t now;
+ uint32_t timeout_ms;
+
+ if (mcu_link_status_get_phase() != MCU_WS_PAIRING) {
+ return;
+ }
+ if (s_pairing.timeout_s == 0) {
+ return;
+ }
+ if (usr_get_pair_flag()) {
+ return; /* 已配网成功,交由 mcu_business_on_paired 处理切态 */
+ }
+
+ now = mcu_util_get_ms();
+ timeout_ms = (uint32_t)s_pairing.timeout_s * 1000u;
+ if ((now - s_pairing.start_ms) < timeout_ms) {
+ return;
+ }
+
+ log_info("pairing timeout, stop adv");
+ usr_var.usr_goto_pair = 0;
+ s_pairing.timeout_s = 0;
+ mcu_link_status_set_phase(0);
+ ble_trans_module_enable(0);
+ usr_var.usr_adv_flag = 0;
+}
diff --git a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_pairing.h b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_pairing.h
new file mode 100644
index 0000000..5eff9ff
--- /dev/null
+++ b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_pairing.h
@@ -0,0 +1,40 @@
+/******************************************************************************
+ * @file mcu_pairing.h
+ * @brief 配网业务:0x10 配网请求处理、配网超时退出
+ * @author cyWu <1917507415@qq.com>
+ * @date 2026.08.12
+ * @version V1.0.0
+ * @history
+ * - V1.0.0, 2026.08.12, cyWu, 从 mcu_link 拆出,独立为配网业务模块
+ ******************************************************************************/
+
+#ifndef __MCU_PAIRING_H__
+#define __MCU_PAIRING_H__
+
+#include
+
+/**
+ * @brief 初始化配网业务状态
+ */
+void mcu_pairing_init(void);
+
+/**
+ * @brief 周期处理:配网超时检测
+ * @note 仅在 mcu_link_status_get_phase()==MCU_WS_PAIRING 时生效
+ */
+void mcu_pairing_periodic(void);
+
+/**
+ * @brief 开始配网(协议层已完成参数校验与 ACK)
+ * @param mode 1 或 2(预留,当前两种模式行为一致)
+ * @param timeout_s 超时秒数,0 表示不超时
+ * @note 置 Bit0=配网中,并触发绑定广播(usr_goto_pair_mode)
+ */
+void mcu_pairing_start(uint8_t mode, uint16_t timeout_s);
+
+/**
+ * @brief 停止配网计时(配网成功后调用)
+ */
+void mcu_pairing_stop(void);
+
+#endif /* __MCU_PAIRING_H__ */
diff --git a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/mcu_bridge.c b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/mcu_bridge.c
index 7a3ec29..3facdc4 100644
--- a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/mcu_bridge.c
+++ b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/mcu_bridge.c
@@ -1,1097 +1,86 @@
/******************************************************************************
* @file mcu_bridge.c
- * @brief BLE+MCU 协议桥 P0 实现
+ * @brief BLE+MCU 接入模块对外总入口实现(组合门面,仅转调)
* @author cyWu <1917507415@qq.com>
- * @date 2026.08.06
- * @version V1.3.0
+ * @date 2026.08.12
+ * @version V2.0.0
* @history
* - V1.0.0, 2026.08.06, cyWu, 首次发布
- * - V1.1.0, 2026.08.06, cyWu, 改为事件队列 + 独立任务驱动,
- * 彻底消除跨任务共享状态的竞态(UART 接收任务 / BLE 协议栈任务 /
- * 原 sys_timer 回调三方并发访问 s_br 的问题)
- * - V1.2.0, 2026.08.10, cyWu, 注册 LP target:桥接忙时禁止进低功耗,
- * 空闲可睡,配合板级 SLEEP_EN 恢复串口方案下的低功耗
+ * - V1.1.0, 2026.08.06, cyWu, 改为事件队列 + 独立任务驱动
+ * - V1.2.0, 2026.08.10, cyWu, 注册 LP target
* - V1.3.0, 2026.08.11, cyWu, 周期递减 UART RX 防睡标志
+ * - V1.4.0, 2026.08.12, cyWu, 工作状态 Bit0/1/2 互斥
+ * - V2.0.0, 2026.08.12, cyWu, 拆分为 protocol/ + business/ 分层,
+ * 本文件收敛为纯组合门面,不再持有任何状态
******************************************************************************/
-#include "system/includes.h"
-#include "asm/power/power_api.h"
-#include "app_main.h"
#include "mcu_bridge.h"
-#include "mcu_uart.h"
-#include "mcu_frame.h"
-#include "usr_le_api.h"
-#include "usr_le_product.h"
-#include "mcu_util.h"
-
-#define LOG_TAG_CONST APP
-#define LOG_TAG "[MCU_BR]"
-#define LOG_ERROR_ENABLE
-#define LOG_DEBUG_ENABLE
-#define LOG_INFO_ENABLE
-#define LOG_DUMP_ENABLE
-#define LOG_CLI_ENABLE
-#include "debug.h"
-
-/*============================================================================*/
-/* 私有宏 */
-/*============================================================================*/
-
-#define MCU_IDENTITY_RETRY_MS (1000u) /* 0x01 轮询间隔 */
-#define MCU_HEARTBEAT_IDLE_MS (55000u) /* 无 MCU 数据超时发心跳 */
-#define MCU_HEARTBEAT_WAIT_MS (2500u) /* 心跳应答等待 */
-#define MCU_HEARTBEAT_MAX_RETRY (3u)
-#define MCU_APP_ACK_WAIT_MS (2500u) /* APP 透传等 MCU ACK */
-#define MCU_APP_ACK_MAX_RETRY (3u)
-#define MCU_REPORT_GW_WAIT_MS (3000u) /* MCU 上报等网关 ACK */
-#define MCU_REPORT_GW_MAX_RETRY (3u)
-#define MCU_IDENTITY_PAYLOAD_MIN (2 + 8 + 8 + 16 + 8) /* Ver+Cat+Prod+SN+Cap */
-
-#define MCU_BRIDGE_TICK_MS (200u) /* 期望的兜底轮询周期(毫秒) */
-/* 杰理 os_sem_pend 超时单位是 OS tick,OS_TICKS_PER_SEC=100 → 1 tick = 10ms */
-#define MCU_BRIDGE_TICK_OS ((MCU_BRIDGE_TICK_MS + 9u) / 10u)
-#define MCU_EVT_QUEUE_DEPTH (8u) /* 事件队列深度 */
-#define MCU_BRIDGE_TASK_PRIO (31u)
-/* 周期逻辑有 MCU_FRAME_MAX_LEN 局部缓冲;BLE 回传大结构已改为 static,2KB 留余量 */
-#define MCU_BRIDGE_TASK_STACK (2048u)
-
-/*============================================================================*/
-/* 外部符号 */
-/*============================================================================*/
-
-extern void ble_trans_module_enable(u8 flag);
-extern u16 usr_get_conn_service(void);
-
-/* 运行时可改写的产品身份(供广播使用) */
-uint8_t g_usr_le_prodcode[USR_LE_PRODCODE_LEN];
-uint8_t g_usr_le_pcode[USR_LE_PCODE_LEN];
-
-/*============================================================================*/
-/* 私有类型 */
-/*============================================================================*/
-
-typedef struct {
- uint8_t active;
- uint8_t sn;
- uint8_t expect_ack; /* 期望的 ACK 命令 */
- uint8_t retry;
- uint32_t send_time;
- uint8_t buf[MCU_FRAME_MAX_LEN];
- uint16_t len;
-} McuPending_t;
+#include "mcu_protocol.h"
+#include "mcu_business.h"
/**
- * @brief 桥接层内部事件类型
- * @note 所有跨任务(UART 接收任务 / BLE 协议栈任务)产生的输入,
- * 都封装为事件投递到队列,只在 mcu_bridge_task 单一上下文中
- * 消费处理,从而避免对 s_br 的并发访问。
- */
-typedef enum {
- MCU_EVT_UART_FRAME = 0, /* MCU 经 UART 送来的完整合法帧 */
- MCU_EVT_APP_FRAME, /* APP/网关经 BLE 下发的 55AA 帧 */
- MCU_EVT_GATEWAY_ACK, /* 网关对 MCU 上报(0x07)的应答 */
- MCU_EVT_BLE_PAIRED, /* AUTHSETUP 成功(配网完成) */
- MCU_EVT_BLE_PAIR_CLEARED /* 配对信息被清除 */
-} McuEvtType_t;
-
-typedef struct {
- McuEvtType_t type;
- uint16_t len;
- uint8_t buf[MCU_FRAME_MAX_LEN];
- uint16_t gw_cmd;
- uint8_t gw_int_cnt;
- int32_t gw_int0;
-} McuEvt_t;
-
-typedef struct {
- uint8_t initialized;
- uint8_t identity_ready;
- uint8_t identity_adv_pending; /* 身份刚就绪,待刷新广播 */
- uint8_t sn;
- uint8_t work_status;
- uint8_t last_pushed_status;
- uint8_t hb_fail_cnt;
- uint8_t hb_waiting;
- uint8_t mcu_comm_alarm;
- uint8_t last_ble_conn;
- uint16_t pair_timeout_s;
- uint32_t pair_start_ms;
- uint32_t last_mcu_rx_ms;
- uint32_t last_identity_tx_ms;
- uint32_t last_hb_tx_ms;
- McuPending_t app_pending; /* APP→MCU 透传等待 */
- McuPending_t ble_pending; /* BLE 主动请求等待(心跳/状态等) */
- McuPending_t report_pending; /* MCU 0x07 上报,等网关 ACK 后再回 0x08 */
-} McuBridge_t;
-
-/*============================================================================*/
-/* 私有变量 */
-/*============================================================================*/
-
-/* 业务状态:仅由 mcu_bridge_task 单一任务上下文读写,天然无竞态 */
-static McuBridge_t s_br;
-static uint8_t s_parse_out[MCU_FRAME_MAX_LEN];
-
-/*
- * 低功耗空闲查询:桥接任务处理事件/周期逻辑时置 1,禁止进 sleep;
- * pend 等待期间置 0,允许系统进入低功耗。由 idle 任务跨上下文读取,故用 volatile。
- */
-static volatile u8 s_bridge_busy = 0;
-
-/**
- * @brief 事件队列:环形缓冲 + 同步原语的集合
- * @note 生产者可来自任意任务(UART 接收任务 / BLE 协议栈任务),
- * 消费者固定为 mcu_bridge_task。lock 只保护本结构体自身的
- * 入队/出队操作,不涉及业务逻辑,因此临界区极短。
- */
-typedef struct {
- McuEvt_t queue[MCU_EVT_QUEUE_DEPTH];
- uint8_t head; /* 下一个可取出的位置 */
- uint8_t tail; /* 下一个可写入的位置 */
- uint8_t count; /* 当前事件个数 */
- OS_MUTEX lock; /* 保护 queue/head/tail/count 四个字段 */
- OS_SEM sem; /* 有新事件入队时唤醒 mcu_bridge_task */
-} McuEvtQueue_t;
-
-static McuEvtQueue_t s_evt_q;
-
-/*============================================================================*/
-/* 私有函数声明 */
-/*============================================================================*/
-
-static uint8_t mcu_bridge_next_sn(void);
-static int32_t mcu_bridge_send_frame(uint8_t cmd, uint8_t sn,
- const uint8_t *payload, uint16_t plen);
-static void mcu_bridge_send_ack(uint8_t cmd, uint8_t sn, uint8_t result);
-static void mcu_bridge_handle_frame(const uint8_t *frame, uint16_t len);
-static void mcu_bridge_handle_identity_ack(const uint8_t *frame, uint16_t len);
-static void mcu_bridge_handle_pair_cfg(const uint8_t *frame, uint16_t len);
-static void mcu_bridge_handle_report(const uint8_t *frame, uint16_t len);
-static void mcu_bridge_handle_app_frame(const uint8_t *data, uint16_t len);
-static void mcu_bridge_handle_gateway_ack(uint16_t cmd, uint8_t gateway_int_cnt,
- int32_t gateway_int0);
-static void mcu_bridge_handle_paired(void);
-static void mcu_bridge_handle_pair_cleared(void);
-static void mcu_bridge_try_identity(void);
-static void mcu_bridge_try_heartbeat(void);
-static void mcu_bridge_try_work_status(void);
-static void mcu_bridge_update_conn_bits(void);
-static void mcu_bridge_check_pair_timeout(void);
-static void mcu_bridge_check_app_pending(void);
-static void mcu_bridge_check_ble_pending(void);
-static void mcu_bridge_check_report_pending(void);
-static void mcu_bridge_set_ws_bit(uint8_t bit, uint8_t on);
-static void mcu_bridge_periodic(void);
-static uint8_t mcu_bridge_post_event(const McuEvt_t *evt);
-static uint8_t mcu_bridge_pop_event(McuEvt_t *evt);
-static void mcu_bridge_dispatch_event(const McuEvt_t *evt);
-static void mcu_bridge_task(void *arg);
-
-/*============================================================================*/
-/* 私有函数 */
-/*============================================================================*/
-
-/**
- * @brief 投递一个事件到队列并唤醒 mcu_bridge_task
- * @param evt 事件内容(按值拷贝入队)
- * @return 1=成功,0=队列已满被丢弃
- * @note 可从任意任务上下文调用(UART 接收任务 / BLE 协议栈任务等)
- */
-static uint8_t mcu_bridge_post_event(const McuEvt_t *evt)
-{
- uint8_t ok = 0;
-
- os_mutex_pend(&s_evt_q.lock, 0);
- if (s_evt_q.count < MCU_EVT_QUEUE_DEPTH) {
- s_evt_q.queue[s_evt_q.tail] = *evt;
- s_evt_q.tail = (uint8_t)((s_evt_q.tail + 1) % MCU_EVT_QUEUE_DEPTH);
- s_evt_q.count++;
- ok = 1;
- }
- os_mutex_post(&s_evt_q.lock);
-
- if (ok) {
- os_sem_post(&s_evt_q.sem);
- } else {
- log_error("event queue full, drop type=%d", evt->type);
- }
- return ok;
-}
-
-/**
- * @brief 从队列取出一个事件
- * @param evt 输出事件
- * @return 1=取到,0=队列为空
- * @note 仅由 mcu_bridge_task 调用
- */
-static uint8_t mcu_bridge_pop_event(McuEvt_t *evt)
-{
- uint8_t ok = 0;
-
- os_mutex_pend(&s_evt_q.lock, 0);
- if (s_evt_q.count > 0) {
- *evt = s_evt_q.queue[s_evt_q.head];
- s_evt_q.head = (uint8_t)((s_evt_q.head + 1) % MCU_EVT_QUEUE_DEPTH);
- s_evt_q.count--;
- ok = 1;
- }
- os_mutex_post(&s_evt_q.lock);
- return ok;
-}
-
-/**
- * @brief 事件分发:将队列事件转交给对应业务处理函数
- * @param evt 事件
- * @note 仅在 mcu_bridge_task 上下文执行,s_br 在此单一上下文内读写
- */
-static void mcu_bridge_dispatch_event(const McuEvt_t *evt)
-{
- switch (evt->type) {
- case MCU_EVT_UART_FRAME:
- mcu_bridge_handle_frame(evt->buf, evt->len);
- break;
- case MCU_EVT_APP_FRAME:
- mcu_bridge_handle_app_frame(evt->buf, evt->len);
- break;
- case MCU_EVT_GATEWAY_ACK:
- mcu_bridge_handle_gateway_ack(evt->gw_cmd, evt->gw_int_cnt, evt->gw_int0);
- break;
- case MCU_EVT_BLE_PAIRED:
- mcu_bridge_handle_paired();
- break;
- case MCU_EVT_BLE_PAIR_CLEARED:
- mcu_bridge_handle_pair_cleared();
- break;
- default:
- log_error("unknown evt type=%d", evt->type);
- break;
- }
-}
-
-/**
- * @brief 桥接层主任务:事件驱动 + 兜底轮询
- * @param arg 未使用
- * @note 唯一读写 s_br 的任务上下文;醒来时机 = 有新事件 或 每
- * MCU_BRIDGE_TICK_MS 兜底一次,用于身份轮询/心跳/超时重传等。
- * 处理期间通过 LP target 挡住系统休眠,避免 UART TX/DMA 异常。
- */
-static void mcu_bridge_task(void *arg)
-{
- McuEvt_t evt;
-
- (void)arg;
- log_info("bridge task start");
-
- while (1) {
- /* 有事件立刻醒;空闲时约每 MCU_BRIDGE_TICK_MS 醒一次做周期检查 */
- os_sem_pend(&s_evt_q.sem, (int)MCU_BRIDGE_TICK_OS);
-
- s_bridge_busy = 1;
- while (mcu_bridge_pop_event(&evt)) {
- mcu_bridge_dispatch_event(&evt);
- }
- mcu_bridge_periodic();
- s_bridge_busy = 0;
- }
-}
-
-/**
- * @brief 低功耗空闲查询:桥接忙则不允许进 sleep
- * @return 1=可进低功耗,0=保持唤醒
- */
-static u8 mcu_bridge_lp_idle_query(void)
-{
- return s_bridge_busy ? 0 : 1;
-}
-
-REGISTER_LP_TARGET(mcu_bridge_lp_target) = {
- .name = "mcu_bridge",
- .is_idle = mcu_bridge_lp_idle_query,
-};
-
-/**
- * @brief 取下一个序列号
- * @return SN
- */
-static uint8_t mcu_bridge_next_sn(void)
-{
- return s_br.sn++;
-}
-
-/**
- * @brief 组帧并通过 UART 发给 MCU
- * @param cmd 命令
- * @param sn 序列号
- * @param payload 数据
- * @param plen 长度
- * @return 帧长;<0 失败
- */
-static int32_t mcu_bridge_send_frame(uint8_t cmd, uint8_t sn,
- const uint8_t *payload, uint16_t plen)
-{
- uint8_t buf[MCU_FRAME_MAX_LEN];
- int32_t total;
-
- total = mcu_frame_pack(buf, sizeof(buf), cmd, sn, payload, plen);
- if (total <= 0) {
- return -1;
- }
- if (mcu_uart_send(buf, (uint16_t)total) != MCU_UART_OK) {
- return -1;
- }
- log_debug("MCU TX cmd=0x%02X sn=%u len=%d", cmd, sn, (int)total);
- return total;
-}
-
-/**
- * @brief 发送仅含 Result 的 ACK 帧给 MCU
- * @param cmd ACK 命令字
- * @param sn 序列号
- * @param result 结果码
- */
-static void mcu_bridge_send_ack(uint8_t cmd, uint8_t sn, uint8_t result)
-{
- mcu_bridge_send_frame(cmd, sn, &result, 1);
-}
-
-/**
- * @brief 设置/清除工作状态位
- * @param bit 位掩码
- * @param on 1=置位,0=清位
- */
-static void mcu_bridge_set_ws_bit(uint8_t bit, uint8_t on)
-{
- if (on) {
- s_br.work_status |= bit;
- } else {
- s_br.work_status &= (uint8_t)~bit;
- }
-}
-
-/**
- * @brief 处理 0x02 身份应答
- * @param frame 完整帧
- * @param len 长度
- * @note 载荷布局(Result 之后):Ver(2)+Category(8)+Product(8)+SN(16)+Cap(8)
- */
-static void mcu_bridge_handle_identity_ack(const uint8_t *frame, uint16_t len)
-{
- if (len < 7) {
- return;
- }
- if (frame[6] != MCU_RESULT_OK) {
- log_error("identity ack result=0x%02X", frame[6]);
- return;
- }
- if (len < (7 + MCU_IDENTITY_PAYLOAD_MIN + 1)) {
- log_error("identity ack too short %u", len);
- return;
- }
-
- /* Category Code 在 Result(frame[6]) 后偏移 Ver(2),取前 4;
- * Product Code 再后 Category(8),取前 6 */
- memcpy(g_usr_le_prodcode, &frame[7 + 2], USR_LE_PRODCODE_LEN);
- memcpy(g_usr_le_pcode, &frame[7 + 2 + 8], USR_LE_PCODE_LEN);
-
- s_br.identity_ready = 1;
- s_br.identity_adv_pending = 1;
- log_info("identity ok prodcode:");
- log_info_hexdump(g_usr_le_prodcode, USR_LE_PRODCODE_LEN);
- log_info("identity ok pcode:");
- log_info_hexdump(g_usr_le_pcode, USR_LE_PCODE_LEN);
-
- /* 置位后由 mcu_bridge_periodic 刷新广播 */
- s_br.last_pushed_status = 0xFF;
-}
-
-/**
- * @brief 处理 0x10 配网请求
- * @param frame 完整帧
- * @param len 长度
- */
-static void mcu_bridge_handle_pair_cfg(const uint8_t *frame, uint16_t len)
-{
- uint8_t sn;
- uint8_t mode;
- uint16_t timeout_s;
-
- if (len < 10) {
- return;
- }
- sn = frame[5];
- mode = frame[6];
- timeout_s = mcu_util_read_u16_be(&frame[7]);
-
- if (mode != 1 && mode != 2) {
- mcu_bridge_send_ack(MCU_CMD_PAIR_CFG_ACK, sn, MCU_RESULT_PARAM_ERR);
- return;
- }
- if (!s_br.identity_ready) {
- mcu_bridge_send_ack(MCU_CMD_PAIR_CFG_ACK, sn, MCU_RESULT_BUSY);
- return;
- }
-
- s_br.pair_timeout_s = timeout_s;
- s_br.pair_start_ms = mcu_util_get_ms();
- mcu_bridge_set_ws_bit(MCU_WS_PAIRING_MODE, 1);
- mcu_bridge_set_ws_bit(MCU_WS_CONFIGURED, 0);
-
- mcu_bridge_send_ack(MCU_CMD_PAIR_CFG_ACK, sn, MCU_RESULT_OK);
-
- /* 重新配网:清配对并开绑定广播(非回连) */
- log_info("MCU pair cfg mode=%u timeout=%u", mode, timeout_s);
- usr_goto_pair_mode();
-}
-
-/**
- * @brief 处理 MCU 主动上报 0x07
- * @param frame 完整帧
- * @param len 长度
- * @note 先转发网关;收到 REPORTCMD_V2 成功应答后再回 MCU 0x08
- */
-static void mcu_bridge_handle_report(const uint8_t *frame, uint16_t len)
-{
- uint8_t sn = frame[5];
-
- if (s_br.report_pending.active) {
- log_error("report busy, drop sn=%u", sn);
- mcu_bridge_send_ack(MCU_CMD_REPORT_ACK, sn, MCU_RESULT_BUSY);
- return;
- }
- if (len > sizeof(s_br.report_pending.buf)) {
- mcu_bridge_send_ack(MCU_CMD_REPORT_ACK, sn, MCU_RESULT_PARAM_ERR);
- return;
- }
-
- memcpy(s_br.report_pending.buf, frame, len);
- s_br.report_pending.len = len;
- s_br.report_pending.sn = sn;
- s_br.report_pending.expect_ack = MCU_CMD_REPORT_ACK; /* 最终要回给 MCU 的命令 */
- s_br.report_pending.retry = 0;
- s_br.report_pending.send_time = mcu_util_get_ms();
- s_br.report_pending.active = 1;
-
- /* 先上报网关,暂不回 MCU 0x08 */
- usr_le_send_mcu_frame(s_br.report_pending.buf, s_br.report_pending.len);
- log_debug("MCU report sn=%u -> gateway, wait ACK", sn);
-}
-
-/**
- * @brief 分发一帧完整 MCU 协议
- * @param frame 完整帧
- * @param len 长度
- */
-static void mcu_bridge_handle_frame(const uint8_t *frame, uint16_t len)
-{
- uint8_t cmd;
- uint8_t sn;
-
- if (!frame || len < 6) {
- return;
- }
-
- s_br.last_mcu_rx_ms = mcu_util_get_ms();
- s_br.hb_fail_cnt = 0;
- s_br.hb_waiting = 0;
- s_br.mcu_comm_alarm = 0;
-
- cmd = frame[4];
- sn = frame[5];
- log_debug("MCU RX cmd=0x%02X sn=%u len=%u", cmd, sn, len);
-
- /* APP 透传等待的 ACK */
- if (s_br.app_pending.active &&
- (cmd == s_br.app_pending.expect_ack) &&
- (sn == s_br.app_pending.sn)) {
- s_br.app_pending.active = 0;
- usr_le_send_mcu_frame((u8 *)frame, len);
- return;
- }
-
- /* BLE 主动请求的 ACK(心跳/状态) */
- if (s_br.ble_pending.active &&
- (cmd == s_br.ble_pending.expect_ack) &&
- (sn == s_br.ble_pending.sn)) {
- s_br.ble_pending.active = 0;
- if (cmd == MCU_CMD_HEARTBEAT_ACK) {
- s_br.hb_waiting = 0;
- s_br.hb_fail_cnt = 0;
- }
- return;
- }
-
- switch (cmd) {
- case MCU_CMD_GET_IDENTITY_ACK:
- mcu_bridge_handle_identity_ack(frame, len);
- break;
- case MCU_CMD_PAIR_CFG:
- mcu_bridge_handle_pair_cfg(frame, len);
- break;
- case MCU_CMD_REPORT:
- mcu_bridge_handle_report(frame, len);
- break;
- case MCU_CMD_CONTROL_ACK:
- case MCU_CMD_READ_ACK:
- /* 无匹配 pending 时仍尝试转发给 APP(容错) */
- usr_le_send_mcu_frame((u8 *)frame, len);
- break;
- case MCU_CMD_HEARTBEAT_ACK:
- case MCU_CMD_WORK_STATUS_ACK:
- break;
- default:
- /* P0 未实现:回不支持(仅对 MCU→BLE 请求类) */
- if (cmd == MCU_CMD_RESET || cmd == MCU_CMD_REBOOT ||
- cmd == MCU_CMD_GET_TIME || cmd == MCU_CMD_FACTORY ||
- cmd == MCU_CMD_PHOTO || cmd == MCU_CMD_RECORD ||
- cmd == MCU_CMD_AUDIO) {
- mcu_bridge_send_ack((uint8_t)(cmd + 1), sn, MCU_RESULT_NOT_SUPPORT);
- }
- break;
- }
-}
-
-/**
- * @brief 处理 APP/网关经 BLE 下发的 55AA 帧
- * @param data 帧数据
- * @param len 长度
- */
-static void mcu_bridge_handle_app_frame(const uint8_t *data, uint16_t len)
-{
- uint8_t cmd;
- uint8_t sn;
- uint8_t expect_ack;
-
- cmd = data[4];
- sn = data[5];
-
- if (cmd == MCU_CMD_CONTROL) {
- expect_ack = MCU_CMD_CONTROL_ACK;
- } else if (cmd == MCU_CMD_READ) {
- expect_ack = MCU_CMD_READ_ACK;
- } else {
- /* 其它命令 P0:原样转发,不等待(后续 OTA 等再扩展) */
- mcu_uart_send(data, len);
- return;
- }
-
- if (s_br.app_pending.active) {
- log_error("app frame busy, drop cmd=0x%02X", cmd);
- return;
- }
-
- memcpy(s_br.app_pending.buf, data, len);
- s_br.app_pending.len = len;
- s_br.app_pending.sn = sn;
- s_br.app_pending.expect_ack = expect_ack;
- s_br.app_pending.retry = 0;
- s_br.app_pending.send_time = mcu_util_get_ms();
- s_br.app_pending.active = 1;
-
- mcu_uart_send(data, len);
- log_debug("app->mcu forward cmd=0x%02X sn=%u wait 0x%02X",
- cmd, sn, expect_ack);
-}
-
-/**
- * @brief 处理网关对 REPORTCMD_V2 主动上报的应答
- * @param cmd bleproto 包 cmd
- * @param gateway_int_cnt gateway_int 个数
- * @param gateway_int0 gateway_int[0]
- * @note 成功条件:cmd==0 && cnt==1 && int0==0;成功后才向 MCU 回 0x08
- */
-static void mcu_bridge_handle_gateway_ack(uint16_t cmd,
- uint8_t gateway_int_cnt,
- int32_t gateway_int0)
-{
- uint8_t sn;
-
- if (!s_br.report_pending.active) {
- return;
- }
-
- /* 与旧 SOC jbReportAckCheck 成功条件一致 */
- if (cmd == 0 && gateway_int_cnt == 1 && gateway_int0 == 0) {
- sn = s_br.report_pending.sn;
- mcu_bridge_send_ack(MCU_CMD_REPORT_ACK, sn, MCU_RESULT_OK);
- s_br.report_pending.active = 0;
- log_info("gateway report ack ok, MCU 0x08 sn=%u", sn);
- return;
- }
-
- log_error("gateway report ack fail cmd=%u cnt=%u int0=%ld",
- (unsigned)cmd, (unsigned)gateway_int_cnt, (long)gateway_int0);
- /* 失败暂不立刻回 MCU,留给超时重试 */
-}
-
-/**
- * @brief 处理配网成功通知
- */
-static void mcu_bridge_handle_paired(void)
-{
- usr_var.usr_goto_pair = 0;
- mcu_bridge_set_ws_bit(MCU_WS_CONFIGURED, 1);
- mcu_bridge_set_ws_bit(MCU_WS_PAIRING_MODE, 0);
- /* Bit1/2/3 预留:INTERNET / APP_ONLINE / BLE_CONNECTED 暂固定为 0 */
- log_info("mcu_bridge_handle_paired");
-}
-
-/**
- * @brief 处理配对信息被清除通知
- */
-static void mcu_bridge_handle_pair_cleared(void)
-{
- mcu_bridge_set_ws_bit(MCU_WS_CONFIGURED, 0);
-}
-
-/**
- * @brief 身份未就绪时每 1s 发 0x01
- */
-static void mcu_bridge_try_identity(void)
-{
- uint32_t now;
- uint8_t sn;
- int32_t total;
-
- if (s_br.identity_ready) {
- return;
- }
-
- now = mcu_util_get_ms();
- if ((now - s_br.last_identity_tx_ms) < MCU_IDENTITY_RETRY_MS) {
- return;
- }
- s_br.last_identity_tx_ms = now;
-
- sn = mcu_bridge_next_sn();
- total = mcu_bridge_send_frame(MCU_CMD_GET_IDENTITY, sn, NULL, 0);
- if (total > 0) {
- log_debug("identity req sn=%u", sn);
- }
-}
-
-/**
- * @brief 心跳检测与发送
- */
-static void mcu_bridge_try_heartbeat(void)
-{
- uint32_t now = mcu_util_get_ms();
- uint8_t sn;
- uint8_t buf[MCU_FRAME_MAX_LEN];
- int32_t total;
-
- if (!s_br.identity_ready) {
- return;
- }
-
- if (s_br.hb_waiting) {
- if ((now - s_br.last_hb_tx_ms) <= MCU_HEARTBEAT_WAIT_MS) {
- return;
- }
- s_br.hb_waiting = 0;
- s_br.ble_pending.active = 0;
- s_br.hb_fail_cnt++;
- log_error("heartbeat timeout fail=%u", s_br.hb_fail_cnt);
- if (s_br.hb_fail_cnt >= MCU_HEARTBEAT_MAX_RETRY) {
- s_br.mcu_comm_alarm = 1;
- log_error("MCU comm alarm");
- /* 告警后重新计时,避免狂打心跳 */
- s_br.last_mcu_rx_ms = now;
- return;
- }
- /* 未达 3 次:立即再发一帧心跳 */
- } else if ((now - s_br.last_mcu_rx_ms) < MCU_HEARTBEAT_IDLE_MS) {
- return;
- }
-
- sn = mcu_bridge_next_sn();
- total = mcu_frame_pack(buf, sizeof(buf), MCU_CMD_HEARTBEAT, sn, NULL, 0);
- if (total <= 0) {
- return;
- }
- if (mcu_uart_send(buf, (uint16_t)total) != MCU_UART_OK) {
- return;
- }
-
- s_br.ble_pending.active = 1;
- s_br.ble_pending.sn = sn;
- s_br.ble_pending.expect_ack = MCU_CMD_HEARTBEAT_ACK;
- s_br.ble_pending.send_time = now;
- s_br.ble_pending.retry = 0;
- s_br.last_hb_tx_ms = now;
- s_br.hb_waiting = 1;
- log_debug("heartbeat tx sn=%u", sn);
-}
-
-/**
- * @brief 工作状态变化时推送 0x14
- */
-static void mcu_bridge_try_work_status(void)
-{
- uint8_t payload[2];
- uint8_t sn;
- uint8_t buf[MCU_FRAME_MAX_LEN];
- int32_t total;
- uint32_t now;
-
- if (!s_br.identity_ready) {
- return;
- }
- if (s_br.work_status == s_br.last_pushed_status) {
- return;
- }
- if (s_br.ble_pending.active) {
- return; /* 避免与心跳等抢占 */
- }
-
- payload[0] = s_br.work_status;
- payload[1] = 0x00; /* RSSI 占位,后续可接真实信号强度 */
-
- sn = mcu_bridge_next_sn();
- total = mcu_frame_pack(buf, sizeof(buf), MCU_CMD_WORK_STATUS, sn, payload, 2);
- if (total <= 0) {
- return;
- }
- if (mcu_uart_send(buf, (uint16_t)total) != MCU_UART_OK) {
- return;
- }
-
- now = mcu_util_get_ms();
- s_br.ble_pending.active = 1;
- s_br.ble_pending.sn = sn;
- s_br.ble_pending.expect_ack = MCU_CMD_WORK_STATUS_ACK;
- s_br.ble_pending.send_time = now;
- s_br.last_pushed_status = s_br.work_status;
- log_info("work_status push 0x%02X", s_br.work_status);
-}
-
-/**
- * @brief 轮询 BLE 连接,维护 Bit5,并在已配网断连时开回连广播
- * @note - Bit1/2/3(INTERNET / APP_ONLINE / BLE_CONNECTED)预留,固定为 0,此处不更新
- * - 已配网(Bit0)时:断连置 Bit5=1,连上后清 Bit5
- * - 未配网时 Bit5 只由 0x10 / 配网超时 / 配网成功路径维护
- */
-static void mcu_bridge_update_conn_bits(void)
-{
- uint8_t conn = (usr_get_conn_service() != 0) ? 1 : 0;
- uint8_t paired = usr_get_pair_flag();
-
- if (conn != s_br.last_ble_conn) {
- s_br.last_ble_conn = conn;
-
- if (!conn && paired) {
- /* 已配网断连:发回连广播(非绑定广播) */
- usr_var.usr_goto_pair = 0;
- if (s_br.identity_ready) {
- usr_ble_adv_init();
- }
- }
- }
-
- /* 已配网:未连接显示「配网中」,已连接则退出「配网中」 */
- if (paired) {
- mcu_bridge_set_ws_bit(MCU_WS_PAIRING_MODE, conn ? 0 : 1);
- }
-}
-
-/**
- * @brief 配网超时退出
- */
-static void mcu_bridge_check_pair_timeout(void)
-{
- uint32_t now;
- uint32_t timeout_ms;
-
- if (!(s_br.work_status & MCU_WS_PAIRING_MODE)) {
- return;
- }
- if (s_br.pair_timeout_s == 0) {
- return;
- }
- if (usr_get_pair_flag()) {
- return;
- }
-
- now = mcu_util_get_ms();
- timeout_ms = (uint32_t)s_br.pair_timeout_s * 1000u;
- if ((now - s_br.pair_start_ms) < timeout_ms) {
- return;
- }
-
- log_info("pair timeout, stop adv");
- usr_var.usr_goto_pair = 0;
- mcu_bridge_set_ws_bit(MCU_WS_PAIRING_MODE, 0);
- ble_trans_module_enable(0);
- usr_var.usr_adv_flag = 0;
-}
-
-/**
- * @brief APP 透传等待超时重发
- */
-static void mcu_bridge_check_app_pending(void)
-{
- uint32_t now;
-
- if (!s_br.app_pending.active) {
- return;
- }
-
- now = mcu_util_get_ms();
- if ((now - s_br.app_pending.send_time) <= MCU_APP_ACK_WAIT_MS) {
- return;
- }
-
- if (s_br.app_pending.retry >= MCU_APP_ACK_MAX_RETRY) {
- log_error("app pending give up cmd expect=0x%02X",
- s_br.app_pending.expect_ack);
- s_br.app_pending.active = 0;
- return;
- }
-
- mcu_uart_send(s_br.app_pending.buf, s_br.app_pending.len);
- s_br.app_pending.retry++;
- s_br.app_pending.send_time = now;
- log_debug("app pending retry %u", s_br.app_pending.retry);
-}
-
-/**
- * @brief MCU 上报等网关 ACK:超时则重发网关,超限则回 MCU 失败
- */
-static void mcu_bridge_check_report_pending(void)
-{
- uint32_t now;
-
- if (!s_br.report_pending.active) {
- return;
- }
-
- now = mcu_util_get_ms();
- if ((now - s_br.report_pending.send_time) <= MCU_REPORT_GW_WAIT_MS) {
- return;
- }
-
- if (s_br.report_pending.retry >= MCU_REPORT_GW_MAX_RETRY) {
- log_error("gateway report ack timeout, sn=%u", s_br.report_pending.sn);
- mcu_bridge_send_ack(MCU_CMD_REPORT_ACK, s_br.report_pending.sn, MCU_RESULT_FAIL);
- s_br.report_pending.active = 0;
- return;
- }
-
- usr_le_send_mcu_frame(s_br.report_pending.buf, s_br.report_pending.len);
- s_br.report_pending.retry++;
- s_br.report_pending.send_time = now;
- log_debug("gateway report retry %u sn=%u",
- s_br.report_pending.retry, s_br.report_pending.sn);
-}
-
-/**
- * @brief BLE→MCU 主动帧等待超时清理
- * @note 工作状态 ACK 超时后会重置 last_pushed_status,
- * 使 mcu_bridge_try_work_status 在下个周期自动重推,避免状态永久失步
- */
-static void mcu_bridge_check_ble_pending(void)
-{
- uint32_t now;
-
- if (!s_br.ble_pending.active) {
- return;
- }
- /* 心跳有独立超时逻辑 */
- if (s_br.ble_pending.expect_ack == MCU_CMD_HEARTBEAT_ACK) {
- return;
- }
-
- now = mcu_util_get_ms();
- if ((now - s_br.ble_pending.send_time) > MCU_APP_ACK_WAIT_MS) {
- if (s_br.ble_pending.expect_ack == MCU_CMD_WORK_STATUS_ACK) {
- log_error("work_status ack timeout, will retry");
- s_br.last_pushed_status = 0xFF;
- }
- s_br.ble_pending.active = 0;
- }
-}
-
-/**
- * @brief 周期处理:身份轮询 / 心跳 / 重传 / 状态同步
- * @note 仅在 mcu_bridge_task 上下文调用
- */
-static void mcu_bridge_periodic(void)
-{
- /* 与供应商 demo 主循环一致:周期递减 usr_uart_recieve,非 0 禁止 sleep */
- mcu_uart_rx_keep_awake_tick();
-
- mcu_bridge_try_identity();
-
- if (s_br.identity_adv_pending) {
- s_br.identity_adv_pending = 0;
- usr_ble_adv_init();
- }
-
- mcu_bridge_update_conn_bits();
- mcu_bridge_check_pair_timeout();
- mcu_bridge_check_app_pending();
- mcu_bridge_check_ble_pending();
- mcu_bridge_check_report_pending();
- mcu_bridge_try_heartbeat();
- mcu_bridge_try_work_status();
-}
-
-/*============================================================================*/
-/* 公有函数 */
-/*============================================================================*/
-
-/**
- * @brief 初始化 MCU 协议桥(含 UART + 事件队列 + 独立任务)
+ * @brief 初始化 MCU 接入模块
* @return McuBridge_Ret_t
*/
McuBridge_Ret_t mcu_bridge_init(void)
{
- if (s_br.initialized) {
- return MCU_BRIDGE_OK;
- }
-
- memset(&s_br, 0, sizeof(s_br));
- memset(g_usr_le_prodcode, 0, sizeof(g_usr_le_prodcode));
- memset(g_usr_le_pcode, 0, sizeof(g_usr_le_pcode));
- mcu_frame_parser_reset();
-
- if (mcu_uart_init() != MCU_UART_OK) {
- return MCU_BRIDGE_ERR_UNKNOWN;
- }
-
- memset(&s_evt_q, 0, sizeof(s_evt_q));
- os_mutex_create(&s_evt_q.lock);
- os_sem_create(&s_evt_q.sem, 0);
-
- s_br.last_mcu_rx_ms = mcu_util_get_ms();
- s_br.last_identity_tx_ms = 0; /* 立即允许发第一帧 0x01 */
- s_br.last_pushed_status = 0xFF; /* 强制首轮差异 */
- s_br.initialized = 1;
-
- /* 上电:不强制配网;广播由 usr_ble_adv_init 在身份就绪后按配对状态决定 */
- usr_var.usr_goto_pair = 0;
- usr_var.usr_adv_flag = 0;
-
- os_task_create(mcu_bridge_task, NULL, MCU_BRIDGE_TASK_PRIO,
- MCU_BRIDGE_TASK_STACK, 0, "mcu_bridge");
-
- log_info("mcu_bridge_init ok");
- return MCU_BRIDGE_OK;
+ return mcu_protocol_init() ? MCU_BRIDGE_OK : MCU_BRIDGE_ERR_UNKNOWN;
}
/**
- * @brief UART 收到原始数据(生产者,可在 UART 接收任务上下文调用)
- * @param data 数据
- * @param len 长度
- * @note 仅做逐字节组帧,帧就绪后投递事件,不直接触碰业务状态 s_br
+ * @brief UART RX 转交协议层
*/
void mcu_bridge_on_uart_rx(const uint8_t *data, uint16_t len)
{
- uint16_t i;
- uint16_t out_len;
- int8_t ret;
- McuEvt_t evt;
-
- if (!s_br.initialized || !data || len == 0) {
- return;
- }
-
- for (i = 0; i < len; i++) {
- ret = mcu_frame_feed(data[i], s_parse_out, &out_len);
- if (ret == 1) {
- evt.type = MCU_EVT_UART_FRAME;
- evt.len = out_len;
- memcpy(evt.buf, s_parse_out, out_len);
- printf("UART valid data:");
- printf_buf(evt.buf, evt.len);
- mcu_bridge_post_event(&evt);
- }
- }
+ mcu_protocol_on_uart_rx(data, len);
}
/**
- * @brief APP/网关经 BLE 下发的 55AA 帧(生产者,可在 BLE 协议栈任务调用)
- * @param data 55AA 帧
- * @param len 长度
+ * @brief APP 帧转交协议层
*/
void mcu_bridge_on_app_frame(const uint8_t *data, uint16_t len)
{
- McuEvt_t evt;
-
- if (!s_br.initialized || !data || len < 6 || len > sizeof(evt.buf)) {
- log_error("app frame invalid len=%u", len);
- return;
- }
- if (data[0] != MCU_PKT_HEAD_0 || data[1] != MCU_PKT_HEAD_1) {
- log_error("app frame head err");
- return;
- }
-
- evt.type = MCU_EVT_APP_FRAME;
- evt.len = len;
- memcpy(evt.buf, data, len);
- mcu_bridge_post_event(&evt);
+ mcu_protocol_on_app_frame(data, len);
}
/**
- * @brief 是否已从 MCU 获取到设备身份
- * @return 1=已就绪,0=未就绪
- * @note 单字节只读快照,可在任意任务直接调用(无需加锁)
+ * @brief 身份是否就绪,转调业务门面
*/
uint8_t mcu_bridge_is_identity_ready(void)
{
- return s_br.identity_ready;
+ return mcu_business_is_identity_ready();
}
/**
- * @brief 配网成功通知(生产者,可在 BLE 协议栈任务调用)
+ * @brief 配网成功:经协议层事件队列串行化,再转业务门面处理
*/
void mcu_bridge_on_paired(void)
{
- McuEvt_t evt;
-
- memset(&evt, 0, sizeof(evt));
- evt.type = MCU_EVT_BLE_PAIRED;
- mcu_bridge_post_event(&evt);
+ mcu_protocol_notify_paired();
}
/**
- * @brief 配对信息被清除通知(生产者,可在 BLE 协议栈任务调用)
+ * @brief 配对清除:经协议层事件队列串行化
*/
void mcu_bridge_on_pair_cleared(void)
{
- McuEvt_t evt;
-
- memset(&evt, 0, sizeof(evt));
- evt.type = MCU_EVT_BLE_PAIR_CLEARED;
- mcu_bridge_post_event(&evt);
+ mcu_protocol_notify_pair_cleared();
}
/**
- * @brief 获取当前工作状态字节
- * @return 工作状态 bitmap
- * @note 单字节只读快照,可在任意任务直接调用(无需加锁)
+ * @brief 获取工作状态,转调业务门面
*/
uint8_t mcu_bridge_get_work_status(void)
{
- return s_br.work_status;
+ return mcu_business_get_work_status();
}
/**
- * @brief 网关对 REPORTCMD_V2 主动上报的应答(生产者,可在 BLE 协议栈任务调用)
- * @param cmd bleproto 包 cmd
- * @param gateway_int_cnt gateway_int 个数
- * @param gateway_int0 gateway_int[0]
+ * @brief 网关上报应答:经协议层事件队列串行化
*/
void mcu_bridge_on_gateway_report_ack(uint16_t cmd,
uint8_t gateway_int_cnt,
int32_t gateway_int0)
{
- McuEvt_t evt;
-
- memset(&evt, 0, sizeof(evt));
- evt.type = MCU_EVT_GATEWAY_ACK;
- evt.gw_cmd = cmd;
- evt.gw_int_cnt = gateway_int_cnt;
- evt.gw_int0 = gateway_int0;
- mcu_bridge_post_event(&evt);
+ mcu_protocol_notify_gateway_ack(cmd, gateway_int_cnt, gateway_int0);
}
diff --git a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/mcu_bridge.h b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/mcu_bridge.h
index ff20ee2..7993176 100644
--- a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/mcu_bridge.h
+++ b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/mcu_bridge.h
@@ -1,13 +1,16 @@
/******************************************************************************
* @file mcu_bridge.h
- * @brief BLE+MCU 协议桥对外 API(模组侧唯一业务入口)
+ * @brief BLE+MCU 接入模块对外总入口(组合门面)
* @author cyWu <1917507415@qq.com>
- * @date 2026.08.06
- * @version V1.1.0
+ * @date 2026.08.12
+ * @version V2.0.0
* @history
* - V1.0.0, 2026.08.06, cyWu, 首次发布
- * - V1.1.0, 2026.08.06, cyWu, 内部改为事件队列 + 独立任务驱动;
- * 所有 on_xxx 接口均可在任意任务上下文安全调用(生产者-消费者模型)
+ * - V1.1.0, 2026.08.06, cyWu, 内部改为事件队列 + 独立任务驱动
+ * - V1.2.0, 2026.08.12, cyWu, 与 mcu_link 解耦
+ * - V2.0.0, 2026.08.12, cyWu, 整体重构为 protocol/ + business/ 分层:
+ * 本文件不再包含任何实现逻辑,只做“组合根”,对外 API 保持不变,
+ * 外部调用方(app_main.c / usr_le_adv.c / usr_le_recieve.c 等)无需改动
******************************************************************************/
#ifndef __MCU_BRIDGE_H__
@@ -16,6 +19,28 @@
#include
#include "mcu_cmd.h"
+/*============================================================================*/
+/* 说明:整体分层 */
+/* */
+/* apps/usr_mcu_bridge/ */
+/* ├── mcu_bridge.c/h —— 本文件:组合根,稳定对外 API */
+/* ├── protocol/ —— 协议层:只做协议机制,不含业务判断 */
+/* │ ├── mcu_cmd.h 命令字 / 结果码 / work_status 位定义 */
+/* │ ├── mcu_frame.c/h 55AA 组帧/解帧 */
+/* │ ├── mcu_uart.c/h UART 收发驱动 */
+/* │ ├── mcu_util.c/h 校验和/大端序/毫秒工具 */
+/* │ └── mcu_protocol.c/h 事件队列/任务/分发/ACK/透传重传/心跳 */
+/* └── business/ —— 业务层:按业务拆分,互不直接依赖对方实现 */
+/* ├── mcu_identity.c/h 身份业务(0x01/0x02) */
+/* ├── mcu_pairing.c/h 配网业务(0x10、超时) */
+/* ├── mcu_link_status.c/h 连接状态业务(Bit0/1/2/6 位图) */
+/* └── mcu_business.c/h 业务门面:协调以上三者,供协议层调用 */
+/* */
+/* 依赖方向(单向,禁止反向 include): */
+/* mcu_bridge → protocol → business(子模块) → business(门面) */
+/* business 子模块只经 mcu_protocol_send_cmd 等窄接口回调协议层发送 */
+/*============================================================================*/
+
/*============================================================================*/
/* 错误码 */
/*============================================================================*/
@@ -30,14 +55,12 @@ typedef enum {
} McuBridge_Ret_t;
/*============================================================================*/
-/* 外部接口 */
+/* 外部接口(稳定 API,供 app_main / usr_le_code 等外部模块调用) */
/*============================================================================*/
/**
- * @brief 初始化 MCU 协议桥(UART + 事件队列 + 独立任务)
+ * @brief 初始化 MCU 接入模块(组合 protocol + business)
* @return McuBridge_Ret_t
- * @note 在 app_main 中调用一次即可;内部会创建 "mcu_bridge" 任务,
- * 所有身份/心跳/透传/状态机逻辑均在该任务单一上下文中处理
*/
McuBridge_Ret_t mcu_bridge_init(void);
@@ -45,8 +68,6 @@ McuBridge_Ret_t mcu_bridge_init(void);
* @brief UART 收到原始数据(由 mcu_uart 接收任务调用)
* @param data 数据
* @param len 长度
- * @note 仅做逐字节组帧;帧就绪后投递事件到 mcu_bridge 任务处理,
- * 可安全在 UART 接收任务上下文调用
*/
void mcu_bridge_on_uart_rx(const uint8_t *data, uint16_t len);
@@ -54,34 +75,28 @@ void mcu_bridge_on_uart_rx(const uint8_t *data, uint16_t len);
* @brief APP/网关经 BLE 下发的 55AA 帧
* @param data 帧数据
* @param len 长度
- * @note 对 0x03/0x05:转发 MCU,等 0x04/0x06 后再回传 BLE;
- * 可安全在 BLE 协议栈任务上下文调用(内部投递事件异步处理)
*/
void mcu_bridge_on_app_frame(const uint8_t *data, uint16_t len);
/**
* @brief 是否已从 MCU 获取到设备身份
* @return 1=已就绪,0=未就绪
- * @note 单字节只读快照,可在任意任务直接调用
*/
uint8_t mcu_bridge_is_identity_ready(void);
/**
- * @brief 配网成功通知(AUTHSETUP 写对后由 BLE 层调用)
- * @note 可安全在 BLE 协议栈任务上下文调用(内部投递事件异步处理)
+ * @brief 配网成功通知(BLE 协议栈任一上下文调用均可,内部会入队串行处理)
*/
void mcu_bridge_on_paired(void);
/**
* @brief 配对信息被清除通知
- * @note 可安全在 BLE 协议栈任务上下文调用(内部投递事件异步处理)
*/
void mcu_bridge_on_pair_cleared(void);
/**
- * @brief 获取当前工作状态字节
+ * @brief 获取当前工作状态字节(命令 0x14 载荷)
* @return 工作状态 bitmap
- * @note 单字节只读快照,可在任意任务直接调用
*/
uint8_t mcu_bridge_get_work_status(void);
@@ -90,8 +105,6 @@ uint8_t mcu_bridge_get_work_status(void);
* @param cmd bleproto 包 cmd
* @param gateway_int_cnt gateway_int 个数
* @param gateway_int0 gateway_int[0]
- * @note 成功条件:cmd==0 && cnt==1 && int0==0;
- * 成功后才向 MCU 回 0x08;可安全在 BLE 协议栈任务上下文调用
*/
void mcu_bridge_on_gateway_report_ack(uint16_t cmd,
uint8_t gateway_int_cnt,
diff --git a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/mcu_cmd.h b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/protocol/mcu_cmd.h
similarity index 73%
rename from JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/mcu_cmd.h
rename to JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/protocol/mcu_cmd.h
index b3b6806..3c4f07f 100644
--- a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/mcu_cmd.h
+++ b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/protocol/mcu_cmd.h
@@ -2,10 +2,12 @@
* @file mcu_cmd.h
* @brief MCU 接入协议命令字 / 结果码 / 工作状态位定义
* @author cyWu <1917507415@qq.com>
- * @date 2026.08.06
- * @version V1.0.0
+ * @date 2026.08.12
+ * @version V1.1.0
* @history
* - V1.0.0, 2026.08.06, cyWu, 首次发布
+ * - V1.1.0, 2026.08.12, cyWu, 重定义工作状态位:Bit0/1/2 互斥过程态;
+ * 随协议层迁入 protocol/ 目录
******************************************************************************/
#ifndef __MCU_CMD_H__
@@ -15,14 +17,23 @@
/*============================================================================*/
/* 工作状态 Bit(命令 0x14) */
+/* */
+/* Bit0/1/2 互斥(至多一个为 1;可全 0=未配网空闲): */
+/* Bit0 配网中 / Bit1 已配网正常 / Bit2 断线重连中 */
+/* Bit3~5、Bit7 预留,固定 0;Bit6 为 OTA,可与过程态独立叠加 */
/*============================================================================*/
-#define MCU_WS_CONFIGURED (1u << 0) /**< 已完成配网 */
-#define MCU_WS_INTERNET (1u << 1) /**< 已连互联网(云),预留:暂无法获取,固定为 0 */
-#define MCU_WS_APP_ONLINE (1u << 2) /**< APP 在线,预留:暂无法获取,固定为 0 */
-#define MCU_WS_BLE_CONNECTED (1u << 3) /**< 手机已连接 BLE,预留:暂无法获取,固定为 0 */
-#define MCU_WS_OTA_UPGRADING (1u << 4) /**< OTA 升级中 */
-#define MCU_WS_PAIRING_MODE (1u << 5) /**< 配网模式中 */
+#define MCU_WS_PAIRING (1u << 0) /**< 配网中(绑定广播) */
+#define MCU_WS_CONFIGURED (1u << 1) /**< 已配网正常态(已连接/稳定工作) */
+#define MCU_WS_RECONNECTING (1u << 2) /**< 断线重连中(回连广播) */
+#define MCU_WS_CLOUD_ONLINE (1u << 3) /**< 已连接到云,预留:暂固定 0 */
+#define MCU_WS_APP_ONLINE (1u << 4) /**< APP 在线,预留:暂固定 0 */
+#define MCU_WS_APP_DIRECT (1u << 5) /**< APP 直连,预留:暂固定 0 */
+#define MCU_WS_OTA_UPGRADING (1u << 6) /**< 模组 OTA 升级中 */
+/* Bit7 预留 */
+
+/** Bit0/1/2 过程态掩码(互斥组) */
+#define MCU_WS_LINK_MASK (MCU_WS_PAIRING | MCU_WS_CONFIGURED | MCU_WS_RECONNECTING)
/*============================================================================*/
/* 命令字 */
diff --git a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/mcu_frame.c b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/protocol/mcu_frame.c
similarity index 100%
rename from JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/mcu_frame.c
rename to JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/protocol/mcu_frame.c
diff --git a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/mcu_frame.h b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/protocol/mcu_frame.h
similarity index 100%
rename from JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/mcu_frame.h
rename to JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/protocol/mcu_frame.h
diff --git a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/protocol/mcu_protocol.c b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/protocol/mcu_protocol.c
new file mode 100644
index 0000000..3d4c086
--- /dev/null
+++ b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/protocol/mcu_protocol.c
@@ -0,0 +1,881 @@
+/******************************************************************************
+ * @file mcu_protocol.c
+ * @brief MCU 接入协议引擎实现
+ * @author cyWu <1917507415@qq.com>
+ * @date 2026.08.12
+ * @version V1.1.0
+ * @history
+ * - V1.0.0, 2026.08.12, cyWu, 从 mcu_bridge.c 拆出(历史版本见原文件):
+ * 事件队列 + 独立任务驱动、LP target、心跳/透传重传均原样保留
+ * - V1.1.0, 2026.08.12, cyWu, 0x07 上报改为不缓存、不超时重发:
+ * MCU 自身已有超时重发机制,模组侧只记 SN 转发+等 ACK 回 0x08,
+ * 去掉 report_pending 整包缓存与 mcu_protocol_check_report_pending()
+ ******************************************************************************/
+
+#include "system/includes.h"
+#include "asm/power/power_api.h"
+#include "mcu_protocol.h"
+#include "mcu_uart.h"
+#include "mcu_frame.h"
+#include "mcu_util.h"
+#include "usr_le_api.h"
+#include "mcu_business.h"
+
+#define LOG_TAG_CONST APP
+#define LOG_TAG "[MCU_PROTO]"
+#define LOG_ERROR_ENABLE
+#define LOG_DEBUG_ENABLE
+#define LOG_INFO_ENABLE
+#define LOG_DUMP_ENABLE
+#define LOG_CLI_ENABLE
+#include "debug.h"
+
+/*============================================================================*/
+/* 私有宏 */
+/*============================================================================*/
+
+#define MCU_HEARTBEAT_IDLE_MS (55000u)
+#define MCU_HEARTBEAT_MAX_RETRY (3u)
+#define MCU_UART_ACK_WAIT_MS (500u) /* 等 MCU UART ACK 超时(心跳/透传/0x14 等) */
+#define MCU_APP_ACK_MAX_RETRY (3u)
+
+#define MCU_PROTOCOL_TICK_MS (200u)
+/* 杰理 os_sem_pend 超时单位是 OS tick,OS_TICKS_PER_SEC=100 → 1 tick = 10ms */
+#define MCU_PROTOCOL_TICK_OS ((MCU_PROTOCOL_TICK_MS + 9u) / 10u)
+#define MCU_EVT_QUEUE_DEPTH (8u)
+#define MCU_PROTOCOL_TASK_PRIO (31u)
+#define MCU_PROTOCOL_TASK_STACK (2048u)
+
+/*============================================================================*/
+/* 私有类型 */
+/*============================================================================*/
+
+typedef struct
+{
+ uint8_t active;
+ uint8_t sn;
+ uint8_t expect_ack;
+ uint8_t retry;
+ uint32_t send_time;
+ uint8_t buf[MCU_FRAME_MAX_LEN];
+ uint16_t len;
+} McuPending_t;
+
+typedef enum
+{
+ MCU_EVT_UART_FRAME = 0,
+ MCU_EVT_APP_FRAME,
+ MCU_EVT_GATEWAY_ACK,
+ MCU_EVT_BLE_PAIRED,
+ MCU_EVT_BLE_PAIR_CLEARED
+} McuEvtType_t;
+
+typedef struct
+{
+ McuEvtType_t type;
+ uint16_t len;
+ uint8_t buf[MCU_FRAME_MAX_LEN];
+ uint16_t gw_cmd;
+ uint8_t gw_int_cnt;
+ int32_t gw_int0;
+} McuEvt_t;
+
+typedef struct
+{
+ uint8_t initialized;
+ uint8_t sn;
+ uint8_t last_pushed_status;
+ uint8_t hb_fail_cnt;
+ uint8_t hb_waiting;
+ uint8_t mcu_comm_alarm;
+ uint32_t last_mcu_rx_ms;
+ uint32_t last_hb_tx_ms;
+ McuPending_t app_pending; /* APP→MCU 透传等待 */
+ McuPending_t ble_pending; /* BLE 主动请求等待(心跳/状态等) */
+ uint8_t report_waiting; /* 1=已转网关,等 ACK 后再回 MCU 0x08 */
+ uint8_t report_sn; /* 等待回 0x08 的 SN */
+} McuProtocol_t;
+
+typedef struct
+{
+ McuEvt_t queue[MCU_EVT_QUEUE_DEPTH];
+ uint8_t head;
+ uint8_t tail;
+ uint8_t count;
+ OS_MUTEX lock;
+ OS_SEM sem;
+} McuEvtQueue_t;
+
+/*============================================================================*/
+/* 私有变量 */
+/*============================================================================*/
+
+static McuProtocol_t s_proto;
+static uint8_t s_parse_out[MCU_FRAME_MAX_LEN];
+static volatile u8 s_protocol_busy = 0;
+static McuEvtQueue_t s_evt_q;
+
+/*============================================================================*/
+/* 私有函数声明 */
+/*============================================================================*/
+
+static uint8_t mcu_protocol_next_sn(void);
+static int32_t mcu_protocol_send_frame(uint8_t cmd, uint8_t sn,
+ const uint8_t *payload, uint16_t plen);
+static void mcu_protocol_send_ack(uint8_t cmd, uint8_t sn, uint8_t result);
+static void mcu_protocol_handle_frame(const uint8_t *frame, uint16_t len);
+static void mcu_protocol_handle_pair_cfg(const uint8_t *frame, uint16_t len);
+static void mcu_protocol_handle_report(const uint8_t *frame, uint16_t len);
+static void mcu_protocol_handle_app_frame(const uint8_t *data, uint16_t len);
+static void mcu_protocol_handle_gateway_ack(uint16_t cmd, uint8_t gateway_int_cnt,
+ int32_t gateway_int0);
+static void mcu_protocol_try_heartbeat(void);
+static void mcu_protocol_try_work_status(void);
+static void mcu_protocol_check_app_pending(void);
+static void mcu_protocol_check_ble_pending(void);
+static void mcu_protocol_periodic(void);
+static uint8_t mcu_protocol_post_event(const McuEvt_t *evt);
+static uint8_t mcu_protocol_pop_event(McuEvt_t *evt);
+static void mcu_protocol_dispatch_event(const McuEvt_t *evt);
+static void mcu_protocol_task(void *arg);
+
+/*============================================================================*/
+/* 事件队列 */
+/*============================================================================*/
+
+/**
+ * @brief 投递事件并唤醒协议任务
+ * @param evt 事件
+ * @return 1=成功,0=队列满
+ */
+static uint8_t mcu_protocol_post_event(const McuEvt_t *evt)
+{
+ uint8_t ok = 0;
+
+ os_mutex_pend(&s_evt_q.lock, 0);
+ if (s_evt_q.count < MCU_EVT_QUEUE_DEPTH)
+ {
+ s_evt_q.queue[s_evt_q.tail] = *evt;
+ s_evt_q.tail = (uint8_t)((s_evt_q.tail + 1) % MCU_EVT_QUEUE_DEPTH);
+ s_evt_q.count++;
+ ok = 1;
+ }
+ os_mutex_post(&s_evt_q.lock);
+
+ if (ok)
+ {
+ os_sem_post(&s_evt_q.sem);
+ }
+ else
+ {
+ log_error("event queue full, drop type=%d", evt->type);
+ }
+ return ok;
+}
+
+/**
+ * @brief 取出一个事件
+ * @param evt 输出
+ * @return 1=取到,0=空
+ */
+static uint8_t mcu_protocol_pop_event(McuEvt_t *evt)
+{
+ uint8_t ok = 0;
+
+ os_mutex_pend(&s_evt_q.lock, 0);
+ if (s_evt_q.count > 0)
+ {
+ *evt = s_evt_q.queue[s_evt_q.head];
+ s_evt_q.head = (uint8_t)((s_evt_q.head + 1) % MCU_EVT_QUEUE_DEPTH);
+ s_evt_q.count--;
+ ok = 1;
+ }
+ os_mutex_post(&s_evt_q.lock);
+ return ok;
+}
+
+/**
+ * @brief 事件分发:跨任务输入统一转交对应处理函数
+ * @param evt 事件
+ * @note 仅在 mcu_protocol_task 上下文执行,s_proto 在此单一上下文内读写
+ */
+static void mcu_protocol_dispatch_event(const McuEvt_t *evt)
+{
+ switch (evt->type)
+ {
+ case MCU_EVT_UART_FRAME:
+ mcu_protocol_handle_frame(evt->buf, evt->len);
+ break;
+ case MCU_EVT_APP_FRAME:
+ mcu_protocol_handle_app_frame(evt->buf, evt->len);
+ break;
+ case MCU_EVT_GATEWAY_ACK:
+ mcu_protocol_handle_gateway_ack(evt->gw_cmd, evt->gw_int_cnt, evt->gw_int0);
+ break;
+ case MCU_EVT_BLE_PAIRED:
+ mcu_business_on_paired();
+ break;
+ case MCU_EVT_BLE_PAIR_CLEARED:
+ mcu_business_on_pair_cleared();
+ break;
+ default:
+ log_error("unknown evt type=%d", evt->type);
+ break;
+ }
+}
+
+/**
+ * @brief 协议引擎主任务:事件驱动 + 兜底轮询
+ * @param arg 未使用
+ */
+static void mcu_protocol_task(void *arg)
+{
+ McuEvt_t evt;
+
+ (void)arg;
+ log_info("protocol task start");
+
+ while (1)
+ {
+ os_sem_pend(&s_evt_q.sem, (int)MCU_PROTOCOL_TICK_OS);
+
+ s_protocol_busy = 1;
+ while (mcu_protocol_pop_event(&evt))
+ {
+ mcu_protocol_dispatch_event(&evt);
+ }
+ mcu_protocol_periodic();
+ s_protocol_busy = 0;
+ }
+}
+
+/**
+ * @brief 低功耗空闲查询:协议任务忙则不允许进 sleep
+ * @return 1=可睡,0=保持唤醒
+ */
+static u8 mcu_protocol_lp_idle_query(void)
+{
+ return s_protocol_busy ? 0 : 1;
+}
+
+REGISTER_LP_TARGET(mcu_protocol_lp_target) = {
+ .name = "mcu_protocol",
+ .is_idle = mcu_protocol_lp_idle_query,
+};
+
+/*============================================================================*/
+/* 发送 */
+/*============================================================================*/
+
+/**
+ * @brief 取下一个 SN
+ * @return SN
+ */
+static uint8_t mcu_protocol_next_sn(void)
+{
+ return s_proto.sn++;
+}
+
+/**
+ * @brief 组帧发送
+ * @param cmd 命令
+ * @param sn 序列号
+ * @param payload 载荷
+ * @param plen 长度
+ * @return 帧长;<0 失败
+ */
+static int32_t mcu_protocol_send_frame(uint8_t cmd, uint8_t sn,
+ const uint8_t *payload, uint16_t plen)
+{
+ uint8_t buf[MCU_FRAME_MAX_LEN];
+ int32_t total;
+
+ total = mcu_frame_pack(buf, sizeof(buf), cmd, sn, payload, plen);
+ if (total <= 0)
+ {
+ return -1;
+ }
+ if (mcu_uart_send(buf, (uint16_t)total) != MCU_UART_OK)
+ {
+ return -1;
+ }
+ log_debug("MCU TX cmd=0x%02X sn=%u len=%d", cmd, sn, (int)total);
+ return total;
+}
+
+/**
+ * @brief 自动 SN 发送(供 business 层调用)
+ * @param cmd 命令
+ * @param payload 载荷
+ * @param plen 长度
+ * @return 帧长;<0 失败
+ */
+int32_t mcu_protocol_send_cmd(uint8_t cmd, const uint8_t *payload, uint16_t plen)
+{
+ return mcu_protocol_send_frame(cmd, mcu_protocol_next_sn(), payload, plen);
+}
+
+/**
+ * @brief 发送仅含 Result 的 ACK 帧
+ * @param cmd ACK 命令
+ * @param sn 序列号
+ * @param result 结果码
+ */
+static void mcu_protocol_send_ack(uint8_t cmd, uint8_t sn, uint8_t result)
+{
+ mcu_protocol_send_frame(cmd, sn, &result, 1);
+}
+
+/**
+ * @brief 强制重推工作状态
+ */
+void mcu_protocol_invalidate_work_status_push(void)
+{
+ s_proto.last_pushed_status = 0xFF;
+}
+
+/*============================================================================*/
+/* 命令处理 */
+/*============================================================================*/
+
+/**
+ * @brief 处理 0x10:协议校验 + ACK,业务交给 business 层
+ * @param frame 完整帧
+ * @param len 长度
+ */
+static void mcu_protocol_handle_pair_cfg(const uint8_t *frame, uint16_t len)
+{
+ uint8_t sn;
+ uint8_t mode;
+ uint16_t timeout_s;
+
+ if (len < 10)
+ {
+ return;
+ }
+ sn = frame[5];
+ mode = frame[6];
+ timeout_s = mcu_util_read_u16_be(&frame[7]);
+
+ if (mode != 1 && mode != 2)
+ {
+ mcu_protocol_send_ack(MCU_CMD_PAIR_CFG_ACK, sn, MCU_RESULT_PARAM_ERR);
+ return;
+ }
+ if (!mcu_business_is_identity_ready())
+ {
+ mcu_protocol_send_ack(MCU_CMD_PAIR_CFG_ACK, sn, MCU_RESULT_BUSY);
+ return;
+ }
+
+ mcu_protocol_send_ack(MCU_CMD_PAIR_CFG_ACK, sn, MCU_RESULT_OK);
+ mcu_business_on_pair_cfg(mode, timeout_s);
+}
+
+/**
+ * @brief 处理 MCU 上报 0x07:转网关,等网关 ACK 后再回 0x08
+ * @param frame 完整帧
+ * @param len 长度
+ * @note 不缓存重发、不超时回失败;MCU 自己会超时重发 0x07,
+ * 这里收到新的 0x07 会直接覆盖上一次等待中的 SN
+ */
+static void mcu_protocol_handle_report(const uint8_t *frame, uint16_t len)
+{
+ uint8_t sn = frame[5];
+
+ s_proto.report_sn = sn;
+ s_proto.report_waiting = 1;
+ usr_le_send_mcu_frame((u8 *)frame, len);
+ log_debug("MCU report sn=%u -> gateway, wait ACK", sn);
+}
+
+/**
+ * @brief 分发 MCU 完整帧
+ * @param frame 完整帧
+ * @param len 长度
+ */
+static void mcu_protocol_handle_frame(const uint8_t *frame, uint16_t len)
+{
+ uint8_t cmd;
+ uint8_t sn;
+
+ if (!frame || len < 6)
+ {
+ return;
+ }
+
+ s_proto.last_mcu_rx_ms = mcu_util_get_ms();
+ s_proto.hb_fail_cnt = 0;
+ s_proto.hb_waiting = 0;
+ s_proto.mcu_comm_alarm = 0;
+
+ cmd = frame[4];
+ sn = frame[5];
+ log_debug("MCU RX cmd=0x%02X sn=%u len=%u", cmd, sn, len);
+
+ if (s_proto.app_pending.active &&
+ (cmd == s_proto.app_pending.expect_ack) &&
+ (sn == s_proto.app_pending.sn))
+ {
+ s_proto.app_pending.active = 0;
+ usr_le_send_mcu_frame((u8 *)frame, len);
+ return;
+ }
+
+ if (s_proto.ble_pending.active &&
+ (cmd == s_proto.ble_pending.expect_ack) &&
+ (sn == s_proto.ble_pending.sn))
+ {
+ s_proto.ble_pending.active = 0;
+ if (cmd == MCU_CMD_HEARTBEAT_ACK)
+ {
+ s_proto.hb_waiting = 0;
+ s_proto.hb_fail_cnt = 0;
+ }
+ return;
+ }
+
+ switch (cmd)
+ {
+ case MCU_CMD_GET_IDENTITY_ACK:
+ mcu_business_on_identity_ack(frame, len);
+ break;
+ case MCU_CMD_PAIR_CFG:
+ mcu_protocol_handle_pair_cfg(frame, len);
+ break;
+ case MCU_CMD_REPORT:
+ mcu_protocol_handle_report(frame, len);
+ break;
+ case MCU_CMD_CONTROL_ACK:
+ case MCU_CMD_READ_ACK:
+ usr_le_send_mcu_frame((u8 *)frame, len);
+ break;
+ case MCU_CMD_HEARTBEAT_ACK:
+ case MCU_CMD_WORK_STATUS_ACK:
+ break;
+ default:
+ if (cmd == MCU_CMD_RESET || cmd == MCU_CMD_REBOOT ||
+ cmd == MCU_CMD_GET_TIME || cmd == MCU_CMD_FACTORY ||
+ cmd == MCU_CMD_PHOTO || cmd == MCU_CMD_RECORD ||
+ cmd == MCU_CMD_AUDIO)
+ {
+ mcu_protocol_send_ack((uint8_t)(cmd + 1), sn, MCU_RESULT_NOT_SUPPORT);
+ }
+ break;
+ }
+}
+
+/**
+ * @brief 处理 APP 下发 55AA
+ * @param data 帧
+ * @param len 长度
+ */
+static void mcu_protocol_handle_app_frame(const uint8_t *data, uint16_t len)
+{
+ uint8_t cmd;
+ uint8_t sn;
+ uint8_t expect_ack;
+
+ cmd = data[4];
+ sn = data[5];
+
+ if (cmd == MCU_CMD_CONTROL)
+ {
+ expect_ack = MCU_CMD_CONTROL_ACK;
+ }
+ else if (cmd == MCU_CMD_READ)
+ {
+ expect_ack = MCU_CMD_READ_ACK;
+ }
+ else
+ {
+ mcu_uart_send(data, len);
+ return;
+ }
+
+ if (s_proto.app_pending.active)
+ {
+ log_error("app frame busy, drop cmd=0x%02X", cmd);
+ return;
+ }
+
+ memcpy(s_proto.app_pending.buf, data, len);
+ s_proto.app_pending.len = len;
+ s_proto.app_pending.sn = sn;
+ s_proto.app_pending.expect_ack = expect_ack;
+ s_proto.app_pending.retry = 0;
+ s_proto.app_pending.send_time = mcu_util_get_ms();
+ s_proto.app_pending.active = 1;
+
+ mcu_uart_send(data, len);
+ log_debug("app->mcu forward cmd=0x%02X sn=%u wait 0x%02X",
+ cmd, sn, expect_ack);
+}
+
+/**
+ * @brief 处理网关对 0x07 的应答
+ * @param cmd bleproto cmd
+ * @param gateway_int_cnt int 个数
+ * @param gateway_int0 int0
+ */
+static void mcu_protocol_handle_gateway_ack(uint16_t cmd,
+ uint8_t gateway_int_cnt,
+ int32_t gateway_int0)
+{
+ uint8_t sn;
+
+ if (!s_proto.report_waiting)
+ {
+ return;
+ }
+
+ if (cmd == 0 && gateway_int_cnt == 1 && gateway_int0 == 0)
+ {
+ sn = s_proto.report_sn;
+ mcu_protocol_send_ack(MCU_CMD_REPORT_ACK, sn, MCU_RESULT_OK);
+ s_proto.report_waiting = 0;
+ log_info("gateway report ack ok, MCU 0x08 sn=%u", sn);
+ return;
+ }
+
+ log_error("gateway report ack fail cmd=%u cnt=%u int0=%ld",
+ (unsigned)cmd, (unsigned)gateway_int_cnt, (long)gateway_int0);
+}
+
+/*============================================================================*/
+/* 周期:心跳 / 状态推送 / pending 重试 */
+/*============================================================================*/
+
+/**
+ * @brief 心跳
+ */
+static void mcu_protocol_try_heartbeat(void)
+{
+ uint32_t now = mcu_util_get_ms();
+ uint8_t sn;
+ uint8_t buf[MCU_FRAME_MAX_LEN];
+ int32_t total;
+
+ if (!mcu_business_is_identity_ready())
+ {
+ return;
+ }
+
+ if (s_proto.hb_waiting)
+ {
+ if ((now - s_proto.last_hb_tx_ms) <= MCU_UART_ACK_WAIT_MS)
+ {
+ return;
+ }
+ s_proto.hb_waiting = 0;
+ s_proto.ble_pending.active = 0;
+ s_proto.hb_fail_cnt++;
+ log_error("heartbeat timeout fail=%u", s_proto.hb_fail_cnt);
+ if (s_proto.hb_fail_cnt >= MCU_HEARTBEAT_MAX_RETRY)
+ {
+ s_proto.mcu_comm_alarm = 1;
+ log_error("MCU comm alarm");
+ s_proto.last_mcu_rx_ms = now;
+ return;
+ }
+ }
+ else if ((now - s_proto.last_mcu_rx_ms) < MCU_HEARTBEAT_IDLE_MS)
+ {
+ return;
+ }
+
+ sn = mcu_protocol_next_sn();
+ total = mcu_frame_pack(buf, sizeof(buf), MCU_CMD_HEARTBEAT, sn, NULL, 0);
+ if (total <= 0)
+ {
+ return;
+ }
+ if (mcu_uart_send(buf, (uint16_t)total) != MCU_UART_OK)
+ {
+ return;
+ }
+
+ s_proto.ble_pending.active = 1;
+ s_proto.ble_pending.sn = sn;
+ s_proto.ble_pending.expect_ack = MCU_CMD_HEARTBEAT_ACK;
+ s_proto.ble_pending.send_time = now;
+ s_proto.ble_pending.retry = 0;
+ s_proto.last_hb_tx_ms = now;
+ s_proto.hb_waiting = 1;
+ log_debug("heartbeat tx sn=%u", sn);
+}
+
+/**
+ * @brief 工作状态变化时推送 0x14(状态值来自 business 层)
+ */
+static void mcu_protocol_try_work_status(void)
+{
+ uint8_t payload[2];
+ uint8_t sn;
+ uint8_t buf[MCU_FRAME_MAX_LEN];
+ int32_t total;
+ uint32_t now;
+ uint8_t ws;
+
+ if (!mcu_business_is_identity_ready())
+ {
+ return;
+ }
+
+ ws = mcu_business_get_work_status();
+ if (ws == s_proto.last_pushed_status)
+ {
+ return;
+ }
+ if (s_proto.ble_pending.active)
+ {
+ return;
+ }
+
+ payload[0] = ws;
+ payload[1] = 0x00;
+
+ sn = mcu_protocol_next_sn();
+ total = mcu_frame_pack(buf, sizeof(buf), MCU_CMD_WORK_STATUS, sn, payload, 2);
+ if (total <= 0)
+ {
+ return;
+ }
+ if (mcu_uart_send(buf, (uint16_t)total) != MCU_UART_OK)
+ {
+ return;
+ }
+
+ now = mcu_util_get_ms();
+ s_proto.ble_pending.active = 1;
+ s_proto.ble_pending.sn = sn;
+ s_proto.ble_pending.expect_ack = MCU_CMD_WORK_STATUS_ACK;
+ s_proto.ble_pending.send_time = now;
+ s_proto.last_pushed_status = ws;
+ log_info("work_status push 0x%02X", ws);
+}
+
+/**
+ * @brief APP 透传超时重发;重试用尽后主动回 FAIL,不让 APP 干等
+ */
+static void mcu_protocol_check_app_pending(void)
+{
+ uint32_t now;
+ uint8_t buf[MCU_FRAME_MAX_LEN];
+ uint8_t result;
+ int32_t total;
+
+ if (!s_proto.app_pending.active)
+ {
+ return;
+ }
+
+ now = mcu_util_get_ms();
+ if ((now - s_proto.app_pending.send_time) <= MCU_UART_ACK_WAIT_MS)
+ {
+ return;
+ }
+
+ if (s_proto.app_pending.retry >= MCU_APP_ACK_MAX_RETRY)
+ {
+ log_error("app pending give up cmd expect=0x%02X, notify APP FAIL",
+ s_proto.app_pending.expect_ack);
+ s_proto.app_pending.active = 0;
+
+ result = MCU_RESULT_FAIL;
+ total = mcu_frame_pack(buf, sizeof(buf), s_proto.app_pending.expect_ack,
+ s_proto.app_pending.sn, &result, 1);
+ if (total > 0)
+ {
+ usr_le_send_mcu_frame(buf, (uint16_t)total);
+ }
+ return;
+ }
+
+ mcu_uart_send(s_proto.app_pending.buf, s_proto.app_pending.len);
+ s_proto.app_pending.retry++;
+ s_proto.app_pending.send_time = now;
+ log_debug("app pending retry %u", s_proto.app_pending.retry);
+}
+
+/**
+ * @brief BLE 主动帧 pending 超时清理
+ */
+static void mcu_protocol_check_ble_pending(void)
+{
+ uint32_t now;
+
+ if (!s_proto.ble_pending.active)
+ {
+ return;
+ }
+ if (s_proto.ble_pending.expect_ack == MCU_CMD_HEARTBEAT_ACK)
+ {
+ return;
+ }
+
+ now = mcu_util_get_ms();
+ if ((now - s_proto.ble_pending.send_time) > MCU_UART_ACK_WAIT_MS)
+ {
+ if (s_proto.ble_pending.expect_ack == MCU_CMD_WORK_STATUS_ACK)
+ {
+ log_error("work_status ack timeout, will retry");
+ s_proto.last_pushed_status = 0xFF;
+ }
+ s_proto.ble_pending.active = 0;
+ }
+}
+
+/**
+ * @brief 周期处理:串口防睡 / 业务周期 / pending 重试 / 心跳 / 状态推送
+ */
+static void mcu_protocol_periodic(void)
+{
+ mcu_uart_rx_keep_awake_tick(); /* 串口防睡 */
+ mcu_business_periodic(); /* 业务周期 */
+ mcu_protocol_check_app_pending(); /* APP 透传超时重发;重试用尽后主动回 FAIL,不让 APP 干等 */
+ mcu_protocol_check_ble_pending(); /* BLE 主动帧 pending 超时清理 */
+ mcu_protocol_try_heartbeat(); /* 心跳 */
+ mcu_protocol_try_work_status(); /* 工作状态变化时推送 0x14(状态值来自 business 层) */
+}
+
+/*============================================================================*/
+/* 公有入口 */
+/*============================================================================*/
+
+/**
+ * @brief 初始化协议引擎
+ * @return 1=成功,0=失败
+ */
+uint8_t mcu_protocol_init(void)
+{
+ if (s_proto.initialized)
+ {
+ return 1;
+ }
+
+ memset(&s_proto, 0, sizeof(s_proto));
+ mcu_frame_parser_reset();
+ mcu_business_init();
+
+ if (mcu_uart_init() != MCU_UART_OK)
+ {
+ return 0;
+ }
+
+ memset(&s_evt_q, 0, sizeof(s_evt_q));
+ os_mutex_create(&s_evt_q.lock);
+ os_sem_create(&s_evt_q.sem, 0);
+
+ s_proto.last_mcu_rx_ms = mcu_util_get_ms();
+ s_proto.last_pushed_status = 0xFF;
+ s_proto.initialized = 1;
+
+ os_task_create(mcu_protocol_task, NULL, MCU_PROTOCOL_TASK_PRIO,
+ MCU_PROTOCOL_TASK_STACK, 0, "mcu_bridge");
+
+ log_info("mcu_protocol_init ok");
+ return 1;
+}
+
+/**
+ * @brief UART RX 生产者
+ * @param data 数据
+ * @param len 长度
+ */
+void mcu_protocol_on_uart_rx(const uint8_t *data, uint16_t len)
+{
+ uint16_t i;
+ uint16_t out_len;
+ int8_t ret;
+ McuEvt_t evt;
+
+ if (!s_proto.initialized || !data || len == 0)
+ {
+ return;
+ }
+
+ for (i = 0; i < len; i++)
+ {
+ ret = mcu_frame_feed(data[i], s_parse_out, &out_len);
+ if (ret == 1)
+ {
+ evt.type = MCU_EVT_UART_FRAME;
+ evt.len = out_len;
+ memcpy(evt.buf, s_parse_out, out_len);
+ printf("UART valid data:");
+ printf_buf(evt.buf, evt.len);
+ mcu_protocol_post_event(&evt);
+ }
+ }
+}
+
+/**
+ * @brief APP 帧生产者
+ * @param data 帧
+ * @param len 长度
+ */
+void mcu_protocol_on_app_frame(const uint8_t *data, uint16_t len)
+{
+ McuEvt_t evt;
+
+ if (!s_proto.initialized || !data || len < 6 || len > sizeof(evt.buf))
+ {
+ log_error("app frame invalid len=%u", len);
+ return;
+ }
+ if (data[0] != MCU_PKT_HEAD_0 || data[1] != MCU_PKT_HEAD_1)
+ {
+ log_error("app frame head err");
+ return;
+ }
+
+ evt.type = MCU_EVT_APP_FRAME;
+ evt.len = len;
+ memcpy(evt.buf, data, len);
+ mcu_protocol_post_event(&evt);
+}
+
+/**
+ * @brief 配网成功入队
+ */
+void mcu_protocol_notify_paired(void)
+{
+ McuEvt_t evt;
+
+ memset(&evt, 0, sizeof(evt));
+ evt.type = MCU_EVT_BLE_PAIRED;
+ mcu_protocol_post_event(&evt);
+}
+
+/**
+ * @brief 配对清除入队
+ */
+void mcu_protocol_notify_pair_cleared(void)
+{
+ McuEvt_t evt;
+
+ memset(&evt, 0, sizeof(evt));
+ evt.type = MCU_EVT_BLE_PAIR_CLEARED;
+ mcu_protocol_post_event(&evt);
+}
+
+/**
+ * @brief 网关上报应答入队
+ * @param cmd cmd
+ * @param gateway_int_cnt cnt
+ * @param gateway_int0 int0
+ */
+void mcu_protocol_notify_gateway_ack(uint16_t cmd,
+ uint8_t gateway_int_cnt,
+ int32_t gateway_int0)
+{
+ McuEvt_t evt;
+
+ memset(&evt, 0, sizeof(evt));
+ evt.type = MCU_EVT_GATEWAY_ACK;
+ evt.gw_cmd = cmd;
+ evt.gw_int_cnt = gateway_int_cnt;
+ evt.gw_int0 = gateway_int0;
+ mcu_protocol_post_event(&evt);
+}
diff --git a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/protocol/mcu_protocol.h b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/protocol/mcu_protocol.h
new file mode 100644
index 0000000..0d44c8e
--- /dev/null
+++ b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/protocol/mcu_protocol.h
@@ -0,0 +1,83 @@
+/******************************************************************************
+ * @file mcu_protocol.h
+ * @brief MCU 接入协议引擎:事件队列 / 任务 / 命令分发 / ACK / 透传重传 / 心跳
+ * @author cyWu <1917507415@qq.com>
+ * @date 2026.08.12
+ * @version V1.0.0
+ * @history
+ * - V1.0.0, 2026.08.12, cyWu, 从 mcu_bridge.c 拆出,仅保留协议机制,
+ * 不含任何业务判断(身份/配网/连接状态见 ../business)
+ ******************************************************************************/
+
+#ifndef __MCU_PROTOCOL_H__
+#define __MCU_PROTOCOL_H__
+
+#include
+#include "mcu_cmd.h"
+
+/*============================================================================*/
+/* 说明 */
+/* 本模块只做协议机制:组帧收发、事件队列驱动的单一任务、命令分发、 */
+/* ACK 与超时重传、心跳保活。所有业务判断(该不该配网/该发什么广播/ */
+/* work_status 具体取值)一律转交 business 层,本模块不感知业务细节。 */
+/*============================================================================*/
+
+/**
+ * @brief 初始化协议引擎(UART + 事件队列 + 独立任务 + business 层)
+ * @return 1=成功,0=失败
+ */
+uint8_t mcu_protocol_init(void);
+
+/**
+ * @brief UART 收到原始数据(由 mcu_uart 接收任务调用)
+ * @param data 数据
+ * @param len 长度
+ */
+void mcu_protocol_on_uart_rx(const uint8_t *data, uint16_t len);
+
+/**
+ * @brief APP/网关经 BLE 下发的 55AA 帧
+ * @param data 帧数据
+ * @param len 长度
+ */
+void mcu_protocol_on_app_frame(const uint8_t *data, uint16_t len);
+
+/**
+ * @brief 配网成功通知(入队,交由协议任务在自身上下文调用 business 层)
+ */
+void mcu_protocol_notify_paired(void);
+
+/**
+ * @brief 配对信息被清除通知(入队)
+ */
+void mcu_protocol_notify_pair_cleared(void);
+
+/**
+ * @brief 网关对 REPORTCMD_V2 主动上报的应答(入队)
+ * @param cmd bleproto 包 cmd
+ * @param gateway_int_cnt gateway_int 个数
+ * @param gateway_int0 gateway_int[0]
+ */
+void mcu_protocol_notify_gateway_ack(uint16_t cmd,
+ uint8_t gateway_int_cnt,
+ int32_t gateway_int0);
+
+/*============================================================================*/
+/* 供 business 层调用的协议发送接口 */
+/*============================================================================*/
+
+/**
+ * @brief 自动分配 SN 并发送一帧到 MCU
+ * @param cmd 命令字
+ * @param payload 载荷,可为 NULL
+ * @param plen 载荷长度
+ * @return 帧长;<0 失败
+ */
+int32_t mcu_protocol_send_cmd(uint8_t cmd, const uint8_t *payload, uint16_t plen);
+
+/**
+ * @brief 强制下一轮重新推送 0x14(业务状态变化后调用)
+ */
+void mcu_protocol_invalidate_work_status_push(void);
+
+#endif /* __MCU_PROTOCOL_H__ */
diff --git a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/mcu_uart.c b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/protocol/mcu_uart.c
similarity index 98%
rename from JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/mcu_uart.c
rename to JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/protocol/mcu_uart.c
index 6815118..4e15314 100644
--- a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/mcu_uart.c
+++ b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/protocol/mcu_uart.c
@@ -44,7 +44,7 @@ static OS_MUTEX s_tx_lock;
/*
* 防睡计数:唤醒口或 UART 收到数据时置 MCU_UART_RX_KEEP_AWAKE_TICKS;
- * 由 mcu_bridge 主循环周期递减;非 0 时 LP target 禁止进 sleep。
+ * 由 mcu_protocol 主循环周期递减;非 0 时 LP target 禁止进 sleep。
*/
static volatile u8 s_usr_uart_recieve = 0;
diff --git a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/mcu_uart.h b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/protocol/mcu_uart.h
similarity index 98%
rename from JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/mcu_uart.h
rename to JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/protocol/mcu_uart.h
index e0149d4..6d57d01 100644
--- a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/mcu_uart.h
+++ b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/protocol/mcu_uart.h
@@ -25,7 +25,7 @@
#define MCU_UART_RX_PIN IO_PORTA_08 /**< MCU 通信 UART RX(board 唤醒口须一致) */
/*
- * sleep 唤醒或串口收数后保持唤醒的 tick 数(mcu_bridge 约每 200ms 递减一次)。
+ * sleep 唤醒或串口收数后保持唤醒的 tick 数(mcu_protocol 约每 200ms 递减一次)。
* 取大一些:第一包可能在唤醒过程中丢失,留给对端协议重试窗口(约 3s)。
*/
#define MCU_UART_RX_KEEP_AWAKE_TICKS (15u)
diff --git a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/mcu_util.c b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/protocol/mcu_util.c
similarity index 100%
rename from JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/mcu_util.c
rename to JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/protocol/mcu_util.c
diff --git a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/mcu_util.h b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/protocol/mcu_util.h
similarity index 100%
rename from JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/mcu_util.h
rename to JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/protocol/mcu_util.h