diff --git a/pyocd/subcommands/run_cmd.py b/pyocd/subcommands/run_cmd.py index 05bfd42f9..4c9ace122 100644 --- a/pyocd/subcommands/run_cmd.py +++ b/pyocd/subcommands/run_cmd.py @@ -128,9 +128,10 @@ def invoke(self) -> int: if isinstance(session.board.target.cores[core_number], GenericMemAPTarget): continue + rtt_cfg = cfg if (cfg := rtt_config_list[core_number]) and cfg.channels is not None else None run_server = RunServer(session=session, core=core_number, - rtt_config=rtt_config_list[core_number], + rtt_config=rtt_cfg, systemview_config=systemview_config, enable_eot=self._args.eot, shutdown_event=self.shared_shutdown) @@ -225,13 +226,18 @@ def __init__(self, session: Session, core: Optional[int] = None, rtt_config: "RT # Start RTT server self._rtt_server = None - try: - rtt_manager = RTTManager(session=session, core=core, rtt_config=rtt_config, systemview_config=systemview_config) - self._rtt_server = rtt_manager.start_server() - if self._rtt_server is not None: - rtt_manager.configure_channels(stdio_handler=self._stdio_handler) - except RuntimeError as e: - LOG.debug("RTT configuration failed for core %d: %s", self.core, e) + self._rtt_config = rtt_config + self._rtt_manager = None + if self._rtt_config is not None: + # Try to start RTT server. If RTT control block is not initialized at program start, this may fail. + # In that case, we'll keep trying to start the RTT server every 10ms in the main loop. + try: + self._rtt_manager = RTTManager(session=session, core=core, rtt_config=rtt_config, systemview_config=systemview_config) + self._rtt_server = self._rtt_manager.start_server() + if self._rtt_server is not None: + self._rtt_manager.configure_channels(stdio_handler=self._stdio_handler) + except RuntimeError as e: + LOG.debug("RTT configuration failed for core %d: %s", self.core, e) # # If SWV is enabled, create a SWVReader thread. Note that we only do @@ -287,11 +293,23 @@ def run(self): if self._rtt_server: self._rtt_server.poll() - # Check target state and handle semihosting every 10ms (every 10 loop iterations) - # to avoid slowing down RTT polling + # 10ms loop (every 10th iteration of 1ms loop) to avoid slowing down RTT polling if state_check_interval_counter == 10: state_check_interval_counter = 0 + # Try to start RTT server if it isn't already running, and if the configuration is present + # This allows RTT to start up successfully even if the RTT control block is not initialized at program start + if self._rtt_config is not None and self._rtt_manager is not None and self._rtt_server is None: + # Attempt to start RTT server + try: + self._rtt_server = self._rtt_manager.start_server() + if self._rtt_server is not None: + LOG.info("RTT enabled for core %d", self.core) + self._rtt_manager.configure_channels(stdio_handler=self._stdio_handler) + except RuntimeError as e: + LOG.debug("RTT configuration failed for core %d: %s", self.core, e) + + # Check target state state = self._target.get_state() # If we were able to successfully read the target state after previously receiving a fault, diff --git a/pyocd/utility/rtt_manager.py b/pyocd/utility/rtt_manager.py index 7c4292c24..e35af4f09 100644 --- a/pyocd/utility/rtt_manager.py +++ b/pyocd/utility/rtt_manager.py @@ -156,6 +156,7 @@ def __init__(self, session: Session, core: Optional[int] = None, rtt_config: RTT else: self._core = core self._target = self._board.target.cores[core] + self._cb_detection_warning_logged = False # RTT configuration self._rtt_config = rtt_config @@ -205,7 +206,7 @@ def _find_segger_rtt_symbol(self) -> Optional[int]: def start_server(self) -> Optional[RTTServer]: """@brief Create and start RTT server.""" - if not self._rtt_config.has_rtt_config: + if self._rtt_config is None or not self._rtt_config.has_rtt_config: LOG.debug("RTT for core %d: no RTT configuration; RTT disabled", self._core) return None @@ -223,7 +224,9 @@ def start_server(self) -> Optional[RTTServer]: if rtt_cb is not None: address, size, auto_detect = rtt_cb if address is None and auto_detect is False: - LOG.warning("RTT for core %d: control block configuration is missing address while auto-detect is disabled; RTT disabled", self._core) + if self._cb_detection_warning_logged is False: + LOG.warning("RTT for core %d: control block configuration is missing address while auto-detect is disabled; RTT disabled", self._core) + self._cb_detection_warning_logged = True return None if address is not None: self._rtt_server = self._start_rtt_server(address, size) @@ -234,10 +237,12 @@ def start_server(self) -> Optional[RTTServer]: LOG.debug("RTT for core %d: RTT control block found via specified address 0x%X", self._core, address) return self._rtt_server else: - if size: - LOG.warning("RTT for core %d: failed to find RTT control block with specified address 0x%X and size 0x%X", self._core, address, size) - else: - LOG.warning("RTT for core %d: failed to find RTT control block with specified address 0x%X", self._core, address) + if self._cb_detection_warning_logged is False: + if size: + LOG.warning("RTT for core %d: failed to find RTT control block with specified address 0x%X and size 0x%X", self._core, address, size) + else: + LOG.warning("RTT for core %d: failed to find RTT control block with specified address 0x%X", self._core, address) + self._cb_detection_warning_logged = True if auto_detect: # Fallback: auto-detect via memory scan in default memory region if no address specified self._rtt_server = self._start_rtt_server(None, None) @@ -245,20 +250,26 @@ def start_server(self) -> Optional[RTTServer]: LOG.debug("RTT for core %d: RTT control block found via auto-detect memory scan in default memory region", self._core) return self._rtt_server else: - LOG.warning("RTT for core %d: failed to find RTT control block with auto-detected address", self._core) + if self._cb_detection_warning_logged is False: + LOG.warning("RTT for core %d: failed to find RTT control block with auto-detected address", self._core) + self._cb_detection_warning_logged = True return None else: # Auto-detect via symbol "_SEGGER_RTT" lookup in the ELF file address = self._find_segger_rtt_symbol() if address is None: - LOG.warning("RTT for core %d: failed to find _SEGGER_RTT symbol in ELF; cannot auto-detect RTT control block", self._core) + if self._cb_detection_warning_logged is False: + LOG.warning("RTT for core %d: failed to find _SEGGER_RTT symbol in ELF; cannot auto-detect RTT control block", self._core) + self._cb_detection_warning_logged = True return None self._rtt_server = self._start_rtt_server(address, None) if self._rtt_server is not None: LOG.debug("RTT for core %d: RTT control block found via _SEGGER_RTT symbol lookup at address 0x%X", self._core, address) return self._rtt_server - LOG.warning("RTT for core %d: failed to find RTT control block with _SEGGER_RTT symbol address 0x%X", self._core, address) + if self._cb_detection_warning_logged is False: + LOG.warning("RTT for core %d: failed to find RTT control block with _SEGGER_RTT symbol address 0x%X", self._core, address) + self._cb_detection_warning_logged = True return None def configure_channels(self, stdio_handler: Optional[StdioHandler] = None):