pyocd / pyOCD

Open source Python library for programming and debugging Arm Cortex-M microcontrollers
https://pyocd.io
Apache License 2.0
1.13k stars 484 forks source link

Error with simultaneous GDB and SWV on CMSIS-DAP probe #855

Closed adamgreig closed 4 years ago

adamgreig commented 4 years ago

Hi! I'm having a somewhat confusing problem with SWV and GDB and I can't tell how pyOCD is meant to resolve this issue, so I'd welcome any guidance. The summary is that CMSIS-DAP probe responses to the regular poll for SWO data by the SWVReader thread (DAP_SWO_Data commands) are being received by the transfer thread (expecting DAP_Transfer responses), or vice versa, so either way an error is thrown, which means I can't use GDB while SWV is active.

I'm using a custom CMSIS-DAP probe, so I worry an implementation issue is causing the fault, but I don't understand how it could be mitigated. My probe implements both v1 and v2 endpoints but does not support SWO streaming on its own endpoint, so all responses are via DAP_SWO_Data command polling. The issue is the same when using either v1 or v2 backends. I don't have access to another CMSIS-DAP probe that also has SWO, and I can't see anything obvious to deal with this in the DAPlink firmware.

I'm using SWV via pyocd gdbserver -O enable_swv=true -O connect_mode=attach on a target that's constantly streaming some ITM data via SWO. There's a very low data rate, maybe 50 bytes/second. After starting pyocd I can telnet to port 4444 and view the correct ITM data, no problems there. I use connect_mode=attach as otherwise the target is halted at this stage which prevents ITM output. At this point the SWVReader thread is constantly calling swo_read(), which sends new DAP_SWO_Data commands and receives responses.

If I then try and attach a GDB session to port 3333, pyOCD sends some DAP_Transfer commands in a separate Python thread. That thread then reads the same USB endpoint as the SWVReader is using, and pretty quickly either it receives a response to the DAP_SWO_Data command, or the SWVReader thread receives a response to the DAP_Transfer command. Either way this immediately causes an error. As far as I can tell there's no locking or synchronisation in pyOCD to prevent this, and from looking at the USB logs and also inserting extra logging into pyOCD, the probe appears to correctly responding in-order.

Has anyone got SWV working at the same time as GDB using a CMSIS-DAP probe without the separate SWO endpoint? Am I missing something obvious? Thanks!

Here's a log snippet with extra logging added to pyusb_backend.py to print out transmitted and received buffers:

Note: `TX [28, ...]` is a poll for DAP_SWO_Data, `RX [28, ...]` is the response. `TX [5, ...]` is a DAP_Transfer command. The trace shows a `DAP_SWO_Data` poll and response, a second poll, then before the response is received there's a `DAP_Transfer` request, which then receives the `DAP_SWO_Data` response. ``` 0005938:DEBUG:pyusb_backend:TX [28, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0] 0005940:DEBUG:gdbserver:GDB received query: [b'Xfer', b'features', b'read', b'target.xml', b'0,7fb#4a'] 0005940:DEBUG:gdbserver:GDB query b'read_feature': offset: 0, size: 2043 0005942:DEBUG:pyusb_backend:RX array('B', [28, 1, 0, 0]) 0005942:DEBUG:cmsis_dap_core:swo_data: got array('B', [28, 1, 0, 0]) 0005942:DEBUG:gdbserver:GDB received query: [b'Xfer', b'features', b'read', b'target.xml', b'7fb,7fb#19'] 0005942:DEBUG:gdbserver:GDB query b'read_feature': offset: 2043, size: 2043 0005943:DEBUG:pyusb_backend:TX [28, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0] 0005943:DEBUG:gdbserver:GDB general set: b'NonStop:0' 0005943:DEBUG:gdbserver:GDB received query: [b'TStatus#49'] 0005944:DEBUG:gdbserver:Current thread 0 is no longer valid, switching context to target 0005944:DEBUG:pyusb_backend:TX [5, 0, 8, 5, 240, 0, 4, 224, 13, 2, 0, 0, 0, 5, 4, 3, 4, 224, 13, 0, 0, 0, 0, 5, 16, 0, 4, 224, 13, 15, 0, 0, 0, 5, 48, 237, 0, 224, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 0005945:DEBUG:pyusb_backend:RX array('B', [28, 1, 4, 0, 192, 255, 136, 122]) 0005945:DEBUG:dap_access_cmsis_dap:_decode_transfer_data: got bytearray(b'\x1c\x01\x04\x00\xc0\xff\x88z') 0005945:ERROR:gdbserver:Unhandled exception in handle_message: DAP_TRANSFER response error ```
flit commented 4 years ago

Should be fixed now! (Terribly sorry I missed this issue back when you submitted it.)