Marus / cortex-debug

Visual Studio Code extension for enhancing debug capabilities for Cortex-M Microcontrollers
MIT License
1.02k stars 240 forks source link

[Question] Restart not working: 'monitor reset hardware' returns 'Reply contains invalid hex digit 83' #498

Closed lutrampal closed 3 years ago

lutrampal commented 3 years ago

Hi,

I think this is really a request for support rather than a potential bug so don't hesitate to close this thread if it does not belong here.

I'm trying to get the restart/reset (not sure which one I should use to be honest) button working. What I want to do is to perform a device reset and re-run my program until main without flashing it again.

I have experience using gdb on the command line but VSCode and the Cortex Debug extension are fairly new to me.

My environment is the following:

The default restart command doesn't work for me, I'm getting an "Unknown reset option" in the debug console. Which makes sense because the default reset command is "monitor reset halt" and it is not mentioned in the user manual for my server (§2.9)

So, I tried using the overrideRestartCommands parameter to set my own commands. Using GDB from the command line, I can perform the reset with the following commands (having previously set a breakpoint to main):

monitor reset hardware
j handleReset

Where handleReset is the entryPoint of my program (@0x08000000). This works just fine as long as I'm doing it manually, outside of VSCode.

So I wrote the following in my launch config:

"overrideRestartCommands": [
    "interrupt",
    "monitor reset hardware",
    "j handleReset"
]

But when I click the restart button, I get the following:

48-exec-interrupt
GDB -> App: {"token":48,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[]}}
GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"console","content":"\nProgram"}]}

Program
GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"console","content":" received signal SIGINT, Interrupt.\n"}]}
 received signal SIGINT, Interrupt.
GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"console","content":"main () at /home/lutrampal/git/stm32-event-hal/src/example.cpp:77\n"}]}
main () at /home/lutrampal/git/stm32-event-hal/src/example.cpp:77
GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"console","content":"77\t        while (true) {}\n"}]}
77          while (true) {}
GDB -> App: {"outOfBandRecord":[{"isStream":false,"type":"exec","asyncClass":"stopped","output":[["reason","signal-received"],["signal-name","SIGINT"],["signal-meaning","Interrupt"],["frame",[["addr","0x90008876"],["func","main"],["args",[]],["file","/home/lutrampal/git/stm32-event-hal/src/example.cpp"],["fullname","/home/lutrampal/git/stm32-event-hal/src/example.cpp"],["line","77"],["arch","armv7e-m"]]],["thread-id","1"],["stopped-threads","all"],["core","0"]]}]}
49-interpreter-exec console "interrupt"
GDB -> App: {"token":49,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[]}}
50-interpreter-exec console "monitor reset hardware"
GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"log","content":"Reply contains invalid hex digit 83\n"}]}
Reply contains invalid hex digit 83
GDB -> App: {"token":50,"outOfBandRecord":[],"resultRecords":{"resultClass":"error","results":[["msg","Reply contains invalid hex digit 83"]]}}

My whole launch configuration is the following:

{
    "name": "Cortex Debug",
    "cwd": "${workspaceRoot}",
    "executable": "./build/example.elf",
    "request": "launch",
    "type": "cortex-debug",
    "servertype": "stlink",
    "stm32cubeprogrammer": "${env:CUBE_PROGRAMMER_BIN_DIR}",
    "serverpath": "${env:STLINK_GDB_SERVER}",
    "serverArgs": [
        "-l", "31", "-v", "-s", "-k", "-el", "${env:STM32_EXT_LOADER}"
    ],
    "overrideGDBServerStartedRegex": "Waiting for connection on port.*",
    "gdbPath": "${env:GDB}",
    "svdFile": "${env:STM32_SVD_FILE}",
    "overrideLaunchCommands": [
        "load",
        "tb handleError"
    ],
    "runToMain": true,
    "preLaunchTask": "Build",
    "demangle": true,
    "showDevDebugOutput": true,
    "overrideRestartCommands": [
        "interrupt",
        "monitor reset hardware",
        "j handleReset"
    ]
}

It works fine for flashing and launching but I had to tinker a bit to get it working. So don't hesitate to tell me if some things look weird in it...

I guess I must be doing something wrong, but I was unable to find my error. Could someone point me to right direction?

Thanks, Lucas

haneefdm commented 3 years ago

I am no ST expert and don't have this board. But, someone may come by to help, so I will leave it open for a few days.

