Marus / cortex-debug

Visual Studio Code extension for enhancing debug capabilities for Cortex-M Microcontrollers
MIT License
984 stars 238 forks source link

`rtt_start_retry` doesn't seem to work #714

Closed werediver closed 2 years ago

werediver commented 2 years ago

I switched to v1.5.5 (pre-release) in hope rtt_start_retry option can help with enabling RTT via OpenOCD automatically (stopping after RTT initialization and manually issuing monitor rtt start works), but it doesn't seem to have any effect.

I understand this is an unstable feature, so just providing feedback.

haneefdm commented 2 years ago

Thank you for trying it out. I had a 70% shot at it so I took it. Could you give me some details of what device and which openocd (xpack, from ST, etc.) There are so many versions of custom openocds so I want to have some idea.

I can create some logging data so we can debug in your setup why it is not working. But first, I will try to duplicate it myself with the info above.

werediver commented 2 years ago

I was trying to set up RTT for Rasperry Pi Pico / RP2040 target using another Pico with raspberrypi/picoprobe as a debugger. The picoprobe, unfortunately, is not a CMSIS-DAP compatible debugger and requires a custom raspberrypi/openocd build.

If I stop the firmware after RTT initialization and manually issue monitor rtt start command, RTT is attached and the plug-in works as expected. Without doing this manual maneuver, though, RTT doesn't get attached, as OpenOCD is searching for a control block before the target is initialized.

