From 287c3f679944849e4e015eae7908a338c2bf7bdd Mon Sep 17 00:00:00 2001 From: yuquanjun Date: Sat, 19 Sep 2026 19:07:23 +0800 Subject: [PATCH] fix(ble): sync timbre/style UI via UI task to avoid hardfault App writes for timbre/BPM/transpose/style were refreshing LCD and reloading tone packs on the 768B BLE recv stack, causing overflow and crashes. Route heavy work through MSG_ID_BLE_* into the UI task, and notify App when the device changes rhythm style. Co-authored-by: Cursor --- Global/Global.h | 2 ++ UI/UI_SongMode.c | 52 ++++++++++++++++++++++++++++++++++++++++ protocol/bl_uart_parse.c | 35 +++++++++++++++------------ task/task_init.c | 9 +++++++ 4 files changed, 83 insertions(+), 15 deletions(-) diff --git a/Global/Global.h b/Global/Global.h index ce430aa..5add3dd 100644 --- a/Global/Global.h +++ b/Global/Global.h @@ -29,6 +29,8 @@ #define MSG_ID_TAP_SPEED 25 #define MSG_ID_LOOP_LIGHT 26 #define MSG_ID_CHARG 27 +#define MSG_ID_BLE_UI_REFRESH 28 +#define MSG_ID_BLE_STYLE_SET 29 #define GPIO_PIN_RESET false #define GPIO_PIN_SET true diff --git a/UI/UI_SongMode.c b/UI/UI_SongMode.c index 4efc507..e8b0beb 100644 --- a/UI/UI_SongMode.c +++ b/UI/UI_SongMode.c @@ -204,6 +204,19 @@ void Touch_Action(int8_t FLAG, uint8_t ID, uint8_t areaIndex,uint8_t value) nvm->param.Param2 = ParamGuiData[EXPRESS_MODE_PARAM].Current; else nvm->param.Param1 = ParamGuiData[SONG_MODE_PARAM].Current; + + /* 联动 App:本地切换节奏风格后上报(格式同 03 04 读回复;万能 tab 为和弦走向不上报) */ + if (tab != 0) + { + uint8_t style_src = (uint8_t)mGuiData[GUI_AUTOBAND_SW].Current; + uint16_t style_id = style_src ? ParamGuiData[EXPRESS_MODE_PARAM].Current + : ParamGuiData[SONG_MODE_PARAM].Current; + uint8_t StyleNotify[9] = {0xF0,0x60,0x03,0x04,0x00,0x00,0x00,0x00,0xF7}; + StyleNotify[5] = style_src; + StyleNotify[6] = (uint8_t)(style_id / 128); + StyleNotify[7] = (uint8_t)(style_id % 128); + USART4_SendData(StyleNotify,sizeof(StyleNotify)); + } } break; case GUI_TIMBRE_SELECT: @@ -237,6 +250,16 @@ void Touch_Action(int8_t FLAG, uint8_t ID, uint8_t areaIndex,uint8_t value) UI_ReloadTonePreset(); if (!UI_SetFocus(GUI_MODE_PARAM)) label_ModeSelece_ui(&UI_Label[GUI_MODE_PARAM],&mGuiData[GUI_MODE_PARAM]); + /* 联动 App:节奏类型/本地曲目切换后上报当前风格 */ + { + uint16_t style_id = value ? ParamGuiData[EXPRESS_MODE_PARAM].Current + : ParamGuiData[SONG_MODE_PARAM].Current; + uint8_t StyleNotify[9] = {0xF0,0x60,0x03,0x04,0x00,0x00,0x00,0x00,0xF7}; + StyleNotify[5] = (uint8_t)value; + StyleNotify[6] = (uint8_t)(style_id / 128); + StyleNotify[7] = (uint8_t)(style_id % 128); + USART4_SendData(StyleNotify,sizeof(StyleNotify)); + } return; } else if(ID==GUI_PLAY_SECTION) @@ -492,6 +515,35 @@ void UI_SongMode_Process(DisplayTaskMessage_Type msg) ResetAutoPowerCount(); } break; + case MSG_ID_BLE_UI_REFRESH: + /* BLE 写指令的 LCD 刷新:状态已在 BLE 任务更新,此处仅在 UI 任务上下文绘制。 + 本消息经 MainTask→UITask 转发到 CurrUIProcress,只在曲目页才会被处理, + 其它页面天然忽略,无需页面判断 */ + switch (msg.ID) + { + case GUI_TIMBRE_SELECT: + UI_SetFocus(GUI_TIMBRE_SELECT); + Refresh_StringTimbre(0, &UI_Label[GUI_TIMBRE_SELECT], &mGuiData[GUI_TIMBRE_SELECT]); + break; + case GUI_MODE_PARAM: + if (!UI_SetFocus(GUI_MODE_PARAM)) + label_ModeSelece_ui(&UI_Label[GUI_MODE_PARAM], &mGuiData[GUI_MODE_PARAM]); + break; + case GUI_SPEED: + Refresh_Transpose(&UI_Label[GUI_SPEED], &mGuiData[GUI_SPEED]); + break; + case GUI_TRANSPOSE: + Refresh_Transpose(&UI_Label[GUI_TRANSPOSE], &mGuiData[GUI_TRANSPOSE]); + break; + default: + break; + } + break; + case MSG_ID_BLE_STYLE_SET: + /* 停伴奏+换库已在 TaskUIThread 全局处理;此处仅刷新节奏风格卡片 */ + if (!UI_SetFocus(GUI_MODE_PARAM)) + label_ModeSelece_ui(&UI_Label[GUI_MODE_PARAM], &mGuiData[GUI_MODE_PARAM]); + break; case MSG_ID_CHARG: Show_Battery_Icon(msg.ID); break; diff --git a/protocol/bl_uart_parse.c b/protocol/bl_uart_parse.c index b218a32..ec7ca4a 100644 --- a/protocol/bl_uart_parse.c +++ b/protocol/bl_uart_parse.c @@ -322,15 +322,18 @@ static void handleStringTimbre(uint8_t *data) uint8_t new_val = data[6]; // �õ�����ɫֵ // ���ֵû�䣬ֱ���˳�����ˢ�� + if (new_val > mGuiData[GUI_TIMBRE_SELECT].Max) + { + return; + } if (new_val == mGuiData[GUI_TIMBRE_SELECT].Current) { return; } mGuiData[GUI_TIMBRE_SELECT].Current = new_val; - if(mGuiData[GUI_TAB_INDEX].Current != 3) - { - //Refresh_StringTimbre(last_value, &UI_Label[GUI_TIMBRE_SELECT], &mGuiData[GUI_TIMBRE_SELECT]); - } + /* LCD 刷新转到 UI 任务执行:TaskBTRecv 栈仅 768B, + 直接绘制易栈溢出并与 UI 任务并发访问 LCD(死机/花屏) */ + MainTask_Sendmsg(MSG_ID_BLE_UI_REFRESH, GUI_TIMBRE_SELECT, 0, 0); if(nvm->param.Timbre != mGuiData[GUI_TIMBRE_SELECT].Current) { nvm->param.Timbre = mGuiData[GUI_TIMBRE_SELECT].Current; @@ -370,10 +373,7 @@ static void handleTranspose(uint8_t *data) return; } mGuiData[GUI_TRANSPOSE].Current = new_val; - if(mGuiData[GUI_TAB_INDEX].Current != 3) - { - Refresh_Transpose(&UI_Label[GUI_TRANSPOSE], &mGuiData[GUI_TRANSPOSE]); - } + MainTask_Sendmsg(MSG_ID_BLE_UI_REFRESH, GUI_TRANSPOSE, 0, 0); if(nvm->param.Transpose != mGuiData[GUI_TRANSPOSE].Current) { nvm->param.Transpose = mGuiData[GUI_TRANSPOSE].Current; @@ -432,10 +432,7 @@ static void handleBPM(uint8_t *data) return; } mGuiData[GUI_SPEED].Current = new_val; - if(mGuiData[GUI_TAB_INDEX].Current != 3) - { - Refresh_Transpose(&UI_Label[GUI_SPEED], &mGuiData[GUI_SPEED]); - } + MainTask_Sendmsg(MSG_ID_BLE_UI_REFRESH, GUI_SPEED, 0, 0); if(nvm->param.BPM != mGuiData[GUI_SPEED].Current) { nvm->param.BPM = mGuiData[GUI_SPEED].Current; @@ -787,9 +784,17 @@ static void handleRhythmStyle(uint8_t *data) id = slot->Max; mGuiData[GUI_AUTOBAND_SW].Current = src; slot->Current = id; - StartFlag = 0; - AutoBandTop1_Stop(); - UI_ReloadTonePreset(); + /* 停伴奏+换库+LCD 刷新全部转到 UI 任务执行(MSG_ID_BLE_STYLE_SET): + TaskBTRecv 栈仅 768B,ReloadTone 深调用链在此溢出导致 hardfault */ + MainTask_Sendmsg(MSG_ID_BLE_STYLE_SET, 0, 0, 0); + /* 与本地切换一致同步 NVM 参数(本地路径同样不立即写 flash) */ + { + NvmParam_Type *nvm = drv_nvm_param_ptr(); + if (src) + nvm->param.Param2 = ParamGuiData[EXPRESS_MODE_PARAM].Current; + else + nvm->param.Param1 = ParamGuiData[SONG_MODE_PARAM].Current; + } /* doc: single-byte bpm; clamp >127 (App should read exact bpm via 03 06) */ resp[5] = (mGuiData[GUI_SPEED].Current > 0x7F) ? 0x7F : (uint8_t)mGuiData[GUI_SPEED].Current; diff --git a/task/task_init.c b/task/task_init.c index 896754f..99aae0c 100644 --- a/task/task_init.c +++ b/task/task_init.c @@ -36,6 +36,13 @@ void TaskUIThread_entry(void* parameter) { if(rt_mq_recv(UITask_msg, &xEvent, sizeof(DisplayTaskMessage_Type), RT_WAITING_FOREVER) == RT_EOK) { + /* BLE 写节奏风格:停伴奏+换库在任何页面都要执行,且必须在 UI 任务上下文 + (TaskBTRecv 栈仅 768B,ReloadTone 深调用链会溢出;本地触控路径同在此任务) */ + if (xEvent.MessageType == MSG_ID_BLE_STYLE_SET) + { + StartFlag = 0; + UI_ReloadTonePreset(); /* 内含 Stop_AutoBand */ + } CurrUIProcress(xEvent); } } @@ -93,6 +100,8 @@ void TaskMainThread_entry(void* parameter) case MSG_ID_POWOFF_CHARG: case MSG_ID_BATTERY_VALUE: case MSG_ID_TOUCH_LONG_REPEAT: + case MSG_ID_BLE_UI_REFRESH: + case MSG_ID_BLE_STYLE_SET: /* 业务消息:先做业务处理,再转发 UI 刷新 */ UITask_Sendmsg(xEvent.MessageType, xEvent.ID, xEvent.HiByte, xEvent.LoByte); break;