54 from __future__
import print_function
68 from sys
import platform
as _platform
72 '''Loads a firmware file'''
76 crctab = array.array(
'I', [
77 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
78 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
79 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
80 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
81 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
82 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
83 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
84 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
85 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
86 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
87 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
88 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
89 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
90 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
91 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
92 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
93 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
94 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
95 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
96 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
97 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
98 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
99 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
100 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
101 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
102 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
103 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
104 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
105 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
106 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
107 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
108 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d])
109 crcpad = bytearray(b
'\xff\xff\xff\xff')
118 self.image = bytearray(zlib.decompress(base64.b64decode(self.desc['image'])))
121 while ((len(self.
image) % 4) != 0):
122 self.image.append(
'\xff')
125 return self.
desc[propname]
129 index = (state ^ byte) & 0xff
130 state = self.
crctab[index] ^ (state >> 8)
135 for i
in range(len(self.
image), (padlen - 1), 4):
141 '''Uploads a firmware file to the PX FMU bootloader'''
151 BAD_SILICON_REV = b
'\x14'
158 CHIP_VERIFY = b
'\x24'
165 SET_BOOT_DELAY = b
'\x2d'
166 GET_CHIP_DES = b
'\x2e'
171 INFO_BL_REV = b
'\x01'
174 INFO_BOARD_ID = b
'\x02'
175 INFO_BOARD_REV = b
'\x03'
176 INFO_FLASH_SIZE = b
'\x04'
181 NSH_INIT = bytearray(b
'\x0d\x0d\x0d')
182 NSH_REBOOT_BL = b
"reboot -b\n"
183 NSH_REBOOT = b
"reboot\n"
184 MAVLINK_REBOOT_ID1 = bytearray(b
'\xfe\x21\x72\xff\x00\x4c\x00\x00\x80\x3f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf6\x00\x01\x00\x00\x48\xf0')
185 MAVLINK_REBOOT_ID0 = bytearray(b
'\xfe\x21\x45\xff\x00\x4c\x00\x00\x80\x3f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf6\x00\x00\x00\x00\xd7\xac')
189 self.
port = serial.Serial(portname, baudrate, timeout=0.5)
194 if self.
port is not None:
202 c = self.port.read(count)
204 raise RuntimeError(
"timeout waiting for data (%u bytes)" % count)
210 val = struct.unpack(
"<I", raw)
217 raise RuntimeError(
"unexpected %s instead of INSYNC" % c)
220 raise RuntimeError(
"bootloader reports INVALID OPERATION")
222 raise RuntimeError(
"bootloader reports OPERATION FAILED")
224 raise RuntimeError(
"unexpected response 0x%x instead of OK" % ord(c))
231 self.port.flushInput()
232 self.
__send(uploader.GET_SYNC
244 raise NotImplementedError()
250 except NotImplementedError:
251 raise RuntimeError(
"Programing not supported for this version of silicon!\n See https://pixhawk.org/help/errata")
258 self.
__send(uploader.GET_DEVICE + param + uploader.EOC)
265 t = struct.pack(
"I", param)
266 self.
__send(uploader.GET_OTP + t + uploader.EOC)
273 t = struct.pack(
"I", param)
274 self.
__send(uploader.GET_SN + t + uploader.EOC)
281 self.
__send(uploader.GET_CHIP + uploader.EOC)
287 self.
__send(uploader.GET_CHIP_DES + uploader.EOC)
289 value = self.
__recv(length)
291 peices = value.split(
",")
295 if maxVal < progress:
298 percent = (float(progress) / float(maxVal)) * 100.0
300 sys.stdout.write(
"\r%s: [%-20s] %.1f%%" % (label,
'='*int(percent/5.0), percent))
307 self.
__send(uploader.CHIP_ERASE
311 deadline = time.time() + 20.0
312 while time.time() < deadline:
315 estimatedTimeRemaining = deadline-time.time()
316 if estimatedTimeRemaining >= 9.0:
320 sys.stdout.write(
" (timeout: %d seconds) " % int(deadline-time.time()) )
327 raise RuntimeError(
"timed out waiting for erase")
332 if runningPython3 ==
True:
333 length = len(data).to_bytes(1, byteorder=
'big')
335 length = chr(len(data))
337 self.
__send(uploader.PROG_MULTI)
346 if runningPython3 ==
True:
347 length = len(data).to_bytes(1, byteorder=
'big')
349 length = chr(len(data))
351 self.
__send(uploader.READ_MULTI)
355 programmed = self.
__recv(len(data))
356 if programmed != data:
357 print(
"got " + binascii.hexlify(programmed))
358 print(
"expect " + binascii.hexlify(data))
365 self.
__send(uploader.REBOOT
375 return [seq[i:i+length]
for i
in range(0, len(seq), length)]
381 groups = self.
__split_len(code, uploader.PROG_MULTI_MAX)
389 if uploadProgress % 256 == 0:
396 self.
__send(uploader.CHIP_VERIFY
400 groups = self.
__split_len(code, uploader.READ_MULTI_MAX)
404 if verifyProgress % 256 == 0:
407 raise RuntimeError(
"Verification failed")
414 self.
__send(uploader.GET_CRC
419 if report_crc != expect_crc:
420 print(
"Expected 0x%x" % expect_crc)
421 print(
"Got 0x%x" % report_crc)
422 raise RuntimeError(
"Program CRC failed")
426 self.
__send(uploader.SET_BOOT_DELAY
427 + struct.pack(
"b", boot_delay)
438 if (self.
bl_rev < uploader.BL_REV_MIN)
or (self.
bl_rev > uploader.BL_REV_MAX):
439 print(
"Unsupported bootloader protocol %d" % uploader.INFO_BL_REV)
440 raise RuntimeError(
"Bootloader protocol mismatch")
449 if self.
board_type != fw.property(
'board_id'):
450 msg =
"Firmware not suitable for this board (board_type=%u board_id=%u)" % (
452 print(
"WARNING: %s" % msg)
454 print(
"FORCED WRITE, FLASHING ANYWAY!")
457 if self.
fw_maxsize < fw.property(
'image_size'):
458 raise RuntimeError(
"Firmware image is too large for this board")
462 for byte
in range(0,32*6,4):
465 print(binascii.hexlify(x).decode(
'Latin-1') +
' ', end=
'')
474 print(
"type: " + self.otp_id.decode(
'Latin-1'))
476 print(
"vid: " + binascii.hexlify(self.
otp_vid).decode(
'Latin-1'))
477 print(
"pid: "+ binascii.hexlify(self.
otp_pid).decode(
'Latin-1'))
478 print(
"coa: "+ binascii.b2a_base64(self.
otp_coa).decode(
'Latin-1'))
479 print(
"sn: ", end=
'')
480 for byte
in range(0,12,4):
483 self.
sn = self.
sn + x
484 print(binascii.hexlify(x).decode(
'Latin-1'), end=
'')
490 print(
"family: %s" % des[0])
491 print(
"revision: %s" % des[1])
505 if args.boot_delay
is not None:
508 print(
"\nRebooting.\n")
515 self.
__send(uploader.NSH_INIT)
516 self.
__send(uploader.NSH_REBOOT_BL)
517 self.
__send(uploader.NSH_INIT)
518 self.
__send(uploader.NSH_REBOOT)
520 self.
__send(uploader.MAVLINK_REBOOT_ID1)
521 self.
__send(uploader.MAVLINK_REBOOT_ID0)
527 if sys.version_info[0] < 3:
528 runningPython3 =
False
530 runningPython3 =
True
533 parser = argparse.ArgumentParser(description=
"Firmware uploader for the PX autopilot system.")
534 parser.add_argument(
'--port', action=
"store", required=
True, help=
"Serial port(s) to which the FMU may be attached")
535 parser.add_argument(
'--baud', action=
"store", type=int, default=115200, help=
"Baud rate of the serial port (default is 115200), only required for true serial ports.")
536 parser.add_argument(
'--force', action=
'store_true', default=
False, help=
'Override board type check and continue loading')
537 parser.add_argument(
'--boot-delay', type=int, default=
None, help=
'minimum boot delay to store in flash')
538 parser.add_argument(
'firmware', action=
"store", help=
"Firmware file to be uploaded")
539 args = parser.parse_args()
542 if os.path.exists(
"/usr/sbin/ModemManager"):
543 print(
"==========================================================================================================")
544 print(
"WARNING: You should uninstall ModemManager as it conflicts with any non-modem serial device (like Pixhawk)")
545 print(
"==========================================================================================================")
549 print(
"Loaded firmware for %x,%x, size: %d bytes, waiting for the bootloader..." % (fw.property(
'board_id'), fw.property(
'board_revision'), fw.property(
'image_size')))
550 print(
"If the board does not respond within 1-2 seconds, unplug and re-plug the USB connector.")
556 patterns = args.port.split(
",")
560 if "linux" in _platform
or "darwin" in _platform:
562 for pattern
in patterns:
563 portlist += glob.glob(pattern)
567 for port
in portlist:
573 if "linux" in _platform:
575 if not "COM" in port
and not "tty.usb" in port:
577 elif "darwin" in _platform:
579 if not "COM" in port
and not "ACM" in port:
581 elif "win" in _platform:
596 print(
"Found board %x,%x bootloader rev %x on %s" % (up.board_type, up.board_rev, up.bl_rev, port))
600 print(
"attempting reboot on %s..." % port)
601 print(
"if the board does not respond, unplug and re-plug the USB connector.")
615 except RuntimeError
as ex:
617 print(
"\nERROR: %s" % ex.args)
634 except KeyboardInterrupt:
635 print(
"\n Upload aborted by user.")
static int print(char **out, const char *format, va_list args)