target/riscv: fix progbuf memory writes in case last write is busy

Restarting the program buffer memory write pipeline when the write of
the last element resulted in the busy response triggers an extra memory
wrtite, that is cought by an assertion:
```
src/target/riscv/riscv-013.c:5048: write_memory_progbuf_inner: Assertion
`next_addr_on_target - args.address <= (target_addr_t)args.size *
args.count' failed.
```

Change-Id: I0f27145cad24686cf539aebfea7f6578b7cd78ab
Signed-off-by: Evgeniy Naydanov <evgeniy.naydanov@syntacore.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/9233
Tested-by: jenkins
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
This commit is contained in:
Evgeniy Naydanov
2025-10-28 17:16:55 +03:00
committed by Tomas Vanek
parent d7fb95d800
commit 4e78563a00

View File

@@ -4875,7 +4875,8 @@ static int write_memory_progbuf_teardown(struct target *target)
* failed write.
*/
static int write_memory_progbuf_handle_busy(struct target *target,
target_addr_t *address_p, uint32_t size, const uint8_t *buffer)
target_addr_t *address_p, target_addr_t end_address, uint32_t size,
const uint8_t *buffer)
{
int res = riscv013_clear_abstract_error(target);
if (res != ERROR_OK)
@@ -4891,8 +4892,12 @@ static int write_memory_progbuf_handle_busy(struct target *target,
if (register_read_direct(target, &address_on_target, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL;
const uint8_t * const curr_buff = buffer + (address_on_target - *address_p);
LOG_TARGET_DEBUG(target, "Restarting from 0x%" TARGET_PRIxADDR, *address_p);
*address_p = address_on_target;
if (*address_p == end_address) {
LOG_TARGET_DEBUG(target, "Got busy while reading after reading the last element");
return ERROR_OK;
}
LOG_TARGET_DEBUG(target, "Restarting from 0x%" TARGET_PRIxADDR, *address_p);
/* This restores the pipeline and ensures one item gets reliably written */
return write_memory_progbuf_startup(target, address_p, curr_buff, size);
}
@@ -4970,7 +4975,8 @@ static int write_memory_progbuf_run_batch(struct target *target, struct riscv_ba
/* TODO: If dmi busy is encountered, the address of the last
* successful write can be deduced by analysing the batch.
*/
return write_memory_progbuf_handle_busy(target, address_p, size, buffer);
return write_memory_progbuf_handle_busy(target, address_p, end_address,
size, buffer);
}
LOG_TARGET_ERROR(target, "Error when writing memory, abstractcs=0x%" PRIx32,
abstractcs);