@@ -12,8 +12,9 @@ mod utils;
12
12
13
13
#[ derive( Debug , PartialEq ) ]
14
14
enum GenerateTarget {
15
- PinMappings ,
16
15
Features ,
16
+ PinMappings ,
17
+ EepromSizes ,
17
18
}
18
19
19
20
lazy_static ! {
@@ -31,6 +32,11 @@ fn gpio_version_to_feature(version: &str) -> Result<String, String> {
31
32
}
32
33
}
33
34
35
+ /// Get the EEPROM size (in KiB) feature for a certain size.
36
+ fn eeprom_size_to_feature ( size : u32 ) -> String {
37
+ format ! ( "eeprom-{}" , size)
38
+ }
39
+
34
40
fn main ( ) -> Result < ( ) , String > {
35
41
let args = App :: new ( "cube-parse" )
36
42
. version ( env ! ( "CARGO_PKG_VERSION" ) )
@@ -47,7 +53,7 @@ fn main() -> Result<(), String> {
47
53
Arg :: with_name ( "generate" )
48
54
. help ( "What to generate" )
49
55
. takes_value ( true )
50
- . possible_values ( & [ "pin_mappings" , "features " ] )
56
+ . possible_values ( & [ "features" , " pin_mappings", "eeprom_sizes " ] )
51
57
. required ( true ) ,
52
58
)
53
59
. arg (
@@ -62,8 +68,9 @@ fn main() -> Result<(), String> {
62
68
let db_dir = Path :: new ( args. value_of ( "db_dir" ) . unwrap ( ) ) ;
63
69
let mcu_family = args. value_of ( "mcu_family" ) . unwrap ( ) ;
64
70
let generate = match args. value_of ( "generate" ) . unwrap ( ) {
65
- "pin_mappings" => GenerateTarget :: PinMappings ,
66
71
"features" => GenerateTarget :: Features ,
72
+ "pin_mappings" => GenerateTarget :: PinMappings ,
73
+ "eeprom_sizes" => GenerateTarget :: EepromSizes ,
67
74
_ => unreachable ! ( ) ,
68
75
} ;
69
76
@@ -79,39 +86,68 @@ fn main() -> Result<(), String> {
79
86
80
87
// MCU map
81
88
//
89
+ // This maps a MCU ref name to the corresponding `mcu::Mcu` instance.
90
+ let mut mcu_map: HashMap < String , mcu:: Mcu > = HashMap :: new ( ) ;
91
+
92
+ // GPIO map
93
+ //
82
94
// The keys of this map are GPIO peripheral version strings (e.g.
83
95
// "STM32L051_gpio_v1_0"), while the value is a Vec of MCU ref names.
84
96
let mut mcu_gpio_map: HashMap < String , Vec < String > > = HashMap :: new ( ) ;
85
97
86
98
// Package map
87
99
//
88
- // The keys of this map are MCU ref names, the values are package names
89
- // (e.g. ).
100
+ // The keys of this map are MCU ref names, the values are package names.
90
101
let mut mcu_package_map: HashMap < String , String > = HashMap :: new ( ) ;
91
102
103
+ // EEPROM size map
104
+ //
105
+ // The keys of this map are EEPROM sizes in KiB, the values are Vecs of MCU ref names.
106
+ let mut mcu_eeprom_size_map: HashMap < u32 , Vec < String > > = HashMap :: new ( ) ;
107
+
108
+ // Iterate through subfamilies, then through MCUs. Fill the maps above with
109
+ // aggregated data.
92
110
for sf in family {
93
111
for mcu in sf {
112
+ // Load MCU data from the XML files
94
113
let mcu_dat = mcu:: Mcu :: load ( & db_dir, & mcu. name )
95
114
. map_err ( |e| format ! ( "Could not load MCU data: {}" , e) ) ?;
96
115
116
+ // Fill GPIO map
97
117
let gpio_version = mcu_dat. get_ip ( "GPIO" ) . unwrap ( ) . get_version ( ) . to_string ( ) ;
98
118
mcu_gpio_map
99
119
. entry ( gpio_version)
100
120
. or_insert ( vec ! [ ] )
101
121
. push ( mcu. ref_name . clone ( ) ) ;
102
122
123
+ // Fill package map
103
124
if mcu_family == "STM32L0" {
104
125
// The stm32l0xx-hal has package based features
105
126
mcu_package_map. insert ( mcu. ref_name . clone ( ) , mcu. package_name . clone ( ) ) ;
106
127
}
128
+
129
+ // Fill EEPROM size map
130
+ if let Some ( size) = mcu_dat. get_eeprom_size_kib ( ) {
131
+ mcu_eeprom_size_map
132
+ . entry ( size)
133
+ . or_insert ( vec ! [ ] )
134
+ . push ( mcu. ref_name . clone ( ) ) ;
135
+ }
136
+
137
+ mcu_map. insert ( mcu. ref_name . clone ( ) , mcu_dat) ;
107
138
}
108
139
}
109
140
110
141
match generate {
111
- GenerateTarget :: Features => {
112
- generate_features ( & mcu_gpio_map, & mcu_package_map, & mcu_family) ?
113
- }
142
+ GenerateTarget :: Features => generate_features (
143
+ & mcu_map,
144
+ & mcu_gpio_map,
145
+ & mcu_package_map,
146
+ & mcu_eeprom_size_map,
147
+ & mcu_family,
148
+ ) ?,
114
149
GenerateTarget :: PinMappings => generate_pin_mappings ( & mcu_gpio_map, & db_dir) ?,
150
+ GenerateTarget :: EepromSizes => generate_eeprom_sizes ( & mcu_eeprom_size_map) ?,
115
151
} ;
116
152
117
153
Ok ( ( ) )
@@ -132,31 +168,67 @@ lazy_static! {
132
168
} ;
133
169
}
134
170
135
- /// Print the IO features, followed by MCU features that act purely as aliases
136
- /// for the IO features.
171
+ /// Generate all Cargo features
137
172
///
138
- /// Both lists are sorted alphanumerically.
173
+ /// Feature categories:
174
+ ///
175
+ /// - IO features (`io-*`)
176
+ /// - EEPROM features (`eeprom-*`)
177
+ ///
178
+ /// Finally, the MCU features are printed, they act purely as aliases for the
179
+ /// other features.
139
180
fn generate_features (
181
+ mcu_map : & HashMap < String , mcu:: Mcu > ,
140
182
mcu_gpio_map : & HashMap < String , Vec < String > > ,
141
183
mcu_package_map : & HashMap < String , String > ,
184
+ mcu_eeprom_size_map : & HashMap < u32 , Vec < String > > ,
142
185
mcu_family : & str ,
143
186
) -> Result < ( ) , String > {
144
- let mut main_features = mcu_gpio_map
187
+ // IO features
188
+ let mut io_features = mcu_gpio_map
145
189
. keys ( )
146
190
. map ( |gpio| gpio_version_to_feature ( gpio) )
147
191
. collect :: < Result < Vec < String > , String > > ( ) ?;
148
- main_features. sort ( ) ;
192
+ io_features. sort ( ) ;
193
+ println ! ( "# Features based on the GPIO peripheral version" ) ;
194
+ println ! ( "# This determines the pin function mapping of the MCU" ) ;
195
+ for feature in io_features {
196
+ println ! ( "{} = []" , feature) ;
197
+ }
198
+ println ! ( ) ;
149
199
200
+ // EEPROM sizes
201
+ let mut eeprom_sizes = mcu_eeprom_size_map. keys ( ) . collect :: < Vec < _ > > ( ) ;
202
+ eeprom_sizes. sort ( ) ;
203
+ println ! ( "# Features based on EEPROM size (in KiB)" ) ;
204
+ for size in eeprom_sizes {
205
+ println ! ( "{} = []" , eeprom_size_to_feature( * size) ) ;
206
+ }
207
+ println ! ( ) ;
208
+
209
+ // Physical packages
210
+ if !mcu_package_map. is_empty ( ) {
211
+ println ! ( "# Physical packages" ) ;
212
+ let mut packages = mcu_package_map
213
+ . values ( )
214
+ . map ( |v| v. to_lowercase ( ) )
215
+ . collect :: < Vec < _ > > ( ) ;
216
+ packages. sort_by ( |a, b| compare_str ( a, b) ) ;
217
+ packages. dedup ( ) ;
218
+ for pkg in packages {
219
+ println ! ( "{} = []" , pkg) ;
220
+ }
221
+ println ! ( ) ;
222
+ }
223
+
224
+ // MCU features
150
225
let mut mcu_aliases = vec ! [ ] ;
151
226
for ( gpio, mcu_list) in mcu_gpio_map {
152
227
let gpio_version_feature = gpio_version_to_feature ( gpio) . unwrap ( ) ;
153
228
for mcu in mcu_list {
154
229
let mut dependencies = vec ! [ ] ;
155
230
156
- // GPIO version feature
157
- dependencies. push ( gpio_version_feature. clone ( ) ) ;
158
-
159
- // Additional dependencies
231
+ // Static feature dependencies
160
232
if let Some ( family) = FEATURE_DEPENDENCIES . get ( mcu_family) {
161
233
for ( pattern, feature) in family {
162
234
if Regex :: new ( pattern) . unwrap ( ) . is_match ( & mcu) {
@@ -171,10 +243,17 @@ fn generate_features(
171
243
dependencies. push ( package. to_lowercase ( ) ) ;
172
244
}
173
245
174
- let mcu_feature = format ! ( "mcu-{}" , mcu) ;
246
+ // GPIO version feature
247
+ dependencies. push ( gpio_version_feature. clone ( ) ) ;
248
+
249
+ // EEPROM size
250
+ if let Some ( size) = mcu_map. get ( mcu) . unwrap ( ) . get_eeprom_size_kib ( ) {
251
+ dependencies. push ( eeprom_size_to_feature ( size) ) ;
252
+ }
253
+
175
254
mcu_aliases. push ( format ! (
176
- "{} = [{}]" ,
177
- mcu_feature ,
255
+ "mcu- {} = [{}]" ,
256
+ mcu ,
178
257
& dependencies. iter( ) . map( |val| format!( "\" {}\" " , val) ) . fold(
179
258
String :: new( ) ,
180
259
|mut acc, x| {
@@ -189,27 +268,12 @@ fn generate_features(
189
268
}
190
269
}
191
270
mcu_aliases. sort ( ) ;
192
-
193
- println ! ( "# Features based on the GPIO peripheral version" ) ;
194
- println ! ( "# This determines the pin function mapping of the MCU" ) ;
195
- for feature in main_features {
196
- println ! ( "{} = []" , feature) ;
197
- }
198
- println ! ( ) ;
199
- if !mcu_package_map. is_empty ( ) {
200
- println ! ( "# Physical packages" ) ;
201
- let mut packages = mcu_package_map
202
- . values ( )
203
- . map ( |v| v. to_lowercase ( ) )
204
- . collect :: < Vec < _ > > ( ) ;
205
- packages. sort_by ( |a, b| compare_str ( a, b) ) ;
206
- packages. dedup ( ) ;
207
- for pkg in packages {
208
- println ! ( "{} = []" , pkg) ;
209
- }
210
- println ! ( ) ;
211
- }
212
- println ! ( "# MCUs" ) ;
271
+ println ! ( "# MCU aliases" ) ;
272
+ println ! ( "#" ) ;
273
+ println ! ( "# Note: These are just aliases, they should not be used to directly feature gate" ) ;
274
+ println ! (
275
+ "# functionality in the HAL! However, user code should usually depend on a MCU alias."
276
+ ) ;
213
277
for alias in mcu_aliases {
214
278
println ! ( "{}" , alias) ;
215
279
}
@@ -235,6 +299,16 @@ fn generate_pin_mappings(
235
299
Ok ( ( ) )
236
300
}
237
301
302
+ /// Generate code containing the EEPROM size.
303
+ fn generate_eeprom_sizes ( mcu_eeprom_size_map : & HashMap < u32 , Vec < String > > ) -> Result < ( ) , String > {
304
+ println ! ( "// EEPROM sizes in KiB, generated with cube-parse" ) ;
305
+ for size in mcu_eeprom_size_map. keys ( ) {
306
+ println ! ( "#[cfg({})]" , eeprom_size_to_feature( * size) ) ;
307
+ println ! ( "const EEPROM_SIZE_KIB: u32 = {};" , size) ;
308
+ }
309
+ Ok ( ( ) )
310
+ }
311
+
238
312
fn render_pin_modes ( ip : & internal_peripheral:: IpGPIO ) {
239
313
let mut pin_map: HashMap < String , Vec < String > > = HashMap :: new ( ) ;
240
314
0 commit comments