From 7fea9217271d4b89dbfb6a60412acbdfa2aad78f Mon Sep 17 00:00:00 2001 From: yuquanjun Date: Mon, 31 Aug 2026 11:24:10 +0800 Subject: [PATCH] Add J-Link RTT logging module with RAM ring buffer and dump tool. Log boot/power/touch/key/UI/NVM events; export via rtt_log_dump.py for field diagnostics. Co-authored-by: Cursor --- APP/app_log.c | 207 ++++++++++++++++++++++ APP/app_log.h | 66 +++++++ APP/app_tm1617.c | 1 + APP/app_tm1629.c | 1 + APP/app_touch.c | 7 +- Global/Global.c | 24 ++- UI/UI_Idle.c | 33 ++-- UI/UI_SongMode.c | 27 ++- UI/UI_global.c | 20 ++- device/LCD_ILI9341/Drv_ILI9341_Lcd_Dump.c | 8 + device/LCD_ILI9341/Drv_XPT2046_Touch.c | 10 +- driver/drv_nvm.c | 9 +- project/IAR_V7.4/YNGJ-GT1-M.ewp | 6 + project/inc/includes.h | 1 + project/src/main.c | 5 + task/task_init.c | 35 ++-- third_party/segger_rtt/SEGGER_RTT_Conf.h | 20 +-- tools/LOG_README.md | 54 ++++++ tools/rtt_log_dump.py | 184 +++++++++++++++++++ 19 files changed, 662 insertions(+), 56 deletions(-) create mode 100644 APP/app_log.c create mode 100644 APP/app_log.h create mode 100644 tools/LOG_README.md create mode 100644 tools/rtt_log_dump.py diff --git a/APP/app_log.c b/APP/app_log.c new file mode 100644 index 0000000..9121606 --- /dev/null +++ b/APP/app_log.c @@ -0,0 +1,207 @@ +#include "includes.h" +#include "SEGGER_RTT.h" +#include + +#if APP_LOG_ENABLE + +static char s_slots[APP_LOG_SLOT_COUNT][APP_LOG_SLOT_SIZE]; +static uint16_t s_head; +static uint16_t s_count; +static uint32_t s_overflow; +static uint32_t s_boot_count; +static char s_ui_page[16] = "boot"; +static char s_debug_level = 'D'; +static char s_cmd_buf[48]; +static uint8_t s_cmd_len; + +static uint32_t app_log_ms(void) +{ + return (uint32_t)(rt_tick_get() * 1000U / RT_TICK_PER_SECOND); +} + +static void app_log_slot_store(const char *line) +{ + uint16_t idx = s_head; + + strncpy(s_slots[idx], line, APP_LOG_SLOT_SIZE - 1U); + s_slots[idx][APP_LOG_SLOT_SIZE - 1U] = '\0'; + s_head = (uint16_t)((s_head + 1U) % APP_LOG_SLOT_COUNT); + if (s_count < APP_LOG_SLOT_COUNT) { + s_count++; + } else { + s_overflow++; + } +} + +void app_log_set_ui_page(const char *name) +{ + if (name == NULL) { + return; + } + strncpy(s_ui_page, name, sizeof(s_ui_page) - 1U); + s_ui_page[sizeof(s_ui_page) - 1U] = '\0'; +} + +void app_log_write(char level, const char *cat, const char *fmt, ...) +{ + char line[APP_LOG_SLOT_SIZE]; + va_list ap; + int n; + + if (level == 'D' && s_debug_level != 'D') { + return; + } + + n = snprintf(line, sizeof(line), "[%05u][%c][%-4s] ", + (unsigned)app_log_ms(), level, cat); + if (n < 0) { + return; + } + if ((size_t)n >= sizeof(line)) { + n = (int)sizeof(line) - 1; + } + + va_start(ap, fmt); + vsnprintf(line + n, sizeof(line) - (size_t)n, fmt, ap); + va_end(ap); + + app_log_slot_store(line); + SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, line); + SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "\n"); +} + +static void app_log_dump_ram(void) +{ + uint16_t start; + uint16_t i; + + SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "LOG_DUMP_BEGIN\n"); + { + char meta[APP_LOG_SLOT_SIZE]; + snprintf(meta, sizeof(meta), + "meta boot=%u lines=%u overflow=%u ui=%s", + (unsigned)s_boot_count, + (unsigned)s_count, + (unsigned)s_overflow, + s_ui_page); + SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, meta); + SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "\n"); + } + + if (s_count == 0U) { + SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "LOG_DUMP_END\n"); + return; + } + + start = (s_count < APP_LOG_SLOT_COUNT) + ? 0U + : s_head; + for (i = 0; i < s_count; i++) { + uint16_t idx = (uint16_t)((start + i) % APP_LOG_SLOT_COUNT); + SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, s_slots[idx]); + SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "\n"); + } + SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "LOG_DUMP_END\n"); +} + +static void app_log_clear_ram(void) +{ + s_head = 0U; + s_count = 0U; + s_overflow = 0U; + memset(s_slots, 0, sizeof(s_slots)); + LOG_I("LOG", "ram cleared"); +} + +static void app_log_print_status(void) +{ + char line[APP_LOG_SLOT_SIZE]; + + snprintf(line, sizeof(line), + "LOG_STATUS boot=%u lines=%u overflow=%u level=%c ui=%s tick=%u", + (unsigned)s_boot_count, + (unsigned)s_count, + (unsigned)s_overflow, + s_debug_level, + s_ui_page, + (unsigned)app_log_ms()); + SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, line); + SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "\n"); +} + +uint8_t app_log_try_command(const char *cmd) +{ + if (cmd == NULL || cmd[0] == '\0') { + return 0U; + } + + if (strncmp(cmd, "log dump", 8) == 0) { + app_log_dump_ram(); + return 1U; + } + if (strncmp(cmd, "log clear", 9) == 0) { + app_log_clear_ram(); + return 1U; + } + if (strncmp(cmd, "log status", 10) == 0) { + app_log_print_status(); + return 1U; + } + if (strncmp(cmd, "log level ", 10) == 0 && cmd[10] != '\0') { + s_debug_level = cmd[10]; + LOG_I("LOG", "level set %c", s_debug_level); + return 1U; + } + return 0U; +} + +static void app_log_feed_char(char c) +{ + if (c == '\r' || c == '\n' || c == '\0') { + if (s_cmd_len > 0U) { + s_cmd_buf[s_cmd_len] = '\0'; + (void)app_log_try_command(s_cmd_buf); + } + s_cmd_len = 0U; + s_cmd_buf[0] = '\0'; + return; + } + + if (s_cmd_len + 1U >= sizeof(s_cmd_buf)) { + s_cmd_len = 0U; + } + s_cmd_buf[s_cmd_len++] = c; + s_cmd_buf[s_cmd_len] = '\0'; +} + +void app_log_poll(void) +{ + char rx[16]; + unsigned read_len; + unsigned i; + + read_len = SEGGER_RTT_Read(APP_LOG_RTT_CHANNEL, rx, sizeof(rx)); + if (read_len == 0U) { + return; + } + + for (i = 0; i < read_len; i++) { + app_log_feed_char(rx[i]); + } +} + +void app_log_init(void) +{ + s_boot_count++; + LOG_I("BOOT", "app_log init boot=%u", (unsigned)s_boot_count); +} + +#else + +void app_log_init(void) {} +void app_log_write(char level, const char *cat, const char *fmt, ...) { (void)level; (void)cat; (void)fmt; } +void app_log_poll(void) {} +uint8_t app_log_try_command(const char *cmd) { (void)cmd; return 0U; } +void app_log_set_ui_page(const char *name) { (void)name; } + +#endif /* APP_LOG_ENABLE */ diff --git a/APP/app_log.h b/APP/app_log.h new file mode 100644 index 0000000..3b736b6 --- /dev/null +++ b/APP/app_log.h @@ -0,0 +1,66 @@ +#ifndef __APP_LOG_H__ +#define __APP_LOG_H__ + +#include + +#ifndef APP_LOG_ENABLE +#define APP_LOG_ENABLE 1 +#endif + +#ifndef APP_LOG_DEBUG +#define APP_LOG_DEBUG 1 +#endif + +#ifndef APP_LOG_RAM_SIZE +#define APP_LOG_RAM_SIZE (4U * 1024U) +#endif + +#ifndef APP_LOG_SLOT_SIZE +#define APP_LOG_SLOT_SIZE 128U +#endif + +#ifndef APP_LOG_RTT_CHANNEL +#define APP_LOG_RTT_CHANNEL 0 +#endif + +#ifndef APP_LOG_TP_VERBOSE +#define APP_LOG_TP_VERBOSE 1 +#endif + +#define APP_LOG_SLOT_COUNT (APP_LOG_RAM_SIZE / APP_LOG_SLOT_SIZE) + +void app_log_init(void); +void app_log_write(char level, const char *cat, const char *fmt, ...); +void app_log_poll(void); +uint8_t app_log_try_command(const char *cmd); +void app_log_set_ui_page(const char *name); + +#if APP_LOG_ENABLE + +#define LOG_I(cat, fmt, ...) app_log_write('I', (cat), (fmt), ##__VA_ARGS__) +#define LOG_W(cat, fmt, ...) app_log_write('W', (cat), (fmt), ##__VA_ARGS__) +#define LOG_E(cat, fmt, ...) app_log_write('E', (cat), (fmt), ##__VA_ARGS__) + +#if APP_LOG_DEBUG +#define LOG_D(cat, fmt, ...) app_log_write('D', (cat), (fmt), ##__VA_ARGS__) +#else +#define LOG_D(cat, fmt, ...) ((void)0) +#endif + +#if APP_LOG_TP_VERBOSE +#define LOG_TP(fmt, ...) LOG_D("TP", fmt, ##__VA_ARGS__) +#else +#define LOG_TP(fmt, ...) ((void)0) +#endif + +#else + +#define LOG_I(cat, fmt, ...) ((void)0) +#define LOG_W(cat, fmt, ...) ((void)0) +#define LOG_E(cat, fmt, ...) ((void)0) +#define LOG_D(cat, fmt, ...) ((void)0) +#define LOG_TP(fmt, ...) ((void)0) + +#endif + +#endif /* __APP_LOG_H__ */ diff --git a/APP/app_tm1617.c b/APP/app_tm1617.c index 6b3d638..d0b681f 100644 --- a/APP/app_tm1617.c +++ b/APP/app_tm1617.c @@ -78,6 +78,7 @@ uint8_t app_tm1617_scan_key(void) if (key != key_last) { key_last = key; + LOG_I("KEY", "tm1617 key=%u", (unsigned)key); TM1617_Handle(key); return key; } diff --git a/APP/app_tm1629.c b/APP/app_tm1629.c index fb51397..309af2a 100644 --- a/APP/app_tm1629.c +++ b/APP/app_tm1629.c @@ -31,6 +31,7 @@ uint8_t app_tm1629_Scan_Key(void) if(key != key_last) { key_last = key; + LOG_I("KEY", "tm1629 key=%u", (unsigned)key); TM1629_Handle(key); return key; } diff --git a/APP/app_touch.c b/APP/app_touch.c index 98a2b3d..b1aca92 100644 --- a/APP/app_touch.c +++ b/APP/app_touch.c @@ -1,6 +1,6 @@ #include "includes.h" -/* 按下即发点击;抬起仅补发未发出的短按 */ +/* ?????????????????????????????? */ typedef enum { TOUCH_IDLE, @@ -58,6 +58,7 @@ app_touch_result_t app_touch_process(uint16_t x, uint16_t y, uint8_t pressed) r.gesture = GESTURE_RELEASE; r.x = down_x; r.y = down_y; + LOG_D("TP", "release x=%u y=%u", (unsigned)down_x, (unsigned)down_y); MainTask_Sendmsg(MSG_ID_TOUCH, 1, down_x, down_y); } touch_state = TOUCH_IDLE; @@ -79,8 +80,9 @@ app_touch_result_t app_touch_process(uint16_t x, uint16_t y, uint8_t pressed) click_sent = 0; repeat_tick = 0; touch_state = TOUCH_PRESS_WAIT_STABLE; - /* 第一帧就发点击,模式选择等页跟手 */ + /* ??????????????????????? */ click_sent = 1; + LOG_D("TP", "press down x=%u y=%u", (unsigned)down_x, (unsigned)down_y); MainTask_Sendmsg(MSG_ID_TOUCH, 1, down_x, down_y); break; @@ -101,6 +103,7 @@ app_touch_result_t app_touch_process(uint16_t x, uint16_t y, uint8_t pressed) long_press_fired = 1; repeat_tick = now; r.gesture = GESTURE_LONG_PRESS; + LOG_D("TP", "long_press x=%u y=%u", (unsigned)down_x, (unsigned)down_y); MainTask_Sendmsg(MSG_ID_TOUCH_LONG_REPEAT, 1, down_x, down_y); return r; } diff --git a/Global/Global.c b/Global/Global.c index cb990f6..7576797 100644 --- a/Global/Global.c +++ b/Global/Global.c @@ -96,12 +96,22 @@ bool AutoCloseFlag = true; void MainTask_Sendmsg(uint16_t ID, uint16_t ID2, uint16_t HiByte, uint16_t LoByte) { DisplayTaskMessage_Type msg; + rt_err_t ret; msg.MessageType = ID; /* 涓氬姟娑堟伅 ID锛圡SG_ID_xxx锛 */ msg.ID = ID2; msg.HiByte = HiByte; msg.LoByte = LoByte; - rt_mq_send(MainTask_msg, &msg, sizeof(DisplayTaskMessage_Type)); + ret = rt_mq_send(MainTask_msg, &msg, sizeof(DisplayTaskMessage_Type)); + + if (ret != RT_EOK) { + LOG_E("MSG", "send fail id=%u ret=%d", (unsigned)ID, (int)ret); + } else if (ID == MSG_ID_TOUCH || ID == MSG_ID_TOUCH_LONG_REPEAT || + ID == MSG_ID_POWER_ON || ID == MSG_ID_POWER_OFF || + ID == MSG_ID_BP_KEY || ID == MSG_ID_TAP_SPEED || + ID == MSG_ID_BP_TRANSPOSE) { + LOG_I("MSG", "id=%u hi=%u lo=%u", (unsigned)ID, (unsigned)HiByte, (unsigned)LoByte); + } } @@ -153,6 +163,7 @@ bool powon = false; /* ==================== 寮鏈/鍏虫満鍔ㄤ綔 ==================== */ void System_PowerOn(void) { + LOG_I("PWR", "power_on begin"); /* 鎺у埗鐢垫簮纭欢 */ BSP_MainPowerEnable(1); BSP_DreamCorePowerEnable(1); @@ -165,6 +176,7 @@ void System_PowerOn(void) app_tm1617_init(); XPT2046_Init(); App_Auto_Init(); + LOG_I("PWR", "periph ready send POWER_ON"); /* 閫氱煡 UI 灞傜敾寮鏈虹晫闈 */ MainTask_Sendmsg(MSG_ID_POWER_ON,0,0,0); } @@ -176,10 +188,14 @@ static void PowerOn(void) static void PowerOff(void) { + uint8_t nvm_ret; + + LOG_I("PWR", "power_off begin"); powon = false; /* 鏇存柊鍏虫満鏍囧織 */ StopFullTask(); - drv_nvm_save_to_flash(); + nvm_ret = drv_nvm_save_to_flash(); + LOG_I("PWR", "nvm_save=%u", (unsigned)nvm_ret); LCD_FillByColor(0, 0, 240, 320, BLACK); LCD_BLK_Clr(); @@ -192,6 +208,7 @@ static void PowerOff(void) BSP_DreamCorePowerEnable(0); BSP_HT7178PowerEnable(0); BSP_BlueToothPowerEnable(0); + LOG_I("PWR", "reset"); __disable_irq(); nvic_system_reset(); //MainTask_Sendmsg(MSG_ID_POWER_OFF,0,0,0); @@ -210,6 +227,7 @@ void Power_Key_Scan() if (s_auto_poweron_pending) { s_auto_poweron_pending = 0; + LOG_I("PWR", "auto power_on"); PowerOn(); pwr_key_state = KEY_STATE_NONE; /* 蹇界暐寮鏈虹灛闂村彲鑳芥畫鐣欑殑鎸夐敭鐢靛钩 */ return; @@ -238,11 +256,13 @@ void Power_Key_Scan() /* 鐢 powon 鍖哄垎锛氬叧鏈洪暱鎸 3s 寮鏈猴紝寮鏈洪暱鎸 2s 鍏虫満 */ if(powon == false && holdtick >= PWR_ON_HOLD_MS) { + LOG_I("PWR", "key power_on hold=%u", (unsigned)holdtick); PowerOn(); pwr_key_state = KEY_STATE_NONE; } else if(powon == true && holdtick >= PWR_OFF_HOLD_MS) { + LOG_I("PWR", "key power_off hold=%u", (unsigned)holdtick); PowerOff(); pwr_key_state = KEY_STATE_NONE; } diff --git a/UI/UI_Idle.c b/UI/UI_Idle.c index 9d0ed2d..e603674 100644 --- a/UI/UI_Idle.c +++ b/UI/UI_Idle.c @@ -211,18 +211,29 @@ void IdleProcess(DisplayTaskMessage_Type msg) break; case MSG_ID_TOUCH: - for(uint8_t k=0; k= Touch_ModeSelect_Areas[k].x_min && msg.HiByte <= Touch_ModeSelect_Areas[k].x_max && - msg.LoByte >= Touch_ModeSelect_Areas[k].y_min && msg.LoByte <= Touch_ModeSelect_Areas[k].y_max ) - { - uint8_t row = (uint8_t)Touch_ModeSelect_Areas[k].Flag; - if (row == s_mode_select_focus) - Touch_Mode_Select_Action(Touch_ModeSelect_Areas[k].Flag, Touch_ModeSelect_Areas[k].ID, k); - else - UI_ModeSelect_SetFocus(row); - break; - } + uint8_t hit = 0U; + for(uint8_t k=0; k= Touch_ModeSelect_Areas[k].x_min && msg.HiByte <= Touch_ModeSelect_Areas[k].x_max && + msg.LoByte >= Touch_ModeSelect_Areas[k].y_min && msg.LoByte <= Touch_ModeSelect_Areas[k].y_max ) + { + hit = 1U; + uint8_t row = (uint8_t)Touch_ModeSelect_Areas[k].Flag; + LOG_I("UI", "mode_select hit area=%u row=%u x=%u y=%u", + (unsigned)k, (unsigned)row, + (unsigned)msg.HiByte, (unsigned)msg.LoByte); + if (row == s_mode_select_focus) + Touch_Mode_Select_Action(Touch_ModeSelect_Areas[k].Flag, Touch_ModeSelect_Areas[k].ID, k); + else + UI_ModeSelect_SetFocus(row); + break; + } + } + if (!hit) { + LOG_I("UI", "mode_select miss x=%u y=%u", + (unsigned)msg.HiByte, (unsigned)msg.LoByte); + } } break; diff --git a/UI/UI_SongMode.c b/UI/UI_SongMode.c index 4b4393d..1f844a2 100644 --- a/UI/UI_SongMode.c +++ b/UI/UI_SongMode.c @@ -377,14 +377,25 @@ void UI_SongMode_Process(DisplayTaskMessage_Type msg) switch(msg.MessageType) { case MSG_ID_TOUCH: - for(uint8_t k=0; k= pCurrentTouch_Area[k].x_min && msg.HiByte <= pCurrentTouch_Area[k].x_max && - msg.LoByte >= pCurrentTouch_Area[k].y_min && msg.LoByte <= pCurrentTouch_Area[k].y_max ) - { - Touch_Action(pCurrentTouch_Area[k].Flag,pCurrentTouch_Area[k].ID,k,pCurrentTouch_Area[k].Value); - ResetAutoPowerCount(); - break; + { + uint8_t hit = 0U; + for(uint8_t k=0; k= pCurrentTouch_Area[k].x_min && msg.HiByte <= pCurrentTouch_Area[k].x_max && + msg.LoByte >= pCurrentTouch_Area[k].y_min && msg.LoByte <= pCurrentTouch_Area[k].y_max ) + { + hit = 1U; + LOG_I("UI", "song hit area=%u id=%u x=%u y=%u", + (unsigned)k, (unsigned)pCurrentTouch_Area[k].ID, + (unsigned)msg.HiByte, (unsigned)msg.LoByte); + Touch_Action(pCurrentTouch_Area[k].Flag,pCurrentTouch_Area[k].ID,k,pCurrentTouch_Area[k].Value); + ResetAutoPowerCount(); + break; + } + } + if (!hit) { + LOG_I("UI", "song miss x=%u y=%u", + (unsigned)msg.HiByte, (unsigned)msg.LoByte); } } break; diff --git a/UI/UI_global.c b/UI/UI_global.c index ad3da65..3c91f98 100644 --- a/UI/UI_global.c +++ b/UI/UI_global.c @@ -32,44 +32,60 @@ void InitMenuUI(void) { // 锟斤拷锟斤拷 UI 锟斤拷锟矫猴拷锟斤拷 // ============================================== void CallUI_Idle(void) { - CurrUIProcress = IdleProcess; + CurrUIProcress = IdleProcess; + app_log_set_ui_page("Idle"); + LOG_I("UI", "page Idle"); } void CallUI_SongMode(void) { UI_SongMode_Init(); CurrUIProcress = UI_SongMode_Process; + app_log_set_ui_page("Song"); + LOG_I("UI", "page SongMode tab=%u", (unsigned)mGuiData[GUI_TAB_INDEX].Current); } void CallUI_ExpertMode(void) { UI_ExpertMode_Init(); // CurrUIProcress = UI_ExpertMode_Process; CurrUIProcress = UI_SongMode_Process; + app_log_set_ui_page("Expert"); + LOG_I("UI", "page ExpertMode"); } void CallUI_FreeMode(void) { - UI_FreeMode_Init(); + UI_FreeMode_Init(); // CurrUIProcress = UI_FreeMode_Process; CurrUIProcress = UI_SongMode_Process; + app_log_set_ui_page("Free"); + LOG_I("UI", "page FreeMode"); } void CallUI_Setting(void) { CurrUIProcress = UI_Setting_Process; UI_Setting_Init(); + app_log_set_ui_page("Setting"); + LOG_I("UI", "page Setting"); } void CallUI_Mixer(void) { CurrUIProcress = UI_Mixer_Process; UI_Mixer_Init(); + app_log_set_ui_page("Mixer"); + LOG_I("UI", "page Mixer"); } void CallUI_SystemSetting(void) { CurrUIProcress = UI_SystemSet_Process; UI_SystemSet_Init(); + app_log_set_ui_page("SysSet"); + LOG_I("UI", "page SystemSetting"); } void CallUI_RestoreSelect(void) { CurrUIProcress = UI_Restore_Select_Process; UI_Restore_Select_Init(); + app_log_set_ui_page("Restore"); + LOG_I("UI", "page Restore"); } static uint8_t s_ui_focus_id = UI_FOCUS_NONE; diff --git a/device/LCD_ILI9341/Drv_ILI9341_Lcd_Dump.c b/device/LCD_ILI9341/Drv_ILI9341_Lcd_Dump.c index d94ef95..dc91780 100644 --- a/device/LCD_ILI9341/Drv_ILI9341_Lcd_Dump.c +++ b/device/LCD_ILI9341/Drv_ILI9341_Lcd_Dump.c @@ -198,6 +198,14 @@ static uint8_t LCD_Dump_CommandPending(void) char c = rx[i]; if (c == '\r' || c == '\n' || c == '\0') { + if (s_cmd_len > 0U) { + s_cmd_buf[s_cmd_len] = '\0'; + if (app_log_try_command(s_cmd_buf)) { + s_cmd_len = 0U; + s_cmd_buf[0] = '\0'; + continue; + } + } s_cmd_len = 0U; s_cmd_buf[0] = '\0'; continue; diff --git a/device/LCD_ILI9341/Drv_XPT2046_Touch.c b/device/LCD_ILI9341/Drv_XPT2046_Touch.c index acc2403..b50e365 100644 --- a/device/LCD_ILI9341/Drv_XPT2046_Touch.c +++ b/device/LCD_ILI9341/Drv_XPT2046_Touch.c @@ -143,9 +143,12 @@ TP_Point TP_ReadRaw(void) TP_Point p = {0, 0, 0}; uint32_t x_sum = 0, y_sum = 0; uint8_t i; + static uint8_t s_raw_logged; - if (!TP_CheckPressed(3)) + if (!TP_CheckPressed(3)) { + s_raw_logged = 0U; return p; + } for (i = 0; i < 5; i++) { @@ -178,6 +181,11 @@ TP_Point TP_ReadRaw(void) } p.pressed = 1; + if (!s_raw_logged) { + LOG_TP("raw x=%u y=%u irq=%u", (unsigned)p.x, (unsigned)p.y, + (unsigned)(TP_IRQ_Read() == 0U)); + s_raw_logged = 1U; + } return p; } diff --git a/driver/drv_nvm.c b/driver/drv_nvm.c index efcfcb7..be290e1 100644 --- a/driver/drv_nvm.c +++ b/driver/drv_nvm.c @@ -79,7 +79,7 @@ void drv_nvm_init(void) dataSum1 = ~dataSum0; if ((dataSum0 != mNvmData.sum[0]) || (dataSum1 != mNvmData.sum[1]) || (mNvmData.data.nvm_version != NVM_VERSION)) { - // load default value; + LOG_W("NVM", "checksum fail load default ver=%u", (unsigned)mNvmData.data.nvm_version); drv_nvm_load_default_value(&mNvmData.data); drv_nvm_save_to_flash(); }else @@ -88,7 +88,8 @@ void drv_nvm_init(void) drv_nvm_save_to_flash(); } memcpy(&mNvmDataShadow, &mNvmData, sizeof(NvmData_Type)); -} + LOG_I("NVM", "init ok ver=%u", (unsigned)mNvmData.data.nvm_version); +} NvmParam_Type * drv_nvm_param_ptr(void) { @@ -146,8 +147,9 @@ uint8_t drv_nvm_save_to_flash(void) uint32_t addr = INNER_FLASH_SAVE_ADDRESS; NvmData_Type * NvmDataToSave; - // 锟斤拷锟斤拷没锟戒化锟斤拷锟斤拷锟斤拷锟斤拷 + // 鏃犲彉鍖栦笉淇濆瓨 if (memcmp(&mNvmDataShadow, &mNvmData, sizeof(NvmData_Type)) == 0) { + LOG_D("NVM", "save skip unchanged"); return 0; } @@ -172,6 +174,7 @@ uint8_t drv_nvm_save_to_flash(void) flash_write_nocheck(addr,pData16,len); flash_lock(); + LOG_I("NVM", "saved to flash"); return 1; } diff --git a/project/IAR_V7.4/YNGJ-GT1-M.ewp b/project/IAR_V7.4/YNGJ-GT1-M.ewp index 0999d2b..8ff421a 100644 --- a/project/IAR_V7.4/YNGJ-GT1-M.ewp +++ b/project/IAR_V7.4/YNGJ-GT1-M.ewp @@ -2001,6 +2001,12 @@ $PROJ_DIR$\..\..\APP\app_touch.h + + $PROJ_DIR$\..\..\APP\app_log.c + + + $PROJ_DIR$\..\..\APP\app_log.h + AutoBand diff --git a/project/inc/includes.h b/project/inc/includes.h index c67e7f0..123d030 100644 --- a/project/inc/includes.h +++ b/project/inc/includes.h @@ -76,5 +76,6 @@ #include "app_tm1617.h" #include "app_touch.h" #include "app_adc.h" +#include "app_log.h" #endif \ No newline at end of file diff --git a/project/src/main.c b/project/src/main.c index 2cc941c..bfd1175 100644 --- a/project/src/main.c +++ b/project/src/main.c @@ -83,6 +83,7 @@ int main(void) bsp_init(); LCD_Init(); LCD_Dump_Init(); + app_log_init(); drv_nvm_init(); TaskInit(); timer_init(); @@ -90,6 +91,7 @@ int main(void) BSP_HT7178PowerEnable (1); BSP_ChargerEnable(1); CurrUIProcress = IdleProcess; + LOG_I("BOOT", "main init done ui=Idle"); /* add user code end 2 */ while(1) @@ -102,6 +104,9 @@ int main(void) /* add user code begin 3 */ Power_Key_Scan(); LCD_Dump_Poll(); +#if !DEBUG_LCD_DUMP + app_log_poll(); +#endif rt_thread_delay(1); /* add user code end 3 */ diff --git a/task/task_init.c b/task/task_init.c index 846e66b..72583f7 100644 --- a/task/task_init.c +++ b/task/task_init.c @@ -1,7 +1,6 @@ #include "includes.h" -#include "SEGGER_RTT.h" -static struct rt_thread TaskScanThread; +static struct rt_thread TaskScanThread; static struct rt_thread TaskUIThread; static struct rt_thread TaskTouchThread; static struct rt_thread TaskMainThread; @@ -51,9 +50,7 @@ void TaskTouchThread_entry(void* parameter) TP_Point tp = TP_Read(); /* 宸插惈杞翠氦鎹/闀滃儚锛岀洿鎺ヨ繘鎵嬪娍 */ if (tp.pressed && !s_last_pressed) { - char buf[40]; - sprintf(buf, "TP %u,%u\n", (unsigned)tp.x, (unsigned)tp.y); - SEGGER_RTT_WriteString(0, buf); + LOG_TP("down cal x=%u y=%u", (unsigned)tp.x, (unsigned)tp.y); } s_last_pressed = tp.pressed; app_touch_process(tp.x, tp.y, tp.pressed); @@ -154,7 +151,7 @@ rt_err_t TaskInit(void) BLTask_msg = rt_mq_create("BLTask msgQ",sizeof(DisplayTaskMessage_Type),128,RT_IPC_FLAG_FIFO); if(MainTask_msg == RT_NULL || UITask_msg == RT_NULL) { - __NOP(); + LOG_E("BOOT", "mq create fail main=%p ui=%p", MainTask_msg, UITask_msg); } ret = rt_thread_init(&TaskScanThread, @@ -316,18 +313,32 @@ void StartScanTask(void) void StopFullTask(void) { - if((TaskScanThread.stat & RT_THREAD_STAT_MASK) != RT_THREAD_CLOSE) + LOG_I("TASK", "StopFullTask begin"); + if((TaskScanThread.stat & RT_THREAD_STAT_MASK) != RT_THREAD_CLOSE) { + LOG_I("TASK", "stop ScanThread"); rt_thread_detach(&TaskScanThread); - if((TaskUIThread.stat & RT_THREAD_STAT_MASK) != RT_THREAD_CLOSE) + } + if((TaskUIThread.stat & RT_THREAD_STAT_MASK) != RT_THREAD_CLOSE) { + LOG_I("TASK", "stop UIThread"); rt_thread_detach(&TaskUIThread); - if((TaskTouchThread.stat & RT_THREAD_STAT_MASK) != RT_THREAD_CLOSE) + } + if((TaskTouchThread.stat & RT_THREAD_STAT_MASK) != RT_THREAD_CLOSE) { + LOG_I("TASK", "stop TouchThread"); rt_thread_detach(&TaskTouchThread); - if((TaskMainThread.stat & RT_THREAD_STAT_MASK) != RT_THREAD_CLOSE) + } + if((TaskMainThread.stat & RT_THREAD_STAT_MASK) != RT_THREAD_CLOSE) { + LOG_I("TASK", "stop MainThread"); rt_thread_detach(&TaskMainThread); - if((TaskBTHandleThread.stat & RT_THREAD_STAT_MASK) != RT_THREAD_CLOSE) + } + if((TaskBTHandleThread.stat & RT_THREAD_STAT_MASK) != RT_THREAD_CLOSE) { + LOG_I("TASK", "stop BTHandleThread"); rt_thread_detach(&TaskBTHandleThread); - if((TaskBTRecvThread.stat & RT_THREAD_STAT_MASK) != RT_THREAD_CLOSE) + } + if((TaskBTRecvThread.stat & RT_THREAD_STAT_MASK) != RT_THREAD_CLOSE) { + LOG_I("TASK", "stop BTRecvThread"); rt_thread_detach(&TaskBTRecvThread); + } + LOG_I("TASK", "StopFullTask done"); } diff --git a/third_party/segger_rtt/SEGGER_RTT_Conf.h b/third_party/segger_rtt/SEGGER_RTT_Conf.h index 1a97c83..8449f24 100644 --- a/third_party/segger_rtt/SEGGER_RTT_Conf.h +++ b/third_party/segger_rtt/SEGGER_RTT_Conf.h @@ -3,30 +3,20 @@ * The Embedded Experts * * www.segger.com * ********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* https://github.com/SEGGERMicro/RTT * -* * -********************************************************************** - ----------------------------END-OF-HEADER------------------------------ Purpose : User configuration file for RTT. For available configuration, refer to SEGGER_RTT_ConfDefaults.h. - ---------------------------------------------------------------------- */ #ifndef SEGGER_RTT_CONF_H #define SEGGER_RTT_CONF_H - -/********************************************************************* -* -* Defines, configurable -* -********************************************************************** -*/ +#define SEGGER_RTT_MAX_NUM_UP_BUFFERS (3) +#define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (3) +#define BUFFER_SIZE_UP (2048) +#define BUFFER_SIZE_DOWN (256) +#define SEGGER_RTT_PRINTF_BUFFER_SIZE (256u) #endif /*************************** End of file ****************************/ diff --git a/tools/LOG_README.md b/tools/LOG_README.md new file mode 100644 index 0000000..67170ae --- /dev/null +++ b/tools/LOG_README.md @@ -0,0 +1,54 @@ +# K1 璁惧鏃ュ織瀵煎嚭锛圝-Link RTT锛 + +## 鐢ㄩ + +鍥轰欢杩愯鏃跺皢鍚姩/鍏虫満銆佽Е鎽搞佹寜閿乁I 鍒囨崲銆佸紓甯哥瓑浜嬩欢鍐欏叆 RAM 鐜舰缂撳啿锛堢害 4KB / 32 鏉★級锛屽苟閫氳繃 SEGGER RTT 瀹炴椂杈撳嚭銆傜幇鍦哄鐜伴棶棰樺悗锛岀敤 J-Link 涓閿鍑烘棩蹇楁枃浠跺彂鍥炲垎鏋愩 + +## 鍓嶇疆鏉′欢 + +- J-Link 璋冭瘯鍣 + SWD 杩炴帴璁惧 +- Python 3.8+ +- 渚濊禆锛歚pip install pylink-square` +- 宸茬儳褰曞寘鍚 `app_log` 妯″潡鐨勫浐浠 + +## 鎿嶄綔姝ラ + +1. 璁惧涓婄數锛屽鐜伴棶棰橈紙渚嬪妯″紡閫夋嫨椤佃Е鎽告棤鍝嶅簲锛夈 +2. PC 杩炴帴 J-Link锛**涓嶈**闅忔剰 Reset锛堜細涓㈠け RAM 鏃ュ織锛涜嫢蹇呴』澶嶄綅锛岃鍏堝鍑烘垨澶嶇幇鍚庡啀瀵煎嚭锛夈 +3. 鍦ㄩ」鐩 `tools` 鐩綍鎵ц锛 + +```bash +python rtt_log_dump.py --out problem.log +``` + +4. 灏嗙敓鎴愮殑 `problem.log` 鍙戦佺粰鐮斿彂鍒嗘瀽銆 + +## 鍏朵粬 RTT 鍛戒护锛圧TT Viewer 缁堢杈撳叆锛 + +| 鍛戒护 | 璇存槑 | +|------|------| +| `log dump` | 瀵煎嚭 RAM 涓叏閮ㄥ巻鍙叉棩蹇 | +| `log clear` | 娓呯┖ RAM 鏃ュ織 | +| `log status` | 鏌ョ湅 boot 娆℃暟銆佹潯鏁般佹孩鍑恒佸綋鍓 UI 椤 | +| `log level D` | 寮鍚 Debug 绾э紙鍚Е鎽哥粏鑺傦級锛沗I` 浠 Info 浠ヤ笂 | + +## 鏃ュ織鏍煎紡 + +``` +[tick_ms][LVL][CAT] message key=val ... +``` + +绫诲埆 CAT锛歚BOOT` `PWR` `UI` `TP` `KEY` `MSG` `NVM` `TASK` `ERR` `ADC` + +## 閰嶅宸ュ叿 + +- 灞忓箷鎴浘锛歚python rtt_lcd_capture.py --out screen.png` +- 鏃ュ織瀵煎嚭锛歚python rtt_log_dump.py --out problem.log` + +## 瑙︽懜闂鎺掓煡瑕佺偣 + +瀵煎嚭鍚庨噸鐐 grep锛 + +- `[TP]` 鈥 raw/cal 鍧愭爣銆乮rq 鐘舵 +- `[MSG] id=12` 鈥 瑙︽懜娑堟伅鏄惁鍙戝嚭 +- `[UI] mode_select miss` 鈥 UI 鍛戒腑娴嬭瘯鏄惁澶辫触 diff --git a/tools/rtt_log_dump.py b/tools/rtt_log_dump.py new file mode 100644 index 0000000..c48340e --- /dev/null +++ b/tools/rtt_log_dump.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python3 +"""Pull K1 device log ring buffer via J-Link RTT (log dump command).""" + +from __future__ import annotations + +import argparse +import os +import sys +import time +from datetime import datetime + +DEFAULT_DEVICES = ("Cortex-M4", "AT32F403AC", "AT32F403A") +DUMP_CMD = b"log dump\n" +END_MARKERS = (b"LOG_DUMP_END",) + + +def import_deps(): + try: + import pylink # noqa: F401 + except ImportError as exc: + raise SystemExit("Missing dependency: pip install pylink-square") from exc + + +def connect_jlink(device: str): + import pylink + + jlink = pylink.JLink() + jlink.open() + try: + jlink.exec_command("HideDeviceSelection = 1") + except Exception: + pass + jlink.set_tif(pylink.enums.JLinkInterfaces.SWD) + + last_error = None + for candidate in (device, *DEFAULT_DEVICES): + try: + try: + jlink.exec_command(f"Device = {candidate}") + except Exception: + pass + jlink.connect(candidate) + print(f"Connected as {candidate}") + return jlink + except pylink.errors.JLinkException as exc: + last_error = exc + jlink.close() + raise SystemExit(f"Failed to connect J-Link: {last_error}") + + +def find_rtt_control_block(jlink, ram_base: int = 0x20000000, ram_size: int = 0x18000) -> int | None: + needle = b"SEGGER RTT" + chunk = 0x1000 + was_halted = jlink.halted() + if not was_halted: + jlink.halt() + try: + for off in range(0, ram_size, chunk): + data = bytes(jlink.memory_read8(ram_base + off, min(chunk, ram_size - off))) + idx = data.find(needle) + if idx >= 0: + return ram_base + off + idx + finally: + if not was_halted: + if hasattr(jlink, "restart"): + jlink.restart() + else: + jlink.go() + time.sleep(0.1) + return None + + +def wait_rtt_ready(jlink, timeout_s: float = 15.0) -> None: + deadline = time.time() + timeout_s + while time.time() < deadline: + try: + if jlink.rtt_get_num_up_buffers() > 0: + return + except Exception: + pass + time.sleep(0.2) + raise SystemExit("RTT control block found but buffers not ready") + + +def send_command(jlink, payload: bytes, retries: int = 30) -> None: + for _ in range(retries): + wrote = jlink.rtt_write(0, list(payload)) + if wrote > 0: + print(f"Sent command ({wrote} bytes): {payload.decode('ascii', errors='replace').strip()}") + return + time.sleep(0.2) + raise SystemExit("Failed to send RTT down command on channel 0") + + +def dump_log(out_path: str, device: str, timeout_s: float) -> None: + jlink = connect_jlink(device) + lines: list[str] = [] + try: + cb = find_rtt_control_block(jlink) + if cb is None: + raise SystemExit("SEGGER RTT control block not found in SRAM") + print(f"RTT CB @ 0x{cb:08X}") + + jlink.rtt_start(cb) + wait_rtt_ready(jlink) + + # Drain stale RTT output. + for _ in range(5): + stale = jlink.rtt_read(0, 4096) + if stale: + text = bytes(stale).decode("utf-8", errors="replace") + if text.strip(): + print("RTT0 stale:", text.strip()[:200]) + time.sleep(0.05) + + send_command(jlink, DUMP_CMD) + + buffer = b"" + deadline = time.time() + timeout_s + started = False + + while time.time() < deadline: + chunk = jlink.rtt_read(0, 4096) + if chunk: + buffer += bytes(chunk) + if not started and b"LOG_DUMP_BEGIN" in buffer: + started = True + if b"LOG_DUMP_END" in buffer: + break + else: + time.sleep(0.01) + + if b"LOG_DUMP_END" not in buffer: + raise SystemExit("Timeout waiting for LOG_DUMP_END (is firmware with app_log flashed?)") + + text = buffer.decode("utf-8", errors="replace") + capture = False + for line in text.splitlines(): + if line.strip() == "LOG_DUMP_BEGIN": + capture = True + continue + if line.strip() == "LOG_DUMP_END": + break + if capture: + lines.append(line) + + header = ( + f"# K1 log dump {datetime.now().isoformat(timespec='seconds')}\n" + f"# device={device}\n" + ) + body = "\n".join(lines) + ("\n" if lines else "") + with open(out_path, "w", encoding="utf-8", newline="\n") as f: + f.write(header) + f.write(body) + + print(f"Saved {len(lines)} log lines to {out_path}") + finally: + try: + jlink.rtt_stop() + except Exception: + pass + jlink.close() + + +def main() -> None: + parser = argparse.ArgumentParser(description="Dump K1 RAM log ring via J-Link RTT") + parser.add_argument( + "--out", + default=f"k1_log_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log", + help="Output log file path", + ) + parser.add_argument("--device", default="AT32F403AC", help="J-Link device name") + parser.add_argument("--timeout", type=float, default=20.0, help="Seconds to wait for dump") + args = parser.parse_args() + + import_deps() + dump_log(args.out, args.device, args.timeout) + + if os.name == "nt" and os.path.isfile(args.out): + print(f"Full path: {os.path.abspath(args.out)}") + + +if __name__ == "__main__": + main()