I understand it's more of an OpenOCD issue, so today I tried switching to ciniml/rust-dap (a CMSIS-DAP compliant debugger running on Pico) and pyocd/pyOCD. pyOCD supports RTT (via pyocd rtt terminal command), but monitor rtt start doesn't work with it (https://github.com/pyocd/pyOCD/issues/1439):

60-interpreter-exec console "monitor rtt start"
-> @"Error: unrecognized command 'rtt'\n"
Error: unrecognized command 'rtt'
-> 60^done

Again, this is an issue with pyOCD and not the plug-in, unless we start talking about custom pyOCD RTT support, but that would be a topic for a separate ticket.

I could use a CMSIS-DAP debugger with the vanilla OpenOCD too, but I assume the vanilla OpenOCD has the same issue with RTT initialization.

haneefdm commented 2 years ago

Glad pyocd now supports RTT but support for it is not in Cortex-Debug as there were no requests and not sure how that one works. Only (latest?) OpenOCD or JLink for now.

There is no standardization on what monitor (aka. gdb-server) commands a given gdb-server supports. Anything after the word monitor is sent to the gdb-server to act on. Syntax/methods/command-set are different. In OpenOCD, it might be rtt start but in pyOCD, it can be something totally different.

Also, CMSIS-DAP may not be related. All that needs to work is SWD and a gdb-server providing the additional service for RTT.

werediver commented 2 years ago

Also, CMSIS-DAP may not be related. All that needs to work is SWD and a gdb-server providing the additional service for RTT.

Sure, the difference CMSIS-DAP makes is with a CMSIS-DAP compliant debugger the vanilla upstream OpenOCD can be used, no outdated custom builds.

I should try a Pico with a CMSIS-DAP compliant firmware and the vanilla upstream OpenOCD.

Another possible combination is a CMSIS-DAP debugger with Black Magic Debug App. I'm inclined to try the latter first, especially given that I should receive BMP v2.3a soon.

In the meantime, I've opened https://github.com/pyocd/pyOCD/issues/1439 to check on pyOCD monitor rtt support.

haneefdm commented 2 years ago

RTT is very custom and unrelated to CMSIS-DAP. RTT is a layer above basic SWD. Not many gdb-servers support it. Until recently OpenOCD didn't. Only SEGGER, the creators of RTT did it with JLink and it had nothing to do with CMSIS. RTT even works with non ARM processors.

haneefdm commented 2 years ago

Servers like JLink/openocd/pyocd need to know about RTT, its protocol and open TCP ports for clients to communicate with. Unrelated to CMSIS. JLink for instance only opens one port for one channel. But OpenOCD can open multiple TCP ports -- one per each channel.

werediver commented 2 years ago

You're right on everything and know more details on the debugging protocols and software than I do, but my point still holds:

Don't you agree CMSIS-DAP does make a difference? Even if unrelated directly to RTT.

haneefdm commented 2 years ago

I have not seen pyOCD's RTT implementation. Your issue over there may be misplaced. JLink for instance does not even need monitor rtt start and nor does it have such a command. pyOCD implemented RTT very recently and I have not had a chance to look at it so chances of it working are near zero with our extension. And nothing to do with CMSIS -- JLink who invented this proves that you do not need CMSIS.

Anyway. If you want to work with me we can make this work with your setup.

werediver commented 2 years ago

I tried some more combinations here, but in the end I'm still interested in making RTT retry logic (rtt_start_retry) work with OpenOCD. I'd appreciate your help.

From what I see in the log, the retry doesn't seem to ever happen (rtt_start_retry is 1000), only the initial attempt. Below is the log filtered by "rtt":

23-interpreter-exec console "monitor rtt setup 0x2003fba0 10 {SEGGER RTT}"
24-interpreter-exec console "monitor rtt server start 60001 0"
-> @"Listening on port 60001 for rtt connections\n"
Listening on port 60001 for rtt connections
25-interpreter-exec console "monitor rtt start"
-> @"rtt: Searching for control block 'SEGGER RTT'\n"
rtt: Searching for control block 'SEGGER RTT'
-> @"rtt: No control block found\n"
rtt: No control block found
Full log ``` Cortex-Debug: VSCode debugger extension version 1.5.5 git(e98ea06). Usaage info: https://github.com/Marus/cortex-debug#usage Reading symbols from arm-none-eabi-objdump --syms -C -h -w /Users/ramanf/Dropbox/Projects/escale/escale_fw_rs/target/thumbv6m-none-eabi/debug/escale Reading symbols from arm-none-eabi-nm --defined-only -S -l -C -p /Users/ramanf/Dropbox/Projects/escale/escale_fw_rs/target/thumbv6m-none-eabi/debug/escale Launching GDB: arm-none-eabi-gdb -q --interpreter=mi2 1-gdb-version Launching gdb-server: openocd -c "gdb_port 50000" -c "tcl_port 50001" -c "telnet_port 50002" -s /Users/ramanf/Dropbox/Projects/escale/escale_fw_rs -f /Users/ramanf/.vscode/extensions/marus25.cortex-debug-1.5.5/support/openocd-helpers.tcl -f interface/cmsis-dap.cfg -f target/rp2040-custom.cfg Please check TERMINAL tab (gdb-server) for output from openocd Finished reading symbols from objdump: Time: 14 ms -> =thread-group-added,id="i1" -> ~"GNU gdb (GDB) 11.2\n" -> ~"Copyright (C) 2022 Free Software Foundation, Inc.\n" -> ~"License GPLv3+: GNU GPL version 3 or later \nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law." -> ~"\nType \"show copying\" and \"show warranty\" for details.\n" -> ~"This GDB was configured as \"--host=aarch64-apple-darwin21.5.0 --target=arm-none-eabi\".\n" -> ~"Type \"show configuration\" for configuration details.\n" -> ~"For bug reporting instructions, please see:\n" -> ~".\n" -> ~"Find the GDB manual and other documentation resources online at:\n ." -> ~"\n\n" -> ~"For help, type \"help\".\n" -> ~"Type \"apropos word\" to search for commands related to \"word\".\n" -> 1^done GNU gdb (GDB) 11.2 Copyright (C) 2022 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "--host=aarch64-apple-darwin21.5.0 --target=arm-none-eabi". Type "show configuration" for configuration details. For bug reporting instructions, please see: . Find the GDB manual and other documentation resources online at: . For help, type "help". Type "apropos word" to search for commands related to "word". 2-gdb-set mi-async on -> 2^done 3-interpreter-exec console "set print demangle on" -> 3^done 4-interpreter-exec console "set print asm-demangle on" -> =cmd-param-changed,param="print asm-demangle",value="on" -> 4^done 5-enable-pretty-printing -> 5^done 6-interpreter-exec console "source /Users/ramanf/.vscode/extensions/marus25.cortex-debug-1.5.5/support/gdbsupport.init" -> 6^done 7-interpreter-exec console "source /Users/ramanf/.vscode/extensions/marus25.cortex-debug-1.5.5/support/gdb-swo.init" -> =cmd-param-changed,param="language",value="c" -> =cmd-param-changed,param="language",value="auto" -> 7^done 8-file-exec-and-symbols "/Users/ramanf/Dropbox/Projects/escale/escale_fw_rs/target/thumbv6m-none-eabi/debug/escale" Finished reading symbols from nm: Time: 224 ms -> 8^done 9-interpreter-exec console "set output-radix 0x10" -> ~"Output radix now set to decimal 16, hex 10, octal 20.\n" Output radix now set to decimal 16, hex 10, octal 20. -> =cmd-param-changed,param="output-radix",value="16" -> 9^done 10-interpreter-exec console "set input-radix 0xa" -> ~"Input radix now set to decimal 10, hex a, octal 12.\n" Input radix now set to decimal 10, hex a, octal 12. -> 10^done 11-target-select extended-remote localhost:50000 -> =thread-group-started,id="i1",pid="42000" -> =thread-created,id="1",group-id="i1" -> =thread-created,id="2",group-id="i1" -> &"warning: multi-threaded target stopped without sending a thread-id, using first non-exited thread\n" warning: multi-threaded target stopped without sending a thread-id, using first non-exited thread -> ~"0x10001aa8 in rp2040_hal::i2c::I2C>, rp2040_hal::gpio::pin::Pin>), rp2040_hal::i2c::Controller>::write_internal>, rp2040_hal::gpio::pin::Pin>)> (bytes=..., do_stop=0x1, self=) at /Users/ramanf/.cargo/registry/src/github.com-1ecc6299db9ec823/rp2040-hal-0.5.0/src/i2c/controller.rs:219\n" 0x10001aa8 in rp2040_hal::i2c::I2C>, rp2040_hal::gpio::pin::Pin>), rp2040_hal::i2c::Controller>::write_internal>, rp2040_hal::gpio::pin::Pin>)> (bytes=..., do_stop=0x1, self=) at /Users/ramanf/.cargo/registry/src/github.com-1ecc6299db9ec823/rp2040-hal-0.5.0/src/i2c/controller.rs:219 -> ~"219\t while self.i2c.ic_raw_intr_stat.read().tx_empty().is_inactive() {}\n" 219 while self.i2c.ic_raw_intr_stat.read().tx_empty().is_inactive() {} -> *stopped,frame={addr="0x10001aa8",func="rp2040_hal::i2c::I2C>, rp2040_hal::gpio::pin::Pin>), rp2040_hal::i2c::Controller>::write_internal>, rp2040_hal::gpio::pin::Pin>)>",args=[{name="bytes",value="..."},{name="do_stop",value="0x1"},{name="self",value=""}],file="/Users/ramanf/.cargo/registry/src/github.com-1ecc6299db9ec823/rp2040-hal-0.5.0/src/i2c/controller.rs",fullname="/Users/ramanf/.cargo/registry/src/github.com-1ecc6299db9ec823/rp2040-hal-0.5.0/src/i2c/controller.rs",line="219",arch="armv6s-m"},thread-id="1",stopped-threads="all" mi2.status = stopped Program stopped, probably due to a reset and/or halt issued by debugger -> 11^connected 12-interpreter-exec console "monitor reset halt" -> @"target halted due to debug-request, current mode: Thread \n" target halted due to debug-request, current mode: Thread -> @"xPSR: 0xf1000000 pc: 0x000000ee msp: 0x20041f00\n" xPSR: 0xf1000000 pc: 0x000000ee msp: 0x20041f00 -> @"target halted due to debug-request, current mode: Thread \n" target halted due to debug-request, current mode: Thread -> @"xPSR: 0xf1000000 pc: 0x000000ee msp: 0x20041f00\n" xPSR: 0xf1000000 pc: 0x000000ee msp: 0x20041f00 -> 12^done 13-target-download -> 13+download,{section=".boot2",section-size="256",total-size="3450130"} -> 13+download,{section=".boot2",section-sent="256",section-size="256",total-sent="256",total-size="3450130"} -> 13+download,{section=".vector_table",section-size="168",total-size="3450130"} -> 13+download,{section=".text",section-size="60740",total-size="3450130"} -> 13+download,{section=".rodata",section-size="18800",total-size="3450130"} -> 13+download,{section=".data",section-size="80",total-size="3450130"} -> 13^done,address="0x100001a8",load-size="80044",transfer-rate="421832",write-rate="8893" 14-interpreter-exec console "monitor reset halt" -> @"target halted due to debug-request, current mode: Thread \n" target halted due to debug-request, current mode: Thread -> @"xPSR: 0xf1000000 pc: 0x000000ee msp: 0x20041f00\n" xPSR: 0xf1000000 pc: 0x000000ee msp: 0x20041f00 -> @"target halted due to debug-request, current mode: Thread \n" target halted due to debug-request, current mode: Thread -> @"xPSR: 0xf1000000 pc: 0x000000ee msp: 0x20041f00\n" xPSR: 0xf1000000 pc: 0x000000ee msp: 0x20041f00 -> 14^done openocd <- 1-tcl_notifications on openocd -> 1-'' Created RTT terminal for channel 0 on tcp port 60001 15-break-insert "/Users/ramanf/Dropbox/Projects/escale/escale_fw_rs/app/src/main.rs:109" -> ~"Note: automatically using hardware breakpoints for read-only addresses.\n" Note: automatically using hardware breakpoints for read-only addresses. -> 15^done,bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="0x100027a6",func="escale::__cortex_m_rt__main",file="app/src/main.rs",fullname="/Users/ramanf/Dropbox/Projects/escale/escale_fw_rs/app/src/main.rs",line="109",thread-groups=["i1"],times="0",original-location="/Users/ramanf/Dropbox/Projects/escale/escale_fw_rs/app/src/main.rs:109"} Returning dummy thread-id to workaround VSCode issue with pause button not working 16-data-list-register-names -> 16^done,register-names=["r0","r1","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12","sp","lr","pc","","","","","","","","","","xPSR","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","msp","psp","primask","basepri","faultmask","control"] Returning dummy stack frame to workaround VSCode issue with pause button not working: {"threadId":1,"startFrame":0,"levels":20} 17-interpreter-exec console "monitor mwb 0x2003fba0 0 10" -> 17^done 18-interpreter-exec console "set output-radix 0xa" -> ~"Output radix now set to decimal 10, hex a, octal 12.\n" -> =cmd-param-changed,param="output-radix",value="10" -> 18^done 19-interpreter-exec console "set input-radix 0xa" -> ~"Input radix now set to decimal 10, hex a, octal 12.\n" -> 19^done 20-data-list-register-values N -> 20^done,register-values=[{number="0",value="1074020404"},{number="1",value="1280"},{number="2",value="536999941"},{number="3",value="2"},{number="4",value="512"},{number="5",value="1"},{number="6",value="0"},{number="7",value="536999964"},{number="8",value="-1"},{number="9",value="-1"},{number="10",value="-1"},{number="11",value="-1"},{number="12",value="536999941"},{number="13",value="0x2001f7e4"},{number="14",value="268442205"},{number="15",value="0x100001a8 "},{number="25",value="1090519040"},{number="91",value="0x20041f00"},{number="92",value="0xfffffffc"},{number="93",value="0"},{number="94",value="0"},{number="95",value="0"},{number="96",value="0"}] 21-interpreter-exec console "set output-radix 0x10" -> ~"Output radix now set to decimal 16, hex 10, octal 20.\n" -> =cmd-param-changed,param="output-radix",value="16" -> 21^done 22-interpreter-exec console "set input-radix 0xa" -> ~"Input radix now set to decimal 10, hex a, octal 12.\n" -> 22^done 23-interpreter-exec console "monitor rtt setup 0x2003fba0 10 {SEGGER RTT}" -> 23^done 24-interpreter-exec console "monitor rtt server start 60001 0" -> @"Listening on port 60001 for rtt connections\n" Listening on port 60001 for rtt connections -> 24^done 25-interpreter-exec console "monitor rtt start" -> @"rtt: Searching for control block 'SEGGER RTT'\n" rtt: Searching for control block 'SEGGER RTT' -> @"rtt: No control block found\n" rtt: No control block found -> 25^done 26-exec-continue --all -> 26^running -> *running,thread-id="all" mi2.status = running openocd -> 'type target_event event resume-start' openocd -> 'type target_event event resumed' openocd -> 'type target_state state running' openocd -> 'type target_event event resume-end' openocd -> 'type target_event event gdb-start' openocd -> 'type target_event event gdb-halt' openocd -> 'type target_state state halted' openocd -> 'type target_event event halted' openocd -> 'type target_event event gdb-halt' openocd -> 'type target_event event gdb-end' openocd -> 'type target_event event halted' -> @"target halted due to debug-request, current mode: Thread \n" target halted due to debug-request, current mode: Thread -> @"xPSR: 0x01000000 pc: 0x0000012a msp: 0x20041f00\n" xPSR: 0x01000000 pc: 0x0000012a msp: 0x20041f00 -> =breakpoint-modified,bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="0x100027a6",func="escale::__cortex_m_rt__main",file="app/src/main.rs",fullname="/Users/ramanf/Dropbox/Projects/escale/escale_fw_rs/app/src/main.rs",line="109",thread-groups=["i1"],times="1",original-location="/Users/ramanf/Dropbox/Projects/escale/escale_fw_rs/app/src/main.rs:109"} -> ~"\n" -> ~"Thread 1 hit Breakpoint 1, escale::__cortex_m_rt__main () at app/src/main.rs:109\n" Thread 1 hit Breakpoint 1, escale::__cortex_m_rt__main () at app/src/main.rs:109 -> ~"109\t rprintln!(\"Starting...\");\n" 109 rprintln!("Starting..."); -> *stopped,reason="breakpoint-hit",disp="keep",bkptno="1",frame={addr="0x100027a6",func="escale::__cortex_m_rt__main",args=[],file="app/src/main.rs",fullname="/Users/ramanf/Dropbox/Projects/escale/escale_fw_rs/app/src/main.rs",line="109",arch="armv6s-m"},thread-id="1",stopped-threads="all" mi2.status = stopped 27-thread-list-ids -> 27^done,thread-ids={thread-id="1",thread-id="2"},current-thread-id="1",number-of-threads="2" 28-thread-info 1 -> 28^done,threads=[{id="1",target-id="Thread 1",details="Name: rp2040.core0, state: breakpoint",frame={level="0",addr="0x100027a6",func="escale::__cortex_m_rt__main",args=[],file="app/src/main.rs",fullname="/Users/ramanf/Dropbox/Projects/escale/escale_fw_rs/app/src/main.rs",line="109",arch="armv6s-m"},state="stopped"}] 29-thread-info 2 -> 29^done,threads=[{id="2",target-id="Thread 2",details="Name: rp2040.core1, state: debug-request",frame={level="0",addr="0x0000012a",func="??",args=[],arch="armv6s-m"},state="stopped"}] 30-interpreter-exec console "set output-radix 0xa" -> ~"Output radix now set to decimal 10, hex a, octal 12.\n" -> =cmd-param-changed,param="output-radix",value="10" -> 30^done 31-interpreter-exec console "set input-radix 0xa" -> ~"Input radix now set to decimal 10, hex a, octal 12.\n" -> 31^done 32-data-list-register-values N -> 32^done,register-values=[{number="0",value="268505828"},{number="1",value="1377849925"},{number="2",value="21588"},{number="3",value="83"},{number="4",value="0"},{number="5",value="1"},{number="6",value="537131960"},{number="7",value="537000764"},{number="8",value="-1"},{number="9",value="-1"},{number="10",value="-1"},{number="11",value="-1"},{number="12",value="537131936"},{number="13",value="0x2001fa24"},{number="14",value="268452911"},{number="15",value="0x100027a6 "},{number="25",value="1090519040"},{number="91",value="0x2001fa24"},{number="92",value="0xfffffffc"},{number="93",value="0"},{number="94",value="0"},{number="95",value="0"},{number="96",value="0"}] 33-interpreter-exec console "set output-radix 0x10" -> ~"Output radix now set to decimal 16, hex 10, octal 20.\n" -> =cmd-param-changed,param="output-radix",value="16" -> 33^done 34-interpreter-exec console "set input-radix 0xa" -> ~"Input radix now set to decimal 10, hex a, octal 12.\n" -> 34^done 35-stack-info-depth --thread 1 1000 -> 35^done,depth="2" 36-stack-list-frames --thread 1 0 1 -> 36^done,stack=[frame={level="0",addr="0x100027a6",func="escale::__cortex_m_rt__main",file="app/src/main.rs",fullname="/Users/ramanf/Dropbox/Projects/escale/escale_fw_rs/app/src/main.rs",line="109",arch="armv6s-m"},frame={level="1",addr="0x10002768",func="escale::__cortex_m_rt__main_trampoline",file="app/src/main.rs",fullname="/Users/ramanf/Dropbox/Projects/escale/escale_fw_rs/app/src/main.rs",line="106",arch="armv6s-m"}] 37-stack-select-frame --thread 1 0 -> 37^done 38-stack-list-variables --thread 1 --frame 0 --simple-values -> 38^done,variables=[{name="channels",type="escale::__cortex_m_rt__main::Channels"}] 39-var-update --thread 1 --frame 0 --all-values var_channels_256 -> 39^error,msg="Variable object not found" 40-var-create --thread 1 --frame 0 var_channels_256 * "channels" -> 40^done,name="var_channels_256",numchild="1",value="{...}",type="escale::__cortex_m_rt__main::Channels",thread-id="1",has_more="0" 41-exec-continue --thread 1 -> 41^running -> *running,thread-id="all" mi2.status = running openocd -> 'type target_event event gdb-start' openocd -> 'type target_event event step-start' openocd -> 'type target_event event resumed' openocd -> 'type target_event event gdb-halt' openocd -> 'type target_event event gdb-end' openocd -> 'type target_event event halted' openocd -> 'type target_event event step-end' openocd -> 'type target_event event resume-start' openocd -> 'type target_event event resumed' openocd -> 'type target_state state running' openocd -> 'type target_event event resume-end' openocd -> 'type target_event event gdb-start' ```

The set-up is

I suppose, I could try debugging the plug-in locally. Will take some time to figure out the process, though, because I'm not typically working with NodeJS, Electron, and JS/TS.

Looking forward for any hints, advice, or extra info requests.

On a side note. I've learned that BMP got RTT support recently (not included in v1.8.2): blackmagic-debug/blackmagic/blob/main/UsingRTT.md. I assume, Cortex Debug doesn't support RTT via BMP yet. It may be a cool future addition too 👀

haneefdm commented 2 years ago

Please hang on...I may have some good news shortly. We have to focus on OpenOCD. Probe/other-SW does not matter.

haneefdm commented 2 years ago

Can you please try this build I created manually (not published to marketplace). You have ot install it manually

https://github.com/Marus/cortex-debug/releases/tag/v1.5.6-pre1

Give me feedback. I create a launch.json to log all transactions to a file and we can enable that if it is still not working.

werediver commented 2 years ago

@haneefdm In a few tests I made, v1.5.6-pre1 worked perfectly! I tried:

The plug-in manages to attach RTT in both cases.

RTT doesn't work, if I use "Run Without Debugging", but, I suppose, that's to be expected.

Thanks a lot for implementing the fix! Looking forward to the next release.

haneefdm commented 2 years ago

Thank you for the feedback. I will make a release (pre) soon. I need to remove some of the debug messages that are still in there.

Yes, Run Without Debugging does not do many of the things we normally do....technically, some things are possible but require a ton of changes and may break the normal flow.