1
- #!/usr/bin/python
2
-
1
+ #!/usr/bin/env python3
3
2
import sys
4
3
import struct
5
4
import subprocess
8
7
import os .path
9
8
import argparse
10
9
10
+
11
11
UF2_MAGIC_START0 = 0x0A324655 # "UF2\n"
12
12
UF2_MAGIC_START1 = 0x9E5D5157 # Randomly selected
13
13
UF2_MAGIC_END = 0x0AB16F30 # Ditto
26
26
appstartaddr = 0x2000
27
27
familyid = 0x0
28
28
29
- def isUF2 (buf ):
29
+
30
+ def is_uf2 (buf ):
30
31
w = struct .unpack ("<II" , buf [0 :8 ])
31
32
return w [0 ] == UF2_MAGIC_START0 and w [1 ] == UF2_MAGIC_START1
32
33
33
- def isHEX (buf ):
34
- w = buf [0 :30 ]
35
- if w [0 ] == ':' and re .match ("^[:0-9a-fA-F\r \n ]+$" , buf ):
34
+ def is_hex (buf ):
35
+ try :
36
+ w = buf [0 :30 ].decode ("utf-8" )
37
+ except UnicodeDecodeError :
38
+ return False
39
+ if w [0 ] == ':' and re .match (b"^[:0-9a-fA-F\r \n ]+$" , buf ):
36
40
return True
37
41
return False
38
42
39
- def convertFromUF2 (buf ):
43
+ def convert_from_uf2 (buf ):
40
44
global appstartaddr
41
- numblocks = len (buf ) / 512
45
+ numblocks = len (buf ) // 512
42
46
curraddr = None
43
- outp = ""
44
- for blockno in range (0 , numblocks ):
47
+ outp = b ""
48
+ for blockno in range (numblocks ):
45
49
ptr = blockno * 512
46
50
block = buf [ptr :ptr + 512 ]
47
- hd = struct .unpack ("<IIIIIIII" , block [0 :32 ])
51
+ hd = struct .unpack (b "<IIIIIIII" , block [0 :32 ])
48
52
if hd [0 ] != UF2_MAGIC_START0 or hd [1 ] != UF2_MAGIC_START1 :
49
- print "Skipping block at " + ptr + "; bad magic"
53
+ print ( "Skipping block at " + ptr + "; bad magic" )
50
54
continue
51
55
if hd [2 ] & 1 :
52
56
# NO-flash flag set; skip block
@@ -67,57 +71,63 @@ def convertFromUF2(buf):
67
71
assert False , "Non-word padding size at " + ptr
68
72
while padding > 0 :
69
73
padding -= 4
70
- outp += "\x00 \x00 \x00 \x00 "
74
+ outp += b "\x00 \x00 \x00 \x00 "
71
75
outp += block [32 : 32 + datalen ]
72
76
curraddr = newaddr + datalen
73
77
return outp
74
78
75
- def convertToUF2 (fileContent ):
79
+ def convert_to_carray (file_content ):
80
+ outp = "const unsigned char bindata[] __attribute__((aligned(16))) = {"
81
+ for i in range (len (file_content )):
82
+ if i % 16 == 0 :
83
+ outp += "\n "
84
+ outp += "0x%02x, " % ord (file_content [i ])
85
+ outp += "\n };\n "
86
+ return outp
87
+
88
+ def convert_to_uf2 (file_content ):
76
89
global familyid
77
- datapadding = ""
90
+ datapadding = b ""
78
91
while len (datapadding ) < 512 - 256 - 32 - 4 :
79
- datapadding += "\x00 \x00 \x00 \x00 "
80
- numblocks = (len (fileContent ) + 255 ) / 256
81
- outp = ""
82
- for blockno in range (0 , numblocks ):
92
+ datapadding += b "\x00 \x00 \x00 \x00 "
93
+ numblocks = (len (file_content ) + 255 ) / / 256
94
+ outp = b ""
95
+ for blockno in range (numblocks ):
83
96
ptr = 256 * blockno
84
- chunk = fileContent [ptr :ptr + 256 ]
97
+ chunk = file_content [ptr :ptr + 256 ]
85
98
flags = 0x0
86
99
if familyid :
87
100
flags |= 0x2000
88
- hd = struct .pack ("<IIIIIIII" ,
89
- UF2_MAGIC_START0 , UF2_MAGIC_START1 ,
101
+ hd = struct .pack (b "<IIIIIIII" ,
102
+ UF2_MAGIC_START0 , UF2_MAGIC_START1 ,
90
103
flags , ptr + appstartaddr , 256 , blockno , numblocks , familyid )
91
104
while len (chunk ) < 256 :
92
- chunk += "\x00 "
93
- block = hd + chunk + datapadding + struct .pack ("<I" , UF2_MAGIC_END )
105
+ chunk += b "\x00 "
106
+ block = hd + chunk + datapadding + struct .pack (b "<I" , UF2_MAGIC_END )
94
107
assert len (block ) == 512
95
108
outp += block
96
109
return outp
97
110
98
111
class Block :
99
112
def __init__ (self , addr ):
100
113
self .addr = addr
101
- self .bytes = []
102
- for i in range (0 , 256 ):
103
- self .bytes .append (0 )
114
+ self .bytes = bytearray (256 )
104
115
105
116
def encode (self , blockno , numblocks ):
106
117
global familyid
107
118
flags = 0x0
108
119
if familyid :
109
120
flags |= 0x2000
110
- hd = struct .pack ("<IIIIIIII" ,
111
- UF2_MAGIC_START0 , UF2_MAGIC_START1 ,
121
+ hd = struct .pack ("<IIIIIIII" ,
122
+ UF2_MAGIC_START0 , UF2_MAGIC_START1 ,
112
123
flags , self .addr , 256 , blockno , numblocks , familyid )
113
- for i in range (0 , 256 ):
114
- hd += chr (self .bytes [i ])
124
+ hd += self .bytes [0 :256 ]
115
125
while len (hd ) < 512 - 4 :
116
- hd += "\x00 "
126
+ hd += b "\x00 "
117
127
hd += struct .pack ("<I" , UF2_MAGIC_END )
118
128
return hd
119
-
120
- def convertFromHexToUF2 (buf ):
129
+
130
+ def convert_from_hex_to_uf2 (buf ):
121
131
global appstartaddr
122
132
appstartaddr = None
123
133
upper = 0
@@ -152,16 +162,17 @@ def convertFromHexToUF2(buf):
152
162
addr += 1
153
163
i += 1
154
164
numblocks = len (blocks )
155
- resfile = ""
165
+ resfile = b ""
156
166
for i in range (0 , numblocks ):
157
167
resfile += blocks [i ].encode (i , numblocks )
158
168
return resfile
159
169
160
-
161
- def getdrives ():
170
+ def get_drives ():
162
171
drives = []
163
172
if sys .platform == "win32" :
164
- r = subprocess .check_output (["wmic" , "PATH" , "Win32_LogicalDisk" , "get" , "DeviceID," , "VolumeName," , "FileSystem," , "DriveType" ])
173
+ r = subprocess .check_output (["wmic" , "PATH" , "Win32_LogicalDisk" ,
174
+ "get" , "DeviceID," , "VolumeName," ,
175
+ "FileSystem," , "DriveType" ])
165
176
for line in r .split ('\n ' ):
166
177
words = re .split ('\s+' , line )
167
178
if len (words ) >= 3 and words [1 ] == "2" and words [2 ] == "FAT" :
@@ -176,36 +187,41 @@ def getdrives():
176
187
rootpath = tmp
177
188
for d in os .listdir (rootpath ):
178
189
drives .append (os .path .join (rootpath , d ))
179
-
180
- def hasInfo (d ):
190
+
191
+
192
+ def has_info (d ):
181
193
try :
182
194
return os .path .isfile (d + INFO_FILE )
183
195
except :
184
196
return False
185
-
186
- return filter (hasInfo , drives )
187
197
188
- def boardID (path ):
198
+ return list (filter (has_info , drives ))
199
+
200
+
201
+ def board_id (path ):
189
202
with open (path + INFO_FILE , mode = 'r' ) as file :
190
- fileContent = file .read ()
191
- return re .search ("Board-ID: ([^\r \n ]*)" , fileContent ).group (1 )
192
-
193
- def listdrives ():
194
- for d in getdrives ():
195
- print d , boardID (d )
203
+ file_content = file .read ()
204
+ return re .search ("Board-ID: ([^\r \n ]*)" , file_content ).group (1 )
205
+
206
+
207
+ def list_drives ():
208
+ for d in get_drives ():
209
+ print (d , board_id (d ))
210
+
196
211
197
- def writeFile (name , buf ):
212
+ def write_file (name , buf ):
198
213
with open (name , "wb" ) as f :
199
214
f .write (buf )
200
- print "Wrote %d bytes to %s." % (len (buf ), name )
215
+ print ("Wrote %d bytes to %s." % (len (buf ), name ))
216
+
201
217
202
218
def main ():
203
219
global appstartaddr , familyid
204
220
def error (msg ):
205
- print msg
221
+ print ( msg )
206
222
sys .exit (1 )
207
223
parser = argparse .ArgumentParser (description = 'Convert to UF2 or flash directly.' )
208
- parser .add_argument ('input' , metavar = 'INPUT' , type = str , nargs = '?' ,
224
+ parser .add_argument ('input' , metavar = 'INPUT' , type = str , nargs = '?' ,
209
225
help = 'input file (HEX, BIN or UF2)' )
210
226
parser .add_argument ('-b' , '--base' , dest = 'base' , type = str ,
211
227
default = "0x2000" ,
@@ -221,6 +237,8 @@ def error(msg):
221
237
parser .add_argument ('-f' , '--family' , dest = 'family' , type = str ,
222
238
default = "0x0" ,
223
239
help = 'specify familyID - number or name (default: 0x0)' )
240
+ parser .add_argument ('-C' , '--carray' , action = 'store_true' ,
241
+ help = 'convert binary file to a C array, not UF2' )
224
242
args = parser .parse_args ()
225
243
appstartaddr = int (args .base , 0 )
226
244
@@ -233,38 +251,42 @@ def error(msg):
233
251
error ("Family ID needs to be a number or one of: " + ", " .join (families .keys ()))
234
252
235
253
if args .list :
236
- listdrives ()
254
+ list_drives ()
237
255
else :
238
256
if not args .input :
239
257
error ("Need input file" )
240
- with open (args .input , mode = 'rb' ) as file :
241
- inpbuf = file .read ()
242
- fromUF2 = isUF2 (inpbuf )
258
+ with open (args .input , mode = 'rb' ) as f :
259
+ inpbuf = f .read ()
260
+ from_uf2 = is_uf2 (inpbuf )
243
261
ext = "uf2"
244
- if fromUF2 :
245
- outbuf = convertFromUF2 (inpbuf )
262
+ if from_uf2 :
263
+ outbuf = convert_from_uf2 (inpbuf )
246
264
ext = "bin"
247
- elif isHEX (inpbuf ):
248
- outbuf = convertFromHexToUF2 (inpbuf )
265
+ elif is_hex (inpbuf ):
266
+ outbuf = convert_from_hex_to_uf2 (inpbuf .decode ("utf-8" ))
267
+ elif args .carray :
268
+ outbuf = convert_to_carray (inpbuf )
269
+ ext = "h"
249
270
else :
250
- outbuf = convertToUF2 (inpbuf )
251
- print "Converting to %s, output size: %d, start address: 0x%x" % ( ext , len ( outbuf ), appstartaddr )
252
-
271
+ outbuf = convert_to_uf2 (inpbuf )
272
+ print ( "Converting to %s, output size: %d, start address: 0x%x" %
273
+ ( ext , len ( outbuf ), appstartaddr ))
253
274
if args .convert :
254
275
drives = []
255
276
if args .output == None :
256
277
args .output = "flash." + ext
257
278
else :
258
- drives = getdrives ()
259
-
279
+ drives = get_drives ()
280
+
260
281
if args .output :
261
- writeFile (args .output , outbuf )
282
+ write_file (args .output , outbuf )
262
283
else :
263
284
if len (drives ) == 0 :
264
285
error ("No drive to deploy." )
265
286
for d in drives :
266
- print "Flashing %s (%s)" % (d , boardID (d ))
267
- writeFile (outbuf , d + "/NEW.UF2" )
287
+ print ("Flashing %s (%s)" % (d , board_id (d )))
288
+ write_file (d + "/NEW.UF2" , outbuf )
289
+
268
290
269
291
if __name__ == "__main__" :
270
- main ()
292
+ main ()
0 commit comments