Files
vd_960/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/usart_biz.c
T
wangfq b493e10454 fix(vd960DBN): UART2 粘帧/checksum fail — 高频打印关中断丢字节 + flag 不清
现场: LUP 帧后 checksum fail 刷屏 (坏帧: 7F 03 39 EF... 多帧拼接)。
根因链条:
1. LUP Rx 打印 190B @256000 = 7.4ms 关中断 (PRINT 临界区)
   → UART2(19200) RX 溢出丢字节 → 帧解析错位 → 粘帧
2. g_pkg_uart_2.flag 清理缺失: uart_srv 0xC0 分支不 InitPkgUart,
   tcp_json_push_sensor not authed 提前 return 也不清
   → 坏帧反复处理 → checksum fail 刷屏

修复:
- LUP Rx 打印 #if 0 (高频打印关中断是丢字节根因, 调试时开)
- json_sensor_callback not authed 打印 #if 0 (每帧刷屏)
- uart_srv 所有分支消费后统一 InitPkgUart (0xC0 + 非0xC0无BLE)
- 顺带修 report disabled 双反斜杠
2026-08-13 17:43:24 +08:00

226 lines
7.5 KiB
C

/*
* usart_biz.c
*
* Created on: 2026-02-26
* Author: wangfq
* Updated: 2026-07-02 — 使用 loop_uart_proto 帧解析器替代 timeout heuristic
*/
#include "config.h"
#include "cmcng.h"
#include "loop_uart_proto.h"
#include <string.h>
#include "dbn_ble_srv.h"
void USART1_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void USART2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void uart_init(void){
GPIO_InitTypeDef GPIO_InitStructure = {0};
USART_InitTypeDef USART_InitStructure = {0};
NVIC_InitTypeDef NVIC_InitStructure = {0};
// usart1 : peripheral / DEBUG
//usart2 :loop mcu
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // Tx
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // Rx
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 192000; // Loop MCU 实际波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_Init(USART2, &USART_InitStructure);
// USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_Cmd(USART2, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 初始化帧解析器
lup_frame_reset();
}
/*********************************************************************
* @fn USART1_IRQHandler
*
* @brief This function handles USART1 global interrupt request.
*
* @return none
*/
void USART1_IRQHandler(void)
{
}
/*********************************************************************
* @fn USART2_IRQHandler
*
* @brief USART2 RX — 使用 lup_feed_byte() 帧解析器
* 当解析出完整帧时,复制到 g_pkg_uart_2.pkg 并设置 flag
*
* @return none
*/
void USART2_IRQHandler(void)
{
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
{
uint8_t _dat = USART_ReceiveData(USART2);
// 喂给帧解析器
if (lup_feed_byte(_dat)) {
// 帧接收完成,复制到 g_pkg_uart_2
const uint8_t *frame = lup_frame_data();
uint16_t frame_len = lup_frame_len();
if (frame_len <= BUFF_STACK_SIZE) {
memcpy(g_pkg_uart_2.pkg, frame, frame_len);
g_pkg_uart_2.offset = frame_len;
g_pkg_uart_2.flag = 1;
g_pkg_uart_2.tick = 0;
}
lup_frame_reset();
} else if (g_lup_parser.state != LUP_FRAME_STATE_IDLE) {
// 正在接收帧中,tick 归零
g_pkg_uart_2.tick = 0;
}
}
}
void UART2_SendString(uint8_t *buf, uint16_t len)
{
uint16_t _len = len;
while(_len){
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
USART_SendData(USART2, *buf++);
_len--;
}
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
}
void UART1_SendString(uint8_t *buf, uint16_t len)
{
uint16_t _len = len;
while(_len){
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
USART_SendData(USART1, *buf++);
_len--;
}
}
/*
* uart_srv — 主循环中调用,处理已接收完整的 UART2 帧
*
* 处理流程:
* 1. 0x7F + 0xC0/0x0C → 传感器数据上报
* - 若无 BLE 连接 → 标记 `_report_flag`,在 TCP JSON 中处理
* - 若有 BLE 连接且 acs_enable → 转 0x8F 前缀发给 BLE
* 2. 0x7F + 其他 CMD → 响应帧,交给 lup_process_frame() 匹配挂起命令
* 3. 非 0x7F → 调试打印(可能是字符串等)
*/
void uart_srv(void)
{
uint8_t i;
uint8_t _report_flag = 0;
// 检查命令超时
lup_cmd_check_timeout();
if(g_pkg_uart_2.flag){
if(g_flag_counter_ota.flag == 0){
if(g_pkg_uart_2.pkg[0] == 0x7F){
uint8_t cmd = g_pkg_uart_2.pkg[3];
// --- 所有 0x7F 帧先经过 lup_process_frame 校验 ---
// 0xC0: 校验后通过回调直接推送 TCP JSON
// 其他: 校验后匹配挂起命令
lup_process_frame(g_pkg_uart_2.pkg, g_pkg_uart_2.offset);
// --- 传感器上报 (0xC0) 分流 ---
// 回调已处理 TCP 推送,此处仅处理 BLE 转发
if(cmd == LUP_CMD_SENSOR_REPORT)
{
if(g_dbn_ble_state_acs_enable.flag != 0){
// BLE ACS 已连接 → 改 Magic 为 0x8F 发给 BLE
g_pkg_uart_2.pkg[0] = 0x8F;
g_flag_notify_temp = set_response_tran_to_notify(g_pkg_uart_2.pkg, g_pkg_uart_2.offset, &g_notify_buftemp); // 保留给 BLE
}
/* 2026-08-13 修复: 0xC0 帧消费后必须清 flag —
原缺失, auth 未通过时 tcp_json_push_sensor 提前 return
也不清 → 坏帧/正常帧反复处理 (checksum fail 刷屏) */
InitPkgUart(&g_pkg_uart_2);
}
else {
if(g_flag_bt_state){
g_flag_notify_temp = set_response_tran_to_notify(g_pkg_uart_2.pkg, g_pkg_uart_2.offset, &g_notify_buftemp);
InitPkgUart(&g_pkg_uart_2);
}
else {
/* 2026-08-13 修复: 非 0xC0 + 无 BLE 连接也清 flag (原缺失) */
InitPkgUart(&g_pkg_uart_2);
}
}
// 调试打印 (2026-08-13: LUP Rx 已在 lup_process_frame 缓冲打印,
// 此处重复逐字节打印冗余且高频 — 暂时关闭)
#if 0
for(i = 0; i < g_pkg_uart_2.offset; i++){
PRINT(" %02X", g_pkg_uart_2.pkg[i]);
}
PRINT("\n");
#endif
}
else {
// 非 0x7F 魔法字节 — hex 打印 (原 %s 会把二进制当字符串 → 乱码)
PRINT("Rcv_len:%d,dat:", g_pkg_uart_2.offset);
for(i = 0; i < g_pkg_uart_2.offset; i++){
PRINT(" %02X", g_pkg_uart_2.pkg[i]);
}
PRINT("\n");
}
}
else{
// OTA 模式 — 忽略 Loop MCU 数据
}
if(g_flag_bt_state){
}
else{
g_dbn_ble_state_acs_enable.flag = 0;
}
}
}