diff options
author | Tomas Vanek <vanekt@fbl.cz> | 2018-01-10 15:17:14 +0100 |
---|---|---|
committer | Tomas Vanek <vanekt@fbl.cz> | 2018-01-11 08:28:29 +0000 |
commit | 779e95cc326e77f628d5feb7d72a064ffedfd820 (patch) | |
tree | 4fd8110cf013dd3dede4b4754f2ef7ba92b07846 | |
parent | 6f5e9941df0f92eac5fa955cc96221da907451b1 (diff) |
arm_adi_v5: fix regression from 4553abf9064fe3c0e4ea2ed29a1d2217df74ff5f
Functions mem_ap_read() and mem_ap_write() incremented address even
if addrinc=false. I overlooked this fact and moved mem_ap_setup_tar()
set wrong addresses in no-incr mode.
Fixed by preventing address increment in no-incr mode.
Change-Id: I512e12a6a64e30cf6bc5bf77e3d57d35cc33e058
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Suggested-by: Matthias Welwarsky <matthias@welwarsky.de>
Reviewed-on: http://openocd.zylin.com/4326
Tested-by: jenkins
Reviewed-by: Christopher Head <chead@zaber.com>
Reviewed-by: Andreas Fritiofson <andreas.fritiofson@gmail.com>
-rw-r--r-- | src/target/arm_adi_v5.c | 28 |
1 files changed, 16 insertions, 12 deletions
diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index ae6c2c62..1ca8e4f0 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -378,33 +378,34 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz /* How many source bytes each transfer will consume, and their location in the DRW, * depends on the type of transfer and alignment. See ARM document IHI0031C. */ uint32_t outvalue = 0; + uint32_t drw_byte_idx = address; if (dap->ti_be_32_quirks) { switch (this_size) { case 4: - outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (address++ & 3) ^ addr_xor); - outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (address++ & 3) ^ addr_xor); - outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (address++ & 3) ^ addr_xor); - outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (address++ & 3) ^ addr_xor); + outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (drw_byte_idx++ & 3) ^ addr_xor); + outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (drw_byte_idx++ & 3) ^ addr_xor); + outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (drw_byte_idx++ & 3) ^ addr_xor); + outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (drw_byte_idx & 3) ^ addr_xor); break; case 2: - outvalue |= (uint32_t)*buffer++ << 8 * (1 ^ (address++ & 3) ^ addr_xor); - outvalue |= (uint32_t)*buffer++ << 8 * (1 ^ (address++ & 3) ^ addr_xor); + outvalue |= (uint32_t)*buffer++ << 8 * (1 ^ (drw_byte_idx++ & 3) ^ addr_xor); + outvalue |= (uint32_t)*buffer++ << 8 * (1 ^ (drw_byte_idx & 3) ^ addr_xor); break; case 1: - outvalue |= (uint32_t)*buffer++ << 8 * (0 ^ (address++ & 3) ^ addr_xor); + outvalue |= (uint32_t)*buffer++ << 8 * (0 ^ (drw_byte_idx & 3) ^ addr_xor); break; } } else { switch (this_size) { case 4: - outvalue |= (uint32_t)*buffer++ << 8 * (address++ & 3); - outvalue |= (uint32_t)*buffer++ << 8 * (address++ & 3); + outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx++ & 3); + outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx++ & 3); /* fallthrough */ case 2: - outvalue |= (uint32_t)*buffer++ << 8 * (address++ & 3); + outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx++ & 3); /* fallthrough */ case 1: - outvalue |= (uint32_t)*buffer++ << 8 * (address++ & 3); + outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx & 3); } } @@ -415,6 +416,8 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz break; mem_ap_update_tar_cache(ap); + if (addrinc) + address += this_size; } /* REVISIT: Might want to have a queued version of this function that does not run. */ @@ -509,7 +512,8 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint break; nbytes -= this_size; - address += this_size; + if (addrinc) + address += this_size; mem_ap_update_tar_cache(ap); } |