2222import struct
2323import pkg_resources
2424
25- from typing import Tuple , List , Optional
25+ from typing import Tuple , List , Optional , Union
2626
2727sys .path .append ('.' )
2828#from cmdebug.svd import SVDFile
3535 32 : "I" ,
3636}
3737
38- def _reg_address (reg : svd_model .SVDRegister ) -> int :
39- assert reg .parent is not None and reg . parent . _address_block is not None , f"Cannot get address for parentless register { reg .name } "
38+ def _reg_address (reg : Union [ svd_model .SVDRegister , svd_model . SVDRegisterArray ] ) -> int :
39+ assert reg .parent is not None , f"Cannot get address for parentless register { reg .name } "
4040 return reg .parent ._base_address + reg .address_offset
4141
4242def _field_accessible (field : svd_model .SVDField , mode : str ) -> bool :
@@ -52,6 +52,28 @@ def _field_readable(field: svd_model.SVDField) -> bool:
5252def _field_writeable (field : svd_model .SVDField ) -> bool :
5353 return _field_accessible (field , "write" )
5454
55+ def _reg_accessible (reg : Union [svd_model .SVDRegister , svd_model .SVDRegisterArray ], mode : str ) -> bool :
56+ if reg ._access is not None :
57+ return mode in reg ._access
58+ elif reg .parent ._access is not None :
59+ return mode in reg .parent ._access
60+ return False
61+
62+ def _reg_readable (reg : Union [svd_model .SVDRegister , svd_model .SVDRegisterArray ]) -> bool :
63+ return _reg_accessible (reg , "read" )
64+
65+ def _reg_writeable (reg : Union [svd_model .SVDRegister , svd_model .SVDRegisterArray ]) -> bool :
66+ return _reg_accessible (reg , "write" )
67+
68+ def _get_regs_by_addresss (peripheral : svd_model .SVDPeripheral ) -> List [Tuple [str , svd_model .SVDRegister , int ]]:
69+ reg_list : List [Tuple [str , svd_model .SVDRegister , int ]] = []
70+ for r in peripheral .registers :
71+ # Assign parent for the lookup, since we know it and for some reason registers derivered from a register array don't have a parent set
72+ r .parent = peripheral
73+ reg_list .append ((r .name , r , _reg_address (r )))
74+
75+ return sorted (reg_list , key = lambda x : x [2 ])
76+
5577class LoadSVD (gdb .Command ):
5678 """ A command to load an SVD file and to create the command for inspecting
5779 that object
@@ -128,30 +150,32 @@ def __init__(self, svd_device: svd_model.SVDDevice):
128150 gdb .Command .__init__ (self , "svd" , gdb .COMMAND_DATA )
129151 self .svd_device = svd_device
130152
131- def _print_registers (self , container_name , form : str , registers : List [svd_model .SVDRegister ]):
132- if len (registers ) == 0 :
133- return
153+ def _print_registers (self , container_name , form : str , peripheral : svd_model .SVDPeripheral ):
134154 gdb .write (f"Registers in { container_name } :\n " )
135- reg_list : List [Tuple [str , str , str ]] = []
136- for r in registers :
137- if r ._access is not None and "read" in r ._access :
155+
156+ reg_list = _get_regs_by_addresss (peripheral )
157+ reg_list_str : List [Tuple [str , str , str ]] = []
158+
159+ for name , r , addr in reg_list :
160+ if _reg_readable (r ):
138161 try :
139- data = self .read (_reg_address ( r ) , r ._size )
162+ data = self .read (addr , r ._size )
140163 data_str = self .format (data , form , r ._size )
141164 if form == 'a' :
142165 data_str += " <" + re .sub (r'\s+' , ' ' ,
143- gdb .execute ("info symbol {}" .format (data ), True ,
144- True ).strip ()) + ">"
166+ gdb .execute ("info symbol {}" .format (data ), True ,
167+ True ).strip ()) + ">"
145168 except gdb .MemoryError :
146169 data_str = "(error reading)"
147170 else :
148171 data_str = "(not readable)"
172+
149173 desc = re .sub (r'\s+' , ' ' , r .description )
150- reg_list .append ((r . name , data_str , desc ))
174+ reg_list_str .append ((name , data_str , desc ))
151175
152- column1_width = max (len (reg [0 ]) for reg in reg_list ) + 2 # padding
153- column2_width = max (len (reg [1 ]) for reg in reg_list )
154- for reg in reg_list :
176+ column1_width = max (len (reg [0 ]) for reg in reg_list_str ) + 2 # padding
177+ column2_width = max (len (reg [1 ]) for reg in reg_list_str )
178+ for reg in reg_list_str :
155179 gdb .write ("\t {}:{}{}" .format (reg [0 ], "" .ljust (column1_width - len (reg [0 ])), reg [1 ].rjust (column2_width )))
156180 if reg [2 ] != reg [0 ]:
157181 gdb .write (" {}" .format (reg [2 ]))
@@ -221,7 +245,7 @@ def invoke(self, args, from_tty):
221245 gdb .write ("\t d(default):decimal, x: hex, o: octal, b: binary\n " )
222246 gdb .write ("\n " )
223247 gdb .write (
224- "Both prefix matching and case-insensitive matching is supported for peripherals, registers, clusters and fields.\n " )
248+ "Both prefix matching and case-insensitive matching is supported for peripherals, registers, and fields.\n " )
225249 return
226250
227251 if not len (s [0 ]):
@@ -248,84 +272,38 @@ def invoke(self, args, from_tty):
248272 peripheral = sorted (matching_peripherals , key = lambda x : x .name )[0 ]
249273
250274 if len (s ) == 1 :
251- self ._print_registers (peripheral .name , form , peripheral .registers )
252- if peripheral ._register_arrays :
253- clusters_iter = peripheral ._register_arrays
254- gdb .write ("Clusters in %s:\n " % peripheral .name )
255- reg_list : List [Tuple [str , str , str ]] = []
256- for r in clusters_iter :
257- desc = re .sub (r'\s+' , ' ' , r .description )
258- reg_list .append ((r .name , "" , desc ))
259-
260- column1_width = max (len (reg [0 ]) for reg in reg_list ) + 2 # padding
261- column2_width = max (len (reg [1 ]) for reg in reg_list )
262- for reg in reg_list :
263- gdb .write (
264- "\t {}:{}{}" .format (reg [0 ], "" .ljust (column1_width - len (reg [0 ])), reg [1 ].rjust (column2_width )))
265- if reg [2 ] != reg [0 ]:
266- gdb .write (" {}" .format (reg [2 ]))
267- gdb .write ("\n " )
275+ self ._print_registers (peripheral .name , form , peripheral )
268276 return
269277
270- cluster = None
271278 if len (s ) == 2 :
272- gdb .write (f"{ [r .name for r in peripheral .registers ]} \n " )
273- matching_clusters = []
274- if peripheral ._register_arrays is not None :
275- matching_clusters = [c for c in peripheral ._register_arrays if c .name .lower ().startswith (s [1 ].lower ())]
276-
277279 matching_registers = []
278280 if peripheral .registers is not None :
279- matching_registers = [r for r in peripheral ._registers if r .name .lower ().startswith (s [1 ].lower ())]
281+ matching_registers = [r for r in peripheral .registers if r .name .lower ().startswith (s [1 ].lower ())]
280282
281- if matching_clusters :
282- # Warn if this matches more than one
283- if len (matching_clusters ) > 1 :
284- matching_names = ", " .join ([c .name for c in matching_clusters ])
285- gdb .write (f'Warning: { s [1 ]} could prefix match any of: { matching_names } \n ' )
286-
287- cluster = matching_clusters [0 ]
288- container = peripheral .name + ' > ' + cluster .name
289- self ._print_registers (container , form , cluster .registers )
290- elif matching_registers :
283+ if matching_registers :
291284 # Warn if this matches more than one
292285 if len (matching_registers ) > 1 :
293286 matching_names = ", " .join ([r .name for r in matching_registers ])
294287 gdb .write (f'Warning: { s [1 ]} could prefix match any of: { matching_names } \n ' )
295288
296- register = sorted (matching_registers )[0 ]
289+ register = sorted (matching_registers , key = lambda x : x . name )[0 ]
297290 container = peripheral .name + ' > ' + register .name
291+ register .parent = peripheral
298292 self ._print_register_fields (container , form , register )
299293
300294 else :
301- gdb .write (f"Register/cluster { s [1 ]} in peripheral { peripheral .name } does not exist!\n " )
295+ gdb .write (f"Register { s [1 ]} in peripheral { peripheral .name } does not exist!\n " )
302296 return
303297
304298 if len (s ) == 3 :
305- # Must be reading from a register within a cluster
306-
307- matching_clusters = []
308- if peripheral ._register_arrays is not None :
309- matching_clusters = [c for c in peripheral ._register_arrays if c .name .lower ().startswith (s [1 ].lower ())]
310-
311- if not matching_clusters :
312- gdb .write (f"Cluster { s [1 ]} in peripheral { peripheral .name } does not exist!\n " )
313- return
314-
315- # Warn if this matches more than one
316- if len (matching_clusters ) > 1 :
317- matching_names = ", " .join ([c .name for c in matching_clusters ])
318- gdb .write (f'Aborting: { s [1 ]} could prefix match any of: { matching_names } \n ' )
319- return
320-
321- cluster = matching_clusters [0 ]
299+ # Must be reading from a register
322300
323301 matching_registers = []
324- if peripheral ._registers is not None :
325- matching_registers = [r for r in peripheral ._registers if r .name .lower ().startswith (s [2 ].lower ())]
302+ if peripheral .registers is not None :
303+ matching_registers = [r for r in peripheral .registers if r .name .lower ().startswith (s [2 ].lower ())]
326304
327305 if not matching_registers :
328- gdb .write (f"Register { s [2 ]} in cluster { cluster . name } in peripheral { peripheral .name } does not exist!\n " )
306+ gdb .write (f"Register { s [2 ]} in peripheral { peripheral .name } does not exist!\n " )
329307 return
330308
331309 # Warn if this matches more than one
@@ -336,15 +314,15 @@ def invoke(self, args, from_tty):
336314
337315 register = matching_registers [0 ]
338316
339- container = ' > ' .join ([peripheral .name , cluster . name , register .name ])
317+ container = ' > ' .join ([peripheral .name , register .name ])
340318 self ._print_register_fields (container , form , register )
341319 return
342320
343321 if len (s ) == 4 :
344322
345323 matching_registers = []
346- if peripheral ._registers is not None :
347- matching_registers = [r for r in peripheral ._registers if r .name .lower ().startswith (s [1 ].lower ())]
324+ if peripheral .registers is not None :
325+ matching_registers = [r for r in peripheral .registers if r .name .lower ().startswith (s [1 ].lower ())]
348326
349327 if not matching_registers :
350328 gdb .write (f"Register { s [1 ]} in peripheral { peripheral .name } does not exist!\n " )
@@ -430,8 +408,7 @@ def complete(self, text, word):
430408 if len (reg ) and reg [0 ] == '&' :
431409 reg = reg [1 :]
432410
433- regs = peripheral .registers + peripheral ._register_arrays
434- matching_regs = [r for r in regs if r .name .lower ().startswith (reg .lower ())]
411+ matching_regs = [r for r in peripheral .registers if r .name .lower ().startswith (reg .lower ())]
435412
436413 if len (matching_regs ) == 0 :
437414 return []
0 commit comments