3
3
4
4
'''Runner for probe-rs.'''
5
5
6
- from runners .core import RunnerCaps , ZephyrBinaryRunner
6
+ from runners .core import FileType , RunnerCaps , ZephyrBinaryRunner
7
7
8
8
DEFAULT_PROBE_RS_GDB_HOST = 'localhost'
9
9
DEFAULT_PROBE_RS_GDB_PORT = 1337
@@ -17,22 +17,46 @@ def __init__(self, cfg, chip,
17
17
gdb_port = DEFAULT_PROBE_RS_GDB_PORT ,
18
18
dev_id = None ,
19
19
erase = False ,
20
+ reset = False ,
21
+ protocol = 'swd' ,
22
+ speed = None ,
23
+ connect_under_reset = False ,
24
+ verify = False ,
25
+ binary_format = 'elf' ,
20
26
tool_opt = None ):
21
27
super ().__init__ (cfg )
22
28
23
29
self .probe_rs = probe_rs
24
30
self .erase = erase
31
+ self .reset = reset
32
+ self .protocol = protocol
33
+ self .speed = speed
34
+ self .connect_under_reset = connect_under_reset
35
+ self .verify = verify
36
+ self .binary_format = binary_format
25
37
26
38
self .args = ['--chip' , chip ]
27
39
28
40
if dev_id is not None :
29
41
self .args += ['--probe' , dev_id ]
30
42
43
+ if protocol != 'swd' :
44
+ self .args += ['--protocol' , protocol ]
45
+
46
+ if speed is not None :
47
+ self .args += ['--speed' , str (speed )]
48
+
49
+ if connect_under_reset :
50
+ self .args += ['--connect-under-reset' ]
51
+
31
52
if tool_opt is not None :
32
53
self .args += tool_opt
33
54
55
+ self .file = cfg .file
56
+ self .file_type = cfg .file_type
34
57
self .elf_name = cfg .elf_file
35
58
59
+ # GDB configuration (upstream compatible)
36
60
self .gdb_cmd = cfg .gdb
37
61
self .gdb_host = gdb_host
38
62
self .gdb_port = gdb_port
@@ -43,23 +67,33 @@ def name(cls):
43
67
44
68
@classmethod
45
69
def capabilities (cls ):
46
- return RunnerCaps (commands = {'flash' , 'debug' , 'debugserver' },
70
+ return RunnerCaps (commands = {'flash' , 'debug' , 'debugserver' , 'attach' },
47
71
dev_id = True ,
48
72
erase = True ,
49
- tool_opt = True )
73
+ reset = True ,
74
+ tool_opt = True ,
75
+ rtt = True ,
76
+ file = True )
50
77
51
78
@classmethod
52
79
def do_add_parser (cls , parser ):
53
80
parser .add_argument ('--chip' , required = True ,
54
81
help = 'chip name' )
55
82
parser .add_argument ('--probe-rs' , default = 'probe-rs' ,
56
83
help = 'path to probe-rs tool, default is probe-rs' )
84
+ parser .add_argument ('--protocol' , choices = ['swd' , 'jtag' ], default = 'swd' ,
85
+ help = 'debug protocol to use (swd or jtag)' )
86
+ parser .add_argument ('--speed' , type = int ,
87
+ help = 'protocol speed in kHz' )
88
+ parser .add_argument ('--connect-under-reset' , action = 'store_true' ,
89
+ help = 'connect under reset' )
90
+ parser .add_argument ('--verify' , action = 'store_true' ,
91
+ help = 'verify flash after programming' )
57
92
parser .add_argument ('--gdb-host' , default = DEFAULT_PROBE_RS_GDB_HOST ,
58
93
help = f'probe-rs gdb host, defaults to { DEFAULT_PROBE_RS_GDB_HOST } ' )
59
- parser .add_argument ('--gdb-port' , default = DEFAULT_PROBE_RS_GDB_PORT ,
94
+ parser .add_argument ('--gdb-port' , type = int , default = DEFAULT_PROBE_RS_GDB_PORT ,
60
95
help = f'probe-rs gdb port, defaults to { DEFAULT_PROBE_RS_GDB_PORT } ' )
61
96
62
-
63
97
@classmethod
64
98
def dev_id_help (cls ) -> str :
65
99
return '''select a specific probe, in the form `VID:PID:<Serial>`'''
@@ -69,12 +103,36 @@ def tool_opt_help(cls) -> str:
69
103
return '''additional options for probe-rs,
70
104
e.g. --chip-description-path=/path/to/chip.yml'''
71
105
106
+ @classmethod
107
+ def _get_binary_format_from_args (cls , args ):
108
+ '''Determine binary format from args.'''
109
+ if args .file_type :
110
+ # Map FileType to probe-rs format names
111
+ format_map = {
112
+ FileType .HEX : 'hex' ,
113
+ FileType .BIN : 'bin' ,
114
+ FileType .ELF : 'elf'
115
+ }
116
+ return format_map .get (args .file_type , 'elf' )
117
+ elif args .file and args .file .endswith ('.hex' ):
118
+ return 'hex'
119
+ else :
120
+ return 'elf'
121
+
72
122
@classmethod
73
123
def do_create (cls , cfg , args ):
74
124
return ProbeRsBinaryRunner (cfg , args .chip ,
75
125
probe_rs = args .probe_rs ,
76
126
dev_id = args .dev_id ,
77
127
erase = args .erase ,
128
+ reset = args .reset ,
129
+ protocol = args .protocol ,
130
+ speed = args .speed ,
131
+ connect_under_reset = args .connect_under_reset ,
132
+ verify = args .verify ,
133
+ gdb_host = args .gdb_host ,
134
+ gdb_port = args .gdb_port ,
135
+ binary_format = cls ._get_binary_format_from_args (args ),
78
136
tool_opt = args .tool_opt )
79
137
80
138
def do_run (self , command , ** kwargs ):
@@ -83,24 +141,53 @@ def do_run(self, command, **kwargs):
83
141
self .do_flash (** kwargs )
84
142
elif command in ('debug' , 'debugserver' ):
85
143
self .do_debug_debugserver (command , ** kwargs )
144
+ elif command == 'attach' :
145
+ self .do_attach (** kwargs )
86
146
87
147
def do_flash (self , ** kwargs ):
88
148
download_args = []
89
149
if self .erase :
90
150
download_args += ['--chip-erase' ]
91
- download_args += [self .elf_name ]
151
+ if self .verify :
152
+ download_args += ['--verify' ]
153
+ # Use provided file or default ELF file
154
+ flash_file = self .file if self .file else self .elf_name
155
+ # Determine format based on file_type or binary_format
156
+ if self .file_type :
157
+ format_map = {
158
+ FileType .HEX : 'hex' ,
159
+ FileType .BIN : 'bin' ,
160
+ FileType .ELF : 'elf'
161
+ }
162
+ flash_format = format_map .get (self .file_type , 'elf' )
163
+ else :
164
+ flash_format = self .binary_format
165
+ download_args += ['--binary-format' , flash_format , flash_file ]
92
166
93
167
self .check_call ([self .probe_rs , 'download' ]
94
168
+ self .args + download_args )
95
169
96
- self .check_call ([self .probe_rs , 'reset' ]
97
- + self .args )
170
+ if self .reset :
171
+ self .check_call ([self .probe_rs , 'reset' ]
172
+ + self .args )
98
173
99
174
def do_debug_debugserver (self , command , ** kwargs ):
175
+ '''Start GDB server or debug session using probe-rs gdb command.'''
100
176
debug_args = ['--gdb-connection-string' , f"{ self .gdb_host } :{ self .gdb_port } " ]
101
177
if command == 'debug' :
178
+ if self .gdb_cmd is None :
179
+ raise ValueError ('Cannot debug; gdb is missing' )
102
180
debug_args += [self .elf_name ]
103
181
debug_args += ['--gdb' , self .gdb_cmd ]
182
+ else :
183
+ # debugserver mode
184
+ self .logger .info (f'probe-rs GDB server running on port { self .gdb_port } ' )
104
185
105
186
self .check_call ([self .probe_rs , 'gdb' ]
106
187
+ self .args + debug_args )
188
+
189
+ def do_attach (self , ** kwargs ):
190
+ '''Attach to RTT logging using probe-rs attach command.'''
191
+ attach_cmd = [self .probe_rs , 'attach' ] + self .args + [self .elf_name ]
192
+ self .logger .info ('Starting RTT session' )
193
+ self .check_call (attach_cmd )
0 commit comments