2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								#!/usr/bin/env python  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								#  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ESP8266 & ESP32 ROM Bootloader Utility  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# Copyright (C) 2014-2016 Fredrik Ahlberg, Angus Gratton, Espressif Systems (Shanghai) PTE LTD, other contributors as noted.  
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# https://github.com/espressif/esptool  
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								#  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# This program is free software; you can redistribute it and/or modify it under  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# the terms of the GNU General Public License as published by the Free Software  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# Foundation; either version 2 of the License, or (at your option) any later version.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								#  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# This program is distributed in the hope that it will be useful, but WITHOUT  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								#  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# You should have received a copy of the GNU General Public License along with  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# Street, Fifth Floor, Boston, MA 02110-1301 USA.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  __future__  import  print_function ,  division  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								import  argparse  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  hashlib  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  inspect  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  os  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  serial  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  struct  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  sys  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  time  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  base64  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  zlib  
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  shlex  
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-06 20:29:12 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								__version__  =  " 2.0-beta3 "  
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								MAX_UINT32  =  0xffffffff  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								MAX_UINT24  =  0xffffff  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  check_supported_function ( func ,  check_func ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Decorator  implementation  that  wraps  a  check  around  an  ESPLoader 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bootloader  function  to  check  if  it ' s supported. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    This  is  used  to  capture  the  multidimensional  differences  in 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    functionality  between  the  ESP8266  &  ESP32  ROM  loaders ,  and  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    software  stub  that  runs  on  both .  Not  possible  to  do  this  cleanly 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    via  inheritance  alone . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  inner ( * args ,  * * kwargs ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        obj  =  args [ 0 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  check_func ( obj ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  func ( * args ,  * * kwargs ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-30 01:28:30 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            raise  NotImplementedInROMError ( obj ,  func ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    return  inner 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  stub_function_only ( func ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Attribute for a function only supported in the software stub loader  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  check_supported_function ( func ,  lambda  o :  o . IS_STUB ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  stub_and_esp32_function_only ( func ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Attribute for a function only supported by software stubs or ESP32 ROM  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  check_supported_function ( func ,  lambda  o :  o . IS_STUB  or  o . CHIP_NAME  ==  " ESP32 " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								PYTHON2  =  sys . version_info [ 0 ]  <  3   # True if on pre-Python 3  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# Function to return nth byte of a bitstring  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# Different behaviour on Python 2 vs 3  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								if  PYTHON2 :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  byte ( bitstr ,  index ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  ord ( bitstr [ index ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								else :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  byte ( bitstr ,  index ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  bitstr [ index ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								def  esp8266_function_only ( func ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Attribute for a function only supported on ESP8266  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  check_supported_function ( func ,  lambda  o :  o . CHIP_NAME  ==  " ESP8266 " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  ESPLoader ( object ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Base class providing access to ESP ROM & softtware stub bootloaders. 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Subclasses  provide  ESP8266  &  ESP32  specific  functionality . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Don ' t instantiate this base class directly, either instantiate a subclass or 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    call  ESPLoader . detect_chip ( )  which  will  interrogate  the  chip  and  return  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    appropriate  subclass  instance . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    CHIP_NAME  =  " Espressif device " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    IS_STUB  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DEFAULT_PORT  =  " /dev/ttyUSB0 " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Commands supported by ESP8266 ROM bootloader 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ESP_FLASH_BEGIN  =  0x02 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ESP_FLASH_DATA   =  0x03 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ESP_FLASH_END    =  0x04 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ESP_MEM_BEGIN    =  0x05 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ESP_MEM_END      =  0x06 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ESP_MEM_DATA     =  0x07 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ESP_SYNC         =  0x08 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ESP_WRITE_REG    =  0x09 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ESP_READ_REG     =  0x0a 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Some comands supported by ESP32 ROM bootloader (or -8266 w/ stub) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ESP_SPI_SET_PARAMS  =  0x0B 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ESP_SPI_ATTACH      =  0x0D 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ESP_CHANGE_BAUDRATE  =  0x0F 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ESP_FLASH_DEFL_BEGIN  =  0x10 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ESP_FLASH_DEFL_DATA   =  0x11 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ESP_FLASH_DEFL_END    =  0x12 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ESP_SPI_FLASH_MD5     =  0x13 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Some commands supported by stub only 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ESP_ERASE_FLASH  =  0xD0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ESP_ERASE_REGION  =  0xD1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ESP_READ_FLASH  =  0xD2 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    ESP_RUN_USER_CODE  =  0xD3 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Maximum block sized for RAM and Flash writes, respectively. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ESP_RAM_BLOCK    =  0x1800 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-12-30 01:28:30 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    FLASH_WRITE_SIZE  =  0x400 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Default baudrate. The ROM auto-bauds, so we can use more or less whatever we want. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ESP_ROM_BAUD     =  115200 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # First byte of the application image 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ESP_IMAGE_MAGIC  =  0xe9 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Initial state for the checksum routine 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ESP_CHECKSUM_MAGIC  =  0xef 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Flash sector size, minimum unit of erase. 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-30 01:28:30 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    FLASH_SECTOR_SIZE  =  0x1000 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    UART_DATA_REG_ADDR  =  0x60000078 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Memory addresses 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    IROM_MAP_START  =  0x40200000 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    IROM_MAP_END  =  0x40300000 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # The number of bytes in the UART response that signify command status 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    STATUS_BYTES_LENGTH  =  2 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  __init__ ( self ,  port = DEFAULT_PORT ,  baud = ESP_ROM_BAUD ) : 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        """ Base constructor for ESPLoader bootloader interaction 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Don ' t call this constructor, either instantiate ESP8266ROM 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        or  ESP32ROM ,  or  use  ESPLoader . detect_chip ( ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        This  base  class  has  all  of  the  instance  methods  for  bootloader 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        functionality  supported  across  various  chips  &  stub 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        loaders .  Subclasses  replace  the  functions  they  don ' t support 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        with  ones  which  throw  NotImplementedInROMError ( ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  isinstance ( port ,  serial . Serial ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . _port  =  port 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            self . _port  =  serial . serial_for_url ( port ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        self . _slip_reader  =  slip_reader ( self . _port ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # setting baud rate in a separate step is a workaround for 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # CH341 driver on some Linux versions (this opens at 9600 then 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # sets), shouldn't matter for other platforms/drivers. See 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        # https://github.com/espressif/esptool/issues/44#issuecomment-107094446 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        self . _port . baudrate  =  baud 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    @staticmethod 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  detect_chip ( port = DEFAULT_PORT ,  baud = ESP_ROM_BAUD ,  connect_mode = ' default_reset ' ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """  Use serial access to detect the chip type. 
 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        We  use  the  UART ' s datecode register for this, it ' s  mapped  at 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        the  same  address  on  ESP8266  &  ESP32  so  we  can  use  one 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        memory  read  and  compare  to  the  datecode  register  for  each  chip 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        type . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        This  routine  automatically  performs  ESPLoader . connect ( )  ( passing 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        connect_mode  parameter )  as  part  of  querying  the  chip . 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        """ 
 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        detect_port  =  ESPLoader ( port ,  baud ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        detect_port . connect ( connect_mode ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        print ( ' Detecting chip type... ' ,  end = ' ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        sys . stdout . flush ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        date_reg  =  detect_port . read_reg ( ESPLoader . UART_DATA_REG_ADDR ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  cls  in  [ ESP8266ROM ,  ESP32ROM ] : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  date_reg  ==  cls . DATE_REG_VALUE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # don't connect a second time 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                inst  =  cls ( detect_port . _port ,  baud ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                print ( '   %s '  %  inst . CHIP_NAME ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                return  inst 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        print ( ' ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        raise  FatalError ( " Unexpected UART datecode value 0x %08x . Failed to autodetect chip type. "  %  date_reg ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Read a SLIP packet from the serial port  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  read ( self ) : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  next ( self . _slip_reader ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Write bytes to the serial port while performing SLIP escaping  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  write ( self ,  packet ) : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        buf  =  b ' \xc0 '  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              +  ( packet . replace ( b ' \xdb ' , b ' \xdb \xdd ' ) . replace ( b ' \xc0 ' , b ' \xdb \xdc ' ) )  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              +  b ' \xc0 ' 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        self . _port . write ( buf ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Calculate checksum of a blob, as it is defined by the ROM  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    @staticmethod 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  checksum ( data ,  state = ESP_CHECKSUM_MAGIC ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  b  in  data : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  type ( b )  is  int :   # python 2/3 compat 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                state  ^ =  b 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                state  ^ =  ord ( b ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        return  state 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Send a request and read the response  """ 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  command ( self ,  op = None ,  data = b " " ,  chk = 0 ,  wait_response = True ) : 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        if  op  is  not  None : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            pkt  =  struct . pack ( b ' <BBHI ' ,  0x00 ,  op ,  len ( data ) ,  chk )  +  data 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            self . write ( pkt ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  not  wait_response : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        # tries to get a response until that response has the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # same operation as the request or a retries limit has 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # exceeded. This is needed for some esp8266s that 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # reply with more sync responses than expected. 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        for  retry  in  range ( 100 ) : 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            p  =  self . read ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  len ( p )  <  8 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ( resp ,  op_ret ,  len_ret ,  val )  =  struct . unpack ( ' <BBHI ' ,  p [ : 8 ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  resp  !=  1 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            data  =  p [ 8 : ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  op  is  None  or  op_ret  ==  op : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return  val ,  data 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        raise  FatalError ( " Response doesn ' t match request " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  check_command ( self ,  op_description ,  op = None ,  data = b ' ' ,  chk = 0 ) : 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Execute  a  command  with  ' command ' ,  check  the  result  code  and  throw  an  appropriate 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        FatalError  if  it  fails . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Returns  the  " result "  of  a  successful  command . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        val ,  data  =  self . command ( op ,  data ,  chk ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # things are a bit weird here, bear with us 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # the status bytes are the last 2/4 bytes in the data (depending on chip) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  len ( data )  <  self . STATUS_BYTES_LENGTH : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            raise  FatalError ( " Failed to  %s . Only got  %d  byte status response. "  %  ( op_description ,  len ( data ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        status_bytes  =  data [ - self . STATUS_BYTES_LENGTH : ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # we only care if the first one is non-zero. If it is, the second byte is a reason. 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  byte ( status_bytes ,  0 )  !=  0 : 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            raise  FatalError . WithResult ( ' Failed to  %s '  %  op_description ,  status_bytes ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # if we had more data than just the status bytes, return it as the result 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # (this is used by the md5sum command, maybe other commands?) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  len ( data )  >  self . STATUS_BYTES_LENGTH : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  data [ : - self . STATUS_BYTES_LENGTH ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else :   # otherwise, just return the 'val' field which comes from the reply header (this is used by read_reg) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  val 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  flush_input ( self ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . _port . flushInput ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . _slip_reader  =  slip_reader ( self . _port ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  sync ( self ) : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        self . command ( self . ESP_SYNC ,  b ' \x07 \x07 \x12 \x20 '  +  32  *  b ' \x55 ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  i  in  range ( 7 ) : 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            self . command ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-03-10 15:40:14 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  _connect_attempt ( self ,  mode = ' default_reset ' ,  esp32r0_delay = False ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """  A single connection attempt, with esp32r0 workaround options  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # esp32r0_delay is a workaround for bugs with the most common auto reset 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # circuit and Windows, if the EN pin on the dev board does not have 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # enough capacitance. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # Newer dev boards shouldn't have this problem (higher value capacitor 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # on the EN pin), and ESP32 revision 1 can't use this workaround as it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # relies on a silicon bug. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # Details: https://github.com/espressif/esptool/issues/136 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        last_error  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # issue reset-to-bootloader: 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # RTS = either CH_PD/EN or nRESET (both active low = chip in reset 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # DTR = GPIO0 (active low = boot to flasher) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # DTR & RTS are active low signals, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # ie True = pin @ 0V, False = pin @ VCC. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  mode  !=  ' no_reset ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . _port . setDTR ( False )   # IO0=HIGH 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . _port . setRTS ( True )    # EN=LOW, chip in reset 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            time . sleep ( 0.1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  esp32r0_delay : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # Some chips are more likely to trigger the esp32r0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # watchdog reset silicon bug if they're held with EN=LOW 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # for a longer period 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                time . sleep ( 1.2 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . _port . setDTR ( True )    # IO0=LOW 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . _port . setRTS ( False )   # EN=HIGH, chip out of reset 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  esp32r0_delay : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # Sleep longer after reset. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # This workaround only works on revision 0 ESP32 chips, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # it exploits a silicon bug spurious watchdog reset. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                time . sleep ( 0.4 )   # allow watchdog reset to occur 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            time . sleep ( 0.05 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . _port . setDTR ( False )   # IO0=HIGH, done 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . _port . timeout  =  0.1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  _  in  range ( 5 ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                self . flush_input ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                self . _port . flushOutput ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                self . sync ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                self . _port . timeout  =  5 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            except  FatalError  as  e : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  esp32r0_delay : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    print ( ' _ ' ,  end = ' ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    print ( ' . ' ,  end = ' ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                sys . stdout . flush ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                time . sleep ( 0.05 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                last_error  =  e 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  last_error 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  connect ( self ,  mode = ' default_reset ' ) : 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        """  Try connecting repeatedly until successful, or giving up  """ 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        print ( ' Connecting... ' ,  end = ' ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        sys . stdout . flush ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        last_error  =  None 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  _  in  range ( 10 ) : 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-10 15:40:14 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                last_error  =  self . _connect_attempt ( mode = mode ,  esp32r0_delay = False ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  last_error  is  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                last_error  =  self . _connect_attempt ( mode = mode ,  esp32r0_delay = True ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  last_error  is  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    return 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        finally : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            print ( ' ' )   # end 'Connecting...' line 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        raise  FatalError ( ' Failed to connect to  %s :  %s '  %  ( self . CHIP_NAME ,  last_error ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Read memory address in target  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  read_reg ( self ,  addr ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # we don't call check_command here because read_reg() function is called 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # when detecting chip type, and the way we check for success (STATUS_BYTES_LENGTH) is different 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # for different chip types (!) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        val ,  data  =  self . command ( self . ESP_READ_REG ,  struct . pack ( ' <I ' ,  addr ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  byte ( data ,  0 )  !=  0 : 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            raise  FatalError . WithResult ( " Failed to read register address  %08x "  %  addr ,  data ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  val 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Write to memory address in target  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  write_reg ( self ,  addr ,  value ,  mask = 0xFFFFFFFF ,  delay_us = 0 ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  self . check_command ( " write target memory " ,  self . ESP_WRITE_REG , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                  struct . pack ( ' <IIII ' ,  addr ,  value ,  mask ,  delay_us ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Start downloading an application image to RAM  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  mem_begin ( self ,  size ,  blocks ,  blocksize ,  offset ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  self . check_command ( " enter RAM download mode " ,  self . ESP_MEM_BEGIN , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                  struct . pack ( ' <IIII ' ,  size ,  blocks ,  blocksize ,  offset ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Send a block of an image to RAM  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  mem_block ( self ,  data ,  seq ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  self . check_command ( " write to target RAM " ,  self . ESP_MEM_DATA , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                  struct . pack ( ' <IIII ' ,  len ( data ) ,  seq ,  0 ,  0 )  +  data , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                  self . checksum ( data ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Leave download mode and run the application  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  mem_finish ( self ,  entrypoint = 0 ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  self . check_command ( " leave RAM download mode " ,  self . ESP_MEM_END , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                  struct . pack ( ' <II ' ,  int ( entrypoint  ==  0 ) ,  entrypoint ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-12-30 01:28:30 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    """  Start downloading to Flash (performs an erase) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Returns  number  of  blocks  ( of  size  self . FLASH_WRITE_SIZE )  to  write . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    def  flash_begin ( self ,  size ,  offset ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        old_tmo  =  self . _port . timeout 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        num_blocks  =  ( size  +  self . FLASH_WRITE_SIZE  -  1 )  / /  self . FLASH_WRITE_SIZE 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        erase_size  =  self . get_erase_size ( offset ,  size ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . _port . timeout  =  20 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        t  =  time . time ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . check_command ( " enter Flash download mode " ,  self . ESP_FLASH_BEGIN , 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-30 01:28:30 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                           struct . pack ( ' <IIII ' ,  erase_size ,  num_blocks ,  self . FLASH_WRITE_SIZE ,  offset ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  size  !=  0  and  not  self . IS_STUB : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            print ( " Took  %.2f s to erase flash block "  %  ( time . time ( )  -  t ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        self . _port . timeout  =  old_tmo 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-30 01:28:30 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  num_blocks 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Write block to flash  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  flash_block ( self ,  data ,  seq ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . check_command ( " write to target Flash after seq  %d "  %  seq , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                           self . ESP_FLASH_DATA , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                           struct . pack ( ' <IIII ' ,  len ( data ) ,  seq ,  0 ,  0 )  +  data , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                           self . checksum ( data ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Leave flash mode and run/reboot  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  flash_finish ( self ,  reboot = False ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        pkt  =  struct . pack ( ' <I ' ,  int ( not  reboot ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        # stub sends a reply to this command 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        self . check_command ( " leave Flash mode " ,  self . ESP_FLASH_END ,  pkt ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Run application code in flash  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  run ( self ,  reboot = False ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # Fake flash begin immediately followed by flash end 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . flash_begin ( 0 ,  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . flash_finish ( reboot ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Read SPI flash manufacturer and device id  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  flash_id ( self ) : 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        SPIFLASH_RDID  =  0x9F 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  self . run_spiflash_command ( SPIFLASH_RDID ,  b " " ,  24 ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  parse_flash_size_arg ( self ,  arg ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  self . FLASH_SIZES [ arg ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        except  KeyError : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            raise  FatalError ( " Flash size  ' %s '  is not supported by this chip type. Supported sizes:  %s " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                             %  ( arg ,  " ,  " . join ( self . FLASH_SIZES . keys ( ) ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  run_stub ( self ,  stub = None ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  stub  is  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  self . IS_STUB : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                raise  FatalError ( " Not possible for a stub to load another stub (memory likely to overlap.) " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            stub  =  self . STUB_CODE 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # Upload 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        print ( " Uploading stub... " ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        for  field  in  [ ' text ' ,  ' data ' ] : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  field  in  stub : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                offs  =  stub [ field  +  " _start " ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                length  =  len ( stub [ field ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                blocks  =  ( length  +  self . ESP_RAM_BLOCK  -  1 )  / /  self . ESP_RAM_BLOCK 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                self . mem_begin ( length ,  blocks ,  self . ESP_RAM_BLOCK ,  offs ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                for  seq  in  range ( blocks ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    from_offs  =  seq  *  self . ESP_RAM_BLOCK 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    to_offs  =  from_offs  +  self . ESP_RAM_BLOCK 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    self . mem_block ( stub [ field ] [ from_offs : to_offs ] ,  seq ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        print ( " Running stub... " ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        self . mem_finish ( stub [ ' entry ' ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        p  =  self . read ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  p  !=  b ' OHAI ' : 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            raise  FatalError ( " Failed to start stub. Unexpected response:  %s "  %  p ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        print ( " Stub running... " ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        return  self . STUB_CLASS ( self ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    @stub_and_esp32_function_only 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  flash_defl_begin ( self ,  size ,  compsize ,  offset ) : 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-30 01:28:30 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        """  Start downloading compressed data to Flash (performs an erase) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Returns  number  of  blocks  ( size  self . FLASH_WRITE_SIZE )  to  write . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """ 
 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        old_tmo  =  self . _port . timeout 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        num_blocks  =  ( compsize  +  self . FLASH_WRITE_SIZE  -  1 )  / /  self . FLASH_WRITE_SIZE 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        erase_blocks  =  ( size  +  self . FLASH_WRITE_SIZE  -  1 )  / /  self . FLASH_WRITE_SIZE 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . _port . timeout  =  20 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        t  =  time . time ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  self . IS_STUB : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            write_size  =  size   # stub expects number of bytes here, manages erasing internally 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            write_size  =  erase_blocks  *  self . FLASH_WRITE_SIZE   # ROM expects rounded up to erase block size 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        print ( " Compressed  %d  bytes to  %d ... "  %  ( size ,  compsize ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        self . check_command ( " enter compressed flash mode " ,  self . ESP_FLASH_DEFL_BEGIN , 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                           struct . pack ( ' <IIII ' ,  write_size ,  num_blocks ,  self . FLASH_WRITE_SIZE ,  offset ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        if  size  !=  0  and  not  self . IS_STUB : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # (stub erases as it writes, but ROM loaders erase on begin) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            print ( " Took  %.2f s to erase flash block "  %  ( time . time ( )  -  t ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        self . _port . timeout  =  old_tmo 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-30 01:28:30 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  num_blocks 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Write block to flash, send compressed  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    @stub_and_esp32_function_only 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  flash_defl_block ( self ,  data ,  seq ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . check_command ( " write compressed data to flash after seq  %d "  %  seq , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                           self . ESP_FLASH_DEFL_DATA ,  struct . pack ( ' <IIII ' ,  len ( data ) ,  seq ,  0 ,  0 )  +  data ,  self . checksum ( data ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Leave compressed flash mode and run/reboot  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    @stub_and_esp32_function_only 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  flash_defl_finish ( self ,  reboot = False ) : 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  not  reboot  and  not  self . IS_STUB : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # skip sending flash_finish to ROM loader, as this 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # exits the bootloader. Stub doesn't do this. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        pkt  =  struct . pack ( ' <I ' ,  int ( not  reboot ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . check_command ( " leave compressed flash mode " ,  self . ESP_FLASH_DEFL_END ,  pkt ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . in_bootloader  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    @stub_and_esp32_function_only 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  flash_md5sum ( self ,  addr ,  size ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # the MD5 command returns additional bytes in the standard 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # command reply slot 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        res  =  self . check_command ( ' calculate md5sum ' ,  self . ESP_SPI_FLASH_MD5 ,  struct . pack ( ' <IIII ' ,  addr ,  size ,  0 ,  0 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  len ( res )  ==  32 : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            return  res . decode ( " utf-8 " )   # already hex formatted 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        elif  len ( res )  ==  16 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  hexify ( res ) . lower ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            raise  FatalError ( " MD5Sum command returned unexpected result:  %r "  %  res ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    @stub_and_esp32_function_only 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  change_baud ( self ,  baud ) : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        print ( " Changing baud rate to  %d "  %  baud ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        self . command ( self . ESP_CHANGE_BAUDRATE ,  struct . pack ( ' <II ' ,  baud ,  0 ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        print ( " Changed. " ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        self . _port . baudrate  =  baud 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        time . sleep ( 0.05 )   # get rid of crap sent during baud rate change 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . flush_input ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    @stub_function_only 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  erase_flash ( self ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        oldtimeout  =  self . _port . timeout 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # depending on flash chip model the erase may take this long (maybe longer!) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . _port . timeout  =  128 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . check_command ( " erase flash " ,  self . ESP_ERASE_FLASH ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        finally : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . _port . timeout  =  oldtimeout 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    @stub_function_only 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  erase_region ( self ,  offset ,  size ) : 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-30 01:28:30 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  offset  %  self . FLASH_SECTOR_SIZE  !=  0 : 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            raise  FatalError ( " Offset to erase from must be a multiple of 4096 " ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-30 01:28:30 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  size  %  self . FLASH_SECTOR_SIZE  !=  0 : 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            raise  FatalError ( " Size of data to erase must be a multiple of 4096 " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . check_command ( " erase region " ,  self . ESP_ERASE_REGION ,  struct . pack ( ' <II ' ,  offset ,  size ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    @stub_function_only 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  read_flash ( self ,  offset ,  length ,  progress_fn = None ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # issue a standard bootloader command to trigger the read 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . check_command ( " read flash " ,  self . ESP_READ_FLASH , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                           struct . pack ( ' <IIII ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                       offset , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                       length , 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-30 01:28:30 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                                       self . FLASH_SECTOR_SIZE , 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                                       64 ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        # now we expect (length // block_size) SLIP frames with the data 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        data  =  b ' ' 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        while  len ( data )  <  length : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            p  =  self . read ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            data  + =  p 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . write ( struct . pack ( ' <I ' ,  len ( data ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  progress_fn  and  ( len ( data )  %  1024  ==  0  or  len ( data )  ==  length ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                progress_fn ( len ( data ) ,  length ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  progress_fn : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            progress_fn ( len ( data ) ,  length ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  len ( data )  >  length : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            raise  FatalError ( ' Read more than expected ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        digest_frame  =  self . read ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  len ( digest_frame )  !=  16 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            raise  FatalError ( ' Expected digest, got:  %s '  %  hexify ( digest_frame ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        expected_digest  =  hexify ( digest_frame ) . upper ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        digest  =  hashlib . md5 ( data ) . hexdigest ( ) . upper ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  digest  !=  expected_digest : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            raise  FatalError ( ' Digest mismatch: expected  %s , got  %s '  %  ( expected_digest ,  digest ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  data 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-06 20:29:12 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  flash_spi_attach ( self ,  hspi_arg ) : 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        """ Send SPI attach command to enable the SPI flash pins 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ESP8266  ROM  does  this  when  you  send  flash_begin ,  ESP32  ROM 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        has  it  as  a  SPI  command . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # last 3 bytes in ESP_SPI_ATTACH argument are reserved values 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-06 20:29:12 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        arg  =  struct . pack ( ' <I ' ,  hspi_arg ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  not  self . IS_STUB : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # ESP32 ROM loader takes additional 'is legacy' arg, which is not 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # currently supported in the stub loader or esptool.py (as it's not usually needed.) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            is_legacy  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            arg  + =  struct . pack ( ' BBBB ' ,  is_legacy ,  0 ,  0 ,  0 ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        self . check_command ( " configure SPI flash pins " ,  ESP32ROM . ESP_SPI_ATTACH ,  arg ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  flash_set_parameters ( self ,  size ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """ Tell the ESP bootloader the parameters of the chip 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Corresponds  to  the  " flashchip "  data  structure  that  the  ROM 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        has  in  RAM . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' size '  is  in  bytes . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        All  other  flash  parameters  are  currently  hardcoded  ( on  ESP8266 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        these  are  mostly  ignored  by  ROM  code ,  on  ESP32  I ' m not sure.) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        fl_id  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        total_size  =  size 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        block_size  =  64  *  1024 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        sector_size  =  4  *  1024 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        page_size  =  256 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        status_mask  =  0xffff 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . check_command ( " set SPI params " ,  ESP32ROM . ESP_SPI_SET_PARAMS , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                           struct . pack ( ' <IIIIII ' ,  fl_id ,  total_size ,  block_size ,  sector_size ,  page_size ,  status_mask ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  run_spiflash_command ( self ,  spiflash_command ,  data = b " " ,  read_bits = 0 ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """ Run an arbitrary SPI flash command. 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        This  function  uses  the  " USR_COMMAND "  functionality  in  the  ESP 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        SPI  hardware ,  rather  than  the  precanned  commands  supported  by 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        hardware .  So  the  value  of  spiflash_command  is  an  actual  command 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        byte ,  sent  over  the  wire . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        After  writing  command  byte ,  writes  ' data '  to  MOSI  and  then 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        reads  back  ' read_bits '  of  reply  on  MISO .  Result  is  a  number . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # SPI_USR register flags 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        SPI_USR_COMMAND  =  ( 1  <<  31 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        SPI_USR_MISO     =  ( 1  <<  28 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        SPI_USR_MOSI     =  ( 1  <<  27 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # SPI registers, base address differs ESP32 vs 8266 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        base  =  self . SPI_REG_BASE 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        SPI_CMD_REG        =  base  +  0x00 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        SPI_USR_REG        =  base  +  0x1C 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        SPI_USR1_REG       =  base  +  0x20 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        SPI_USR2_REG       =  base  +  0x24 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        SPI_W0_REG         =  base  +  self . SPI_W0_OFFS 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # following two registers are ESP32 only 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  self . SPI_HAS_MOSI_DLEN_REG : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # ESP32 has a more sophisticated wayto set up "user" commands 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            def  set_data_lengths ( mosi_bits ,  miso_bits ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                SPI_MOSI_DLEN_REG  =  base  +  0x28 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                SPI_MISO_DLEN_REG  =  base  +  0x2C 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  mosi_bits  >  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    self . write_reg ( SPI_MOSI_DLEN_REG ,  mosi_bits  -  1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  miso_bits  >  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    self . write_reg ( SPI_MISO_DLEN_REG ,  miso_bits  -  1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            def  set_data_lengths ( mosi_bits ,  miso_bits ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                SPI_DATA_LEN_REG  =  SPI_USR1_REG 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                SPI_MOSI_BITLEN_S  =  17 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                SPI_MISO_BITLEN_S  =  8 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                mosi_mask  =  0  if  ( mosi_bits  ==  0 )  else  ( mosi_bits  -  1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                miso_mask  =  0  if  ( miso_bits  ==  0 )  else  ( miso_bits  -  1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                self . write_reg ( SPI_DATA_LEN_REG , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                               ( miso_mask  <<  SPI_MISO_BITLEN_S )  |  ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                   mosi_mask  <<  SPI_MOSI_BITLEN_S ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # SPI peripheral "command" bitmasks for SPI_CMD_REG 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        SPI_CMD_USR   =  ( 1  <<  18 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # shift values 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        SPI_USR2_DLEN_SHIFT  =  28 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  read_bits  >  32 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            raise  FatalError ( " Reading more than 32 bits back from a SPI flash operation is unsupported " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  len ( data )  >  64 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            raise  FatalError ( " Writing more than 64 bytes of data with one SPI command is unsupported " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        data_bits  =  len ( data )  *  8 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        old_spi_usr  =  self . read_reg ( SPI_USR_REG ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        old_spi_usr2  =  self . read_reg ( SPI_USR2_REG ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        flags  =  SPI_USR_COMMAND 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  read_bits  >  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            flags  | =  SPI_USR_MISO 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  data_bits  >  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            flags  | =  SPI_USR_MOSI 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        set_data_lengths ( data_bits ,  read_bits ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . write_reg ( SPI_USR_REG ,  flags ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . write_reg ( SPI_USR2_REG , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                       ( 7  <<  SPI_USR2_DLEN_SHIFT )  |  spiflash_command ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  data_bits  ==  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . write_reg ( SPI_W0_REG ,  0 )   # clear data register before we read it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-10 15:40:14 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            data  =  pad_to ( data ,  4 ,  b ' \00 ' )   # pad to 32-bit multiple 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            words  =  struct . unpack ( " I "  *  ( len ( data )  / /  4 ) ,  data ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            next_reg  =  SPI_W0_REG 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  word  in  words : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                self . write_reg ( next_reg ,  word ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                next_reg  + =  4 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . write_reg ( SPI_CMD_REG ,  SPI_CMD_USR ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        def  wait_done ( ) : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            for  _  in  range ( 10 ) : 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                if  ( self . read_reg ( SPI_CMD_REG )  &  SPI_CMD_USR )  ==  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            raise  FatalError ( " SPI command did not complete in time " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        wait_done ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        status  =  self . read_reg ( SPI_W0_REG ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        # restore some SPI controller registers 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . write_reg ( SPI_USR_REG ,  old_spi_usr ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . write_reg ( SPI_USR2_REG ,  old_spi_usr2 ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  status 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  read_status ( self ,  num_bytes = 2 ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """ Read up to 24 bits (num_bytes) of SPI flash status register contents 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        via  RDSR ,  RDSR2 ,  RDSR3  commands 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Not  all  SPI  flash  supports  all  three  commands .  The  upper  1  or  2 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        bytes  may  be  0xFF . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        SPIFLASH_RDSR   =  0x05 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        SPIFLASH_RDSR2  =  0x35 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        SPIFLASH_RDSR3  =  0x15 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        status  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        shift  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  cmd  in  [ SPIFLASH_RDSR ,  SPIFLASH_RDSR2 ,  SPIFLASH_RDSR3 ] [ 0 : num_bytes ] : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            status  + =  self . run_spiflash_command ( cmd ,  read_bits = 8 )  <<  shift 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            shift  + =  8 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  status 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  write_status ( self ,  new_status ,  num_bytes = 2 ,  set_non_volatile = False ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """ Write up to 24 bits (num_bytes) of new status register 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        num_bytes  can  be  1 ,  2  or  3. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Not  all  flash  supports  the  additional  commands  to  write  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        second  and  third  byte  of  the  status  register .  When  writing  2 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        bytes ,  esptool  also  sends  a  16 - byte  WRSR  command  ( as  some 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        flash  types  use  this  instead  of  WRSR2 . ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        If  the  set_non_volatile  flag  is  set ,  non - volatile  bits  will 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        be  set  as  well  as  volatile  ones  ( WREN  used  instead  of  WEVSR ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        SPIFLASH_WRSR  =  0x01 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        SPIFLASH_WRSR2  =  0x31 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        SPIFLASH_WRSR3  =  0x11 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        SPIFLASH_WEVSR  =  0x50 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        SPIFLASH_WREN  =  0x06 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        SPIFLASH_WRDI  =  0x04 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        enable_cmd  =  SPIFLASH_WREN  if  set_non_volatile  else  SPIFLASH_WEVSR 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # try using a 16-bit WRSR (not supported by all chips) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # this may be redundant, but shouldn't hurt 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  num_bytes  ==  2 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . run_spiflash_command ( enable_cmd ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . run_spiflash_command ( SPIFLASH_WRSR ,  struct . pack ( " <H " ,  new_status ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # also try using individual commands (also not supported by all chips for num_bytes 2 & 3) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  cmd  in  [ SPIFLASH_WRSR ,  SPIFLASH_WRSR2 ,  SPIFLASH_WRSR3 ] [ 0 : num_bytes ] : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . run_spiflash_command ( enable_cmd ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . run_spiflash_command ( cmd ,  struct . pack ( " B " ,  new_status  &  0xFF ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            new_status  >> =  8 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . run_spiflash_command ( SPIFLASH_WRDI ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  hard_reset ( self ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . _port . setRTS ( True )   # EN->LOW 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        time . sleep ( 0.1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . _port . setRTS ( False ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  soft_reset ( self ,  stay_in_bootloader ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  not  self . IS_STUB : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  stay_in_bootloader : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return   # ROM bootloader is already in bootloader! 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # 'run user code' is as close to a soft reset as we can do 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                self . flash_begin ( 0 ,  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                self . flash_finish ( False ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  stay_in_bootloader : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # soft resetting from the stub loader 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # will re-load the ROM bootloader 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                self . flash_begin ( 0 ,  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                self . flash_finish ( True ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            elif  self . CHIP_NAME  !=  " ESP8266 " : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                raise  FatalError ( " Soft resetting is currently only supported on ESP8266 " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # running user code from stub loader requires some hacks 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # in the stub loader 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                self . command ( self . ESP_RUN_USER_CODE ,  wait_response = False ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  ESP8266ROM ( ESPLoader ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Access class for ESP8266 ROM bootloader 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    CHIP_NAME  =  " ESP8266 " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    IS_STUB  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DATE_REG_VALUE  =  0x00062000 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # OTP ROM addresses 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ESP_OTP_MAC0     =  0x3ff00050 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ESP_OTP_MAC1     =  0x3ff00054 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ESP_OTP_MAC3     =  0x3ff0005c 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    SPI_REG_BASE     =  0x60000200 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    SPI_W0_OFFS      =  0x40 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    SPI_HAS_MOSI_DLEN_REG  =  False 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    FLASH_SIZES  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' 512KB ' : 0x00 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' 256KB ' : 0x10 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' 1MB ' : 0x20 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' 2MB ' : 0x30 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' 4MB ' : 0x40 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' 2MB-c1 ' :  0x50 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' 4MB-c1 ' : 0x60 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' 4MB-c2 ' : 0x70 } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    FLASH_HEADER_OFFSET  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-06 20:29:12 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  flash_spi_attach ( self ,  hspi_arg ) : 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  self . IS_STUB : 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-06 20:29:12 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            super ( ESP8266ROM ,  self ) . flash_spi_attach ( hspi_arg ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # ESP8266 ROM has no flash_spi_attach command in serial protocol, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # but flash_begin will do it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . flash_begin ( 0 ,  0 ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  flash_set_parameters ( self ,  size ) : 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        # not implemented in ROM, but OK to silently skip for ROM 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  self . IS_STUB : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            super ( ESP8266ROM ,  self ) . flash_set_parameters ( size ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  chip_id ( self ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """  Read Chip ID from OTP ROM - see http://esp8266-re.foogod.com/wiki/System_get_chip_id_ % 28IoT_RTOS_SDK_0.9.9 % 29  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        id0  =  self . read_reg ( self . ESP_OTP_MAC0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        id1  =  self . read_reg ( self . ESP_OTP_MAC1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  ( id0  >>  24 )  |  ( ( id1  &  MAX_UINT24 )  <<  8 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  read_mac ( self ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """  Read MAC from OTP ROM  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        mac0  =  self . read_reg ( self . ESP_OTP_MAC0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        mac1  =  self . read_reg ( self . ESP_OTP_MAC1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        mac3  =  self . read_reg ( self . ESP_OTP_MAC3 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( mac3  !=  0 ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            oui  =  ( ( mac3  >>  16 )  &  0xff ,  ( mac3  >>  8 )  &  0xff ,  mac3  &  0xff ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        elif  ( ( mac1  >>  16 )  &  0xff )  ==  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            oui  =  ( 0x18 ,  0xfe ,  0x34 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        elif  ( ( mac1  >>  16 )  &  0xff )  ==  1 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            oui  =  ( 0xac ,  0xd0 ,  0x74 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            raise  FatalError ( " Unknown OUI " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  oui  +  ( ( mac1  >>  8 )  &  0xff ,  mac1  &  0xff ,  ( mac0  >>  24 )  &  0xff ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  get_erase_size ( self ,  offset ,  size ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """  Calculate an erase size given a specific size in bytes. 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Provides  a  workaround  for  the  bootloader  erase  bug . """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        sectors_per_block  =  16 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-30 01:28:30 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        sector_size  =  self . FLASH_SECTOR_SIZE 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        num_sectors  =  ( size  +  sector_size  -  1 )  / /  sector_size 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        start_sector  =  offset  / /  sector_size 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        head_sectors  =  sectors_per_block  -  ( start_sector  %  sectors_per_block ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  num_sectors  <  head_sectors : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            head_sectors  =  num_sectors 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  num_sectors  <  2  *  head_sectors : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            return  ( num_sectors  +  1 )  / /  2  *  sector_size 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  ( num_sectors  -  head_sectors )  *  sector_size 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  ESP8266StubLoader ( ESP8266ROM ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Access class for ESP8266 stub loader, runs on top of ROM. 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    FLASH_WRITE_SIZE  =  0x4000   # matches MAX_WRITE_BLOCK in stub_loader.c 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    IS_STUB  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  __init__ ( self ,  rom_loader ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . _port  =  rom_loader . _port 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . flush_input ( )   # resets _slip_reader 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-12-30 01:28:30 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  get_erase_size ( self ,  offset ,  size ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  size   # stub doesn't have same size bug as ROM loader 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								ESP8266ROM . STUB_CLASS  =  ESP8266StubLoader  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  ESP32ROM ( ESPLoader ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ Access class for ESP32 ROM bootloader 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    CHIP_NAME  =  " ESP32 " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    IS_STUB  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DATE_REG_VALUE  =  0x15122500 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    IROM_MAP_START  =  0x400d0000 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    IROM_MAP_END    =  0x40400000 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DROM_MAP_START  =  0x3F400000 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DROM_MAP_END    =  0x3F700000 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # ESP32 uses a 4 byte status reply 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    STATUS_BYTES_LENGTH  =  4 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    SPI_REG_BASE    =  0x60002000 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    EFUSE_REG_BASE  =  0x6001a000 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    SPI_W0_OFFS  =  0x80 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    SPI_HAS_MOSI_DLEN_REG  =  True 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    FLASH_SIZES  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' 1MB ' : 0x00 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' 2MB ' : 0x10 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' 4MB ' : 0x20 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' 8MB ' : 0x30 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' 16MB ' : 0x40 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    FLASH_HEADER_OFFSET  =  0x1000 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    def  read_efuse ( self ,  n ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """  Read the nth word of the ESP3x EFUSE region.  """ 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  self . read_reg ( self . EFUSE_REG_BASE  +  ( 4  *  n ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  chip_id ( self ) : 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        word16  =  self . read_efuse ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        word17  =  self . read_efuse ( 2 ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        return  ( ( word17  &  MAX_UINT24 )  <<  24 )  |  ( word16  >>  8 )  &  MAX_UINT24 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  read_mac ( self ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """  Read MAC from EFUSE region  """ 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-10 15:40:14 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        words  =  [ self . read_efuse ( 2 ) ,  self . read_efuse ( 1 ) ] 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        bitstring  =  struct . pack ( " >II " ,  * words ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-10 15:40:14 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        bitstring  =  bitstring [ 2 : 8 ]   # trim the 2 byte CRC 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        try : 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-10 15:40:14 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            return  tuple ( ord ( b )  for  b  in  bitstring ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        except  TypeError :   # Python 3, bitstring elements are already bytes 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  tuple ( bitstring ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  get_erase_size ( self ,  offset ,  size ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  size 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  ESP32StubLoader ( ESP32ROM ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Access class for ESP32 stub loader, runs on top of ROM. 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    FLASH_WRITE_SIZE  =  0x4000   # matches MAX_WRITE_BLOCK in stub_loader.c 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    STATUS_BYTES_LENGTH  =  2   # same as ESP8266, different to ESP32 ROM 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    IS_STUB  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  __init__ ( self ,  rom_loader ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . _port  =  rom_loader . _port 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . flush_input ( )   # resets _slip_reader 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								ESP32ROM . STUB_CLASS  =  ESP32StubLoader  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  ESPBOOTLOADER ( object ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  These are constants related to software ESP bootloader, working with  ' v2 '  image files  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # First byte of the "v2" application image 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    IMAGE_V2_MAGIC  =  0xea 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # First 'segment' value in a "v2" application image, appears to be a constant version value? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    IMAGE_V2_SEGMENT  =  4 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  LoadFirmwareImage ( chip ,  filename ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Load a firmware image. Can be for ESP8266 or ESP32. ESP8266 images will be examined to determine if they are 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        original  ROM  firmware  images  ( ESPFirmwareImage )  or  " v2 "  OTA  bootloader  images . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Returns  a  BaseFirmwareImage  subclass ,  either  ESPFirmwareImage  ( v1 )  or  OTAFirmwareImage  ( v2 ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    with  open ( filename ,  ' rb ' )  as  f : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  chip  ==  ' esp32 ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  ESP32FirmwareImage ( f ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else :   # Otherwise, ESP8266 so look at magic to determine the image type 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            magic  =  ord ( f . read ( 1 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            f . seek ( 0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  magic  ==  ESPLoader . ESP_IMAGE_MAGIC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return  ESPFirmwareImage ( f ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            elif  magic  ==  ESPBOOTLOADER . IMAGE_V2_MAGIC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return  OTAFirmwareImage ( f ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                raise  FatalError ( " Invalid image magic number:  %d "  %  magic ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  ImageSegment ( object ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Wrapper class for a segment in an ESP image 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ( very  similar  to  a  section  in  an  ELFImage  also )  """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  __init__ ( self ,  addr ,  data ,  file_offs = None ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . addr  =  addr 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # pad all ImageSegments to at least 4 bytes length 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-10 15:40:14 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        self . data  =  pad_to ( data ,  4 ,  b ' \x00 ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        self . file_offs  =  file_offs 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        self . include_in_checksum  =  True 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  copy_with_new_addr ( self ,  new_addr ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """  Return a new ImageSegment with same data, but mapped at 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        a  new  address .  """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  ImageSegment ( new_addr ,  self . data ,  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  __repr__ ( self ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        r  =  " len 0x %05x  load 0x %08x "  %  ( len ( self . data ) ,  self . addr ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  self . file_offs  is  not  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            r  + =  "  file_offs 0x %08x "  %  ( self . file_offs ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  r 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  ELFSection ( ImageSegment ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Wrapper class for a section in an ELF image, has a section 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    name  as  well  as  the  common  properties  of  an  ImageSegment .  """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  __init__ ( self ,  name ,  addr ,  data ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        super ( ELFSection ,  self ) . __init__ ( addr ,  data ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        self . name  =  name . decode ( " utf-8 " ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  __repr__ ( self ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  " %s   %s "  %  ( self . name ,  super ( ELFSection ,  self ) . __repr__ ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  BaseFirmwareImage ( object ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    SEG_HEADER_LEN  =  8 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Base class with common firmware image functions  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  __init__ ( self ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . segments  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . entrypoint  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  load_common_header ( self ,  load_file ,  expected_magic ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ( magic ,  segments ,  self . flash_mode ,  self . flash_size_freq ,  self . entrypoint )  =  struct . unpack ( ' <BBBBI ' ,  load_file . read ( 8 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  magic  !=  expected_magic  or  segments  >  16 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                raise  FatalError ( ' Invalid firmware image magic= %d  segments= %d '  %  ( magic ,  segments ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  segments 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  load_segment ( self ,  f ,  is_irom_segment = False ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """  Load the next segment from the image file  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        file_offs  =  f . tell ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ( offset ,  size )  =  struct . unpack ( ' <II ' ,  f . read ( 8 ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        self . warn_if_unusual_segment ( offset ,  size ,  is_irom_segment ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        segment_data  =  f . read ( size ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  len ( segment_data )  <  size : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            raise  FatalError ( ' End of file reading segment 0x %x , length  %d  (actual length  %d ) '  %  ( offset ,  size ,  len ( segment_data ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        segment  =  ImageSegment ( offset ,  segment_data ,  file_offs ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . segments . append ( segment ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  segment 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  warn_if_unusual_segment ( self ,  offset ,  size ,  is_irom_segment ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  not  is_irom_segment : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  offset  >  0x40200000  or  offset  <  0x3ffe0000  or  size  >  65536 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                print ( ' WARNING: Suspicious segment 0x %x , length  %d '  %  ( offset ,  size ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    def  save_segment ( self ,  f ,  segment ,  checksum = None ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """  Save the next segment to the image file, return next checksum value if provided  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        f . write ( struct . pack ( ' <II ' ,  segment . addr ,  len ( segment . data ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        f . write ( segment . data ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  checksum  is  not  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  ESPLoader . checksum ( segment . data ,  checksum ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  read_checksum ( self ,  f ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """  Return ESPLoader checksum from end of just-read image  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # Skip the padding. The checksum is stored in the last byte so that the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # file is a multiple of 16 bytes. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        align_file_position ( f ,  16 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  ord ( f . read ( 1 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  calculate_checksum ( self ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """  Calculate checksum of loaded image, based on segments in 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        segment  array . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        checksum  =  ESPLoader . ESP_CHECKSUM_MAGIC 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  seg  in  self . segments : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  seg . include_in_checksum : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                checksum  =  ESPLoader . checksum ( seg . data ,  checksum ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  checksum 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    def  append_checksum ( self ,  f ,  checksum ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """  Append ESPLoader checksum to the just-written image  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        align_file_position ( f ,  16 ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        f . write ( struct . pack ( b ' B ' ,  checksum ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  write_common_header ( self ,  f ,  segments ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        f . write ( struct . pack ( ' <BBBBI ' ,  ESPLoader . ESP_IMAGE_MAGIC ,  len ( segments ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            self . flash_mode ,  self . flash_size_freq ,  self . entrypoint ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  is_irom_addr ( self ,  addr ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """  Returns True if an address starts in the irom region. 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Valid  for  ESP8266  only . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """ 
 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  ESP8266ROM . IROM_MAP_START  < =  addr  <  ESP8266ROM . IROM_MAP_END 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  get_irom_segment ( self ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            irom_segments  =  [ s  for  s  in  self . segments  if  self . is_irom_addr ( s . addr ) ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  len ( irom_segments )  >  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  len ( irom_segments )  !=  1 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    raise  FatalError ( ' Found  %d  segments that could be irom0. Bad ELF file? '  %  len ( irom_segments ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return  irom_segments [ 0 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  get_non_irom_segments ( self ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        irom_segment  =  self . get_irom_segment ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  [ s  for  s  in  self . segments  if  s  !=  irom_segment ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  ESPFirmwareImage ( BaseFirmwareImage ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """   ' Version 1 '  firmware image, segments loaded directly by the ROM bootloader.  """ 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ROM_LOADER  =  ESP8266ROM 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    def  __init__ ( self ,  load_file = None ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        super ( ESPFirmwareImage ,  self ) . __init__ ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . flash_mode  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . flash_size_freq  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . version  =  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  load_file  is  not  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            segments  =  self . load_common_header ( load_file ,  ESPLoader . ESP_IMAGE_MAGIC ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            for  _  in  range ( segments ) : 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                self . load_segment ( load_file ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . checksum  =  self . read_checksum ( load_file ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  default_output_name ( self ,  input_file ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """  Derive a default output name from the ELF name.  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  input_file  +  ' - ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  save ( self ,  basename ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """  Save a set of V1 images for flashing. Parameter is a base filename.  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # IROM data goes in its own plain binary file 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        irom_segment  =  self . get_irom_segment ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  irom_segment  is  not  None : 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            with  open ( " %s 0x %05x .bin "  %  ( basename ,  irom_segment . addr  -  ESP8266ROM . IROM_MAP_START ) ,  " wb " )  as  f : 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                f . write ( irom_segment . data ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # everything but IROM goes at 0x00000 in an image file 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        normal_segments  =  self . get_non_irom_segments ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        with  open ( " %s 0x00000.bin "  %  basename ,  ' wb ' )  as  f : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . write_common_header ( f ,  normal_segments ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            checksum  =  ESPLoader . ESP_CHECKSUM_MAGIC 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            for  segment  in  normal_segments : 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                checksum  =  self . save_segment ( f ,  segment ,  checksum ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . append_checksum ( f ,  checksum ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  OTAFirmwareImage ( BaseFirmwareImage ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """   ' Version 2 '  firmware image, segments loaded by software bootloader stub 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ( ie  Espressif  bootloader  or  rboot ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ROM_LOADER  =  ESP8266ROM 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    def  __init__ ( self ,  load_file = None ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        super ( OTAFirmwareImage ,  self ) . __init__ ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . version  =  2 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  load_file  is  not  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            segments  =  self . load_common_header ( load_file ,  ESPBOOTLOADER . IMAGE_V2_MAGIC ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  segments  !=  ESPBOOTLOADER . IMAGE_V2_SEGMENT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # segment count is not really segment count here, but we expect to see '4' 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                print ( ' Warning: V2 header has unexpected  " segment "  count  %d  (usually 4) '  %  segments ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # irom segment comes before the second header 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # the file is saved in the image with a zero load address 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # in the header, so we need to calculate a load address 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            irom_segment  =  self . load_segment ( load_file ,  True ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            # for actual mapped addr, add ESP8266ROM.IROM_MAP_START + flashing_Addr + 8 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            irom_segment . addr  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            irom_segment . include_in_checksum  =  False 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            first_flash_mode  =  self . flash_mode 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            first_flash_size_freq  =  self . flash_size_freq 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            first_entrypoint  =  self . entrypoint 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # load the second header 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            segments  =  self . load_common_header ( load_file ,  ESPLoader . ESP_IMAGE_MAGIC ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  first_flash_mode  !=  self . flash_mode : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                print ( ' WARNING: Flash mode value in first header (0x %02x ) disagrees with second (0x %02x ). Using second value. ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                      %  ( first_flash_mode ,  self . flash_mode ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  first_flash_size_freq  !=  self . flash_size_freq : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                print ( ' WARNING: Flash size/freq value in first header (0x %02x ) disagrees with second (0x %02x ). Using second value. ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                      %  ( first_flash_size_freq ,  self . flash_size_freq ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  first_entrypoint  !=  self . entrypoint : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                print ( ' WARNING: Entrypoint address in first header (0x %08x ) disagrees with second header (0x %08x ). Using second value. ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                      %  ( first_entrypoint ,  self . entrypoint ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # load all the usual segments 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            for  _  in  range ( segments ) : 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                self . load_segment ( load_file ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . checksum  =  self . read_checksum ( load_file ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  default_output_name ( self ,  input_file ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """  Derive a default output name from the ELF name.  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        irom_segment  =  self . get_irom_segment ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  irom_segment  is  not  None : 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            irom_offs  =  irom_segment . addr  -  ESP8266ROM . IROM_MAP_START 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            irom_offs  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  " %s -0x %05x .bin "  %  ( os . path . splitext ( input_file ) [ 0 ] , 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-30 01:28:30 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                                  irom_offs  &  ~ ( ESPLoader . FLASH_SECTOR_SIZE  -  1 ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  save ( self ,  filename ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        with  open ( filename ,  ' wb ' )  as  f : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # Save first header for irom0 segment 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            f . write ( struct . pack ( b ' <BBBBI ' ,  ESPBOOTLOADER . IMAGE_V2_MAGIC ,  ESPBOOTLOADER . IMAGE_V2_SEGMENT , 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                                self . flash_mode ,  self . flash_size_freq ,  self . entrypoint ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            irom_segment  =  self . get_irom_segment ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  irom_segment  is  not  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # save irom0 segment, make sure it has load addr 0 in the file 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                irom_segment  =  irom_segment . copy_with_new_addr ( 0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                self . save_segment ( f ,  irom_segment ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # second header, matches V1 header and contains loadable segments 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            normal_segments  =  self . get_non_irom_segments ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . write_common_header ( f ,  normal_segments ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            checksum  =  ESPLoader . ESP_CHECKSUM_MAGIC 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  segment  in  normal_segments : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                checksum  =  self . save_segment ( f ,  segment ,  checksum ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . append_checksum ( f ,  checksum ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  ESP32FirmwareImage ( BaseFirmwareImage ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  ESP32 firmware image is very similar to V1 ESP8266 image, 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    except  with  an  additional  16  byte  reserved  header  at  top  of  image , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    and  because  of  new  flash  mapping  capabilities  the  flash - mapped  regions 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    can  be  placed  in  the  normal  image  ( just  @  64 kB  padded  offsets ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ROM_LOADER  =  ESP32ROM 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    def  __init__ ( self ,  load_file = None ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        super ( ESP32FirmwareImage ,  self ) . __init__ ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . flash_mode  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . flash_size_freq  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . version  =  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  load_file  is  not  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            segments  =  self . load_common_header ( load_file ,  ESPLoader . ESP_IMAGE_MAGIC ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-30 01:28:30 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            additional_header  =  list ( struct . unpack ( " B "  *  16 ,  load_file . read ( 16 ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-03-10 15:40:14 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            # check these bytes are unused 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  additional_header  !=  [ 0 ]  *  16 : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                print ( " WARNING: ESP32 image header contains unknown flags. Possibly this image is from a newer version of esptool.py " ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            for  _  in  range ( segments ) : 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                self . load_segment ( load_file ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . checksum  =  self . read_checksum ( load_file ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  is_flash_addr ( self ,  addr ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  ( ESP32ROM . IROM_MAP_START  < =  addr  <  ESP32ROM . IROM_MAP_END )  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            or  ( ESP32ROM . DROM_MAP_START  < =  addr  <  ESP32ROM . DROM_MAP_END ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  default_output_name ( self ,  input_file ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """  Derive a default output name from the ELF name.  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  " %s .bin "  %  ( os . path . splitext ( input_file ) [ 0 ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  warn_if_unusual_segment ( self ,  offset ,  size ,  is_irom_segment ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        pass   # TODO: add warnings for ESP32 segment offset/size combinations that are wrong 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    def  save ( self ,  filename ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        padding_segments  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        with  open ( filename ,  ' wb ' )  as  f : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . write_common_header ( f ,  self . segments ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-30 01:28:30 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-03-10 15:40:14 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            # first 4 bytes of header are read by ROM bootloader for SPI 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # config, but currently unused 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            f . write ( b ' \x00 '  *  16 ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            checksum  =  ESPLoader . ESP_CHECKSUM_MAGIC 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            last_addr  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  segment  in  sorted ( self . segments ,  key = lambda  s : s . addr ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # IROM/DROM segment flash mappings need to align on 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # 64kB boundaries. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # TODO: intelligently order segments to reduce wastage 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # by squeezing smaller DRAM/IRAM segments into the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # 64kB padding space. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                IROM_ALIGN  =  65536 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # check for multiple ELF sections that live in the same flash mapping region. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # this is usually a sign of a broken linker script, but if you have a legitimate 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # use case then let us know (we can merge segments here, but as a rule you probably 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # want to merge them in your linker script.) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  last_addr  is  not  None  and  self . is_flash_addr ( last_addr )  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                   and  self . is_flash_addr ( segment . addr )  and  segment . addr  / /  IROM_ALIGN  ==  last_addr  / /  IROM_ALIGN : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    raise  FatalError ( ( " Segment loaded at 0x %08x  lands in same 64KB flash mapping as segment loaded at 0x %08x .  "  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                     " Can ' t generate binary. Suggest changing linker script or ELF to merge sections. " )  % 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                     ( segment . addr ,  last_addr ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                last_addr  =  segment . addr 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  self . is_flash_addr ( segment . addr ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    # Actual alignment required for the segment header: positioned so that 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    # after we write the next 8 byte header, file_offs % IROM_ALIGN == segment.addr % IROM_ALIGN 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    # 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    # (this is because the segment's vaddr may not be IROM_ALIGNed, more likely is aligned 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    # IROM_ALIGN+0x10 to account for longest possible header. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    align_past  =  ( segment . addr  %  IROM_ALIGN )  -  self . SEG_HEADER_LEN 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    assert  ( align_past  +  self . SEG_HEADER_LEN )  ==  ( segment . addr  %  IROM_ALIGN ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    # subtract SEG_HEADER_LEN a second time, as the padding block has a header as well 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    pad_len  =  ( IROM_ALIGN  -  ( f . tell ( )  %  IROM_ALIGN ) )  +  align_past  -  self . SEG_HEADER_LEN 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    if  pad_len  <  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        pad_len  + =  IROM_ALIGN 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    if  pad_len  >  0 : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        null  =  ImageSegment ( 0 ,  b ' \x00 '  *  pad_len ,  f . tell ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                        checksum  =  self . save_segment ( f ,  null ,  checksum ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        padding_segments  + =  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    # verify that after the 8 byte header is added, were are at the correct offset relative to the segment's vaddr 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    assert  ( f . tell ( )  +  8 )  %  IROM_ALIGN  ==  segment . addr  %  IROM_ALIGN 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                checksum  =  self . save_segment ( f ,  segment ,  checksum ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . append_checksum ( f ,  checksum ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # kinda hacky: go back to the initial header and write the new segment count 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # that includes padding segments. Luckily(?) this header is not checksummed 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            f . seek ( 1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                f . write ( chr ( len ( self . segments )  +  padding_segments ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            except  TypeError :   # Python 3 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                f . write ( bytes ( [ len ( self . segments )  +  padding_segments ] ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  ELFFile ( object ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    SEC_TYPE_PROGBITS  =  0x01 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    SEC_TYPE_STRTAB  =  0x03 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  __init__ ( self ,  name ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # Load sections from the ELF file 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . name  =  name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        with  open ( self . name ,  ' rb ' )  as  f : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . _read_elf_file ( f ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  get_section ( self ,  section_name ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  s  in  self . sections : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  s . name  ==  section_name : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return  s 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        raise  ValueError ( " No section  %s  in ELF file "  %  section_name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  _read_elf_file ( self ,  f ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # read the ELF file header 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        LEN_FILE_HEADER  =  0x34 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ( ident , _type , machine , _version , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             self . entrypoint , _phoff , shoff , _flags , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             _ehsize ,  _phentsize , _phnum , _shentsize , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             _shnum , shstrndx )  =  struct . unpack ( " <16sHHLLLLLHHHHHH " ,  f . read ( LEN_FILE_HEADER ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        except  struct . error  as  e : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            raise  FatalError ( " Failed to read a valid ELF header from  %s :  %s "  %  ( self . name ,  e ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  byte ( ident ,  0 )  !=  0x7f  or  ident [ 1 : 4 ]  !=  b ' ELF ' : 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            raise  FatalError ( " %s  has invalid ELF magic header "  %  self . name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  machine  !=  0x5e : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            raise  FatalError ( " %s  does not appear to be an Xtensa ELF file. e_machine= %04x "  %  ( self . name ,  machine ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . _read_sections ( f ,  shoff ,  shstrndx ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  _read_sections ( self ,  f ,  section_header_offs ,  shstrndx ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        f . seek ( section_header_offs ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        section_header  =  f . read ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        LEN_SEC_HEADER  =  0x28 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  len ( section_header )  ==  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            raise  FatalError ( " No section header found at offset  %04x  in ELF file. "  %  section_header_offs ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  len ( section_header )  %  LEN_SEC_HEADER  !=  0 : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            print ( ' WARNING: Unexpected ELF section header length  %04x  is not mod- %02x '  %  ( len ( section_header ) , LEN_SEC_HEADER ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # walk through the section header and extract all sections 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        section_header_offsets  =  range ( 0 ,  len ( section_header ) ,  LEN_SEC_HEADER ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        def  read_section_header ( offs ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            name_offs , sec_type , _flags , lma , sec_offs , size  =  struct . unpack_from ( " <LLLLLL " ,  section_header [ offs : ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  ( name_offs ,  sec_type ,  lma ,  size ,  sec_offs ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        all_sections  =  [ read_section_header ( offs )  for  offs  in  section_header_offsets ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        prog_sections  =  [ s  for  s  in  all_sections  if  s [ 1 ]  ==  ELFFile . SEC_TYPE_PROGBITS ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # search for the string table section 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  not  shstrndx  *  LEN_SEC_HEADER  in  section_header_offsets : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            raise  FatalError ( " ELF file has no STRTAB section at shstrndx  %d "  %  shstrndx ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        _ , sec_type , _ , sec_size , sec_offs  =  read_section_header ( shstrndx  *  LEN_SEC_HEADER ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  sec_type  !=  ELFFile . SEC_TYPE_STRTAB : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            print ( ' WARNING: ELF file has incorrect STRTAB section type 0x %02x '  %  sec_type ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        f . seek ( sec_offs ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        string_table  =  f . read ( sec_size ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # build the real list of ELFSections by reading the actual section names from the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # string table section, and actual data for each section from the ELF file itself 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        def  lookup_string ( offs ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            raw  =  string_table [ offs : ] 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            return  raw [ : raw . index ( b ' \x00 ' ) ] 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        def  read_data ( offs , size ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            f . seek ( offs ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  f . read ( size ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        prog_sections  =  [ ELFSection ( lookup_string ( n_offs ) ,  lma ,  read_data ( offs ,  size ) )  for  ( n_offs ,  _type ,  lma ,  size ,  offs )  in  prog_sections 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                         if  lma  !=  0 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . sections  =  prog_sections 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  slip_reader ( port ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ Generator to read SLIP packets from a serial port. 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Yields  one  full  SLIP  packet  at  a  time ,  raises  exception  on  timeout  or  invalid  data . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Designed  to  avoid  too  many  calls  to  serial . read ( 1 ) ,  which  can  bog 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    down  on  slow  systems . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    partial_packet  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    in_escape  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  True : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        waiting  =  port . inWaiting ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        read_bytes  =  port . read ( 1  if  waiting  ==  0  else  waiting ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  read_bytes  ==  b ' ' : 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            raise  FatalError ( " Timed out waiting for packet  %s "  %  ( " header "  if  partial_packet  is  None  else  " content " ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  b  in  read_bytes : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  type ( b )  is  int : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                b  =  bytes ( [ b ] )   # python 2/3 compat 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            if  partial_packet  is  None :   # waiting for packet header 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                if  b  ==  b ' \xc0 ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    partial_packet  =  b " " 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    raise  FatalError ( ' Invalid head of packet ( %r ) '  %  b ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            elif  in_escape :   # part-way through escape sequence 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                in_escape  =  False 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                if  b  ==  b ' \xdc ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    partial_packet  + =  b ' \xc0 ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                elif  b  ==  b ' \xdd ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    partial_packet  + =  b ' \xdb ' 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                else : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    raise  FatalError ( ' Invalid SLIP escape ( %r %r ) '  %  ( b ' \xdb ' ,  b ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            elif  b  ==  b ' \xdb ' :   # start of escape sequence 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                in_escape  =  True 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            elif  b  ==  b ' \xc0 ' :   # end of packet 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                yield  partial_packet 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                partial_packet  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else :   # normal byte in packet 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                partial_packet  + =  b 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  arg_auto_int ( x ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  int ( x ,  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  div_roundup ( a ,  b ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Return a/b rounded up to nearest integer, 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    equivalent  result  to  int ( math . ceil ( float ( int ( a ) )  /  float ( int ( b ) ) ) ,  only 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    without  possible  floating  point  accuracy  errors . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  ( int ( a )  +  int ( b )  -  1 )  / /  int ( b ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								def  align_file_position ( f ,  size ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Align the position in the file to the next block of specified size  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    align  =  ( size  -  1 )  -  ( f . tell ( )  %  size ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    f . seek ( align ,  1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  flash_size_bytes ( size ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Given a flash size of the type passed in args.flash_size 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ( ie  512 KB  or  1 MB )  then  return  the  size  in  bytes . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  " MB "  in  size : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  int ( size [ : size . index ( " MB " ) ] )  *  1024  *  1024 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    elif  " KB "  in  size : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  int ( size [ : size . index ( " KB " ) ] )  *  1024 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        raise  FatalError ( " Unknown size  %s "  %  size ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  hexify ( s ) :  
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  not  PYTHON2 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  ' ' . join ( ' %02X '  %  c  for  c  in  s ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  ' ' . join ( ' %02X '  %  ord ( c )  for  c  in  s ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  unhexify ( hs ) :  
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    s  =  bytes ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    for  i  in  range ( 0 ,  len ( hs )  -  1 ,  2 ) : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        hex_string  =  hs [ i : i  +  2 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  not  PYTHON2 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            s  + =  bytes ( [ int ( hex_string ,  16 ) ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            s  + =  chr ( int ( hex_string ,  16 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    return  s 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-03-10 15:40:14 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  pad_to ( data ,  alignment ,  pad_character = b ' \xFF ' ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Pad to the next alignment boundary  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    pad_mod  =  len ( data )  %  alignment 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  pad_mod  !=  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        data  + =  pad_character  *  ( alignment  -  pad_mod ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  data 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								class  FatalError ( RuntimeError ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Wrapper  class  for  runtime  errors  that  aren ' t caused by internal bugs, but by 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ESP8266  responses  or  input  content . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  __init__ ( self ,  message ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        RuntimeError . __init__ ( self ,  message ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    @staticmethod 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  WithResult ( message ,  result ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Return  a  fatal  error  object  that  appends  the  hex  values  of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' result '  as  a  string  formatted  argument . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """ 
 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        message  + =  "  (result was  %s ) "  %  hexify ( result ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        return  FatalError ( message ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  NotImplementedInROMError ( FatalError ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Wrapper  class  for  the  error  thrown  when  a  particular  ESP  bootloader  function 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    is  not  implemented  in  the  ROM  bootloader . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-30 01:28:30 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  __init__ ( self ,  bootloader ,  func ) : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        FatalError . __init__ ( self ,  " %s  ROM does not support function  %s . "  %  ( bootloader . CHIP_NAME ,  func . __name__ ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# "Operation" commands, executable at command line. One function each  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								#  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# Each function takes either two args (<ESPLoader instance>, <args>) or a single <args>  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# argument.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  load_ram ( esp ,  args ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    image  =  LoadFirmwareImage ( esp ,  args . filename ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    print ( ' RAM boot... ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    for  ( offset ,  size ,  data )  in  image . segments : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        print ( ' Downloading  %d  bytes at  %08x ... '  %  ( size ,  offset ) ,  end = '   ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        sys . stdout . flush ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        esp . mem_begin ( size ,  div_roundup ( size ,  esp . ESP_RAM_BLOCK ) ,  esp . ESP_RAM_BLOCK ,  offset ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        seq  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        while  len ( data )  >  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            esp . mem_block ( data [ 0 : esp . ESP_RAM_BLOCK ] ,  seq ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            data  =  data [ esp . ESP_RAM_BLOCK : ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            seq  + =  1 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        print ( ' done! ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    print ( ' All segments done, executing at  %08x '  %  image . entrypoint ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    esp . mem_finish ( image . entrypoint ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  read_mem ( esp ,  args ) :  
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    print ( ' 0x %08x  = 0x %08x '  %  ( args . address ,  esp . read_reg ( args . address ) ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  write_mem ( esp ,  args ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    esp . write_reg ( args . address ,  args . value ,  args . mask ,  0 ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    print ( ' Wrote  %08x , mask  %08x  to  %08x '  %  ( args . value ,  args . mask ,  args . address ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  dump_mem ( esp ,  args ) :  
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    f  =  open ( args . filename ,  ' wb ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  i  in  range ( args . size  / /  4 ) : 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        d  =  esp . read_reg ( args . address  +  ( i  *  4 ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        f . write ( struct . pack ( b ' <I ' ,  d ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        if  f . tell ( )  %  1024  ==  0 : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            print ( ' \r %d  bytes read... ( %d   %% ) '  %  ( f . tell ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                  f . tell ( )  *  100  / /  args . size ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  end = '   ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        sys . stdout . flush ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    print ( ' Done! ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  detect_flash_size ( esp ,  args ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  args . flash_size  ==  ' detect ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        flash_id  =  esp . flash_id ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        size_id  =  flash_id  >>  16 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        args . flash_size  =  { 0x12 :  ' 256KB ' ,  0x13 :  ' 512KB ' ,  0x14 :  ' 1MB ' ,  0x15 :  ' 2MB ' ,  0x16 :  ' 4MB ' ,  0x17 :  ' 8MB ' ,  0x18 :  ' 16MB ' } . get ( size_id ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  args . flash_size  is  None : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            print ( ' Warning: Could not auto-detect Flash size (FlashID=0x %x , SizeID=0x %x ), defaulting to 4MB '  %  ( flash_id ,  size_id ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            args . flash_size  =  ' 4MB ' 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            print ( ' Auto-detected Flash size: ' ,  args . flash_size ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  _get_flash_params ( esp ,  args ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Return binary flash parameters (bitstring length 2) for args  """ 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    detect_flash_size ( esp ,  args ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    flash_mode  =  { ' qio ' : 0 ,  ' qout ' : 1 ,  ' dio ' : 2 ,  ' dout ' :  3 } [ args . flash_mode ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    flash_size_freq  =  esp . parse_flash_size_arg ( args . flash_size ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    flash_size_freq  + =  { ' 40m ' : 0 ,  ' 26m ' : 1 ,  ' 20m ' : 2 ,  ' 80m ' :  0xf } [ args . flash_freq ] 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  struct . pack ( b ' BB ' ,  flash_mode ,  flash_size_freq ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  _update_image_flash_params ( esp ,  address ,  flash_params ,  image ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Modify the flash mode & size bytes if this looks like an executable image  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  address  ==  esp . FLASH_HEADER_OFFSET  and  ( image [ 0 ]  ==  ' \xe9 '  or  image [ 0 ]  ==  0xE9 ) :   # python 2/3 compat: 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        print ( ' Flash params set to 0x %04x '  %  struct . unpack ( " >H " ,  flash_params ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        image  =  image [ 0 : 2 ]  +  flash_params  +  image [ 4 : ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  image 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  write_flash ( esp ,  args ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    flash_params  =  _get_flash_params ( esp ,  args ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # set args.compress based on default behaviour: 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # -> if either --compress or --no-compress is set, honour that 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # -> otherwise, set --compress unless --no-stub is set 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  args . compress  is  None  and  not  args . no_compress : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        args . compress  =  not  args . no_stub 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # verify file sizes fit in flash 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    flash_end  =  flash_size_bytes ( args . flash_size ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  address ,  argfile  in  args . addr_filename : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        argfile . seek ( 0 , 2 )   # seek to end 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  address  +  argfile . tell ( )  >  flash_end : 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            raise  FatalError ( ( " File  %s  (length  %d ) at offset  %d  will not fit in  %d  bytes of flash.  "  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                             " Use --flash-size argument, or change flashing address. " ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                             %  ( argfile . name ,  argfile . tell ( ) ,  address ,  flash_end ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        argfile . seek ( 0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  address ,  argfile  in  args . addr_filename : 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-30 01:28:30 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  args . no_stub : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            print ( ' Erasing flash... ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-10 15:40:14 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        image  =  pad_to ( argfile . read ( ) ,  4 ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        image  =  _update_image_flash_params ( esp ,  address ,  flash_params ,  image ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        calcmd5  =  hashlib . md5 ( image ) . hexdigest ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        uncsize  =  len ( image ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        if  args . compress : 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            uncimage  =  image 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            image  =  zlib . compress ( uncimage ,  9 ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-30 01:28:30 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            blocks  =  esp . flash_defl_begin ( uncsize ,  len ( image ) ,  address ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-30 01:28:30 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            blocks  =  esp . flash_begin ( uncsize ,  address ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        argfile . seek ( 0 )   # in case we need it again 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        seq  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        written  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        t  =  time . time ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        while  len ( image )  >  0 : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            print ( ' \r Writing at 0x %08x ... ( %d   %% ) '  %  ( address  +  seq  *  esp . FLASH_WRITE_SIZE ,  100  *  ( seq  +  1 )  / /  blocks ) ,  end = ' ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            sys . stdout . flush ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            block  =  image [ 0 : esp . FLASH_WRITE_SIZE ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  args . compress : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                esp . flash_defl_block ( block ,  seq ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # Pad the last block 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                block  =  block  +  b ' \xff '  *  ( esp . FLASH_WRITE_SIZE  -  len ( block ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                esp . flash_block ( block ,  seq ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            image  =  image [ esp . FLASH_WRITE_SIZE : ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            seq  + =  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            written  + =  len ( block ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        t  =  time . time ( )  -  t 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        speed_msg  =  " " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  args . compress : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  t  >  0.0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                speed_msg  =  "  (effective  %.1f  kbit/s) "  %  ( uncsize  /  t  *  8  /  1000 ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            print ( ' \r Wrote  %d  bytes ( %d  compressed) at 0x %08x  in  %.1f  seconds %s ... '  %  ( uncsize ,  written ,  address ,  t ,  speed_msg ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  t  >  0.0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                speed_msg  =  "  ( %.1f  kbit/s) "  %  ( written  /  t  *  8  /  1000 ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            print ( ' \r Wrote  %d  bytes at 0x %08x  in  %.1f  seconds %s ... '  %  ( written ,  address ,  t ,  speed_msg ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-30 01:28:30 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            res  =  esp . flash_md5sum ( address ,  uncsize ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  res  !=  calcmd5 : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                print ( ' File  md5:  %s '  %  calcmd5 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                print ( ' Flash md5:  %s '  %  res ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                print ( ' MD5 of 0xFF is  %s '  %  ( hashlib . md5 ( b ' \xFF '  *  uncsize ) . hexdigest ( ) ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-30 01:28:30 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                raise  FatalError ( " MD5 of file does not match data in flash! " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                print ( ' Hash of data verified. ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-30 01:28:30 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        except  NotImplementedInROMError : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            pass 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    print ( ' \n Leaving... ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  esp . IS_STUB : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # skip sending flash_finish to ROM loader here, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # as it causes the loader to exit and run user code 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        esp . flash_begin ( 0 ,  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  args . compress : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            esp . flash_defl_finish ( False ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            esp . flash_finish ( False ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    if  args . verify : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        print ( ' Verifying just-written flash... ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        print ( ' (This option is deprecated, flash contents are now always read back after flashing.) ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        _verify_flash ( esp ,  args ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  image_info ( args ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    image  =  LoadFirmwareImage ( args . chip ,  args . filename ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    print ( ' Image version:  %d '  %  image . version ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    print ( ' Entry point:  %08x '  %  image . entrypoint  if  image . entrypoint  !=  0  else  ' Entry point not set ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    print ( ' %d  segments '  %  len ( image . segments ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    print 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    idx  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  seg  in  image . segments : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        idx  + =  1 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        print ( ' Segment  %d :  %r '  %  ( idx ,  seg ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    calc_checksum  =  image . calculate_checksum ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    print ( ' Checksum:  %02x  ( %s ) '  %  ( image . checksum , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                   ' valid '  if  image . checksum  ==  calc_checksum  else  ' invalid - calculated  %02x '  %  calc_checksum ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  make_image ( args ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    image  =  ESPFirmwareImage ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  len ( args . segfile )  ==  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        raise  FatalError ( ' No segments specified ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  len ( args . segfile )  !=  len ( args . segaddr ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        raise  FatalError ( ' Number of specified files does not match number of specified addresses ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  ( seg ,  addr )  in  zip ( args . segfile ,  args . segaddr ) : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        data  =  open ( seg ,  ' rb ' ) . read ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        image . segments . append ( ImageSegment ( addr ,  data ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    image . entrypoint  =  args . entrypoint 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    image . save ( args . output ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  elf2image ( args ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    e  =  ELFFile ( args . input ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  args . chip  ==  ' auto ' :   # Default to ESP8266 for backwards compatibility 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        print ( " Creating image for ESP8266... " ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        args . chip  ==  ' esp8266 ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  args . chip  ==  ' esp32 ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        image  =  ESP32FirmwareImage ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    elif  args . version  ==  ' 1 ' :   # ESP8266 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        image  =  ESPFirmwareImage ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        image  =  OTAFirmwareImage ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    image . entrypoint  =  e . entrypoint 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    image . segments  =  e . sections   # ELFSection is a subclass of ImageSegment 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    image . flash_mode  =  { ' qio ' : 0 ,  ' qout ' : 1 ,  ' dio ' : 2 ,  ' dout ' :  3 } [ args . flash_mode ] 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    image . flash_size_freq  =  image . ROM_LOADER . FLASH_SIZES [ args . flash_size ] 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    image . flash_size_freq  + =  { ' 40m ' : 0 ,  ' 26m ' : 1 ,  ' 20m ' : 2 ,  ' 80m ' :  0xf } [ args . flash_freq ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  args . output  is  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        args . output  =  image . default_output_name ( args . input ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    image . save ( args . output ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  read_mac ( esp ,  args ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    mac  =  esp . read_mac ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-12-30 01:28:30 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  print_mac ( label ,  mac ) : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        print ( ' %s :  %s '  %  ( label ,  ' : ' . join ( map ( lambda  x :  ' %02x '  %  x ,  mac ) ) ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    print_mac ( " MAC " ,  mac ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  chip_id ( esp ,  args ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    chipid  =  esp . chip_id ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    print ( ' Chip ID: 0x %08x '  %  chipid ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  erase_flash ( esp ,  args ) :  
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    print ( ' Erasing flash (this may take a while)... ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    t  =  time . time ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    esp . erase_flash ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    print ( ' Chip erase completed successfully in  %.1f s '  %  ( time . time ( )  -  t ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  erase_region ( esp ,  args ) :  
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    print ( ' Erasing region (may be slow depending on size)... ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    t  =  time . time ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    esp . erase_region ( args . address ,  args . size ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    print ( ' Erase completed successfully in  %.1f  seconds. '  %  ( time . time ( )  -  t ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  run ( esp ,  args ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    esp . run ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  flash_id ( esp ,  args ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    flash_id  =  esp . flash_id ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    print ( ' Manufacturer:  %02x '  %  ( flash_id  &  0xff ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    print ( ' Device:  %02x %02x '  %  ( ( flash_id  >>  8 )  &  0xff ,  ( flash_id  >>  16 )  &  0xff ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  read_flash ( esp ,  args ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  args . no_progress : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        flash_progress  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        def  flash_progress ( progress ,  length ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            msg  =  ' %d  ( %d   %% ) '  %  ( progress ,  progress  *  100.0  /  length ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            padding  =  ' \b '  *  len ( msg ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  progress  ==  length : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                padding  =  ' \n ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            sys . stdout . write ( msg  +  padding ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            sys . stdout . flush ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    t  =  time . time ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    data  =  esp . read_flash ( args . address ,  args . size ,  flash_progress ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    t  =  time . time ( )  -  t 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    print ( ' \r Read  %d  bytes at 0x %x  in  %.1f  seconds ( %.1f  kbit/s)... ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          %  ( len ( data ) ,  args . address ,  t ,  len ( data )  /  t  *  8  /  1000 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    open ( args . filename ,  ' wb ' ) . write ( data ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  verify_flash ( esp ,  args ,  flash_params = None ) :  
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    _verify_flash ( esp ,  args ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  _verify_flash ( esp ,  args ) :  
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    differences  =  False 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    flash_params  =  _get_flash_params ( esp ,  args ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    for  address ,  argfile  in  args . addr_filename : 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-10 15:40:14 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        image  =  pad_to ( argfile . read ( ) ,  4 ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        argfile . seek ( 0 )   # rewind in case we need it again 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        image  =  _update_image_flash_params ( esp ,  address ,  flash_params ,  image ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        image_size  =  len ( image ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        print ( ' Verifying 0x %x  ( %d ) bytes @ 0x %08x  in flash against  %s ... '  %  ( image_size ,  image_size ,  address ,  argfile . name ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        # Try digest first, only read if there are differences. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        digest  =  esp . flash_md5sum ( address ,  image_size ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        expected_digest  =  hashlib . md5 ( image ) . hexdigest ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  digest  ==  expected_digest : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            print ( ' -- verify OK (digest matched) ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            differences  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  getattr ( args ,  ' diff ' ,  ' no ' )  !=  ' yes ' : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                print ( ' -- verify FAILED (digest mismatch) ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        flash  =  esp . read_flash ( address ,  image_size ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        assert  flash  !=  image 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        diff  =  [ i  for  i  in  range ( image_size )  if  flash [ i ]  !=  image [ i ] ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        print ( ' -- verify FAILED:  %d  differences, first @ 0x %08x '  %  ( len ( diff ) ,  address  +  diff [ 0 ] ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        for  d  in  diff : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            flash_byte  =  flash [ d ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            image_byte  =  image [ d ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  PYTHON2 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                flash_byte  =  ord ( flash_byte ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                image_byte  =  ord ( image_byte ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            print ( '     %08x   %02x   %02x '  %  ( address  +  d ,  flash_byte ,  image_byte ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    if  differences : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        raise  FatalError ( " Verify failed. " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  read_flash_status ( esp ,  args ) :  
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    print ( ' Status value: 0x %04x '  %  esp . read_status ( args . bytes ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  write_flash_status ( esp ,  args ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    fmt  =  " 0x %% 0 %d x "  %  ( args . bytes  *  2 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    args . value  =  args . value  &  ( ( 1  <<  ( args . bytes  *  8 ) )  -  1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    print ( ( ' Initial flash status:  '  +  fmt )  %  esp . read_status ( args . bytes ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    print ( ( ' Setting flash status:  '  +  fmt )  %  args . value ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    esp . write_status ( args . value ,  args . bytes ,  args . non_volatile ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    print ( ( ' After flash status:    '  +  fmt )  %  esp . read_status ( args . bytes ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								def  version ( args ) :  
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    print ( __version__ ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								#  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# End of operations functions  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								#  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  main ( ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser  =  argparse . ArgumentParser ( description = ' esptool.py v %s  - ESP8266 ROM Bootloader Utility '  %  __version__ ,  prog = ' esptool ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser . add_argument ( ' --chip ' ,  ' -c ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        help = ' Target chip type ' , 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        choices = [ ' auto ' ,  ' esp8266 ' ,  ' esp32 ' ] , 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                        default = os . environ . get ( ' ESPTOOL_CHIP ' ,  ' auto ' ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser . add_argument ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' --port ' ,  ' -p ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        help = ' Serial port device ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        default = os . environ . get ( ' ESPTOOL_PORT ' ,  ESPLoader . DEFAULT_PORT ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser . add_argument ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' --baud ' ,  ' -b ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        help = ' Serial port baud rate used when flashing/reading ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        type = arg_auto_int , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        default = os . environ . get ( ' ESPTOOL_BAUD ' ,  ESPLoader . ESP_ROM_BAUD ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    parser . add_argument ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' --before ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        help = ' What to do before connecting to the chip ' , 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-10 15:40:14 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        choices = [ ' default_reset ' ,  ' no_reset ' ] , 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        default = os . environ . get ( ' ESPTOOL_BEFORE ' ,  ' default_reset ' ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser . add_argument ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' --after ' ,  ' -a ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        help = ' What to do after esptool.py is finished ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        choices = [ ' hard_reset ' ,  ' soft_reset ' ,  ' no_reset ' ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        default = os . environ . get ( ' ESPTOOL_AFTER ' ,  ' hard_reset ' ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    parser . add_argument ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' --no-stub ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        help = " Disable launching the flasher stub, only talk to ROM bootloader. Some features will not be available. " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        action = ' store_true ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    subparsers  =  parser . add_subparsers ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        dest = ' operation ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        help = ' Run esptool  {command}  -h for additional help ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-06 20:29:12 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  add_spi_connection_arg ( parent ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        parent . add_argument ( ' --spi-connection ' ,  ' -sc ' ,  help = ' ESP32-only argument. Override default SPI Flash connection.  '  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            ' Value can be SPI, HSPI or a comma-separated list of 5 I/O numbers to use for SPI flash (CLK,Q,D,HD,CS). ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            action = SpiConnectionAction ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    parser_load_ram  =  subparsers . add_parser ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' load_ram ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        help = ' Download an image to RAM and execute ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_load_ram . add_argument ( ' filename ' ,  help = ' Firmware image ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_dump_mem  =  subparsers . add_parser ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' dump_mem ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        help = ' Dump arbitrary memory to disk ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_dump_mem . add_argument ( ' address ' ,  help = ' Base address ' ,  type = arg_auto_int ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_dump_mem . add_argument ( ' size ' ,  help = ' Size of region to dump ' ,  type = arg_auto_int ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_dump_mem . add_argument ( ' filename ' ,  help = ' Name of binary dump ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_read_mem  =  subparsers . add_parser ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' read_mem ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        help = ' Read arbitrary memory location ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_read_mem . add_argument ( ' address ' ,  help = ' Address to read ' ,  type = arg_auto_int ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_write_mem  =  subparsers . add_parser ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' write_mem ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        help = ' Read-modify-write to arbitrary memory location ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_write_mem . add_argument ( ' address ' ,  help = ' Address to write ' ,  type = arg_auto_int ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_write_mem . add_argument ( ' value ' ,  help = ' Value ' ,  type = arg_auto_int ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_write_mem . add_argument ( ' mask ' ,  help = ' Mask of bits to write ' ,  type = arg_auto_int ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  add_spi_flash_subparsers ( parent ,  auto_detect = False ) : 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        """  Add common parser arguments for SPI flash properties  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        parent . add_argument ( ' --flash_freq ' ,  ' -ff ' ,  help = ' SPI Flash frequency ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            choices = [ ' 40m ' ,  ' 26m ' ,  ' 20m ' ,  ' 80m ' ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            default = os . environ . get ( ' ESPTOOL_FF ' ,  ' 40m ' ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        parent . add_argument ( ' --flash_mode ' ,  ' -fm ' ,  help = ' SPI Flash mode ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            choices = [ ' qio ' ,  ' qout ' ,  ' dio ' ,  ' dout ' ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            default = os . environ . get ( ' ESPTOOL_FM ' ,  ' qio ' ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        parent . add_argument ( ' --flash_size ' ,  ' -fs ' ,  help = ' SPI Flash size in MegaBytes (1MB, 2MB, 4MB, 8MB, 16M) ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            '  plus ESP8266-only (256KB, 512KB, 2MB-c1, 4MB-c1, 4MB-2) ' , 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                            action = FlashSizeAction ,  auto_detect = auto_detect , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            default = os . environ . get ( ' ESPTOOL_FS ' ,  ' detect '  if  auto_detect  else  ' 1MB ' ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-06 20:29:12 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        add_spi_connection_arg ( parent ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_write_flash  =  subparsers . add_parser ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' write_flash ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        help = ' Write a binary blob to flash ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_write_flash . add_argument ( ' addr_filename ' ,  metavar = ' <address> <filename> ' ,  help = ' Address followed by binary filename, separated by space ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                    action = AddrFilenamePairAction ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    add_spi_flash_subparsers ( parser_write_flash ,  auto_detect = True ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    parser_write_flash . add_argument ( ' --no-progress ' ,  ' -p ' ,  help = ' Suppress progress output ' ,  action = " store_true " ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    parser_write_flash . add_argument ( ' --verify ' ,  help = ' Verify just-written data on flash  '  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                    ' (mostly superfluous, data is read back during flashing) ' ,  action = ' store_true ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    compress_args  =  parser_write_flash . add_mutually_exclusive_group ( required = False ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    compress_args . add_argument ( ' --compress ' ,  ' -z ' ,  help = ' Compress data in transfer (default unless --no-stub is specified) ' , action = " store_true " ,  default = None ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    compress_args . add_argument ( ' --no-compress ' ,  ' -u ' ,  help = ' Disable data compression during transfer (default if --no-stub is specified) ' , action = " store_true " ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    subparsers . add_parser ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' run ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        help = ' Run application code in flash ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_image_info  =  subparsers . add_parser ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' image_info ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        help = ' Dump headers from an application image ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_image_info . add_argument ( ' filename ' ,  help = ' Image file to parse ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_make_image  =  subparsers . add_parser ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' make_image ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        help = ' Create an application image from binary files ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_make_image . add_argument ( ' output ' ,  help = ' Output image file ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_make_image . add_argument ( ' --segfile ' ,  ' -f ' ,  action = ' append ' ,  help = ' Segment input file ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_make_image . add_argument ( ' --segaddr ' ,  ' -a ' ,  action = ' append ' ,  help = ' Segment base address ' ,  type = arg_auto_int ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_make_image . add_argument ( ' --entrypoint ' ,  ' -e ' ,  help = ' Address of entry point ' ,  type = arg_auto_int ,  default = 0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_elf2image  =  subparsers . add_parser ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' elf2image ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        help = ' Create an application image from ELF file ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_elf2image . add_argument ( ' input ' ,  help = ' Input ELF file ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_elf2image . add_argument ( ' --output ' ,  ' -o ' ,  help = ' Output filename prefix (for version 1 image), or filename (for version 2 single image) ' ,  type = str ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_elf2image . add_argument ( ' --version ' ,  ' -e ' ,  help = ' Output image version ' ,  choices = [ ' 1 ' , ' 2 ' ] ,  default = ' 1 ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-30 01:28:30 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    add_spi_flash_subparsers ( parser_elf2image ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    subparsers . add_parser ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' read_mac ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        help = ' Read MAC address from OTP ROM ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    subparsers . add_parser ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' chip_id ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        help = ' Read Chip ID from OTP ROM ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-06 20:29:12 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    parser_flash_id  =  subparsers . add_parser ( 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        ' flash_id ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        help = ' Read SPI flash manufacturer and device ID ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-06 20:29:12 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    add_spi_connection_arg ( parser_flash_id ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    parser_read_status  =  subparsers . add_parser ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' read_flash_status ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        help = ' Read SPI flash status register ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-06 20:29:12 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    add_spi_connection_arg ( parser_read_status ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    parser_read_status . add_argument ( ' --bytes ' ,  help = ' Number of bytes to read (1-3) ' ,  type = int ,  choices = [ 1 , 2 , 3 ] ,  default = 2 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_write_status  =  subparsers . add_parser ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' write_flash_status ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        help = ' Write SPI flash status register ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-06 20:29:12 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    add_spi_connection_arg ( parser_write_status ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-28 01:53:02 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    parser_write_status . add_argument ( ' --non-volatile ' ,  help = ' Write non-volatile bits (use with caution) ' ,  action = ' store_true ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_write_status . add_argument ( ' --bytes ' ,  help = ' Number of status bytes to write (1-3) ' ,  type = int ,  choices = [ 1 , 2 , 3 ] ,  default = 2 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_write_status . add_argument ( ' value ' ,  help = ' New value ' ,  type = arg_auto_int ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    parser_read_flash  =  subparsers . add_parser ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' read_flash ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        help = ' Read SPI flash content ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-06 20:29:12 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    add_spi_connection_arg ( parser_read_flash ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    parser_read_flash . add_argument ( ' address ' ,  help = ' Start address ' ,  type = arg_auto_int ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_read_flash . add_argument ( ' size ' ,  help = ' Size of region to dump ' ,  type = arg_auto_int ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_read_flash . add_argument ( ' filename ' ,  help = ' Name of binary dump ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_read_flash . add_argument ( ' --no-progress ' ,  ' -p ' ,  help = ' Suppress progress output ' ,  action = " store_true " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_verify_flash  =  subparsers . add_parser ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' verify_flash ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        help = ' Verify a binary blob against flash ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_verify_flash . add_argument ( ' addr_filename ' ,  help = ' Address and binary file to verify there, separated by space ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                     action = AddrFilenamePairAction ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_verify_flash . add_argument ( ' --diff ' ,  ' -d ' ,  help = ' Show differences ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                     choices = [ ' no ' ,  ' yes ' ] ,  default = ' no ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    add_spi_flash_subparsers ( parser_verify_flash ,  auto_detect = True ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-06 20:29:12 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    parser_erase_flash  =  subparsers . add_parser ( 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        ' erase_flash ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        help = ' Perform Chip Erase on SPI flash ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-06 20:29:12 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    add_spi_connection_arg ( parser_erase_flash ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_erase_region  =  subparsers . add_parser ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' erase_region ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        help = ' Erase a region of the flash ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-06 20:29:12 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    add_spi_connection_arg ( parser_erase_region ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    parser_erase_region . add_argument ( ' address ' ,  help = ' Start address (must be multiple of 4096) ' ,  type = arg_auto_int ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser_erase_region . add_argument ( ' size ' ,  help = ' Size of region to erase (must be multiple of 4096) ' ,  type = arg_auto_int ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    subparsers . add_parser ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' version ' ,  help = ' Print esptool version ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # internal sanity check - every operation matches a module function of the same name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  operation  in  subparsers . choices . keys ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        assert  operation  in  globals ( ) ,  " %s  should be a module function "  %  operation 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    expand_file_arguments ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    args  =  parser . parse_args ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    print ( ' esptool.py v %s '  %  __version__ ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # operation function can take 1 arg (args), 2 args (esp, arg) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # or be a member function of the ESPLoader class. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  args . operation  is  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        parser . print_help ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        sys . exit ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    operation_func  =  globals ( ) [ args . operation ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    operation_args , _ , _ , _  =  inspect . getargspec ( operation_func ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  operation_args [ 0 ]  ==  ' esp ' :   # operation function takes an ESPLoader connection object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        initial_baud  =  min ( ESPLoader . ESP_ROM_BAUD ,  args . baud )   # don't sync faster than the default baud rate 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  args . chip  ==  ' auto ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            esp  =  ESPLoader . detect_chip ( args . port ,  initial_baud ,  args . before ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            chip_class  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                ' esp8266 ' :  ESP8266ROM , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                ' esp32 ' :  ESP32ROM , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } [ args . chip ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            esp  =  chip_class ( args . port ,  initial_baud ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            esp . connect ( args . before ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  not  args . no_stub : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            esp  =  esp . run_stub ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  args . baud  >  initial_baud : 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-30 01:28:30 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                esp . change_baud ( args . baud ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            except  NotImplementedInROMError : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                print ( " WARNING: ROM doesn ' t support changing baud rate. Keeping initial baud rate  %d "  %  initial_baud ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-06 20:29:12 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        # override common SPI flash parameter stuff if configured to do so 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  hasattr ( args ,  " spi_connection " )  and  args . spi_connection  is  not  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  esp . CHIP_NAME  !=  " ESP32 " : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                raise  FatalError ( " Chip  %s  does not support --spi-connection option. "  %  esp . CHIP_NAME ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            print ( " Configuring SPI flash mode... " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            esp . flash_spi_attach ( args . spi_connection ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        elif  args . no_stub : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            print ( " Enabling default SPI flash mode... " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # ROM loader doesn't enable flash unless we explicitly do it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            esp . flash_spi_attach ( 0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        if  hasattr ( args ,  " flash_size " ) : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            print ( " Configuring flash size... " ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            detect_flash_size ( esp ,  args ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            esp . flash_set_parameters ( flash_size_bytes ( args . flash_size ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        operation_func ( esp ,  args ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # finish execution based on args.after 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  args . after  ==  ' hard_reset ' : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            print ( ' Hard resetting... ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            esp . hard_reset ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        elif  args . after  ==  ' soft_reset ' : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            print ( ' Soft resetting... ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            # flash_finish will trigger a soft reset 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            esp . soft_reset ( False ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            print ( ' Staying in bootloader. ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  esp . IS_STUB : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                esp . soft_reset ( True )   # exit stub back to ROM loader 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        operation_func ( args ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  expand_file_arguments ( ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Any argument starting with  " @ "  gets replaced with all values read from a text file. 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Text  file  arguments  can  be  split  by  newline  or  by  space . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Values  are  added  " as-is " ,  as  if  they  were  specified  in  this  order  on  the  command  line . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    new_args  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    expanded  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  arg  in  sys . argv : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  arg . startswith ( " @ " ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            expanded  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            with  open ( arg [ 1 : ] , " r " )  as  f : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                for  line  in  f . readlines ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    new_args  + =  shlex . split ( line ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            new_args . append ( arg ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  expanded : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        print ( " esptool.py  %s "  %  ( "   " . join ( new_args [ 1 : ] ) ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        sys . argv  =  new_args 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								class  FlashSizeAction ( argparse . Action ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Custom flash size parser class to support backwards compatibility with megabit size arguments. 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ( At  next  major  relase ,  remove  deprecated  sizes  and  this  can  become  a  ' normal '  choices =  argument  again . ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  __init__ ( self ,  option_strings ,  dest ,  nargs = 1 ,  auto_detect = False ,  * * kwargs ) : 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        super ( FlashSizeAction ,  self ) . __init__ ( option_strings ,  dest ,  nargs ,  * * kwargs ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        self . _auto_detect  =  auto_detect 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  __call__ ( self ,  parser ,  namespace ,  values ,  option_string = None ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            value  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                ' 2m ' :  ' 256KB ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                ' 4m ' :  ' 512KB ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                ' 8m ' :  ' 1MB ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                ' 16m ' :  ' 2MB ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                ' 32m ' :  ' 4MB ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                ' 16m-c1 ' :  ' 2MB-c1 ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                ' 32m-c1 ' :  ' 4MB-c1 ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                ' 32m-c2 ' :  ' 4MB-c2 ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } [ values [ 0 ] ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            print ( " WARNING: Flash size arguments in megabits like  ' %s '  are deprecated. "  %  ( values [ 0 ] ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            print ( " Please use the equivalent size  ' %s ' . "  %  ( value ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            print ( " Megabit arguments may be removed in a future release. " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        except  KeyError : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            value  =  values [ 0 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        known_sizes  =  dict ( ESP8266ROM . FLASH_SIZES ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        known_sizes . update ( ESP32ROM . FLASH_SIZES ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  self . _auto_detect : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            known_sizes [ ' detect ' ]  =  ' detect ' 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        if  value  not  in  known_sizes : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            raise  argparse . ArgumentError ( self ,  ' %s  is not a known flash size. Known sizes:  %s '  %  ( value ,  " ,  " . join ( known_sizes . keys ( ) ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        setattr ( namespace ,  self . dest ,  value ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-06 20:29:12 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								class  SpiConnectionAction ( argparse . Action ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Custom action to parse  ' spi connection '  override. Values are SPI, HSPI, or a sequence of 5 pin numbers separated by commas. 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  __call__ ( self ,  parser ,  namespace ,  value ,  option_string = None ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  value . upper ( )  ==  " SPI " : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            value  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        elif  value . upper ( )  ==  " HSPI " : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            value  =  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        elif  " , "  in  value : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            values  =  value . split ( " , " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  len ( values )  !=  5 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                raise  argparse . ArgumentError ( self ,  ' %s  is not a valid list of comma-separate pin numbers. Must be 5 numbers - CLK,Q,D,HD,CS. '  %  value ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                values  =  tuple ( int ( v , 0 )  for  v  in  values ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            except  ValueError : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                raise  argparse . ArgumentError ( self ,  ' %s  is not a valid argument. All pins must be numeric values '  %  values ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  any ( [ v  for  v  in  values  if  v  >  33  or  v  <  0 ] ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                raise  argparse . ArgumentError ( self ,  ' Pin numbers must be in the range 0-33. ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # encode the pin numbers as a 32-bit integer with packed 6-bit values, the same way ESP32 ROM takes them 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # TODO: make this less ESP32 ROM specific somehow... 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            clk , q , d , hd , cs  =  values 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            value  =  ( hd  <<  24 )  |  ( cs  <<  18 )  |  ( d  <<  12 )  |  ( q  <<  6 )  |  clk 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            raise  argparse . ArgumentError ( self ,  ' %s  is not a valid spi-connection value.  '  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                         ' Values are SPI, HSPI, or a sequence of 5 pin numbers CLK,Q,D,HD,CS). '  %  values ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        setattr ( namespace ,  self . dest ,  value ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								class  AddrFilenamePairAction ( argparse . Action ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """  Custom parser class for the address/filename pairs passed as arguments  """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  __init__ ( self ,  option_strings ,  dest ,  nargs = ' + ' ,  * * kwargs ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        super ( AddrFilenamePairAction ,  self ) . __init__ ( option_strings ,  dest ,  nargs ,  * * kwargs ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  __call__ ( self ,  parser ,  namespace ,  values ,  option_string = None ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # validate pair arguments 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        pairs  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  i  in  range ( 0 , len ( values ) , 2 ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                address  =  int ( values [ i ] , 0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            except  ValueError  as  e : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                raise  argparse . ArgumentError ( self , ' Address  " %s "  must be a number '  %  values [ i ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                argfile  =  open ( values [ i  +  1 ] ,  ' rb ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            except  IOError  as  e : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                raise  argparse . ArgumentError ( self ,  e ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            except  IndexError : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                raise  argparse . ArgumentError ( self , ' Must be pairs of an address and the binary filename to write there ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            pairs . append ( ( address ,  argfile ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-10 15:40:14 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # Sort the addresses and check for overlapping 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        end  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  address ,  argfile  in  sorted ( pairs ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            argfile . seek ( 0 , 2 )   # seek to end 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            size  =  argfile . tell ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            argfile . seek ( 0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            sector_start  =  address  &  ~ ( ESPLoader . FLASH_SECTOR_SIZE  -  1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            sector_end  =  ( ( address  +  size  +  ESPLoader . FLASH_SECTOR_SIZE  -  1 )  &  ~ ( ESPLoader . FLASH_SECTOR_SIZE  -  1 ) )  -  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  sector_start  <  end : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                message  =  ' Detected overlap at address: 0x %x  for file:  %s '  %  ( address ,  argfile . name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                raise  argparse . ArgumentError ( self ,  message ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            end  =  sector_end 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        setattr ( namespace ,  self . dest ,  pairs ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-01-05 13:54:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# Binary stub code (see flasher_stub dir for source & details)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ESP8266ROM . STUB_CODE  =  eval ( zlib . decompress ( base64 . b64decode ( b """ 
  
						 
					
						
							
								
									
										
										
										
											2017-05-06 20:29:12 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								eNrNPWtj00a2f8VSQkhMaDWSrEcIxXaCSSlsA5QUet020kiCsoVNjHdDWfrfr85rZiQ7BNrt3vsh1CONZs6cc + a8Z / rv68v63fL63qC8Pn9XZPN3Kpi / C4Jx + 4 + av2sa + JsdwqPuX9b + NfWdb48mX7ffxe1fCV3v \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								tG81N + o71C1zPivbniqHWcbUk16c9iZQ638rpw + B5gCkuzPRDD2o7UfjtcuZv8v1DV5HEcivdtrrbvd / 0 hqCqLfyXkM + LzvY6SBksOPA1iI / qxCMZw5AQBPzdQ6N2mnkBtGx8wY + VqUdugjmix4yMgPCfCk / j9t / \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								aqehQmcI7YBRBk5DNWYR + + 3 jnAEKXFCBOEXlQBc40AWdl5rmMvOokYMi1aV5EDishg2ZvQTWEkJnmdMobOMZfjXefYD / CW7hf94dGfa4z7 / K + Gv + pfUX / Eu1E9QhN6osx18vzbN2kEpmzFvAauTi8YMtAYmH9NrR \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								K1pU3n5ZKGJy + ES1v3XgFxs + EpAWHBYH7dOwmLbjh8UE5iva4ZqwuENbpU5pNG1QBFNE8FARKyICAT3t7yBxNxiAFH7jpyEwI8 + a6aEH / Q / uEjkC1TYL3kZaCY2VPBzuwtwDGlIDWsKpwC8LGdGkVbEG1AIfMioC \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ZQYDqoRBPDAPcOhd + IdHi / ujXfYcYEWETOTHI9q7TXMuPxhFYcmA8GC6WTcYcmULew7c1 + yFBsZtEhIqWchngpiM3tAk5sWOfaqicAJsEnIn5T86wCcjv / CBW2BcIBK + jUI7VgZ4VirwB810vtze7UATtl8zGTSv \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								qSz7axLSg6yGRgbDFiw1spZ6BeO8kWkj352fxlNqAD8GHm1AFL0tc5ZtF5XeBUmLy6KR65qBUZcAI9AWzSqZdcvFVcV8Q9ii / 1 YhCG5AFSI5IeiDIA0fNQJt + zBnodckbzca7Dz7UZ4czN80G9L1Ac8J31SuGGoO \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								8 Ktz / P3EmS6yEOZZV + TlHeCC5D1BBlhu3jpDiIZKuHPQyFezd3a00hlt9hqez9pvWFYq3UNETnNtNyQbaHVj6QwPWkDe0MhND84vLBKy1H6iXACm8tx3Hj4XqEKHrpWCHirabSdcyrOAngGHA7S / 93 ihS9Ysuea + \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								i7rvGAkjF1eqAkkOmgtGf84SKTF6sOGPwtkP8u7cFSq / rbJg3YqtuiKmVjjxa6Ngdyfw0b / 6 H52QyFcFLogYGBf / BfXK9MMBsGB88gSUGsvLEHTJVyyiEpbi1p6ALYfi9c3KdI8JnXVAc2mc60v + kX5Fa4A5UIWt \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Dk3LaC5bRrJ2GSes2mvA9PeWBGBnVKFs7S2D8GfC7D8z5oUgZSMU / VFocmvl1T690snfXGJvSZfZQ3icPfCGjoh3AQmF75ztPst4Phgr5ulU2I6y + WmjzEQEpDQQYCiIZxMXuR4xox0u5N0WOOMmpN3tLkbzJdsF \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								+ + MxsQbqJ2AaUCPayk4eJgc9gZwv6r1uZnamujiYWrKDAVnXYx + GS7 + A8R8zdKNSLIgp / 0 A59RRkvkjg9PQpKp1DeHh8OIAOALgaRwOAS4tO0UrWPMDd2wI5u + HgBcYGvFg0OLhRSTRfgjwxb7MTFmlZyEIIkaOT \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								gRVVGckP4gkSB0JhtH + Ra2YDw33fYkdP + I72bIf1gsQX1ut5L / w1MILXncayP8kplXY + M0xLrGGmxsEnTObaJfs7op3WaZdpGv0PRRq2cafNX5K10aTJLnw + AP7ugpUbdiHDPGeRGiCo7S4Cuxet6 + wbn1rBaPj9 \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								gHpp5BwQWM1zAg07RDP0OEZGyvLylbPPKoumVYyShBKTWOBFHgkGy7sLNoTb3zDiwrEytONPrkgxsMN1KYaMkinAZlFhyzER7v + pELztjBu5Ke0TgCWIt0Ki23X0nS1hld5ICYdIVSBTEIei0nCa26xLo5S9LxzY \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Y2hXmMQjS7KprTmGktZ0yHY9mqipg8lkuMmoafr9bsNUN + eCuqr / 3 idLuc64Q97vwMwZu / 6 Zj9Y52ujRFP6Nn83nYIL9E0aZkRtG3dfbkREakdEAuBAYFeUGsuPdH5iQCfBS1yX8uE3so4Cm3WOFYXGDGa92DK3Y \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Y1cUnDfNSy5Dn / lOie9ZMqdEPhqKC + 9 GWVwjb4kV7fWUxarspRA7hAXw + + gBm76hNzpnj6QGPvFunH3D6rk4JJcZTPKq + HtZ7OAgu + Nn7C8WZBnDJlUohn6FGS / Iuidt8SvBAGZorRe79GEG5FGj7V9hwmJrUWzi \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								wMP9JyA4P8BWgw7xSxAjwNFlZNkdgyCxInS1HIa7bJveI0ZCZtJMmNSVsBHxEewH + G8W5rANcvIuivROjs7t5mv6pP25xcYLKIoWO2D16Y0Ag0ntHCkzNVhguThR8dflj4Q53KwNUvcNIaJIScTW6GMhC3m / 0 Rig \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								+ nSTk6mKAmjELic + 4 KGsjWQG6H26Aj / q / hrm3t + ZOQ4MjrigJV07TnFJr + 16 VPSc1jH7wgl8CPwjC / / LHvx5aNS77IbAq51OGjt5mh / BfyOIPoUvWdoH12DjvPKnRfC4iMviS6AP8ChzryKmW5EGCPXUCx57cenh \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								R15EPE6bribffdAQH2r9r + NBLJszG6DvdPwdOLzlUx4uPH / ObIRhIXRX0D9 / kVr8B6PxGGIuYlUkY9g2UdAA0 + gZD5WsIN + 7 B2PvHuSMaLJFgsiVLMxKTXJ7TCRk5nBfGj5jBvUH27xFNS0u0JG3D3PlpTApDaMl \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								pCh0DYWQviyP57BRG98GUYmc / Lsai9QGJ7yGHZOVzH4JKwAc8ZxVRqstN9vllOnAm + yQyoC9VkcT0mqwrKY6ASpsoJ7dRGFQ3UJEbH4EEblBxA4HcPWTE9JuTcHmRNzj6Gz9ymeuJfAHlp51ls7L4LjamBcMlFIf \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								gH4D + kgF1sZVyUOSBQ3wZ5Xj4jcuXfxCVo4OAY6jT1hNx7NPX / efpDgsG / UdxKiCjBUa2FtN / crf84HVpqSYDKnZUayziay8F3VN9yefzv0wVUV / uZaw0WJH0whlTSSxAhkMHtC31YRN1NqIuFf + fV + wRFDz1NYu \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								nbBhXL2K7kf + AfQxyPYYFTAysF9TGbkIIwseBLUK4GmSWdfEw2itAmsJlP8y91sfBEQlBb2a1sZY3grnyz3X7oBIJAIV + BjdyBN2mxKOuHRRuPt2JrFkiUQBx + 0 j5q99KsftRyekTuuEP4n7ZGSUJ3 + ZrGkCu + Fq \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								TH4s0cTYcjjMsp3jjQbB / sGMFh6Eq0KllSY5QA + 7 MVh4EFgvm8VdAfCpNf5IFz2kRhUcgH1wuoFWwnUyqSCOhYSoeiG6CKhQrgEgQwAyAwAjiq1zI / N2wWZaosH / 3 hrxawi3C0qqnazM1uwmpBKEM1v67hwD0Bqd \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								mffwzwWFVAMFUbIQWom0kpsgrcC217D6lBT4Au2rng6vctqeVocvvFB0N2lt0OAwo37 / 9 Kzh2A4Qp8k4NoHobvf2Ytb32HrrwYRPxFFRZI0t6 + 6 Qn8z85L + A7bMrxjiIgmr6ghwyziV8ZFE6XrMoCXxkwwtFhjN0 \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								sUtsV9yuGzCXSuIimx4IW0UXbO2CX6vDM0rZSdA + j6cS + Sx99vWa1JccgiR4gMZ62Xdtp0fmU9phWSZDgIUHeZY622N / G6IYqYzXDI8Wh / ZjttIxDohhSOXE3QC7EARvpSMkAnizObr82ucYNRh5FiGj9f + ZkMHg \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								RuO9JWLShnfWNznnFzBUiEOBoaXGM6Yw4KtGfzMY2PDoGsvgiFhxDuPdjwZb8D0kiUCborIokwTx9MKC0nq / CPdjzA / 3 jeekz6NCqJYLXbN5xozjZrOT2 / tX0myN / QV23QmpFx3 + P1AM3reokb / qc2WL82BzuDl5 \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								QCiydqhV1MZIbZHvpajPfYyfJKRilY6QPBHOCVl8dX7okuZsAeTCnT4 + ewfqaQHm7zNwRdShuDytvlIu7RYFjfU / qwJmfn2yB09p3cP5dSdWFaiT / gce078lEw6JQA13ppSIxOSPerTKIi2HqZZBtiEAhDIaCy14 \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								qiyE7an84iZC / oVVha4XliVuiF2AH2IGKnJFEe6VYLohXH441fSzBeILUoLoxMcyDzCaglymeuhqYNb / GNVZIHrbVkFqPM9ATUIrQ6nsc7iHZox2iNp5ccgZq3pkl4vmZbLJ6sOgm / PHTOrlni9wDEiEwx9gLccI \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								wgcyS8HObXL2SS9R1REYkeAHanDhMEeXyeRIxLzIOMsleEx486K3C4URmM + WBHA6LXCbHUICPloU2Vk64Bi + UmGRhl4y9VIEJV54SVhsj6PB1MvOzpHxDxdFMi2yexTbqRJWsGDTpGlwdkRYzINDG5Afj9W02Lb + \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								JwKZcQIQS0kwPofgT9s1jd / CAFNvG2gUTb + H1kKy5yAqUrKT0Ihq5KvgDFTi + AK / ZTqjr1 / 5 OAJyh / j8dZBPBB + Me6wRCduVn8HKzw5hCwCd0vE95FV4giNX8XzZrgfmiCWeABuoBdj / DoX61AT + 6 oWHyL5osdb + \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								DNSkxTDsfG30WcqmZbnwUpgvO0PUY3A9CLKAN2eOQIyRjc4iWlsePrGSMM / dPYLRMha3tubDu7m1Y4PgRWqTvVlltQGI6oqT59RXEssQhQfIi8SXVzsSGh5h0A6kKCDmnJPnerhx5jPiTLqG2QI2TC7xTzX + Wsme \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								uUcwS2LdrV3ADumY0q4pP0Nv6ZpdjKn30WQr0GJ2KFADRm + jP5Ap6ShdjOPAdtEBxHSC + D5guYgI2aGN8wHP1xF7quX0RmsDgdWLVlzMOjYRJxOiFd26l4877eidRScw3ei / 57 RbqoeO85k6ToTJBBgaTm31Q1be \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								7 MwR2ToWNoA2cdaNAU18g6ASFYsRVdhLLv / 87 jJP6DIPCqpgIMyD2jvIFYydUZXRG6tncgkZamaHmCmvSjFCYkt + sDQN + X1UDQSAzxMh + SEzieKEvYomFdvCB0ez3YRbppiBpog6Zp2TE0ezWik04LQ6g38pSIJW \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								gpKggKb0M27hrb6vOeV8QYA + GQjPLDoNZX + kJHORr7LXojmKravcJqWNITNHc / cfhESCIMfCHsptGBPKLzhOd + eKON0art / gKF0Wr5qIhvnTKyJ1DudrdhECshw2V / eA5b8gM / shvQ1Tef9DayVK5vS5pnxYVnBK \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								RuU41gWMtYoLgOsCCH4BKxxeeHdhSDTW9HDrPo2x7LAFyXTiDB5QaZGADQquJdg4LYsc7h2GhCN1hbP9M63EWnOt / UbO9vumZ / B3HYLzLfhyihRS6OapcEj0TaTsp2le8L7g + BKtfYWTnoBU9LFyD4UvRDMavRrh \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								X1Cp1 / 0 + zC3AHphBXOygpgxO9B6sI0ijNZrTdogxddAfYdXn9jCiBglNjJOXUU6 / wCLEuLvepnwniHuAq0Qr9ondNkYb1smUJaQmzYD6JuKiymRktu7OcS76c0Pk7Lc2odlwiaLRrjrZxrA517OVGDkH6dhRqeVf \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								pFIzUan6UpU6ZGGK1aQx12z + QZWKIKUdlTpao1I5Hnztc4TLW85Vsj2ERZfVOu2a / He0q / 6 LtCtLk3BVwU64bMOy0Fj0mmUh9IAGp8xCaEgFgx11espxy8QUb2NI7QNpvsyhvSo3OhoP5drpC7RkUdXuQVynaMZg \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								jQJe80QYYGYqA / pKdSUsMnCkJBVjvBBjdfa13U6mbEeTH4hhw3h9oKkTXi3duK6ETIxxDInjFJy23FbLWp6QOoKNwWV8sUIb9iHLwNBmwrXl5Z7fIVPgkClQLWlYOkV2IwMlVLn5gUPZPfsGC0nMXlxYwqH2ATla \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								vse9ubpBn4jRI / QZCX1eO5nLSwjFxZumlmyz72yArsuna / GJgm2w + en4nK7g85z2YlPe9y91RuCxwrqE1sv6mjHb5A5mUxM3UeW9D451l + Kiz0SHY73ZGXqR7316iOUCpcH3e2NTWsPSxyBPhaoELTnI2TVY4uK3 \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								k4Z3HQUdd7A87mFZ6iXKp68tuTgtLyOpG09nL4SAtMEbyX5AYqAQJGOocwi5PBib5EdDSXqu8N6UGG / 5 qoRHSQnmkkrATk1gY1aHDIdkFgLc7NllknsDtQAnsQvW6XkEJXFN9TGrMOwJbRvxDvtC25g7Nzkx1jcR \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								WciSCA865mHRMQmjjjUostkJ8bpm3RqrTyJFrt1ARIvFzNjrGQ06GaJZcCQEQY / JKFUsJWgkDqm5vk + p0zFLdmDCQJ3 + IsZB / IKNA3t4omslqPQUS0Hv2T2cIX3XGQdmHUNY3vcAo + tsk2I4RcY9goUB9wXxq0MM \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								uJkgSx6L4DkUs0DfiNLbkmNK + lbBCo + 5 qvVKNsuYzQrMwbG / aDgs / w9wWJ + 3 gnVGAuLOOUBQjT5qJJSukfDwUiMhHnMtfIH1sOul5jmHIy9lqKnLUF1rkw4etFJTAnrWVMjVkAZF3kiM8y3oSSw7kKHI7HCpoXgg \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								xI7X2AmXCMYJFzyXsinV3iHmVqbF5oQSsfAOhMBejIdlMGOskpf25EFZTT + dxVZKxrpcVnL0qEz + 44 xWXi3HXoAQ04sVCZZ2PqBAgyPHJBloNZ7g + cxRQIi4XI6GFSU60NALKrFaRw7q + sEIa4pT9IXOcGz0C8Ji \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								GBwMvhcReHx3QKbZ8PBedpcLUqXGDzdGsfuEYuJ4oHP / iccFE6C89GZezn5eTxgnmV / nC6jPN47 + LkbpMeetqOoSRiMDLBhuOO69Ki981MmLYojKVvZ5WUrBUetimIOQUzGSSg4VVNO77nOFTSXN8FaED8JbT2Hb \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								JBJfFLGXiqfI4X50S3B8AqoB4o3kocKH6tVTttaVFd14Aq7un96DaD0a1CnXhYSc3QVutfVYX6ErhpmkTw5x7hJM5I / N / s6BlssiPqO / xCHTJon7h0uzpCBbamVuIyq2Pj2dvcs5IcLDySoernJK / 2 x9mu7Vp1EJ \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								+ 5 qarJlV8J + X / d0la8C63hiW + U / 53 erftDlV2RzxRKyWcHrMFqGhmXI4u5S1dqD2 / omSZCMv7UHV7HJuBgUWexCoLbAMiAzHduFDKGtZwHYByyv + DX79Qk5Cho8wBAQ / Rh + 4 ZAw4j6NU4KzoEYeTUjZ / EGdIwGdA \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								GMV2dnFMpGlQIujjY3DGqGLWzfWD1AX82CDY72y6STpa / 0 YlsxwB3O4l5Z2UIh44K5xn6oefSHbANjJPIS9bPF3zIrrsRXzZi9FlL5LLXqS9F9jI0Awtogu0oc82JoBqn / CN58qD004RmHvap / T3zEjDPTGRL2At \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								DZoMkPEO6hbzGLekrH2rxb4kKjwmM / t1nwotwhWG1PkQHxyF4FPKv / T7LjzK83LB / hmpYDos4315 / h30b2n4IxNWv7xNvFrC4V4tx7giYXw8MwUZQpy7ePqc9nvNkqzi + AEkmYrwA4l + FALCmZz2B8GFH2W8Q6Ne \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								9 FhEWdArfJYDaZB + q2p1j0yEG9tY5dvIMUFfziHwORsFoehiZyObLzAqDSiCv + hs3yZS1aiUcxVYI1OhQDi9xtZp + dPxT4NjPuen8 / ni2AdZqBcMWXqTWCgbReY0ORZreDfo1JiKeGZ9RLGBrJaDJfjF9j6ohamj \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								l2vZwjWZl9qEeOWAULoDjKAdDGJVUw1jaSM1QW4V8knGmDUcC31ZifzsdszbseFgMVpDARzM5l6Q2yg81l3wUt3ssx2fSOo / 1 MmJGa8D4XdOXwRs9kQ6rh1 / QPcVSFCu4LlqOl24D4x2cwD5PMjRZeaQKxOBUYkH \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								4 YvtXejfis65446G / bs4nMNBQP5R7zSXPUNgTgWKMcfOCwkH / N7nawAqPmtEhYFfchEIbJUmb / ekWA14gEmjF3UDVMTG4G + 08 kyKkXENRw + ezecvf333ASHho1FCos7Z38qJ2vP + rEILMpY + F86FKvlKudeCe6aW \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								OxCJzlUHzsFBPkQSiLddiJmdH83n2S5e4 + DhMer2UW7jT + SaQ + C55kAabs1nzjk0nUH1AIQ7YT83 + XHIuxVP5eE7Xp0grBaYQ + + ge4mFDj28psLDayo8vKbCu0M1l4rKp52rT4hFTtmqC91bYcJ1V8RAVqjRnXsV \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								8 LqFwWDzZMpXUmAReTOxeRz3ngXPGu38 + OvOZQx448TJstPDubZBheTfDjYCs5TMuc9Grb / cBvxqczNMFruXwYzNnTQPqJoGbzJRnU8z + tSBHfe7Ytsll2tDBnL2FZe0xANsmLCL + jdRyHk2Kilegsj8gB80qtMV \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								D7eZ04PNAEzTbPSt1LXK6Su46iKI2L9t8on8aPuPD2i1POAzZrQaL4e4H0k0A / HQYNC8gtBDE5tPSgx5379rgTrk + elLjy5aaRpkqpjyZ / seWHfoOSA8aKi5t3TgOdhHpGzbBUtxPgd5mmaFdSxAz + k8q5FvzuO4 \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								y21Kjg7s + TaSxx3wYDVfioMnRPDUISdwMejdyHZumPMthaWqKPOI3FgxxzyhAneXuXcddYXx2C7TBm7cLenwmA4LnlH9KuH4Ak8 / 7 nL + m / VHAJd81GziK0nI6hHZrfSQ65theUUmmzbuIDzvbErk5xOo8222H3BJ \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								RzS / vmGzvSqcfM9wGS2 + vTsYxHLypp44EJAA3C24ErwZP + 3 soBBDqkGweSI36KA2adBuM8ql6fKD4tIZ + 3 iqO + yBtX8kWbIHA + SD / EG2u + fv7Ap5gZqXUfGB3EskHWq0LkArqbu09Cp / dARKu + X35Tlyv1VTqD4g \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								q4zlNuBdV3CtjsKLFWKOBmo5HsN1unrStR / R7YmEDDUFgt7Q86rpk7dvIbH9c53kRs3uYGPcQXDHNRjO9UNzJlmvXrqRaanm13FrW + FXw5vg6GqwhirWVGi55nA3RHYOqIVrLrJHfPSkycx + GQiaEQhzphjOw2FJ \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								qN0ELE / FzH2MUiiYzyfPNx + JsoEv4p2YLj37wTfbXuNFGjr / bge + goLyFXsgU7e5MhLXNgp22TL7GFe4AMpdKCVCGqg7 / UmkA4aq99eC8GkztROY + wLkcPvoLjOOnJEdiZJAmKQbniWPLoMMKyPUZ0PWg46oxGoR \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								qYabYI8Z42MRK0qgsb + T8sG12N2fV0vb1Q1auYRtsXceFvZ2KbViHGZsrANw2gDUu81AlevQJKze423q8My1K166jTO3sXQb79zGh + 5 lfFnvcr6833ZvYMNK7szco / YN / orNs + qWcz9fnsslasacc9HKN + KgYAD8 \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								gsBDaQdSrxWC7k1qcG0HXlUHR2Ak1ohuANurqvBR2cgNCA27FQoDV45jQt75Y2aYJvyVbwRZK6agELfk6F2ngveBZAi0c6lC / 1 M8MwgWLIUMho9gqkOxL / DCG + xayA1YuMqX9oRFlcgNP + TbYBAdHQg59dVY0weW \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								KneWFU9 / k8yeMlK4WlleYetm2onfcUBc2xtifuXYbCJG2kQsoZvMvsUhzBTfnsPpPbIuES29qcP + 1 I / 49 ovGBiZaqJ9xUKOoH / Geoee / wPOCb8NwoPX4cgl8RBl0DKVDeR94MihJmrMvhYWiTNRnaOu2q9pmBWtB \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								qpxrbSef1s4dcuEaHJZmAQ1HcED + 0 GUvj7hCurHZoXbII1pnidlYcxwO6 + NHg6cBBlZivnIowEih5Y / 7 iW9OtB2656IhwhSxgC7zrUNwGQo0QG / z5FhrufaiNjmgJ2YVgglpDrKRnKv6SrYyene4YX4SL6YozMmO \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								C7kGxyxwwmUxjXW4Ww6aYrbgXuqI1yAYbLAUSkuHVDFfy1JX5iQvXaPZGNf0ky0F / Fb1pdInCaNaVIGIHy0HCZ0xXQw16h / msCWnciVLrTlqbzY3bqC6u4GyNRZUgxg0QNzmIYKHA / 4 mX / 2 m4mhuJcGx4AQPaHnv \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								+ QY + R57yKKMVXrlYYRTarCRLbvYDlkhSqDlRyz9GKGsfPBbliVb492yMlJabcjiaaQ4yBRFFXXGcLT4tM9ra5BNQptRiKuYNHMMJh5hz2RHvsHNuT3pq7DlfyszYmwLPHaClf7Wuv7X0zDdUB4XN67sDvN7357fL \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								YgGX / KogjdM8aK3S9k39Zrn4zX0Ytw + rYlnAbcC + e4MtypCRkxB0IvxUQsJ / iApOPsIFvHP7k3Kc1PiZC0jwJlQlCdMxFzLLG0Qb3kg8 / sn86nzwaL7khy0zys + sAUdkdWyncYNAXe2DC6xlzMZpqFSOb31kXOLh \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								9 d00n0xqG39nuxEnYV4lFEUs3oPxBz4k8PHpLm8UJd0E1H9zZn49YUYKxjsO0pvITHxhUIqGMuH / jXmIF8bQDEefD9 + fbtSNgemawLR01ty / M2wlBB312r0TsN2jkW6xD5WMdVq925VVb248 + uUqysC9P9Y2OncC \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Fr2oTW9Mrdbcma16 / fv3aIe9dtRrx7120mtnvbbutlUPns6BZTVwG52e7mXc6nT12u6 / 7E9 d0Q4 / k4eu4qmreKzfTq5op1e0s4 + 2 lx9pvflIq3t797q2 / mh78bG9c + Xf5 + 7 b5LNwtPyMdfchb66QAj3IVQ8S1cOi \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								6 oy34TZuuI3OsLfcxoHbeOI2OgR525M0PTiLXlv32nW0Zpeo / + Iu / qulwJ + VEn9WivxZKfNnpdBV7c / 8 U4GNm5kdmOLOo4OiI95pscmULBhrHMAwO01d / v + KWF2pz + ataw1Hadj6ltnv / wsZwgm9 \ 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								""" ))) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ESP32ROM . STUB_CODE  =  eval ( zlib . decompress ( base64 . b64decode ( b """ 
  
						 
					
						
							
								
									
										
										
										
											2017-05-06 20:29:12 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								eNqNWnt31LgV / yqOgbxItpbtseW0WxKgQwjblkAJgc7pjiXbCbSkkM4h4Szbz17dlyTPTNr + MWDL0tXVffzuQ / lla9HfLrYOErM1ux104v4pH8FThk / V0ew2c4 + Ncq + d + w2zW5slNKj1bOH + hafs / tkxfcWZ7f8z \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								UwG9jCbIT2XCQRY9RT8tHPUT99kSJQ17GnrO3FiW + 713 YE3M1cYKe + kHosiv27PF2fUq / 0 gGiKtcTuLey2Q7W3 + SLDskVvvAp6ocJ23gue8imdmlPZuG9gwDyMTZt7ul538qPOssWg1K7R4RAflldI5I3RvCTZ7C \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								J + D7iXuYwEl0OEnf0td2ItI / f0wiGkRUxRGQhU9v3TwYNecp8PQGVO3OZicwI2eioLoCpJ0enrtX9cCNF5GKM36GY02AwmkYDLoCuU1oRZePPj6 + HGn6GOW5YKL68XHKqrbZQQmEHjfpkqBFiGCXyG62ZKT40mSR \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								rGENepN9FBmOaKeM3w8P5ekYmOA1akS69KSDslDCIKAaHo7kwR / 0 HFzi5AlYnhp92Hb / VEmyYIXm4KW2ugef3OS + p8lGhWcv5jbf5Af8LcgOWmavceQs2wdYdx9bvYnImkilDf1v4MfPfjvLHtg4jSqztHPDUgVB \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								wEewdRhreCy4UP5XlrvjR9vRcY75S7QBcq4iDpleU8Mev4 + Xazorni8LXt2hh9fk9qqZEjZl2Xc3DezCfVEgafdlMfZhJr0CAjBQejp340UTGOqUh8YFH70YCeWctzXpJhMGAHUq7BrWOjyXghfO5OzYHN7RkjEm \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								vdwH62IUPCLbcBhRZhPL9laAv4Onl + 9 fv5zN3BxdyeqeJESu + dStdl + USFnfJ9kh9OQUDETsMciCWlQJUioSx6jJE0YSxoU + 8 mltD1KyKVvu / AW5OnjzDv4DluGo4HtjNBiHKPTez + hHLsY8Or6P54f5KUmiDaFL \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								JNt2BNc6CgGBqx9nVyHo9Jb8CJFckaW2eUB58B8lAKhIOF0fRZg8gtJi2Z1DhG6TGE1zjo4m3 + CZYOLDKirHsmyze2Rky1EKDUiCTiaxvFW3EZscFPF4mRz1BGbmH + EVdXWUwnOBnIFHthBWmt1d2lbTnJAN6OZk \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								5 z3bC1rV / uyK6dsJ89uM + N0jrPFhPDAEwIxqy8kIcVpPuoDvnRlnJCPByBzLtl6MaeNaoamZTv1f6HQ8p1yds5oh0EkOgHYVEEToybsyKadXRsArZ2xdm7HJ83n84gCuA3OfOPvv9A / sCY2NhiF + wnndS7WxQTwA \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								VKGCoyxy5KRVwEkI / hWHEvSil08A0TvOSkRDKkyLKYE3wQ4y37AjrnBRLK89SQ8RPs8sGSs6BLuuiVYDsLctx4R + jQ5hvIlSHyNrHgQrRQshuSM62WUteB + KrBN2tN3 / sojLWF + f45dF / HIbvwBIXTDWAZ6zi8AW \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								l + wsG6C2JsIHOWI70Pm0fg7mcB0khV5a7c2uII5oc8Hz7tAcng4B6JkTOAzmUw4bqPQ6nhIv / SPsciroBbo3wtqbj7RIkses2o + SNK + oQ0sCpmOEuoCMZ34p9lcloBAONgAwq8GGsTzKMFAKk1dw + uoTsdG0p9PZ \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								tXDyQOQxdzviFmyzGP7YAhHieEfihWRsVOJ03NbMlFlxro / px6c1oam1nDjgbi + 79 YfWtfvcFrRFH1cTLLOuXK88yUcUp9uY9OXbEhy / sKHVKCIoxarp7ArOPKG5bf5CkGqg3Qkiv1M + aTjd6urN6WyL / AylMnyG \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								j8nYM9sVdO3DaXBpts5FWeiTIHRy8T2I2Kj14i7 / ewVMKdgXDtSptyR03VOe5auhOwo8VxP8 + fjoOfjfQ6wDSjSCxSFbEFUK + lAq + SXFLNeIYIl6hOeHoyJ2LQMEmVlUoWxFsYT5isolmGRCUfT9kkn3DCbnkvkd \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/ mMXQ4XOOWJYu4dPP9F / JVV + uBhNR17AZKnsOsxIfy6snHuA + olCLE5VJdGCEkVxPhv54FUKAUo / 5 uwjuwvANyiKY + HVMdhiWEWaj7GEeJHWOVknWkgum7wgvLYq6UMqiAaluILDh14466la6iYRUthdyC / te5 + s \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								PQ8BT44TuPVul5JVw0BUHRbObpMHyahtUjAkTu7w4naNROy4taK5lLAEOOBCNk / ugcWk8Bi3ChICE0jfMnY13GaNHw2Rf3XqNW8ZDYKwoGAAwYHUW2mIWO + e / RoJIUr0r2DThxtMrT8ieB + GEzOumwGnx42iW7aA \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								1 RYUj6rKHMHhDYWpTKWnswUOqZ3TgcpmVaf8tZBp2HGCVoSap8kATRa9DR4XcZPvnHJhEdmINmJnBLZwPmvZCmgL9ovxLpxA58kGlVAYymvKbpQa5xqwp2UMlXFwltaP96LEqbiAPz6x2eVwmEZS0orCYpZd5H / C \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								k3Ax6gGk + poMlYz3Mgg1sR42ZRxDhBtrEfsGqZirX / D1jM / ryOjBp5a3rfF2AsixxBVB1AWm5sPXwJi2EQWcM8jCKbV4hKaJaE6 / CYeSd9vRjrZqaLttMGg / + EQmw4DjhQvEYYnbH3hTLoZliRpN05UEUptGjFlm \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								rEFw5aLYoQeErWrf7bmQsYzGqDIHUTQ + TsiUpQ0fxN + KaFMKeJmaktmKxKDwpQ1 + Jzn9Pvqw18cmZySiThY3htJR5GIQdenTNJmnZOOq2uUK002vozCJvSWoILX6uowUZ5QEKPBEzHEwG87JH6y9T9SGJqY2h3B8 \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								RmcZ + nbOThWVgC3 / BuxdXq3ZtEMInT + FjfyOz7gTu0KKmL9YofMe8qZVzs + 4 QdNPubPr83LpigRJT / 8 eDN7PzdjwTaSMXosZPlvztStEVW1kFZnaDNOyai5NKkwxsKN1whjSxoZmuRpXjXjK37hxoan3vEVY1ZrQ \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								0 rJmTV4ERlcip3uw7hnseBTF3Wp5wxZFciY3BXW0ZUISU1xZWAXA2PA1BCZ4PXec1Qeourv8IczEHcARin0 + c3USOpLga7COuEH9LWJBVBfs8yjm51TqbW2 / I6iHRuqAHaOBDLbxYD7fgSaIIdyGXRquH4zgOstN \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ckfZmbuuDc0yBqwdjom1aL1LAdvHmQlDHjyXEgoqjjksrRZvLBI2GhjBHm + VyPw6YlzxaTJ6SOYEIbh7tkONHRLWtBxXKJgcd0GU0nZZEqY3qd / IXYqW7 / oimBwXjQY7yduQVlUPA / RqQkLNaNeY2McE7KYhkR6O \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ZabAUrWx5ESofRXwLr73EQIclrK1Hk0fVb / WhWHrPoQRxb6MOXMZOwS3v210PxYZmhiRZlsDbbSAJQ2kfE3DyWAk7VcM1JCi9Z / AxDq8OpJZcDdQ / / gHIgnIpsqVkwGh / sDb8j616Kxve + 1 S4HHqWLxIkY2rF1TX \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								4 RmahG7nyIJzelHYEd8g24Zp0BTAPLWSSiQS4igoNeOIJnJbVdoyrA1DwpccAF5NzeW / v3BpJMVqMcU6YzjXSynWIJcNlboAF5tQQjQ9RWYxyZq + xWjqo7EJJY2qo / pwlCq8WAn1qvptnGqoKuRJqgzQq6rQBOtq \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								BkLFCWIfB6xLIOOLmn5cCWAvtsXMGIzmiN6MgTdDGB03ArtulQQmrQXfxygux5bmoIPqUEjTUfFWwMclyu0gBAPy9 + Q8cZCXxUbAr0jjzJs4VgruKUxC07BBxTySIfeUpmAyPfBpMl9PrKTzg6TzQ5IKCRMlR5bR \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								y6MAVDtgL / 0X7 hF1oJP7uElLlPvsBgR / Da / VLSR0trmpgq0BQXDrjttmFisruYjQ8OELtTwGvuTBGdCUKrjWZZU1fJMxSA2jSYXAhZUx7lWB8JbV5qDnCtDsAejki0QnshrTwKgEQcM3Sy3cI7S6FTsi / 245 srUA \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								C4Zv1nAA + wyfA1VsQ7TEHfbyRchduDfAe5GKwSZqWpLM + q + xoL5x / IfaoboF9dobioX1gEHxhoN4dUN9hs6jjUBhvfMaFC6WDImeS02vt5kLgCNT + nAWX8F5vCUKXDv2ZOBnlPoZ9iw09n61wa274NuNXp2D42tU \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								B1xg4xStcrsOSGL4ilWuK3BmLjMl0WLK1RrKYnB87YLxCFSgp6TtYXDF9WU9xwo4XPyaknnQ1BnAyq / 3 bX / xfXrKCZ11Li2XOLusfACc0nUspiH6BpzhAoLdW9AENrdrSV19ZFW / Lh / pE9eAV3O + / ZJalW9At + KG \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ys0acLMhm6h9txBl4FsMH3iKlSwHBFH9GzPZC0lj3xJUYza0gfbwIVCWTn6jbJS + 6 ktfTFo93wb + P + Hyn5log9eSTdhe5TQNqP4TlYWG / IpQAo7d1MEY1t + VNBISfOq7zeDJboi5gs2D2DFQV7G8sEP2nQIW7bLJ \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								sX2ymfJTFVqyowu + bOee7AVkbMrtNgkzIaRajLVN / NdHOHefRuLj + R267ywLOYwZLU0DI2E5LxmLa2svwb8O + / lfi / Ya / kZMZXVZFKoqtfvSXy2uv / nBIstLN9i1i5b / mCxq / m7xl5hQMZlUhda / / gfTQr5T \ 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								""" ))) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-06 20:29:12 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  _main ( ) :  
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        main ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    except  FatalError  as  e : 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-06 15:17:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        print ( ' \n A fatal error occurred:  %s '  %  e ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-06 14:21:30 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        sys . exit ( 2 ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-06 20:29:12 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								if  __name__  ==  ' __main__ ' :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _main ( )