Skip to content

pyocd load operation failing when smart flash is enabled. #1964

Description

@ash1994-ctrl

Observed on PIC32CK-GC/PIC32CK-SG devices and using pyocd v43.1, pyocd load operation is failing on 2nd load and subsequent load operation. It works when we do complete erase and the load, but fails when try to load again. When smart_flash is disabled , we don't see this behavior, which suggest something wrong with smart_flash algorithem. Below is the partial log from debug statements that I have added in the pyocd source locally.

0002743 I now Loading C:\Users\C76947\FL_Test\PIC32CK_GC_test\out\Project\PIC32CK2051GC01144\Debug\Project.hex [load_cmd]
0002746 W [DEBUG] FlashBuilder.program() called: smart_flash=True, fast_verify=False, chip_erase=sector [builder]
0002747 W [DEBUG] _compute_sector_erase_pages_and_weight: fast_verify=False, crc_supported=False, is_readable=True [builder]
0002747 W [DEBUG] Using partial page read analysis [builder]
0002747 W [DEBUG] _analyze_pages_with_partial_read called, PAGE_ESTIMATE_SIZE=32 [builder]
0002748 D halting core 0 [cortex_m]
0002755 D resuming core 0 [cortex_m]
0002755 D added=[] removed=[] [manager]
0002755 D bps after flush={} [manager]
0002761 W [DEBUG] Partial read: page_addr=0x08000000, read_size=32 [builder]
0002762 W [DEBUG] Partial read result: page_addr=0x08000000, same=True [builder]
0002762 W [DEBUG] flash_data[:16]=['0x0', '0x0', '0x8', '0x20', '0xa5', '0x3', '0x0', '0x8', '0x9d', '0x3', '0x0', '0x8', '0x91', '0x3', '0x0', '0x8'] [builder]
0002762 W [DEBUG] file_data[:16]=['0x0', '0x0', '0x8', '0x20', '0xa5', '0x3', '0x0', '0x8', '0x9d', '0x3', '0x0', '0x8', '0x91', '0x3', '0x0', '0x8'] [builder]
0002762 W [DEBUG] Page 0x08000000 marked as potentially same (needs full verify) [builder]
0002763 D Analyze time: 0.015505 [builder]
0002763 W [DEBUG] _scan_pages_for_same called [builder]
0002763 W [DEBUG] Unknown pages to scan: 1 [builder]
0002763 W [DEBUG] Calling _enable_read_access... [builder]
0002763 W [DEBUG] _enable_read_access completed [builder]
0002763 W [DEBUG] Processing page 0x08000000, cached_estimate_data=True [builder]
0002763 W [DEBUG] Page 0x08000000: page.size=4096, len(page.data)=4096, offset=32, read_len=4064 [builder]
0002763 W [DEBUG] About to read 4064 bytes from 0x08000020... [builder]
0002780 W [DEBUG] Read FAILED: bytearray index out of range [builder]

