Release 0.2.3: fix local song HKTK load/play and keep tone map logs.
Use 41KB preset buffer with compressed 2.bin, expert/normal StartWithNote path, Flash Map address logs, and ship flash-mode/hub assets plus flash helpers. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
c4852aca5d
commit
4544f8706a
128
APP/app_log.c
128
APP/app_log.c
|
|
@ -14,13 +14,15 @@ static char s_debug_level = 'D';
|
||||||
static char s_cmd_buf[48];
|
static char s_cmd_buf[48];
|
||||||
static uint8_t s_cmd_len;
|
static uint8_t s_cmd_len;
|
||||||
|
|
||||||
/* RTT 二进制烧录:将 ui0902_res.bin 写到 W25Q128 @ UI0902_RES_BASE */
|
/* RTT 二进制烧录:写到 W25Q128(ui0902 或本地曲目) */
|
||||||
static uint8_t s_flash_mode;
|
static uint8_t s_flash_mode;
|
||||||
|
static uint32_t s_flash_base;
|
||||||
static uint32_t s_flash_addr;
|
static uint32_t s_flash_addr;
|
||||||
static uint32_t s_flash_remain;
|
static uint32_t s_flash_remain;
|
||||||
static uint32_t s_flash_last_sector;
|
static uint32_t s_flash_last_sector;
|
||||||
static uint16_t s_flash_page_len;
|
static uint16_t s_flash_page_len;
|
||||||
static uint8_t s_flash_page[256];
|
static uint8_t s_flash_page[256];
|
||||||
|
static char s_flash_ok_tag[24];
|
||||||
|
|
||||||
uint8_t app_log_flash_busy(void)
|
uint8_t app_log_flash_busy(void)
|
||||||
{
|
{
|
||||||
|
|
@ -61,7 +63,7 @@ static void app_log_flash_feed(const uint8_t *data, unsigned len)
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
for (i = 0; i < len && s_flash_remain > 0U; i++) {
|
for (i = 0; i < len && s_flash_remain > 0U; i++) {
|
||||||
if (s_flash_page_len == 0U && s_flash_addr == UI0902_RES_BASE && i == 0U) {
|
if (s_flash_page_len == 0U && s_flash_addr == s_flash_base && i == 0U) {
|
||||||
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "FLASH_RX\n");
|
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "FLASH_RX\n");
|
||||||
}
|
}
|
||||||
s_flash_page[s_flash_page_len++] = data[i];
|
s_flash_page[s_flash_page_len++] = data[i];
|
||||||
|
|
@ -73,34 +75,42 @@ static void app_log_flash_feed(const uint8_t *data, unsigned len)
|
||||||
|
|
||||||
if (s_flash_remain == 0U && s_flash_mode) {
|
if (s_flash_remain == 0U && s_flash_mode) {
|
||||||
s_flash_mode = 0U;
|
s_flash_mode = 0U;
|
||||||
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "FLASH_UI0902_OK\n");
|
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, s_flash_ok_tag);
|
||||||
UI_DrawModeSelectScreen();
|
UI_DrawModeSelectScreen();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void app_log_flash_start(uint32_t size)
|
static void app_log_flash_start_at(uint32_t base, uint32_t size, const char *go_tag, const char *ok_tag)
|
||||||
{
|
{
|
||||||
char msg[64];
|
char msg[80];
|
||||||
|
|
||||||
if (size == 0U || size > (2U * 1024U * 1024U)) {
|
if (size == 0U || size > (2U * 1024U * 1024U)) {
|
||||||
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "FLASH_UI0902_ERR size\n");
|
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "FLASH_ERR size\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
s_flash_mode = 1U;
|
s_flash_mode = 1U;
|
||||||
s_flash_addr = UI0902_RES_BASE;
|
s_flash_base = base;
|
||||||
|
s_flash_addr = base;
|
||||||
s_flash_remain = size;
|
s_flash_remain = size;
|
||||||
s_flash_last_sector = 0xFFFFFFFFUL;
|
s_flash_last_sector = 0xFFFFFFFFUL;
|
||||||
s_flash_page_len = 0U;
|
s_flash_page_len = 0U;
|
||||||
s_cmd_len = 0U;
|
s_cmd_len = 0U;
|
||||||
s_cmd_buf[0] = '\0';
|
s_cmd_buf[0] = '\0';
|
||||||
|
strncpy(s_flash_ok_tag, ok_tag, sizeof(s_flash_ok_tag) - 1U);
|
||||||
|
s_flash_ok_tag[sizeof(s_flash_ok_tag) - 1U] = '\0';
|
||||||
|
|
||||||
snprintf(msg, sizeof(msg),
|
snprintf(msg, sizeof(msg),
|
||||||
"FLASH_UI0902_GO base=0x%08lX size=%lu\n",
|
"%s base=0x%08lX size=%lu\n",
|
||||||
(unsigned long)UI0902_RES_BASE, (unsigned long)size);
|
go_tag, (unsigned long)base, (unsigned long)size);
|
||||||
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, msg);
|
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void app_log_flash_start(uint32_t size)
|
||||||
|
{
|
||||||
|
app_log_flash_start_at(UI0902_RES_BASE, size, "FLASH_UI0902_GO", "FLASH_UI0902_OK\n");
|
||||||
|
}
|
||||||
|
|
||||||
static void app_log_slot_store(const char *line)
|
static void app_log_slot_store(const char *line)
|
||||||
{
|
{
|
||||||
uint16_t idx = s_head;
|
uint16_t idx = s_head;
|
||||||
|
|
@ -264,6 +274,106 @@ uint8_t app_log_try_command(const char *cmd)
|
||||||
app_log_flash_start(size);
|
app_log_flash_start(size);
|
||||||
return 1U;
|
return 1U;
|
||||||
}
|
}
|
||||||
|
if (strncmp(cmd, "flash haitian ", 14) == 0) {
|
||||||
|
uint32_t size = (uint32_t)strtoul(cmd + 14, NULL, 10);
|
||||||
|
app_log_flash_start_at(FLASH_ADDR_SONG_HAITIAN, size,
|
||||||
|
"FLASH_HAITIAN_GO", "FLASH_HAITIAN_OK\n");
|
||||||
|
return 1U;
|
||||||
|
}
|
||||||
|
if (strncmp(cmd, "tone status", 11) == 0) {
|
||||||
|
uint8_t hdr[16];
|
||||||
|
uint8_t name[40];
|
||||||
|
uint8_t cur_hdr[16];
|
||||||
|
char *pname;
|
||||||
|
char line[192];
|
||||||
|
const char *map;
|
||||||
|
W25Q128_Read(hdr, FLASH_ADDR_SONG_HAITIAN, 16);
|
||||||
|
W25Q128_Read(name, FLASH_ADDR_SONG_HAITIAN + 1280 + 4, 32);
|
||||||
|
name[32] = 0;
|
||||||
|
W25Q128_Read(cur_hdr, (uint32_t)ADDRESS, 16);
|
||||||
|
pname = AutoBandTop1_GetPresetName();
|
||||||
|
if (ADDRESS == EXTFLASH_BIN1_RHYTHM_ADDR)
|
||||||
|
map = "BIN1_RHYTHM";
|
||||||
|
else if (ADDRESS == EXTFLASH_BIN2_SONG_HAITIAN_ADDR)
|
||||||
|
map = "BIN2_SONG_HAITIAN";
|
||||||
|
else if (ADDRESS == EXTFLASH_BIN3_UNIVERSAL_ADDR)
|
||||||
|
map = "BIN3_UNIVERSAL";
|
||||||
|
else
|
||||||
|
map = "UNKNOWN";
|
||||||
|
snprintf(line, sizeof(line),
|
||||||
|
"TONE tab=%u sw=%u addr=0x%08lX map=%s songidx=%u rhyt=%u\n",
|
||||||
|
(unsigned)mGuiData[GUI_TAB_INDEX].Current,
|
||||||
|
(unsigned)mGuiData[GUI_AUTOBAND_SW].Current,
|
||||||
|
(unsigned long)ADDRESS, map,
|
||||||
|
(unsigned)ParamGuiData[EXPRESS_MODE_PARAM].Current,
|
||||||
|
(unsigned)ParamGuiData[SONG_MODE_PARAM].Current);
|
||||||
|
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, line);
|
||||||
|
snprintf(line, sizeof(line),
|
||||||
|
"TONE map BIN1=0x%08lX BIN2=0x%08lX BIN3=0x%08lX\n",
|
||||||
|
(unsigned long)EXTFLASH_BIN1_RHYTHM_ADDR,
|
||||||
|
(unsigned long)EXTFLASH_BIN2_SONG_HAITIAN_ADDR,
|
||||||
|
(unsigned long)EXTFLASH_BIN3_UNIVERSAL_ADDR);
|
||||||
|
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, line);
|
||||||
|
snprintf(line, sizeof(line),
|
||||||
|
"TONE @ADDRESS magic=%02X%02X%02X%02X cnt=%lu\n",
|
||||||
|
cur_hdr[0], cur_hdr[1], cur_hdr[2], cur_hdr[3],
|
||||||
|
(unsigned long)(cur_hdr[12] | (cur_hdr[13] << 8) |
|
||||||
|
(cur_hdr[14] << 16) | (cur_hdr[15] << 24)));
|
||||||
|
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, line);
|
||||||
|
snprintf(line, sizeof(line),
|
||||||
|
"TONE @BIN2 magic=%02X%02X%02X%02X max=%lu cnt=%lu name=%.16s\n",
|
||||||
|
hdr[0], hdr[1], hdr[2], hdr[3],
|
||||||
|
(unsigned long)(hdr[8] | (hdr[9] << 8) | (hdr[10] << 16) | (hdr[11] << 24)),
|
||||||
|
(unsigned long)(hdr[12] | (hdr[13] << 8) | (hdr[14] << 16) | (hdr[15] << 24)),
|
||||||
|
(char *)name);
|
||||||
|
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, line);
|
||||||
|
snprintf(line, sizeof(line),
|
||||||
|
"TONE loaded name=%s count=%d\n",
|
||||||
|
pname ? pname : "(null)",
|
||||||
|
AutoBandTop1_GetPresetItemCount());
|
||||||
|
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, line);
|
||||||
|
return 1U;
|
||||||
|
}
|
||||||
|
if (strncmp(cmd, "tone reload", 11) == 0) {
|
||||||
|
char line[96];
|
||||||
|
UI_ReloadTonePreset();
|
||||||
|
snprintf(line, sizeof(line),
|
||||||
|
"TONE_RELOAD addr=0x%08lX name=%s\n",
|
||||||
|
(unsigned long)ADDRESS,
|
||||||
|
AutoBandTop1_GetPresetName() ? AutoBandTop1_GetPresetName() : "(null)");
|
||||||
|
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, line);
|
||||||
|
return 1U;
|
||||||
|
}
|
||||||
|
if (strncmp(cmd, "tone local", 10) == 0) {
|
||||||
|
char line[128];
|
||||||
|
int ret;
|
||||||
|
mGuiData[GUI_TAB_INDEX].Current = 1; /* 专业 */
|
||||||
|
mGuiData[GUI_AUTOBAND_SW].Current = 1; /* 本地曲目 */
|
||||||
|
ParamGuiData[EXPRESS_MODE_PARAM].Current = 0;
|
||||||
|
UI_ApplyToneAddress();
|
||||||
|
AutoBandTop1_Stop();
|
||||||
|
StartFlag = 0;
|
||||||
|
ret = AutoBandTop1_LoadPresetItemFromFlash(0);
|
||||||
|
snprintf(line, sizeof(line),
|
||||||
|
"TONE_LOCAL ret=%d addr=0x%08lX map=BIN2@0x%08lX name=%s count=%d %s\n",
|
||||||
|
ret, (unsigned long)ADDRESS,
|
||||||
|
(unsigned long)EXTFLASH_BIN2_SONG_HAITIAN_ADDR,
|
||||||
|
AutoBandTop1_GetPresetName() ? AutoBandTop1_GetPresetName() : "(null)",
|
||||||
|
AutoBandTop1_GetPresetItemCount(),
|
||||||
|
(ADDRESS == EXTFLASH_BIN2_SONG_HAITIAN_ADDR) ? "OK" : "MISMATCH");
|
||||||
|
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, line);
|
||||||
|
return 1U;
|
||||||
|
}
|
||||||
|
if (strncmp(cmd, "tone pick", 9) == 0) {
|
||||||
|
/* 模拟专业+本地曲目拨片(无和弦板) */
|
||||||
|
mGuiData[GUI_TAB_INDEX].Current = 1;
|
||||||
|
mGuiData[GUI_AUTOBAND_SW].Current = 1;
|
||||||
|
KEY_ID_1629 = 0; /* 走默认和弦兜底 */
|
||||||
|
StartFlag = 0;
|
||||||
|
Pick_Handle();
|
||||||
|
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "TONE_PICK_DONE\n");
|
||||||
|
return 1U;
|
||||||
|
}
|
||||||
if (strncmp(cmd, "flash erase chip", 16) == 0) {
|
if (strncmp(cmd, "flash erase chip", 16) == 0) {
|
||||||
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "FLASH_ERASE_BEGIN\n");
|
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "FLASH_ERASE_BEGIN\n");
|
||||||
LOG_I("FLASH", "W25Q128 chip erase start");
|
LOG_I("FLASH", "W25Q128 chip erase start");
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ int16_t MIC_VOL_MAP[11]= {-9000,-7000,-5000,-3000,-1000,1000,3000,5000,7000,9000
|
||||||
|
|
||||||
uint8_t TOUCH_AREA_NUM = (sizeof(Touch_Areas)/sizeof(Touch_AreaTypeDef));
|
uint8_t TOUCH_AREA_NUM = (sizeof(Touch_Areas)/sizeof(Touch_AreaTypeDef));
|
||||||
|
|
||||||
const uint8_t Version[3] = {0,2,2}; /* major.minor.patch — 0.2.2: BT persist, settings icon focus, auto-off UI */
|
const uint8_t Version[3] = {0,2,3}; /* major.minor.patch — 0.2.3: local song HKTK load/play + tone addr logs */
|
||||||
|
|
||||||
uint8_t Led = 8;
|
uint8_t Led = 8;
|
||||||
bool PressFlag = 0;
|
bool PressFlag = 0;
|
||||||
|
|
@ -775,21 +775,48 @@ void Pick_Handle()
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
if(StartFlag == 0) //当播放了之后,拨片不再起作用
|
/* 普通:节奏/本地曲目均用 StartWithNote;切库后允许再次拨片起奏 */
|
||||||
|
if (StartFlag == 0 || mGuiData[GUI_AUTOBAND_SW].Current)
|
||||||
{
|
{
|
||||||
StartFlag = 1;
|
StartFlag = 1;
|
||||||
|
AutoBandTop1_Stop();
|
||||||
AutoBandTop1_SetLoopMode(0,1);
|
AutoBandTop1_SetLoopMode(0,1);
|
||||||
|
AutoBandTop1_SetRunVar(mGuiData[GUI_PLAY_SECTION].Current);
|
||||||
|
/* 起调必须用 0x3C+移调;勿用和弦音区 MIDI(如 48),否则本地曲目起奏异常 */
|
||||||
midi = 0x3C + mGuiData[GUI_TRANSPOSE].Current;
|
midi = 0x3C + mGuiData[GUI_TRANSPOSE].Current;
|
||||||
AutoBandTop1_StartWithNote(midi);
|
AutoBandTop1_StartWithNote(midi);
|
||||||
AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt);
|
AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt);
|
||||||
|
if (mGuiData[GUI_AUTOBAND_SW].Current)
|
||||||
|
LOG_I("pick", "local/normal root=%u name=%s", midi,
|
||||||
|
AutoBandTop1_GetPresetName() ? AutoBandTop1_GetPresetName() : "?");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
StartFlag = 1;
|
StartFlag = 1;
|
||||||
|
if (mGuiData[GUI_AUTOBAND_SW].Current)
|
||||||
|
{
|
||||||
|
/* 本地曲目:与普通模式同一套起奏(0x3C 根音 + 和弦音) */
|
||||||
|
AutoBandTop1_Stop();
|
||||||
|
AutoBandTop1_SetLoopMode(0,1);
|
||||||
|
AutoBandTop1_SetRunVar(mGuiData[GUI_PLAY_SECTION].Current);
|
||||||
|
midi = 0x3C + mGuiData[GUI_TRANSPOSE].Current;
|
||||||
|
AutoBandTop1_StartWithNote(midi);
|
||||||
|
AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt);
|
||||||
|
LOG_I("pick", "local/expert root=%u name=%s sw=%u tab=%u",
|
||||||
|
midi,
|
||||||
|
AutoBandTop1_GetPresetName() ? AutoBandTop1_GetPresetName() : "?",
|
||||||
|
(unsigned)mGuiData[GUI_AUTOBAND_SW].Current,
|
||||||
|
(unsigned)mGuiData[GUI_TAB_INDEX].Current);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
AutoBandTop1_SetPiecePlayMode(1,0,1920);
|
AutoBandTop1_SetPiecePlayMode(1,0,1920);
|
||||||
AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt);
|
AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt);
|
||||||
AutoBandTop1_SetLoopMode(0,1);
|
AutoBandTop1_SetLoopMode(0,1);
|
||||||
|
LOG_I("pick", "expert/rhythm piece name=%s",
|
||||||
|
AutoBandTop1_GetPresetName() ? AutoBandTop1_GetPresetName() : "?");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
StartFlag = 1;
|
StartFlag = 1;
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
MidiFifoSeq_t m_MidiSendFifo;
|
MidiFifoSeq_t m_MidiSendFifo;
|
||||||
#define PRESET_BUFFER_SIZE (1024*40)
|
#define PRESET_BUFFER_SIZE (1024*41) /* 2s.res compressed HKTK preset 39760 bytes */
|
||||||
static int m_presetCount = 0;
|
static int m_presetCount = 0;
|
||||||
static uint8_t pStoreBuffer[PRESET_BUFFER_SIZE];
|
static uint8_t pStoreBuffer[PRESET_BUFFER_SIZE];
|
||||||
//static uint8_t* pStoreBuffer;
|
//static uint8_t* pStoreBuffer;
|
||||||
|
|
@ -76,9 +76,60 @@ static void Func_CallBack_PitchWheel(int channel,int cc,int value)
|
||||||
mymidififo_InQueue(&m_MidiSendFifo,&midimsg);
|
mymidififo_InQueue(&m_MidiSendFifo,&midimsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Flash Map 0903:对照 ExtFlash_Tone_Addr.h / Doc/.../FLASH_MAP.txt */
|
||||||
|
static const char *ToneFlashMapBank(uint32_t abs)
|
||||||
|
{
|
||||||
|
if (abs >= EXTFLASH_BIN1_RHYTHM_ADDR &&
|
||||||
|
abs < EXTFLASH_BIN1_RHYTHM_ADDR + EXTFLASH_BIN1_RHYTHM_SIZE)
|
||||||
|
return "BIN1_RHYTHM";
|
||||||
|
if (abs >= EXTFLASH_BIN2_SONG_HAITIAN_ADDR &&
|
||||||
|
abs < EXTFLASH_BIN2_SONG_HAITIAN_ADDR + EXTFLASH_BIN2_SONG_HAITIAN_SIZE)
|
||||||
|
return "BIN2_SONG_HAITIAN";
|
||||||
|
if (abs >= EXTFLASH_BIN3_UNIVERSAL_ADDR &&
|
||||||
|
abs < EXTFLASH_BIN3_UNIVERSAL_ADDR + EXTFLASH_BIN3_UNIVERSAL_SIZE)
|
||||||
|
return "BIN3_UNIVERSAL";
|
||||||
|
if (abs >= FLASH_ADDR_AUTOBAND_LEGACY &&
|
||||||
|
abs < FLASH_ADDR_AUTOBAND_LEGACY + 0x10000UL)
|
||||||
|
return "LEGACY_AUTOBAND";
|
||||||
|
return "OUT_OF_MAP";
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t s_flash_rd_last_base = 0xFFFFFFFFu;
|
||||||
|
static uint16_t s_flash_rd_log_cnt = 0;
|
||||||
|
|
||||||
static int Func_CallBack_ReadFlash(int address,int length,uint8_t* pOutput)
|
static int Func_CallBack_ReadFlash(int address,int length,uint8_t* pOutput)
|
||||||
{
|
{
|
||||||
W25Q128_Read(pOutput, (uint32_t)ADDRESS+address, length);
|
uint32_t base = (uint32_t)ADDRESS;
|
||||||
|
uint32_t abs = base + (uint32_t)address;
|
||||||
|
const char *bank;
|
||||||
|
|
||||||
|
if (base != s_flash_rd_last_base) {
|
||||||
|
s_flash_rd_last_base = base;
|
||||||
|
s_flash_rd_log_cnt = 0;
|
||||||
|
LOG_I("FLASH_RD", "bank base=0x%08X map=%s (BIN1=0x%08X BIN2=0x%08X BIN3=0x%08X)",
|
||||||
|
(unsigned)base,
|
||||||
|
ToneFlashMapBank(base),
|
||||||
|
(unsigned)EXTFLASH_BIN1_RHYTHM_ADDR,
|
||||||
|
(unsigned)EXTFLASH_BIN2_SONG_HAITIAN_ADDR,
|
||||||
|
(unsigned)EXTFLASH_BIN3_UNIVERSAL_ADDR);
|
||||||
|
}
|
||||||
|
|
||||||
|
bank = ToneFlashMapBank(abs);
|
||||||
|
/* 加载阶段打印前若干次 + 每次 offset==0;避免播放期刷屏 */
|
||||||
|
if (s_flash_rd_log_cnt < 16u || address == 0) {
|
||||||
|
LOG_I("FLASH_RD", "abs=0x%08X off=%d len=%d map=%s",
|
||||||
|
(unsigned)abs, address, length, bank);
|
||||||
|
if (s_flash_rd_log_cnt < 0xFFFFu)
|
||||||
|
s_flash_rd_log_cnt++;
|
||||||
|
if (s_flash_rd_log_cnt == 16u)
|
||||||
|
LOG_I("FLASH_RD", "further reads omitted (same base)");
|
||||||
|
} else if (bank[0] == 'O') {
|
||||||
|
/* 读到 Map 外:始终告警 */
|
||||||
|
LOG_W("FLASH_RD", "OUT_OF_MAP abs=0x%08X off=%d len=%d base=0x%08X",
|
||||||
|
(unsigned)abs, address, length, (unsigned)base);
|
||||||
|
}
|
||||||
|
|
||||||
|
W25Q128_Read(pOutput, abs, length);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
|
|
@ -97,11 +148,14 @@ void App_Auto_Init(void)
|
||||||
int ret = AutoBandTop1_LoadPresetItemFromFlash(0);
|
int ret = AutoBandTop1_LoadPresetItemFromFlash(0);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
{
|
{
|
||||||
LOG_E("AUTO", "LoadPreset fail ret=%d addr=0x%08X",
|
LOG_E("AUTO", "LoadPreset fail ret=%d addr=0x%08X map=%s",
|
||||||
ret, (unsigned)ADDRESS);
|
ret, (unsigned)ADDRESS, ToneFlashMapBank((uint32_t)ADDRESS));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
LOG_I("AUTO", "LoadPreset ok name=%s addr=0x%08X map=%s",
|
||||||
|
AutoBandTop1_GetPresetName() ? AutoBandTop1_GetPresetName() : "?",
|
||||||
|
(unsigned)ADDRESS, ToneFlashMapBank((uint32_t)ADDRESS));
|
||||||
AutoBandTop1_ChangeBPM(mGuiData[1].Current);
|
AutoBandTop1_ChangeBPM(mGuiData[1].Current);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -178,12 +178,21 @@ void Touch_Action(int8_t FLAG, uint8_t ID, uint8_t areaIndex,uint8_t value)
|
||||||
show_Param(&UI_Label[GUI_MODE_PARAM], pCurData);
|
show_Param(&UI_Label[GUI_MODE_PARAM], pCurData);
|
||||||
|
|
||||||
UI_ApplyToneAddress();
|
UI_ApplyToneAddress();
|
||||||
|
int ret = 0;
|
||||||
if (tab == 0)
|
if (tab == 0)
|
||||||
AutoBandTop1_LoadPresetItemFromFlash(ParamGuiData[ALL_MODE_PARAM].Current);
|
ret = AutoBandTop1_LoadPresetItemFromFlash(ParamGuiData[ALL_MODE_PARAM].Current);
|
||||||
else if (mGuiData[GUI_AUTOBAND_SW].Current)
|
else if (mGuiData[GUI_AUTOBAND_SW].Current)
|
||||||
AutoBandTop1_LoadPresetItemFromFlash(ParamGuiData[EXPRESS_MODE_PARAM].Current);
|
ret = AutoBandTop1_LoadPresetItemFromFlash(ParamGuiData[EXPRESS_MODE_PARAM].Current);
|
||||||
else
|
else
|
||||||
AutoBandTop1_LoadPresetItemFromFlash(ParamGuiData[SONG_MODE_PARAM].Current);
|
ret = AutoBandTop1_LoadPresetItemFromFlash(ParamGuiData[SONG_MODE_PARAM].Current);
|
||||||
|
if (ret != 0)
|
||||||
|
LOG_E("tone", "load preset failed tab=%d sw=%d ret=%d addr=0x%08X",
|
||||||
|
tab, mGuiData[GUI_AUTOBAND_SW].Current, ret, (unsigned)ADDRESS);
|
||||||
|
else
|
||||||
|
LOG_I("tone", "load preset ok tab=%d sw=%d name=%s addr=0x%08X",
|
||||||
|
tab, mGuiData[GUI_AUTOBAND_SW].Current,
|
||||||
|
AutoBandTop1_GetPresetName() ? AutoBandTop1_GetPresetName() : "?",
|
||||||
|
(unsigned)ADDRESS);
|
||||||
|
|
||||||
if (tab == 0)
|
if (tab == 0)
|
||||||
nvm->param.Param3 = ParamGuiData[ALL_MODE_PARAM].Current;
|
nvm->param.Param3 = ParamGuiData[ALL_MODE_PARAM].Current;
|
||||||
|
|
@ -216,7 +225,11 @@ void Touch_Action(int8_t FLAG, uint8_t ID, uint8_t areaIndex,uint8_t value)
|
||||||
/* 万能无节奏/本地 TAB,忽略该触控 */
|
/* 万能无节奏/本地 TAB,忽略该触控 */
|
||||||
if (mGuiData[GUI_TAB_INDEX].Current == 0)
|
if (mGuiData[GUI_TAB_INDEX].Current == 0)
|
||||||
return;
|
return;
|
||||||
|
if (mGuiData[ID].Current == value)
|
||||||
|
return;
|
||||||
mGuiData[ID].Current = value;
|
mGuiData[ID].Current = value;
|
||||||
|
StartFlag = 0;
|
||||||
|
AutoBandTop1_Stop();
|
||||||
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]);
|
||||||
|
|
|
||||||
|
|
@ -112,36 +112,66 @@ void CallUI_RestoreSelect(void) {
|
||||||
/* 音师:万能→3.bin;普通/专业:节奏→1.bin、本地曲目→2.bin */
|
/* 音师:万能→3.bin;普通/专业:节奏→1.bin、本地曲目→2.bin */
|
||||||
void UI_ApplyToneAddress(void)
|
void UI_ApplyToneAddress(void)
|
||||||
{
|
{
|
||||||
|
uint32_t expect = 0;
|
||||||
|
const char *map_name = "?";
|
||||||
|
|
||||||
switch (mGuiData[GUI_TAB_INDEX].Current)
|
switch (mGuiData[GUI_TAB_INDEX].Current)
|
||||||
{
|
{
|
||||||
case 0: /* 万能:和弦走向库 */
|
case 0: /* 万能:和弦走向库 */
|
||||||
ADDRESS = FLASH_ADDR_MODE_UNIVERSAL;
|
ADDRESS = FLASH_ADDR_MODE_UNIVERSAL;
|
||||||
return;
|
expect = EXTFLASH_BIN3_UNIVERSAL_ADDR;
|
||||||
|
map_name = "BIN3_UNIVERSAL";
|
||||||
|
break;
|
||||||
case 1: /* 专业 */
|
case 1: /* 专业 */
|
||||||
if (mGuiData[GUI_AUTOBAND_SW].Current)
|
if (mGuiData[GUI_AUTOBAND_SW].Current) {
|
||||||
ADDRESS = FLASH_ADDR_SONG_HAITIAN;
|
ADDRESS = FLASH_ADDR_SONG_HAITIAN;
|
||||||
else
|
expect = EXTFLASH_BIN2_SONG_HAITIAN_ADDR;
|
||||||
|
map_name = "BIN2_SONG_HAITIAN";
|
||||||
|
} else {
|
||||||
ADDRESS = FLASH_ADDR_MODE_EXPERT;
|
ADDRESS = FLASH_ADDR_MODE_EXPERT;
|
||||||
return;
|
expect = EXTFLASH_BIN1_RHYTHM_ADDR;
|
||||||
|
map_name = "BIN1_RHYTHM";
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 2: /* 普通 */
|
case 2: /* 普通 */
|
||||||
if (mGuiData[GUI_AUTOBAND_SW].Current)
|
if (mGuiData[GUI_AUTOBAND_SW].Current) {
|
||||||
ADDRESS = FLASH_ADDR_SONG_HAITIAN;
|
ADDRESS = FLASH_ADDR_SONG_HAITIAN;
|
||||||
else
|
expect = EXTFLASH_BIN2_SONG_HAITIAN_ADDR;
|
||||||
|
map_name = "BIN2_SONG_HAITIAN";
|
||||||
|
} else {
|
||||||
ADDRESS = FLASH_ADDR_MODE_NORMAL;
|
ADDRESS = FLASH_ADDR_MODE_NORMAL;
|
||||||
return;
|
expect = EXTFLASH_BIN1_RHYTHM_ADDR;
|
||||||
|
map_name = "BIN1_RHYTHM";
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ADDRESS = FLASH_ADDR_MODE_UNIVERSAL;
|
ADDRESS = FLASH_ADDR_MODE_UNIVERSAL;
|
||||||
return;
|
expect = EXTFLASH_BIN3_UNIVERSAL_ADDR;
|
||||||
|
map_name = "BIN3_UNIVERSAL";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG_I("tone", "ADDRESS=0x%08X map=%s expect=0x%08X tab=%u sw=%u %s",
|
||||||
|
(unsigned)ADDRESS, map_name, (unsigned)expect,
|
||||||
|
(unsigned)mGuiData[GUI_TAB_INDEX].Current,
|
||||||
|
(unsigned)mGuiData[GUI_AUTOBAND_SW].Current,
|
||||||
|
(ADDRESS == expect) ? "OK" : "MISMATCH");
|
||||||
}
|
}
|
||||||
|
|
||||||
void UI_ReloadTonePreset(void)
|
void UI_ReloadTonePreset(void)
|
||||||
{
|
{
|
||||||
UI_ApplyToneAddress();
|
UI_ApplyToneAddress();
|
||||||
|
/* 换库前先停,避免播放中改 relocate 指针 */
|
||||||
|
AutoBandTop1_Stop();
|
||||||
|
StartFlag = 0;
|
||||||
/* 万能:和弦走向 */
|
/* 万能:和弦走向 */
|
||||||
if (mGuiData[GUI_TAB_INDEX].Current == 0)
|
if (mGuiData[GUI_TAB_INDEX].Current == 0)
|
||||||
{
|
{
|
||||||
AutoBandTop1_LoadPresetItemFromFlash(ParamGuiData[ALL_MODE_PARAM].Current);
|
int ret = AutoBandTop1_LoadPresetItemFromFlash(ParamGuiData[ALL_MODE_PARAM].Current);
|
||||||
|
LOG_I("tone", "load universal idx=%d ret=%d name=%s addr=0x%08X map=BIN3@0x%08X",
|
||||||
|
ParamGuiData[ALL_MODE_PARAM].Current, ret,
|
||||||
|
AutoBandTop1_GetPresetName() ? AutoBandTop1_GetPresetName() : "?",
|
||||||
|
(unsigned)ADDRESS, (unsigned)EXTFLASH_BIN3_UNIVERSAL_ADDR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* 普通/专业:本地曲目或节奏类型 */
|
/* 普通/专业:本地曲目或节奏类型 */
|
||||||
|
|
@ -151,7 +181,18 @@ void UI_ReloadTonePreset(void)
|
||||||
local->Max = (LOCAL_SONG_COUNT > 0) ? (uint16_t)(LOCAL_SONG_COUNT - 1) : 0;
|
local->Max = (LOCAL_SONG_COUNT > 0) ? (uint16_t)(LOCAL_SONG_COUNT - 1) : 0;
|
||||||
if (local->Current > local->Max)
|
if (local->Current > local->Max)
|
||||||
local->Current = local->Max;
|
local->Current = local->Max;
|
||||||
AutoBandTop1_LoadPresetItemFromFlash(local->Current);
|
int ret = AutoBandTop1_LoadPresetItemFromFlash(local->Current);
|
||||||
|
if (ret != 0)
|
||||||
|
LOG_E("tone", "load local song idx=%d failed ret=%d addr=0x%08X map=BIN2@0x%08X",
|
||||||
|
local->Current, ret, (unsigned)ADDRESS,
|
||||||
|
(unsigned)EXTFLASH_BIN2_SONG_HAITIAN_ADDR);
|
||||||
|
else
|
||||||
|
LOG_I("tone", "local song idx=%d name=%s addr=0x%08X map=BIN2@0x%08X %s",
|
||||||
|
local->Current,
|
||||||
|
AutoBandTop1_GetPresetName() ? AutoBandTop1_GetPresetName() : "?",
|
||||||
|
(unsigned)ADDRESS,
|
||||||
|
(unsigned)EXTFLASH_BIN2_SONG_HAITIAN_ADDR,
|
||||||
|
(ADDRESS == EXTFLASH_BIN2_SONG_HAITIAN_ADDR) ? "OK" : "MISMATCH");
|
||||||
{
|
{
|
||||||
int bin_n = AutoBandTop1_GetPresetItemCount();
|
int bin_n = AutoBandTop1_GetPresetItemCount();
|
||||||
if (bin_n != LOCAL_SONG_COUNT)
|
if (bin_n != LOCAL_SONG_COUNT)
|
||||||
|
|
@ -159,7 +200,16 @@ void UI_ReloadTonePreset(void)
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
AutoBandTop1_LoadPresetItemFromFlash(ParamGuiData[SONG_MODE_PARAM].Current);
|
{
|
||||||
|
int ret = AutoBandTop1_LoadPresetItemFromFlash(ParamGuiData[SONG_MODE_PARAM].Current);
|
||||||
|
LOG_I("tone", "load rhythm idx=%d ret=%d name=%s addr=0x%08X map=BIN1@0x%08X %s",
|
||||||
|
ParamGuiData[SONG_MODE_PARAM].Current, ret,
|
||||||
|
AutoBandTop1_GetPresetName() ? AutoBandTop1_GetPresetName() : "?",
|
||||||
|
(unsigned)ADDRESS,
|
||||||
|
(unsigned)EXTFLASH_BIN1_RHYTHM_ADDR,
|
||||||
|
(ADDRESS == EXTFLASH_BIN1_RHYTHM_ADDR) ? "OK" : "MISMATCH");
|
||||||
|
(void)ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t s_ui_focus_id = UI_FOCUS_NONE;
|
static uint8_t s_ui_focus_id = UI_FOCUS_NONE;
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,9 @@
|
||||||
#define EXTFLASH_BIN1_RHYTHM_SIZE 530317UL
|
#define EXTFLASH_BIN1_RHYTHM_SIZE 530317UL
|
||||||
|
|
||||||
#define EXTFLASH_BIN2_SONG_HAITIAN_ADDR 0x0009D07DUL
|
#define EXTFLASH_BIN2_SONG_HAITIAN_ADDR 0x0009D07DUL
|
||||||
#define EXTFLASH_BIN2_SONG_HAITIAN_SIZE 46474UL
|
#define EXTFLASH_BIN2_SONG_HAITIAN_SIZE 41040UL
|
||||||
|
|
||||||
#define EXTFLASH_BIN3_UNIVERSAL_ADDR 0x000A8607UL
|
#define EXTFLASH_BIN3_UNIVERSAL_ADDR 0x000A70CDUL
|
||||||
#define EXTFLASH_BIN3_UNIVERSAL_SIZE 31854UL
|
#define EXTFLASH_BIN3_UNIVERSAL_SIZE 31854UL
|
||||||
|
|
||||||
/* Convenience aliases used by UI ADDRESS */
|
/* Convenience aliases used by UI ADDRESS */
|
||||||
|
|
@ -35,8 +35,8 @@
|
||||||
/* Legacy AutoBand bank — not repacked in 0903; left unchanged in firmware */
|
/* Legacy AutoBand bank — not repacked in 0903; left unchanged in firmware */
|
||||||
#define FLASH_ADDR_AUTOBAND_LEGACY 0x0009EB5FUL
|
#define FLASH_ADDR_AUTOBAND_LEGACY 0x0009EB5FUL
|
||||||
|
|
||||||
#define EXTFLASH_TONE_PACK_END 0x000B0275UL
|
#define EXTFLASH_TONE_PACK_END 0x000AED3BUL
|
||||||
#define EXTFLASH_TONE_PACK_SIZE 721525UL
|
#define EXTFLASH_TONE_PACK_SIZE 716091UL
|
||||||
#define UI0902_RES_BASE_SAFE_GAP (0x00100000UL - EXTFLASH_TONE_PACK_END)
|
#define UI0902_RES_BASE_SAFE_GAP (0x00100000UL - EXTFLASH_TONE_PACK_END)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
* Please modify RT_HEAP_SIZE if you enable RT_USING_HEAP
|
* Please modify RT_HEAP_SIZE if you enable RT_USING_HEAP
|
||||||
* the RT_HEAP_SIZE max value = (sram size - ZI size), 1024 means 1024 bytes
|
* the RT_HEAP_SIZE max value = (sram size - ZI size), 1024 means 1024 bytes
|
||||||
*/
|
*/
|
||||||
#define RT_HEAP_SIZE (20*1024)
|
#define RT_HEAP_SIZE (19*1024) /* 20KB-1KB to fit 41KB preset buffer in 96KB RAM */
|
||||||
static rt_uint8_t rt_heap[RT_HEAP_SIZE];
|
static rt_uint8_t rt_heap[RT_HEAP_SIZE];
|
||||||
|
|
||||||
RT_WEAK void *rt_heap_begin_get(void)
|
RT_WEAK void *rt_heap_begin_get(void)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
import subprocess, shutil, os, time
|
||||||
|
|
||||||
|
base = os.path.join(r"C:\Users\qjyu\Documents\SoundWalker", "一诺国际吉他",
|
||||||
|
r"Code\YNGJ-GT1-M - AT32F403ARCT7")
|
||||||
|
stage = r"C:\Temp\k1flash"
|
||||||
|
os.makedirs(stage, exist_ok=True)
|
||||||
|
|
||||||
|
out_src = os.path.join(base, r"project\IAR_V7.4\YNGJ-GT1-M\Exe\YNGJ-GT1-M.out")
|
||||||
|
out_dst = os.path.join(stage, "YNGJ-GT1-M.out")
|
||||||
|
with open(out_src, "rb") as a, open(out_dst, "wb") as b:
|
||||||
|
shutil.copyfileobj(a, b)
|
||||||
|
print("copied", os.path.getsize(out_dst), flush=True)
|
||||||
|
|
||||||
|
gen_src = os.path.join(base, r"project\IAR_V7.4\settings\YNGJ-GT1-M.YNGJ-GT1-M.general.xcl")
|
||||||
|
drv_src = os.path.join(base, r"project\IAR_V7.4\settings\YNGJ-GT1-M.YNGJ-GT1-M.driver.xcl")
|
||||||
|
lines = open(gen_src, encoding="utf-8", errors="replace").read().splitlines()
|
||||||
|
new = []
|
||||||
|
for ln in lines:
|
||||||
|
new.append(f'"{out_dst}" ' if (".out" in ln and "YNGJ" in ln) else ln)
|
||||||
|
open(os.path.join(stage, "general.xcl"), "w", encoding="utf-8", newline="\n").write("\n".join(new) + "\n")
|
||||||
|
shutil.copy2(drv_src, os.path.join(stage, "driver.xcl"))
|
||||||
|
|
||||||
|
for n in ("cspybat.exe", "CSpyBat.exe", "JLink.exe", "IarIdePm.exe",
|
||||||
|
"JLinkGUIServer.exe", "JLinkRTTClient.exe", "JFlash.exe"):
|
||||||
|
subprocess.run(["taskkill", "/F", "/IM", n], capture_output=True)
|
||||||
|
time.sleep(1.5)
|
||||||
|
|
||||||
|
# Force Artery AT32F403ACx (RCT7) — avoid Cortex-M4 / wrong-chip popup
|
||||||
|
drv_path = os.path.join(stage, "driver.xcl")
|
||||||
|
drv_lines = open(drv_path, encoding="utf-8", errors="replace").read().splitlines()
|
||||||
|
forced = []
|
||||||
|
for ln in drv_lines:
|
||||||
|
if ln.strip().startswith("--jlink_device"):
|
||||||
|
continue
|
||||||
|
forced.append(ln)
|
||||||
|
forced.append('--jlink_device=AT32F403AC')
|
||||||
|
open(drv_path, "w", encoding="utf-8", newline="\n").write("\n".join(forced) + "\n")
|
||||||
|
print("driver device forced: AT32F403AC", flush=True)
|
||||||
|
|
||||||
|
cspy = r"C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.3\common\bin\cspybat.exe"
|
||||||
|
cmd = [cspy, "-f", os.path.join(stage, "general.xcl"),
|
||||||
|
f"--debug_file={out_dst}", "--download_only", "--backend",
|
||||||
|
"-f", drv_path]
|
||||||
|
logp = os.path.join(stage, "cspy.log")
|
||||||
|
print("cspybat start (AT32F403AC / FlashAT32F403ARCT7)", flush=True)
|
||||||
|
with open(logp, "w", encoding="utf-8", errors="replace") as log:
|
||||||
|
r = subprocess.run(cmd, stdout=log, stderr=subprocess.STDOUT, timeout=180)
|
||||||
|
print("cspy exit", r.returncode, flush=True)
|
||||||
|
print(open(logp, encoding="utf-8", errors="replace").read()[-2000:])
|
||||||
|
if r.returncode != 0:
|
||||||
|
raise SystemExit(r.returncode)
|
||||||
|
|
||||||
|
jlink = r"C:\Program Files\SEGGER\JLink_V818\JLink.exe"
|
||||||
|
reset = os.path.join(base, r"tools\reset_run.jlink")
|
||||||
|
print("reset AT32F403AC", flush=True)
|
||||||
|
subprocess.run([jlink, "-Device", "AT32F403AC", "-If", "SWD",
|
||||||
|
"-Speed", "4000", "-AutoConnect", "1",
|
||||||
|
"-CommandFile", reset], capture_output=True, timeout=30)
|
||||||
|
time.sleep(3)
|
||||||
|
print("Done", flush=True)
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
gImage_mixer 34x33
|
||||||
|
gImage_SystemSetting 33x33
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 415 B |
Binary file not shown.
|
After Width: | Height: | Size: 550 B |
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
|
|
@ -0,0 +1,186 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Flash Doc/音色文件/0907/2.res (or --bin) to W25Q128 @ FLASH_ADDR_SONG_HAITIAN via RTT."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
|
DEFAULT_DEVICES = ("Cortex-M4", "AT32F403AC", "AT32F403A")
|
||||||
|
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
REPO = os.path.dirname(os.path.dirname(ROOT))
|
||||||
|
DEFAULT_BIN = os.path.join(REPO, "Doc", "音色文件", "0907", "2.res")
|
||||||
|
FLASH_ADDR_SONG_HAITIAN = 0x0009D07D
|
||||||
|
|
||||||
|
|
||||||
|
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 Exception 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):
|
||||||
|
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 rtt_read_text(jlink, timeout_s: float = 0.2) -> str:
|
||||||
|
deadline = time.time() + timeout_s
|
||||||
|
chunks: list[bytes] = []
|
||||||
|
while time.time() < deadline:
|
||||||
|
try:
|
||||||
|
data = bytes(jlink.rtt_read(0, 512) or [])
|
||||||
|
except Exception:
|
||||||
|
data = b""
|
||||||
|
if data:
|
||||||
|
chunks.append(data)
|
||||||
|
deadline = time.time() + timeout_s
|
||||||
|
else:
|
||||||
|
time.sleep(0.02)
|
||||||
|
return b"".join(chunks).decode("ascii", errors="replace")
|
||||||
|
|
||||||
|
|
||||||
|
def wait_for(jlink, marker: str, timeout_s: float = 30.0) -> str:
|
||||||
|
deadline = time.time() + timeout_s
|
||||||
|
buf = ""
|
||||||
|
while time.time() < deadline:
|
||||||
|
buf += rtt_read_text(jlink, 0.15)
|
||||||
|
if marker in buf:
|
||||||
|
return buf
|
||||||
|
raise SystemExit(f"Timeout waiting for {marker!r}\n--- RTT ---\n{buf[-800:]}")
|
||||||
|
|
||||||
|
|
||||||
|
def send_bytes(jlink, payload: bytes) -> None:
|
||||||
|
off = 0
|
||||||
|
while off < len(payload):
|
||||||
|
try:
|
||||||
|
n = jlink.rtt_write(0, list(payload[off : off + 64]))
|
||||||
|
except Exception:
|
||||||
|
time.sleep(0.05)
|
||||||
|
continue
|
||||||
|
if n is None or n <= 0:
|
||||||
|
time.sleep(0.02)
|
||||||
|
continue
|
||||||
|
off += n
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("--bin", default=DEFAULT_BIN)
|
||||||
|
parser.add_argument("--device", default="Cortex-M4")
|
||||||
|
parser.add_argument("--no-reset", action="store_true")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if not os.path.isfile(args.bin):
|
||||||
|
raise SystemExit(f"missing bin: {args.bin}")
|
||||||
|
|
||||||
|
data = open(args.bin, "rb").read()
|
||||||
|
size = len(data)
|
||||||
|
print(f"bin={args.bin} size={size} addr=0x{FLASH_ADDR_SONG_HAITIAN:08X}")
|
||||||
|
|
||||||
|
jlink = connect_jlink(args.device)
|
||||||
|
try:
|
||||||
|
cb = find_rtt_control_block(jlink)
|
||||||
|
if cb is None:
|
||||||
|
raise SystemExit("RTT control block not found")
|
||||||
|
print(f"RTT CB @ 0x{cb:08X}")
|
||||||
|
jlink.rtt_start(cb)
|
||||||
|
time.sleep(0.3)
|
||||||
|
_ = rtt_read_text(jlink, 0.3)
|
||||||
|
|
||||||
|
if not args.no_reset:
|
||||||
|
print("hardware reset...")
|
||||||
|
jlink.reset(halt=False)
|
||||||
|
time.sleep(3.5)
|
||||||
|
try:
|
||||||
|
jlink.rtt_stop()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
cb = find_rtt_control_block(jlink)
|
||||||
|
if cb is None:
|
||||||
|
raise SystemExit("RTT CB missing after reset")
|
||||||
|
print(f"RTT CB @ 0x{cb:08X}")
|
||||||
|
jlink.rtt_start(cb)
|
||||||
|
time.sleep(0.5)
|
||||||
|
_ = rtt_read_text(jlink, 0.5)
|
||||||
|
|
||||||
|
cmd = f"flash haitian {size}\n".encode("ascii")
|
||||||
|
send_bytes(jlink, cmd)
|
||||||
|
print("sent flash command, waiting GO...")
|
||||||
|
log = wait_for(jlink, "FLASH_HAITIAN_GO", 20.0)
|
||||||
|
print(log.strip().splitlines()[-1])
|
||||||
|
time.sleep(0.2)
|
||||||
|
|
||||||
|
chunk = 256
|
||||||
|
sent = 0
|
||||||
|
t0 = time.time()
|
||||||
|
receiving = False
|
||||||
|
while sent < size:
|
||||||
|
end = min(sent + chunk, size)
|
||||||
|
send_bytes(jlink, data[sent:end])
|
||||||
|
sent = end
|
||||||
|
log = wait_for(jlink, "FLASH_ACK", 60.0)
|
||||||
|
if (not receiving) and ("FLASH_RX" in log or "FLASH_ACK" in log):
|
||||||
|
receiving = True
|
||||||
|
print("device receiving...")
|
||||||
|
if "FLASH_HAITIAN_OK" in log:
|
||||||
|
print(log.strip().splitlines()[-1])
|
||||||
|
print("Done. Local song bank updated.")
|
||||||
|
return
|
||||||
|
if sent % (4 * 1024) == 0 or sent == size:
|
||||||
|
elapsed = time.time() - t0
|
||||||
|
print(f" {sent}/{size} ({100.0 * sent / size:.1f}%) {elapsed:.1f}s")
|
||||||
|
|
||||||
|
log = wait_for(jlink, "FLASH_HAITIAN_OK", 60.0)
|
||||||
|
print(log.strip().splitlines()[-1])
|
||||||
|
print("Done. Local song bank updated.")
|
||||||
|
finally:
|
||||||
|
try:
|
||||||
|
jlink.rtt_stop()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
jlink.close()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
@ -25,7 +25,7 @@ MAP_TXT = REPO / "Doc" / "音色文件" / "0903" / "FLASH_MAP.txt"
|
||||||
IAP_DIR = REPO / "升级" / "MCU主控升级"
|
IAP_DIR = REPO / "升级" / "MCU主控升级"
|
||||||
OUT_ROOT = REPO / "tools" / "out"
|
OUT_ROOT = REPO / "tools" / "out"
|
||||||
|
|
||||||
FW_VER = "0.2.2"
|
FW_VER = "0.2.3"
|
||||||
TONE_RES_VER = "0903"
|
TONE_RES_VER = "0903"
|
||||||
UI0902_RES_BASE = 0x00100000
|
UI0902_RES_BASE = 0x00100000
|
||||||
|
|
||||||
|
|
@ -126,8 +126,8 @@ def main() -> None:
|
||||||
"",
|
"",
|
||||||
"外部 Flash 分区:",
|
"外部 Flash 分区:",
|
||||||
" 0x00000000 音色/充电图 (toneRes)",
|
" 0x00000000 音色/充电图 (toneRes)",
|
||||||
" logo pad + Charg@0xCB70 + 1.bin@0x1B8F0 + 2.bin + 3.bin",
|
" logo pad + Charg@0xCB70 + 1.bin@0x1B8F0 + 2.bin(HKTK/2s) + 3.bin",
|
||||||
" 0x00100000 UI0902 图片 (模式选择大图、全屏开机 Logo、设置/调音台素材等)",
|
" 0x00100000 UI0902 图片 (模式选择、开机 Logo、充电、烧录模式、设置/调音台等)",
|
||||||
"",
|
"",
|
||||||
f" {comb_name} size={comb_dst.stat().st_size} @ 0x00000000",
|
f" {comb_name} size={comb_dst.stat().st_size} @ 0x00000000",
|
||||||
f" sha256={sha256(comb_dst)}",
|
f" sha256={sha256(comb_dst)}",
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
HideDeviceSelection 1
|
||||||
si SWD
|
si SWD
|
||||||
speed 4000
|
speed 4000
|
||||||
device Cortex-M4
|
device Cortex-M4
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue