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 <cursoragent@cursor.com>
This commit is contained in:
parent
b8eaf2c808
commit
7fea921727
|
|
@ -0,0 +1,207 @@
|
||||||
|
#include "includes.h"
|
||||||
|
#include "SEGGER_RTT.h"
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#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 */
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
#ifndef __APP_LOG_H__
|
||||||
|
#define __APP_LOG_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#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__ */
|
||||||
|
|
@ -78,6 +78,7 @@ uint8_t app_tm1617_scan_key(void)
|
||||||
if (key != key_last)
|
if (key != key_last)
|
||||||
{
|
{
|
||||||
key_last = key;
|
key_last = key;
|
||||||
|
LOG_I("KEY", "tm1617 key=%u", (unsigned)key);
|
||||||
TM1617_Handle(key);
|
TM1617_Handle(key);
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ uint8_t app_tm1629_Scan_Key(void)
|
||||||
if(key != key_last)
|
if(key != key_last)
|
||||||
{
|
{
|
||||||
key_last = key;
|
key_last = key;
|
||||||
|
LOG_I("KEY", "tm1629 key=%u", (unsigned)key);
|
||||||
TM1629_Handle(key);
|
TM1629_Handle(key);
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
|
|
||||||
/* 按下即发点击;抬起仅补发未发出的短按 */
|
/* ?????????????????????????????? */
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
TOUCH_IDLE,
|
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.gesture = GESTURE_RELEASE;
|
||||||
r.x = down_x;
|
r.x = down_x;
|
||||||
r.y = down_y;
|
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);
|
MainTask_Sendmsg(MSG_ID_TOUCH, 1, down_x, down_y);
|
||||||
}
|
}
|
||||||
touch_state = TOUCH_IDLE;
|
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;
|
click_sent = 0;
|
||||||
repeat_tick = 0;
|
repeat_tick = 0;
|
||||||
touch_state = TOUCH_PRESS_WAIT_STABLE;
|
touch_state = TOUCH_PRESS_WAIT_STABLE;
|
||||||
/* 第一帧就发点击,模式选择等页跟手 */
|
/* ??????????????????????? */
|
||||||
click_sent = 1;
|
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);
|
MainTask_Sendmsg(MSG_ID_TOUCH, 1, down_x, down_y);
|
||||||
break;
|
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;
|
long_press_fired = 1;
|
||||||
repeat_tick = now;
|
repeat_tick = now;
|
||||||
r.gesture = GESTURE_LONG_PRESS;
|
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);
|
MainTask_Sendmsg(MSG_ID_TOUCH_LONG_REPEAT, 1, down_x, down_y);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -96,12 +96,22 @@ bool AutoCloseFlag = true;
|
||||||
void MainTask_Sendmsg(uint16_t ID, uint16_t ID2, uint16_t HiByte, uint16_t LoByte)
|
void MainTask_Sendmsg(uint16_t ID, uint16_t ID2, uint16_t HiByte, uint16_t LoByte)
|
||||||
{
|
{
|
||||||
DisplayTaskMessage_Type msg;
|
DisplayTaskMessage_Type msg;
|
||||||
|
rt_err_t ret;
|
||||||
|
|
||||||
msg.MessageType = ID; /* 业务消息 ID(MSG_ID_xxx) */
|
msg.MessageType = ID; /* 业务消息 ID(MSG_ID_xxx) */
|
||||||
msg.ID = ID2;
|
msg.ID = ID2;
|
||||||
msg.HiByte = HiByte;
|
msg.HiByte = HiByte;
|
||||||
msg.LoByte = LoByte;
|
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)
|
void System_PowerOn(void)
|
||||||
{
|
{
|
||||||
|
LOG_I("PWR", "power_on begin");
|
||||||
/* 控制电源硬件 */
|
/* 控制电源硬件 */
|
||||||
BSP_MainPowerEnable(1);
|
BSP_MainPowerEnable(1);
|
||||||
BSP_DreamCorePowerEnable(1);
|
BSP_DreamCorePowerEnable(1);
|
||||||
|
|
@ -165,6 +176,7 @@ void System_PowerOn(void)
|
||||||
app_tm1617_init();
|
app_tm1617_init();
|
||||||
XPT2046_Init();
|
XPT2046_Init();
|
||||||
App_Auto_Init();
|
App_Auto_Init();
|
||||||
|
LOG_I("PWR", "periph ready send POWER_ON");
|
||||||
/* 通知 UI 层画开机界面 */
|
/* 通知 UI 层画开机界面 */
|
||||||
MainTask_Sendmsg(MSG_ID_POWER_ON,0,0,0);
|
MainTask_Sendmsg(MSG_ID_POWER_ON,0,0,0);
|
||||||
}
|
}
|
||||||
|
|
@ -176,10 +188,14 @@ static void PowerOn(void)
|
||||||
|
|
||||||
static void PowerOff(void)
|
static void PowerOff(void)
|
||||||
{
|
{
|
||||||
|
uint8_t nvm_ret;
|
||||||
|
|
||||||
|
LOG_I("PWR", "power_off begin");
|
||||||
powon = false; /* 更新关机标志 */
|
powon = false; /* 更新关机标志 */
|
||||||
StopFullTask();
|
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_FillByColor(0, 0, 240, 320, BLACK);
|
||||||
LCD_BLK_Clr();
|
LCD_BLK_Clr();
|
||||||
|
|
@ -192,6 +208,7 @@ static void PowerOff(void)
|
||||||
BSP_DreamCorePowerEnable(0);
|
BSP_DreamCorePowerEnable(0);
|
||||||
BSP_HT7178PowerEnable(0);
|
BSP_HT7178PowerEnable(0);
|
||||||
BSP_BlueToothPowerEnable(0);
|
BSP_BlueToothPowerEnable(0);
|
||||||
|
LOG_I("PWR", "reset");
|
||||||
__disable_irq();
|
__disable_irq();
|
||||||
nvic_system_reset();
|
nvic_system_reset();
|
||||||
//MainTask_Sendmsg(MSG_ID_POWER_OFF,0,0,0);
|
//MainTask_Sendmsg(MSG_ID_POWER_OFF,0,0,0);
|
||||||
|
|
@ -210,6 +227,7 @@ void Power_Key_Scan()
|
||||||
if (s_auto_poweron_pending)
|
if (s_auto_poweron_pending)
|
||||||
{
|
{
|
||||||
s_auto_poweron_pending = 0;
|
s_auto_poweron_pending = 0;
|
||||||
|
LOG_I("PWR", "auto power_on");
|
||||||
PowerOn();
|
PowerOn();
|
||||||
pwr_key_state = KEY_STATE_NONE; /* 忽略开机瞬间可能残留的按键电平 */
|
pwr_key_state = KEY_STATE_NONE; /* 忽略开机瞬间可能残留的按键电平 */
|
||||||
return;
|
return;
|
||||||
|
|
@ -238,11 +256,13 @@ void Power_Key_Scan()
|
||||||
/* 用 powon 区分:关机长按 3s 开机,开机长按 2s 关机 */
|
/* 用 powon 区分:关机长按 3s 开机,开机长按 2s 关机 */
|
||||||
if(powon == false && holdtick >= PWR_ON_HOLD_MS)
|
if(powon == false && holdtick >= PWR_ON_HOLD_MS)
|
||||||
{
|
{
|
||||||
|
LOG_I("PWR", "key power_on hold=%u", (unsigned)holdtick);
|
||||||
PowerOn();
|
PowerOn();
|
||||||
pwr_key_state = KEY_STATE_NONE;
|
pwr_key_state = KEY_STATE_NONE;
|
||||||
}
|
}
|
||||||
else if(powon == true && holdtick >= PWR_OFF_HOLD_MS)
|
else if(powon == true && holdtick >= PWR_OFF_HOLD_MS)
|
||||||
{
|
{
|
||||||
|
LOG_I("PWR", "key power_off hold=%u", (unsigned)holdtick);
|
||||||
PowerOff();
|
PowerOff();
|
||||||
pwr_key_state = KEY_STATE_NONE;
|
pwr_key_state = KEY_STATE_NONE;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
33
UI/UI_Idle.c
33
UI/UI_Idle.c
|
|
@ -211,18 +211,29 @@ void IdleProcess(DisplayTaskMessage_Type msg)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MSG_ID_TOUCH:
|
case MSG_ID_TOUCH:
|
||||||
for(uint8_t k=0; k<TOUCH_AREA_MODE_SELECT_NUM; k++)
|
|
||||||
{
|
{
|
||||||
if( msg.HiByte >= Touch_ModeSelect_Areas[k].x_min && msg.HiByte <= Touch_ModeSelect_Areas[k].x_max &&
|
uint8_t hit = 0U;
|
||||||
msg.LoByte >= Touch_ModeSelect_Areas[k].y_min && msg.LoByte <= Touch_ModeSelect_Areas[k].y_max )
|
for(uint8_t k=0; k<TOUCH_AREA_MODE_SELECT_NUM; k++)
|
||||||
{
|
{
|
||||||
uint8_t row = (uint8_t)Touch_ModeSelect_Areas[k].Flag;
|
if( msg.HiByte >= Touch_ModeSelect_Areas[k].x_min && msg.HiByte <= Touch_ModeSelect_Areas[k].x_max &&
|
||||||
if (row == s_mode_select_focus)
|
msg.LoByte >= Touch_ModeSelect_Areas[k].y_min && msg.LoByte <= Touch_ModeSelect_Areas[k].y_max )
|
||||||
Touch_Mode_Select_Action(Touch_ModeSelect_Areas[k].Flag, Touch_ModeSelect_Areas[k].ID, k);
|
{
|
||||||
else
|
hit = 1U;
|
||||||
UI_ModeSelect_SetFocus(row);
|
uint8_t row = (uint8_t)Touch_ModeSelect_Areas[k].Flag;
|
||||||
break;
|
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;
|
break;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -377,14 +377,25 @@ void UI_SongMode_Process(DisplayTaskMessage_Type msg)
|
||||||
switch(msg.MessageType)
|
switch(msg.MessageType)
|
||||||
{
|
{
|
||||||
case MSG_ID_TOUCH:
|
case MSG_ID_TOUCH:
|
||||||
for(uint8_t k=0; k<TOUCH_AREA_NUM; k++)
|
{
|
||||||
{
|
uint8_t hit = 0U;
|
||||||
if( msg.HiByte >= pCurrentTouch_Area[k].x_min && msg.HiByte <= pCurrentTouch_Area[k].x_max &&
|
for(uint8_t k=0; k<TOUCH_AREA_NUM; k++)
|
||||||
msg.LoByte >= pCurrentTouch_Area[k].y_min && msg.LoByte <= pCurrentTouch_Area[k].y_max )
|
{
|
||||||
{
|
if( msg.HiByte >= pCurrentTouch_Area[k].x_min && msg.HiByte <= pCurrentTouch_Area[k].x_max &&
|
||||||
Touch_Action(pCurrentTouch_Area[k].Flag,pCurrentTouch_Area[k].ID,k,pCurrentTouch_Area[k].Value);
|
msg.LoByte >= pCurrentTouch_Area[k].y_min && msg.LoByte <= pCurrentTouch_Area[k].y_max )
|
||||||
ResetAutoPowerCount();
|
{
|
||||||
break;
|
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;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -32,44 +32,60 @@ void InitMenuUI(void) {
|
||||||
// <20><><EFBFBD><EFBFBD> UI <20><><EFBFBD>ú<EFBFBD><C3BA><EFBFBD>
|
// <20><><EFBFBD><EFBFBD> UI <20><><EFBFBD>ú<EFBFBD><C3BA><EFBFBD>
|
||||||
// ==============================================
|
// ==============================================
|
||||||
void CallUI_Idle(void) {
|
void CallUI_Idle(void) {
|
||||||
CurrUIProcress = IdleProcess;
|
CurrUIProcress = IdleProcess;
|
||||||
|
app_log_set_ui_page("Idle");
|
||||||
|
LOG_I("UI", "page Idle");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallUI_SongMode(void) {
|
void CallUI_SongMode(void) {
|
||||||
UI_SongMode_Init();
|
UI_SongMode_Init();
|
||||||
CurrUIProcress = UI_SongMode_Process;
|
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) {
|
void CallUI_ExpertMode(void) {
|
||||||
UI_ExpertMode_Init();
|
UI_ExpertMode_Init();
|
||||||
// CurrUIProcress = UI_ExpertMode_Process;
|
// CurrUIProcress = UI_ExpertMode_Process;
|
||||||
CurrUIProcress = UI_SongMode_Process;
|
CurrUIProcress = UI_SongMode_Process;
|
||||||
|
app_log_set_ui_page("Expert");
|
||||||
|
LOG_I("UI", "page ExpertMode");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallUI_FreeMode(void) {
|
void CallUI_FreeMode(void) {
|
||||||
UI_FreeMode_Init();
|
UI_FreeMode_Init();
|
||||||
// CurrUIProcress = UI_FreeMode_Process;
|
// CurrUIProcress = UI_FreeMode_Process;
|
||||||
CurrUIProcress = UI_SongMode_Process;
|
CurrUIProcress = UI_SongMode_Process;
|
||||||
|
app_log_set_ui_page("Free");
|
||||||
|
LOG_I("UI", "page FreeMode");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallUI_Setting(void) {
|
void CallUI_Setting(void) {
|
||||||
CurrUIProcress = UI_Setting_Process;
|
CurrUIProcress = UI_Setting_Process;
|
||||||
UI_Setting_Init();
|
UI_Setting_Init();
|
||||||
|
app_log_set_ui_page("Setting");
|
||||||
|
LOG_I("UI", "page Setting");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallUI_Mixer(void) {
|
void CallUI_Mixer(void) {
|
||||||
CurrUIProcress = UI_Mixer_Process;
|
CurrUIProcress = UI_Mixer_Process;
|
||||||
UI_Mixer_Init();
|
UI_Mixer_Init();
|
||||||
|
app_log_set_ui_page("Mixer");
|
||||||
|
LOG_I("UI", "page Mixer");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallUI_SystemSetting(void) {
|
void CallUI_SystemSetting(void) {
|
||||||
CurrUIProcress = UI_SystemSet_Process;
|
CurrUIProcress = UI_SystemSet_Process;
|
||||||
UI_SystemSet_Init();
|
UI_SystemSet_Init();
|
||||||
|
app_log_set_ui_page("SysSet");
|
||||||
|
LOG_I("UI", "page SystemSetting");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallUI_RestoreSelect(void) {
|
void CallUI_RestoreSelect(void) {
|
||||||
CurrUIProcress = UI_Restore_Select_Process;
|
CurrUIProcress = UI_Restore_Select_Process;
|
||||||
UI_Restore_Select_Init();
|
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;
|
static uint8_t s_ui_focus_id = UI_FOCUS_NONE;
|
||||||
|
|
|
||||||
|
|
@ -198,6 +198,14 @@ static uint8_t LCD_Dump_CommandPending(void)
|
||||||
char c = rx[i];
|
char c = rx[i];
|
||||||
|
|
||||||
if (c == '\r' || c == '\n' || c == '\0') {
|
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_len = 0U;
|
||||||
s_cmd_buf[0] = '\0';
|
s_cmd_buf[0] = '\0';
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
|
|
@ -143,9 +143,12 @@ TP_Point TP_ReadRaw(void)
|
||||||
TP_Point p = {0, 0, 0};
|
TP_Point p = {0, 0, 0};
|
||||||
uint32_t x_sum = 0, y_sum = 0;
|
uint32_t x_sum = 0, y_sum = 0;
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
|
static uint8_t s_raw_logged;
|
||||||
|
|
||||||
if (!TP_CheckPressed(3))
|
if (!TP_CheckPressed(3)) {
|
||||||
|
s_raw_logged = 0U;
|
||||||
return p;
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < 5; i++)
|
for (i = 0; i < 5; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -178,6 +181,11 @@ TP_Point TP_ReadRaw(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
p.pressed = 1;
|
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;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ void drv_nvm_init(void)
|
||||||
dataSum1 = ~dataSum0;
|
dataSum1 = ~dataSum0;
|
||||||
|
|
||||||
if ((dataSum0 != mNvmData.sum[0]) || (dataSum1 != mNvmData.sum[1]) || (mNvmData.data.nvm_version != NVM_VERSION)) {
|
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_load_default_value(&mNvmData.data);
|
||||||
drv_nvm_save_to_flash();
|
drv_nvm_save_to_flash();
|
||||||
}else
|
}else
|
||||||
|
|
@ -88,7 +88,8 @@ void drv_nvm_init(void)
|
||||||
drv_nvm_save_to_flash();
|
drv_nvm_save_to_flash();
|
||||||
}
|
}
|
||||||
memcpy(&mNvmDataShadow, &mNvmData, sizeof(NvmData_Type));
|
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)
|
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;
|
uint32_t addr = INNER_FLASH_SAVE_ADDRESS;
|
||||||
NvmData_Type * NvmDataToSave;
|
NvmData_Type * NvmDataToSave;
|
||||||
|
|
||||||
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD>仯<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
// 无变化不保存
|
||||||
if (memcmp(&mNvmDataShadow, &mNvmData, sizeof(NvmData_Type)) == 0) {
|
if (memcmp(&mNvmDataShadow, &mNvmData, sizeof(NvmData_Type)) == 0) {
|
||||||
|
LOG_D("NVM", "save skip unchanged");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -172,6 +174,7 @@ uint8_t drv_nvm_save_to_flash(void)
|
||||||
flash_write_nocheck(addr,pData16,len);
|
flash_write_nocheck(addr,pData16,len);
|
||||||
flash_lock();
|
flash_lock();
|
||||||
|
|
||||||
|
LOG_I("NVM", "saved to flash");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2001,6 +2001,12 @@
|
||||||
<file>
|
<file>
|
||||||
<name>$PROJ_DIR$\..\..\APP\app_touch.h</name>
|
<name>$PROJ_DIR$\..\..\APP\app_touch.h</name>
|
||||||
</file>
|
</file>
|
||||||
|
<file>
|
||||||
|
<name>$PROJ_DIR$\..\..\APP\app_log.c</name>
|
||||||
|
</file>
|
||||||
|
<file>
|
||||||
|
<name>$PROJ_DIR$\..\..\APP\app_log.h</name>
|
||||||
|
</file>
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group>
|
||||||
<name>AutoBand</name>
|
<name>AutoBand</name>
|
||||||
|
|
|
||||||
|
|
@ -76,5 +76,6 @@
|
||||||
#include "app_tm1617.h"
|
#include "app_tm1617.h"
|
||||||
#include "app_touch.h"
|
#include "app_touch.h"
|
||||||
#include "app_adc.h"
|
#include "app_adc.h"
|
||||||
|
#include "app_log.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -83,6 +83,7 @@ int main(void)
|
||||||
bsp_init();
|
bsp_init();
|
||||||
LCD_Init();
|
LCD_Init();
|
||||||
LCD_Dump_Init();
|
LCD_Dump_Init();
|
||||||
|
app_log_init();
|
||||||
drv_nvm_init();
|
drv_nvm_init();
|
||||||
TaskInit();
|
TaskInit();
|
||||||
timer_init();
|
timer_init();
|
||||||
|
|
@ -90,6 +91,7 @@ int main(void)
|
||||||
BSP_HT7178PowerEnable (1);
|
BSP_HT7178PowerEnable (1);
|
||||||
BSP_ChargerEnable(1);
|
BSP_ChargerEnable(1);
|
||||||
CurrUIProcress = IdleProcess;
|
CurrUIProcress = IdleProcess;
|
||||||
|
LOG_I("BOOT", "main init done ui=Idle");
|
||||||
/* add user code end 2 */
|
/* add user code end 2 */
|
||||||
|
|
||||||
while(1)
|
while(1)
|
||||||
|
|
@ -102,6 +104,9 @@ int main(void)
|
||||||
/* add user code begin 3 */
|
/* add user code begin 3 */
|
||||||
Power_Key_Scan();
|
Power_Key_Scan();
|
||||||
LCD_Dump_Poll();
|
LCD_Dump_Poll();
|
||||||
|
#if !DEBUG_LCD_DUMP
|
||||||
|
app_log_poll();
|
||||||
|
#endif
|
||||||
|
|
||||||
rt_thread_delay(1);
|
rt_thread_delay(1);
|
||||||
/* add user code end 3 */
|
/* add user code end 3 */
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
#include "includes.h"
|
#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 TaskUIThread;
|
||||||
static struct rt_thread TaskTouchThread;
|
static struct rt_thread TaskTouchThread;
|
||||||
static struct rt_thread TaskMainThread;
|
static struct rt_thread TaskMainThread;
|
||||||
|
|
@ -51,9 +50,7 @@ void TaskTouchThread_entry(void* parameter)
|
||||||
TP_Point tp = TP_Read(); /* 已含轴交换/镜像,直接进手势 */
|
TP_Point tp = TP_Read(); /* 已含轴交换/镜像,直接进手势 */
|
||||||
if (tp.pressed && !s_last_pressed)
|
if (tp.pressed && !s_last_pressed)
|
||||||
{
|
{
|
||||||
char buf[40];
|
LOG_TP("down cal x=%u y=%u", (unsigned)tp.x, (unsigned)tp.y);
|
||||||
sprintf(buf, "TP %u,%u\n", (unsigned)tp.x, (unsigned)tp.y);
|
|
||||||
SEGGER_RTT_WriteString(0, buf);
|
|
||||||
}
|
}
|
||||||
s_last_pressed = tp.pressed;
|
s_last_pressed = tp.pressed;
|
||||||
app_touch_process(tp.x, tp.y, 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);
|
BLTask_msg = rt_mq_create("BLTask msgQ",sizeof(DisplayTaskMessage_Type),128,RT_IPC_FLAG_FIFO);
|
||||||
if(MainTask_msg == RT_NULL || UITask_msg == RT_NULL)
|
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,
|
ret = rt_thread_init(&TaskScanThread,
|
||||||
|
|
@ -316,18 +313,32 @@ void StartScanTask(void)
|
||||||
|
|
||||||
void StopFullTask(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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
rt_thread_detach(&TaskBTRecvThread);
|
||||||
|
}
|
||||||
|
LOG_I("TASK", "StopFullTask done");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,30 +3,20 @@
|
||||||
* The Embedded Experts *
|
* The Embedded Experts *
|
||||||
* www.segger.com *
|
* 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.
|
Purpose : User configuration file for RTT.
|
||||||
For available configuration,
|
For available configuration,
|
||||||
refer to SEGGER_RTT_ConfDefaults.h.
|
refer to SEGGER_RTT_ConfDefaults.h.
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SEGGER_RTT_CONF_H
|
#ifndef SEGGER_RTT_CONF_H
|
||||||
#define SEGGER_RTT_CONF_H
|
#define SEGGER_RTT_CONF_H
|
||||||
|
|
||||||
|
#define SEGGER_RTT_MAX_NUM_UP_BUFFERS (3)
|
||||||
/*********************************************************************
|
#define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (3)
|
||||||
*
|
#define BUFFER_SIZE_UP (2048)
|
||||||
* Defines, configurable
|
#define BUFFER_SIZE_DOWN (256)
|
||||||
*
|
#define SEGGER_RTT_PRINTF_BUFFER_SIZE (256u)
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
/*************************** End of file ****************************/
|
/*************************** End of file ****************************/
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
# K1 设备日志导出(J-Link RTT)
|
||||||
|
|
||||||
|
## 用途
|
||||||
|
|
||||||
|
固件运行时将启动/关机、触摸、按键、UI 切换、异常等事件写入 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 命令(RTT 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 坐标、irq 状态
|
||||||
|
- `[MSG] id=12` — 触摸消息是否发出
|
||||||
|
- `[UI] mode_select miss` — UI 命中测试是否失败
|
||||||
|
|
@ -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()
|
||||||
Loading…
Reference in New Issue