emacs-lsp / dap-mode

Emacs :heart: Debug Adapter Protocol
https://emacs-lsp.github.io/dap-mode
GNU General Public License v3.0
1.3k stars 182 forks source link

[Proposal] [Cortex-Debug] Debugger for STM32 #224

Open tosiek88 opened 4 years ago

tosiek88 commented 4 years ago

Today I made some test and looks like the Cortex-Debug can be adopted - Parts of this debuger are based upon Jan Jurzitza's (WebFreak) code-debug which is already working in dap-mode.

I will try to add provider and we will see how its cooperate, it will be amazing debugging cortex uC in emacs !

yyoncho commented 4 years ago

Thank you. Let me know if you have any issues with that.

tosiek88 commented 4 years ago

So looks like I have a lack of knowledge how to configure this one right. One way to run debug is to use arm-toolchain - arm-none-eabi-gdb but before that, OpenOCD have to by fire up something like that :

openocd -c "gdb_port 50000" -f /usr/share/openocd/scripts/interface/stlink-v2-1.cfg -f /usr/share/openocd/scripts/target/stm32f4x.cfg 

next arm-none-eabi-gdb :

./opt/armcc/bin/arm-none-eabi-gdb ~/develop/STM32_VSCODE/build/vsarm_firmware.elf

then in gdb session or as --ex argument:

target extended-remote localhost:50000

and session is going, ofc. in case of dap-mode arm-none-eabi-gdb should be in mi mode (--interpreter=mi)

Another way is to use Cortex-debug, but for me is not obvious which file is responsible for start gdb debugger, I assume that similar to for example cppdbg is gdb.js but I need to dig more. Another thing that this debbuger fire up automatically OpenOCD - looks like in pipe manner.

I have full working example in VSCode on procesor STM32F411. launch.json looks like that:

        {
            "type": "cortex-debug",
            "request": "launch",
            "servertype": "openocd",
            "cwd": "${workspaceRoot}",
            "internalConsoleOptions": "openOnSessionStart",
            "executable": "./build/vsarm_firmware.elf",
            "name": "Debug (openocd)",
            "device": "STM32F411CE",
            "v1": false,
            "svdFile": "${workspaceRoot}/STM32F411.svd",
            "configFiles": [
                "/usr/share/openocd/scripts/interface/stlink-v2-1.cfg",
                "/usr/share/openocd/scripts/target/stm32f4x.cfg"
            ]
}

And LOG from Cortex-debug gdb

Please check OUTPUT tab (Adapter Output) for output from openocd
Launching server: "openocd" "-c" "gdb_port 50000" "-s" "/home/tocha/develop/STM32_VSCODE" "-f" "/usr/share/openocd/scripts/interface/stlink-v2-1.cfg" "-f" "/usr/share/openocd/scripts/target/stm32f4x.cfg" "-c" "tpiu config internal /tmp/tmp-1954isFCOwFTQ5p2 uart off 100000000 2000000"
Launching GDB: "/home/tocha/opt/armcc/bin/arm-none-eabi-gdb" "-q" "--interpreter=mi2"
1-gdb-set target-async on
2-interpreter-exec console "source /home/tocha/.vscode/extensions/marus25.cortex-debug-0.3.4/support/gdbsupport.init"
3-target-select extended-remote localhost:50000
4-interpreter-exec console "monitor reset halt"
5-target-download
6-interpreter-exec console "monitor reset halt"
7-enable-pretty-printing
8-interpreter-exec console "EnableITMAccess"
9-interpreter-exec console "BaseSWOSetup 49"
10-interpreter-exec console "SetITMId 1"
11-interpreter-exec console "ITMDWTTransferEnable"
12-interpreter-exec console "DisableITMPorts 0xFFFFFFFF"
13-interpreter-exec console "EnableITMPorts 0x3"
14-interpreter-exec console "EnableDWTSync"
15-interpreter-exec console "ITMSyncEnable"
16-interpreter-exec console "ITMGlobalEnable"
17-interpreter-exec console "DisablePCSample"
GDB -> App: {"outOfBandRecord":[{"isStream":false,"type":"notify","asyncClass":"thread-group-added","output":[["id","i1"]]}]}
GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"log","content":"/home/tocha/.gdbinit:2220: Error in sourced command file:\n"}]}
/home/tocha/.gdbinit:2220: Error in sourced command file:
GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"log","content":"Scripting in the \"Python\" language is not supported in this copy of GDB.\n"}]}
Scripting in the "Python" language is not supported in this copy of GDB.
GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"console","content":"Reading symbols from /home/tocha/develop/STM32_VSCODE/build/vsarm_firmware.elf...\n"}]}

My biggest problem is that I don't have knowledge about Elisp (yet), so it will take some time to adapt. For now I begin with scratch config and template:

