diff --git a/docs/options.md b/docs/options.md
index 5e842277b..5bbf79aa6 100644
--- a/docs/options.md
+++ b/docs/options.md
@@ -152,9 +152,11 @@ Log details of loaded .FLM flash algos.
debug.traceback |
bool |
-True |
+False |
-Print tracebacks for exceptions.
+Print tracebacks for exceptions, including errors that are only logged as well as critical errors that cause pyocd to terminate.
+
+Disabled by default, unless the log level is raised to Debug.
|
enable_multicore_debug |
diff --git a/pyocd/commands/commander.py b/pyocd/commands/commander.py
index 3059f5396..1e8079615 100755
--- a/pyocd/commands/commander.py
+++ b/pyocd/commands/commander.py
@@ -214,10 +214,11 @@ def connect(self) -> bool:
connect_mode=connect_mode,
frequency=self.args.frequency,
options=options,
- option_defaults=dict(
- auto_unlock=False,
- resume_on_disconnect=False,
- )
+ option_defaults={
+ 'auto_unlock': False,
+ 'resume_on_disconnect': False,
+ 'debug.traceback': logging.getLogger('pyocd').isEnabledFor(logging.DEBUG),
+ }
)
if not self._post_connect():
diff --git a/pyocd/core/options.py b/pyocd/core/options.py
index b99b5ef01..1e4b3b0f6 100644
--- a/pyocd/core/options.py
+++ b/pyocd/core/options.py
@@ -64,7 +64,7 @@ class OptionInfo(NamedTuple):
"When switching between SWD and JTAG, use the SWJ sequence from ADIv5.2 that utilizes a new dormant state."),
OptionInfo('debug.log_flm_info', bool, False,
"Log details of loaded .FLM flash algos."),
- OptionInfo('debug.traceback', bool, True,
+ OptionInfo('debug.traceback', bool, False,
"Print tracebacks for exceptions."),
OptionInfo('enable_multicore_debug', bool, False,
"Whether to put pyOCD into multicore debug mode. Doing so changes the default software reset type of "
diff --git a/pyocd/subcommands/base.py b/pyocd/subcommands/base.py
index 16542331d..4a65cdcd6 100644
--- a/pyocd/subcommands/base.py
+++ b/pyocd/subcommands/base.py
@@ -1,5 +1,5 @@
# pyOCD debugger
-# Copyright (c) 2021 Chris Reed
+# Copyright (c) 2021-2023 Chris Reed
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,7 +17,7 @@
import argparse
import logging
import prettytable
-from typing import (List, Optional, Type)
+from typing import (Any, Dict, List, Optional, Type)
from ..utility.cmdline import convert_frequency
@@ -169,4 +169,17 @@ def _get_pretty_table(self, fields: List[str], header: bool = None) -> prettytab
pt.vrules = prettytable.NONE
return pt
+ def _modified_option_defaults(self) -> Dict[str, Any]:
+ """@brief Returns a dict of session option defaults.
+
+ @return A dict containing updated default values for session options, based on common
+ subcommand arguments. It is intended to be passed as the `option_defaults` argument when
+ creating a `Session` instance.
+ @precondition Logging must have been configured.
+ """
+ return {
+ # Change 'debug.traceback' default to True if debug logging is enabled.
+ 'debug.traceback': logging.getLogger('pyocd').isEnabledFor(logging.DEBUG),
+ }
+
diff --git a/pyocd/subcommands/erase_cmd.py b/pyocd/subcommands/erase_cmd.py
index 918820ea5..602d3fff0 100644
--- a/pyocd/subcommands/erase_cmd.py
+++ b/pyocd/subcommands/erase_cmd.py
@@ -85,7 +85,9 @@ def invoke(self) -> int:
frequency=self._args.frequency,
blocking=(not self._args.no_wait),
connect_mode=self._args.connect_mode,
- options=convert_session_options(self._args.options))
+ options=convert_session_options(self._args.options),
+ option_defaults=self._modified_option_defaults(),
+ )
if session is None:
LOG.error("No device available to erase")
return 1
diff --git a/pyocd/subcommands/gdbserver_cmd.py b/pyocd/subcommands/gdbserver_cmd.py
index a788c2c64..7b7df012c 100644
--- a/pyocd/subcommands/gdbserver_cmd.py
+++ b/pyocd/subcommands/gdbserver_cmd.py
@@ -183,7 +183,9 @@ def invoke(self) -> int:
target_override=self._args.target_override,
frequency=self._args.frequency,
connect_mode=self._args.connect_mode,
- options=sessionOptions)
+ options=sessionOptions,
+ option_defaults=self._modified_option_defaults(),
+ )
if session is None:
LOG.error("No probe selected.")
return 1
diff --git a/pyocd/subcommands/load_cmd.py b/pyocd/subcommands/load_cmd.py
index a27b8c079..29f7b2ef2 100644
--- a/pyocd/subcommands/load_cmd.py
+++ b/pyocd/subcommands/load_cmd.py
@@ -91,7 +91,9 @@ def invoke(self) -> int:
frequency=self._args.frequency,
blocking=(not self._args.no_wait),
connect_mode=self._args.connect_mode,
- options=convert_session_options(self._args.options))
+ options=convert_session_options(self._args.options),
+ option_defaults=self._modified_option_defaults(),
+ )
if session is None:
LOG.error("No target device available")
return 1
diff --git a/pyocd/subcommands/reset_cmd.py b/pyocd/subcommands/reset_cmd.py
index 8d642546d..d14075c29 100644
--- a/pyocd/subcommands/reset_cmd.py
+++ b/pyocd/subcommands/reset_cmd.py
@@ -84,7 +84,9 @@ def invoke(self) -> None:
connect_mode=self._args.connect_mode,
resume_on_disconnect=not self._args.halt,
reset_type=self._args.reset_type,
- options=convert_session_options(self._args.options))
+ options=convert_session_options(self._args.options),
+ option_defaults=self._modified_option_defaults(),
+ )
if session is None:
LOG.error("No target device available to reset")
sys.exit(1)
diff --git a/pyocd/subcommands/rtt_cmd.py b/pyocd/subcommands/rtt_cmd.py
index 4561ddea6..62e1648b4 100644
--- a/pyocd/subcommands/rtt_cmd.py
+++ b/pyocd/subcommands/rtt_cmd.py
@@ -80,7 +80,9 @@ def invoke(self) -> int:
frequency=self._args.frequency,
blocking=(not self._args.no_wait),
connect_mode=self._args.connect_mode,
- options=convert_session_options(self._args.options))
+ options=convert_session_options(self._args.options),
+ option_defaults=self._modified_option_defaults(),
+ )
if session is None:
LOG.error("No target device available")