From 9bbbaf9bad50bf93405e685f06f289bd896ca963 Mon Sep 17 00:00:00 2001 From: liangkangnan Date: Thu, 11 Nov 2021 09:54:00 +0800 Subject: [PATCH] add tinyriscv_program command Signed-off-by: liangkangnan --- src/target/target.c | 301 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 295 insertions(+), 6 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index 7eeb35f59..0472f81a3 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -41,7 +41,9 @@ #include "config.h" #endif +#include #include +#include #include #include @@ -74,6 +76,7 @@ static int target_gdb_fileio_end_default(struct target *target, int retcode, int fileio_errno, bool ctrl_c); static int target_profiling_default(struct target *target, uint32_t *samples, uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds); +static int halt_mcu(struct target *target); /* targets */ extern struct target_type arm7tdmi_target; @@ -2853,6 +2856,12 @@ COMMAND_HANDLER(handle_reg_command) target = get_current_target(CMD_CTX); + if (target->state != TARGET_HALTED) { + LOG_INFO("Please halt the target first"); + retval = !ERROR_OK; + return retval; + } + /* list all available registers for the current target */ if (CMD_ARGC == 0) { struct reg_cache *cache = target->reg_cache; @@ -3127,6 +3136,10 @@ COMMAND_HANDLER(handle_resume_command) struct target *target = get_current_target(CMD_CTX); + if (target->state != TARGET_HALTED) { + halt_mcu(target); + } + /* with no CMD_ARGV, resume from current pc, addr = 0, * with one arguments, addr = CMD_ARGV[0], * handle breakpoints, not debugging */ @@ -6187,8 +6200,8 @@ COMMAND_HANDLER(handle_load_bin_command) target_addr_t addr; int retval; int i; - uint8_t *write_buffer; - uint8_t *read_buffer; + uint8_t *write_buffer = NULL; + uint8_t *read_buffer = NULL; size_t buf_cnt; uint32_t image_size; @@ -6252,17 +6265,19 @@ COMMAND_HANDLER(handle_load_bin_command) retval = target_read_buffer(target, image.sections[i].base_address, buf_cnt, read_buffer); if (retval != ERROR_OK) { free(write_buffer); - free(read_buffer); + if (read_buffer != NULL) + free(read_buffer); break; } - int k; + size_t k; for (k = 0; k < buf_cnt; k++) { if (write_buffer[k] != read_buffer[k]) { command_print(CMD, "write failed at address " TARGET_ADDR_FMT "", image.sections[i].base_address); free(write_buffer); - free(read_buffer); + if (read_buffer != NULL) + free(read_buffer); retval = ERROR_FAIL; goto end; } @@ -6275,7 +6290,7 @@ COMMAND_HANDLER(handle_load_bin_command) image.sections[i].base_address); free(write_buffer); - if (verify) + if (verify && (read_buffer != NULL)) free(read_buffer); } @@ -6291,6 +6306,273 @@ end: return retval; } + +// 烧写数据地址:4K + 1K + 256 +#define DATA_ADDR (0x20001500) + +// 烧写数据长度 +#define DATA_LEN (0x20001400) + +// 烧写(擦除)地址 +#define PROGRAM_ADDR (0x20001404) + +// 擦除标志 +// 0: 不擦除,1:擦除 +#define ERASE_FLAG (0x20001408) + +// 烧写状态标志 +// bit0为烧写结束标志,0:未烧写完成,1:烧写完成。 +// bit1为烧写结果标志,0:烧写失败,1:烧写成功 +#define RESULT_FLAG (0x2000140C) + +// loader地址 +#define LOADER_ADDR (0x20000000) + +// 每次烧写最大长度 +#define EACH_BURN_LEN (256) + +// 扇区大小 +#define FLASH_SECTOR_SIZE (4096) + +static int program_result(struct target *target) +{ + int retval; + int data; + int timeout = 0; + +wait: + usleep(200000); + + // 读烧写结束标记 + retval = target_read_buffer(target, RESULT_FLAG, 4, (uint8_t *)(&data)); + if (retval != ERROR_OK) { + goto end; + } + + // 烧写结束 + if (data & 0x1) { + // 烧写失败 + if (!(data & 0x2)) { + retval = !ERROR_OK; + // 烧写成功 + } else { + retval = ERROR_OK; + } + // 还没烧写结束 + } else { + timeout++; + if (timeout >= 20) { + retval = !ERROR_OK; + goto end; + } + goto wait; + } + +end: + return retval; +} + +static int halt_mcu(struct target *target) +{ + int retval; + + target->verbose_halt_msg = true; + + // halt住MCU + retval = target_halt(target); + if (retval != ERROR_OK) { + return retval; + } + + // 等待halt成功 + retval = target_wait_state(target, TARGET_HALTED, DEFAULT_HALT_TIMEOUT); + if (retval != ERROR_OK) { + return retval; + } + + return retval; +} + +COMMAND_HANDLER(handle_tinyriscv_program_command) +{ + struct fileio *file; + target_addr_t addr; + int retval; + size_t i; + uint8_t *data_buffer; + size_t count; + size_t file_size; + size_t num; + int data; + struct target *target; + + static const uint8_t tinyriscv_flash_write_code[] = { +#include "../../contrib/loaders/flash/tinyriscv/tinyriscv.inc" + }; + + target = get_current_target(CMD_CTX); + + // 参数检查 + if (CMD_ARGC != 2) + return ERROR_COMMAND_SYNTAX_ERROR; + + // 烧写地址 + COMMAND_PARSE_ADDRESS(CMD_ARGV[1], addr); + + struct duration bench; + duration_start(&bench); + + // halt住MCU + retval = halt_mcu(target); + if (retval != ERROR_OK) { + goto end2; + } + + LOG_INFO("flash loader downloading..."); + + // 先下载loader到内存 + retval = target_write_buffer(target, LOADER_ADDR, sizeof(tinyriscv_flash_write_code), + tinyriscv_flash_write_code); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to download flash loader into ram"); + goto end2; + } + + // 打开要烧写的文件 + if (fileio_open(&file, CMD_ARGV[0], FILEIO_READ, FILEIO_BINARY) != ERROR_OK) { + LOG_ERROR("fail to open %s", CMD_ARGV[0]); + retval = ERROR_FAIL; + goto end2; + } + + // 文件大小 + fileio_size(file, &file_size); + //LOG_INFO("bin file size: %d(bytes)", (int)(file_size)); + + LOG_INFO("erasing..."); + + // 要擦除多少个扇区 + num = (file_size / FLASH_SECTOR_SIZE) + 1; + for (i = 0; i < num; i++) { + data = 0x1; + // 擦除标记 + retval = target_write_buffer(target, ERASE_FLAG, 4, (uint8_t *)(&data)); + if (retval != ERROR_OK) { + LOG_ERROR("write erase_flag failed!!!"); + goto end1; + } + data = addr + (i * FLASH_SECTOR_SIZE); + LOG_INFO("erase addr: 0x%x", data); + // 擦除地址 + retval = target_write_buffer(target, PROGRAM_ADDR, 4, (uint8_t *)(&data)); + if (retval != ERROR_OK) { + LOG_ERROR("write erase_addr failed!!!"); + goto end1; + } + // halt住MCU + retval = halt_mcu(target); + if (retval != ERROR_OK) { + goto end1; + } + // 开始烧写 + retval = target_resume(target, 0, LOADER_ADDR, 1, 0); + if (retval != ERROR_OK) { + LOG_ERROR("resume failed!!!"); + goto end1; + } + // 获取烧写结果 + retval = program_result(target); + if (retval != ERROR_OK) { + LOG_ERROR("erase failed!!!"); + goto end1; + } + } + + // 清擦除标志 + data = 0; + retval = target_write_buffer(target, ERASE_FLAG, 4, (uint8_t *)(&data)); + if (retval != ERROR_OK) { + goto end1; + } + + // 分配内存 + data_buffer = malloc(EACH_BURN_LEN); + if (data_buffer == NULL) { + LOG_ERROR("error allocating data buffer (%d bytes)", + EACH_BURN_LEN); + retval = ERROR_FAIL; + goto end1; + } + + retval = ERROR_OK; + + LOG_INFO("programming..."); + + num = file_size; + while (num > 0) { + fileio_read(file, EACH_BURN_LEN, data_buffer, &count); + if (count > 0) { + // 下载数据 + retval = target_write_buffer(target, DATA_ADDR, count, data_buffer); + if (retval != ERROR_OK) { + LOG_ERROR("write data failed!!!"); + break; + } + data = addr; + LOG_INFO("program addr: 0x%x", data); + // 烧写地址 + retval = target_write_buffer(target, PROGRAM_ADDR, 4, (uint8_t *)(&data)); + if (retval != ERROR_OK) { + LOG_ERROR("write program addr failed!!!"); + break; + } + data = count; + // 烧写长度 + retval = target_write_buffer(target, DATA_LEN, 4, (uint8_t *)(&data)); + if (retval != ERROR_OK) { + LOG_ERROR("write data len failed!!!"); + break; + } + // halt住MCU + retval = halt_mcu(target); + if (retval != ERROR_OK) { + goto end1; + } + // 开始烧写 + retval = target_resume(target, 0, LOADER_ADDR, 1, 0); + if (retval != ERROR_OK) { + LOG_ERROR("resume failed!!!"); + break; + } + // 获取烧写结果 + retval = program_result(target); + if (retval != ERROR_OK) { + LOG_ERROR("program failed!!!"); + break; + } + addr += count; + } + num -= count; + } + + if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { + LOG_INFO("program %" PRIu32 " bytes " + "in %fs (%0.3f KiB/s)", (uint32_t)(file_size), + duration_elapsed(&bench), duration_kbps(&bench, file_size)); + } + + free(data_buffer); +end1: + fileio_close(file); +end2: + if (retval == ERROR_OK) { + LOG_INFO("End, program succ"); + } else { + LOG_ERROR("End, program failed!!!"); + } + return retval; +} + static const struct command_registration target_exec_command_handlers[] = { { .name = "fast_load_image", @@ -6544,6 +6826,13 @@ static const struct command_registration target_exec_command_handlers[] = { .help = "Download bin file into memory and verify it", .usage = "filename address verify", }, + { + .name = "tinyriscv_program", + .handler = handle_tinyriscv_program_command, + .mode = COMMAND_EXEC, + .help = "Program file into external flash", + .usage = "filename address", + }, COMMAND_REGISTRATION_DONE };