From what I see though, for overrideRestartCommands, The interrupt is not needed as it will already be in an interrupted state before these commands are handled. In fact, it may interfere as it may produce an error from gdb. The next line monitor reset hardware should be okay provided this gdb-server is okay with it. The next line j handleReset though, shouldn't the reset already accomplish this? Also, jumping to a function is okay but what is your stack pointer set to? In my experience, you have to set both the SP and PC to the correct values or else things get super messed up (at least for the debugger). You can also probably do the following.

set $sp 0xsome-value
j handleReset

I would make sure that the LR (Link Register) is also correct. If memory servers it should be set to -1 or else stack dump will be bogus.

All of this should be done by the monitor reset anyways.

lutrampal commented 3 years ago

Thank you for your quick reply!

Removing the interrupt does not change anything (don't know why I put that here in the first place then...).

Thanks for pointing out that I should not have to manually jump to my resetHandler: I did have an issue with my linker script! I fixed it and removed the jump command but it does not resolve my original problem unfortunately.

Regarding your other questions, I checked that:

haneefdm commented 3 years ago

Shouldn't the stack pointer be in RAM? Typically at the end of the ram growing downwards. Of course, other variations exist but always something in RW memory

lutrampal commented 3 years ago

Yes, sorry my reply was unclear. The stack pointer takes the value found at the very beginning of the flash. e.g. if *0x08000000 = 0x2000FC00 then, at reset we have $sp = 0x2000FC00

haneefdm commented 3 years ago

Then, the only thing to do is to do a continue, which should have been done automatically for you. Try adding it to your overrideRestartCommands.

What happened when you did not even have a overrideRestartCommands? That should have worked as well. This is all we do.

            "monitor reset halt"

Not written by me, but an ST-user. Is this wrong for the general use case?

Could you please do me a favor and run the following command in the Debug Console and report back with what you see?

monitor help

I use a Mac and have not figured out how to use the stlink gdb server. Some issue the dynamically linked libraries

lutrampal commented 3 years ago

Adding a continue does not solve the issue. The error Reply contains invalid hex digit 83 is happening as a result of monitor reset hardware.

I can't say if monitor reset halt is wrong in general, but when I run it on my ST-LINK_gdbserver.exe (v5.9.1, the latest one packaged with CubeIDE v1.7.0), I get Unknown reset option so clearly it's not understanding the halt option. This user manual I found does not mention it either (§2.9) so I guess it does not exist. Unfortunately the document does not indicate to which version of ST-LINK_gdbserver.exe it is applicable... It is quite recent though and the revision history mentions some updates to the monitor reset commands. Maybe it was removed recently?

Yes ST tools can be a pain to get working on something other than Windows... Here's the output for monitor help:

Supported monitor commands are:
help
reset
flash mass_erase
flash set_parallelism_mode
led blink
ReadAP
ReadDP
WriteAP

There doesn't seem to be a help command to get the list of valid arguments to monitor reset (I tried monitor help reset and monitor reset help but no luck). We know from the user manual that at least monitor reset, monitor reset hardware and monitor reset core are valid.

haneefdm commented 3 years ago

Hmmm. Thanks for the info. reset halt is also used for the launch. Yes, I have seen people mention the unknown reset option but looks like the command was not totally ignored. Maybe hardware is a hard-reset and core is more like soft reset. I don't use this so, I don't want to second guess the original author's intent.

Back to your issue. Could you check the gdb-server window in the Terminal tab for issues from the stlink-server. Does it give you a similar error if you do a monitor reset core? Or just a monitor reset which may do a default thing.

Could you upgrade to STLink V3? I think most boards are upgradeable. We are only testing with V3

Or maybe what we need is a proper command-line option. That manual says the following for command-line options. This should be true for our extension to work, but I don't see that. You can use serverArgs to pass extra options.

--halt
Halts all cores during reset

and this

Use the command
>monitor reset
after downloading the code in order to set the SP and PC correctly. STM32CubeIDE issues this command
automatically after downloading the code to the target device.
lutrampal commented 3 years ago

Some good suggestions that I'd not thought about before, thank you for your time!

haneefdm commented 3 years ago

Unless I can reproduce the problem, there is nothing more I can do. All our testing is with V3 and it may very well be an issue between the ST gdb-server and the probe HW.

I will be fixing the monitor reset halt problem in the next release. Already fixed in my branch.

lutrampal commented 3 years ago

I understand, thank you for trying anyway.