50
50
51
51
ALL_PLATFORMS = {
52
52
# classic Arduino AVR
53
- "uno" : "arduino:avr:uno" ,
54
- "leonardo" : "arduino:avr:leonardo" ,
55
- "mega2560" : "arduino:avr:mega:cpu=atmega2560" ,
53
+ "uno" : [ "arduino:avr:uno" , None ] ,
54
+ "leonardo" : [ "arduino:avr:leonardo" , None ] ,
55
+ "mega2560" : [ "arduino:avr:mega:cpu=atmega2560" , None ] ,
56
56
# Arduino SAMD
57
- "zero" : "arduino:samd:arduino_zero_native" ,
58
- "cpx" : "arduino:samd:adafruit_circuitplayground_m0" ,
57
+ "zero" : [ "arduino:samd:arduino_zero_native" , "0x68ed2b88" ] ,
58
+ "cpx" : [ "arduino:samd:adafruit_circuitplayground_m0" , "0x68ed2b88" ] ,
59
59
# Espressif
60
- "esp8266" : "esp8266:esp8266:huzzah:eesz=4M3M,xtal=80" ,
61
- "esp32" : "esp32:esp32:featheresp32:FlashFreq=80" ,
62
- "magtag" : "esp32:esp32:adafruit_magtag29_esp32s2" ,
63
- "funhouse" : "esp32:esp32:adafruit_funhouse_esp32s2" ,
64
- "metroesp32s2" : "esp32:esp32:adafruit_metro_esp32s2" ,
60
+ "esp8266" : [ "esp8266:esp8266:huzzah:eesz=4M3M,xtal=80" , "0x7eab61ed" ] ,
61
+ "esp32" : [ "esp32:esp32:featheresp32:FlashFreq=80" , "0x1c5f21b0" ] ,
62
+ "magtag" : [ "esp32:esp32:adafruit_magtag29_esp32s2" , "0xbfdd4eee" ] ,
63
+ "funhouse" : [ "esp32:esp32:adafruit_funhouse_esp32s2" , "0xbfdd4eee" ] ,
64
+ "metroesp32s2" : [ "esp32:esp32:adafruit_metro_esp32s2" , "0xbfdd4eee" ] ,
65
65
# Adafruit AVR
66
- "trinket_3v" : "adafruit:avr:trinket3" ,
67
- "trinket_5v" : "adafruit:avr:trinket5" ,
68
- "protrinket_3v" : "adafruit:avr:protrinket3" ,
69
- "protrinket_5v" : "adafruit:avr:protrinket5" ,
70
- "gemma" : "adafruit:avr:gemma" ,
71
- "flora" : "adafruit:avr:flora8" ,
72
- "feather32u4" : "adafruit:avr:feather32u4" ,
73
- "cpc" : "arduino:avr:circuitplay32u4cat" ,
66
+ "trinket_3v" : [ "adafruit:avr:trinket3" , None ] ,
67
+ "trinket_5v" : [ "adafruit:avr:trinket5" , None ] ,
68
+ "protrinket_3v" : [ "adafruit:avr:protrinket3" , None ] ,
69
+ "protrinket_5v" : [ "adafruit:avr:protrinket5" , None ] ,
70
+ "gemma" : [ "adafruit:avr:gemma" , None ] ,
71
+ "flora" : [ "adafruit:avr:flora8" , None ] ,
72
+ "feather32u4" : [ "adafruit:avr:feather32u4" , None ] ,
73
+ "cpc" : [ "arduino:avr:circuitplay32u4cat" , None ] ,
74
74
# Adafruit SAMD
75
- "gemma_m0" : "adafruit:samd:adafruit_gemma_m0" ,
76
- "trinket_m0" : "adafruit:samd:adafruit_trinket_m0" ,
77
- "feather_m0_express" : "adafruit:samd:adafruit_feather_m0_express" ,
78
- "feather_m4_can" : "adafruit:samd:adafruit_feather_m4_can:speed=120" ,
79
- "feather_m4_can_tinyusb" : "adafruit:samd:adafruit_feather_m4_can:speed=120,usbstack=tinyusb" ,
80
- "metro_m0" : "adafruit:samd:adafruit_metro_m0" ,
81
- "metro_m0_tinyusb" : "adafruit:samd:adafruit_metro_m0:usbstack=tinyusb" ,
82
- "metro_m4" : "adafruit:samd:adafruit_metro_m4:speed=120" ,
83
- "metro_m4_tinyusb" : "adafruit:samd:adafruit_metro_m4:speed=120,usbstack=tinyusb" ,
84
- "metro_m4_airliftlite" : "adafruit:samd:adafruit_metro_m4_airliftlite:speed=120" ,
85
- "metro_m4_airliftlite_tinyusb" : "adafruit:samd:adafruit_metro_m4_airliftlite:speed=120,usbstack=tinyusb" ,
86
- "pybadge" : "adafruit:samd:adafruit_pybadge_m4:speed=120" ,
87
- "pybadge_tinyusb" : "adafruit:samd:adafruit_pybadge_m4:speed=120,usbstack=tinyusb" ,
88
- "pygamer" : "adafruit:samd:adafruit_pygamer_m4:speed=120" ,
75
+ "gemma_m0" : [ "adafruit:samd:adafruit_gemma_m0" , "0x68ed2b88" ] ,
76
+ "trinket_m0" : [ "adafruit:samd:adafruit_trinket_m0" , "0x68ed2b88" ] ,
77
+ "feather_m0_express" : [ "adafruit:samd:adafruit_feather_m0_express" , "0x68ed2b88" ] ,
78
+ "feather_m4_can" : [ "adafruit:samd:adafruit_feather_m4_can:speed=120" , "0x68ed2b88" ] ,
79
+ "feather_m4_can_tinyusb" : [ "adafruit:samd:adafruit_feather_m4_can:speed=120,usbstack=tinyusb" , "0x68ed2b88" ] ,
80
+ "metro_m0" : [ "adafruit:samd:adafruit_metro_m0" , "0x68ed2b88" ] ,
81
+ "metro_m0_tinyusb" : [ "adafruit:samd:adafruit_metro_m0:usbstack=tinyusb" , "0x68ed2b88" ] ,
82
+ "metro_m4" : [ "adafruit:samd:adafruit_metro_m4:speed=120" , "0x55114460" ] ,
83
+ "metro_m4_tinyusb" : [ "adafruit:samd:adafruit_metro_m4:speed=120,usbstack=tinyusb" , "0x55114460" ] ,
84
+ "metro_m4_airliftlite" : [ "adafruit:samd:adafruit_metro_m4_airliftlite:speed=120" , "0x55114460" ] ,
85
+ "metro_m4_airliftlite_tinyusb" : [ "adafruit:samd:adafruit_metro_m4_airliftlite:speed=120,usbstack=tinyusb" , "0x55114460" ] ,
86
+ "pybadge" : [ "adafruit:samd:adafruit_pybadge_m4:speed=120" , "0x55114460" ] ,
87
+ "pybadge_tinyusb" : [ "adafruit:samd:adafruit_pybadge_m4:speed=120,usbstack=tinyusb" , "0x55114460" ] ,
88
+ "pygamer" : [ "adafruit:samd:adafruit_pygamer_m4:speed=120" , "0x55114460" ] ,
89
89
"hallowing_m0" : "adafruit:samd:adafruit_hallowing" ,
90
- "hallowing_m4" : "adafruit:samd:adafruit_hallowing_m4:speed=120" ,
91
- "hallowing_m4_tinyusb" : "adafruit:samd:adafruit_hallowing_m4:speed=120,usbstack=tinyusb" ,
92
- "neotrellis_m4" : "adafruit:samd:adafruit_trellis_m4:speed=120" ,
93
- "monster_m4sk" : "adafruit:samd:adafruit_monster_m4sk:speed=120" ,
94
- "monster_m4sk_tinyusb" : "adafruit:samd:adafruit_monster_m4sk:speed=120,usbstack=tinyusb" ,
95
- "pyportal" : "adafruit:samd:adafruit_pyportal_m4:speed=120" ,
96
- "pyportal_tinyusb" : "adafruit:samd:adafruit_pyportal_m4:speed=120,usbstack=tinyusb" ,
97
- "pyportal_titano" : "adafruit:samd:adafruit_pyportal_m4_titano:speed=120" ,
98
- "pyportal_titano_tinyusb" : "adafruit:samd:adafruit_pyportal_m4_titano:speed=120,usbstack=tinyusb" ,
99
- "cpx_ada" : "adafruit:samd:adafruit_circuitplayground_m0" ,
100
- "grand_central" : "adafruit:samd:adafruit_grandcentral_m4:speed=120" ,
101
- "grand_central_tinyusb" : "adafruit:samd:adafruit_grandcentral_m4:speed=120,usbstack=tinyusb" ,
102
- "matrixportal" : "adafruit:samd:adafruit_matrixportal_m4:speed=120" ,
103
- "matrixportal_tinyusb" : "adafruit:samd:adafruit_matrixportal_m4:speed=120,usbstack=tinyusb" ,
104
- "neotrinkey_m0" : "adafruit:samd:adafruit_neotrinkey_m0" ,
105
- "rotarytrinkey_m0" : "adafruit:samd:adafruit_rotarytrinkey_m0" ,
106
- "neokeytrinkey_m0" : "adafruit:samd:adafruit_neokeytrinkey_m0" ,
107
- "slidetrinkey_m0" : "adafruit:samd:adafruit_slidetrinkey_m0" ,
108
- "proxlighttrinkey_m0" : "adafruit:samd:adafruit_proxlighttrinkey_m0" ,
90
+ "hallowing_m4" : [ "adafruit:samd:adafruit_hallowing_m4:speed=120" , "0x55114460" ] ,
91
+ "hallowing_m4_tinyusb" : [ "adafruit:samd:adafruit_hallowing_m4:speed=120,usbstack=tinyusb" , "0x55114460" ] ,
92
+ "neotrellis_m4" : [ "adafruit:samd:adafruit_trellis_m4:speed=120" , "0x55114460" ] ,
93
+ "monster_m4sk" : [ "adafruit:samd:adafruit_monster_m4sk:speed=120" , "0x55114460" ] ,
94
+ "monster_m4sk_tinyusb" : [ "adafruit:samd:adafruit_monster_m4sk:speed=120,usbstack=tinyusb" , "0x55114460" ] ,
95
+ "pyportal" : [ "adafruit:samd:adafruit_pyportal_m4:speed=120" , "0x55114460" ] ,
96
+ "pyportal_tinyusb" : [ "adafruit:samd:adafruit_pyportal_m4:speed=120,usbstack=tinyusb" , "0x55114460" ] ,
97
+ "pyportal_titano" : [ "adafruit:samd:adafruit_pyportal_m4_titano:speed=120" , "0x55114460" ] ,
98
+ "pyportal_titano_tinyusb" : [ "adafruit:samd:adafruit_pyportal_m4_titano:speed=120,usbstack=tinyusb" , "0x55114460" ] ,
99
+ "cpx_ada" : [ "adafruit:samd:adafruit_circuitplayground_m0" , "0x68ed2b88" ] ,
100
+ "grand_central" : [ "adafruit:samd:adafruit_grandcentral_m4:speed=120" , "0x55114460" ] ,
101
+ "grand_central_tinyusb" : [ "adafruit:samd:adafruit_grandcentral_m4:speed=120,usbstack=tinyusb" , "0x55114460" ] ,
102
+ "matrixportal" : [ "adafruit:samd:adafruit_matrixportal_m4:speed=120" , "0x55114460" ] ,
103
+ "matrixportal_tinyusb" : [ "adafruit:samd:adafruit_matrixportal_m4:speed=120,usbstack=tinyusb" , "0x55114460" ] ,
104
+ "neotrinkey_m0" : [ "adafruit:samd:adafruit_neotrinkey_m0" , "0x68ed2b88" ] ,
105
+ "rotarytrinkey_m0" : [ "adafruit:samd:adafruit_rotarytrinkey_m0" , "0x68ed2b88" ] ,
106
+ "neokeytrinkey_m0" : [ "adafruit:samd:adafruit_neokeytrinkey_m0" , "0x68ed2b88" ] ,
107
+ "slidetrinkey_m0" : [ "adafruit:samd:adafruit_slidetrinkey_m0" , "0x68ed2b88" ] ,
108
+ "proxlighttrinkey_m0" : [ "adafruit:samd:adafruit_proxlighttrinkey_m0" , "0x68ed2b88" ] ,
109
109
# Arduino nRF
110
- "microbit" : "sandeepmistry:nRF5:BBCmicrobit:softdevice=s110" ,
110
+ "microbit" : [ "sandeepmistry:nRF5:BBCmicrobit:softdevice=s110" , None ] ,
111
111
# Adafruit nRF
112
- "nrf52832" : "adafruit:nrf52:feather52832:softdevice=s132v6,debug=l0" ,
113
- "nrf52840" : "adafruit:nrf52:feather52840:softdevice=s140v6,debug=l0" ,
114
- "cpb" : "adafruit:nrf52:cplaynrf52840:softdevice=s140v6,debug=l0" ,
115
- "clue" : "adafruit:nrf52:cluenrf52840:softdevice=s140v6,debug=l0" ,
112
+ "nrf52832" : [ "adafruit:nrf52:feather52832:softdevice=s132v6,debug=l0" , None ] ,
113
+ "nrf52840" : [ "adafruit:nrf52:feather52840:softdevice=s140v6,debug=l0" , "0xada52840" ] ,
114
+ "cpb" : [ "adafruit:nrf52:cplaynrf52840:softdevice=s140v6,debug=l0" , "0xada52840" ] ,
115
+ "clue" : [ "adafruit:nrf52:cluenrf52840:softdevice=s140v6,debug=l0" , "0xada52840" ] ,
116
116
# RP2040 (Philhower)
117
- "pico_rp2040" : "rp2040:rp2040:rpipico:freq=125,flash=2097152_0" ,
118
- "pico_rp2040_tinyusb" : "rp2040:rp2040:rpipico:flash=2097152_0,freq=125,dbgport=Disabled,dbglvl=None,usbstack=tinyusb" ,
119
- "feather_rp2040" : "rp2040:rp2040:adafruitfeather:freq=125,flash=8388608_0" ,
120
- "feather_rp2040_tinyusb" : "rp2040:rp2040:adafruit_feather:flash=8388608_0,freq=125,dbgport=Disabled,dbglvl=None,usbstack=tinyusb" ,
121
- "qt2040_trinkey" : "rp2040:rp2040:adafruit_trinkeyrp2040qt:freq=125,flash=8388608_0" ,
122
- "qt2040_trinkey_tinyusb" : "rp2040:rp2040:adafruit_trinkeyrp2040qt:flash=8388608_0,freq=125,dbgport=Disabled,dbglvl=None,usbstack=tinyusb" ,
117
+ "pico_rp2040" : [ "rp2040:rp2040:rpipico:freq=125,flash=2097152_0" , "0xe48bff56" ] ,
118
+ "pico_rp2040_tinyusb" : [ "rp2040:rp2040:rpipico:flash=2097152_0,freq=125,dbgport=Disabled,dbglvl=None,usbstack=tinyusb" , "0xe48bff56" ] ,
119
+ "feather_rp2040" : [ "rp2040:rp2040:adafruitfeather:freq=125,flash=8388608_0" , "0xe48bff56" ] ,
120
+ "feather_rp2040_tinyusb" : [ "rp2040:rp2040:adafruit_feather:flash=8388608_0,freq=125,dbgport=Disabled,dbglvl=None,usbstack=tinyusb" , "0xe48bff56" ] ,
121
+ "qt2040_trinkey" : [ "rp2040:rp2040:adafruit_trinkeyrp2040qt:freq=125,flash=8388608_0" , "0xe48bff56" ] ,
122
+ "qt2040_trinkey_tinyusb" : [ "rp2040:rp2040:adafruit_trinkeyrp2040qt:flash=8388608_0,freq=125,dbgport=Disabled,dbglvl=None,usbstack=tinyusb" , "0xe48bff56" ] ,
123
123
# Attiny8xy (SpenceKonde)
124
- "attiny817" : "megaTinyCore:megaavr:atxy7:chip=817" ,
125
- "attiny816" : "megaTinyCore:megaavr:atxy6:chip=816" ,
126
- "attiny807" : "megaTinyCore:megaavr:atxy7:chip=807" ,
127
- "attiny806" : "megaTinyCore:megaavr:atxy6:chip=806" ,
124
+ "attiny817" : [ "megaTinyCore:megaavr:atxy7:chip=817" , None ] ,
125
+ "attiny816" : [ "megaTinyCore:megaavr:atxy6:chip=816" , None ] ,
126
+ "attiny807" : [ "megaTinyCore:megaavr:atxy7:chip=807" , None ] ,
127
+ "attiny806" : [ "megaTinyCore:megaavr:atxy6:chip=806" , None ] ,
128
128
# groupings
129
129
"main_platforms" : ("uno" , "leonardo" , "mega2560" , "zero" ,
130
130
"esp8266" , "esp32" , "metro_m4" , "trinket_m0" ),
131
131
"arcada_platforms" : ("pybadge" , "pygamer" , "hallowing_m4" ,
132
132
"cpb" , "cpx_ada" ),
133
+ "wippersnapper_platforms" : ("metro_m4_airliftlite_tinyusb" , "pyportal_tinyusb" ),
133
134
"rp2040_platforms" : ("pico_rp2040" , "feather_rp2040" )
134
135
}
135
136
@@ -211,12 +212,38 @@ def run_or_die(cmd, error):
211
212
212
213
print ("Libraries installed: " , glob .glob (os .environ ['HOME' ]+ '/Arduino/libraries/*' ))
213
214
214
- # link our library folder to the arduino libraries folder
215
- if not IS_LEARNING_SYS :
216
- try :
217
- os .symlink (BUILD_DIR , os .environ ['HOME' ]+ '/Arduino/libraries/' + os .path .basename (BUILD_DIR ))
218
- except FileExistsError :
219
- pass
215
+ ################################ UF2 Utils.
216
+
217
+ def glob1 (pattern ):
218
+ result = glob .glob (pattern )
219
+ if len (result ) != 1 :
220
+ raise RuntimeError (f"Required pattern { pattern } to match exactly 1 file, got { result } " )
221
+ return result [0 ]
222
+
223
+ def generate_uf2 (example_path ):
224
+ """Generates a .uf2 file from a .bin or .hex file.
225
+ :param str example_path: A path to the compiled .bin or .hex file.
226
+ """
227
+ if ALL_PLATFORMS [platform ][1 ] == None :
228
+ return False
229
+ # Convert .hex to .uf2
230
+ family_id = ALL_PLATFORMS [platform ][1 ]
231
+ cli_build_path = "build/*.*." + fqbn .split (':' )[2 ] + "/*.hex"
232
+ input_file = glob1 (os .path .join (example_path , cli_build_path ))
233
+ output_file = os .path .splitext (input_file )[0 ] + ".uf2"
234
+ cmd = ['python3' , 'uf2conv.py' , input_file , '-c' , '-f' , family_id , '-o' , output_file ]
235
+ proc = subprocess .Popen (cmd , stdout = subprocess .PIPE , stderr = subprocess .PIPE )
236
+ r = proc .wait (timeout = 60 )
237
+ out = proc .stdout .read ()
238
+ err = proc .stderr .read ()
239
+ if r == 0 and not err :
240
+ ColorPrint .print_pass (CHECK )
241
+ else :
242
+ ColorPrint .print_fail (CROSS )
243
+ ColorPrint .print_fail (out .decode ("utf-8" ))
244
+ ColorPrint .print_fail (err .decode ("utf-8" ))
245
+ return False
246
+ return True
220
247
221
248
################################ Test platforms
222
249
platforms = []
@@ -225,9 +252,9 @@ def run_or_die(cmd, error):
225
252
# expand groups:
226
253
for arg in sys .argv [1 :]:
227
254
platform = ALL_PLATFORMS .get (arg , None )
228
- if isinstance (platform , str ):
255
+ if isinstance (platform , list ):
229
256
platforms .append (arg )
230
- elif isinstance (platform , collections . abc . Iterable ):
257
+ elif isinstance (platform , tuple ):
231
258
for p in platform :
232
259
platforms .append (p )
233
260
else :
@@ -248,15 +275,35 @@ def test_examples_in_folder(folderpath):
248
275
# check if we should SKIP
249
276
skipfilename = folderpath + "/." + platform + ".test.skip"
250
277
onlyfilename = folderpath + "/." + platform + ".test.only"
278
+ # check if we should GENERATE UF2
279
+ gen_file_name = folderpath + "/." + platform + ".generate"
251
280
if os .path .exists (skipfilename ):
252
281
ColorPrint .print_warn ("skipping" )
253
282
continue
254
283
if glob .glob (folderpath + "/.*.test.only" ) and not os .path .exists (onlyfilename ):
255
284
ColorPrint .print_warn ("skipping" )
256
285
continue
286
+ if os .path .exists (gen_file_name ):
287
+ ColorPrint .print_info ("Generating UF2 after compile." )
288
+ # Download uf2conv.py and dependency if we don't already have it
289
+ cmd = "wget -nc --no-check-certificate http://raw.githubusercontent.com/microsoft/uf2/master/utils/uf2families.json https://raw.githubusercontent.com/microsoft/uf2/master/utils/uf2conv.py"
290
+ proc = subprocess .Popen (cmd , stdout = subprocess .PIPE , stderr = subprocess .PIPE , shell = True )
291
+ r = proc .wait (timeout = 60 )
292
+ out = proc .stdout .read ()
293
+ if r != 0 :
294
+ ColorPrint .print_fail ("Failed to download UF2 Utils!" )
295
+ ColorPrint .print_fail (out .decode ("utf-8" ))
296
+ ColorPrint .print_fail (err .decode ("utf-8" ))
297
+ continue
298
+ # Create a uf2 directory if doesn't exist
299
+ if not os .path .isdir ("uf2" ):
300
+ os .mkdir ("uf2" )
257
301
258
302
if BUILD_WARN :
259
- cmd = ['arduino-cli' , 'compile' , '--warnings' , 'all' , '--fqbn' , fqbn , examplepath ]
303
+ if os .path .exists (gen_file_name ):
304
+ cmd = ['arduino-cli' , 'compile' , '--warnings' , 'all' , '--fqbn' , fqbn , '-e' , examplepath ]
305
+ else :
306
+ cmd = ['arduino-cli' , 'compile' , '--warnings' , 'all' , '--fqbn' , fqbn , examplepath ]
260
307
else :
261
308
cmd = ['arduino-cli' , 'compile' , '--warnings' , 'none' , '--export-binaries' , '--fqbn' , fqbn , examplepath ]
262
309
proc = subprocess .Popen (cmd , stdout = subprocess .PIPE ,
@@ -269,6 +316,9 @@ def test_examples_in_folder(folderpath):
269
316
if err :
270
317
# also print out warning message
271
318
ColorPrint .print_fail (err .decode ("utf-8" ))
319
+ if os .path .exists (gen_file_name ):
320
+ ColorPrint .print_info ("Generating UF2..." )
321
+ success = generate_uf2 (folderpath )
272
322
else :
273
323
ColorPrint .print_fail (CROSS )
274
324
ColorPrint .print_fail (out .decode ("utf-8" ))
@@ -315,7 +365,7 @@ def test_examples_in_learningrepo(folderpath):
315
365
316
366
317
367
for platform in platforms :
318
- fqbn = ALL_PLATFORMS [platform ]
368
+ fqbn = ALL_PLATFORMS [platform ][ 0 ]
319
369
print ('#' * 80 )
320
370
ColorPrint .print_info ("SWITCHING TO " + fqbn )
321
371
install_platform (":" .join (fqbn .split (':' , 2 )[0 :2 ])) # take only first two elements
0 commit comments