27
27
28
28
29
29
class SvdParser (parser .Parser ):
30
- """
31
- CMSIS System View Description format (CMSIS-SVD)
32
- http://www.keil.com/pack/doc/CMSIS/SVD/html/index.html
33
- """
30
+ """Yasha parser for CMSIS-SVD files"""
34
31
file_extension = [".svd" ]
35
32
36
33
def parse (self , file ):
37
- f = SvdFile (file )
38
- f .parse ()
39
-
40
- vars = {
41
- "cpu" : f .cpu ,
42
- "device" : f .device ,
43
- "peripherals" : [f .peripherals [name ] for name in f .peripherals_order ],
34
+ svd = SvdFile (file )
35
+ svd .parse ()
36
+
37
+ variables = {
38
+ "cpu" : svd .cpu ,
39
+ "device" : svd .device ,
40
+ "peripherals" : [svd .peripherals [name ] for
41
+ name in svd .peripherals_order ],
44
42
}
45
- return vars
43
+ return variables
46
44
47
45
48
46
class SvdFile ():
47
+ """SVD File: Entry class to parse CMSIS-SVD file
48
+
49
+ SVD = System View Description format
50
+ CMSIS = Cortex Microcontroller Software Interface Standard
51
+ Read more from http://www.keil.com/pack/doc/CMSIS/SVD/html/
52
+ """
49
53
50
54
def __init__ (self , file ):
51
- if type (file ) is str :
55
+ if isinstance (file , str ) :
52
56
self .root = ET .fromstring (file )
53
57
else :
54
58
tree = ET .parse (file )
55
59
self .root = tree .getroot ()
56
60
57
- def parse (self ):
58
- self .cpu = Cpu (self .root .find ("cpu" ))
59
- self .device = Device (self .root )
60
-
61
+ self .cpu = None
62
+ self .device = None
61
63
self .peripherals = {}
62
64
self .peripherals_order = []
63
65
self .derived_peripherals = []
64
66
self .peripheral_groups = {}
65
67
68
+ def parse (self ):
69
+ self .cpu = Cpu (self .root .find ("cpu" ))
70
+ self .device = Device (self .root )
71
+
66
72
for e in self .root .iter ("peripheral" ):
67
73
p = Peripheral (e , self .device )
68
74
self .peripherals [p .name ] = p
@@ -74,7 +80,7 @@ def parse(self):
74
80
if p .groupName :
75
81
try :
76
82
self .peripheral_groups [p .groupName ].append (p .name )
77
- except :
83
+ except KeyError :
78
84
self .peripheral_groups [p .groupName ] = [p .name ]
79
85
80
86
for p in [self .peripherals [name ] for name in self .derived_peripherals ]:
@@ -123,14 +129,14 @@ def to_mixed_case(snake_case):
123
129
continue
124
130
try :
125
131
value = element .find (to_mixed_case (key )).text
126
- except : # Maybe it's attribute?
132
+ except AttributeError : # Maybe it's attribute?
127
133
default = defaults [key ] if key in defaults else None
128
134
value = element .get (to_mixed_case (key ), default )
129
135
130
136
if value and key in self .cast_to_integer :
131
137
try :
132
138
value = int (value )
133
- except : # It has to be hex
139
+ except ValueError : # It has to be hex
134
140
value = int (value , 16 )
135
141
136
142
setattr (self , key , value )
@@ -152,6 +158,8 @@ def to_dict(self):
152
158
153
159
154
160
class Device (SvdElement ):
161
+ """SVD Devices element"""
162
+
155
163
type = "device"
156
164
cast_to_integer = ["size" ]
157
165
props = [
@@ -178,6 +186,8 @@ def init(self):
178
186
179
187
180
188
class Cpu (SvdElement ):
189
+ """SVD CPU section"""
190
+
181
191
type = "cpu"
182
192
props = [
183
193
"name" , "revision" , "endian" , "mpuPresent" , "fpuPresent" , "fpuDP" ,
@@ -201,6 +211,17 @@ def init(self):
201
211
202
212
203
213
class Peripheral (SvdElement ):
214
+ """SVD Peripherals Level
215
+
216
+ A peripheral is a named collection of registers. A peripheral is mapped
217
+ to a defined base address within the device's address space. A peripheral
218
+ allocates one or more exclusive address blocks relative to its base
219
+ address, such that all described registers fit into the allocated address
220
+ blocks. Allocated addresses without an associated register description
221
+ are automatically considered reserved. The peripheral can be assigned to
222
+ a group of peripherals and may be associated with one or more interrupts.
223
+ """
224
+
204
225
type = "peripheral"
205
226
cast_to_integer = ["size" , "baseAddress" ]
206
227
props = [
@@ -237,17 +258,27 @@ def from_element(self, element, defaults={}):
237
258
elif r .tag == "register" :
238
259
r = Register (r , self , parent = self )
239
260
self .registers .extend (r .to_array ())
240
- except :
261
+ except TypeError :
241
262
pass
242
263
243
264
try : # Because interrupt may be None
244
265
for i in element .findall ("interrupt" ):
245
266
self .interrupts .append (Interrupt (i ))
246
- except :
267
+ except TypeError :
247
268
pass
248
269
249
270
250
271
class Register (SvdElement ):
272
+ """SVD Registers Level
273
+
274
+ A register is a named, programmable resource that belongs to a
275
+ peripheral. Registers are mapped to a defined address in the address
276
+ space of the device. An address is specified relative to the peripheral
277
+ base address. The description of a register documents the purpose and
278
+ function of the resource. A debugger requires information about the
279
+ permitted access to a resource as well as side effects triggered by
280
+ read and write accesses respectively.
281
+ """
251
282
type = "register"
252
283
cast_to_integer = ["size" , "addressOffset" , "dim" ,
253
284
"dimIncrement" , "resetValue" , "resetMask" ]
@@ -283,19 +314,19 @@ def from_element(self, element, defaults={}):
283
314
if self .dim :
284
315
try :
285
316
self .dimIndex = int (self .dimIndex )
286
- except :
317
+ except ValueError :
287
318
try :
288
319
start , stop = self .dimIndex .split ("-" )
289
320
start , stop = (int (start ), int (stop )+ 1 )
290
321
self .dimIndex = list (range (start , stop ))
291
- except :
322
+ except ValueError :
292
323
self .dimIndex = self .dimIndex .split ("," )
293
324
294
325
try : # Because fields may be None
295
326
for e in element .find ("fields" ):
296
327
field = Field (e , self , parent = self )
297
328
self .fields .append (field )
298
- except :
329
+ except TypeError :
299
330
pass
300
331
301
332
def to_array (self ):
@@ -331,6 +362,13 @@ def to_array(self):
331
362
332
363
333
364
class Cluster (SvdElement ):
365
+ """SVD Cluster extension level
366
+
367
+ Cluster adds an optional sub-level within the CMSIS SVD registers level.
368
+ A cluster describes a sequence of neighboring registers within
369
+ a peripheral.
370
+ """
371
+
334
372
type = "cluster"
335
373
cast_to_integer = ["addressOffset" , "dim" , "dimIncrement" ]
336
374
props = [
@@ -355,18 +393,24 @@ def from_element(self, element, defaults={}):
355
393
# TODO: Should work like Register.to_array(), if there's self.dim
356
394
self .name = self .name .replace ("%s" , str (self .dim ))
357
395
358
- try :
396
+ try : # findall() may return None
359
397
for e in element .findall ("*" ):
360
398
if e .tag == "cluster" : # Cluster may include yet another cluster
361
399
self .registers .append (Cluster (e , defaults , parent = self ))
362
400
elif e .tag == "register" :
363
401
r = Register (e , defaults , parent = self )
364
402
self .registers .extend (r .to_array ())
365
- except :
403
+ except TypeError :
366
404
pass
367
405
368
406
369
407
class Field (SvdElement ):
408
+ """SVD Fields level
409
+
410
+ All fields of a register are enclosed between the <fields>
411
+ opening and closing tags.
412
+ """
413
+
370
414
type = "field"
371
415
cast_to_integer = ["bitOffset" , "bitWidth" , "lsb" , "msb" ]
372
416
props = [
@@ -407,20 +451,26 @@ def from_element(self, element, defaults={}):
407
451
self .bitWidth = self .msb - self .lsb + 1
408
452
self .bitRange = "[{}:{}]" .format (self .msb , self .lsb )
409
453
410
- try : # Because enumeratedValues may be None
454
+ try : # Because findall() may return None
411
455
for e in element .findall ("enumeratedValues" ):
412
456
try :
413
457
usage = e .find ("usage" ).text
414
- except :
458
+ except AttributeError :
415
459
usage = "read-write"
416
460
for e in e .findall ("enumeratedValue" ):
417
461
enum = EnumeratedValue (e , {}, parent = self )
418
462
self .enumeratedValues [usage ].append (enum )
419
- except :
463
+ except TypeError :
420
464
pass
421
465
422
466
423
467
class EnumeratedValue (SvdElement ):
468
+ """SVD Enumerated values Level
469
+
470
+ The concept of enumerated values creates a map between unsigned
471
+ integers and an identifier string.
472
+ """
473
+
424
474
type = "enumeratedValue"
425
475
cast_to_integer = ["value" ]
426
476
props = ["derivedFrom" , "name" , "description" , "value" , "isDefault" ]
0 commit comments