8660e8fcad36519508d5a1f24c897bb3cb0854d6
5 Copyright (C) Dean Camera, 2020.
7 dean [at] fourwalledcubicle [dot] com
12 Front-end programmer for the LUFA HID class bootloader.
15 python hid_bootloader_loader.py <Device> <Input>.hex
18 python hid_bootloader_loader.py at90usb1287 Mouse.hex
20 Requires the hidapi (https://pypi.python.org/pypi/hidapi) and
21 IntelHex (https://pypi.python.org/pypi/IntelHex) libraries.
26 from intelhex
import IntelHex
29 # Device information table
30 device_info_map
= dict()
31 device_info_map
['at90usb1287'] = {'page_size': 256, 'flash_kb': 128}
32 device_info_map
['at90usb1286'] = {'page_size': 256, 'flash_kb': 128}
33 device_info_map
['at90usb647'] = {'page_size': 256, 'flash_kb': 64}
34 device_info_map
['at90usb646'] = {'page_size': 256, 'flash_kb': 64}
35 device_info_map
['atmega32u4'] = {'page_size': 128, 'flash_kb': 32}
36 device_info_map
['atmega32u2'] = {'page_size': 128, 'flash_kb': 32}
37 device_info_map
['atmega16u4'] = {'page_size': 128, 'flash_kb': 16}
38 device_info_map
['atmega16u2'] = {'page_size': 128, 'flash_kb': 16}
39 device_info_map
['at90usb162'] = {'page_size': 128, 'flash_kb': 16}
40 device_info_map
['atmega8u2'] = {'page_size': 128, 'flash_kb': 8}
41 device_info_map
['at90usb82'] = {'page_size': 128, 'flash_kb': 8}
44 def get_hid_device_handle():
45 all_hid_devices
= hid
.enumerate()
47 lufa_hid_devices
= [d
for d
in all_hid_devices
if d
['vendor_id'] == 0x03EB and d
['product_id'] == 0x2067]
49 if len(lufa_hid_devices
) is 0:
52 device_handle
= hid
.device()
53 device_handle
.open_path(lufa_hid_devices
[0]['path'])
57 def send_page_data(hid_device
, address
, data
):
58 # Bootloader page data should be the HID Report ID (always zero) followed
59 # by the starting address to program, then one device's flash page worth
61 output_report_data
= bytearray(65)
62 output_report_data
[0] = 0
63 output_report_data
[1] = address
& 0xFF
64 output_report_data
[2] = address
>> 8
65 output_report_data
[3 : ] = data
67 hid_device
.write(output_report_data
)
70 def program_device(hex_data
, device_info
):
71 hid_device
= get_hid_device_handle()
73 if hid_device
is None:
74 print("No valid HID device found.")
78 print("Connected to bootloader.", flush
=True)
80 # Program in all data from the loaded HEX file, in a number of device
82 for addr
in range(0, hex_data
.maxaddr(), device_info
['page_size']):
83 # Compute the address range of the current page in the device
84 current_page_range
= range(addr
, addr
+device_info
['page_size'])
86 # Extract the data from the hex file at the specified start page
87 # address and convert it to a regular list of bytes
88 page_data
= [hex_data
[i
] for i
in current_page_range
]
90 print("Writing address 0x%04X-0x%04X" %
(current_page_range
[0], current_page_range
[-1]), flush
=True)
92 # Devices with more than 64KB of flash should shift down the page
93 # address so that it is 16-bit (page size is guaranteed to be
94 # >= 256 bytes so no non-zero address bits are discarded)
95 if device_info
['flash_kb'] < 64:
96 send_page_data(hid_device
, addr
, page_data
)
98 send_page_data(hid_device
, addr
>> 8, page_data
)
100 # Once programming is complete, start the application via a dummy page
101 # program to the page address 0xFFFF
102 print("Programming complete, starting application.", flush
=True)
103 send_page_data(hid_device
, 0xFFFF, [0] * device_info
['page_size'])
109 if __name__
== '__main__':
110 if len(sys
.argv
) != 3:
112 print("\t{} device file.hex".format(sys
.argv
[0]))
115 # Load the specified HEX file
117 hex_data
= IntelHex(sys
.argv
[2])
119 print("Could not open the specified HEX file.")
122 # Retrieve the device information entry for the specified device
124 device_info
= device_info_map
[sys
.argv
[1]]
126 print("Unknown device name specified.")
129 program_device(hex_data
, device_info
)