qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

flash.py (5225B)


      1 """Compile and flash QMK Firmware
      2 
      3 You can compile a keymap already in the repo or using a QMK Configurator export.
      4 A bootloader must be specified.
      5 """
      6 from argcomplete.completers import FilesCompleter
      7 from pathlib import Path
      8 
      9 from milc import cli
     10 
     11 import qmk.path
     12 from qmk.decorators import automagic_keyboard, automagic_keymap
     13 from qmk.commands import build_environment
     14 from qmk.keyboard import keyboard_completer, keyboard_folder
     15 from qmk.keymap import keymap_completer, locate_keymap
     16 from qmk.flashers import flasher
     17 from qmk.build_targets import KeyboardKeymapBuildTarget, JsonKeymapBuildTarget
     18 
     19 
     20 def _list_bootloaders():
     21     """Prints the available bootloaders listed in docs.qmk.fm.
     22     """
     23     cli.print_help()
     24     cli.log.info('Here are the available bootloaders:')
     25     cli.echo('\tavrdude')
     26     cli.echo('\tbootloadhid')
     27     cli.echo('\tdfu')
     28     cli.echo('\tdfu-util')
     29     cli.echo('\tmdloader')
     30     cli.echo('\tst-flash')
     31     cli.echo('\tst-link-cli')
     32     cli.log.info('Enhanced variants for split keyboards:')
     33     cli.echo('\tavrdude-split-left')
     34     cli.echo('\tavrdude-split-right')
     35     cli.echo('\tdfu-ee')
     36     cli.echo('\tdfu-split-left')
     37     cli.echo('\tdfu-split-right')
     38     cli.echo('\tdfu-util-split-left')
     39     cli.echo('\tdfu-util-split-right')
     40     cli.echo('\tuf2-split-left')
     41     cli.echo('\tuf2-split-right')
     42     cli.echo('For more info, visit https://docs.qmk.fm/#/flashing')
     43     return False
     44 
     45 
     46 def _flash_binary(filename, mcu):
     47     """Try to flash binary firmware
     48     """
     49     cli.echo('Flashing binary firmware...\nPlease reset your keyboard into bootloader mode now!\nPress Ctrl-C to exit.\n')
     50     try:
     51         err, msg = flasher(mcu, filename)
     52         if err:
     53             cli.log.error(msg)
     54             return False
     55     except KeyboardInterrupt:
     56         cli.log.info('Ctrl-C was pressed, exiting...')
     57     return True
     58 
     59 
     60 @cli.argument('filename', nargs='?', arg_only=True, type=qmk.path.FileType('r'), completer=FilesCompleter('.json'), help='A configurator export JSON to be compiled and flashed or a pre-compiled binary firmware file (bin/hex) to be flashed.')
     61 @cli.argument('-b', '--bootloaders', action='store_true', help='List the available bootloaders.')
     62 @cli.argument('-bl', '--bootloader', default='flash', help='The flash command, corresponding to qmk\'s make options of bootloaders.')
     63 @cli.argument('-m', '--mcu', help='The MCU name. Required for HalfKay, HID, USBAspLoader and ISP flashing.')
     64 @cli.argument('-kb', '--keyboard', type=keyboard_folder, completer=keyboard_completer, help='The keyboard to build a firmware for. Ignored when a configurator export is supplied.')
     65 @cli.argument('-km', '--keymap', completer=keymap_completer, help='The keymap to build a firmware for. Ignored when a configurator export is supplied.')
     66 @cli.argument('-n', '--dry-run', arg_only=True, action='store_true', help="Don't actually build, just show the make command to be run.")
     67 @cli.argument('-j', '--parallel', type=int, default=1, help="Set the number of parallel make jobs; 0 means unlimited.")
     68 @cli.argument('-e', '--env', arg_only=True, action='append', default=[], help="Set a variable to be passed to make. May be passed multiple times.")
     69 @cli.argument('-c', '--clean', arg_only=True, action='store_true', help="Remove object files before compiling.")
     70 @cli.subcommand('QMK Flash.')
     71 @automagic_keyboard
     72 @automagic_keymap
     73 def flash(cli):
     74     """Compile and or flash QMK Firmware or keyboard/layout
     75 
     76     If a binary firmware is supplied, try to flash that.
     77 
     78     If a Configurator export is supplied this command will create a new keymap, overwriting an existing keymap if one exists.
     79 
     80     If a keyboard and keymap are provided this command will build a firmware based on that.
     81 
     82     If bootloader is omitted the make system will use the configured bootloader for that keyboard.
     83     """
     84     if cli.args.filename and isinstance(cli.args.filename, Path) and cli.args.filename.suffix in ['.bin', '.hex', '.uf2']:
     85         return _flash_binary(cli.args.filename, cli.args.mcu)
     86 
     87     if cli.args.bootloaders:
     88         return _list_bootloaders()
     89 
     90     # Build the environment vars
     91     envs = build_environment(cli.args.env)
     92 
     93     # Handler for the build target
     94     target = None
     95 
     96     if cli.args.filename:
     97         # if we were given a filename, assume we have a json build target
     98         target = JsonKeymapBuildTarget(cli.args.filename)
     99 
    100     elif cli.config.flash.keyboard and cli.config.flash.keymap:
    101         # if we got a keyboard and keymap, attempt to find it
    102         if not locate_keymap(cli.config.flash.keyboard, cli.config.flash.keymap):
    103             cli.log.error('Invalid keymap argument.')
    104             cli.print_help()
    105             return False
    106 
    107         # If we got here, then we have a valid keyboard and keymap for a build target
    108         target = KeyboardKeymapBuildTarget(cli.config.flash.keyboard, cli.config.flash.keymap)
    109 
    110     if not target:
    111         cli.log.error('You must supply a configurator export, both `--keyboard` and `--keymap`, or be in a directory for a keyboard or keymap.')
    112         cli.print_help()
    113         return False
    114 
    115     target.configure(parallel=cli.config.flash.parallel, clean=cli.args.clean)
    116     return target.compile(cli.args.bootloader, dry_run=cli.args.dry_run, **envs)