Update IDF to abea9e4c0 (#2458)

* Update IDF to abea9e4c0

* Update esptool

* Enable PSRAM for PICO D4

* Enable APP_ROLLBACK_ENABLE
This commit is contained in:
Me No Dev 2019-02-14 16:49:30 +01:00 committed by GitHub
parent c0345eafbf
commit 010a7c60f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
101 changed files with 741 additions and 307 deletions

View File

@ -21,6 +21,9 @@
#include "esp_partition.h"
#include "esp_log.h"
#include "esp_timer.h"
#ifdef CONFIG_APP_ROLLBACK_ENABLE
#include "esp_ota_ops.h"
#endif //CONFIG_APP_ROLLBACK_ENABLE
#ifdef CONFIG_BT_ENABLED
#include "esp_bt.h"
#endif //CONFIG_BT_ENABLED
@ -145,6 +148,9 @@ void initVariant() {}
void init() __attribute__((weak));
void init() {}
bool verifyOta() __attribute__((weak));
bool verifyOta() { return true; }
#ifdef CONFIG_BT_ENABLED
//overwritten in esp32-hal-bt.c
bool btInUse() __attribute__((weak));
@ -153,6 +159,20 @@ bool btInUse(){ return false; }
void initArduino()
{
#ifdef CONFIG_APP_ROLLBACK_ENABLE
const esp_partition_t *running = esp_ota_get_running_partition();
esp_ota_img_states_t ota_state;
if (esp_ota_get_state_partition(running, &ota_state) == ESP_OK) {
if (ota_state == ESP_OTA_IMG_PENDING_VERIFY) {
if (verifyOta()) {
esp_ota_mark_app_valid_cancel_rollback();
} else {
log_e("OTA verification failed! Start rollback to the previous version ...");
esp_ota_mark_app_invalid_rollback_and_reboot();
}
}
}
#endif
//init proper ref tick value for PLL (uncomment if REF_TICK is different than 1MHz)
//ESP_REG(APB_CTRL_PLL_TICK_CONF_REG) = APB_CLK_FREQ / REF_CLK_FREQ - 1;
#ifdef F_CPU

View File

@ -19,7 +19,7 @@ bool psramInit(){
}
uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG);
uint32_t pkg_ver = chip_ver & 0x7;
if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5 || pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2 || pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4) {
if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5 || pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) {
spiramFailed = true;
log_w("PSRAM not supported!");
return false;

View File

@ -38,7 +38,7 @@
{
"packager": "esp32",
"name": "esptool_py",
"version": "2.6.0"
"version": "2.6.1"
},
{
"packager": "esp32",
@ -85,42 +85,42 @@
},
{
"name": "esptool_py",
"version": "2.6.0",
"version": "2.6.1",
"systems": [
{
"host": "i686-mingw32",
"url": "https://dl.espressif.com/dl/esptool-2.6.0-windows.zip",
"archiveFileName": "esptool-2.6.0-windows.zip",
"checksum": "SHA-256:a73f4cf68db240d7f1d250c5c7f2dfcb53c17a37483729f1bf71f8f43d79a799",
"size": "3421208"
"url": "https://dl.espressif.com/dl/esptool-2.6.1-windows.zip",
"archiveFileName": "esptool-2.6.1-windows.zip",
"checksum": "SHA-256:84cf0b369a7707fe566434faba148852fc464992111d5baa95b658b374802f96",
"size": "3422445"
},
{
"host": "x86_64-apple-darwin",
"url": "https://dl.espressif.com/dl/esptool-2.6.0-macos.tar.gz",
"archiveFileName": "esptool-2.6.0-macos.tar.gz",
"checksum": "SHA-256:0a881b91547c840fab8c72ae3d031069384278b8c2e5241647e8c8292c5e4a4b",
"size": "3835660"
"url": "https://dl.espressif.com/dl/esptool-2.6.1-macos.tar.gz",
"archiveFileName": "esptool-2.6.1-macos.tar.gz",
"checksum": "SHA-256:f4eb758a301d6902cc9dfcd49d36345d2f075ad123da7cf8132d15cfb7533457",
"size": "3837085"
},
{
"host": "x86_64-pc-linux-gnu",
"url": "https://dl.espressif.com/dl/esptool-2.6.0-linux.tar.gz",
"archiveFileName": "esptool-2.6.0-linux.tar.gz",
"checksum": "SHA-256:6d162f70f395ca31f5008829dd7e833e729f044a9c7355d5be8ce333a054e110",
"size": "43535"
"url": "https://dl.espressif.com/dl/esptool-2.6.1-linux.tar.gz",
"archiveFileName": "esptool-2.6.1-linux.tar.gz",
"checksum": "SHA-256:eaf82ff4070d9792f6a42ae1e485375de5a87bec59ef01dfb95de901519ec7fb",
"size": "44762"
},
{
"host": "i686-pc-linux-gnu",
"url": "https://dl.espressif.com/dl/esptool-2.6.0-linux.tar.gz",
"archiveFileName": "esptool-2.6.0-linux.tar.gz",
"checksum": "SHA-256:6d162f70f395ca31f5008829dd7e833e729f044a9c7355d5be8ce333a054e110",
"size": "43535"
"url": "https://dl.espressif.com/dl/esptool-2.6.1-linux.tar.gz",
"archiveFileName": "esptool-2.6.1-linux.tar.gz",
"checksum": "SHA-256:eaf82ff4070d9792f6a42ae1e485375de5a87bec59ef01dfb95de901519ec7fb",
"size": "44762"
},
{
"host": "arm-linux-gnueabihf",
"url": "https://dl.espressif.com/dl/esptool-2.6.0-linux.tar.gz",
"archiveFileName": "esptool-2.6.0-linux.tar.gz",
"checksum": "SHA-256:6d162f70f395ca31f5008829dd7e833e729f044a9c7355d5be8ce333a054e110",
"size": "43535"
"url": "https://dl.espressif.com/dl/esptool-2.6.1-linux.tar.gz",
"archiveFileName": "esptool-2.6.1-linux.tar.gz",
"checksum": "SHA-256:eaf82ff4070d9792f6a42ae1e485375de5a87bec59ef01dfb95de901519ec7fb",
"size": "44762"
}
]
},

View File

@ -32,9 +32,12 @@ import sys
import time
import zlib
import string
import serial.tools.list_ports as list_ports
try:
import serial
except ImportError:
print("Pyserial is not installed for %s. Check the README for installation instructions." % (sys.executable))
raise
# check 'serial' is 'pyserial' and not 'serial' https://github.com/espressif/esptool/issues/269
try:
@ -50,8 +53,14 @@ See https://github.com/espressif/esptool/issues/269#issuecomment-385298196 for d
except TypeError:
pass # __doc__ returns None for pyserial
try:
import serial.tools.list_ports as list_ports
except ImportError:
print("The installed version (%s) of pyserial appears to be too old for esptool.py (Python interpreter %s). "
"Check the README for installation instructions." % (sys.VERSION, sys.executable))
raise
__version__ = "2.6-beta1"
__version__ = "2.6"
MAX_UINT32 = 0xffffffff
MAX_UINT24 = 0xffffff
@ -221,7 +230,12 @@ class ESPLoader(object):
self._set_port_baudrate(baud)
self._trace_enabled = trace_enabled
# set write timeout, to prevent esptool blocked at write forever.
try:
self._port.write_timeout = DEFAULT_SERIAL_WRITE_TIMEOUT
except NotImplementedError:
# no write timeout for RFC2217 ports
# need to set the property back to None or it will continue to fail
self._port.write_timeout = None
def _set_port_baudrate(self, baud):
try:
@ -1274,19 +1288,26 @@ class ELFSection(ImageSegment):
class BaseFirmwareImage(object):
SEG_HEADER_LEN = 8
SHA256_DIGEST_LEN = 32
""" Base class with common firmware image functions """
def __init__(self):
self.segments = []
self.entrypoint = 0
self.elf_sha256 = None
self.elf_sha256_offset = 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))
if magic != expected_magic:
raise FatalError('Invalid firmware image magic=0x%x' % (magic))
return segments
def verify(self):
if len(self.segments) > 16:
raise FatalError('Invalid segment count %d (max 16). Usually this indicates a linker script problem.' % len(self.segments))
def load_segment(self, f, is_irom_segment=False):
""" Load the next segment from the image file """
file_offs = f.tell()
@ -1304,12 +1325,33 @@ class BaseFirmwareImage(object):
if offset > 0x40200000 or offset < 0x3ffe0000 or size > 65536:
print('WARNING: Suspicious segment 0x%x, length %d' % (offset, size))
def maybe_patch_segment_data(self, f, segment_data):
"""If SHA256 digest of the ELF file needs to be inserted into this segment, do so. Returns segment data."""
segment_len = len(segment_data)
file_pos = f.tell()
if self.elf_sha256_offset >= file_pos and self.elf_sha256_offset < file_pos + segment_len:
# SHA256 digest needs to be patched into this segment,
# calculate offset of the digest inside the segment.
patch_offset = self.elf_sha256_offset - file_pos
# Sanity checks
if patch_offset < self.SEG_HEADER_LEN or patch_offset + self.SHA256_DIGEST_LEN > segment_len:
raise FatalError('Can not place SHA256 digest on segment boundary' +
'(elf_sha256_offset=%d, file_pos=%d, segment_size=%d)' %
(self.elf_sha256_offset, file_pos, segment_len))
assert(len(self.elf_sha256) == self.SHA256_DIGEST_LEN)
# offset relative to the data part
patch_offset -= self.SEG_HEADER_LEN
segment_data = segment_data[0:patch_offset] + self.elf_sha256 + \
segment_data[patch_offset + self.SHA256_DIGEST_LEN:]
return segment_data
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)
segment_data = self.maybe_patch_segment_data(f, segment.data)
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)
return ESPLoader.checksum(segment_data, checksum)
def read_checksum(self, f):
""" Return ESPLoader checksum from end of just-read image """
@ -1374,6 +1416,8 @@ class ESP8266ROMFirmwareImage(BaseFirmwareImage):
self.load_segment(load_file)
self.checksum = self.read_checksum(load_file)
self.verify()
def default_output_name(self, input_file):
""" Derive a default output name from the ELF name. """
return input_file + '-'
@ -1442,6 +1486,8 @@ class ESP8266V2FirmwareImage(BaseFirmwareImage):
self.load_segment(load_file)
self.checksum = self.read_checksum(load_file)
self.verify()
def default_output_name(self, input_file):
""" Derive a default output name from the ELF name. """
irom_segment = self.get_irom_segment()
@ -1514,6 +1560,8 @@ class ESP32FirmwareImage(BaseFirmwareImage):
EXTENDED_HEADER_STRUCT_FMT = "B" * 16
IROM_ALIGN = 65536
def __init__(self, load_file=None):
super(ESP32FirmwareImage, self).__init__()
self.secure_pad = False
@ -1549,6 +1597,8 @@ class ESP32FirmwareImage(BaseFirmwareImage):
calc_digest.update(load_file.read(end - start))
self.calc_digest = calc_digest.digest() # TODO: decide what to do here?
self.verify()
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)
@ -1575,8 +1625,6 @@ class ESP32FirmwareImage(BaseFirmwareImage):
flash_segments = [copy.deepcopy(s) for s in sorted(self.segments, key=lambda s:s.addr) if self.is_flash_addr(s.addr)]
ram_segments = [copy.deepcopy(s) for s in sorted(self.segments, key=lambda s:s.addr) if not self.is_flash_addr(s.addr)]
IROM_ALIGN = 65536
# check for multiple ELF sections that are mapped 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
@ -1584,7 +1632,7 @@ class ESP32FirmwareImage(BaseFirmwareImage):
if len(flash_segments) > 0:
last_addr = flash_segments[0].addr
for segment in flash_segments[1:]:
if segment.addr // IROM_ALIGN == last_addr // IROM_ALIGN:
if segment.addr // self.IROM_ALIGN == last_addr // self.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))
@ -1596,15 +1644,15 @@ class ESP32FirmwareImage(BaseFirmwareImage):
#
# (this is because the segment's vaddr may not be IROM_ALIGNed, more likely is aligned
# IROM_ALIGN+0x18 to account for the binary file header
align_past = (segment.addr % IROM_ALIGN) - self.SEG_HEADER_LEN
pad_len = (IROM_ALIGN - (f.tell() % IROM_ALIGN)) + align_past
if pad_len == 0 or pad_len == IROM_ALIGN:
align_past = (segment.addr % self.IROM_ALIGN) - self.SEG_HEADER_LEN
pad_len = (self.IROM_ALIGN - (f.tell() % self.IROM_ALIGN)) + align_past
if pad_len == 0 or pad_len == self.IROM_ALIGN:
return 0 # already aligned
# subtract SEG_HEADER_LEN a second time, as the padding block has a header as well
pad_len -= self.SEG_HEADER_LEN
if pad_len < 0:
pad_len += IROM_ALIGN
pad_len += self.IROM_ALIGN
return pad_len
# try to fit each flash segment on a 64kB aligned boundary
@ -1623,8 +1671,8 @@ class ESP32FirmwareImage(BaseFirmwareImage):
total_segments += 1
else:
# write the flash segment
assert (f.tell() + 8) % IROM_ALIGN == segment.addr % IROM_ALIGN
checksum = self.save_segment(f, segment, checksum)
assert (f.tell() + 8) % self.IROM_ALIGN == segment.addr % self.IROM_ALIGN
checksum = self.save_flash_segment(f, segment, checksum)
flash_segments.pop(0)
total_segments += 1
@ -1638,12 +1686,12 @@ class ESP32FirmwareImage(BaseFirmwareImage):
# This ensures all mapped flash content will be verified.
if not self.append_digest:
raise FatalError("secure_pad only applies if a SHA-256 digest is also appended to the image")
align_past = (f.tell() + self.SEG_HEADER_LEN) % IROM_ALIGN
align_past = (f.tell() + self.SEG_HEADER_LEN) % self.IROM_ALIGN
# 16 byte aligned checksum (force the alignment to simplify calculations)
checksum_space = 16
# after checksum: SHA-256 digest + (to be added by signing process) version, signature + 12 trailing bytes due to alignment
space_after_checksum = 32 + 4 + 64 + 12
pad_len = (IROM_ALIGN - align_past - checksum_space - space_after_checksum) % IROM_ALIGN
pad_len = (self.IROM_ALIGN - align_past - checksum_space - space_after_checksum) % self.IROM_ALIGN
pad_segment = ImageSegment(0, b'\x00' * pad_len, f.tell())
checksum = self.save_segment(f, pad_segment, checksum)
@ -1654,7 +1702,7 @@ class ESP32FirmwareImage(BaseFirmwareImage):
image_length = f.tell()
if self.secure_pad:
assert ((image_length + space_after_checksum) % IROM_ALIGN) == 0
assert ((image_length + space_after_checksum) % self.IROM_ALIGN) == 0
# kinda hacky: go back to the initial header and write the new segment count
# that includes padding segments. This header is not checksummed
@ -1674,6 +1722,16 @@ class ESP32FirmwareImage(BaseFirmwareImage):
with open(filename, 'wb') as real_file:
real_file.write(f.getvalue())
def save_flash_segment(self, f, segment, checksum=None):
""" Save the next segment to the image file, return next checksum value if provided """
segment_end_pos = f.tell() + len(segment.data) + self.SEG_HEADER_LEN
segment_len_remainder = segment_end_pos % self.IROM_ALIGN
if segment_len_remainder < 0x24:
# Work around a bug in ESP-IDF 2nd stage bootloader, that it didn't map the
# last MMU page, if an IROM/DROM segment was < 0x24 bytes over the page boundary.
segment.data += b'\x00' * (0x24 - segment_len_remainder)
return self.save_segment(f, segment, checksum)
def load_extended_header(self, load_file):
def split_byte(n):
return (n & 0x0F, (n >> 4) & 0x0F)
@ -1790,9 +1848,16 @@ class ELFFile(object):
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]
if lma != 0 and size > 0]
self.sections = prog_sections
def sha256(self):
# return SHA256 hash of the input ELF file
sha256 = hashlib.sha256()
with open(self.name, 'rb') as f:
sha256.update(f.read())
return sha256.digest()
def slip_reader(port, trace_function):
"""Generator to read SLIP packets from a serial port.
@ -1991,7 +2056,7 @@ def write_mem(esp, args):
def dump_mem(esp, args):
f = open(args.filename, 'wb')
with open(args.filename, 'wb') as f:
for i in range(args.size // 4):
d = esp.read_reg(args.address + (i * 4))
f.write(struct.pack(b'<I', d))
@ -2060,6 +2125,9 @@ def write_flash(esp, args):
% (argfile.name, argfile.tell(), address, flash_end))
argfile.seek(0)
if args.erase_all:
erase_flash(esp, args)
for address, argfile in args.addr_filename:
if args.no_stub:
print('Erasing flash...')
@ -2087,7 +2155,7 @@ def write_flash(esp, args):
sys.stdout.flush()
block = image[0:esp.FLASH_WRITE_SIZE]
if args.compress:
esp.flash_defl_block(block, seq, timeout=DEFAULT_TIMEOUT * ratio)
esp.flash_defl_block(block, seq, timeout=DEFAULT_TIMEOUT * ratio * 2)
else:
# Pad the last block
block = block + b'\xff' * (esp.FLASH_WRITE_SIZE - len(block))
@ -2165,7 +2233,8 @@ def make_image(args):
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):
data = open(seg, 'rb').read()
with open(seg, 'rb') as f:
data = f.read()
image.segments.append(ImageSegment(addr, data))
image.entrypoint = args.entrypoint
image.save(args.output)
@ -2190,6 +2259,12 @@ def elf2image(args):
image.flash_size_freq = image.ROM_LOADER.FLASH_SIZES[args.flash_size]
image.flash_size_freq += {'40m':0, '26m':1, '20m':2, '80m': 0xf}[args.flash_freq]
if args.elf_sha256_offset:
image.elf_sha256 = e.sha256()
image.elf_sha256_offset = args.elf_sha256_offset
image.verify()
if args.output is None:
args.output = image.default_output_name(args.input)
image.save(args.output)
@ -2254,7 +2329,8 @@ def read_flash(esp, args):
t = time.time() - t
print('\rRead %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)
with open(args.filename, 'wb') as f:
f.write(data)
def verify_flash(esp, args):
@ -2316,7 +2392,13 @@ def version(args):
#
def main():
def main(custom_commandline=None):
"""
Main function for esptool
custom_commandline - Optional override for default arguments parsing (that uses sys.argv), can be a list of custom arguments
as strings.
"""
parser = argparse.ArgumentParser(description='esptool.py v%s - ESP8266 ROM Bootloader Utility' % __version__, prog='esptool')
parser.add_argument('--chip', '-c',
@ -2413,15 +2495,18 @@ def main():
default=os.environ.get('ESPTOOL_FS', 'detect' if auto_detect else '1MB'))
add_spi_connection_arg(parent)
parser_write_flash = subparsers.add_parser(
'write_flash',
help='Write a binary blob to flash')
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)
parser_write_flash.add_argument('--erase-all', '-e',
help='Erase all regions of flash (not just write areas) before programming',
action="store_true")
add_spi_flash_subparsers(parser_write_flash, is_elf2image=False)
parser_write_flash.add_argument('--no-progress', '-p', help='Suppress progress output', action="store_true")
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")
@ -2450,6 +2535,8 @@ def main():
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')
parser_elf2image.add_argument('--secure-pad', action='store_true', help='Pad image so once signed it will end on a 64KB boundary. For ESP32 images only.')
parser_elf2image.add_argument('--elf-sha256-offset', help='If set, insert SHA256 hash (32 bytes) of the input ELF file at specified offset in the binary.',
type=arg_auto_int, default=None)
add_spi_flash_subparsers(parser_elf2image, is_elf2image=True)
@ -2521,7 +2608,7 @@ def main():
expand_file_arguments()
args = parser.parse_args()
args = parser.parse_args(custom_commandline)
print('esptool.py v%s' % __version__)
@ -2607,7 +2694,14 @@ def main():
detect_flash_size(esp, args)
esp.flash_set_parameters(flash_size_bytes(args.flash_size))
try:
operation_func(esp, args)
finally:
try: # Clean up AddrFilenamePairAction files
for address, argfile in args.addr_filename:
argfile.close()
except AttributeError:
pass
# Handle post-operation behaviour (reset or other)
if operation_func == load_ram:
@ -2752,73 +2846,73 @@ class AddrFilenamePairAction(argparse.Action):
# Binary stub code (see flasher_stub dir for source & details)
ESP8266ROM.STUB_CODE = eval(zlib.decompress(base64.b64decode(b"""
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\
nORxF3HqX/8XohBRvg==\
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\
""")))
ESP32ROM.STUB_CODE = eval(zlib.decompress(base64.b64decode(b"""
eNqNWnt31LgV/yqOYfJaskeyPbZEz0IS6BBg2xIoIdDp2bFlOyFbcoDOQjgL/ezVfVnyzNDtHxNkPa/u43cf4vedZXez3LmbNDvzm94k/k9xH1oKW+XR/Eb5ptX+s/W/fn7jVEKdxsyX/i+01O2zExrFmfX/M1PD\

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -76,6 +76,7 @@
#define CONFIG_CONSOLE_UART_BAUDRATE 115200
#define CONFIG_SPIRAM_SUPPORT 1
#define CONFIG_LWIP_MAX_SOCKETS 10
#define CONFIG_APP_ROLLBACK_ENABLE 1
#define CONFIG_LWIP_NETIF_LOOPBACK 1
#define CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT "pthread"
#define CONFIG_EMAC_TASK_PRIORITY 20
@ -198,6 +199,7 @@
#define CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN 0
#define CONFIG_LWIP_DHCP_RESTORE_LAST_IP 1
#define CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN 2
#define CONFIG_PICO_PSRAM_CS_IO 10
#define CONFIG_EMAC_TASK_STACK_SIZE 3072
#define CONFIG_MB_QUEUE_LENGTH 20
#define CONFIG_SW_COEXIST_PREFERENCE_VALUE 0
@ -334,7 +336,6 @@
#define CONFIG_MONITOR_BAUD_OTHER_VAL 115200
#define CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF 1
#define CONFIG_ESPTOOLPY_PORT "/dev/cu.usbserial-DO00EAB0"
#define CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS 1
#define CONFIG_TASK_WDT_PANIC 1
#define CONFIG_UNITY_ENABLE_DOUBLE 1
#define CONFIG_BLUEDROID_PINNED_TO_CORE 0

View File

@ -260,10 +260,25 @@ void esp_tls_conn_delete(esp_tls_t *tls);
size_t esp_tls_get_bytes_avail(esp_tls_t *tls);
/**
* @brief Create a global CA store with the buffer provided in cfg.
* @brief Create a global CA store, initially empty.
*
* This function should be called if the application wants to use the same CA store for
* multiple connections. The application must call this function before calling esp_tls_conn_new().
* This function should be called if the application wants to use the same CA store for multiple connections.
* This function initialises the global CA store which can be then set by calling esp_tls_set_global_ca_store().
* To be effective, this function must be called before any call to esp_tls_set_global_ca_store().
*
* @return
* - ESP_OK if creating global CA store was successful.
* - ESP_ERR_NO_MEM if an error occured when allocating the mbedTLS resources.
*/
esp_err_t esp_tls_init_global_ca_store();
/**
* @brief Set the global CA store with the buffer provided in pem format.
*
* This function should be called if the application wants to set the global CA store for
* multiple connections i.e. to add the certificates in the provided buffer to the certificate chain.
* This function implicitly calls esp_tls_init_global_ca_store() if it has not already been called.
* The application must call this function before calling esp_tls_conn_new().
*
* @param[in] cacert_pem_buf Buffer which has certificates in pem format. This buffer
* is used for creating a global CA store, which can be used
@ -271,7 +286,7 @@ size_t esp_tls_get_bytes_avail(esp_tls_t *tls);
* @param[in] cacert_pem_bytes Length of the buffer.
*
* @return
* - ESP_OK if creating global CA store was successful.
* - ESP_OK if adding certificates was successful.
* - Other if an error occured or an action must be taken by the calling process.
*/
esp_err_t esp_tls_set_global_ca_store(const unsigned char *cacert_pem_buf, const unsigned int cacert_pem_bytes);

View File

@ -94,7 +94,7 @@ typedef struct {
int pin_href; /*!< GPIO pin for camera HREF line */
int pin_pclk; /*!< GPIO pin for camera PCLK line */
int xclk_freq_hz; /*!< Frequency of XCLK signal, in Hz. Either 10KHz or 20KHz */
int xclk_freq_hz; /*!< Frequency of XCLK signal, in Hz. Either 20KHz or 10KHz for OV2640 double FPS (Experimental) */
ledc_timer_t ledc_timer; /*!< LEDC timer to be used for generating XCLK */
ledc_channel_t ledc_channel; /*!< LEDC channel to be used for generating XCLK */

View File

@ -86,6 +86,7 @@ typedef struct _sensor {
uint8_t slv_addr; // Sensor I2C slave address.
pixformat_t pixformat;
camera_status_t status;
int xclk_freq_hz;
// Sensor function pointers
int (*init_status) (sensor_t *sensor);

View File

@ -1044,9 +1044,10 @@ esp_err_t esp_mesh_set_vote_percentage(float percentage);
float esp_mesh_get_vote_percentage(void);
/**
* @brief Set mesh softAP associate expired time
* @brief Set mesh softAP associate expired time (default:10 seconds)
* - If mesh softAP hasn't received any data from an associated child within this time,
* mesh softAP will take this child inactive and disassociate it.
* - If mesh softAP is encrypted, this value should be set a greater value, such as 30 seconds.
*
* @param[in] seconds the expired time
*
@ -1227,7 +1228,7 @@ esp_err_t esp_mesh_get_group_list(mesh_addr_t *addr, int num);
bool esp_mesh_is_my_group(const mesh_addr_t *addr);
/**
* @brief Set mesh network capacity
* @brief Set mesh network capacity (max:1000, default:300)
*
* @attention This API shall be called before mesh is started.
*

View File

@ -22,8 +22,9 @@
#include "esp_err.h"
typedef enum {
ESP_SPIRAM_SIZE_32MBITS = 0, /*!< SPI RAM size is 32 MBits */
ESP_SPIRAM_SIZE_64MBITS = 1, /*!< SPI RAM size is 64 MBits */
ESP_SPIRAM_SIZE_16MBITS = 0, /*!< SPI RAM size is 16 MBits */
ESP_SPIRAM_SIZE_32MBITS = 1, /*!< SPI RAM size is 32 MBits */
ESP_SPIRAM_SIZE_64MBITS = 2, /*!< SPI RAM size is 64 MBits */
ESP_SPIRAM_SIZE_INVALID, /*!< SPI RAM size is invalid */
} esp_spiram_size_t;

View File

@ -405,7 +405,7 @@ typedef struct {
typedef struct {
wifi_pkt_rx_ctrl_t rx_ctrl;/**< received packet radio metadata header of the CSI data */
uint8_t mac[6]; /**< source MAC address of the CSI data */
bool last_word_invalid; /**< last four bytes of the CSI data is invalid or not */
bool first_word_invalid; /**< first four bytes of the CSI data is invalid or not */
int8_t *buf; /**< buffer of CSI data */
uint16_t len; /**< length of CSI data */
} wifi_csi_info_t;

View File

@ -166,6 +166,8 @@ void esp_sha_unlock_engine(esp_sha_type sha_type);
* while it is in use by the SHA engine. Caller should use esp_sha_wait_idle()
* to ensure the SHA engine is not reading from the memory block in hardware.
*
* @note This function enters a critical section. Do not block while holding this lock.
*
* @note You do not need to lock the memory block before calling esp_sha_block() or esp_sha_read_digest_state(), these functions handle memory block locking internally.
*
* Call esp_sha_unlock_memory_block() when done.
@ -177,6 +179,8 @@ void esp_sha_lock_memory_block(void);
*
* Caller should have already locked a SHA engine before calling this function.
*
* This function releases the critical section entered by esp_sha_lock_memory_block().
*
* Call following esp_sha_lock_memory_block().
*/
void esp_sha_unlock_memory_block(void);

View File

@ -105,7 +105,9 @@ typedef struct {
esp_http_client_auth_type_t auth_type; /*!< Http authentication type, see `esp_http_client_auth_type_t` */
const char *path; /*!< HTTP Path, if not set, default is `/` */
const char *query; /*!< HTTP query */
const char *cert_pem; /*!< SSL Certification, PEM format as string, if the client requires to verify server */
const char *cert_pem; /*!< SSL server certification, PEM format as string, if the client requires to verify server */
const char *client_cert_pem; /*!< SSL client certification, PEM format as string, if the server requires to verify client */
const char *client_key_pem; /*!< SSL client key, PEM format as string, if the server requires to verify client */
esp_http_client_method_t method; /*!< HTTP Method */
int timeout_ms; /*!< Network timeout in milliseconds */
bool disable_auto_redirect; /*!< Disable HTTP automatic redirects */

View File

@ -49,6 +49,7 @@ initializer that should be kept in sync
.global_transport_ctx_free_fn = NULL, \
.open_fn = NULL, \
.close_fn = NULL, \
.uri_match_fn = NULL \
}
#define ESP_ERR_HTTPD_BASE (0x8000) /*!< Starting number of HTTPD error codes */
@ -61,6 +62,10 @@ initializer that should be kept in sync
#define ESP_ERR_HTTPD_ALLOC_MEM (ESP_ERR_HTTPD_BASE + 7) /*!< Failed to dynamically allocate memory for resource */
#define ESP_ERR_HTTPD_TASK (ESP_ERR_HTTPD_BASE + 8) /*!< Failed to launch server task/thread */
/* Symbol to be used as length parameter in httpd_resp_send APIs
* for setting buffer length to string length */
#define HTTPD_RESP_USE_STRLEN -1
/* ************** Group: Initialization ************** */
/** @name Initialization
* APIs related to the Initialization of the web server
@ -82,7 +87,7 @@ typedef enum http_method httpd_method_t;
/**
* @brief Prototype for freeing context data (if any)
* @param[in] ctx : object to free
* @param[in] ctx object to free
*/
typedef void (*httpd_free_ctx_fn_t)(void *ctx);
@ -92,8 +97,8 @@ typedef void (*httpd_free_ctx_fn_t)(void *ctx);
* Called immediately after the socket was opened to set up the send/recv functions and
* other parameters of the socket.
*
* @param[in] hd : server instance
* @param[in] sockfd : session socket file descriptor
* @param[in] hd server instance
* @param[in] sockfd session socket file descriptor
* @return status
*/
typedef esp_err_t (*httpd_open_func_t)(httpd_handle_t hd, int sockfd);
@ -104,11 +109,26 @@ typedef esp_err_t (*httpd_open_func_t)(httpd_handle_t hd, int sockfd);
* @note It's possible that the socket descriptor is invalid at this point, the function
* is called for all terminated sessions. Ensure proper handling of return codes.
*
* @param[in] hd : server instance
* @param[in] sockfd : session socket file descriptor
* @param[in] hd server instance
* @param[in] sockfd session socket file descriptor
*/
typedef void (*httpd_close_func_t)(httpd_handle_t hd, int sockfd);
/**
* @brief Function prototype for URI matching.
*
* @param[in] reference_uri URI/template with respect to which the other URI is matched
* @param[in] uri_to_match URI/template being matched to the reference URI/template
* @param[in] match_upto For specifying the actual length of `uri_to_match` up to
* which the matching algorithm is to be applied (The maximum
* value is `strlen(uri_to_match)`, independent of the length
* of `reference_uri`)
* @return true on match
*/
typedef bool (*httpd_uri_match_func_t)(const char *reference_uri,
const char *uri_to_match,
size_t match_upto);
/**
* @brief HTTP Server Configuration Structure
*
@ -195,6 +215,24 @@ typedef struct httpd_config {
* was closed by the network stack - that is, the file descriptor may not be valid anymore.
*/
httpd_close_func_t close_fn;
/**
* URI matcher function.
*
* Called when searching for a matching URI:
* 1) whose request handler is to be executed right
* after an HTTP request is successfully parsed
* 2) in order to prevent duplication while registering
* a new URI handler using `httpd_register_uri_handler()`
*
* Available options are:
* 1) NULL : Internally do basic matching using `strncmp()`
* 2) `httpd_uri_match_wildcard()` : URI wildcard matcher
*
* Users can implement their own matching functions (See description
* of the `httpd_uri_match_func_t` function prototype)
*/
httpd_uri_match_func_t uri_match_fn;
} httpd_config_t;
/**
@ -227,8 +265,8 @@ typedef struct httpd_config {
*
* @endcode
*
* @param[in] config : Configuration for new instance of the server
* @param[out] handle : Handle to newly created instance of the server. NULL on error
* @param[in] config Configuration for new instance of the server
* @param[out] handle Handle to newly created instance of the server. NULL on error
* @return
* - ESP_OK : Instance created successfully
* - ESP_ERR_INVALID_ARG : Null argument(s)
@ -451,11 +489,11 @@ esp_err_t httpd_unregister_uri(httpd_handle_t handle, const char* uri);
* HTTPD_SOCK_ERR_ codes, which will eventually be conveyed as
* return value of httpd_send() function
*
* @param[in] hd : server instance
* @param[in] sockfd : session socket file descriptor
* @param[in] buf : buffer with bytes to send
* @param[in] buf_len : data size
* @param[in] flags : flags for the send() function
* @param[in] hd server instance
* @param[in] sockfd session socket file descriptor
* @param[in] buf buffer with bytes to send
* @param[in] buf_len data size
* @param[in] flags flags for the send() function
* @return
* - Bytes : The number of bytes sent successfully
* - HTTPD_SOCK_ERR_INVALID : Invalid arguments
@ -472,11 +510,11 @@ typedef int (*httpd_send_func_t)(httpd_handle_t hd, int sockfd, const char *buf,
* HTTPD_SOCK_ERR_ codes, which will eventually be conveyed as
* return value of httpd_req_recv() function
*
* @param[in] hd : server instance
* @param[in] sockfd : session socket file descriptor
* @param[in] buf : buffer with bytes to send
* @param[in] buf_len : data size
* @param[in] flags : flags for the send() function
* @param[in] hd server instance
* @param[in] sockfd session socket file descriptor
* @param[in] buf buffer with bytes to send
* @param[in] buf_len data size
* @param[in] flags flags for the send() function
* @return
* - Bytes : The number of bytes received successfully
* - 0 : Buffer length parameter is zero / connection closed by peer
@ -494,8 +532,8 @@ typedef int (*httpd_recv_func_t)(httpd_handle_t hd, int sockfd, char *buf, size_
* HTTPD_SOCK_ERR_ codes, which will be handled accordingly in
* the server task.
*
* @param[in] hd : server instance
* @param[in] sockfd : session socket file descriptor
* @param[in] hd server instance
* @param[in] sockfd session socket file descriptor
* @return
* - Bytes : The number of bytes waiting to be received
* - HTTPD_SOCK_ERR_INVALID : Invalid arguments
@ -744,6 +782,30 @@ esp_err_t httpd_req_get_url_query_str(httpd_req_t *r, char *buf, size_t buf_len)
*/
esp_err_t httpd_query_key_value(const char *qry, const char *key, char *val, size_t val_size);
/**
* @brief Test if a URI matches the given wildcard template.
*
* Template may end with "?" to make the previous character optional (typically a slash),
* "*" for a wildcard match, and "?*" to make the previous character optional, and if present,
* allow anything to follow.
*
* Example:
* - * matches everything
* - /foo/? matches /foo and /foo/
* - /foo/\* (sans the backslash) matches /foo/ and /foo/bar, but not /foo or /fo
* - /foo/?* or /foo/\*? (sans the backslash) matches /foo/, /foo/bar, and also /foo, but not /foox or /fo
*
* The special characters "?" and "*" anywhere else in the template will be taken literally.
*
* @param[in] uri_template URI template (pattern)
* @param[in] uri_to_match URI to be matched
* @param[in] match_upto how many characters of the URI buffer to test
* (there may be trailing query string etc.)
*
* @return true if a match was found
*/
bool httpd_uri_match_wildcard(const char *uri_template, const char *uri_to_match, size_t match_upto);
/**
* @brief API to send a complete HTTP response.
*
@ -772,7 +834,7 @@ esp_err_t httpd_query_key_value(const char *qry, const char *key, char *val, siz
*
* @param[in] r The request being responded to
* @param[in] buf Buffer from where the content is to be fetched
* @param[in] buf_len Length of the buffer, -1 to use strlen()
* @param[in] buf_len Length of the buffer, HTTPD_RESP_USE_STRLEN to use strlen()
*
* @return
* - ESP_OK : On successfully sending the response packet
@ -811,7 +873,7 @@ esp_err_t httpd_resp_send(httpd_req_t *r, const char *buf, ssize_t buf_len);
*
* @param[in] r The request being responded to
* @param[in] buf Pointer to a buffer that stores the data
* @param[in] buf_len Length of the data from the buffer that should be sent out, -1 to use strlen()
* @param[in] buf_len Length of the buffer, HTTPD_RESP_USE_STRLEN to use strlen()
*
* @return
* - ESP_OK : On successfully sending the response packet chunk
@ -822,6 +884,48 @@ esp_err_t httpd_resp_send(httpd_req_t *r, const char *buf, ssize_t buf_len);
*/
esp_err_t httpd_resp_send_chunk(httpd_req_t *r, const char *buf, ssize_t buf_len);
/**
* @brief API to send a complete string as HTTP response.
*
* This API simply calls http_resp_send with buffer length
* set to string length assuming the buffer contains a null
* terminated string
*
* @param[in] r The request being responded to
* @param[in] str String to be sent as response body
*
* @return
* - ESP_OK : On successfully sending the response packet
* - ESP_ERR_INVALID_ARG : Null request pointer
* - ESP_ERR_HTTPD_RESP_HDR : Essential headers are too large for internal buffer
* - ESP_ERR_HTTPD_RESP_SEND : Error in raw send
* - ESP_ERR_HTTPD_INVALID_REQ : Invalid request
*/
inline esp_err_t httpd_resp_sendstr(httpd_req_t *r, const char *str) {
return httpd_resp_send(r, str, (str == NULL) ? 0 : strlen(str));
}
/**
* @brief API to send a string as an HTTP response chunk.
*
* This API simply calls http_resp_send_chunk with buffer length
* set to string length assuming the buffer contains a null
* terminated string
*
* @param[in] r The request being responded to
* @param[in] str String to be sent as response body (NULL to finish response packet)
*
* @return
* - ESP_OK : On successfully sending the response packet
* - ESP_ERR_INVALID_ARG : Null request pointer
* - ESP_ERR_HTTPD_RESP_HDR : Essential headers are too large for internal buffer
* - ESP_ERR_HTTPD_RESP_SEND : Error in raw send
* - ESP_ERR_HTTPD_INVALID_REQ : Invalid request
*/
inline esp_err_t httpd_resp_sendstr_chunk(httpd_req_t *r, const char *str) {
return httpd_resp_send_chunk(r, str, (str == NULL) ? 0 : strlen(str));
}
/* Some commonly used status codes */
#define HTTPD_200 "200 OK" /*!< HTTP Response 200 */
#define HTTPD_204 "204 No Content" /*!< HTTP Response 204 */

View File

@ -33,6 +33,7 @@ extern "C" {
* @return
* - ESP_OK: OTA data updated, next reboot will use specified partition.
* - ESP_FAIL: For generic failure.
* - ESP_ERR_INVALID_ARG: Invalid argument
* - ESP_ERR_OTA_VALIDATE_FAILED: Invalid app image
* - ESP_ERR_NO_MEM: Cannot allocate memory for OTA operation.
* - ESP_ERR_FLASH_OP_TIMEOUT or ESP_ERR_FLASH_OP_FAIL: Flash write failed.

View File

@ -15,68 +15,88 @@
#ifndef __ESP_ETH_H__
#define __ESP_ETH_H__
#include <stdbool.h>
#include <stdint.h>
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "esp_types.h"
#include "esp_err.h"
/**
* @brief Ethernet interface mode
*
*/
typedef enum {
ETH_MODE_RMII = 0,
ETH_MODE_MII,
ETH_MODE_RMII = 0, /*!< RMII mode */
ETH_MODE_MII, /*!< MII mode */
} eth_mode_t;
/**
* @brief Ethernet clock mode
*
*/
typedef enum {
ETH_CLOCK_GPIO0_IN = 0,
ETH_CLOCK_GPIO16_OUT = 2,
ETH_CLOCK_GPIO17_OUT = 3
ETH_CLOCK_GPIO0_IN = 0, /*!< RMII clock input to GPIO0 */
ETH_CLOCK_GPIO0_OUT = 1, /*!< RMII clock output from GPIO0 */
ETH_CLOCK_GPIO16_OUT = 2, /*!< RMII clock output from GPIO16 */
ETH_CLOCK_GPIO17_OUT = 3 /*!< RMII clock output from GPIO17 */
} eth_clock_mode_t;
/**
* @brief Ethernet Speed
*
*/
typedef enum {
ETH_SPEED_MODE_10M = 0,
ETH_SPEED_MODE_100M,
ETH_SPEED_MODE_10M = 0, /*!< Ethernet speed: 10Mbps */
ETH_SPEED_MODE_100M, /*!< Ethernet speed: 100Mbps */
} eth_speed_mode_t;
/**
* @brief Ethernet Duplex
*
*/
typedef enum {
ETH_MODE_HALFDUPLEX = 0,
ETH_MODE_FULLDUPLEX,
ETH_MODE_HALFDUPLEX = 0, /*!< Ethernet half duplex */
ETH_MODE_FULLDUPLEX, /*!< Ethernet full duplex */
} eth_duplex_mode_t;
/**
* @brief Ethernet PHY address
*
*/
typedef enum {
PHY0 = 0,
PHY1,
PHY2,
PHY3,
PHY4,
PHY5,
PHY6,
PHY7,
PHY8,
PHY9,
PHY10,
PHY11,
PHY12,
PHY13,
PHY14,
PHY15,
PHY16,
PHY17,
PHY18,
PHY19,
PHY20,
PHY21,
PHY22,
PHY23,
PHY24,
PHY25,
PHY26,
PHY27,
PHY28,
PHY29,
PHY30,
PHY31,
PHY0 = 0, /*!< PHY address 0 */
PHY1, /*!< PHY address 1 */
PHY2, /*!< PHY address 2 */
PHY3, /*!< PHY address 3 */
PHY4, /*!< PHY address 4 */
PHY5, /*!< PHY address 5 */
PHY6, /*!< PHY address 6 */
PHY7, /*!< PHY address 7 */
PHY8, /*!< PHY address 8 */
PHY9, /*!< PHY address 9 */
PHY10, /*!< PHY address 10 */
PHY11, /*!< PHY address 11 */
PHY12, /*!< PHY address 12 */
PHY13, /*!< PHY address 13 */
PHY14, /*!< PHY address 14 */
PHY15, /*!< PHY address 15 */
PHY16, /*!< PHY address 16 */
PHY17, /*!< PHY address 17 */
PHY18, /*!< PHY address 18 */
PHY19, /*!< PHY address 19 */
PHY20, /*!< PHY address 20 */
PHY21, /*!< PHY address 21 */
PHY22, /*!< PHY address 22 */
PHY23, /*!< PHY address 23 */
PHY24, /*!< PHY address 24 */
PHY25, /*!< PHY address 25 */
PHY26, /*!< PHY address 26 */
PHY27, /*!< PHY address 27 */
PHY28, /*!< PHY address 28 */
PHY29, /*!< PHY address 29 */
PHY30, /*!< PHY address 30 */
PHY31 /*!< PHY address 31 */
} eth_phy_base_t;
typedef bool (*eth_phy_check_link_func)(void);
@ -94,9 +114,9 @@ typedef void (*eth_phy_power_enable_func)(bool enable);
*
*/
typedef struct {
eth_phy_base_t phy_addr; /*!< phy base addr (0~31) */
eth_mode_t mac_mode; /*!< mac mode only support RMII now */
eth_clock_mode_t clock_mode; /*!< external/internal clock mode selecton */
eth_phy_base_t phy_addr; /*!< PHY address (0~31) */
eth_mode_t mac_mode; /*!< MAC mode: only support RMII now */
eth_clock_mode_t clock_mode; /*!< external/internal clock mode selection */
eth_tcpip_input_func tcpip_input; /*!< tcpip input func */
eth_phy_func phy_init; /*!< phy init func */
eth_phy_check_link_func phy_check_link; /*!< phy check link func */

View File

@ -20,38 +20,55 @@ extern "C" {
#include "esp_eth.h"
/** Common PHY-management functions.
These are not enough to drive any particular Ethernet PHY, but they provide a common configuration structure and
management functions.
/**
* @brief Common PHY-management functions.
*
* @note These are not enough to drive any particular Ethernet PHY.
* They provide a common configuration structure and management functions.
*
*/
/** Configure fixed pins for RMII data interface.
This configures GPIOs 0, 19, 22, 25, 26, 27 for use with RMII
data interface. These pins cannot be changed, and must be wired to
ethernet functions.
This is not sufficient to fully configure the Ethernet PHY,
MDIO configuration interface pins (such as SMI MDC, MDO, MDI)
must also be configured correctly in the GPIO matrix.
/**
* @brief Configure fixed pins for RMII data interface.
*
* @note This configures GPIOs 0, 19, 22, 25, 26, 27 for use with RMII data interface.
* These pins cannot be changed, and must be wired to ethernet functions.
* This is not sufficient to fully configure the Ethernet PHY.
* MDIO configuration interface pins (such as SMI MDC, MDO, MDI) must also be configured correctly in the GPIO matrix.
*
*/
void phy_rmii_configure_data_interface_pins(void);
/** Configure variable pins for SMI (MDIO) ethernet functions.
Calling this function along with mii_configure_default_pins() will
fully configure the GPIOs for the ethernet PHY.
/**
* @brief Configure variable pins for SMI ethernet functions.
*
* @param mdc_gpio MDC GPIO Pin number
* @param mdio_gpio MDIO GPIO Pin number
*
* @note Calling this function along with mii_configure_default_pins() will fully configure the GPIOs for the ethernet PHY.
*/
void phy_rmii_smi_configure_pins(uint8_t mdc_gpio, uint8_t mdio_gpio);
/** Enable flow control in standard PHY MII register.
/**
* @brief Enable flow control in standard PHY MII register.
*
*/
void phy_mii_enable_flow_ctrl(void);
/**
* @brief Check Ethernet link status via MII interface
*
* @return true Link is on
* @return false Link is off
*/
bool phy_mii_check_link_status(void);
/**
* @brief Check pause frame ability of partner via MII interface
*
* @return true Partner is able to process pause frame
* @return false Partner can not process pause frame
*/
bool phy_mii_get_partner_pause_enable(void);
#ifdef __cplusplus

View File

@ -0,0 +1,75 @@
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "phy.h"
/**
* @brief Dump IP101 PHY SMI configuration registers
*
*/
void phy_ip101_dump_registers();
/**
* @brief Default IP101 phy_check_init function
*
*/
void phy_ip101_check_phy_init(void);
/**
* @brief Default IP101 phy_get_speed_mode function
*
* @return eth_speed_mode_t Ethernet speed mode
*/
eth_speed_mode_t phy_ip101_get_speed_mode(void);
/**
* @brief Default IP101 phy_get_duplex_mode function
*
* @return eth_duplex_mode_t Ethernet duplex mode
*/
eth_duplex_mode_t phy_ip101_get_duplex_mode(void);
/**
* @brief Default IP101 phy_power_enable function
*
*/
void phy_ip101_power_enable(bool);
/**
* @brief Default IP101 phy_init function
*
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
esp_err_t phy_ip101_init(void);
/**
* @brief Default IP101 PHY configuration
*
* @note This configuration is not suitable for use as-is,
* it will need to be modified for your particular PHY hardware setup.
*
*/
extern const eth_config_t phy_ip101_default_ethernet_config;
#ifdef __cplusplus
}
#endif

View File

@ -20,45 +20,53 @@ extern "C" {
#include "phy.h"
/** @brief Dump all LAN8720 PHY SMI configuration registers
/**
* @brief Dump LAN8720 PHY SMI configuration registers
*
* @note These registers are dumped at 'debug' level, so output
* may not be visible depending on default log levels.
*/
void phy_lan8720_dump_registers();
/** @brief Default LAN8720 phy_check_init function.
/**
* @brief Default LAN8720 phy_check_init function
*
*/
void phy_lan8720_check_phy_init(void);
/** @brief Default LAN8720 phy_get_speed_mode function.
/**
* @brief Default LAN8720 phy_get_speed_mode function
*
* @return eth_speed_mode_t Ethernet speed mode
*/
eth_speed_mode_t phy_lan8720_get_speed_mode(void);
/** @brief Default LAN8720 phy_get_duplex_mode function.
/**
* @brief Default LAN8720 phy_get_duplex_mode function
*
* @return eth_duplex_mode_t Ethernet duplex mode
*/
eth_duplex_mode_t phy_lan8720_get_duplex_mode(void);
/** @brief Default LAN8720 phy_power_enable function.
/**
* @brief Default LAN8720 phy_power_enable function
*
* @note This function may need to be replaced with a custom function
* if the PHY has a GPIO to enable power or start a clock.
*
* Consult the ethernet example to see how this is done.
*/
void phy_lan8720_power_enable(bool);
/** @brief Default LAN8720 phy_init function.
/**
* @brief Default LAN8720 phy_init function
*
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
esp_err_t phy_lan8720_init(void);
/** @brief Default LAN8720 PHY configuration
/**
* @brief Default LAN8720 PHY configuration
*
* This configuration is not suitable for use as-is, it will need
* to be modified for your particular PHY hardware setup.
* @note This configuration is not suitable for use as-is,
* it will need to be modified for your particular PHY hardware setup.
*
* Consult the Ethernet example to see how this is done.
*/
extern const eth_config_t phy_lan8720_default_ethernet_config;

View File

@ -18,8 +18,9 @@
extern "C" {
#endif
/* This header contains register/bit masks for the standard
PHY MII registers that should be supported by all PHY models.
/**
* @brief This header contains register/bit masks for the standard PHY MII registers that should be supported by all PHY models.
*
*/
#define MII_BASIC_MODE_CONTROL_REG (0x0)

View File

@ -20,44 +20,53 @@ extern "C" {
#include "phy.h"
/** @brief Dump all TLK110 PHY SMI configuration registers
/**
* @brief Dump TLK110 PHY SMI configuration registers
*
* @note These registers are dumped at 'debug' level, so output
* may not be visible depending on default log levels.
*/
void phy_tlk110_dump_registers();
/** @brief Default TLK110 phy_check_init function.
/**
* @brief Default TLK110 phy_check_init function
*
*/
void phy_tlk110_check_phy_init(void);
/** @brief Default TLK110 phy_get_speed_mode function.
/**
* @brief Default TLK110 phy_get_speed_mode function
*
* @return eth_speed_mode_t Ethernet speed mode
*/
eth_speed_mode_t phy_tlk110_get_speed_mode(void);
/** @brief Default TLK110 phy_get_duplex_mode function.
/**
* @brief Default TLK110 phy_get_duplex_mode function
*
* @return eth_duplex_mode_t Ethernet duplex mode
*/
eth_duplex_mode_t phy_tlk110_get_duplex_mode(void);
/** @brief Default TLK110 phy_power_enable function.
/**
* @brief Default TLK110 phy_power_enable function
*
* @note This function may need to be replaced with a custom function
* if the PHY has a GPIO to enable power or start a clock.
*
* Consult the ethernet example to see how this is done.
*/
void phy_tlk110_power_enable(bool);
/** @brief Default TLK110 phy_init function.
/**
* @brief Default TLK110 phy_init function
*
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
esp_err_t phy_tlk110_init(void);
/** @brief Default TLK110 PHY configuration
/**
* @brief Default TLK110 PHY configuration
*
* This configuration is not suitable for use as-is, it will need
* to be modified for your particular PHY hardware setup.
* @note This configuration is not suitable for use as-is,
* it will need to be modified for your particular PHY hardware setup.
*
* Consult the Ethernet example to see how this is done.
*/
extern const eth_config_t phy_tlk110_default_ethernet_config;

View File

@ -26,7 +26,7 @@
/* ----------------------- Defines ------------------------------------------*/
#define MB_INST_MIN_SIZE (2) // The minimal size of Modbus registers area in bytes
#define MB_INST_MAX_SIZE (2048) // The maximum size of Modbus area in bytes
#define MB_INST_MAX_SIZE (65535 * 2) // The maximum size of Modbus area in bytes
#define MB_CONTROLLER_STACK_SIZE (CONFIG_MB_CONTROLLER_STACK_SIZE) // Stack size for Modbus controller
#define MB_CONTROLLER_PRIORITY (CONFIG_MB_SERIAL_TASK_PRIO - 1) // priority of MB controller task

View File

@ -576,6 +576,11 @@
#if PPP_SUPPORT
/**
* PPP_NOTIFY_PHASE==1: Support PPP notify phase.
*/
#define PPP_NOTIFY_PHASE CONFIG_PPP_NOTIFY_PHASE_SUPPORT
/**
* PAP_SUPPORT==1: Support PAP.
*/

View File

@ -45,6 +45,7 @@ typedef enum {
- current_data_offset offset of the current data for this event
- total_data_len total length of the data received
*/
MQTT_EVENT_BEFORE_CONNECT, /*!< The event occurs before connecting */
} esp_mqtt_event_id_t;
typedef enum {
@ -103,6 +104,7 @@ typedef struct {
const char *client_cert_pem; /*!< Pointer to certificate data in PEM format for SSL mutual authentication, default is NULL, not required if mutual authentication is not needed. If it is not NULL, also `client_key_pem` has to be provided. */
const char *client_key_pem; /*!< Pointer to private key data in PEM format for SSL mutual authentication, default is NULL, not required if mutual authentication is not needed. If it is not NULL, also `client_cert_pem` has to be provided. */
esp_mqtt_transport_t transport; /*!< overrides URI transport */
int refresh_connection_after_ms; /*!< Refresh connection after this value (in milliseconds) */
} esp_mqtt_client_config_t;
esp_mqtt_client_handle_t esp_mqtt_client_init(const esp_mqtt_client_config_t *config);
@ -113,6 +115,7 @@ esp_err_t esp_mqtt_client_subscribe(esp_mqtt_client_handle_t client, const char
esp_err_t esp_mqtt_client_unsubscribe(esp_mqtt_client_handle_t client, const char *topic);
int esp_mqtt_client_publish(esp_mqtt_client_handle_t client, const char *topic, const char *data, int len, int qos, int retain);
esp_err_t esp_mqtt_client_destroy(esp_mqtt_client_handle_t client);
esp_err_t esp_mqtt_set_config(esp_mqtt_client_handle_t client, const esp_mqtt_client_config_t *config);
#ifdef __cplusplus
}

View File

@ -65,6 +65,20 @@ typedef enum {
NVS_READWRITE /*!< Read and write */
} nvs_open_mode;
typedef enum {
NVS_TYPE_U8 = 0x01,
NVS_TYPE_I8 = 0x11,
NVS_TYPE_U16 = 0x02,
NVS_TYPE_I16 = 0x12,
NVS_TYPE_U32 = 0x04,
NVS_TYPE_I32 = 0x14,
NVS_TYPE_U64 = 0x08,
NVS_TYPE_I64 = 0x18,
NVS_TYPE_STR = 0x21,
NVS_TYPE_BLOB = 0x42,
NVS_TYPE_ANY = 0xff // Must be last
} nvs_type_t;
/**
* @brief Open non-volatile storage with a given namespace from the default NVS partition
*

View File

@ -205,12 +205,28 @@
#define EFUSE_RD_FLASH_CRYPT_CONFIG_M ((EFUSE_RD_FLASH_CRYPT_CONFIG_V)<<(EFUSE_RD_FLASH_CRYPT_CONFIG_S))
#define EFUSE_RD_FLASH_CRYPT_CONFIG_V 0xF
#define EFUSE_RD_FLASH_CRYPT_CONFIG_S 28
/* EFUSE_RD_DIG_VOL_L6: RO; bitpos:[27:24]; */
/*descritpion: This field stores the difference between the digital regulator voltage at level6 and 1.2 V. (RO)
BIT[27] is the sign bit, 0: + , 1: -
BIT[26:24] is the difference value, unit: 0.017V
volt_lv6 = BIT[27] ? 1.2 - BIT[26:24] * 0.017 : 1.2 + BIT[26:24] * 0.017 */
#define EFUSE_RD_DIG_VOL_L6 0x0F
#define EFUSE_RD_DIG_VOL_L6_M ((EFUSE_RD_DIG_VOL_L6_V)<<(EFUSE_RD_DIG_VOL_L6_S))
#define EFUSE_RD_DIG_VOL_L6_V 0x0F
#define EFUSE_RD_DIG_VOL_L6_S 24
/* EFUSE_RD_VOL_LEVEL_HP_INV: RO; bitpos:[23:22] */
/*description: This field stores the voltage level for CPU to run at 240 MHz, or for flash/PSRAM to run at 80 MHz.
0x0: level 7; 0x1: level 6; 0x2: level 5; 0x3: level 4. (RO)*/
#define EFUSE_RD_VOL_LEVEL_HP_INV 0x03
#define EFUSE_RD_VOL_LEVEL_HP_INV_M ((EFUSE_RD_VOL_LEVEL_HP_INV_V)<<(EFUSE_RD_VOL_LEVEL_HP_INV_S))
#define EFUSE_RD_VOL_LEVEL_HP_INV_V 0x03
#define EFUSE_RD_VOL_LEVEL_HP_INV_S 22
/* EFUSE_RD_INST_CONFIG : RO ;bitpos:[27:20] ;default: 8'b0 ; */
/*description: */
#define EFUSE_RD_INST_CONFIG 0x000000FF
#define EFUSE_RD_INST_CONFIG_M ((EFUSE_RD_INST_CONFIG_V)<<(EFUSE_RD_INST_CONFIG_S))
#define EFUSE_RD_INST_CONFIG_V 0xFF
#define EFUSE_RD_INST_CONFIG_S 20
/* Deprecated */
#define EFUSE_RD_INST_CONFIG 0x000000FF /** Deprecated **/
#define EFUSE_RD_INST_CONFIG_M ((EFUSE_RD_INST_CONFIG_V)<<(EFUSE_RD_INST_CONFIG_S)) /** Deprecated **/
#define EFUSE_RD_INST_CONFIG_V 0xFF /** Deprecated **/
#define EFUSE_RD_INST_CONFIG_S 20 /** Deprecated **/
/* EFUSE_RD_SPI_PAD_CONFIG_CS0 : RO ;bitpos:[19:15] ;default: 5'b0 ; */
/*description: read for SPI_pad_config_cs0*/
#define EFUSE_RD_SPI_PAD_CONFIG_CS0 0x0000001F
@ -464,12 +480,28 @@
#define EFUSE_FLASH_CRYPT_CONFIG_M ((EFUSE_FLASH_CRYPT_CONFIG_V)<<(EFUSE_FLASH_CRYPT_CONFIG_S))
#define EFUSE_FLASH_CRYPT_CONFIG_V 0xF
#define EFUSE_FLASH_CRYPT_CONFIG_S 28
/* EFUSE_DIG_VOL_L6: R/W; bitpos:[27:24]; */
/*descritpion: This field stores the difference between the digital regulator voltage at level6 and 1.2 V. (R/W)
BIT[27] is the sign bit, 0: + , 1: -
BIT[26:24] is the difference value, unit: 0.017V
volt_lv6 = BIT[27] ? 1.2 - BIT[26:24] * 0.017 : 1.2 + BIT[26:24] * 0.017 */
#define EFUSE_DIG_VOL_L6 0x0F
#define EFUSE_DIG_VOL_L6_M ((EFUSE_RD_DIG_VOL_L6_V)<<(EFUSE_RD_DIG_VOL_L6_S))
#define EFUSE_DIG_VOL_L6_V 0x0F
#define EFUSE_DIG_VOL_L6_S 24
/* EFUSE_VOL_LEVEL_HP_INV: R/W; bitpos:[23:22] */
/*description: This field stores the voltage level for CPU to run at 240 MHz, or for flash/PSRAM to run at 80 MHz.
0x0: level 7; 0x1: level 6; 0x2: level 5; 0x3: level 4. (R/W)*/
#define EFUSE_VOL_LEVEL_HP_INV 0x03
#define EFUSE_VOL_LEVEL_HP_INV_M ((EFUSE_RD_VOL_LEVEL_HP_INV_V)<<(EFUSE_RD_VOL_LEVEL_HP_INV_S))
#define EFUSE_VOL_LEVEL_HP_INV_V 0x03
#define EFUSE_VOL_LEVEL_HP_INV_S 22
/* EFUSE_INST_CONFIG : R/W ;bitpos:[27:20] ;default: 8'b0 ; */
/*description: */
#define EFUSE_INST_CONFIG 0x000000FF
#define EFUSE_INST_CONFIG_M ((EFUSE_INST_CONFIG_V)<<(EFUSE_INST_CONFIG_S))
#define EFUSE_INST_CONFIG_V 0xFF
#define EFUSE_INST_CONFIG_S 20
/* Deprecated */
#define EFUSE_INST_CONFIG 0x000000FF /** Deprecated **/
#define EFUSE_INST_CONFIG_M ((EFUSE_INST_CONFIG_V)<<(EFUSE_INST_CONFIG_S)) /** Deprecated **/
#define EFUSE_INST_CONFIG_V 0xFF /** Deprecated **/
#define EFUSE_INST_CONFIG_S 20 /** Deprecated **/
/* EFUSE_SPI_PAD_CONFIG_CS0 : R/W ;bitpos:[19:15] ;default: 5'b0 ; */
/*description: program for SPI_pad_config_cs0*/
#define EFUSE_SPI_PAD_CONFIG_CS0 0x0000001F

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More