def main(): from greatfet.utils import GreatFETArgumentParser # Set up a simple argument parser. parser = GreatFETArgumentParser(description="utility for reading from the GreatFET's ADC") parser.add_argument('-f', '--format', dest='format', type=str, default='voltage', choices=['voltage', 'raw'], help="Format to output in.\nVoltage string, or raw fraction returned by the ADC.") parser.add_argument('-m', '--machine-readable', dest='machine_readable', action='store_true', default=False, help="Don't output unit suffixes.") parser.add_argument('-n', '--samples', dest='sample_count', type=int, default=1, help="The number of samples to read. (default: 1)") parser.add_argument('-o', '--output', dest='output', type=argparse.FileType('w'), default='-', help="File to output to. Specify - to output to stdout (default).") args = parser.parse_args() log_function = parser.get_log_function() device = parser.find_specified_device() if not device.supports_api('adc'): sys.stderr.write("This device doesn't seem to support an ADC. Perhaps your firmware needs to be upgraded?\n") sys.exit(0) samples = device.adc.read_samples(args.sample_count) for sample in samples: output_sample(sample, args) args.output.close()
def main(): # Set up a simple argument parser. parser = GreatFETArgumentParser( description= "Utility for loading runtime extensions on to a GreatFET board.") parser.add_argument( '--m0', dest="m0", type=argparse.FileType('rb'), metavar='<filename>', help="loads the provided loadable file to run on the GreatFET's m0 core" ) args = parser.parse_args() log_function = parser.get_log_function() device = parser.find_specified_device() if not args.m0: parser.print_help() sys.exit(-1) if args.m0: data = args.m0.read() log_function( "Loading {} byte loadable onto the M0 coprocessor.\n".format( len(data))) device.m0.run_loadable(data)
def main(): logfile = 'log.bin' # logfile = '/tmp/fifo' from greatfet.utils import GreatFETArgumentParser # Set up a simple argument parser. parser = GreatFETArgumentParser(description="Utility for experimenting with GreatFET's ADC") parser.add_argument('-f', dest='filename', metavar='<filename>', type=str, help="Write data to file", default=logfile) parser.add_argument('-a', dest='adc', action='store_true', help="Use internal ADC") args = parser.parse_args() log_function = parser.get_log_function() device = parser.find_specified_device() if args.adc: device.comms._vendor_request_out(vendor_requests.ADC_INIT) else: device.comms._vendor_request_out(vendor_requests.SDIR_RX_START) time.sleep(1) print(device.comms.device) with open(args.filename, 'wb') as f: try: while True: d = device.comms.device.read(0x81, 0x4000, 1000) # print(d) f.write(d) except KeyboardInterrupt: pass if not args.adc: device.comms._vendor_request_out(vendor_requests.SDIR_RX_STOP)
def main(): from greatfet.utils import GreatFETArgumentParser # Set up a simple argument parser. parser = GreatFETArgumentParser( description="Utility for experimenting with GreatFET's DAC", verbose_by_default=True) parser.add_argument( '-f', '--format', dest='format', type=str, default='voltage', choices=['voltage', 'raw'], help= "Format for the input.\nVoltage string, or binary value to be loaded into the DAC." ) parser.add_argument( 'value', metavar='[value]', type=float, help= "The desired voltage (default) or raw value to load into DAC (with -f raw)." ) args = parser.parse_args() log_function = parser.get_log_function() device = parser.find_specified_device() device.apis.dac.initialize() if args.format == "voltage": # Voltage must be passed to the device in millivolts, so * 1000. device.apis.dac.set_voltage(int(args.value * 1000)) log_function("DAC set to {} volts".format(args.value)) else: device.apis.dac.set_value(int(args.value)) log_function("DAC set to {}".format(int(args.value)))
def main(): parser = GreatFETArgumentParser( description="Convenience shell for working with GreatFET devices.") parser.add_argument('-n', '--length', dest='length', metavar='<bytes>', type=int, help="maximum amount of data to read (default: 4096)", default=4096) args = parser.parse_args() args = parser.parse_args() gf = parser.find_specified_device() log_function = parser.get_log_function() #Read and print the logs logs = gf.read_debug_ring(args.length) log_function("Ring buffer contained {} bytes of data:\n".format(len(logs))) print(logs)
def main(): from greatfet.utils import GreatFETArgumentParser # Set up a simple argument parser. parser = GreatFETArgumentParser(description="Periodically print temperature from DS18B20 sensor") parser.add_argument('-S', dest='s20', action='store_true', help='DS18S20') args = parser.parse_args() log_function = parser.get_log_function() device = parser.find_specified_device() while True: data = device.vendor_request_in(vendor_requests.DS18B20_READ, length=2, timeout=2000) # temperature data is 16 bit signed temp = struct.unpack('<h', data)[0] if args.s20: temp /= 2.0 else: temp /= 16.0 print(time.strftime("%H:%M:%S"), temp, '{:.01f}'.format(temp * 9 / 5 + 32)) time.sleep(1)
def main(): parser = GreatFETArgumentParser( description="Convenience shell for working with GreatFET devices.") parser.add_argument('-n', '--length', dest='length', metavar='<bytes>', type=int, help="maximum amount of data to read (default: 4096)", default=4096) args = parser.parse_args() args = parser.parse_args() gf = parser.find_specified_device() log_function = parser.get_log_function() if not gf.supports_api('debug'): print("ERROR: This board doesn't appear to support the debug API -- was its firmware built without it?") return if not gf.apis.debug.supports_verb('read_dmesg'): print("ERROR: This board doesn't appear to support debug logging. Was its firmware built with logging or the ringbuffer off?") return #Read and print the dmesg log. logs = gf.read_debug_ring(args.length) log_function("Ring buffer contained {} bytes of data:\n".format(len(logs))) print(logs)
def main(): # Set up a simple argument parser. parser = GreatFETArgumentParser( dfu=True, description="Utility for flashing firmware on GreatFET boards") parser.add_argument('-a', '--address', metavar='<n>', type=int, help="starting address (default: 0)", default=0) parser.add_argument( '-l', '--length', metavar='<n>', type=int, help="number of bytes to read (default: {})".format(MAX_FLASH_LENGTH), default=MAX_FLASH_LENGTH) parser.add_argument('-r', '--read', dest='read', metavar='<filename>', type=str, help="Read data into file", default='') parser.add_argument('-w', '--write', dest='write', metavar='<filename>', type=str, help="Write data from file", default='') parser.add_argument( '-R', '--reset', dest='reset', action='store_true', help="Reset GreatFET after performing other operations.") args = parser.parse_args() # Validate our options. # If we don't have an option, print our usage. if not any(( args.read, args.write, args.reset, )): parser.print_help() sys.exit(0) # Determine whether we're going to log to the stdout, or not at all. log_function = parser.get_log_function() # If we're supposed to install firmware via a DFU stub, install it first. if args.dfu: try: load_dfu_stub(args) except DeviceNotFoundError: print("Couldn't find a GreatFET-compatible board in DFU mode!", file=sys.stderr) sys.exit(errno.ENODEV) # Create our GreatFET connection. log_function("Trying to find a GreatFET device...") device = parser.find_specified_device() log_function("{} found. (Serial number: {})".format( device.board_name(), device.serial_number())) # Ensure that the device supports an onboard SPI flash. try: device.onboard_flash except AttributeError: print( "The attached GreatFET ({}) doesn't appear to have an SPI flash to program!" .format(device.board_name()), file=sys.stderr) sys.exit(errno.ENOSYS) # If we have a write command, write first, to match the behavior of hackrf_spiflash. if args.write: log_function("Writing data to SPI flash...") spi_flash_write(device, args.write, args.address, log_function) log_function("Write complete!") if not (args.reset or args.dfu): log_function( "Reset not specified; new firmware will not start until next reset." ) # Handle any read commands. if args.read: log_function("Reading data from SPI flash...") spi_flash_read(device, args.read, args.address, args.length, log_function) log_function("Read complete!") # Finally, reset the target if args.reset or args.dfu: log_function("Resetting GreatFET...") device.reset(reconnect=False) log_function("Reset complete!")
def main(): # Simple type-arguments for parsing. int_from_msps = lambda x: from_eng_notation( x, units=['Hz', 'SPS'], to_type=int) # Set up our argument parser. parser = GreatFETArgumentParser( description="Logic analyzer implementation for GreatFET", verbose_by_default=True) parser.add_argument( '-o', '-b', '--binary', dest='binary', metavar='<filename>', type=str, help="Write the raw samples captured to a file with the provided name." ) parser.add_argument( '-p', '--pulseview', '--sigrok', dest='pulseview', metavar="<filename>", type=str, help= "Generate a Sigrok/PulseView session file, and write it to the provided filename." ) parser.add_argument('-f', '--samplerate', metavar='samples_per_second', type=int_from_msps, default=17000000, dest='sample_rate', help='samples to capture per second') parser.add_argument('-n', '--num-channels', metavar='channels', type=int, default=8, dest='bus_width', help='the number of channels to capture') parser.add_argument( '-B', '--second-bank', action='store_const', const=8, default=0, dest='first_pin', help= "Provide this option to capture from SGPIO8 up, rather than from SGPIO0 up." ) parser.add_argument( '-O', '--stdout', dest='write_to_stdout', action='store_true', help= 'Provide this option to write the raw binary samples to the standard out. Implies -q.' ) parser.add_argument( '--rhododendron', dest='rhododendron', action='store_true', help= 'Capture raw packets for e.g. low or full speed USB using the Rhodadendon neighbor.' ) parser.add_argument( '--raw-usb', dest='raw_usb', action='store_true', help= 'Capture raw packets for e.g. low or full speed USB on SGPIO0 and SGPIO1.' ) parser.add_argument( '--debug-sgpio', dest='debug_sgpio', action='store_true', help= 'Developer option for debugging; dumps the SGPIO configuration before starting.' ) parser.add_argument( '--stats', dest='print_stats', action='store_true', help='Print capture statistics after the transfer is complete.') # And grab our GreatFET. args = parser.parse_args() # If we're writing binary samples directly to stdout, don't emit logs to stdout; otherwise, honor the # --quiet flag. if args.write_to_stdout: log_function = log_silent else: log_function = parser.get_log_function() # Ensure we have at least one write operation. if not (args.pulseview or args.binary or args.write_to_stdout): parser.print_help() sys.exit(-1) # Capture a few of the arguments. sample_rate = args.sample_rate bus_width = args.bus_width channel_names = None # If we have one of the raw-usb options, apply their settings. if args.raw_usb or args.rhododendron: sample_rate = int(51e6) bus_width = 2 channel_names = {0: 'D-', 1: 'D+'} if args.rhododendron: args.first_pin = 8 # Find our GreatFET. device = parser.find_specified_device() # Configure which locations we're using for SGPIO8/9. device.apis.logic_analyzer.configure_alt_mappings(args.rhododendron) # Set the first pin in our capture according to our bank setting. device.apis.logic_analyzer.change_first_pin(args.first_pin) # Replace the sample rate with the actual achieved sample rate. sample_rate, buffer_size, endpoint = device.apis.logic_analyzer.configure( sample_rate, bus_width) # If we've been asked to dump SGPIO debug info, do so. if args.debug_sgpio: device.apis.logic_analyzer.dump_sgpio_configuration(False) print(device.read_debug_ring(), file=sys.stderr) sys.stderr.flush() # Print what we're doing and our status. log_function("Sampling {} channels at {}Hz.".format( bus_width, eng_notation(sample_rate))) log_function("Press Ctrl+C to stop reading data from device.") # If we have a target binary file, open the target filename and use that to store samples. if args.binary: bin_file = open(args.binary, 'wb') bin_file_name = args.binary # Otherwise, create an temporary file and use that. (It's automatically destroyed on close, which is fancy.) elif args.pulseview: try: holding_dir = os.path.dirname(os.path.abspath(args.pulseview)) except: holding_dir = None bin_file = tempfile.NamedTemporaryFile(dir=holding_dir) bin_file_name = bin_file.name # Create queues of transfer objects that we'll use as a producer/consumer interface for our comm thread. empty_buffers = [] full_buffers = [] # Allocate a set of transfer buffers, so we don't have to continuously allocate them. for _ in range(DEFAULT_PREALLOCATED_BUFFERS): empty_buffers.append(allocate_transfer_buffer(buffer_size)) # Finally, spawn the thread that will handle our data processing and output. termination_request = threading.Event() thread_arguments = (termination_request, args, bus_width, bin_file, empty_buffers, full_buffers) data_thread = threading.Thread(target=background_process_data, args=thread_arguments) # Now that we're done with all of that setup, perform our actual sampling, in a tight loop, data_thread.start() device.apis.logic_analyzer.start() start_time = time.time() try: while True: # Grab a transfer buffer from the empty list... try: transfer_buffer = empty_buffers.pop() except IndexError: # If we don't have a buffer to fill, allocate a new one. It'll wind up in our buffer pool shortly. transfer_buffer = allocate_transfer_buffer(buffer_size) # Capture data from the device, and unpack it. device.comms.device.read(endpoint, transfer_buffer, 3000) # ... and pop it into the to-be-processed queue. full_buffers.append(transfer_buffer) except KeyboardInterrupt: pass except usb.core.USBError as e: log_error("") if e.errno == 32: log_error( "ERROR: Couldn't pull data from the device fast enough! Aborting." ) log_error( "(Lowering the sample rate may help. Sometimes, switching to another USB bus / port may help.)" ) else: log_error( "ERROR: Communications failure -- check the connection to -- and state of -- the GreatFET. " ) log_error( "(More debug information may be available if you run 'gf dmesg')." ) log_error(e) finally: elapsed_time = time.time() - start_time # No matter what, once we're done stop the device from sampling. device.apis.logic_analyzer.stop() # Signal to our data processing thread that it's time to terminate. termination_request.set() # Wait for our data processing thread to complete. log_function('') log_function( 'Capture terminated -- waiting for data processing to complete.') data_thread.join() # Flush whatever data we've read to disk, so it can be correctly read by subsequent operations. if args.pulseview: bin_file.flush() # Finally, generate our output. if args.binary: log_function("Binary data written to file '{}'.".format(args.binary)) if args.pulseview: emit_sigrok_file(args.pulseview, bin_file_name, bus_width, sample_rate, args.first_pin, channel_names) log_function( "Sigrok/PulseView compatible session file created: '{}'.".format( args.pulseview)) # Print how long we sampled for, as a nicety. log_function("Sampled for {} seconds.".format(round(elapsed_time, 4)))
def main(): # Start off with a default packet state. current_packet_type = None current_packet_data = array.array('B') current_packet_remaining = 0 next_data_packet_emit_after = [] next_data_packet_timestamp = None current_usb_data = array.array('B') def emit_usb_packet(packet_data): """ Emits a raw USB packet to the target format. """ print("Packet: [{}]".format(packet_data)) def is_valid_pid_byte(byte): """ Returns true iff the given byte could be a valid PID. """ pid = byte & 0xf inverse = byte >> 4 return (pid ^ inverse) == 0xf def hack_smoothe_out_jitter(packet_data, emit_point): """ XXX Horrorhack intended to "smoothe" over a missing firmware piece until it's implemented. """ try: print("next PID would be {} -- valid: {}".format( packet_data[emit_point], is_valid_pid_byte(packet_data[emit_point]))) # If the next byte is a valid PID, there's no need to hack anything. # Move along.. if is_valid_pid_byte(packet_data[emit_point]): return 0 except IndexError: pass print("trying to smoothe out a bit of jitter:") try: print("trying delta -1 [{}] -- {}".format( packet_data[emit_point - 1], is_valid_pid_byte(packet_data[emit_point - 1]))) # Otherwise, if the previous byte was a valid PID, move back to it. if is_valid_pid_byte(packet_data[emit_point - 1]): return -1 except IndexError: pass try: print("trying delta +1 [{}] -- {}".format( packet_data[emit_point + 1], is_valid_pid_byte(packet_data[emit_point + 1]))) # Otherwise, if the previous byte was a valid PID, move back to it. if is_valid_pid_byte(packet_data[emit_point + 1]): return 1 except IndexError: pass return 0 def handle_capture_packet(packet_type, packet_data): """ Handles a received full packet from the analyzer. """ nonlocal current_packet_type, current_packet_data, current_packet_remaining nonlocal next_data_packet_emit_after, next_data_packet_timestamp, current_usb_data # If this is an "end event" packet, grab the point at which # we're supposed to emit the packet. if packet_type == PACKET_TYPE_EVENT_END_OK: if (not next_data_packet_emit_after) or ( next_data_packet_emit_after[-1] != packet_data[0]): next_data_packet_emit_after.append(packet_data[0]) # If this is start packet, grab the timestamp from it. elif packet_type == PACKET_TYPE_EVENT_START: # FIXME: implement pass # If this is a USB data packet, handle it. elif packet_type == PACKET_TYPE_USB_DATA: print("got {} bytes of USB data [{}] <emit at: {}>".format( len(packet_data), packet_data, next_data_packet_emit_after)) existing_packet_length = len(current_usb_data) # Add the data to the current packet. current_usb_data.extend(packet_data) # Store that we're handled 0 bytes into the current packet. position_in_packet = 0 # If this packet ends a USB packet, emit the completed usb packet. while next_data_packet_emit_after: emit_after_bytes = next_data_packet_emit_after.pop( 0) - position_in_packet + 1 print("emit after: {} bytes [data: {}]".format( emit_after_bytes, current_usb_data)) # Emit the USB packet up until this point... emit_point = existing_packet_length + emit_after_bytes # XXX: Temporary hack to smoothe out single-byte event offsets until # the firmware properly has NXT and DIR tied to an SCT counter. delta = hack_smoothe_out_jitter(current_usb_data, emit_point) emit_point += delta emit_after_bytes += delta emit_usb_packet(current_usb_data[0:emit_point]) # ... and mark ourselves as already having emitted the relevant bytes, so # the future "emit afters" can be scaled properly. position_in_packet += emit_after_bytes # ... and remove those packets from the buffer. del current_usb_data[0:emit_point] next_data_packet_emit_after = [] def parse_capture_packets(samples, args, bin_file): """ Parses a set of packets coming from a USB capture device. """ nonlocal current_packet_type, current_packet_data, current_packet_remaining nonlocal next_data_packet_emit_after, next_data_packet_timestamp, current_usb_data # Parse all of the samples we have in our buffer. while samples: sample = samples.pop(0) #print("sample: {} / current_packet_remaining: {}".format(sample, current_packet_remaining)) # If we have data remaining in our packet, parse this sample as data. if current_packet_remaining: current_packet_data.append(sample) current_packet_remaining -= 1 # If we just completed a given packet, handle it. if current_packet_remaining == 0: handle_capture_packet(current_packet_type, current_packet_data) # Clear out our packet state. del current_packet_data[:] # Otherwise, handle this as a new packet. elif (current_packet_remaining == 0) and (sample in PACKET_SIZES): current_packet_type = sample current_packet_remaining = PACKET_SIZES[current_packet_type] - 1 else: raise IOError( "unknown packet type {}! stream error?\n".format(sample)) # Set up our argument parser. parser = GreatFETArgumentParser( description="Simple Rhododendron capture utility for GreatFET.", verbose_by_default=True) parser.add_argument( '-o', '-b', '--binary', dest='binary', metavar='<filename>', type=str, help="Write the raw samples captured to a file with the provided name." ) parser.add_argument( '--m0', dest="m0", type=argparse.FileType('rb'), metavar='<filename>', help= "loads the specific m0 coprocessor 'loadable' instead of the default Rhododendron one" ) parser.add_argument('-F', '--full-speed', dest='speed', action='store_const', const=SPEED_FULL, default=SPEED_HIGH, help="Capture full-speed data.") parser.add_argument('-L', '--low-speed', dest='speed', action='store_const', const=SPEED_LOW, default=SPEED_HIGH, help="Capture low-speed data.") parser.add_argument('-H', '--high-speed', dest='speed', action='store_const', const=SPEED_HIGH, help="Capture high-speed data. The default.") parser.add_argument( '-O', '--stdout', dest='write_to_stdout', action='store_true', help= 'Provide this option to log the received data to the stdout.. Implies -q.' ) # And grab our GreatFET. args = parser.parse_args() # If we're writing binary samples directly to stdout, don't emit logs to stdout; otherwise, honor the # --quiet flag. if args.write_to_stdout: log_function = log_silent else: log_function = parser.get_log_function() # Ensure we have at least one write operation. if not (args.binary or args.write_to_stdout): parser.print_help() sys.exit(-1) # Find our GreatFET. device = parser.find_specified_device() # Bring our Rhododendron board online; and capture communication parameters. buffer_size, endpoint = device.apis.usb_analyzer.initialize( args.speed, timeout=10000, comms_timeout=10000) # $Load the Rhododendron firmware loadable into memory... try: if args.m0: data = args.m0.read() else: data = read_rhododendron_m0_loadable() except (OSError, TypeError): log_error("Can't find a Rhododendron m0 program to load!") log_error("We can't run without one.") sys.exit(-1) # Debug only: setup a pin to track when we're handling SGPIO data. debug_pin = device.gpio.get_pin('J1_P3') debug_pin.set_direction(debug_pin.DIRECTION_OUT) # ... and then run it on our m0 coprocessor. device.m0.run_loadable(data) # Print what we're doing and our status. log_function("Reading raw {}-speed USB data!\n".format( SPEED_NAMES[args.speed])) log_function("Press Ctrl+C to stop reading data from device.") # If we have a target binary file, open the target filename and use that to store samples. bin_file = None if args.binary: bin_file = open(args.binary, 'wb') bin_file_name = args.binary # Now that we're done with all of that setup, perform our actual sampling, in a tight loop, device.apis.usb_analyzer.start_capture() transfer_buffer = allocate_transfer_buffer(buffer_size) total_captured = 0 try: while True: # Capture data from the device, and unpack it. try: new_samples = device.comms.device.read( endpoint, transfer_buffer, SAMPLE_DELIVERY_TIMEOUT_MS) samples = transfer_buffer[0:new_samples - 1] total_captured += new_samples log_function("Captured {} bytes.".format(total_captured), end="\r") parse_capture_packets(samples, args, bin_file) except usb.core.USBError as e: if e.errno != errno.ETIMEDOUT: raise except KeyboardInterrupt: pass except usb.core.USBError as e: log_error("") if e.errno == 32: log_error( "ERROR: Couldn't pull data from the device fast enough! Aborting." ) else: log_error( "ERROR: Communications failure -- check the connection to -- and state of -- the GreatFET. " ) log_error( "(More debug information may be available if you run 'gf dmesg')." ) log_error(e) finally: # No matter what, once we're done stop the device from sampling. device.apis.usb_analyzer.stop_capture() if args.binary: log_function("Binary data written to file '{}'.".format( args.binary))
def main(): # Grab any GreatFET assets that should have shipped with the tool. dfu_stub_path = find_greatfet_asset('flash_stub.bin') auto_firmware_path = find_greatfet_asset("greatfet_usb.bin") # Set up a simple argument parser.- parser = GreatFETArgumentParser( dfu=True, verbose_by_default=True, description="Utility for flashing firmware on GreatFET boards") parser.add_argument('-a', '--address', metavar='<n>', type=int, help="starting address (default: 0)", default=0) parser.add_argument( '-l', '--length', metavar='<n>', type=int, default=None, help= "number of bytes to read; if not specified, we try to read the programmed sections" ) parser.add_argument('-r', '--read', dest='read', metavar='<filename>', type=str, help="Read data into file", default='') parser.add_argument('-w', '--write', dest='write', metavar='<filename>', type=str, help="Write data from file", default='') parser.add_argument( '-R', '--reset', dest='reset', action='store_true', help="Reset GreatFET after performing other operations.") parser.add_argument( '-V', '--volatile-upload', dest='volatile', metavar="<filename>", type=str, help= "Uploads a GreatFET firmware image to RAM via DFU mode. Firmware is not flashed." ) # If we have the ability to automatically install firmware, provide that as an option. if auto_firmware_path: parser.add_argument( '--autoflash', action='store_true', dest='autoflash', help= "Automatically flash the attached board with the firmware corresponding to the installed tools." ) parser.add_argument( '-U', '--volatile-upload-auto', dest='volatile_auto', action='store_true', help= "Automatically upload the tools' firmware via DFU mode. Firmware is not flashed." ) args = parser.parse_args() # If we're trying to automatically flash the given firmware, set the relevant options accordingly. try: if not args.write and args.autoflash: args.write = auto_firmware_path args.reset = True except AttributeError: pass try: if not args.volatile and args.volatile_auto: args.volatile = auto_firmware_path except AttributeError: pass # Validate our options. # If we don't have an option, print our usage. if not any((args.read, args.write, args.reset, args.volatile)): parser.print_help() sys.exit(0) # Determine whether we're going to log to the stdout, or not at all. log_function = parser.get_log_function() if args.dfu_stub: dfu_stub_path = args.dfu_stub # If we're uploading a file via DFU for a "volatile" flash, do so and abort. if args.volatile: try: device = LPC43xxTarget() except BoardNotFoundError: print("Couldn't find a GreatFET-compatible board in DFU mode!", file=sys.stderr) sys.exit(errno.ENODEV) log_function("Uploading data to RAM...\n") dfu_upload(device, args.volatile, log_function) sys.exit(0) # If we're supposed to install firmware via a DFU stub, install it first. if args.dfu: try: load_dfu_stub(dfu_stub_path) except DeviceNotFoundError: print("Couldn't find a GreatFET-compatible board in DFU mode!", file=sys.stderr) sys.exit(errno.ENODEV) # Create our GreatFET connection. log_function("Trying to find a GreatFET device...") device = parser.find_specified_device() log_function("{} found. (Serial number: {})".format( device.board_name(), device.serial_number())) # Ensure that the device supports an onboard SPI flash. try: device.onboard_flash except AttributeError: print( "The attached GreatFET ({}) doesn't appear to have an SPI flash to program!" .format(device.board_name()), file=sys.stderr) sys.exit(errno.ENOSYS) # If we have a write command, write first, to match the behavior of hackrf_spiflash. if args.write: log_function("Writing data to SPI flash...\n") spi_flash_write(device, args.write, args.address, log_function) log_function("Write complete!") if not (args.reset or args.dfu): log_function( "Reset not specified; new firmware will not start until next reset." ) # Handle any read commands. if args.read: log_function("Reading data from SPI flash...\n") spi_flash_read(device, args.read, args.address, args.length, log_function) log_function("Read complete!") # Finally, reset the target if args.reset or args.dfu: log_function("Resetting GreatFET...") device.reset(reconnect=False, is_post_firmware_flash=bool(args.write)) log_function("Reset complete!")