diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index fa07fe821..50535e266 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -2813,6 +2813,14 @@ static unsigned riscv_xlen_nonconst(struct target *target) return riscv_xlen(target); } +static unsigned int riscv_data_bits(struct target *target) +{ + RISCV_INFO(r); + if (r->data_bits) + return r->data_bits(target); + return riscv_xlen(target); +} + struct target_type riscv_target = { .name = "riscv", @@ -2857,6 +2865,7 @@ struct target_type riscv_target = { .commands = riscv_command_handlers, .address_bits = riscv_xlen_nonconst, + .data_bits = riscv_data_bits }; /*** RISC-V Interface ***/ diff --git a/src/target/target.c b/src/target/target.c index 39a07ad6c..63f68ebab 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -1506,6 +1506,13 @@ unsigned target_address_bits(struct target *target) return 32; } +unsigned int target_data_bits(struct target *target) +{ + if (target->type->data_bits) + return target->type->data_bits(target); + return 32; +} + static int target_profiling(struct target *target, uint32_t *samples, uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds) { @@ -2402,10 +2409,13 @@ static int target_write_buffer_default(struct target *target, target_addr_t address, uint32_t count, const uint8_t *buffer) { uint32_t size; + unsigned int data_bytes = target_data_bits(target) / 8; - /* Align up to maximum 4 bytes. The loop condition makes sure the next pass + /* Align up to maximum bytes. The loop condition makes sure the next pass * will have something to do with the size we leave to it. */ - for (size = 1; size < 4 && count >= size * 2 + (address & size); size *= 2) { + for (size = 1; + size < data_bytes && count >= size * 2 + (address & size); + size *= 2) { if (address & size) { int retval = target_write_memory(target, address, size, 1, buffer); if (retval != ERROR_OK) @@ -2463,10 +2473,13 @@ int target_read_buffer(struct target *target, target_addr_t address, uint32_t si static int target_read_buffer_default(struct target *target, target_addr_t address, uint32_t count, uint8_t *buffer) { uint32_t size; + unsigned int data_bytes = target_data_bits(target) / 8; - /* Align up to maximum 4 bytes. The loop condition makes sure the next pass + /* Align up to maximum bytes. The loop condition makes sure the next pass * will have something to do with the size we leave to it. */ - for (size = 1; size < 4 && count >= size * 2 + (address & size); size *= 2) { + for (size = 1; + size < data_bytes && count >= size * 2 + (address & size); + size *= 2) { if (address & size) { int retval = target_read_memory(target, address, size, 1, buffer); if (retval != ERROR_OK) diff --git a/src/target/target.h b/src/target/target.h index d86c63eb0..18a9516f5 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -684,6 +684,13 @@ target_addr_t target_address_max(struct target *target); */ unsigned target_address_bits(struct target *target); +/** + * Return the number of data bits this target supports. + * + * This routine is a wrapper for target->type->data_bits. + */ +unsigned int target_data_bits(struct target *target); + /** Return the *name* of this targets current state */ const char *target_state_name(struct target *target); diff --git a/src/target/target_type.h b/src/target/target_type.h index cc51c0401..cf30cf8cc 100644 --- a/src/target/target_type.h +++ b/src/target/target_type.h @@ -295,6 +295,11 @@ struct target_type { * typically be 32 for 32-bit targets, and 64 for 64-bit targets. If not * implemented, it's assumed to be 32. */ unsigned (*address_bits)(struct target *target); + + /* Return the number of system bus data bits this target supports. This + * will typically be 32 for 32-bit targets, and 64 for 64-bit targets. If + * not implemented, it's assumed to be 32. */ + unsigned int (*data_bits)(struct target *target); }; #endif /* OPENOCD_TARGET_TARGET_TYPE_H */