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 encrypt=False, 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.encrypt = encrypt 40 self.no_stub = no_stub 41 42 @classmethod 43 def name(cls): 44 return 'esp32' 45 46 @classmethod 47 def capabilities(cls): 48 return RunnerCaps(commands={'flash'}, erase=True, reset=True) 49 50 @classmethod 51 def do_add_parser(cls, parser): 52 # Required 53 parser.add_argument('--esp-idf-path', required=True, 54 help='path to ESP-IDF') 55 # Optional 56 parser.add_argument('--esp-boot-address', default='0x1000', 57 help='bootloader load address') 58 parser.add_argument('--esp-partition-table-address', default='0x8000', 59 help='partition table load address') 60 parser.add_argument('--esp-app-address', default='0x10000', 61 help='application load address') 62 parser.add_argument('--esp-device', default=os.environ.get('ESPTOOL_PORT', None), 63 help='serial port to flash') 64 parser.add_argument('--esp-baud-rate', default='921600', 65 help='serial baud rate, default 921600') 66 parser.add_argument('--esp-monitor-baud', default='115200', 67 help='serial monitor baud rate, default 115200') 68 parser.add_argument('--esp-flash-size', default='detect', 69 help='flash size, default "detect"') 70 parser.add_argument('--esp-flash-freq', default='40m', 71 help='flash frequency, default "40m"') 72 parser.add_argument('--esp-flash-mode', default='dio', 73 help='flash mode, default "dio"') 74 parser.add_argument( 75 '--esp-tool', 76 help='''if given, complete path to espidf. default is to search for 77 it in [ESP_IDF_PATH]/tools/esptool_py/esptool.py''') 78 parser.add_argument('--esp-flash-bootloader', 79 help='Bootloader image to flash') 80 parser.add_argument('--esp-flash-partition_table', 81 help='Partition table to flash') 82 parser.add_argument('--esp-encrypt', default=False, action='store_true', 83 help='Encrypt firmware while flashing (correct efuses required)') 84 parser.add_argument('--esp-no-stub', default=False, action='store_true', 85 help='Disable launching the flasher stub, only talk to ROM bootloader') 86 87 parser.set_defaults(reset=True) 88 89 @classmethod 90 def do_create(cls, cfg, args): 91 if args.esp_tool: 92 espidf = args.esp_tool 93 else: 94 espidf = path.join(args.esp_idf_path, 'tools', 'esptool_py', 95 'esptool.py') 96 97 return Esp32BinaryRunner( 98 cfg, args.esp_device, boot_address=args.esp_boot_address, 99 part_table_address=args.esp_partition_table_address, 100 app_address=args.esp_app_address, erase=args.erase, reset=args.reset, 101 baud=args.esp_baud_rate, flash_size=args.esp_flash_size, 102 flash_freq=args.esp_flash_freq, flash_mode=args.esp_flash_mode, 103 espidf=espidf, bootloader_bin=args.esp_flash_bootloader, 104 partition_table_bin=args.esp_flash_partition_table, 105 encrypt=args.esp_encrypt, no_stub=args.esp_no_stub) 106 107 def do_run(self, command, **kwargs): 108 self.require(self.espidf) 109 110 # Add Python interpreter 111 cmd_flash = [sys.executable, self.espidf, '--chip', 'auto'] 112 113 if self.device is not None: 114 cmd_flash.extend(['--port', self.device]) 115 116 if self.erase is True: 117 cmd_erase = cmd_flash + ['erase_flash'] 118 self.check_call(cmd_erase) 119 120 if self.no_stub is True: 121 cmd_flash.extend(['--no-stub']) 122 cmd_flash.extend(['--baud', self.baud]) 123 cmd_flash.extend(['--before', 'default_reset']) 124 if self.reset: 125 cmd_flash.extend(['--after', 'hard_reset', 'write_flash', '-u']) 126 cmd_flash.extend(['--flash_mode', self.flash_mode]) 127 cmd_flash.extend(['--flash_freq', self.flash_freq]) 128 cmd_flash.extend(['--flash_size', self.flash_size]) 129 130 if self.encrypt: 131 cmd_flash.extend(['--encrypt']) 132 133 if self.bootloader_bin: 134 cmd_flash.extend([self.boot_address, self.bootloader_bin]) 135 if self.partition_table_bin: 136 cmd_flash.extend([self.part_table_address, self.partition_table_bin]) 137 cmd_flash.extend([self.app_address, self.app_bin]) 138 else: 139 cmd_flash.extend([self.app_address, self.app_bin]) 140 141 self.logger.info(f"Flashing esp32 chip on {self.device} ({self.baud}bps)") 142 self.check_call(cmd_flash) 143