Fix flashing HiFive Unleashed (#402)

* Align algorithm stack to XLEN.

This fixes algorithm timeout on RV64 targets.
Also improve debug information in various places.

Change-Id: Id3121f9c6e753c6a7e14da511e4de0587a6f7b4d

* Compile 32-bit RISC-V algorithms for RV32E.

Change-Id: I33a698c0c6ba540de29fa0459242c72a67b0cbaa

* Remove debug code.

Change-Id: I37c966ce0f2d1fe68cd6ae0724d19ae95ebaf51b

* Dump start of gdb packets escaping non-printable.

Change-Id: Ie5f36b5c9041bfc0e5aa9543f0afe2c4810c2915

* Propagate flash programming errors.

Change-Id: I0c938ce7a1062bcc93426538cbc82424000f37b7

* Improve debug messaging.

Change-Id: I47ac3518f3b241986c677824864102936100adf6

* Add debug output to flash image.

This is helpful when you're debugging the flash algorithm itself, and a
nop when running it through OpenOCD.

Change-Id: Id44c6498c288872cc2cec79044116ac38198c572

* Make timeout depend on how much data is written.

Change-Id: I819efa04cd6f6bd6664afd5c53cc7a8a5c84f54e

* Fix issi erase commands.

This is required to flash HiFive Unleashed.

Change-Id: I33e4869d1d05ca8a1df6136bccf11afda61bfe10

* Fix running algorithm on multicore `-rtos riscv`.

The bug was that poll() might change the currently selected hart, and in
that case we'd access registers on that other hart after the algorithm
is finished.

Change-Id: I140431898285cf471b372139cef2378ab4879377

* Make fespi flash algorithm debugging optional.

Also add a scheme that allows you to see the stack trace of where a
failure occurred if debugging is enabled.

Change-Id: Ia9a3a9a941ceba0f8ff6b47da5a8643e5f84b252
This commit is contained in:
Tim Newsome
2019-09-09 12:01:17 -07:00
committed by GitHub
parent 24d59cfb90
commit 274be9587f
13 changed files with 245 additions and 151 deletions
+1 -1
View File
@@ -590,7 +590,7 @@ static int fespi_write(struct flash_bank *bank, const uint8_t *buffer,
fespi_info->ctrl_base, page_size, data_wa->address, offset, cur_count,
buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]);
retval = target_run_algorithm(target, 0, NULL, 5, reg_params,
algorithm_wa->address, 0, 10000, NULL);
algorithm_wa->address, 0, cur_count * 2, NULL);
if (retval != ERROR_OK) {
LOG_ERROR("Failed to execute algorithm at " TARGET_ADDR_FMT ": %d",
algorithm_wa->address, retval);
+4 -4
View File
@@ -124,10 +124,10 @@ const struct flash_device flash_devices[] = {
FLASH_ID("issi is25lp064", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x0017609d, 0x100, 0x10000, 0x800000),
FLASH_ID("issi is25lp128d", 0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x0018609d, 0x100, 0x10000, 0x1000000),
FLASH_ID("issi is25wp128d", 0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x0018709d, 0x100, 0x10000, 0x1000000),
FLASH_ID("issi is25lp256d", 0x13, 0xec, 0x12, 0xdc, 0xc7, 0x0019609d, 0x100, 0x10000, 0x2000000),
FLASH_ID("issi is25wp256d", 0x13, 0xec, 0x12, 0xdc, 0xc7, 0x0019709d, 0x100, 0x10000, 0x2000000),
FLASH_ID("issi is25lp512m", 0x13, 0xec, 0x12, 0xdc, 0xc7, 0x001a609d, 0x100, 0x10000, 0x4000000),
FLASH_ID("issi is25wp512m", 0x13, 0xec, 0x12, 0xdc, 0xc7, 0x001a709d, 0x100, 0x10000, 0x4000000),
FLASH_ID("issi is25lp256d", 0x13, 0xec, 0x12, 0xd8, 0xc7, 0x0019609d, 0x100, 0x10000, 0x2000000),
FLASH_ID("issi is25wp256d", 0x13, 0xec, 0x12, 0xd8, 0xc7, 0x0019709d, 0x100, 0x10000, 0x2000000),
FLASH_ID("issi is25lp512m", 0x13, 0xec, 0x12, 0xd8, 0xc7, 0x001a609d, 0x100, 0x10000, 0x4000000),
FLASH_ID("issi is25wp512m", 0x13, 0xec, 0x12, 0xd8, 0xc7, 0x001a709d, 0x100, 0x10000, 0x4000000),
/* FRAM, no erase commands, no write page or sectors */
FRAM_ID("fu mb85rs16n", 0x03, 0, 0x02, 0x00010104, 0x800),
+17 -10
View File
@@ -3178,16 +3178,23 @@ static int gdb_input_inner(struct connection *connection)
gdb_packet_buffer[packet_size] = '\0';
if (LOG_LEVEL_IS(LOG_LVL_DEBUG)) {
if (packet[0] == 'X') {
/* binary packets spew junk into the debug log stream */
char buf[50];
int x;
for (x = 0; (x < 49) && (packet[x] != ':'); x++)
buf[x] = packet[x];
buf[x] = 0;
LOG_DEBUG("received packet: '%s:<binary-data>'", buf);
} else
LOG_DEBUG("received packet: '%s'", packet);
char buf[64];
unsigned offset = 0;
int i = 0;
while (i < packet_size && offset < 56) {
if (packet[i] == '\\') {
buf[offset++] = '\\';
buf[offset++] = '\\';
} else if (isprint(packet[i])) {
buf[offset++] = packet[i];
} else {
sprintf(buf + offset, "\\x%02x", (unsigned char) packet[i]);
offset += 4;
}
i++;
}
buf[offset] = 0;
LOG_DEBUG("received packet: '%s'%s", buf, i < packet_size ? "..." : "");
}
if (packet_size > 0) {
+2
View File
@@ -84,6 +84,8 @@ enum gdb_regno {
GDB_REGNO_DCSR = CSR_DCSR + GDB_REGNO_CSR0,
GDB_REGNO_DSCRATCH = CSR_DSCRATCH + GDB_REGNO_CSR0,
GDB_REGNO_MSTATUS = CSR_MSTATUS + GDB_REGNO_CSR0,
GDB_REGNO_MEPC = CSR_MEPC + GDB_REGNO_CSR0,
GDB_REGNO_MCAUSE = CSR_MCAUSE + GDB_REGNO_CSR0,
GDB_REGNO_CSR4095 = GDB_REGNO_CSR0 + 4095,
GDB_REGNO_PRIV = 4161,
GDB_REGNO_COUNT
+7 -6
View File
@@ -3300,14 +3300,15 @@ struct target_type riscv013_target = {
static int riscv013_get_register(struct target *target,
riscv_reg_t *value, int hid, int rid)
{
LOG_DEBUG("reading register %s on hart %d", gdb_regno_name(rid), hid);
LOG_DEBUG("[%d] reading register %s on hart %d", target->coreid,
gdb_regno_name(rid), hid);
riscv_set_current_hartid(target, hid);
int result = ERROR_OK;
if (rid == GDB_REGNO_PC) {
result = register_read(target, value, GDB_REGNO_DPC);
LOG_DEBUG("read PC from DPC: 0x%" PRIx64, *value);
LOG_DEBUG("[%d] read PC from DPC: 0x%" PRIx64, target->coreid, *value);
} else if (rid == GDB_REGNO_PRIV) {
uint64_t dcsr;
result = register_read(target, &dcsr, GDB_REGNO_DCSR);
@@ -3323,19 +3324,19 @@ static int riscv013_get_register(struct target *target,
static int riscv013_set_register(struct target *target, int hid, int rid, uint64_t value)
{
LOG_DEBUG("writing 0x%" PRIx64 " to register %s on hart %d", value,
gdb_regno_name(rid), hid);
LOG_DEBUG("[%d] writing 0x%" PRIx64 " to register %s on hart %d",
target->coreid, value, gdb_regno_name(rid), hid);
riscv_set_current_hartid(target, hid);
if (rid <= GDB_REGNO_XPR31) {
return register_write_direct(target, rid, value);
} else if (rid == GDB_REGNO_PC) {
LOG_DEBUG("writing PC to DPC: 0x%" PRIx64, value);
LOG_DEBUG("[%d] writing PC to DPC: 0x%" PRIx64, target->coreid, value);
register_write_direct(target, GDB_REGNO_DPC, value);
uint64_t actual_value;
register_read_direct(target, &actual_value, GDB_REGNO_DPC);
LOG_DEBUG(" actual DPC written: 0x%016" PRIx64, actual_value);
LOG_DEBUG("[%d] actual DPC written: 0x%016" PRIx64, target->coreid, actual_value);
if (value != actual_value) {
LOG_ERROR("Written PC (0x%" PRIx64 ") does not match read back "
"value (0x%" PRIx64 ")", value, actual_value);
+30 -10
View File
@@ -1416,6 +1416,7 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params,
target_addr_t exit_point, int timeout_ms, void *arch_info)
{
riscv_info_t *info = (riscv_info_t *) target->arch_info;
int hartid = riscv_current_hartid(target);
if (num_mem_params > 0) {
LOG_ERROR("Memory parameters are not supported for RISC-V algorithms.");
@@ -1495,12 +1496,23 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params,
LOG_DEBUG("poll()");
int64_t now = timeval_ms();
if (now - start > timeout_ms) {
LOG_ERROR("Algorithm timed out after %d ms.", timeout_ms);
LOG_ERROR(" now = 0x%08x", (uint32_t) now);
LOG_ERROR(" start = 0x%08x", (uint32_t) start);
LOG_ERROR("Algorithm timed out after %" PRId64 " ms.", now - start);
riscv_halt(target);
old_or_new_riscv_poll(target);
for (enum gdb_regno regno = 0; regno <= GDB_REGNO_PC; regno++) {
enum gdb_regno regnums[] = {
GDB_REGNO_RA, GDB_REGNO_SP, GDB_REGNO_GP, GDB_REGNO_TP,
GDB_REGNO_T0, GDB_REGNO_T1, GDB_REGNO_T2, GDB_REGNO_FP,
GDB_REGNO_S1, GDB_REGNO_A0, GDB_REGNO_A1, GDB_REGNO_A2,
GDB_REGNO_A3, GDB_REGNO_A4, GDB_REGNO_A5, GDB_REGNO_A6,
GDB_REGNO_A7, GDB_REGNO_S2, GDB_REGNO_S3, GDB_REGNO_S4,
GDB_REGNO_S5, GDB_REGNO_S6, GDB_REGNO_S7, GDB_REGNO_S8,
GDB_REGNO_S9, GDB_REGNO_S10, GDB_REGNO_S11, GDB_REGNO_T3,
GDB_REGNO_T4, GDB_REGNO_T5, GDB_REGNO_T6,
GDB_REGNO_PC,
GDB_REGNO_MSTATUS, GDB_REGNO_MEPC, GDB_REGNO_MCAUSE,
};
for (unsigned i = 0; i < DIM(regnums); i++) {
enum gdb_regno regno = regnums[i];
riscv_reg_t reg_value;
if (riscv_get_register(target, &reg_value, regno) != ERROR_OK)
break;
@@ -1514,6 +1526,10 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params,
return result;
}
/* The current hart id might have been changed in poll(). */
if (riscv_set_current_hartid(target, hartid) != ERROR_OK)
return ERROR_FAIL;
if (reg_pc->type->get(reg_pc) != ERROR_OK)
return ERROR_FAIL;
uint64_t final_pc = buf_get_u64(reg_pc->value, 0, reg_pc->size);
@@ -1538,24 +1554,24 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params,
if (reg_params[i].direction == PARAM_IN ||
reg_params[i].direction == PARAM_IN_OUT) {
struct reg *r = register_get_by_name(target->reg_cache, reg_params[i].reg_name, 0);
if (r->type->get(r) != ERROR_OK)
if (r->type->get(r) != ERROR_OK) {
LOG_ERROR("get(%s) failed", r->name);
return ERROR_FAIL;
}
buf_cpy(r->value, reg_params[i].value, reg_params[i].size);
}
LOG_DEBUG("restore %s", reg_params[i].reg_name);
struct reg *r = register_get_by_name(target->reg_cache, reg_params[i].reg_name, 0);
buf_set_u64(buf, 0, info->xlen[0], saved_regs[r->number]);
if (r->type->set(r, buf) != ERROR_OK)
if (r->type->set(r, buf) != ERROR_OK) {
LOG_ERROR("set(%s) failed", r->name);
return ERROR_FAIL;
}
}
return ERROR_OK;
}
/* Should run code on the target to perform CRC of
memory. Not yet implemented.
*/
static int riscv_checksum_memory(struct target *target,
target_addr_t address, uint32_t count,
uint32_t *checksum)
@@ -2967,6 +2983,10 @@ const char *gdb_regno_name(enum gdb_regno regno)
return "dscratch";
case GDB_REGNO_MSTATUS:
return "mstatus";
case GDB_REGNO_MEPC:
return "mepc";
case GDB_REGNO_MCAUSE:
return "mcause";
case GDB_REGNO_PRIV:
return "priv";
default: