1# Copyright (c) 2017 Linaro Limited. 2# Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd. 3# 4# SPDX-License-Identifier: Apache-2.0 5 6'''Runner for flashing ESP32 devices with esptool/espidf.''' 7 8from os import path 9 10from runners.core import ZephyrBinaryRunner, RunnerCaps 11 12import os 13import sys 14 15class Esp32BinaryRunner(ZephyrBinaryRunner): 16 '''Runner front-end for espidf.''' 17 18 def __init__(self, cfg, device, boot_address, part_table_address, 19 app_address, erase=False, reset=False, baud=921600, 20 flash_size='detect', flash_freq='40m', flash_mode='dio', 21 espidf='espidf', bootloader_bin=None, partition_table_bin=None, 22 no_stub=False): 23 super().__init__(cfg) 24 self.elf = cfg.elf_file 25 self.app_bin = cfg.bin_file 26 self.erase = bool(erase) 27 self.reset = bool(reset) 28 self.device = device 29 self.boot_address = boot_address 30 self.part_table_address = part_table_address 31 self.app_address = app_address 32 self.baud = baud 33 self.flash_size = flash_size 34 self.flash_freq = flash_freq 35 self.flash_mode = flash_mode 36 self.espidf = espidf 37 self.bootloader_bin = bootloader_bin 38 self.partition_table_bin = partition_table_bin 39 self.no_stub = no_stub 40 41 @classmethod 42 def name(cls): 43 return 'esp32' 44 45 @classmethod 46 def capabilities(cls): 47 return RunnerCaps(commands={'flash'}, erase=True, reset=True) 48 49 @classmethod 50 def do_add_parser(cls, parser): 51 # Required 52 parser.add_argument('--esp-idf-path', required=True, 53 help='path to ESP-IDF') 54 # Optional 55 parser.add_argument('--esp-boot-address', default='0x1000', 56 help='bootloader load address') 57 parser.add_argument('--esp-partition-table-address', default='0x8000', 58 help='partition table load address') 59 parser.add_argument('--esp-app-address', default='0x10000', 60 help='application load address') 61 parser.add_argument('--esp-device', default=os.environ.get('ESPTOOL_PORT', None), 62 help='serial port to flash') 63 parser.add_argument('--esp-baud-rate', default='921600', 64 help='serial baud rate, default 921600') 65 parser.add_argument('--esp-flash-size', default='detect', 66 help='flash size, default "detect"') 67 parser.add_argument('--esp-flash-freq', default='40m', 68 help='flash frequency, default "40m"') 69 parser.add_argument('--esp-flash-mode', default='dio', 70 help='flash mode, default "dio"') 71 parser.add_argument( 72 '--esp-tool', 73 help='''if given, complete path to espidf. default is to search for 74 it in [ESP_IDF_PATH]/tools/esptool_py/esptool.py''') 75 parser.add_argument('--esp-flash-bootloader', 76 help='Bootloader image to flash') 77 parser.add_argument('--esp-flash-partition_table', 78 help='Partition table to flash') 79 parser.add_argument('--esp-no-stub', default=False, action='store_true', 80 help='Disable launching the flasher stub, only talk to ROM bootloader') 81 82 parser.set_defaults(reset=True) 83 84 @classmethod 85 def do_create(cls, cfg, args): 86 if args.esp_tool: 87 espidf = args.esp_tool 88 else: 89 espidf = path.join(args.esp_idf_path, 'tools', 'esptool_py', 90 'esptool.py') 91 92 return Esp32BinaryRunner( 93 cfg, args.esp_device, boot_address=args.esp_boot_address, 94 part_table_address=args.esp_partition_table_address, 95 app_address=args.esp_app_address, erase=args.erase, reset=args.reset, 96 baud=args.esp_baud_rate, flash_size=args.esp_flash_size, 97 flash_freq=args.esp_flash_freq, flash_mode=args.esp_flash_mode, 98 espidf=espidf, bootloader_bin=args.esp_flash_bootloader, 99 partition_table_bin=args.esp_flash_partition_table, 100 no_stub=args.esp_no_stub) 101 102 def do_run(self, command, **kwargs): 103 self.require(self.espidf) 104 105 # Add Python interpreter 106 cmd_flash = [sys.executable, self.espidf, '--chip', 'auto'] 107 108 if self.device is not None: 109 cmd_flash.extend(['--port', self.device]) 110 111 if self.erase is True: 112 cmd_erase = cmd_flash + ['erase_flash'] 113 self.check_call(cmd_erase) 114 115 if self.no_stub is True: 116 cmd_flash.extend(['--no-stub']) 117 cmd_flash.extend(['--baud', self.baud]) 118 cmd_flash.extend(['--before', 'default_reset']) 119 if self.reset: 120 cmd_flash.extend(['--after', 'hard_reset', 'write_flash', '-u']) 121 cmd_flash.extend(['--flash_mode', self.flash_mode]) 122 cmd_flash.extend(['--flash_freq', self.flash_freq]) 123 cmd_flash.extend(['--flash_size', self.flash_size]) 124 125 if self.bootloader_bin: 126 cmd_flash.extend([self.boot_address, self.bootloader_bin]) 127 if self.partition_table_bin: 128 cmd_flash.extend([self.part_table_address, self.partition_table_bin]) 129 cmd_flash.extend([self.app_address, self.app_bin]) 130 else: 131 cmd_flash.extend([self.app_address, self.app_bin]) 132 133 self.logger.info("Flashing esp32 chip on {} ({}bps)". 134 format(self.device, self.baud)) 135 self.check_call(cmd_flash) 136