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 <cursoragent@cursor.com>
This commit is contained in:
yuquanjun 2026-09-19 19:07:23 +08:00
parent fd58637e9d
commit 287c3f6799
4 changed files with 83 additions and 15 deletions

View File

@ -29,6 +29,8 @@
#define MSG_ID_TAP_SPEED 25 #define MSG_ID_TAP_SPEED 25
#define MSG_ID_LOOP_LIGHT 26 #define MSG_ID_LOOP_LIGHT 26
#define MSG_ID_CHARG 27 #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_RESET false
#define GPIO_PIN_SET true #define GPIO_PIN_SET true

View File

@ -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; nvm->param.Param2 = ParamGuiData[EXPRESS_MODE_PARAM].Current;
else else
nvm->param.Param1 = ParamGuiData[SONG_MODE_PARAM].Current; 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; break;
case GUI_TIMBRE_SELECT: 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(); UI_ReloadTonePreset();
if (!UI_SetFocus(GUI_MODE_PARAM)) if (!UI_SetFocus(GUI_MODE_PARAM))
label_ModeSelece_ui(&UI_Label[GUI_MODE_PARAM],&mGuiData[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; return;
} }
else if(ID==GUI_PLAY_SECTION) else if(ID==GUI_PLAY_SECTION)
@ -492,6 +515,35 @@ void UI_SongMode_Process(DisplayTaskMessage_Type msg)
ResetAutoPowerCount(); ResetAutoPowerCount();
} }
break; 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: case MSG_ID_CHARG:
Show_Battery_Icon(msg.ID); Show_Battery_Icon(msg.ID);
break; break;

View File

@ -322,15 +322,18 @@ static void handleStringTimbre(uint8_t *data)
uint8_t new_val = data[6]; // <20>õ<EFBFBD><C3B5><EFBFBD><EFBFBD><EFBFBD>ɫֵ uint8_t new_val = data[6]; // <20>õ<EFBFBD><C3B5><EFBFBD><EFBFBD><EFBFBD>ɫֵ
// <20><><EFBFBD>ֵû<D6B5>䣬ֱ<E4A3AC><D6B1><EFBFBD>˳<EFBFBD><CBB3><EFBFBD><EFBFBD><EFBFBD>ˢ<EFBFBD><CBA2> // <20><><EFBFBD>ֵû<D6B5>䣬ֱ<E4A3AC><D6B1><EFBFBD>˳<EFBFBD><CBB3><EFBFBD><EFBFBD><EFBFBD>ˢ<EFBFBD><CBA2>
if (new_val > mGuiData[GUI_TIMBRE_SELECT].Max)
{
return;
}
if (new_val == mGuiData[GUI_TIMBRE_SELECT].Current) if (new_val == mGuiData[GUI_TIMBRE_SELECT].Current)
{ {
return; return;
} }
mGuiData[GUI_TIMBRE_SELECT].Current = new_val; mGuiData[GUI_TIMBRE_SELECT].Current = new_val;
if(mGuiData[GUI_TAB_INDEX].Current != 3) /* LCD 刷新转到 UI 任务执行:TaskBTRecv 栈仅 768B,
{ 直接绘制易栈溢出并与 UI 任务并发访问 LCD(死机/花屏) */
//Refresh_StringTimbre(last_value, &UI_Label[GUI_TIMBRE_SELECT], &mGuiData[GUI_TIMBRE_SELECT]); MainTask_Sendmsg(MSG_ID_BLE_UI_REFRESH, GUI_TIMBRE_SELECT, 0, 0);
}
if(nvm->param.Timbre != mGuiData[GUI_TIMBRE_SELECT].Current) if(nvm->param.Timbre != mGuiData[GUI_TIMBRE_SELECT].Current)
{ {
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; return;
} }
mGuiData[GUI_TRANSPOSE].Current = new_val; mGuiData[GUI_TRANSPOSE].Current = new_val;
if(mGuiData[GUI_TAB_INDEX].Current != 3) MainTask_Sendmsg(MSG_ID_BLE_UI_REFRESH, GUI_TRANSPOSE, 0, 0);
{
Refresh_Transpose(&UI_Label[GUI_TRANSPOSE], &mGuiData[GUI_TRANSPOSE]);
}
if(nvm->param.Transpose != mGuiData[GUI_TRANSPOSE].Current) if(nvm->param.Transpose != mGuiData[GUI_TRANSPOSE].Current)
{ {
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; return;
} }
mGuiData[GUI_SPEED].Current = new_val; mGuiData[GUI_SPEED].Current = new_val;
if(mGuiData[GUI_TAB_INDEX].Current != 3) MainTask_Sendmsg(MSG_ID_BLE_UI_REFRESH, GUI_SPEED, 0, 0);
{
Refresh_Transpose(&UI_Label[GUI_SPEED], &mGuiData[GUI_SPEED]);
}
if(nvm->param.BPM != mGuiData[GUI_SPEED].Current) if(nvm->param.BPM != mGuiData[GUI_SPEED].Current)
{ {
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; id = slot->Max;
mGuiData[GUI_AUTOBAND_SW].Current = src; mGuiData[GUI_AUTOBAND_SW].Current = src;
slot->Current = id; slot->Current = id;
StartFlag = 0; /* 停伴奏+换库+LCD 刷新全部转到 UI 任务执行(MSG_ID_BLE_STYLE_SET):
AutoBandTop1_Stop(); TaskBTRecv 栈仅 768B,ReloadTone 深调用链在此溢出导致 hardfault */
UI_ReloadTonePreset(); 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) */ /* doc: single-byte bpm; clamp >127 (App should read exact bpm via 03 06) */
resp[5] = (mGuiData[GUI_SPEED].Current > 0x7F) resp[5] = (mGuiData[GUI_SPEED].Current > 0x7F)
? 0x7F : (uint8_t)mGuiData[GUI_SPEED].Current; ? 0x7F : (uint8_t)mGuiData[GUI_SPEED].Current;

View File

@ -36,6 +36,13 @@ void TaskUIThread_entry(void* parameter)
{ {
if(rt_mq_recv(UITask_msg, &xEvent, sizeof(DisplayTaskMessage_Type), RT_WAITING_FOREVER) == RT_EOK) 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); CurrUIProcress(xEvent);
} }
} }
@ -93,6 +100,8 @@ void TaskMainThread_entry(void* parameter)
case MSG_ID_POWOFF_CHARG: case MSG_ID_POWOFF_CHARG:
case MSG_ID_BATTERY_VALUE: case MSG_ID_BATTERY_VALUE:
case MSG_ID_TOUCH_LONG_REPEAT: case MSG_ID_TOUCH_LONG_REPEAT:
case MSG_ID_BLE_UI_REFRESH:
case MSG_ID_BLE_STYLE_SET:
/* 业务消息:先做业务处理,再转发 UI 刷新 */ /* 业务消息:先做业务处理,再转发 UI 刷新 */
UITask_Sendmsg(xEvent.MessageType, xEvent.ID, xEvent.HiByte, xEvent.LoByte); UITask_Sendmsg(xEvent.MessageType, xEvent.ID, xEvent.HiByte, xEvent.LoByte);
break; break;