add tinyriscv_program command
Signed-off-by: liangkangnan <liangkangnan@163.com>tinyriscv
parent
e5a97681ea
commit
9bbbaf9bad
|
@ -41,7 +41,9 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <helper/time_support.h>
|
||||
#include <helper/fileio.h>
|
||||
#include <jtag/jtag.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);
|
||||
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,16 +6265,18 @@ 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);
|
||||
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);
|
||||
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
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue