Source file: /~heha/hsn/esptool.zip/espcom.h

#pragma once
/* Packetized serial communication to Extensa ESP8266 and ESP32xx microcontrollers
 */
//#include <windows.h>	// HANDLE
#include "info.h"	// esp::Chipmagic
#include "intrin.h"	// autostring

struct ESP {
 enum{
  FLASH_BEGIN = 0x02,	// Kommandos
  FLASH_DATA  = 0x03,
  FLASH_END   = 0x04,
  MEM_BEGIN   = 0x05,
  MEM_END     = 0x06,
  MEM_DATA    = 0x07,
  SYNC        = 0x08,
  WRITE_REG   = 0x09,
  READ_REG    = 0x0A,
  SPI_SET_PARAMS = 0x0B,
  SPI_ATTACH = 0x0D,
  READ_FLASH_SLOW = 0x0E,	// ROM only, much slower than the stub flash read
  CHANGE_BAUDRATE = 0x0F,
  DEFL_ADD = 0x0E,	// Add to FLASH_BEGIN, FLASH_DATA, FLASH_END when compressed data are used
  SPI_FLASH_MD5 = 0x13,
// Commands supported by ESP32-S2 and later chips ROM bootloader only
  GET_SECURITY_INFO = 0x14,
// Commands supported by stub only
  ERASE_FLASH = 0xD0,
  ERASE_REGION = 0xD1,
  READ_FLASH = 0xD2,
  RUN_USER_CODE = 0xD3,
// Flash encryption encrypted data command
  FLASH_ENCRYPT_DATA = 0xD4,

// Maximum block sized for RAM and Flash writes, respectively.
  RAM_BLOCK   = 0x1800,	// 6 KiByte
  FLASH_BLOCK = 0x400,	// 1 KiByte
  ROM_BAUD    = 115200,	// Default baudrate.
// The ROM code auto-bauds, so we can use any baudrate.
  OTP_MAC    = 0x3ff00050,	// OTP ROM address (ESP8266)
  EFUSE_RDATA16 = 0x6001a000+4*16,	// eFuse data (ESP32) - funktioniert nicht!
 };
 HANDLE _port;
 esp::Chipmagic chip;
 const esp::Info1*info1;
 const esp::Info2*info2;
 byte lastError;
 byte statusbytes;
 bool stub_active;

// Konstruktor
 ESP(unsigned port);

/* https://docs.espressif.com/projects/esptool/en/latest/esp32/advanced-topics/serial-protocol.html
	The bootloader protocol uses SLIP packet framing for data transmissions in both directions.

	Each SLIP packet begins and ends with 0xC0.
	Within the packet, all occurrences of 0xC0 and 0xDB are replaced with 0xDB 0xDC and 0xDB 0xDD.
	The replacing is to be done after the checksum and lengths are calculated,
	so the packet length may be longer than the size field below.
 */
// Datenstruktur mit variabler Länge, für Senden und Empfang
 struct HDR{
  byte dir;	// 0 = Request, 1 = Response
  byte cmd;	// Kommando
  uint16 siz;	// Länge der nachfolgenden Daten
  uint32 val;	// Prüfsumme (nur für wenige Kommandos), Daten (nur bei READ_REG)
  byte*data() {return reinterpret_cast<byte*>(this+1);}		// Nachfolgend <siz> Byte Daten
  const byte*data() const {return reinterpret_cast<const byte*>(this+1);}
  inline void set(byte op, const void*_data=0, unsigned dlen=0, uint32 ck=0) {
   dir=0;cmd=op;siz=dlen;val=ck;memcpy(data(),_data,dlen);
  }
/* Checks status bytes of answer data */
  byte getStatus(const ESP*other) const;
 };

 bool setError(byte n) {
  if (!lastError) lastError=n;	// Folgefehler nicht aufzeichnen
  return false;			// immer 0 = false liefern
 }
private:
// Sowas ähnliches wie std::unique_ptr<HDR> mit den Mitteln von Uralt-C++
#if 1
 typedef autofreeptr<HDR> autoHDR;
#else
 class autoHDR{
  friend ESP;
  HDR*h;
  autoHDR(autoHDR&o) {h=o.h; o.h=0;}			// Raubkopier-Konstruktor
  void operator=(autoHDR&o) {free(h); h=o.h; o.h=0;}	// Raubkopier-Zuweisung
  ~autoHDR() {free(h);}					// Destruktor = Dreierregel
  operator const HDR*() const {return h;}
  const HDR*operator->() const {return h;}
  autoHDR(HDR*o):h(o) {}		// Pointer-Übernahme (muss von alloc/realloc kommen)
  void operator=(HDR*o) {free(h); h=o;}	// Pointer-Übernahme (darf auch nullptr sein)
 };
#endif

