Skip to content

Commit faebcca

Browse files
authored
hslink: Support upgrade bootloader (#38)
1 parent b1b1054 commit faebcca

File tree

18 files changed

+290
-43
lines changed

18 files changed

+290
-43
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,6 @@
2222
[submodule "projects/HSLink-Pro/third_party_components/flashdb/FlashDB"]
2323
path = projects/HSLink-Pro/third_party_components/flashdb/FlashDB
2424
url = https://github.com/armink/FlashDB.git
25+
[submodule "projects/HSLink-Pro/third_party_components/b64.c/b64.c"]
26+
path = projects/HSLink-Pro/third_party_components/b64.c/b64.c
27+
url = https://github.com/HSLink/b64.c.git

projects/HSLink-Pro/common/hslinkpro/board.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,6 @@
2525
#define BOARD_NAME "hslinkpro"
2626
#define BOARD_UF2_SIGNATURE (0x0A4D5048UL)
2727

28-
#define BL_SIZE (128 * 1024)
29-
#define BL_B_SLOT_SIZE BL_SIZE
30-
3128
static const uint32_t HARDWARE_VER_ADDR = 70;
3229

3330
typedef struct {

projects/HSLink-Pro/common/user_config.h

Lines changed: 0 additions & 22 deletions
This file was deleted.

projects/HSLink-Pro/src/DAP_config.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -644,13 +644,21 @@ __STATIC_FORCEINLINE uint32_t PIN_nRESET_IN(void)
644644
*/
645645
__STATIC_FORCEINLINE void PIN_nRESET_OUT(uint32_t bit)
646646
{
647+
static uint8_t SRST_Level = 0xFF;
648+
if (SRST_Level == 0xFF) {
649+
if (CheckHardwareVersion(1, 2, UINT8_MAX)) {
650+
SRST_Level = 0;
651+
} else {
652+
SRST_Level = 1;
653+
}
654+
}
647655
if (bit & 0x01) {
648656
if (SETTING_GET_RESET_MODE(HSLink_Setting.reset, RESET_NRST)) {
649-
gpio_write_pin(PIN_GPIO, GPIO_GET_PORT_INDEX(PIN_SRST), GPIO_GET_PIN_INDEX(PIN_SRST), Setting_GetSRSTLevel());
657+
gpio_write_pin(PIN_GPIO, GPIO_GET_PORT_INDEX(PIN_SRST), GPIO_GET_PIN_INDEX(PIN_SRST), SRST_Level);
650658
}
651659
} else {
652660
if (SETTING_GET_RESET_MODE(HSLink_Setting.reset, RESET_NRST)) {
653-
gpio_write_pin(PIN_GPIO, GPIO_GET_PORT_INDEX(PIN_SRST), GPIO_GET_PIN_INDEX(PIN_SRST), !Setting_GetSRSTLevel());
661+
gpio_write_pin(PIN_GPIO, GPIO_GET_PORT_INDEX(PIN_SRST), GPIO_GET_PIN_INDEX(PIN_SRST), !SRST_Level);
654662
}
655663
if (SETTING_GET_RESET_MODE(HSLink_Setting.reset, RESET_ARM_SWD_SOFT)) {
656664
software_reset();

projects/HSLink-Pro/src/HID_COMM/hid_comm.cpp

Lines changed: 183 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44
#include "setting.h"
55
#include "usb_configuration.h"
66
#include "HSLink_Pro_expansion.h"
7+
#include "fal.h"
8+
#include "fal_cfg.h"
9+
#include <b64.h>
10+
#include "crc32.h"
11+
12+
#define LOG_TAG "HID_COMM"
13+
#include "elog.h"
714

815
#ifdef CONFIG_USE_HID_CONFIG
916

@@ -13,8 +20,8 @@
1320

1421
using namespace rapidjson;
1522

16-
#include <unordered_map>
1723
#include <functional>
24+
#include <unordered_map>
1825

1926
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t HID_read_buffer[HID_PACKET_SIZE];
2027
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t HID_write_buffer[HID_PACKET_SIZE];
@@ -34,6 +41,8 @@ const char *response_str[] = {
3441
"failed"
3542
};
3643

44+
std::string_view filed_miss_msg = "Some fields are missing";
45+
3746
static volatile HID_State_t HID_ReadState = HID_STATE_BUSY;
3847

3948
/*!< custom hid report descriptor */
@@ -93,6 +102,26 @@ struct usbd_endpoint hid_custom_out_ep = {
93102
.ep_cb = usbd_hid_custom_out_callback,
94103
};
95104

105+
static bool CheckField(const Value &object, std::pair<std::string_view, Type> field) {
106+
auto &[field_name, field_type] = field;
107+
if (!object.HasMember(field_name.data())) {
108+
return false;
109+
}
110+
if (object[field_name.data()].GetType() != field_type) {
111+
return false;
112+
}
113+
return true;
114+
}
115+
116+
static bool CheckFields(const Value &object, std::vector<std::pair<std::string_view, Type>> fields) {
117+
for (auto &field: fields) {
118+
if (!CheckField(object, field)) {
119+
return false;
120+
}
121+
}
122+
return true;
123+
}
124+
96125
static void FillStatus(HID_Response_t status, char *res, const char *message) {
97126
StringBuffer buffer;
98127
Writer writer(buffer);
@@ -105,6 +134,10 @@ static void FillStatus(HID_Response_t status, char *res, const char *message) {
105134
std::strcpy(res, buffer.GetString());
106135
}
107136

137+
static void FillStatus(HID_Response_t status, char *res, std::string_view message) {
138+
FillStatus(status, res, message.data());
139+
}
140+
108141
static void FillStatus(HID_Response_t status, char *res) {
109142
FillStatus(status, res, "");
110143
}
@@ -327,6 +360,151 @@ static void get_setting(Document &root, char *res) {
327360
std::strcpy(res, buffer.GetString());
328361
}
329362

363+
static void erase_bl_b(Document &root, char *res) {
364+
fal_partition_erase(bl_b_part,0, bl_b_part->len);
365+
FillStatus(HID_RESPONSE_SUCCESS, res);
366+
}
367+
368+
static void write_bl_b(Document &root, char *res) {
369+
#define PACK_SIZE 512
370+
if (!CheckFields(root,
371+
{{"addr", Type::kNumberType},
372+
{"len", Type::kNumberType},
373+
{"data", Type::kStringType}})) {
374+
FillStatus(HID_RESPONSE_FAILED, res, filed_miss_msg);
375+
return;
376+
}
377+
auto addr = root["addr"].GetInt();
378+
auto len = root["len"].GetInt();
379+
auto data_b64 = root["data"].GetString();
380+
auto data_b64_len = root["data"].GetStringLength();
381+
log_d("addr: 0x%X, len: %d, data_len: %d", addr, len, data_b64_len);
382+
// elog_hexdump("b64", 16, data_b64, data_b64_len);
383+
if (addr + len > bl_b_part->len) {
384+
const char *message = "addr out of range";
385+
USB_LOG_WRN("%s\n", message);
386+
FillStatus(HID_RESPONSE_FAILED, res, message);
387+
return;
388+
}
389+
if (len % 4 != 0) {
390+
char msg[64];
391+
snprintf(msg, sizeof(msg), "len %d not multiple of 4", len);
392+
log_w(msg);
393+
FillStatus(HID_RESPONSE_FAILED, res, msg);
394+
return;
395+
}
396+
if (addr % 512 != 0) {
397+
log_w("addr %d not multiple of 512", addr);
398+
return;
399+
}
400+
log_i("addr: 0x%X, len: %d", addr, len);
401+
size_t data_len = 0;
402+
uint8_t *data = b64_decode_ex(data_b64, data_b64_len, &data_len);
403+
log_d("solve b64 data_len: %d", data_len);
404+
// elog_hexdump(LOG_TAG, 16, data, data_len);
405+
if (data_len != len) {
406+
log_w("data_len != len");
407+
FillStatus(HID_RESPONSE_FAILED, res, "data_len != len");
408+
return;
409+
}
410+
if (data_len > PACK_SIZE) {
411+
char msg[64];
412+
snprintf(msg, sizeof(msg), "data_len %d > %d", data_len, PACK_SIZE);
413+
log_w(msg);
414+
FillStatus(HID_RESPONSE_FAILED, res, msg);
415+
return;
416+
}
417+
fal_partition_write(bl_b_part, addr, data, len);
418+
log_i("write %d bytes to 0x%X done", len, addr + bl_b_part->offset);
419+
FillStatus(HID_RESPONSE_SUCCESS, res);
420+
free(data);
421+
}
422+
423+
static void upgrade_bl(Document &root, char *res) {
424+
if (!CheckFields(root,
425+
{{"len", Type::kNumberType},
426+
{"crc", Type::kStringType}})) {
427+
FillStatus(HID_RESPONSE_FAILED, res, filed_miss_msg);
428+
return;
429+
}
430+
auto len = root["len"].GetInt();
431+
auto crc_str = root["crc"].GetString();
432+
auto crc = strtoul(crc_str + 2, nullptr, 16);
433+
if (len > bl_b_part->len) {
434+
char msg[64];
435+
snprintf(msg, sizeof(msg), "len %d > %d", len, bl_b_part->len);
436+
log_w(msg);
437+
FillStatus(HID_RESPONSE_FAILED, res, msg);
438+
return;
439+
}
440+
if (len % 4) {
441+
log_w("len %% 4 != 0");
442+
FillStatus(HID_RESPONSE_FAILED, res, "len %% 4 != 0");
443+
return;
444+
}
445+
446+
{
447+
uint32_t crc_calc = 0xFFFFFFFF;
448+
const uint32_t CRC_CALC_LEN = 8 * 1024;
449+
auto buf = std::make_unique<uint8_t[]>(CRC_CALC_LEN);
450+
for (uint32_t i = 0; i < len; i += CRC_CALC_LEN) {
451+
auto calc_len = std::min(CRC_CALC_LEN, len - i);
452+
fal_partition_read(bl_b_part, i, buf.get(), calc_len);
453+
crc_calc = CRC_CalcArray_Software(buf.get(), calc_len, crc_calc);
454+
// log_d("crc calc 0x%x", crc_calc);
455+
}
456+
if (crc != crc_calc) {
457+
log_w("crc != crc_calc recv 0x%x calc 0x%x", crc, crc_calc);
458+
FillStatus(HID_RESPONSE_FAILED, res, "crc != crc_calc");
459+
return;
460+
}
461+
}
462+
463+
log_d("crc check pass, start copy...");
464+
{
465+
constexpr uint32_t COPY_LEN = 4 * 1024;
466+
auto buf = std::make_unique<uint8_t[]>(COPY_LEN);
467+
fal_partition_erase(bl_part, 0, bl_part->len);
468+
for (size_t i = 0; i < bl_part->len; i += COPY_LEN) {
469+
auto copy_len = std::min(COPY_LEN, (uint32_t)(bl_part->len - i));
470+
log_d("copy from 0x%X to 0x%X, size 0x%X",
471+
i + bl_b_part->offset,
472+
i + bl_part->offset,
473+
copy_len);
474+
fal_partition_read(bl_b_part, i, buf.get(), copy_len);
475+
fal_partition_write(bl_part, i, buf.get(), copy_len);
476+
}
477+
}
478+
log_d("copy done");
479+
{
480+
const uint32_t COMP_LEN = 1024;
481+
auto buf_1 = std::make_unique<uint8_t[]>(COMP_LEN);
482+
auto buf_2 = std::make_unique<uint8_t[]>(COMP_LEN);
483+
for (size_t i = 0; i < bl_part->len; i += COMP_LEN) {
484+
auto comp_len = std::min(COMP_LEN, (uint32_t)(bl_part->len - i));
485+
fal_partition_read(bl_b_part, i, buf_1.get(), comp_len);
486+
fal_partition_read(bl_part, i, buf_2.get(), comp_len);
487+
if (memcmp(buf_1.get(), buf_2.get(), comp_len) != 0) {
488+
log_w("copy fail at 0x%X", i);
489+
FillStatus(HID_RESPONSE_FAILED, res, "copy done check failed");
490+
log_d("in b slot");
491+
elog_hexdump(LOG_TAG, 16, buf_1.get(), comp_len);
492+
log_d("in bl");
493+
elog_hexdump(LOG_TAG, 16, buf_2.get(), comp_len);
494+
// TODO should we roll back bl? or copy it again?
495+
}
496+
}
497+
}
498+
499+
log_d("check done");
500+
501+
FillStatus(HID_RESPONSE_SUCCESS, res);
502+
503+
board_delay_ms(1000);
504+
505+
HSP_Reboot();
506+
}
507+
330508
static void HID_Write(const std::string &res) {
331509
std::strcpy(reinterpret_cast<char *>(HID_write_buffer + 1), res.c_str());
332510
}
@@ -351,7 +529,10 @@ void HID_Handle() {
351529
{"upgrade", upgrade},
352530
{"entry_sys_bl", entry_sys_bl},
353531
{"entry_hslink_bl", entry_hslink_bl},
354-
{"set_hw_ver", set_hw_ver}
532+
{"set_hw_ver", set_hw_ver},
533+
{"erase_bl_b", erase_bl_b},
534+
{"write_bl_b", write_bl_b},
535+
{"upgrade_bl", upgrade_bl}
355536
};
356537

357538
Document root;

projects/HSLink-Pro/src/HSLink_Pro_expansion.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,27 @@ extern "C" void HSP_Loop(void) {
461461
}
462462
}
463463

464+
extern "C" void HSP_Reboot(void) {
465+
bl_setting.keep_bootloader = 0;
466+
neopixel->SetPixel(0, 0, 0, 0);
467+
neopixel->Flush();
468+
disable_global_irq(CSR_MSTATUS_MIE_MASK);
469+
//disable_global_irq(CSR_MSTATUS_SIE_MASK);
470+
disable_global_irq(CSR_MSTATUS_UIE_MASK);
471+
l1c_dc_invalidate_all();
472+
l1c_dc_disable();
473+
fencei();
474+
475+
api_boot_arg_t boot_arg = {
476+
.index = 0,
477+
.peripheral = API_BOOT_PERIPH_AUTO,
478+
.src = API_BOOT_SRC_PRIMARY,
479+
.tag = API_BOOT_TAG,
480+
};
481+
482+
ROM_API_TABLE_ROOT->run_bootloader(&boot_arg);
483+
}
484+
464485
extern "C" void HSP_EnterHSLinkBootloader(void) {
465486
bl_setting.keep_bootloader = 1;
466487
neopixel->SetPixel(0, 0, 0, 0);

projects/HSLink-Pro/src/HSLink_Pro_expansion.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ void HSP_Init(void);
3535
*/
3636
void HSP_Loop(void);
3737

38+
void HSP_Reboot(void);
39+
3840
void HSP_EnterHSLinkBootloader(void);
3941

4042
void HSP_EntrySysBootloader(void);

projects/HSLink-Pro/src/JTAG_DP/JTAG_DP_SPI.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,13 @@ void SPI_PORT_JTAG_SETUP(void)
9292
gpiom_configure_pin_control_setting(PIN_SRST);
9393
gpiom_configure_pin_control_setting(PIN_JTAG_TRST);
9494

95+
static uint8_t SRST_Level = 1;
96+
if (CheckHardwareVersion(1, 2, UINT8_MAX)) {
97+
SRST_Level = 0;
98+
}
99+
95100
gpio_set_pin_output(PIN_GPIO, GPIO_GET_PORT_INDEX(PIN_SRST), GPIO_GET_PIN_INDEX(PIN_SRST));
96-
gpio_write_pin(PIN_GPIO, GPIO_GET_PORT_INDEX(PIN_SRST), GPIO_GET_PIN_INDEX(PIN_SRST), Setting_GetSRSTLevel());
101+
gpio_write_pin(PIN_GPIO, GPIO_GET_PORT_INDEX(PIN_SRST), GPIO_GET_PIN_INDEX(PIN_SRST), SRST_Level);
97102
gpio_set_pin_output(PIN_GPIO, GPIO_GET_PORT_INDEX(PIN_JTAG_TRST), GPIO_GET_PIN_INDEX(PIN_JTAG_TRST));
98103
gpio_write_pin(PIN_GPIO, GPIO_GET_PORT_INDEX(PIN_JTAG_TRST), GPIO_GET_PIN_INDEX(PIN_JTAG_TRST), 1);
99104

projects/HSLink-Pro/src/SW_DP/SW_DP_SPI.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,14 @@ void SPI_PORT_SWD_SETUP(void)
4343
HPM_IOC->PAD[PIN_SRST].FUNC_CTL = IOC_PAD_FUNC_CTL_ALT_SELECT_SET(0);
4444
HPM_IOC->PAD[PIN_SRST].PAD_CTL = IOC_PAD_PAD_CTL_PRS_SET(2) | IOC_PAD_PAD_CTL_PE_SET(1) | IOC_PAD_PAD_CTL_PS_SET(1) | IOC_PAD_PAD_CTL_SPD_SET(3);
4545
gpiom_configure_pin_control_setting(PIN_SRST);
46+
47+
static uint8_t SRST_Level = 1;
48+
if (CheckHardwareVersion(1, 2, UINT8_MAX)) {
49+
SRST_Level = 0;
50+
}
51+
4652
gpio_set_pin_output(PIN_GPIO, GPIO_GET_PORT_INDEX(PIN_SRST), GPIO_GET_PIN_INDEX(PIN_SRST));
47-
gpio_write_pin(PIN_GPIO, GPIO_GET_PORT_INDEX(PIN_SRST), GPIO_GET_PIN_INDEX(PIN_SRST), Setting_GetSRSTLevel());
53+
gpio_write_pin(PIN_GPIO, GPIO_GET_PORT_INDEX(PIN_SRST), GPIO_GET_PIN_INDEX(PIN_SRST), SRST_Level);
4854

4955
gpio_write_pin(PIN_SWDIO_DIR_GPIO, GPIO_GET_PORT_INDEX(SWDIO_DIR), GPIO_GET_PIN_INDEX(SWDIO_DIR), 0); // 默认SWDIO为输入
5056

projects/HSLink-Pro/src/setting.cpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -178,11 +178,3 @@ void Setting_SaveHardwareVersion(version_t hw_ver) {
178178
std::to_string(hw_ver.patch);
179179
fdb_kv_set(&env_db, "hw_ver", hw_ver_str.c_str());
180180
}
181-
182-
uint8_t Setting_GetSRSTLevel(void) {
183-
uint8_t level = 1;
184-
if (CheckHardwareVersion(1, 2, UINT8_MAX)) {
185-
level = 0;
186-
}
187-
return level;
188-
}

0 commit comments

Comments
 (0)