Skip to content

Commit 10a2823

Browse files
committed
Read memory words individually if burst read fails
1 parent 933cb87 commit 10a2823

File tree

1 file changed

+79
-44
lines changed

1 file changed

+79
-44
lines changed

src/target/riscv/riscv-013.c

Lines changed: 79 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2036,53 +2036,13 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
20362036
* Read the requested memory, taking care to execute every read exactly once,
20372037
* even if cmderr=busy is encountered.
20382038
*/
2039-
static int read_memory_progbuf(struct target *target, target_addr_t address,
2039+
static int read_memory_progbuf_inner(struct target *target, target_addr_t address,
20402040
uint32_t size, uint32_t count, uint8_t *buffer)
20412041
{
20422042
RISCV013_INFO(info);
20432043

20442044
int result = ERROR_OK;
20452045

2046-
LOG_DEBUG("reading %d words of %d bytes from 0x%" TARGET_PRIxADDR, count,
2047-
size, address);
2048-
2049-
select_dmi(target);
2050-
2051-
/* s0 holds the next address to write to
2052-
* s1 holds the next data value to write
2053-
*/
2054-
uint64_t s0, s1;
2055-
if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK)
2056-
return ERROR_FAIL;
2057-
if (register_read(target, &s1, GDB_REGNO_S1) != ERROR_OK)
2058-
return ERROR_FAIL;
2059-
2060-
if (execute_fence(target) != ERROR_OK)
2061-
return ERROR_FAIL;
2062-
2063-
/* Write the program (load, increment) */
2064-
struct riscv_program program;
2065-
riscv_program_init(&program, target);
2066-
switch (size) {
2067-
case 1:
2068-
riscv_program_lbr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0);
2069-
break;
2070-
case 2:
2071-
riscv_program_lhr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0);
2072-
break;
2073-
case 4:
2074-
riscv_program_lwr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0);
2075-
break;
2076-
default:
2077-
LOG_ERROR("Unsupported size: %d", size);
2078-
return ERROR_FAIL;
2079-
}
2080-
riscv_program_addi(&program, GDB_REGNO_S0, GDB_REGNO_S0, size);
2081-
2082-
if (riscv_program_ebreak(&program) != ERROR_OK)
2083-
return ERROR_FAIL;
2084-
riscv_program_write(&program);
2085-
20862046
/* Write address to S0, and execute buffer. */
20872047
result = register_write_direct(target, GDB_REGNO_S0, address);
20882048
if (result != ERROR_OK)
@@ -2210,7 +2170,7 @@ static int read_memory_progbuf(struct target *target, target_addr_t address,
22102170
1 << DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET);
22112171
break;
22122172
default:
2213-
LOG_ERROR("error when reading memory, abstractcs=0x%08lx", (long)abstractcs);
2173+
LOG_DEBUG("error when reading memory, abstractcs=0x%08lx", (long)abstractcs);
22142174
riscv013_clear_abstract_error(target);
22152175
riscv_batch_free(batch);
22162176
result = ERROR_FAIL;
@@ -2268,13 +2228,88 @@ static int read_memory_progbuf(struct target *target, target_addr_t address,
22682228
write_to_buf(buffer + receive_addr - address, value, size);
22692229
log_memory_access(receive_addr, value, size, true);
22702230

2271-
riscv_set_register(target, GDB_REGNO_S0, s0);
2272-
riscv_set_register(target, GDB_REGNO_S1, s1);
22732231
return ERROR_OK;
22742232

22752233
error:
22762234
dmi_write(target, DMI_ABSTRACTAUTO, 0);
22772235

2236+
return result;
2237+
}
2238+
2239+
/**
2240+
* Read the requested memory, silently handling memory access errors.
2241+
*/
2242+
static int read_memory_progbuf(struct target *target, target_addr_t address,
2243+
uint32_t size, uint32_t count, uint8_t *buffer)
2244+
{
2245+
int result = ERROR_OK;
2246+
2247+
LOG_DEBUG("reading %d words of %d bytes from 0x%" TARGET_PRIxADDR, count,
2248+
size, address);
2249+
2250+
select_dmi(target);
2251+
2252+
/* s0 holds the next address to write to
2253+
* s1 holds the next data value to write
2254+
*/
2255+
uint64_t s0, s1;
2256+
if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK)
2257+
return ERROR_FAIL;
2258+
if (register_read(target, &s1, GDB_REGNO_S1) != ERROR_OK)
2259+
return ERROR_FAIL;
2260+
2261+
if (execute_fence(target) != ERROR_OK)
2262+
return ERROR_FAIL;
2263+
2264+
/* Write the program (load, increment) */
2265+
struct riscv_program program;
2266+
riscv_program_init(&program, target);
2267+
switch (size) {
2268+
case 1:
2269+
riscv_program_lbr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0);
2270+
break;
2271+
case 2:
2272+
riscv_program_lhr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0);
2273+
break;
2274+
case 4:
2275+
riscv_program_lwr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0);
2276+
break;
2277+
default:
2278+
LOG_ERROR("Unsupported size: %d", size);
2279+
return ERROR_FAIL;
2280+
}
2281+
riscv_program_addi(&program, GDB_REGNO_S0, GDB_REGNO_S0, size);
2282+
2283+
if (riscv_program_ebreak(&program) != ERROR_OK)
2284+
return ERROR_FAIL;
2285+
riscv_program_write(&program);
2286+
2287+
result = read_memory_progbuf_inner(target, address, size, count, buffer);
2288+
2289+
/* The full read did not succeed, so we will try to read each word individually. */
2290+
/* This will not be fast, but reading outside actual memory is a special case anyway. */
2291+
/* It will make the toolchain happier, especially Eclipse Memory View as it reads ahead. */
2292+
if (result != ERROR_OK) {
2293+
target_addr_t address_i = address;
2294+
uint32_t size_i = size;
2295+
uint32_t count_i = 1;
2296+
uint8_t* buffer_i = buffer;
2297+
2298+
for (uint32_t i = 0; i < count; i++, address_i += size_i, buffer_i += size_i) {
2299+
result = read_memory_progbuf_inner(target, address_i, size_i, count_i, buffer_i);
2300+
2301+
/* The read of a single word failed, so we will just return 0 for that instead */
2302+
if (result != ERROR_OK) {
2303+
LOG_DEBUG("error reading single word of %d bytes from 0x%" TARGET_PRIxADDR,
2304+
size_i, address_i);
2305+
2306+
uint64_t value_i = 0;
2307+
write_to_buf(buffer_i, value_i, size_i);
2308+
}
2309+
}
2310+
result = ERROR_OK;
2311+
}
2312+
22782313
riscv_set_register(target, GDB_REGNO_S0, s0);
22792314
riscv_set_register(target, GDB_REGNO_S1, s1);
22802315
return result;

0 commit comments

Comments
 (0)