 int readByte();
public:
/*  Read bytes from the serial port while performing SLIP unescaping 
flags.0: (in) 0				(out) 1 = packet complete (return value == blen)
flags.1: (in) 1 = read until C0 appears	(out) 0 = C0 found, otherwise timeout
flags.2: (in) 1 = expect C0 before data	(out) 0 = C0 found, otherwise message read to end-C0 or blen
flags.3: (in) 1 = expect C0 after data	(out) 1 = No C0 after data (this is an error)
flags.4: (in) 0				(out) 1 = timeout
flags.5: (in) 0				(out) 1 = invalid SLIP escape
flags.6: (in) 1 = FatalExit on error	(out) 0 always
At return, flags==1 means success, and flags==0 means success but incomplete.
All other flag bits indicate error or warning conditions on return.
Both bit 1 and bit 2 may be set on invocation, expecting two C0 adjanced bytes.
 */
 unsigned readSlip(void*buf, unsigned blen,byte&flags);

 bool writeByte(byte c);

/*  Write bytes to the serial port while performing SLIP escaping  */
 bool writeSlip(const void*data, unsigned dlen);
 bool writeSlip(const HDR*packet);

/*  Receive a response to a command  */
 autoHDR readSlip(const HDR*sent,uint32 to_ms);

/*  Send a request and read the response: The response from ROM bootloader is somehow random for MD5 check */
 autoHDR command(byte op, const void*data=0, int dlen=0, uint32 chk=0, uint32 to_ms=50,bool check_status=true);

 void _cdecl ComError(const char*msg,...);

 bool sync(uint32 syncs);
 bool changeHostBaud(uint32 baud);	// nur PC
 bool tryBaud(uint32 baud,uint32 syncs);
 bool changeDeviceBaud(uint32 baud);	// beides
/*  Try connecting repeatedly until successful, or giving up  */
 bool connect(unsigned baud);


private:
 void setReadTimeout(DWORD ms) const;
 uint32 currentBaud;
 LastBaud lastB;
public:

/*  Read memory address in target  */
 uint32 read_reg(uint32 addr);

/*  Write to memory address in target  */
 void write_reg(uint32 addr, uint32 value, uint32 mask, uint32 delay_us=0);

 String<32>get_chip_description();

 String<100>features();

 int get_crystal_freq();

 struct BeginInfo{		// for mem_begin and flash_begin
  uint32 size,nblk,sblk,addr;	// overall size, number of blocks, blocksize, target address
 };
 struct DataInfo{
  uint32 sblk,iblk,rsv2,rsv3;
 };

/*  Start downloading an application image to RAM  */
 bool mem_begin(BeginInfo&);

/*  Send a block of an image to RAM  */
 bool mem_block(DataInfo&,const void*data);

/*  Leave download mode and run the application  */
 bool mem_finish(uint32 entrypoint=0);

/*  Start downloading to Flash (performs an erase)  */
 bool flash_begin(BeginInfo&,byte compress/*0 or DEFL_ADD*/);

/*  Write block to flash  */
 bool flash_block(DataInfo&,const void*data, byte compress/*0 or DEFL_ADD*/);

/*  (Leave flash mode and) run/reboot  */
 bool flash_finish(bool reboot,byte compress/*0 or DEFL_ADD*/);

/*  Run application code in flash  */
 void run(bool reboot=false) {
        // Fake flash begin immediately followed by flash end
  BeginInfo bi={0};
  flash_begin(bi,false);
  flash_finish(reboot,false);
 }

 struct MAC{
  uint64 mac;
  MAC(uint64 m):mac(m) {}
  String<18>toString();
 };
    /*  Read MAC from OTP ROM  */
 MAC read_mac(int=0);

/*  Read SPI flash manufacturer and device id  */
 uint32 flash_id();
private:
 bool chunk2ram(const Dumpfile&);
 static bool chunk2ram(void*cbd,const Dumpfile&);

public:
 bool load_stub();

/*  Read SPI flash  */
 bool flash2file(const char*fname);

    /*  Abuse the loader protocol to force flash to be left in write mode  */
 void flash_unlock_dio() {
        // Enable flash write mode
  BeginInfo bi={0};
  flash_begin(bi,false);
        // Reset the chip rather than call flash_finish(), which would have
        // write protected the chip again (why oh why does it do that?!)
  bi.addr=0x40100000;
  mem_begin(bi);
  mem_finish(0x40000080);
 }

/* Perform a chip erase of SPI flash. Stub is loaded */
 bool flash_erase();

 bool flash_verify(const char*fname);
      
    /* Set the flash params for ESP booter */
 bool flash_spi_param_set();
    
 static byte crc8(byte abyte);
    
 static byte crc8(const void*dlist,int len);
    
 static unsigned crc16(const void*data,int dlen);

 bool check_crc();

    /*  GPIO Change  */
 void HSPI_INIT();

private:
 bool write_flash_cb(const Dumpfile&);
 bool verboseDownloadCb(const Dumpfile&);
public:
 static bool write_flash_cb(void*cbd,const Dumpfile&);
 static bool verboseDownloadCb(void*cbd,const Dumpfile&);

 ~ESP();
};
Detected encoding: ANSI (CP1252)4
Wrong umlauts? - Assume file is ANSI (CP1252) encoded