Skip to content

Commit c2642ac

Browse files
committed
Read memory words individually if burst read fails
1 parent b590802 commit c2642ac

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
@@ -2021,53 +2021,13 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
20212021
* Read the requested memory, taking care to execute every read exactly once,
20222022
* even if cmderr=busy is encountered.
20232023
*/
2024-
static int read_memory_progbuf(struct target *target, target_addr_t address,
2024+
static int read_memory_progbuf_inner(struct target *target, target_addr_t address,
20252025
uint32_t size, uint32_t count, uint8_t *buffer)
20262026
{
20272027
RISCV013_INFO(info);
20282028

20292029
int result = ERROR_OK;
20302030

2031-
LOG_DEBUG("reading %d words of %d bytes from 0x%" TARGET_PRIxADDR, count,
2032-
size, address);
2033-
2034-
select_dmi(target);
2035-
2036-
/* s0 holds the next address to write to
2037-
* s1 holds the next data value to write
2038-
*/
2039-
uint64_t s0, s1;
2040-
if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK)
2041-
return ERROR_FAIL;
2042-
if (register_read(target, &s1, GDB_REGNO_S1) != ERROR_OK)
2043-
return ERROR_FAIL;
2044-
2045-
if (execute_fence(target) != ERROR_OK)
2046-
return ERROR_FAIL;
2047-
2048-
/* Write the program (load, increment) */
2049-
struct riscv_program program;
2050-
riscv_program_init(&program, target);
2051-
switch (size) {
2052-
case 1:
2053-
riscv_program_lbr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0);
2054-
break;
2055-
case 2:
2056-
riscv_program_lhr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0);
2057-
break;
2058-
case 4:
2059-
riscv_program_lwr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0);
2060-
break;
2061-
default:
2062-
LOG_ERROR("Unsupported size: %d", size);
2063-
return ERROR_FAIL;
2064-
}
2065-
riscv_program_addi(&program, GDB_REGNO_S0, GDB_REGNO_S0, size);
2066-
2067-
if (riscv_program_ebreak(&program) != ERROR_OK)
2068-
return ERROR_FAIL;
2069-
riscv_program_write(&program);
2070-
20712031
/* Write address to S0, and execute buffer. */
20722032
result = register_write_direct(target, GDB_REGNO_S0, address);
20732033
if (result != ERROR_OK)
@@ -2195,7 +2155,7 @@ static int read_memory_progbuf(struct target *target, target_addr_t address,
21952155
1 << DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET);
21962156
break;
21972157
default:
2198-
LOG_ERROR("error when reading memory, abstractcs=0x%08lx", (long)abstractcs);
2158+
LOG_DEBUG("error when reading memory, abstractcs=0x%08lx", (long)abstractcs);
21992159
riscv013_clear_abstract_error(target);
22002160
riscv_batch_free(batch);
22012161
result = ERROR_FAIL;
@@ -2253,13 +2213,88 @@ static int read_memory_progbuf(struct target *target, target_addr_t address,
22532213
write_to_buf(buffer + receive_addr - address, value, size);
22542214
log_memory_access(receive_addr, value, size, true);
22552215

2256-
riscv_set_register(target, GDB_REGNO_S0, s0);
2257-
riscv_set_register(target, GDB_REGNO_S1, s1);
22582216
return ERROR_OK;
22592217

22602218
error:
22612219
dmi_write(target, DMI_ABSTRACTAUTO, 0);
22622220

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

0 commit comments

Comments
 (0)