add tinyriscv_program command

Signed-off-by: liangkangnan <liangkangnan@163.com>
tinyriscv
liangkangnan 2021-11-11 09:54:00 +08:00
parent e5a97681ea
commit 9bbbaf9bad
1 changed files with 295 additions and 6 deletions

View File

@ -41,7 +41,9 @@
#include "config.h" #include "config.h"
#endif #endif
#include <sys/time.h>
#include <helper/time_support.h> #include <helper/time_support.h>
#include <helper/fileio.h>
#include <jtag/jtag.h> #include <jtag/jtag.h>
#include <flash/nor/core.h> #include <flash/nor/core.h>
@ -74,6 +76,7 @@ static int target_gdb_fileio_end_default(struct target *target, int retcode,
int fileio_errno, bool ctrl_c); int fileio_errno, bool ctrl_c);
static int target_profiling_default(struct target *target, uint32_t *samples, static int target_profiling_default(struct target *target, uint32_t *samples,
uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds); uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds);
static int halt_mcu(struct target *target);
/* targets */ /* targets */
extern struct target_type arm7tdmi_target; extern struct target_type arm7tdmi_target;
@ -2853,6 +2856,12 @@ COMMAND_HANDLER(handle_reg_command)
target = get_current_target(CMD_CTX); 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 */ /* list all available registers for the current target */
if (CMD_ARGC == 0) { if (CMD_ARGC == 0) {
struct reg_cache *cache = target->reg_cache; struct reg_cache *cache = target->reg_cache;
@ -3127,6 +3136,10 @@ COMMAND_HANDLER(handle_resume_command)
struct target *target = get_current_target(CMD_CTX); 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 no CMD_ARGV, resume from current pc, addr = 0,
* with one arguments, addr = CMD_ARGV[0], * with one arguments, addr = CMD_ARGV[0],
* handle breakpoints, not debugging */ * handle breakpoints, not debugging */
@ -6187,8 +6200,8 @@ COMMAND_HANDLER(handle_load_bin_command)
target_addr_t addr; target_addr_t addr;
int retval; int retval;
int i; int i;
uint8_t *write_buffer; uint8_t *write_buffer = NULL;
uint8_t *read_buffer; uint8_t *read_buffer = NULL;
size_t buf_cnt; size_t buf_cnt;
uint32_t image_size; 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); retval = target_read_buffer(target, image.sections[i].base_address, buf_cnt, read_buffer);
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
free(write_buffer); free(write_buffer);
free(read_buffer); if (read_buffer != NULL)
free(read_buffer);
break; break;
} }
int k; size_t k;
for (k = 0; k < buf_cnt; k++) { for (k = 0; k < buf_cnt; k++) {
if (write_buffer[k] != read_buffer[k]) { if (write_buffer[k] != read_buffer[k]) {
command_print(CMD, "write failed at address " TARGET_ADDR_FMT "", command_print(CMD, "write failed at address " TARGET_ADDR_FMT "",
image.sections[i].base_address); image.sections[i].base_address);
free(write_buffer); free(write_buffer);
free(read_buffer); if (read_buffer != NULL)
free(read_buffer);
retval = ERROR_FAIL; retval = ERROR_FAIL;
goto end; goto end;
} }
@ -6275,7 +6290,7 @@ COMMAND_HANDLER(handle_load_bin_command)
image.sections[i].base_address); image.sections[i].base_address);
free(write_buffer); free(write_buffer);
if (verify) if (verify && (read_buffer != NULL))
free(read_buffer); free(read_buffer);
} }
@ -6291,6 +6306,273 @@ end:
return retval; 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[] = { static const struct command_registration target_exec_command_handlers[] = {
{ {
.name = "fast_load_image", .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", .help = "Download bin file into memory and verify it",
.usage = "filename address verify", .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 COMMAND_REGISTRATION_DONE
}; };