;;Link: https://github.com/Marus/cortex-debug"
(defun dap-arm-none-eabi-gdb(conf)
  "Populate CONF with the required arguments."
  (-> conf
      (dap--put-if-absent :dap-server-path dap-gdb-arm-none-eabi-debug-program )
      (dap--put-if-absent :type "gdb")
      (dap--put-if-absent :cwd default-directory)
      (dap--put-if-absent :target (read-file-name "Select file to debug."))
      (dap--put-if-absent :name "GDB Cortex Debug")))

(dap-register-debug-provider "gdb" 'dap-arm-none-eabi-gdb(
(dap-register-debug-template "ARM - GDB"
                             (list :type "arm-none-eabi-gdb"
                                   :cwd "\/home\/tocha\/develop\/STM32_VSCODE\/"
                                   :request "launch"
                                   :debug_port 50000
                                   :device "STM32F411CE"
                                   :v1 "false"
                                   :host "localhost"
                                   :name "Run Configuration"))))
yyoncho commented 4 years ago

Something like that should be the initial version.

(dap-register-debug-provider "cortex-debug" #'identity)
(dap-debug
 (list :type "cortex-debug"
       :request "launch"
       :servertype "openocd"
       :dap-server-path '("node" "<FIXME path-to-extension>/dist/debugadapter.js")
       :cwd "<FIXME path to project>"
       :internalConsoleOptions "openOnSessionStart"
       :executable "./build/vsarm_firmware.elf"
       :name "Debug (openocd)"
       :device "STM32F411CE"
       :v1 false
       :svdFile "<FIXME path to project>/STM32F411.svd"
       :configFiles ["/usr/share/openocd/scripts/interface/stlink-v2-1.cfg"
                     "/usr/share/openocd/scripts/target/stm32f4x.cfg"]))
roangel commented 4 years ago

Any plans of getting this feature in?

yyoncho commented 4 years ago

Any plans of getting this feature in?

It all depends on someone with expertise in the domain taking care of this. Alternatinatively, someone from the core team can take care of this if there is simple to follow recipe how to make that work in vscode. Consider the fact that this is the first time I have heard of STM32/Cortex.

roangel commented 4 years ago

Same as @tosiek88, I have a fully working example in VSCode, but have no idea of lisp, and have never come across code-debug nor dap-mode

nbfalcon commented 4 years ago

@roangel fyi: dap-mode supports launch.json files. After a quick glimpse at yours, I think it should work. So just copy your launch.json file to .vscode/launch.json in your project root, and everything should work. There are currently some limitations (not full json5 support, i.e. no trailing commas), but most things should work.

nbfalcon commented 4 years ago

Variables also work just fine, so you don't need to replace ${workspaceFolder}, etc. with anything else.

nbfalcon commented 4 years ago

Nevermind, I overlooked "type": "cortex-debug". Yeah, we need to support cortex-debug first, then you can use your launch.json unmodified.

roangel commented 4 years ago

I wonder, if this can be done: https://www.eggers-club.de/blog/2017/07/01/embedded-debugging-with-lldb-sure/ I guess that if we have lldb-vscode working with dap-mode, which we do, it shouldn't be crazy hard to connect both ends right?

roangel commented 4 years ago

I wonder, if this can be done: https://www.eggers-club.de/blog/2017/07/01/embedded-debugging-with-lldb-sure/ I guess that if we have lldb-vscode working with dap-mode, which we do, it shouldn't be crazy hard to connect both ends right?

I have an st-link with me and a stm32 microcontroller to debug. This works for me: image

Problem is I am finding problems to pass the right commands to lldb. Does anyone know how to pass these startup commands to lldb from the debug-template?

(dap-register-debug-template
  "LLDB::Run"
  (list :type "lldb"
        :cwd "~/src/pacflyer_PX4/PX4/"
        :request "launch"
        :program "~/src/pacflyer_PX4/PX4/build/px4_fmu-v5_default/px4_fmu-v5_default.elf"
    ;; :initCommands "[
    ;;       "platform select remote-gdb-server>", ;; // Execute `platform list` for a list of available remote platform plugins.
    ;;       "platform connect connect://localhost:4242"
    ;;       ;; "settings set target.inherit-env false", // See the note below.
    ;;       ],
        :name "LLDB::Run"))
yyoncho commented 4 years ago

Is this lldb-vscode or native debug adapter? Usually, the best way to find that info is to look at the package.json for vscode package or debug adapter sources.

roangel commented 4 years ago

Is this lldb-vscode or native debug adapter? Usually, the best way to find that info is to look at the package.json for vscode package or debug adapter sources.

I compiled the lldb that I use in that picture from https://github.com/llvm/llvm-project, and then compiled llbd-vscode. The one from there is the one I use in emacs.

tosiek88 commented 4 years ago

Hi again I don't have to much time to work with this, but for my point of view better to adapt https://github.com/Marus/cortex-debug/ it has written debugger adaptor, and can be fire up even from node js. in Package.json there is all the commands how to work with it.

c2real commented 3 years ago

Something like that should be the initial version.