0002785 W [DEBUG] Full traceback:
Traceback (most recent call last):
File "c:\Users\C76947\pyocd_internal\pyocd\flash\builder.py", line 923, in _scan_pages_for_same
read_data = self.flash.target.read_memory_block8(page.addr + offset, page.size - offset)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "c:\Users\C76947\pyocd_internal\pyocd\core\soc_target.py", line 241, in read_memory_block8
return self.selected_core_or_raise.read_memory_block8(addr, size)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "c:\Users\C76947\pyocd_internal\pyocd\coresight\cortex_m.py", line 636, in read_memory_block8
data = self.ap.read_memory_block8(addr, size)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "c:\Users\C76947\pyocd_internal\pyocd\core\memory_interface.py", line 181, in read_memory_block8
data32 = self.read_memory_block32(addr, size // 4)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "c:\Users\C76947\pyocd_internal\pyocd\utility\concurrency.py", line 29, in _locking
return func(self, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "c:\Users\C76947\pyocd_internal\pyocd\coresight\ap.py", line 1277, in _read_memory_block32
resp += self._read_block32_page(addr, n//4)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "c:\Users\C76947\pyocd_internal\pyocd\coresight\ap.py", line 1235, in _read_block32_page
resp = self.dp.read_ap_multiple(self.address.address + self._reg_offset + MEM_AP_DRW, size)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "c:\Users\C76947\pyocd_internal\pyocd\coresight\dap.py", line 1006, in read_ap_multiple
return read_ap_multiple_cb()
^^^^^^^^^^^^^^^^^^^^^
File "c:\Users\C76947\pyocd_internal\pyocd\coresight\dap.py", line 996, in read_ap_multiple_cb
return result_cb()
^^^^^^^^^^^
File "c:\Users\C76947\pyocd_internal\pyocd\probe\cmsis_dap_probe.py", line 658, in read_ap_repeat_callback
values = result()
^^^^^^^^
File "c:\Users\C76947\pyocd_internal\pyocd\probe\pydapaccess\dap_access_cmsis_dap.py", line 1123, in reg_read_repeat_cb
res = transfer.get_result()
^^^^^^^^^^^^^^^^^^^^^
File "c:\Users\C76947\pyocd_internal\pyocd\probe\pydapaccess\dap_access_cmsis_dap.py", line 161, in get_result
self.daplink.flush()
File "c:\Users\C76947\pyocd_internal\pyocd\utility\concurrency.py", line 29, in _locking
return func(self, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "c:\Users\C76947\pyocd_internal\pyocd\probe\pydapaccess\dap_access_cmsis_dap.py", line 887, in flush
self._read_packet()
File "c:\Users\C76947\pyocd_internal\pyocd\utility\concurrency.py", line 29, in _locking
return func(self, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "c:\Users\C76947\pyocd_internal\pyocd\probe\pydapaccess\dap_access_cmsis_dap.py", line 1168, in _read_packet
decoded_data = cmd.decode_data(raw_data)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "c:\Users\C76947\pyocd_internal\pyocd\probe\pydapaccess\dap_access_cmsis_dap.py", line 484, in decode_data
data = self._decode_transfer_block_data(data)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "c:\Users\C76947\pyocd_internal\pyocd\probe\pydapaccess\dap_access_cmsis_dap.py", line 448, in _decode_transfer_block_data
if data[0] != Command.DAP_TRANSFER_BLOCK:
~~~~^^^
IndexError: bytearray index out of range
[builder]
0002786 D uninit session <pyocd.core.session.Session object at 0x000001A3C5F88310> [session]
0002787 W In uninit [board]
0002787 D uninit board <pyocd.board.board.Board object at 0x000001A3C43C8550> [board]
0002787 W uninit 'True' [board]
0002788 W In disconnect [cortex_m]
0002789 E Probe error during disconnect: [session]

it suggest that in the smart flash, after reading first 32 bytes of the pages , if that matches with what is already programmed on the device , it try to read remaining 4064 bytes and then ends up in error.

Instead of reading 4064 bytes , I modified it to read in smaller chunks of 512 bytes and then it worked. Here is the log
0002052 W [DEBUG] Page 0x08000000: page.size=4096, len(page.data)=4096, offset=32, read_len=4064 [builder]
0002052 W [DEBUG] About to read 4064 bytes from 0x08000020 in 512-byte chunks... [builder]
0002057 W [DEBUG] Read chunk: addr=0x08000020, size=512, got=512 bytes [builder]
0002061 W [DEBUG] Read chunk: addr=0x08000220, size=512, got=512 bytes [builder]
0002065 W [DEBUG] Read chunk: addr=0x08000420, size=512, got=512 bytes [builder]
0002069 W [DEBUG] Read chunk: addr=0x08000620, size=512, got=512 bytes [builder]
0002074 W [DEBUG] Read chunk: addr=0x08000820, size=512, got=512 bytes [builder]
0002079 W [DEBUG] Read chunk: addr=0x08000a20, size=512, got=512 bytes [builder]
0002084 W [DEBUG] Read chunk: addr=0x08000c20, size=512, got=512 bytes [builder]
0002088 W [DEBUG] Read chunk: addr=0x08000e20, size=480, got=480 bytes [builder]
0002088 W [DEBUG] Read completed, total 4096 bytes [builder]
0002088 W [DEBUG] Page 0x08000000: same=True, page_data_len=4096, read_data_len=4096 [builder]
[==================================================] 100%

Without this change and smart flash enabled, we get "IndexError: bytearray index out of range". So we always have to include smart_flash disable argument to get it working. I did not see this behavior on older pyocd version(v38.0).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions