Skip to content

Commit 31df059

Browse files
fkjagodzinskiflit
authored andcommitted
probe: stlink: Fix 1-byte transfers (#1476)
Internally the 1-byte transfers are handled in 3 phases: 1. read/write 8-bit chunks until the first aligned address is reached, 2. read/write 32-bit chunks from all aligned addresses, 3. read/write 8-bit chunks from the remaining unaligned addresses. Size of the first unaligned read/write is set to the result of address alignment check (4-byte) and can be either 1, 2, or 3 bytes (the value of `unaligned_count` calculated as `addr & 0x3`). This is incorrect and every transfer with the requested size smaller than `unaligned_count` is terminated with the following error: Unhandled exception in handle_message (b'm'): result size (3) != requested size (1) [gdbserver] Skip the first unaligned transfer if the requested size is so small that phase-1 would not even reach aligned address. Handle the whole request in the second unaligned read/write (phase-3).
1 parent 2cb49b6 commit 31df059

File tree

1 file changed

+15
-8
lines changed

1 file changed

+15
-8
lines changed

pyocd/probe/stlink_probe.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# pyOCD debugger
2-
# Copyright (c) 2018-2020 Arm Limited
2+
# Copyright (c) 2018-2020,2022 Arm Limited
33
# Copyright (c) 2021-2022 Chris Reed
44
# SPDX-License-Identifier: Apache-2.0
55
#
@@ -305,21 +305,28 @@ def read_memory_block8(self, addr: int, size: int, **attrs: Any) -> Sequence[int
305305
csw = attrs.get('csw', 0)
306306
res = []
307307

308-
# read leading unaligned bytes
309-
unaligned_count = addr & 3
310-
if (size > 0) and (unaligned_count > 0):
308+
# Transfers are handled in 3 phases:
309+
# 1. read 8-bit chunks until the first aligned address is reached,
310+
# 2. read 32-bit chunks from all aligned addresses,
311+
# 3. read 8-bit chunks from the remaining unaligned addresses.
312+
# If the requested size is so small that phase-1 would not even reach
313+
# aligned address, go straight to phase-3.
314+
315+
# 1. read leading unaligned bytes
316+
unaligned_count = 3 & (4 - addr)
317+
if (size > unaligned_count > 0):
311318
res += self._link.read_mem8(addr, unaligned_count, self._apsel, csw)
312319
size -= unaligned_count
313320
addr += unaligned_count
314321

315-
# read aligned block of 32 bits
322+
# 2. read aligned block of 32 bits
316323
if (size >= 4):
317324
aligned_size = size & ~3
318325
res += self._link.read_mem32(addr, aligned_size, self._apsel, csw)
319326
size -= aligned_size
320327
addr += aligned_size
321328

322-
# read trailing unaligned bytes
329+
# 3. read trailing unaligned bytes
323330
if (size > 0):
324331
res += self._link.read_mem8(addr, size, self._apsel, csw)
325332

@@ -332,8 +339,8 @@ def write_memory_block8(self, addr: int, data: Sequence[int], **attrs: Any) -> N
332339
idx = 0
333340

334341
# write leading unaligned bytes
335-
unaligned_count = addr & 3
336-
if (size > 0) and (unaligned_count > 0):
342+
unaligned_count = 3 & (4 - addr)
343+
if (size > unaligned_count > 0):
337344
self._link.write_mem8(addr, data[:unaligned_count], self._apsel, csw)
338345
size -= unaligned_count
339346
addr += unaligned_count

0 commit comments

Comments
 (0)