(dap-register-debug-provider "cortex-debug" #'identity)
(dap-debug
 (list :type "cortex-debug"
       :request "launch"
       :servertype "openocd"
       :dap-server-path '("node" "<FIXME path-to-extension>/dist/debugadapter.js")
       :cwd "<FIXME path to project>"
       :internalConsoleOptions "openOnSessionStart"
       :executable "./build/vsarm_firmware.elf"
       :name "Debug (openocd)"
       :device "STM32F411CE"
       :v1 false
       :svdFile "<FIXME path to project>/STM32F411.svd"
       :configFiles ["/usr/share/openocd/scripts/interface/stlink-v2-1.cfg"
                     "/usr/share/openocd/scripts/target/stm32f4x.cfg"]))

Hi, @yyoncho I think dap-gdb-lldb.el almost can do the same thing. I do some testing, change

(defun dap-gdb-lldb--populate-gdbserver (conf)
... 
(dap--put-if-absent :request "lanuch")`
(dap--put-if-absent :gdbpath "arm-none-eabi-gdb")

Then the launch.json config file

    "version": "0.2.0",
    "configurations": [
        {
            "name": "Debug (OpenOCD)",
            "type": "gdbserver",
            "request": "launch",
            "cwd": "/home/c2real/Projects/STM32F429-Base",
            "executable": "./build/STM32F429-Base.elf",
            "target": "/home/c2real/Projects/STM32F429-Base/build/STM32F429-Base.elf",
            "debugger_args": "-x=/home/c2real/Projects/STM32F429-Base/gdbstartup",
            "showDevDebugOutput": true,
            "printCalls": true
        }
    ]
}

here is the gdb init file

target remote 127.0.0.1:3333
monitor halt
monitor reset
file /home/c2real/Projects/STM32F429-Base/build/STM32F429-Base.elf
load

arm-none-eabi-gdb need a init file to write image to MCU, in case, if the image on MCU is different from current elf file, the single step/break points will have errors.

And also need to start a gdb server from the console, I use openocd.

Snipaste_2020-11-24_10-38-30 Snipaste_2020-11-24_11-02-15 Snipaste_2020-11-24_11-34-18

yyoncho commented 3 years ago

@c2real nice!

I do some testing, change

(defun dap-gdb-lldb--populate-gdbserver (conf)
... 
(dap--put-if-absent :request "lanuch")`
(dap--put-if-absent :gdbpath "arm-none-eabi-gdb")

I think you can pass those through the template itself without code change, no?

Other than that if you are willing to write a blog/tutorial/wiki I will be happy to link it from lsp-mode docs and popularize it because it all seems to narrow down to documentation.

c2real commented 3 years ago

@c2real nice!

I do some testing, change

(defun dap-gdb-lldb--populate-gdbserver (conf)
... 
(dap--put-if-absent :request "lanuch")`
(dap--put-if-absent :gdbpath "arm-none-eabi-gdb")

I think you can pass those through the template itself without code change, no?

Other than that if you are willing to write a blog/tutorial/wiki I will be happy to link it from lsp-mode docs and popularize it because it all seems to narrow down to documentation.

yes, pass all parameters via launch.json should be ok. I will test later, and write a brief guide on how to setup the develop environment with stm32 evk board.

nbfalcon commented 3 years ago

Is there some way to have it start OpenOCD automatically, perhaps by specifying a tty?

tosiek88 commented 3 years ago

I think that cortex-debug should do it , because : "servertype": "openocd"

and

VSCode config fire up this: Please check OUTPUT tab (Adapter Output) for output from openocd Launching server: "openocd" "-c" "gdb_port 50000" "-s" "/home/tocha/develop/STM32_VSCODE" "-f" "/usr/share/openocd/scripts/interface/stlink-v2-1.cfg" "-f" "/usr/share/openocd/scripts/target/stm32f4x.cfg" "-c" "tpiu config internal /tmp/tmp-1954isFCOwFTQ5p2 uart off 100000000 2000000" Launching GDB: "/home/tocha/opt/armcc/bin/arm-none-eabi-gdb" "-q" "--interpreter=mi2"

in https://github.com/Marus/cortex-debug/blob/master/package.json there is a path to OpenOCD GDB server that need to be specify.

c2real commented 3 years ago

I write a brief note about how I setup the dap-mode/dap-gdb-lldb. here the link https://github.com/c2real/dap-mode-setup-for-mcu/blob/main/README.md And I also find that, other people do the same thing via cpptool, it should be under vscode, but I think it maybe usefully for config under emacs, https://github.com/microsoft/vscode-cpptools/issues/328#issuecomment-261427055 For the cortex-debug, I tried, but not success, I don't know how node work, it just hang there.

c2real commented 3 years ago

Is there some way to have it start OpenOCD automatically, perhaps by specifying a tty?

Yes, it could work, and when you terminate the debugging, you should also close the openocd process, otherwise, next time, when start again, another process try to access the usb device, it may cause problem.

I am not good at emacs-lisp, so just start the openocd process at the very beginning once, it will be ok.

nbfalcon commented 3 years ago

Does the adapter itself not have such a feature? If not, then this should probably be implemented upstream, if at all.