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 8import os 9import sys 10from os import path 11 12from runners.core import RunnerCaps, ZephyrBinaryRunner 13 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-monitor-baud', default='115200', 66 help='serial monitor baud rate, default 115200') 67 parser.add_argument('--esp-flash-size', default='detect', 68 help='flash size, default "detect"') 69 parser.add_argument('--esp-flash-freq', default='40m', 70 help='flash frequency, default "40m"') 71 parser.add_argument('--esp-flash-mode', default='dio', 72 help='flash mode, default "dio"') 73 parser.add_argument( 74 '--esp-tool', 75 help='''if given, complete path to espidf. default is to search for 76 it in [ESP_IDF_PATH]/tools/esptool_py/esptool.py''') 77 parser.add_argument('--esp-flash-bootloader', 78 help='Bootloader image to flash') 79 parser.add_argument('--esp-flash-partition_table', 80 help='Partition table to flash') 81 parser.add_argument('--esp-no-stub', default=False, action='store_true', 82 help='Disable launching the flasher stub, only talk to ROM bootloader') 83 84 parser.set_defaults(reset=True) 85 86 @classmethod 87 def do_create(cls, cfg, args): 88 if args.esp_tool: 89 espidf = args.esp_tool 90 else: 91 espidf = path.join(args.esp_idf_path, 'tools', 'esptool_py', 92 'esptool.py') 93 94 return Esp32BinaryRunner( 95 cfg, args.esp_device, boot_address=args.esp_boot_address, 96 part_table_address=args.esp_partition_table_address, 97 app_address=args.esp_app_address, erase=args.erase, reset=args.reset, 98 baud=args.esp_baud_rate, flash_size=args.esp_flash_size, 99 flash_freq=args.esp_flash_freq, flash_mode=args.esp_flash_mode, 100 espidf=espidf, bootloader_bin=args.esp_flash_bootloader, 101 partition_table_bin=args.esp_flash_partition_table, 102 no_stub=args.esp_no_stub) 103 104 def do_run(self, command, **kwargs): 105 self.require(self.espidf) 106 107 # Add Python interpreter 108 cmd_flash = [sys.executable, self.espidf, '--chip', 'auto'] 109 110 if self.device is not None: 111 cmd_flash.extend(['--port', self.device]) 112 113 if self.erase is True: 114 cmd_erase = cmd_flash + ['erase_flash'] 115 self.check_call(cmd_erase) 116 117 if self.no_stub is True: 118 cmd_flash.extend(['--no-stub']) 119 cmd_flash.extend(['--baud', self.baud]) 120 cmd_flash.extend(['--before', 'default_reset']) 121 if self.reset: 122 cmd_flash.extend(['--after', 'hard_reset', 'write_flash', '-u']) 123 cmd_flash.extend(['--flash_mode', self.flash_mode]) 124 cmd_flash.extend(['--flash_freq', self.flash_freq]) 125 cmd_flash.extend(['--flash_size', self.flash_size]) 126 127 if self.bootloader_bin: 128 cmd_flash.extend([self.boot_address, self.bootloader_bin]) 129 if self.partition_table_bin: 130 cmd_flash.extend([self.part_table_address, self.partition_table_bin]) 131 cmd_flash.extend([self.app_address, self.app_bin]) 132 else: 133 cmd_flash.extend([self.app_address, self.app_bin]) 134 135 self.logger.info(f"Flashing esp32 chip on {self.device} ({self.baud}bps)") 136 self.check_call(cmd_flash) 137