# Copyright 2014-2015 Ivan Kravets # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from os.path import join, isfile from shutil import copyfile from time import sleep from SCons.Script import Exit from serial import Serial from platformio.util import get_logicaldisks, get_serialports, get_systype def FlushSerialBuffer(env, port): s = Serial(env.subst(port)) s.flushInput() s.setDTR(False) s.setRTS(False) sleep(0.1) s.setDTR(True) s.setRTS(True) s.close() def TouchSerialPort(env, port, baudrate): if "windows" not in get_systype(): try: s = Serial(env.subst(port)) s.close() except: # pylint: disable=W0702 pass s = Serial(port=env.subst(port), baudrate=baudrate) s.setDTR(False) s.close() sleep(0.4) def WaitForNewSerialPort(_, before): new_port = None elapsed = 0 while elapsed < 10: now = [i['port'] for i in get_serialports()] diff = list(set(now) - set(before)) if diff: new_port = diff[0] break before = now sleep(0.25) elapsed += 0.25 if not new_port: Exit("Error: Couldn't find a board on the selected port. " "Check that you have the correct port selected. " "If it is correct, try pressing the board's reset " "button after initiating the upload.") return new_port def AutodetectUploadPort(env): if "UPLOAD_PORT" in env: return if env.subst("$FRAMEWORK") == "mbed": msdlabels = ("mbed", "nucleo", "frdm") for item in get_logicaldisks(): if (not item['name'] or not any([l in item['name'].lower() for l in msdlabels])): continue env.Replace(UPLOAD_PORT=item['disk']) break else: board_build_opts = env.get("BOARD_OPTIONS", {}).get("build", {}) board_hwid = ("%s:%s" % ( board_build_opts.get("vid"), board_build_opts.get("pid") )).replace("0x", "") for item in get_serialports(): if "VID:PID" not in item['hwid']: continue env.Replace(UPLOAD_PORT=item['port']) if board_hwid in item['hwid']: break if "UPLOAD_PORT" in env: print "Auto-detected UPLOAD_PORT/DISK: %s" % env['UPLOAD_PORT'] else: Exit("Error: Please specify `upload_port` for environment or use " "global `--upload-port` option.\n" "For some development platforms this can be a USB flash drive " "(i.e. /media//)\n") def UploadToDisk(_, target, source, env): # pylint: disable=W0613,W0621 env.AutodetectUploadPort() for ext in ("bin", "hex"): fpath = join(env.subst("$BUILD_DIR"), "firmware.%s" % ext) if not isfile(fpath): continue copyfile(fpath, join(env.subst("$UPLOAD_PORT"), "firmware.%s" % ext)) print ("Firmware has been successfully uploaded.\n" "Please restart your board.") def exists(_): return True def generate(env): env.AddMethod(FlushSerialBuffer) env.AddMethod(TouchSerialPort) env.AddMethod(WaitForNewSerialPort) env.AddMethod(AutodetectUploadPort) env.AddMethod(UploadToDisk) return env