1414# See the License for the specific language governing permissions and
1515# limitations under the License.
1616
17- from typing import Optional , Tuple , List
17+ from typing import Optional , Tuple , List , Union
1818import os
1919import logging
2020from pathlib import Path
2424from ..core .session import Session
2525from ..debug .elf .elf import ELFBinaryFile
2626from .stdio import StdioHandler
27- from .rtt_server import RTTServer , RTTChanStdioWorker , RTTChanTCPWorker , RTTChanSysViewFileWorker , RTTChanSysViewTCPWorker
27+ from .rtt_server import RTTServer , RTTChanStdioWorker , RTTChanTCPWorker , RTTChanSysViewFileWorker , RTTChanSysViewTCPWorker , RTTChanFileWorker
2828from .systemview import SystemViewConfig
2929
3030LOG = logging .getLogger (__name__ )
@@ -34,8 +34,8 @@ class RTTConfig:
3434 """@brief Data class representing RTT configuration for a specific core."""
3535
3636 # type aliases scoped to the class
37- RTTControlBlock = Optional [Tuple [Optional [int ], Optional [int ], bool ]] # (address, size, auto-detect)
38- RTTChannel = Optional [Tuple [int , str , Optional [int ]]] # (number, mode, port)
37+ RTTControlBlock = Optional [Tuple [Optional [int ], Optional [int ], bool ]] # (address, size, auto-detect)
38+ RTTChannel = Optional [Tuple [int , str , Optional [Union [ int , str ]], Optional [ str ]]] # (number, mode, port/file-out, file--in )
3939 RTTChannelList = Optional [Tuple [RTTChannel , ...]]
4040
4141 _session : Session
@@ -50,8 +50,14 @@ def __post_init__(self):
5050 self ._rtt_configuration ()
5151
5252 # Helper methods
53- def _add_channel (self , ch_list : List ["RTTConfig.RTTChannel" ], number : int , mode : str , port : Optional [int ] = None ) -> None :
54- SUPPORTED_MODES = {'stdio' , 'server' , 'systemview' , 'systemview-server' }
53+ def _add_channel (self , ch_list : List ["RTTConfig.RTTChannel" ],
54+ number : int ,
55+ mode : str ,
56+ port : Optional [int ] = None ,
57+ file_out : Optional [str ] = None ,
58+ file_in : Optional [str ] = None ) -> None :
59+
60+ SUPPORTED_MODES = {'stdio' , 'server' , 'systemview' , 'systemview-server' , 'file' }
5561
5662 if number is None :
5763 # Warn about missing channel number
@@ -85,8 +91,32 @@ def _add_channel(self, ch_list: List["RTTConfig.RTTChannel"], number: int, mode:
8591 # Count the number of SystemView channels
8692 self .num_systemview_channels += 1
8793
88- port_str = f", port={ port } " if port is not None else ""
89- ch_list .append ((number , mode , port ))
94+ if mode == 'file' :
95+ if file_out is None or file_in is None :
96+ # If file not provided, set default: <target>_core<X>_ch<Y>
97+ file_root = f"{ self ._session .board .target_type } "
98+ if len (self ._session .board .target .cores ) > 1 :
99+ file_root += f"_core{ self ._core } "
100+ file_root += f"_ch{ number } "
101+ file_out = file_out or f"{ file_root } .out"
102+ file_in = file_in or f"{ file_root } .in"
103+ # Check if the folder exists for output file
104+
105+ if file_out is not None :
106+ dir_out = os .path .dirname (file_out )
107+ if dir_out and not os .path .exists (dir_out ):
108+ LOG .warning ("RTT channel %d configuration for core %d: directory for file-out '%s' for %s mode does not exist; channel out disabled" , number , self ._core , dir_out , mode )
109+ file_out = None
110+
111+ if file_in and not os .path .exists (file_in ):
112+ LOG .warning ("RTT channel %d configuration for core %d: file-in '%s' for %s mode does not exist; channel in disabled" , number , self ._core , file_in , mode )
113+ file_in = None
114+
115+ else :
116+ file_out = None
117+ file_in = None
118+
119+ ch_list .append ((number , mode , port or file_out or None , file_in ))
90120
91121 def _rtt_configuration (self ) -> None :
92122 rtt_config_list = self ._session .options .get ('rtt' ) or []
@@ -127,15 +157,15 @@ def _rtt_configuration(self) -> None:
127157 rtt_ch : List ["RTTConfig.RTTChannel" ] = []
128158 if ch_l is not None :
129159 for ch in ch_l :
130- self ._add_channel (rtt_ch , ch .get ('number' ), ch .get ('mode' ), ch .get ('port' ))
160+ self ._add_channel (rtt_ch , ch .get ('number' ), ch .get ('mode' ), ch .get ('port' ) or ch . get ( 'file-out' ), ch . get ( 'file-in' ) )
131161 if ch_g is not None :
132162 for ch in ch_g :
133163 if ch_l is not None and any (ch .get ('number' ) == local_ch .get ('number' ) for local_ch in ch_l ):
134164 # Skip global channel configuration if a local channel with the same number exists
135165 LOG .debug ("RTT channel %d configuration for core %d: pname specific configuration used; skipping global channel configuration" ,
136166 ch .get ('number' ), self ._core )
137167 else :
138- self ._add_channel (rtt_ch , ch .get ('number' ), ch .get ('mode' ), ch .get ('port' ))
168+ self ._add_channel (rtt_ch , ch .get ('number' ), ch .get ('mode' ), ch .get ('port' ) or ch . get ( 'file-out' ), ch . get ( 'file-in' ) )
139169
140170 # Sort channels by channel number if any were added
141171 if rtt_ch :
@@ -270,7 +300,7 @@ def configure_channels(self, stdio_handler: Optional[StdioHandler] = None):
270300
271301 stdio_enabled = False
272302
273- for number , mode , server_port in self ._rtt_config .channels :
303+ for number , mode , port_or_file_out , file_in in self ._rtt_config .channels :
274304 if self ._rtt_server .is_channel_idx_valid (number ) is False :
275305 LOG .warning ("RTT for core %d: channel index %d is out of range; skipping configuration for channel %d" , self ._core , number , number )
276306 continue
@@ -294,25 +324,34 @@ def configure_channels(self, stdio_handler: Optional[StdioHandler] = None):
294324 # Server mode
295325 elif mode == 'server' :
296326 try :
297- self ._rtt_server .add_channel_worker (number , lambda : RTTChanTCPWorker (server_port , listen = True ))
298- LOG .info ("RTT channel %d configuration for core %d: mode=%s, port=%d" , number , self ._core , mode , server_port )
327+ self ._rtt_server .add_channel_worker (number , lambda : RTTChanTCPWorker (port_or_file_out , listen = True ))
328+ LOG .info ("RTT channel %d configuration for core %d: mode=%s, port=%d" , number , self ._core , mode , port_or_file_out )
299329 except exceptions .RTTError as e :
300330 LOG .error ("RTT for core %d: failed to enable server mode for RTT channel %d: %s" , self ._core , number , e )
301331 # SystemView mode
302332 elif mode == 'systemview' :
303333 try :
304334 fname_root = self ._systemview .file .rsplit ('.' , 1 )[0 ]
305335 fname = f'{ fname_root } .core{ self ._core } .ch{ number } .bin'
306- self ._rtt_server .add_channel_worker (number , lambda : RTTChanSysViewFileWorker (rtt_server = self ._rtt_server , rtt_channel = number , file_out = fname , auto_start = self ._systemview .auto_start , auto_stop = self ._systemview .auto_stop ))
336+ self ._rtt_server .add_channel_worker (number , lambda : RTTChanSysViewFileWorker (rtt_server = self ._rtt_server , channel = number , file_out = fname , auto_start = self ._systemview .auto_start , auto_stop = self ._systemview .auto_stop ))
307337 LOG .info ("RTT channel %d configuration for core %d: mode=%s" , number , self ._core , mode )
308338 except (IOError , exceptions .RTTError ) as e :
309339 LOG .error ("RTT for core %d: failed to enable systemview mode for RTT channel %d: %s" , self ._core , number , e )
310340 # SystemView server mode
311341 elif mode == 'systemview-server' :
312342 try :
313- self ._rtt_server .add_channel_worker (number , lambda : RTTChanSysViewTCPWorker (server_port , listen = True ))
314- LOG .info ("RTT channel %d configuration for core %d: mode=%s, port=%d" , number , self ._core , mode , server_port )
343+ self ._rtt_server .add_channel_worker (number , lambda : RTTChanSysViewTCPWorker (port_or_file_out , listen = True ))
344+ LOG .info ("RTT channel %d configuration for core %d: mode=%s, port=%d" , number , self ._core , mode , port_or_file_out )
315345 except exceptions .RTTError as e :
316346 LOG .error ("RTT for core %d: failed to enable systemview server mode for RTT channel %d: %s" , self ._core , number , e )
347+ # File mode
348+ elif mode == 'file' :
349+ try :
350+ self ._rtt_server .add_channel_worker (number , lambda : RTTChanFileWorker (channel = number , file_out = port_or_file_out , file_in = file_in ))
351+ file_out_str = f", file-out={ port_or_file_out } " if port_or_file_out else ""
352+ file_in_str = f", file-in={ file_in } " if file_in else ""
353+ LOG .info ("RTT channel %d configuration for core %d: mode=%s%s%s" , number , self ._core , mode , file_out_str , file_in_str )
354+ except (IOError , exceptions .RTTError ) as e :
355+ LOG .error ("RTT for core %d: failed to enable file mode for RTT channel %d: %s" , self ._core , number , e )
317356 else :
318357 LOG .warning ("RTT for core %d: unsupported channel mode '%s' for channel %d; skipping configuration for channel %d" , self ._core , mode , number , number )
0 commit comments