diff --git a/tools/cmake/UploadMethodManager.cmake b/tools/cmake/UploadMethodManager.cmake index 5dfd0aa..5f967da 100644 --- a/tools/cmake/UploadMethodManager.cmake +++ b/tools/cmake/UploadMethodManager.cmake @@ -14,6 +14,14 @@ # use a higher numbered port to allow use without root on Linux/Mac set(GDB_PORT 23331 CACHE STRING "Port that the GDB server will be started on.") +# Load the upload method. This is expected to set the following variables: +# UPLOAD_${UPLOAD_METHOD}_FOUND - True iff the dependencies for this upload method were found +# UPLOAD_SUPPORTS_DEBUG - True iff this upload method supports debugging +# UPLOAD_GDBSERVER_DEBUG_COMMAND - Command to start a new GDB server +# UPLOAD_WANTS_EXTENDED_REMOTE - True iff GDB should use "target extended-remote" to connect to the GDB server +# UPLOAD_LAUNCH_COMMANDS - List of GDB commands to run after launching GDB. +# UPLOAD_RESTART_COMMANDS - List of commands to run when the "restart chip" function is used. +# See here for more info: https://github.com/mbed-ce/mbed-os/wiki/Debugger-Commands-and-State-in-Upload-Methods include(UploadMethod${UPLOAD_METHOD}) if(NOT "${UPLOAD_${UPLOAD_METHOD}_FOUND}") @@ -24,46 +32,27 @@ message(FATAL_ERROR "The upload method ${UPLOAD_METHOD} is not enabled in the config code for this target -- set ${UPLOAD_METHOD}_UPLOAD_ENABLED to TRUE to enable it.") endif() -message(STATUS "Board upload method set to ${UPLOAD_METHOD}") - -# ---------------------------------------------- -# Generate gdbinit if needed - if(UPLOAD_SUPPORTS_DEBUG) - # create init file for GDB client - if(UPLOAD_WANTS_EXTENDED_REMOTE) - set(UPLOAD_GDB_REMOTE_KEYWORD "extended-remote") - else() - set(UPLOAD_GDB_REMOTE_KEYWORD "remote") - endif() - - file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/mbed-cmake.gdbinit CONTENT -"# connect to GDB server -target ${UPLOAD_GDB_REMOTE_KEYWORD} localhost:${GDB_PORT} -") + message(STATUS "Mbed: Code upload and debugging enabled via upload method ${UPLOAD_METHOD}") +elseif(NOT "${UPLOAD_METHOD}" STREQUAL "NONE") + message(STATUS "Mbed: Code upload enabled via upload method ${UPLOAD_METHOD}") endif() -# UPLOAD_SUPPORTS_DEBUG needs to be made into a cache variable so that it can +# These variables need to be made into a cache variables so that they can # be seen by higher level directories when they call mbed_generate_upload_debug_targets() set(MBED_UPLOAD_SUPPORTS_DEBUG ${UPLOAD_SUPPORTS_DEBUG} CACHE INTERNAL "" FORCE) +set(MBED_UPLOAD_GDBSERVER_DEBUG_COMMAND ${UPLOAD_GDBSERVER_DEBUG_COMMAND} CACHE INTERNAL "" FORCE) +set(MBED_UPLOAD_WANTS_EXTENDED_REMOTE ${UPLOAD_WANTS_EXTENDED_REMOTE} CACHE INTERNAL "" FORCE) +set(MBED_UPLOAD_LAUNCH_COMMANDS ${UPLOAD_LAUNCH_COMMANDS} CACHE INTERNAL "" FORCE) +set(MBED_UPLOAD_RESTART_COMMANDS ${UPLOAD_RESTART_COMMANDS} CACHE INTERNAL "" FORCE) # ---------------------------------------------- # Function for creating targets -function(mbed_generate_upload_debug_targets target) +function(mbed_generate_upload_target target) # add upload target gen_upload_target(${target} ${CMAKE_CURRENT_BINARY_DIR}/$.bin ${CMAKE_CURRENT_BINARY_DIR}/$.hex ) - - # add debug target - if(MBED_UPLOAD_SUPPORTS_DEBUG AND MBED_GDB_FOUND) - add_custom_target(debug-${target} - COMMENT "starting GDB to debug ${target}..." - COMMAND ${MBED_GDB} - --command=${CMAKE_BINARY_DIR}/mbed-cmake.gdbinit - $ - USES_TERMINAL) - endif() endfunction() \ No newline at end of file diff --git a/tools/cmake/mbed_ide_debug_cfg_generator.cmake b/tools/cmake/mbed_ide_debug_cfg_generator.cmake index 831ad2a..a36e203 100644 --- a/tools/cmake/mbed_ide_debug_cfg_generator.cmake +++ b/tools/cmake/mbed_ide_debug_cfg_generator.cmake @@ -7,13 +7,21 @@ # ------------------------------------------------------------- if($ENV{CLION_IDE}) - message(STATUS "Detected CLion IDE, will generate CLion debug configurations") + message(STATUS "Mbed: Detected CLion IDE, will generate CLion debug configurations") set(MBED_GENERATE_CLION_DEBUG_CFGS TRUE) + set(MBED_CLION_PROFILE_NAME "" CACHE STRING "Name of the Clion build profile (Settings > Build, Execution, Deployment > CMake > Name textbox") + + if(MBED_CLION_PROFILE_NAME STREQUAL "") + message(FATAL_ERROR "In order to generate CLion configuration files, Mbed CE needs to know the name of the current CLion build profile. This name is the string typed into the Name textbox under Settings > Build, Execution, Deployment > CMake. Pass this name with '-DMBED_CLION_PROFILE_NAME='.") + endif() + elseif(CMAKE_EXPORT_COMPILE_COMMANDS) # TODO: Is this actually a reliable way of detecting VS Code? Not sure if it will create false positives. - message(STATUS "Detected VS Code IDE, will generate VS Code debug configurations") + message(STATUS "Mbed: Detected VS Code IDE, will generate VS Code debug configurations") set(MBED_GENERATE_VS_CODE_DEBUG_CFGS TRUE) +elseif(MBED_UPLOAD_SUPPORTS_DEBUG) + message(STATUS "Mbed: No IDE detected, will generate configurations for command-line debugging (e.g. ninja gdbserver, then ninja debug-SomeProgram)") endif() # CLion generator @@ -31,11 +39,43 @@ set(CONFIG_NAME "GDB ${CMAKE_TARGET} ${MBED_TARGET} ${CMAKE_BUILD_TYPE}") set(RUN_CONF_PATH "${CLION_RUN_CONF_DIR}/${CONFIG_NAME}.xml") + # Convert the CMake list into the correct format for the run configuration XML + list(GET MBED_UPLOAD_GDBSERVER_DEBUG_COMMAND 0 GDBSERVER_EXECUTABLE) + list(SUBLIST MBED_UPLOAD_GDBSERVER_DEBUG_COMMAND 1 -1 GDBSERVER_ARGS) + set(GDBSERVER_ARGS_STR "") + set(IS_FIRST_ARG TRUE) + foreach(ELEMENT ${GDBSERVER_ARGS}) + + if(IS_FIRST_ARG) + set(IS_FIRST_ARG FALSE) + else() + string(APPEND GDBSERVER_ARGS_STR " ") + endif() + + # Escape quotes and ampersands + string(REPLACE "\"" """ ELEMENT "${ELEMENT}") + string(REPLACE "&" "&" ELEMENT "${ELEMENT}") + + if("${ELEMENT}" MATCHES " ") + string(APPEND GDBSERVER_ARGS_STR ""${ELEMENT}"") + else() + string(APPEND GDBSERVER_ARGS_STR "${ELEMENT}") + endif() + endforeach() + + # Generate run configuration XML file. + # This file is based on a generic Embedded GDB Server run configuration generated by CLion, + # with constant strings replaced by placeholders for CMake. file(GENERATE OUTPUT ${RUN_CONF_PATH} CONTENT " - \" sysroot=\"\"> - + + + + + + ") @@ -55,9 +95,16 @@ # Start building up json file. Needs to be a global property so we can append to it from anywhere. # Note: Cannot use a cache variable for this because cache variables aren't allowed to contain newlines. set_property(GLOBAL PROPERTY VSCODE_LAUNCH_JSON_CONTENT -"{ +"// Auto-generated by Mbed CE. Edits will be erased when CMake is rerun. +{ \"configurations\": [") + set_property(GLOBAL PROPERTY VSCODE_TASKS_JSON_CONTENT +"// Auto-generated by Mbed CE. Edits will be erased when CMake is rerun. +{ + \"version\": \"2.0.0\", + \"tasks\": [") + # Find objdump as the extension uses it. In a sane world it should be in the compiler bin dir. find_program(MBED_OBJDUMP NAMES arm-none-eabi-objdump objdump @@ -68,10 +115,15 @@ function(mbed_generate_ide_debug_configuration CMAKE_TARGET) # Create name (combine target name, Mbed target, and build config to generate a unique string) - set(CONFIG_NAME "Connect to GDB ${CMAKE_TARGET} ${MBED_TARGET} ${CMAKE_BUILD_TYPE}") + set(CONFIG_NAME "Debug ${CMAKE_TARGET} ${MBED_TARGET} ${CMAKE_BUILD_TYPE}") + + # Convert CMake lists to json + list(JOIN MBED_UPLOAD_LAUNCH_COMMANDS "\", \"" UPLOAD_LAUNCH_COMMANDS_FOR_JSON) + list(JOIN MBED_UPLOAD_RESTART_COMMANDS "\", \"" UPLOAD_RESTART_COMMANDS_FOR_JSON) # property list here: https://github.com/Marus/cortex-debug/blob/master/debug_attributes.md set_property(GLOBAL APPEND_STRING PROPERTY VSCODE_LAUNCH_JSON_CONTENT " + // Debug launch for target ${CMAKE_TARGET}. { \"type\": \"cortex-debug\", \"name\": \"${CONFIG_NAME}\", @@ -81,13 +133,36 @@ \"objdumpPath\": \"${MBED_OBJDUMP}\", \"servertype\": \"external\", \"gdbTarget\": \"localhost:${GDB_PORT}\", - \"request\": \"attach\" + \"request\": \"launch\", + \"preLaunchTask\": \"Build ${CMAKE_TARGET} and start GDB server\", + // Override the command sequences used by VS Code to be correct for this GDB server + \"overrideLaunchCommands\": [\"${UPLOAD_LAUNCH_COMMANDS_FOR_JSON}\"], + \"overrideRestartCommands\": [\"${UPLOAD_RESTART_COMMANDS_FOR_JSON}\"], },") + # Add tasks to both build only, and build and start the GDB server. + # Schema for tasks.json can be seen here https://code.visualstudio.com/docs/editor/tasks-appendix + set_property(GLOBAL APPEND_STRING PROPERTY VSCODE_TASKS_JSON_CONTENT " + // Build for target ${CMAKE_TARGET} + { + \"label\": \"Build ${CMAKE_TARGET}\", + \"type\": \"shell\", + \"command\": \"${CMAKE_COMMAND}\", + \"args\": [\"--build\", \"${CMAKE_BINARY_DIR}\", \"--target\", \"${CMAKE_TARGET}\"], + }, + // Build ${CMAKE_TARGET} and run the GDB server + { + \"label\": \"Build ${CMAKE_TARGET} and start GDB server\", + \"dependsOn\": [\"Build ${CMAKE_TARGET}\", \"GDB Server\"], + \"dependsOrder\": \"sequence\", + },") + endfunction(mbed_generate_ide_debug_configuration) # Take all generated debug configurations and write them to launch.json. function(mbed_finalize_ide_debug_configurations) + + # Add footer set_property(GLOBAL APPEND_STRING PROPERTY VSCODE_LAUNCH_JSON_CONTENT " ] @@ -95,18 +170,118 @@ get_property(VSCODE_LAUNCH_JSON_CONTENT GLOBAL PROPERTY VSCODE_LAUNCH_JSON_CONTENT) file(GENERATE OUTPUT ${VSCODE_LAUNCH_JSON_PATH} CONTENT ${VSCODE_LAUNCH_JSON_CONTENT}) + + + # Convert the CMake list into the correct format for tasks.json + list(GET MBED_UPLOAD_GDBSERVER_DEBUG_COMMAND 0 GDBSERVER_EXECUTABLE) + list(SUBLIST MBED_UPLOAD_GDBSERVER_DEBUG_COMMAND 1 -1 GDBSERVER_ARGS) + set(GDBSERVER_ARGS_STR "") + set(IS_FIRST_ARG TRUE) + foreach(ELEMENT ${GDBSERVER_ARGS}) + + if(IS_FIRST_ARG) + set(IS_FIRST_ARG FALSE) + else() + string(APPEND GDBSERVER_ARGS_STR ", ") + endif() + + # Escape any quotes in the element + string(REPLACE "\"" "\\\"" ELEMENT "${ELEMENT}") + + string(APPEND GDBSERVER_ARGS_STR "\"${ELEMENT}\"") + endforeach() + + set_property(GLOBAL APPEND_STRING PROPERTY VSCODE_TASKS_JSON_CONTENT " + { + \"label\": \"GDB Server\", + \"type\": \"shell\", + \"command\": \"${GDBSERVER_EXECUTABLE}\", + \"args\": [${GDBSERVER_ARGS_STR}], + \"isBackground\": true, + // This task is run to start the GDB server, so that the launch configuration can connect to it. + // Problem is, it's a GDB server, and since it never exits, VSCode + // will never start the debug session. All this is needed so VSCode just lets it run. + \"problemMatcher\": [ + { + \"pattern\": [ + { + \"regexp\": \"________________\", + \"file\": 1, + \"location\": 2, + \"message\": 3 + } + ], + \"background\": { + \"activeOnStart\": true, + \"beginsPattern\": \".*\", + \"endsPattern\": \".*\", + } + } + ], + } + ] + +} + ") + + # Write out tasks.json + set(VSCODE_TASKS_JSON_PATH ${CMAKE_SOURCE_DIR}/.vscode/tasks.json) + get_property(VSCODE_TASKS_JSON_CONTENT GLOBAL PROPERTY VSCODE_TASKS_JSON_CONTENT) + file(GENERATE OUTPUT ${VSCODE_TASKS_JSON_PATH} CONTENT ${VSCODE_TASKS_JSON_CONTENT}) + endfunction(mbed_finalize_ide_debug_configurations) -# No-op generator +# Command-line generator # ------------------------------------------------------------- -else() +elseif(MBED_UPLOAD_SUPPORTS_DEBUG) function(mbed_generate_ide_debug_configuration CMAKE_TARGET) - # Empty + + # add debug target + if(MBED_UPLOAD_SUPPORTS_DEBUG AND MBED_GDB_FOUND) + add_custom_target(debug-${target} + COMMENT "Starting GDB to debug ${target}..." + COMMAND ${MBED_GDB} + --command=${CMAKE_BINARY_DIR}/mbed-cmake.gdbinit + $ + USES_TERMINAL) + endif() + endfunction(mbed_generate_ide_debug_configuration) function(mbed_finalize_ide_debug_configurations) - # Empty + + # create init file for GDB client + if(MBED_UPLOAD_WANTS_EXTENDED_REMOTE) + set(UPLOAD_GDB_REMOTE_KEYWORD "extended-remote") + else() + set(UPLOAD_GDB_REMOTE_KEYWORD "remote") + endif() + + list(JOIN MBED_UPLOAD_LAUNCH_COMMANDS "\n" MBED_UPLOAD_LAUNCH_COMMANDS_FOR_GDBINIT) + + file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/mbed-cmake.gdbinit CONTENT +"# connect to GDB server +target ${UPLOAD_GDB_REMOTE_KEYWORD} localhost:${GDB_PORT} +${MBED_UPLOAD_LAUNCH_COMMANDS_FOR_GDBINIT} +c" +) + + # Create target to start the GDB server + add_custom_target(gdbserver + COMMENT "Starting ${UPLOAD_METHOD} GDB server" + COMMAND ${MBED_UPLOAD_GDBSERVER_DEBUG_COMMAND} + USES_TERMINAL + VERBATIM) endfunction(mbed_finalize_ide_debug_configurations) +else() + + # No-ops + function(mbed_generate_ide_debug_configuration CMAKE_TARGET) + endfunction() + + function(mbed_finalize_ide_debug_configurations) + endfunction() + endif() \ No newline at end of file diff --git a/tools/cmake/mbed_target_functions.cmake b/tools/cmake/mbed_target_functions.cmake index 26e120e..272c15e 100644 --- a/tools/cmake/mbed_target_functions.cmake +++ b/tools/cmake/mbed_target_functions.cmake @@ -181,7 +181,7 @@ mbed_generate_map_file(${target}) endif() - mbed_generate_upload_debug_targets(${target}) + mbed_generate_upload_target(${target}) mbed_generate_ide_debug_configuration(${target}) endfunction() diff --git a/tools/cmake/upload_methods/UploadMethodJLINK.cmake b/tools/cmake/upload_methods/UploadMethodJLINK.cmake index 4caf9f3..37b5bbf 100644 --- a/tools/cmake/upload_methods/UploadMethodJLINK.cmake +++ b/tools/cmake/upload_methods/UploadMethodJLINK.cmake @@ -2,10 +2,15 @@ # SPDX-License-Identifier: Apache-2.0 ### J-Link Upload Method -# This method needs the following parameters: +# This method needs the following parameters: # JLINK_UPLOAD_INTERFACE - Interface to use with J-Link. Should be "JTAG" or "SWD". # JLINK_CLOCK_SPEED - Speed to run the J-Link at, in KHz. # JLINK_CPU_NAME - Name of CPU to pass to J-Link +# This method has the following options: +# JLINK_USB_SERIAL_NUMBER - Use a J-Link connected over USB with the specified serial number. +# JLINK_NETWORK_ADDRESS - Use a J-Link connected over the network with the given [:port] +# JLINK_NO_GUI - If set to true, suppress GUI dialog boxes from the J-Link software. +# set(UPLOAD_SUPPORTS_DEBUG TRUE) @@ -13,11 +18,34 @@ find_package(JLINK) set(UPLOAD_JLINK_FOUND ${JLINK_FOUND}) +### Setup options +set(JLINK_USB_SERIAL_NUMBER "" CACHE STRING "Use a J-Link connected over USB with the specified serial number.") +set(JLINK_NETWORK_ADDRESS "" CACHE STRING "Use a J-Link connected over the network with the given [:port]") + +# Figure out -select option. See here: https://wiki.segger.com/J-Link_GDB_Server#-select +if((NOT "${JLINK_USB_SERIAL_NUMBER}" STREQUAL "") AND (NOT "${JLINK_NETWORK_ADDRESS}" STREQUAL "")) + message(FATAL_ERROR "Cannot use both JLINK_USB_SERIAL_NUMBER and JLINK_NETWORK_ADDRESS at the same time!") +elseif(NOT "${JLINK_USB_SERIAL_NUMBER}" STREQUAL "") + set(JLINK_SELECT_ARG -Select usb=${JLINK_USB_SERIAL_NUMBER} CACHE INTERNAL "" FORCE) +elseif(NOT "${JLINK_NETWORK_ADDRESS}" STREQUAL "") + set(JLINK_SELECT_ARG -Select ip=${JLINK_NETWORK_ADDRESS} CACHE INTERNAL "" FORCE) +else() + # use default behavior + set(JLINK_SELECT_ARG "" CACHE INTERNAL "" FORCE) +endif() + # default to JTAG if(NOT DEFINED JLINK_UPLOAD_INTERFACE) set(JLINK_UPLOAD_INTERFACE JTAG CACHE INTERNAL "" FORCE) endif() +option(JLINK_NO_GUI "If true, suppress GUI dialog boxes from the J-Link software. Note: does not suppress license dialogs from J-Link EDU and On-Board probes, these are intentionally impossible to disable." FALSE) +if(JLINK_NO_GUI) + set(JLINK_NOGUI_ARG -Nogui CACHE INTERNAL "" FORCE) +else() + set(JLINK_NOGUI_ARG "" CACHE INTERNAL "" FORCE) +endif() + ### Function to generate upload target function(gen_upload_target TARGET_NAME BIN_FILE HEX_FILE) @@ -31,26 +59,28 @@ add_custom_target(flash-${TARGET_NAME} COMMENT "Flashing ${TARGET_NAME} with J-Link..." COMMAND ${JLINK} + ${JLINK_SELECT_ARG} + ${JLINK_NOGUI_ARG} -Device ${JLINK_CPU_NAME} -Speed ${JLINK_CLOCK_SPEED} -if ${JLINK_UPLOAD_INTERFACE} -JTAGConf -1,-1 -AutoConnect 1 -ExitOnError - -CommandFile ${COMMAND_FILE_PATH} - VERBATIM) + -CommandFile ${COMMAND_FILE_PATH}) add_dependencies(flash-${TARGET_NAME} ${TARGET_NAME}) endfunction(gen_upload_target) -### Function to generate debug target -add_custom_target(gdbserver - COMMENT "Starting J-Link GDB server" - COMMAND +### Commands to run the debug server. +# Note: Command-line options for the GDB server are documented on the wiki here: +# https://wiki.segger.com/J-Link_GDB_Server:#Command_line_options +set(UPLOAD_GDBSERVER_DEBUG_COMMAND "${JLINK_GDBSERVER}" - -Select USB + ${JLINK_SELECT_ARG} + ${JLINK_NOGUI_ARG} -Device ${JLINK_CPU_NAME} -Speed ${JLINK_CLOCK_SPEED} -endian little @@ -59,5 +89,18 @@ -LocalhostOnly -noIR -port ${GDB_PORT} - USES_TERMINAL - VERBATIM) + -singlerun # Terminate GDB server after GDB disconnects + ) + +# Reference: https://github.com/Marus/cortex-debug/blob/056c03f01e008828e6527c571ef5c9adaf64083f/src/jlink.ts#L42 +set(UPLOAD_LAUNCH_COMMANDS + "monitor halt" + "monitor reset" + "load" + "break main" + "monitor reset" +) +set(UPLOAD_RESTART_COMMANDS + "monitor halt" + "monitor reset" +) \ No newline at end of file diff --git a/tools/cmake/upload_methods/UploadMethodOPENOCD.cmake b/tools/cmake/upload_methods/UploadMethodOPENOCD.cmake index 22ca676..0e3cb5c 100644 --- a/tools/cmake/upload_methods/UploadMethodOPENOCD.cmake +++ b/tools/cmake/upload_methods/UploadMethodOPENOCD.cmake @@ -53,16 +53,30 @@ add_dependencies(flash-${TARGET_NAME} ${TARGET_NAME}) endfunction(gen_upload_target) -### Function to generate debug target -add_custom_target(gdbserver - COMMENT "Starting OpenOCD GDB server" - COMMAND +### Commands to run the debug server. +set(UPLOAD_GDBSERVER_DEBUG_COMMAND ${OpenOCD} ${OPENOCD_CHIP_CONFIG_COMMANDS} ${OPENOCD_ADAPTER_SERIAL_COMMAND} - -c "gdb_port ${GDB_PORT}" - USES_TERMINAL - VERBATIM) + # Shut down OpenOCD when GDB disconnects. + # see https://github.com/Marus/cortex-debug/issues/371#issuecomment-999727626 + -c "[target current] configure -event gdb-detach {shutdown}" + -c "gdb_port ${GDB_PORT}") # request extended-remote GDB sessions set(UPLOAD_WANTS_EXTENDED_REMOTE TRUE) + +# Reference: https://github.com/Marus/cortex-debug/blob/056c03f01e008828e6527c571ef5c9adaf64083f/src/openocd.ts#L100 +set(UPLOAD_LAUNCH_COMMANDS + "monitor reset halt" + "load" + "break main" + "monitor reset halt" +) +set(UPLOAD_RESTART_COMMANDS + "monitor reset halt" + + # The following will force an sync between gdb and openocd + "monitor gdb_sync" + "stepi" +) \ No newline at end of file diff --git a/tools/cmake/upload_methods/UploadMethodPYOCD.cmake b/tools/cmake/upload_methods/UploadMethodPYOCD.cmake index 994acd9..8f1e40b 100644 --- a/tools/cmake/upload_methods/UploadMethodPYOCD.cmake +++ b/tools/cmake/upload_methods/UploadMethodPYOCD.cmake @@ -41,19 +41,23 @@ add_dependencies(flash-${TARGET_NAME} ${TARGET_NAME}) endfunction(gen_upload_target) -### Function to generate debug target -add_custom_target(gdbserver - COMMENT "Starting pyOCD GDB server" - COMMAND +### Commands to run the debug server. +set(UPLOAD_GDBSERVER_DEBUG_COMMAND ${Python3_EXECUTABLE} -m pyocd gdbserver - -v --no-wait -t ${PYOCD_TARGET_NAME} ${PYOCD_PROBE_ARGS} -f ${PYOCD_CLOCK_SPEED} - -p ${GDB_PORT} - --persist - --semihosting - USES_TERMINAL) + -p ${GDB_PORT}) + +# Reference: https://github.com/Marus/cortex-debug/blob/056c03f01e008828e6527c571ef5c9adaf64083f/src/pyocd.ts#L40 +set(UPLOAD_LAUNCH_COMMANDS +"monitor reset halt" +"load" +"break main" +) +set(UPLOAD_RESTART_COMMANDS +"monitor reset" +) \ No newline at end of file diff --git a/tools/cmake/upload_methods/UploadMethodREDLINK.cmake b/tools/cmake/upload_methods/UploadMethodREDLINK.cmake index 95c5e94..e2914db 100644 --- a/tools/cmake/upload_methods/UploadMethodREDLINK.cmake +++ b/tools/cmake/upload_methods/UploadMethodREDLINK.cmake @@ -10,6 +10,8 @@ # This method creates the following options: # REDLINK_PROBE_SN - Serial number of the debug probe to connect to. If blank, will connect to any probe. +set(UPLOAD_SUPPORTS_DEBUG TRUE) + ### Handle options set(REDLINK_PROBE_SN "" CACHE STRING "Serial number of the debug probe to connect to for Redlink. Set to empty to detect any matching adapter.") @@ -57,27 +59,34 @@ endfunction(gen_upload_target) -### Function to generate debug target -add_custom_target(gdbserver - COMMENT "Starting Redlink GDB server" - COMMAND - ${crt_emu_cm_redlink_PATH} - -p ${REDLINK_PART_NUMBER} - --flash-hashing - -x ${REDLINK_PART_XML_DIR} - --flash-dir ${REDLINK_FLASH_LOADER_PATH} - -g - -s ${REDLINK_CLOCK_SPEED} - -2 - ${REDLINK_CONNECT_ARGS} - ${REDLINK_PROBE_ARGS} - --server :${GDB_PORT} - --vc - --connect-reset system - --kill-server # Because redlink seems to not handle Ctrl-C, we use this to close it when GDB exits - USES_TERMINAL - VERBATIM) +### Commands to run the debug server. +set(UPLOAD_GDBSERVER_DEBUG_COMMAND + ${crt_emu_cm_redlink_PATH} + -p ${REDLINK_PART_NUMBER} + --flash-hashing + -x ${REDLINK_PART_XML_DIR} + --flash-dir ${REDLINK_FLASH_LOADER_PATH} + -g + -s ${REDLINK_CLOCK_SPEED} + -2 + ${REDLINK_CONNECT_ARGS} + ${REDLINK_PROBE_ARGS} + --server :${GDB_PORT} + --vc + --connect-reset system + --kill-server # Close Redlink when GDB exits +) # request extended-remote GDB sessions -set(UPLOAD_WANTS_EXTENDED_REMOTE TRUE) \ No newline at end of file +set(UPLOAD_WANTS_EXTENDED_REMOTE TRUE) + +set(UPLOAD_LAUNCH_COMMANDS + "monitor reset" # undocumented, but works + "load" + "break main" + "monitor reset" +) +set(UPLOAD_RESTART_COMMANDS + "monitor reset" +) \ No newline at end of file diff --git a/tools/cmake/upload_methods/UploadMethodSTLINK.cmake b/tools/cmake/upload_methods/UploadMethodSTLINK.cmake index afc728b..7df3c61 100644 --- a/tools/cmake/upload_methods/UploadMethodSTLINK.cmake +++ b/tools/cmake/upload_methods/UploadMethodSTLINK.cmake @@ -35,12 +35,24 @@ add_dependencies(flash-${TARGET_NAME} ${TARGET_NAME}) endfunction(gen_upload_target) -### Function to generate debug target -add_custom_target(gdbserver - COMMENT "Starting st-util GDB server" - COMMAND +### Commands to run the debug server. +set(UPLOAD_WANTS_EXTENDED_REMOTE TRUE) +set(UPLOAD_GDBSERVER_DEBUG_COMMAND ${st-util_PATH} ${STLINK_SERIAL_ARGUMENT} ${STLINK_ARGS} --listen_port=${GDB_PORT} - USES_TERMINAL) + --multi) + +# Reference: https://github.com/Marus/cortex-debug/blob/056c03f01e008828e6527c571ef5c9adaf64083f/src/stutil.ts#L39 +# (except I had to change target-download to load for some reason) +set(UPLOAD_LAUNCH_COMMANDS + "monitor halt" + "monitor reset" + "load" + "break main" + "monitor reset" +) +set(UPLOAD_RESTART_COMMANDS + "monitor reset" +) \ No newline at end of file diff --git a/tools/cmake/upload_methods/UploadMethodSTM32CUBE.cmake b/tools/cmake/upload_methods/UploadMethodSTM32CUBE.cmake index 44d05ec..c309a62 100644 --- a/tools/cmake/upload_methods/UploadMethodSTM32CUBE.cmake +++ b/tools/cmake/upload_methods/UploadMethodSTM32CUBE.cmake @@ -44,18 +44,26 @@ endfunction(gen_upload_target) -### Function to generate debug target +### Commands to run the debug server. # The debugger needs to be passed the directory containing STM32CubeProg get_filename_component(CUBE_PROG_DIR ${STM32CubeProg_PATH} DIRECTORY) -add_custom_target(gdbserver - COMMENT "Starting ST-LINK GDB server" - COMMAND +set(UPLOAD_GDBSERVER_DEBUG_COMMAND ${STLINK_gdbserver_COMMAND} ${STM32CUBE_GDBSERVER_ARGS} -cp "${CUBE_PROG_DIR}" - --persistent # don't close debugger after GDB disconnects, matches behavior of other tools like J-Link -p ${GDB_PORT} - ${STM32CUBE_GDB_PROBE_ARGS} - USES_TERMINAL) + --halt + ${STM32CUBE_GDB_PROBE_ARGS}) + +# Reference: https://github.com/Marus/cortex-debug/blob/056c03f01e008828e6527c571ef5c9adaf64083f/src/stlink.ts#L113 +set(UPLOAD_LAUNCH_COMMANDS + "monitor reset" + "load" + "break main" + "monitor reset" +) +set(UPLOAD_RESTART_COMMANDS + "monitor reset" +) \ No newline at end of file