@@ -15,6 +15,7 @@ import re
15
15
from pathlib import Path
16
16
from collections import defaultdict
17
17
18
+
18
19
def getDefineForDevice (device_id , familyDefines ):
19
20
"""
20
21
Returns the STM32 specific define from an identifier
@@ -61,45 +62,67 @@ def getDefineForDevice(device_id, familyDefines):
61
62
62
63
return None
63
64
65
+
66
+ class RegisterMap :
67
+ def __init__ (self , registers , logger ):
68
+ self ._registers = registers
69
+ self ._register_string = "\n " .join (registers )
70
+ self .result = None
71
+ self ._log = logger
72
+ # print(self._register_string)
73
+
74
+ def _result (self , query , value , ll ):
75
+ self .result = value
76
+ self ._log (f"{ query } -{ ll } -> { self .result } " )
77
+ return self .result
78
+
79
+ def findall (self , query , default = None ):
80
+ if query in self ._registers :
81
+ return self ._result (query , [query ], "fi" )
82
+ if matches := re .findall (f"(?:{ query } )\n " , self ._register_string ):
83
+ return self ._result (query , matches , "fn" )
84
+ return self ._result (query , default or [], "fd" )
85
+
86
+ def search (self , query , default = None ):
87
+ if query in self ._registers :
88
+ return self ._result (query , query , "si" )
89
+ if (match := re .search (f"(?:{ query } )\n " , self ._register_string )) is not None :
90
+ if not (groups := match .groups ()):
91
+ return self ._result (query , match .group (0 )[:- 1 ], "s0" )
92
+ if len (groups ) == 1 :
93
+ return self ._result (query , groups [0 ], "s1" )
94
+ return self ._result (query , groups , "sn" )
95
+ return self ._result (query , default , "sd" )
96
+
97
+ def _ops (self , re_pers , re_regs , re_bits , bit_fmt ):
98
+ reg_bits = defaultdict (list )
99
+ matches = re .findall (f"(({ re_pers } )_({ re_regs } )_(?:{ re_bits } ))\n " , self ._register_string )
100
+ for whole , per , reg in matches :
101
+ reg_bits [f"{ per } ->{ reg } " ].append (whole )
102
+ statements = [f"{ reg } { bit_fmt (' | ' .join (bits ))} ;" for reg , bits in reg_bits .items ()]
103
+ return "\n " .join (statements )
104
+
105
+ def set (self , pers , regs , bits ):
106
+ return self ._ops (pers , regs , bits , lambda bits : f" |= { bits } " )
107
+
108
+ def clear (self , pers , regs , bits ):
109
+ return self ._ops (pers , regs , bits , lambda bits : f" &= ~({ bits } )" )
110
+
111
+
64
112
bprops = {}
65
- def common_rcc_map (env ):
113
+ def common_register_map (env ):
66
114
"""
67
- Finds all CMSIS bit fields related to enabling and resetting peripherals
68
- in the RCC of the format `RCC_(REGISTER)_(PERIPHERAL)_(TYPE)` where:
115
+ Finds all register and bit names in the CMSIS header file.
69
116
70
- - REGISTER: a variation of `(BUS)(ID?)(ENR|RSTR)`, e.g. `AHB1ENR`
71
- - PERIPHERAL: typical peripheral name, e.g. `GPIOA`
72
- - TYPE: either `EN` or `RST`.
73
-
74
- :returns: a 2D-dictionary: `map[PERIPHERAL][TYPE] = REGISTER`
117
+ :returns: a RegisterMap object that allows regex-ing for register names.
75
118
"""
76
- headers = env .query ("headers" )
77
- core_header = repopath ("ext/arm/cmsis/CMSIS/Core/Include" , headers ["core_header" ])
78
-
79
- content = ""
80
- for header_path in [core_header , localpath (bprops ["folder" ], headers ["device_header" ])]:
81
- content += Path (header_path ).read_text (encoding = "utf-8" , errors = "replace" )
82
-
83
- # find mpu and fpu features
84
- features = re .findall (r"#define +__([MF]PU)_PRESENT +([01])" , content )
85
- core_features = {f [0 ]:bool (int (f [1 ])) for f in features }
86
- # find all peripherals
87
- mperipherals = re .findall (r"#define +(.*?) +\(\((.*?_Type(?:Def)?)" , content )
88
- # We only care about the absolute peripheral addresses
89
- peripherals = [(p [0 ],p [1 ]) for p in mperipherals ]
90
- # filter out MPU and/or FPU if required
91
- peripherals = filter (lambda p : p [0 ] not in core_features or core_features [p [0 ]], peripherals )
92
- peripherals = sorted (peripherals , key = lambda p : p [0 ])
93
- # print("\n".join([s+" -> "+hex(a) for (s,k,a) in peripherals]))
94
-
95
- # Find all RCC enable and reset definitions
96
- match = re .findall (r"RCC_([A-Z0-9]*?)_([A-Z0-9]+?)(EN|RST) " , content )
97
- rcc_map = defaultdict (dict )
98
- for (reg , per , typ ) in match :
99
- rcc_map [per ][typ ] = reg
100
-
101
- bprops ["peripherals" ] = peripherals
102
- return rcc_map
119
+ headers = env .query (":cmsis:device:headers" )
120
+ core_header = Path (repopath ("ext/arm/cmsis/CMSIS/Core/Include" , headers ["core_header" ]))
121
+ device_header = Path (localpath (bprops ["folder" ], headers ["device_header" ]))
122
+ content = "\n " .join (header .read_text (encoding = "utf-8" , errors = "replace" )
123
+ for header in [core_header , device_header ])
124
+ registers = re .findall (r"#define\s+([^\s\(\)]*?)(?:_Msk\s+\(|\s+\(.*?_Pos\)|\s+\(?0x)" , content )
125
+ return RegisterMap (registers , print )
103
126
104
127
105
128
def common_header_file (env ):
@@ -127,7 +150,7 @@ def common_header_file(env):
127
150
define = None
128
151
129
152
content = Path (localpath (folder , family_header )).read_text (encoding = "utf-8" , errors = "replace" )
130
- match = re .findall (r"if defined\((?P<define> STM32[CFGHLU ][\w\d]+)\)" , content )
153
+ match = re .findall (r"if defined\((STM32[A-Z ][\w\d]+)\)" , content )
131
154
define = getDefineForDevice (device .identifier , match )
132
155
if define is None or match is None :
133
156
raise ValidateException ("No device define found for '{}'!" .format (device .partname ))
@@ -198,17 +221,17 @@ def prepare(module, options):
198
221
return False
199
222
200
223
module .add_query (
201
- EnvironmentQuery (name = "rcc-map " , factory = common_rcc_map ))
224
+ EnvironmentQuery (name = "headers " , factory = common_header_file ))
202
225
module .add_query (
203
226
EnvironmentQuery (name = "peripherals" , factory = common_peripherals ))
204
227
module .add_query (
205
- EnvironmentQuery (name = "headers " , factory = common_header_file ))
228
+ EnvironmentQuery (name = "registers " , factory = common_register_map ))
206
229
207
230
module .depends (":cmsis:core" )
208
231
return True
209
232
210
233
def validate (env ):
211
- env .query ("rcc-map " )
234
+ env .query ("headers " )
212
235
env .query ("peripherals" )
213
236
214
237
def build (env ):
0 commit comments