From 5b20197414f6bc3f33d8235c747841a2c98fcabc Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Wed, 9 Oct 2019 08:21:06 +0000 Subject: [PATCH 1/2] IDF release/v3.3 46b12a560 --- platform.txt | 4 +- tools/esptool.py | 54 +- tools/gen_esp32part.py | 148 +-- tools/platformio-build.py | 6 +- tools/sdk/bin/bootloader_dio_40m.bin | Bin 15872 -> 16864 bytes tools/sdk/bin/bootloader_dio_80m.bin | Bin 15856 -> 16880 bytes tools/sdk/bin/bootloader_dout_40m.bin | Bin 15872 -> 16864 bytes tools/sdk/bin/bootloader_dout_80m.bin | Bin 15856 -> 16880 bytes tools/sdk/bin/bootloader_qio_40m.bin | Bin 17408 -> 18384 bytes tools/sdk/bin/bootloader_qio_80m.bin | Bin 17392 -> 18416 bytes tools/sdk/bin/bootloader_qout_40m.bin | Bin 17408 -> 18384 bytes tools/sdk/bin/bootloader_qout_80m.bin | Bin 17392 -> 18416 bytes tools/sdk/include/app_trace/esp_app_trace.h | 26 +- tools/sdk/include/app_update/esp_ota_ops.h | 106 ++ .../bootloader_support/bootloader_common.h | 59 +- .../bootloader_flash_config.h | 71 ++ .../include/bootloader_support/esp_efuse.h | 106 -- .../bootloader_support/esp_image_format.h | 40 +- .../bootloader_support/esp_secure_boot.h | 28 +- tools/sdk/include/bt/esp_bt.h | 2 +- tools/sdk/include/bt/esp_gap_ble_api.h | 34 +- tools/sdk/include/config/sdkconfig.h | 25 +- tools/sdk/include/driver/driver/can.h | 31 +- tools/sdk/include/driver/driver/i2s.h | 37 + tools/sdk/include/driver/driver/rmt.h | 27 + tools/sdk/include/driver/driver/spi_common.h | 48 +- tools/sdk/include/driver/driver/spi_master.h | 4 + tools/sdk/include/driver/driver/spi_slave.h | 31 +- tools/sdk/include/driver/driver/uart.h | 7 +- tools/sdk/include/efuse/esp_efuse.h | 362 +++++++ tools/sdk/include/efuse/esp_efuse_table.h | 69 ++ tools/sdk/include/esp-tls/esp_tls.h | 23 +- tools/sdk/include/esp32/esp_attr.h | 35 +- tools/sdk/include/esp32/esp_clk.h | 1 + tools/sdk/include/esp32/esp_core_dump.h | 64 -- tools/sdk/include/esp32/esp_event_legacy.h | 5 + .../sdk/include/esp32/esp_flash_data_types.h | 14 +- tools/sdk/include/esp32/esp_phy_init.h | 12 + tools/sdk/include/esp32/esp_wifi_internal.h | 82 +- tools/sdk/include/esp32/rom/crc.h | 57 +- tools/sdk/include/esp32/rom/spi_flash.h | 5 + tools/sdk/include/esp32/rom/uart.h | 6 +- tools/sdk/include/esp_event/esp_event.h | 166 ++-- .../include/esp_http_client/esp_http_client.h | 32 +- .../include/esp_http_server/esp_http_server.h | 304 +++++- .../sdk/include/esp_https_ota/esp_https_ota.h | 1 + .../esp_https_server/esp_https_server.h | 130 +++ tools/sdk/include/espcoredump/esp_core_dump.h | 89 ++ tools/sdk/include/fatfs/ffconf.h | 9 +- tools/sdk/include/freemodbus/mbcontroller.h | 2 +- .../freertos/freertos/FreeRTOSConfig.h | 7 +- .../sdk/include/freertos/freertos/portmacro.h | 68 ++ tools/sdk/include/idf_test/idf_performance.h | 14 +- tools/sdk/include/lwip/lwipopts.h | 44 +- tools/sdk/include/mbedtls/mbedtls/aes.h | 76 +- tools/sdk/include/mbedtls/mbedtls/aesni.h | 52 +- tools/sdk/include/mbedtls/mbedtls/arc4.h | 5 + tools/sdk/include/mbedtls/mbedtls/aria.h | 103 +- tools/sdk/include/mbedtls/mbedtls/asn1write.h | 317 +++--- tools/sdk/include/mbedtls/mbedtls/base64.h | 9 + tools/sdk/include/mbedtls/mbedtls/bignum.h | 816 +++++++++------ tools/sdk/include/mbedtls/mbedtls/blowfish.h | 141 ++- tools/sdk/include/mbedtls/mbedtls/bn_mul.h | 52 +- tools/sdk/include/mbedtls/mbedtls/camellia.h | 221 +++-- tools/sdk/include/mbedtls/mbedtls/ccm.h | 118 ++- tools/sdk/include/mbedtls/mbedtls/certs.h | 240 ++++- tools/sdk/include/mbedtls/mbedtls/chacha20.h | 54 +- .../sdk/include/mbedtls/mbedtls/chachapoly.h | 83 +- .../include/mbedtls/mbedtls/check_config.h | 15 + tools/sdk/include/mbedtls/mbedtls/cipher.h | 228 +++-- tools/sdk/include/mbedtls/mbedtls/cmac.h | 7 + .../sdk/include/mbedtls/mbedtls/compat-1.3.h | 6 + tools/sdk/include/mbedtls/mbedtls/config.h | 209 +++- tools/sdk/include/mbedtls/mbedtls/ctr_drbg.h | 74 +- tools/sdk/include/mbedtls/mbedtls/debug.h | 36 + tools/sdk/include/mbedtls/mbedtls/des.h | 6 + tools/sdk/include/mbedtls/mbedtls/dhm.h | 173 ++-- tools/sdk/include/mbedtls/mbedtls/ecdh.h | 292 ++++-- tools/sdk/include/mbedtls/mbedtls/ecdsa.h | 332 +++++-- tools/sdk/include/mbedtls/mbedtls/ecjpake.h | 148 +-- tools/sdk/include/mbedtls/mbedtls/ecp.h | 590 ++++++++--- .../include/mbedtls/mbedtls/ecp_internal.h | 6 + tools/sdk/include/mbedtls/mbedtls/error.h | 19 +- tools/sdk/include/mbedtls/mbedtls/gcm.h | 107 +- tools/sdk/include/mbedtls/mbedtls/havege.h | 6 + tools/sdk/include/mbedtls/mbedtls/hkdf.h | 6 + tools/sdk/include/mbedtls/mbedtls/hmac_drbg.h | 36 +- tools/sdk/include/mbedtls/mbedtls/md.h | 2 + tools/sdk/include/mbedtls/mbedtls/md2.h | 5 + tools/sdk/include/mbedtls/mbedtls/md4.h | 5 + tools/sdk/include/mbedtls/mbedtls/md5.h | 5 + tools/sdk/include/mbedtls/mbedtls/net.h | 5 + tools/sdk/include/mbedtls/mbedtls/nist_kw.h | 6 + tools/sdk/include/mbedtls/mbedtls/padlock.h | 42 +- tools/sdk/include/mbedtls/mbedtls/pem.h | 6 + tools/sdk/include/mbedtls/mbedtls/pk.h | 215 +++- .../sdk/include/mbedtls/mbedtls/pk_internal.h | 23 + tools/sdk/include/mbedtls/mbedtls/pkcs12.h | 10 + tools/sdk/include/mbedtls/mbedtls/pkcs5.h | 14 + tools/sdk/include/mbedtls/mbedtls/platform.h | 3 + .../include/mbedtls/mbedtls/platform_util.h | 86 +- tools/sdk/include/mbedtls/mbedtls/poly1305.h | 55 +- tools/sdk/include/mbedtls/mbedtls/ripemd160.h | 6 + tools/sdk/include/mbedtls/mbedtls/rsa.h | 598 ++++++----- tools/sdk/include/mbedtls/mbedtls/sha1.h | 66 +- tools/sdk/include/mbedtls/mbedtls/sha256.h | 93 +- tools/sdk/include/mbedtls/mbedtls/sha512.h | 94 +- tools/sdk/include/mbedtls/mbedtls/ssl.h | 237 +++-- tools/sdk/include/mbedtls/mbedtls/ssl_cache.h | 6 + .../mbedtls/mbedtls/ssl_ciphersuites.h | 6 + .../sdk/include/mbedtls/mbedtls/ssl_cookie.h | 6 + .../include/mbedtls/mbedtls/ssl_internal.h | 27 +- .../sdk/include/mbedtls/mbedtls/ssl_ticket.h | 6 + tools/sdk/include/mbedtls/mbedtls/threading.h | 3 + tools/sdk/include/mbedtls/mbedtls/version.h | 10 +- tools/sdk/include/mbedtls/mbedtls/x509.h | 4 + tools/sdk/include/mbedtls/mbedtls/x509_crt.h | 139 ++- tools/sdk/include/mbedtls/mbedtls/x509_csr.h | 8 + tools/sdk/include/mbedtls/mbedtls/xtea.h | 6 + tools/sdk/include/mqtt/mqtt_client.h | 128 +-- tools/sdk/include/mqtt/mqtt_config.h | 17 +- tools/sdk/include/nvs_flash/nvs.h | 14 + tools/sdk/include/pthread/esp_pthread.h | 20 +- tools/sdk/include/soc/soc/apb_ctrl_struct.h | 2 + tools/sdk/include/soc/soc/can_struct.h | 2 + tools/sdk/include/soc/soc/efuse_reg.h | 53 +- tools/sdk/include/soc/soc/gpio_sd_struct.h | 2 + tools/sdk/include/soc/soc/gpio_struct.h | 2 + tools/sdk/include/soc/soc/hinf_struct.h | 2 + tools/sdk/include/soc/soc/host_struct.h | 2 + tools/sdk/include/soc/soc/i2c_struct.h | 2 + tools/sdk/include/soc/soc/i2s_struct.h | 2 + tools/sdk/include/soc/soc/ledc_reg.h | 104 +- tools/sdk/include/soc/soc/ledc_struct.h | 2 + tools/sdk/include/soc/soc/mcpwm_struct.h | 2 + tools/sdk/include/soc/soc/pcnt_struct.h | 2 + tools/sdk/include/soc/soc/rmt_reg.h | 436 +++++++- tools/sdk/include/soc/soc/rmt_struct.h | 2 + tools/sdk/include/soc/soc/rtc_cntl_struct.h | 2 + tools/sdk/include/soc/soc/rtc_io_struct.h | 2 + tools/sdk/include/soc/soc/sdmmc_struct.h | 2 + tools/sdk/include/soc/soc/sens_struct.h | 2 + tools/sdk/include/soc/soc/slc_struct.h | 2 + tools/sdk/include/soc/soc/soc_memory_layout.h | 5 + tools/sdk/include/soc/soc/spi_struct.h | 2 + tools/sdk/include/soc/soc/syscon_struct.h | 2 + .../sdk/include/soc/soc/timer_group_struct.h | 2 + tools/sdk/include/soc/soc/uart_struct.h | 2 + tools/sdk/include/soc/soc/uhci_struct.h | 2 + tools/sdk/include/spi_flash/esp_partition.h | 1 + .../sdk/include/tcpip_adapter/tcpip_adapter.h | 656 +++++++------ .../tcpip_adapter/tcpip_adapter_internal.h | 66 ++ tools/sdk/include/ulp/esp32/ulp.h | 3 + tools/sdk/include/unity/unity.h | 503 ++++++++++ tools/sdk/include/unity/unity_config.h | 53 + tools/sdk/include/unity/unity_internals.h | 928 ++++++++++++++++++ tools/sdk/include/unity/unity_test_runner.h | 174 ++++ tools/sdk/include/vfs/esp_vfs.h | 6 + .../wifi_provisioning/manager.h | 553 +++++++++++ .../wifi_provisioning/scheme_ble.h | 82 ++ .../wifi_provisioning/scheme_console.h | 34 + .../wifi_provisioning/scheme_softap.h | 34 + .../wifi_provisioning/wifi_scan.h | 166 ++++ .../wpa_supplicant/wpa2/eap_peer/eap_i.h | 13 +- tools/sdk/ld/esp32.common.ld | 343 ------- tools/sdk/ld/esp32.ld | 2 +- tools/sdk/ld/esp32.project.ld | 620 ++++++++++++ .../sdk/ld/esp32.spiram.rom-functions-dram.ld | 143 --- .../sdk/ld/esp32.spiram.rom-functions-iram.ld | 140 --- tools/sdk/ld/esp32_out.ld | 2 +- tools/sdk/ld/wifi_iram.ld | 4 - tools/sdk/lib/libapp_trace.a | Bin 23392 -> 23396 bytes tools/sdk/lib/libapp_update.a | Bin 53622 -> 84376 bytes tools/sdk/lib/libasio.a | Bin 2005368 -> 2005552 bytes tools/sdk/lib/libbootloader_support.a | Bin 314066 -> 303580 bytes tools/sdk/lib/libbt.a | Bin 13168296 -> 13212234 bytes tools/sdk/lib/libbtdm_app.a | Bin 379068 -> 387370 bytes tools/sdk/lib/libcoap.a | Bin 461522 -> 461522 bytes tools/sdk/lib/libcoexist.a | Bin 62032 -> 61420 bytes tools/sdk/lib/libconsole.a | Bin 402520 -> 403052 bytes tools/sdk/lib/libcore.a | Bin 11844 -> 6942 bytes tools/sdk/lib/libcxx.a | Bin 64392 -> 64392 bytes tools/sdk/lib/libdriver.a | Bin 2481178 -> 2529586 bytes tools/sdk/lib/libefuse.a | Bin 0 -> 134348 bytes tools/sdk/lib/libesp-tls.a | Bin 80712 -> 81840 bytes tools/sdk/lib/libesp32-camera.a | Bin 620514 -> 626286 bytes tools/sdk/lib/libesp32.a | Bin 1354082 -> 1398378 bytes tools/sdk/lib/libesp_adc_cal.a | Bin 40168 -> 40168 bytes tools/sdk/lib/libesp_event.a | Bin 89594 -> 95966 bytes tools/sdk/lib/libesp_http_client.a | Bin 185878 -> 189900 bytes tools/sdk/lib/libesp_http_server.a | Bin 263204 -> 278748 bytes tools/sdk/lib/libesp_https_ota.a | Bin 20990 -> 21310 bytes tools/sdk/lib/libesp_https_server.a | Bin 0 -> 33476 bytes tools/sdk/lib/libesp_ringbuf.a | Bin 118552 -> 118572 bytes tools/sdk/lib/libespcoredump.a | Bin 0 -> 20876 bytes tools/sdk/lib/libespnow.a | Bin 46778 -> 46778 bytes tools/sdk/lib/libethernet.a | Bin 182758 -> 183598 bytes tools/sdk/lib/libexpat.a | Bin 1219570 -> 1219570 bytes tools/sdk/lib/libface_detection.a | Bin 72260 -> 72260 bytes tools/sdk/lib/libface_recognition.a | Bin 87948 -> 88004 bytes tools/sdk/lib/libfatfs.a | Bin 457564 -> 469132 bytes tools/sdk/lib/libfb_gfx.a | Bin 22972 -> 22972 bytes tools/sdk/lib/libfreemodbus.a | Bin 249952 -> 249972 bytes tools/sdk/lib/libfreertos.a | Bin 541580 -> 541644 bytes tools/sdk/lib/libheap.a | Bin 232422 -> 240654 bytes tools/sdk/lib/libimage_util.a | Bin 63478 -> 63478 bytes tools/sdk/lib/libjsmn.a | Bin 21818 -> 21818 bytes tools/sdk/lib/libjson.a | Bin 304226 -> 304226 bytes tools/sdk/lib/liblibsodium.a | Bin 1826584 -> 1826584 bytes tools/sdk/lib/liblog.a | Bin 40924 -> 41636 bytes tools/sdk/lib/liblwip.a | Bin 3315688 -> 3315616 bytes tools/sdk/lib/libmbedtls.a | Bin 3459180 -> 3570104 bytes tools/sdk/lib/libmdns.a | Bin 683504 -> 683616 bytes tools/sdk/lib/libmesh.a | Bin 947578 -> 946006 bytes tools/sdk/lib/libmicro-ecc.a | Bin 155456 -> 155456 bytes tools/sdk/lib/libmqtt.a | Bin 222380 -> 189508 bytes tools/sdk/lib/libnet80211.a | Bin 989744 -> 1060792 bytes tools/sdk/lib/libnewlib.a | Bin 131182 -> 140912 bytes tools/sdk/lib/libnghttp.a | Bin 1565326 -> 1565326 bytes tools/sdk/lib/libnvs_flash.a | Bin 845000 -> 845956 bytes tools/sdk/lib/libopenssl.a | Bin 290112 -> 290116 bytes tools/sdk/lib/libphy.a | Bin 503548 -> 518898 bytes tools/sdk/lib/libpp.a | Bin 496318 -> 498410 bytes tools/sdk/lib/libprotobuf-c.a | Bin 329390 -> 329390 bytes tools/sdk/lib/libprotocomm.a | Bin 441402 -> 441522 bytes tools/sdk/lib/libpthread.a | Bin 118870 -> 124250 bytes tools/sdk/lib/libsdmmc.a | Bin 257532 -> 257532 bytes tools/sdk/lib/libsmartconfig.a | Bin 108030 -> 108022 bytes tools/sdk/lib/libsmartconfig_ack.a | Bin 22666 -> 22506 bytes tools/sdk/lib/libsoc.a | Bin 235434 -> 236490 bytes tools/sdk/lib/libspi_flash.a | Bin 214692 -> 223014 bytes tools/sdk/lib/libspiffs.a | Bin 587430 -> 592010 bytes tools/sdk/lib/libtcp_transport.a | Bin 156182 -> 156646 bytes tools/sdk/lib/libtcpip_adapter.a | Bin 135352 -> 135812 bytes tools/sdk/lib/libulp.a | Bin 38022 -> 38006 bytes tools/sdk/lib/libunity.a | Bin 0 -> 174798 bytes tools/sdk/lib/libvfs.a | Bin 244094 -> 249860 bytes tools/sdk/lib/libwear_levelling.a | Bin 237860 -> 237964 bytes tools/sdk/lib/libwifi_provisioning.a | Bin 148730 -> 532314 bytes tools/sdk/lib/libwpa.a | Bin 161476 -> 161496 bytes tools/sdk/lib/libwpa2.a | Bin 30216 -> 30220 bytes tools/sdk/lib/libwpa_supplicant.a | Bin 3120678 -> 3120678 bytes tools/sdk/lib/libwps.a | Bin 71936 -> 71908 bytes tools/sdk/lib/libxtensa-debug-module.a | Bin 12438 -> 12438 bytes tools/sdk/sdkconfig | 71 +- 245 files changed, 10790 insertions(+), 3503 deletions(-) create mode 100644 tools/sdk/include/bootloader_support/bootloader_flash_config.h delete mode 100644 tools/sdk/include/bootloader_support/esp_efuse.h create mode 100644 tools/sdk/include/efuse/esp_efuse.h create mode 100644 tools/sdk/include/efuse/esp_efuse_table.h delete mode 100644 tools/sdk/include/esp32/esp_core_dump.h create mode 100644 tools/sdk/include/esp_https_server/esp_https_server.h create mode 100644 tools/sdk/include/espcoredump/esp_core_dump.h mode change 100644 => 100755 tools/sdk/include/mqtt/mqtt_client.h create mode 100644 tools/sdk/include/tcpip_adapter/tcpip_adapter_internal.h create mode 100644 tools/sdk/include/unity/unity.h create mode 100644 tools/sdk/include/unity/unity_config.h create mode 100644 tools/sdk/include/unity/unity_internals.h create mode 100644 tools/sdk/include/unity/unity_test_runner.h create mode 100644 tools/sdk/include/wifi_provisioning/wifi_provisioning/manager.h create mode 100644 tools/sdk/include/wifi_provisioning/wifi_provisioning/scheme_ble.h create mode 100644 tools/sdk/include/wifi_provisioning/wifi_provisioning/scheme_console.h create mode 100644 tools/sdk/include/wifi_provisioning/wifi_provisioning/scheme_softap.h create mode 100644 tools/sdk/include/wifi_provisioning/wifi_provisioning/wifi_scan.h delete mode 100644 tools/sdk/ld/esp32.common.ld create mode 100644 tools/sdk/ld/esp32.project.ld delete mode 100644 tools/sdk/ld/esp32.spiram.rom-functions-dram.ld delete mode 100644 tools/sdk/ld/esp32.spiram.rom-functions-iram.ld delete mode 100644 tools/sdk/ld/wifi_iram.ld create mode 100644 tools/sdk/lib/libefuse.a create mode 100644 tools/sdk/lib/libesp_https_server.a create mode 100644 tools/sdk/lib/libespcoredump.a create mode 100644 tools/sdk/lib/libunity.a diff --git a/platform.txt b/platform.txt index aad26366171..d85e21e7826 100644 --- a/platform.txt +++ b/platform.txt @@ -22,7 +22,7 @@ compiler.warning_flags.all=-Wall -Werror=all -Wextra compiler.path={runtime.tools.xtensa-esp32-elf-gcc.path}/bin/ compiler.sdk.path={runtime.platform.path}/tools/sdk -compiler.cpreprocessor.flags=-DESP_PLATFORM -DMBEDTLS_CONFIG_FILE="mbedtls/esp_config.h" -DHAVE_CONFIG_H -DGCC_NOT_5_2_0=0 -DWITH_POSIX "-I{compiler.sdk.path}/include/config" "-I{compiler.sdk.path}/include/app_trace" "-I{compiler.sdk.path}/include/app_update" "-I{compiler.sdk.path}/include/asio" "-I{compiler.sdk.path}/include/bootloader_support" "-I{compiler.sdk.path}/include/bt" "-I{compiler.sdk.path}/include/coap" "-I{compiler.sdk.path}/include/console" "-I{compiler.sdk.path}/include/driver" "-I{compiler.sdk.path}/include/esp-tls" "-I{compiler.sdk.path}/include/esp32" "-I{compiler.sdk.path}/include/esp_adc_cal" "-I{compiler.sdk.path}/include/esp_event" "-I{compiler.sdk.path}/include/esp_http_client" "-I{compiler.sdk.path}/include/esp_http_server" "-I{compiler.sdk.path}/include/esp_https_ota" "-I{compiler.sdk.path}/include/esp_ringbuf" "-I{compiler.sdk.path}/include/ethernet" "-I{compiler.sdk.path}/include/expat" "-I{compiler.sdk.path}/include/fatfs" "-I{compiler.sdk.path}/include/freemodbus" "-I{compiler.sdk.path}/include/freertos" "-I{compiler.sdk.path}/include/heap" "-I{compiler.sdk.path}/include/idf_test" "-I{compiler.sdk.path}/include/jsmn" "-I{compiler.sdk.path}/include/json" "-I{compiler.sdk.path}/include/libsodium" "-I{compiler.sdk.path}/include/log" "-I{compiler.sdk.path}/include/lwip" "-I{compiler.sdk.path}/include/mbedtls" "-I{compiler.sdk.path}/include/mdns" "-I{compiler.sdk.path}/include/micro-ecc" "-I{compiler.sdk.path}/include/mqtt" "-I{compiler.sdk.path}/include/newlib" "-I{compiler.sdk.path}/include/nghttp" "-I{compiler.sdk.path}/include/nvs_flash" "-I{compiler.sdk.path}/include/openssl" "-I{compiler.sdk.path}/include/protobuf-c" "-I{compiler.sdk.path}/include/protocomm" "-I{compiler.sdk.path}/include/pthread" "-I{compiler.sdk.path}/include/sdmmc" "-I{compiler.sdk.path}/include/smartconfig_ack" "-I{compiler.sdk.path}/include/soc" "-I{compiler.sdk.path}/include/spi_flash" "-I{compiler.sdk.path}/include/spiffs" "-I{compiler.sdk.path}/include/tcp_transport" "-I{compiler.sdk.path}/include/tcpip_adapter" "-I{compiler.sdk.path}/include/ulp" "-I{compiler.sdk.path}/include/vfs" "-I{compiler.sdk.path}/include/wear_levelling" "-I{compiler.sdk.path}/include/wifi_provisioning" "-I{compiler.sdk.path}/include/wpa_supplicant" "-I{compiler.sdk.path}/include/xtensa-debug-module" "-I{compiler.sdk.path}/include/esp-face" "-I{compiler.sdk.path}/include/esp32-camera" "-I{compiler.sdk.path}/include/esp-face" "-I{compiler.sdk.path}/include/fb_gfx" +compiler.cpreprocessor.flags=-DESP_PLATFORM -DMBEDTLS_CONFIG_FILE="mbedtls/esp_config.h" -DHAVE_CONFIG_H -DGCC_NOT_5_2_0=0 -DWITH_POSIX "-I{compiler.sdk.path}/include/config" "-I{compiler.sdk.path}/include/app_trace" "-I{compiler.sdk.path}/include/app_update" "-I{compiler.sdk.path}/include/asio" "-I{compiler.sdk.path}/include/bootloader_support" "-I{compiler.sdk.path}/include/bt" "-I{compiler.sdk.path}/include/coap" "-I{compiler.sdk.path}/include/console" "-I{compiler.sdk.path}/include/driver" "-I{compiler.sdk.path}/include/efuse" "-I{compiler.sdk.path}/include/esp-tls" "-I{compiler.sdk.path}/include/esp32" "-I{compiler.sdk.path}/include/esp_adc_cal" "-I{compiler.sdk.path}/include/esp_event" "-I{compiler.sdk.path}/include/esp_http_client" "-I{compiler.sdk.path}/include/esp_http_server" "-I{compiler.sdk.path}/include/esp_https_ota" "-I{compiler.sdk.path}/include/esp_https_server" "-I{compiler.sdk.path}/include/esp_ringbuf" "-I{compiler.sdk.path}/include/espcoredump" "-I{compiler.sdk.path}/include/ethernet" "-I{compiler.sdk.path}/include/expat" "-I{compiler.sdk.path}/include/fatfs" "-I{compiler.sdk.path}/include/freemodbus" "-I{compiler.sdk.path}/include/freertos" "-I{compiler.sdk.path}/include/heap" "-I{compiler.sdk.path}/include/idf_test" "-I{compiler.sdk.path}/include/jsmn" "-I{compiler.sdk.path}/include/json" "-I{compiler.sdk.path}/include/libsodium" "-I{compiler.sdk.path}/include/log" "-I{compiler.sdk.path}/include/lwip" "-I{compiler.sdk.path}/include/mbedtls" "-I{compiler.sdk.path}/include/mdns" "-I{compiler.sdk.path}/include/micro-ecc" "-I{compiler.sdk.path}/include/mqtt" "-I{compiler.sdk.path}/include/newlib" "-I{compiler.sdk.path}/include/nghttp" "-I{compiler.sdk.path}/include/nvs_flash" "-I{compiler.sdk.path}/include/openssl" "-I{compiler.sdk.path}/include/protobuf-c" "-I{compiler.sdk.path}/include/protocomm" "-I{compiler.sdk.path}/include/pthread" "-I{compiler.sdk.path}/include/sdmmc" "-I{compiler.sdk.path}/include/smartconfig_ack" "-I{compiler.sdk.path}/include/soc" "-I{compiler.sdk.path}/include/spi_flash" "-I{compiler.sdk.path}/include/spiffs" "-I{compiler.sdk.path}/include/tcp_transport" "-I{compiler.sdk.path}/include/tcpip_adapter" "-I{compiler.sdk.path}/include/ulp" "-I{compiler.sdk.path}/include/unity" "-I{compiler.sdk.path}/include/vfs" "-I{compiler.sdk.path}/include/wear_levelling" "-I{compiler.sdk.path}/include/wifi_provisioning" "-I{compiler.sdk.path}/include/wpa_supplicant" "-I{compiler.sdk.path}/include/xtensa-debug-module" "-I{compiler.sdk.path}/include/esp-face" "-I{compiler.sdk.path}/include/esp32-camera" "-I{compiler.sdk.path}/include/esp-face" "-I{compiler.sdk.path}/include/fb_gfx" compiler.c.cmd=xtensa-esp32-elf-gcc compiler.c.flags=-std=gnu99 -Os -g3 -fstack-protector -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -nostdlib -Wpointer-arith {compiler.warning_flags} -Wno-maybe-uninitialized -Wno-unused-function -Wno-unused-but-set-variable -Wno-unused-variable -Wno-deprecated-declarations -Wno-unused-parameter -Wno-sign-compare -Wno-old-style-declaration -MMD -c @@ -35,7 +35,7 @@ compiler.S.flags=-c -g3 -x assembler-with-cpp -MMD -mlongcalls compiler.c.elf.cmd=xtensa-esp32-elf-gcc compiler.c.elf.flags=-nostdlib "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" -T esp32_out.ld -T esp32.common.ld -T esp32.rom.ld -T esp32.peripherals.ld -T esp32.rom.libgcc.ld -T esp32.rom.spiram_incompatible_fns.ld -u ld_include_panic_highint_hdl -u call_user_start_cpu0 -Wl,--gc-sections -Wl,-static -Wl,--undefined=uxTopUsedPriority -u __cxa_guard_dummy -u __cxx_fatal_exception -compiler.c.elf.libs=-lgcc -lesp32 -lphy -lesp_http_client -lmbedtls -lrtc -lesp_http_server -lbtdm_app -lspiffs -lbootloader_support -lmdns -lnvs_flash -lfatfs -lpp -lnet80211 -ljsmn -lface_detection -llibsodium -lvfs -ldl_lib -llog -lfreertos -lcxx -lsmartconfig_ack -lxtensa-debug-module -lheap -ltcpip_adapter -lmqtt -lulp -lfd -lfb_gfx -lnghttp -lprotocomm -lsmartconfig -lm -lethernet -limage_util -lc_nano -lsoc -ltcp_transport -lc -lmicro-ecc -lface_recognition -ljson -lwpa_supplicant -lmesh -lesp_https_ota -lwpa2 -lexpat -llwip -lwear_levelling -lapp_update -ldriver -lbt -lespnow -lcoap -lasio -lnewlib -lconsole -lapp_trace -lesp32-camera -lhal -lprotobuf-c -lsdmmc -lcore -lpthread -lcoexist -lfreemodbus -lspi_flash -lesp-tls -lwpa -lwifi_provisioning -lwps -lesp_adc_cal -lesp_event -lopenssl -lesp_ringbuf -lfr -lstdc++ +compiler.c.elf.libs=-lgcc -lesp32 -lphy -lesp_http_client -lmbedtls -lrtc -lesp_http_server -lbtdm_app -lspiffs -lbootloader_support -lmdns -lnvs_flash -lfatfs -lpp -lnet80211 -ljsmn -lface_detection -llibsodium -lvfs -ldl_lib -llog -lfreertos -lcxx -lsmartconfig_ack -lxtensa-debug-module -lheap -ltcpip_adapter -lmqtt -lulp -lfd -lfb_gfx -lnghttp -lunity -lprotocomm -lespcoredump -lesp_https_server -lsmartconfig -lm -lethernet -limage_util -lc_nano -lsoc -ltcp_transport -lc -lmicro-ecc -lface_recognition -ljson -lwpa_supplicant -lmesh -lesp_https_ota -lwpa2 -lexpat -llwip -lwear_levelling -lapp_update -ldriver -lbt -lespnow -lcoap -lasio -lnewlib -lconsole -lapp_trace -lesp32-camera -lhal -lprotobuf-c -lsdmmc -lcore -lpthread -lcoexist -lfreemodbus -lspi_flash -lesp-tls -lwpa -lwifi_provisioning -lwps -lesp_adc_cal -lesp_event -lopenssl -lesp_ringbuf -lefuse -lfr -lstdc++ compiler.as.cmd=xtensa-esp32-elf-as diff --git a/tools/esptool.py b/tools/esptool.py index d6ceb6f9b39..a867a691c22 100755 --- a/tools/esptool.py +++ b/tools/esptool.py @@ -1018,11 +1018,6 @@ class ESP8266ROM(ESPLoader): BOOTLOADER_FLASH_OFFSET = 0 - MEMORY_MAP = [[0x3FF00000, 0x3FF00010, "DPORT"], - [0x3FFE8000, 0x40000000, "DRAM"], - [0x40100000, 0x40108000, "IRAM"], - [0x40201010, 0x402E1010, "IROM"]] - def get_efuses(self): # Return the 128 bits of ESP8266 efuse as a single Python integer return (self.read_reg(0x3ff0005c) << 96 | @@ -1121,7 +1116,6 @@ class ESP32ROM(ESPLoader): """ CHIP_NAME = "ESP32" - IMAGE_CHIP_ID = 0 IS_STUB = False DATE_REG_VALUE = 0x15122500 @@ -1158,22 +1152,6 @@ class ESP32ROM(ESPLoader): OVERRIDE_VDDSDIO_CHOICES = ["1.8V", "1.9V", "OFF"] - MEMORY_MAP = [[0x3F400000, 0x3F800000, "DROM"], - [0x3F800000, 0x3FC00000, "EXTRAM_DATA"], - [0x3FF80000, 0x3FF82000, "RTC_DRAM"], - [0x3FF90000, 0x40000000, "BYTE_ACCESSIBLE"], - [0x3FFAE000, 0x40000000, "DRAM"], - [0x3FFAE000, 0x40000000, "DMA"], - [0x3FFE0000, 0x3FFFFFFC, "DIRAM_DRAM"], - [0x40000000, 0x40070000, "IROM"], - [0x40070000, 0x40078000, "CACHE_PRO"], - [0x40078000, 0x40080000, "CACHE_APP"], - [0x40080000, 0x400A0000, "IRAM"], - [0x400A0000, 0x400BFFFC, "DIRAM_IRAM"], - [0x400C0000, 0x400C2000, "RTC_IRAM"], - [0x400D0000, 0x40400000, "IROM"], - [0x50000000, 0x50002000, "RTC_DATA"]] - """ Try to read the BLOCK1 (encryption key) and check if it is valid """ def is_flash_encryption_key_valid(self): @@ -1714,7 +1692,7 @@ class ESP32FirmwareImage(BaseFirmwareImage): # to be set to this value so ROM bootloader will skip it. WP_PIN_DISABLED = 0xEE - EXTENDED_HEADER_STRUCT_FMT = " 1 ) - + names = [p.name for p in self] + duplicates = set(n for n in names if names.count(n) > 1) + # print sorted duplicate partitions by name if len(duplicates) != 0: print("A list of partitions that have the same name:") @@ -183,14 +191,14 @@ def verify(self): if len(duplicates.intersection([p.name])) != 0: print("%s" % (p.to_csv())) raise InputError("Partition names must be unique") - + # check for overlaps last = None for p in sorted(self, key=lambda x:x.offset): if p.offset < offset_part_table + PARTITION_TABLE_SIZE: raise InputError("Partition offset 0x%x is below 0x%x" % (p.offset, offset_part_table + PARTITION_TABLE_SIZE)) if last is not None and p.offset < last.offset + last.size: - raise InputError("Partition at 0x%x overlaps 0x%x-0x%x" % (p.offset, last.offset, last.offset+last.size-1)) + raise InputError("Partition at 0x%x overlaps 0x%x-0x%x" % (p.offset, last.offset, last.offset + last.size - 1)) last = p def flash_size(self): @@ -205,17 +213,17 @@ def flash_size(self): @classmethod def from_binary(cls, b): - md5 = hashlib.md5(); + md5 = hashlib.md5() result = cls() for o in range(0,len(b),32): - data = b[o:o+32] + data = b[o:o + 32] if len(data) != 32: raise InputError("Partition table length must be a multiple of 32 bytes") - if data == b'\xFF'*32: + if data == b'\xFF' * 32: return result # got end marker - if md5sum and data[:2] == MD5_PARTITION_BEGIN[:2]: #check only the magic number part + if md5sum and data[:2] == MD5_PARTITION_BEGIN[:2]: # check only the magic number part if data[16:] == md5.digest(): - continue # the next iteration will check for the end marker + continue # the next iteration will check for the end marker else: raise InputError("MD5 checksums don't match! (computed: 0x%s, parsed: 0x%s)" % (md5.hexdigest(), binascii.hexlify(data[16:]))) else: @@ -227,34 +235,35 @@ def to_binary(self): result = b"".join(e.to_binary() for e in self) if md5sum: result += MD5_PARTITION_BEGIN + hashlib.md5(result).digest() - if len(result )>= MAX_PARTITION_LENGTH: + if len(result) >= MAX_PARTITION_LENGTH: raise InputError("Binary partition table length (%d) longer than max" % len(result)) result += b"\xFF" * (MAX_PARTITION_LENGTH - len(result)) # pad the sector, for signing return result def to_csv(self, simple_formatting=False): - rows = [ "# Espressif ESP32 Partition Table", - "# Name, Type, SubType, Offset, Size, Flags" ] - rows += [ x.to_csv(simple_formatting) for x in self ] + rows = ["# Espressif ESP32 Partition Table", + "# Name, Type, SubType, Offset, Size, Flags"] + rows += [x.to_csv(simple_formatting) for x in self] return "\n".join(rows) + "\n" + class PartitionDefinition(object): MAGIC_BYTES = b"\xAA\x50" ALIGNMENT = { - APP_TYPE : 0x10000, - DATA_TYPE : 0x04, + APP_TYPE: 0x10000, + DATA_TYPE: 0x04, } # dictionary maps flag name (as used in CSV flags list, property name) # to bit set in flags words in binary format FLAGS = { - "encrypted" : 0 + "encrypted": 0 } # add subtypes for the 16 OTA slot values ("ota_XX, etc.") - for ota_slot in range(16): - SUBTYPES[TYPES["app"]]["ota_%d" % ota_slot] = 0x10 + ota_slot + for ota_slot in range(NUM_PARTITION_SUBTYPE_APP_OTA): + SUBTYPES[TYPES["app"]]["ota_%d" % ota_slot] = MIN_PARTITION_SUBTYPE_APP_OTA + ota_slot def __init__(self): self.name = "" @@ -268,7 +277,7 @@ def __init__(self): def from_csv(cls, line, line_no): """ Parse a line from the CSV """ line_w_defaults = line + ",,,," # lazy way to support default fields - fields = [ f.strip() for f in line_w_defaults.split(",") ] + fields = [f.strip() for f in line_w_defaults.split(",")] res = PartitionDefinition() res.line_no = line_no @@ -298,7 +307,7 @@ def __repr__(self): def maybe_hex(x): return "0x%x" % x if x is not None else "None" return "PartitionDefinition('%s', 0x%x, 0x%x, %s, %s)" % (self.name, self.type, self.subtype or 0, - maybe_hex(self.offset), maybe_hex(self.size)) + maybe_hex(self.offset), maybe_hex(self.size)) def __str__(self): return "Part '%s' %d/%d @ 0x%x size 0x%x" % (self.name, self.type, self.subtype, self.offset or -1, self.size or -1) @@ -325,7 +334,7 @@ def parse_type(self, strval): def parse_subtype(self, strval): if strval == "": - return 0 # default + return 0 # default return parse_int(strval, SUBTYPES.get(self.type, {})) def parse_address(self, strval): @@ -349,12 +358,14 @@ def verify(self): raise ValidationError(self, "Size field is not set") if self.name in TYPES and TYPES.get(self.name, "") != self.type: - critical("WARNING: Partition has name '%s' which is a partition type, but does not match this partition's type (0x%x). Mistake in partition table?" % (self.name, self.type)) + critical("WARNING: Partition has name '%s' which is a partition type, but does not match this partition's " + "type (0x%x). Mistake in partition table?" % (self.name, self.type)) all_subtype_names = [] for names in (t.keys() for t in SUBTYPES.values()): all_subtype_names += names if self.name in all_subtype_names and SUBTYPES.get(self.type, {}).get(self.name, "") != self.subtype: - critical("WARNING: Partition has name '%s' which is a partition subtype, but this partition has non-matching type 0x%x and subtype 0x%x. Mistake in partition table?" % (self.name, self.type, self.subtype)) + critical("WARNING: Partition has name '%s' which is a partition subtype, but this partition has " + "non-matching type 0x%x and subtype 0x%x. Mistake in partition table?" % (self.name, self.type, self.subtype)) STRUCT_FORMAT = b"<2sBBLL16sL" @@ -365,21 +376,21 @@ def from_binary(cls, b): res = cls() (magic, res.type, res.subtype, res.offset, res.size, res.name, flags) = struct.unpack(cls.STRUCT_FORMAT, b) - if b"\x00" in res.name: # strip null byte padding from name string + if b"\x00" in res.name: # strip null byte padding from name string res.name = res.name[:res.name.index(b"\x00")] res.name = res.name.decode() if magic != cls.MAGIC_BYTES: raise InputError("Invalid magic bytes (%r) for partition definition" % magic) for flag,bit in cls.FLAGS.items(): - if flags & (1<?nkt_#R(bU}~Dm2qC{|!;OZMOE)%9?k_ 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 tU*~@LPg?i+Z#o?|EFV`UaHOs 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 diff --git a/tools/sdk/bin/bootloader_dio_80m.bin b/tools/sdk/bin/bootloader_dio_80m.bin index 726e1ca9145c7ee894b1f4c8587d7b9b683d1502..5b22ceb78581d614fe4ed44dd67812e8c73759f6 100644 GIT binary patch delta 10250 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�=&!`Eq0cJ7FX3V(Bd?1?$k^ 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 D$|dt3 diff --git a/tools/sdk/bin/bootloader_dout_40m.bin b/tools/sdk/bin/bootloader_dout_40m.bin index eab1e96d1f50bb4718805292a647224b6e97ca22..c91272bdca0ed8de1ee759d7742b2de022733839 100644 GIT binary patch delta 10250 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 diff --git a/tools/sdk/bin/bootloader_dout_80m.bin b/tools/sdk/bin/bootloader_dout_80m.bin index 4d1f69f44c1bc23fcee0bbff232d6bd2a8cb321c..daee693cdce307ba309e5cfd827bbdca42417f08 100644 GIT binary patch delta 10250 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 D*CF&? diff --git a/tools/sdk/bin/bootloader_qio_40m.bin b/tools/sdk/bin/bootloader_qio_40m.bin index 0c2e9fe279a6330dc8997fd2524171066180bfdc..46ddab04dbdd981cc0c128455b80d9f1386b8542 100644 GIT binary patch delta 10964 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 delta 10214 zcmZu%3w#q**1t1J(@8o&(w2gK$V_NTTUtyCLd!$i3I!BbgtegJ%EML^KOcY#Dw^DY zZCZ+SI;^%VtVuLdDivB(@WI-mvWRpA-|OcCb*uQ;wJTuLyyiP+GA-bK{rx60=YJme z+;i_ebMKj++{U;(%>Gk4XX`MobUR#zW}Px~7bzw04k2DZeg;Ij8~97$GPVM8j4Znd z*$ap;s#sBi!0$pk1pXBKD+Q_mF6IMoVrf5IpTcz-u5aP`7hG%azIVO6K<`Zn+6WQs z=VpSE4z%xX{5mA-5(|;0{fY_{%B?;U9FfI+ttG zuf_Vk!HSWD|7BeBYSFInx$bh}E@x;yYPWLMeMHDNk8crLP`QQUiz+OHh&c*BS`!ph zL8m5}aY52*NF?;Ki_Hufv7!f7Iue;4&Q+IPo$HWNR8b>MR$OgnYEfMEs=r3`!$^k% zZC+-zxU7ig8EbAM)pI9G22IJCpla!Vqs9D2t70JpwR(v|3dZ7Q`(xPHudz!TI}7wB zjm;wTeC#wwDtDOQ^OBQ2LZ>%@e}(=BF@9LjFy5KLKScknl01*kKMk?Q^Y!#Qjf2m< zL!4{*Hu{yu!RIfBIMetY^iz$4&!6CP$GfW2N%S~6EuDxpwqY#xBz3$Kb7FUr03O2r z78kx4dgH&L*DpXj)DcdSI#tLB5%6`yyq=2(;rZXhrRr*u1+$w>E_0IV(_G zVvRe@;86>QZgJ9HpjGP}ZHtR+eESj!K5tMUtB*dVS!wueO>l zIh(U3KaGq}xUL?I``aA#M&(<$Y-bb8yV+qbkEPKgoG9jX(1DF-%@!fhL9FcXaj!5N z&lc)5pL3Ga8p?C5Tn(#w0?WQGn$@@Qm#jYVF?fJ}Ehi-mpHOibOaYu^Wylg*Sy zJzQGNE;c^j|8(@$(x098U~r zhm*dKG`?zX@)JZ2m_NFEcMsVHuu$gXyudP-KXU1 zQ%3SVz|dy{f2D=Quks)ILAr9@E_ejUF{2m}sZ`e##8zGjXT9&mp>p z^EIioi9Q8>#|3@cH0aM4AZOg#pe>(A6Ok{7JgPyBLr@1rs5ObYBKQKTkHEMk0#cVm z>*Oa=FLy3e`JCj645m1g=cHSPXf-dmtxVb(Vm~0Xv%QDNiH9!D8_UUq49wygk@!@f zuHF+X^biNSI^wGJHu(scZQ(N3yS>W#*6-;R5!YI?-G0tFbyC@tk!x_RxU6P%d9Xc+ z>dGxZD;E$xosL7qAx7*u=4JMCtC*>iRYjT^aorf#P3U1&-K-&974dr+IvSy}x!B!e z{oN~si5TgU(R#;hgv!SfAsZ3vN?feNBXWJ(xUo|rJLIy-ktZjan~r4*E#B6W@y$ZZ z{$ukF>!c#&IU@20X}M!QQQBGCfP#st!xr%kgl$hNGfZiBaXk#55%9|yqaJeF{0atb zDA#rqzm=r@VC=Lqj!5|6M7G98s+v)4s<9xUC*iQk>=Wp(Veq;qq4Rz7%|3b-iFRFJ zmr~4B>-5DmN2f2c=A2lYYfURMU}^)E-t|h_&5XZWs9LWy94}_(Qv0m6Nwb`MioryX z|A3OVgOrOTX%?SSkw8GQcb$^f1`t>NrUDr3nRGihS*?dxH~w>uT)d^jf5aSkS4q2uZ1LH8 z6?`LvmC_erTG$I@_YOGi6X)uS{_-Qw&0T1lD(9$lyVR{wFv)fKSej7#fP z>0(R68>;kiRoZr1DSwlJkW88MNoO|)ZS@|Dw^e2NLOJ3ie9{&leFiLJs}1*V=StU*Atb z5GuPryeLO*{KE`L|4R|e!?~;=Olo-V)OF$Rc_6yW zR~D|?!~sL?W=`@saBoiBJ#qRVn0k(9YxLxFlV!)%v^ZQ}*UAMl<)70xJH_Wisv^w{ zyWD0mBd#H(hZ~#BVmeZ-tao3+={8H__6Pb}ERa-P+t$G@BB$7xv%!=zI!RqY@HXR% z;DQwe5yBnHe?mK&++N1l7kcs)*6k&(#&z_EP`wqg??dC_m>_p%q!cQl+M;ypSa_Sm zK1K zLy(L+(5`dqh}HZ3xaI_&Jqnok_Yj2MHbrSj7vBLfNDeS{?N1B6vlZ`D;Y8cfEYj)a zd`Cl7zgOs+A$KlG`y@t>$jzA(j4y>eoPir z`6~h)b(fVM@d`qx0E^}m1>KoUNrApc51Ejmo)FCM!whctjwu~GL+wl;qO|I)W2fY| z9oGAgpSG1i&gsz~X6TbBT4>s7>ewD?*V#f!yRP>tMQjLNmDLCIRjO@_H6%z0WoMXR z*?yt?)JE$=;|>*8FUoazLQ{+As?d}}V;r^cIOWhNM~(b!)_8N(G^H}1Z&=Sa9M-od z1`fzyWsPP7|B%C34tsTIP7eP+%!-d(b8_yjNW>|hMpuSv$1%KN*|K#og3=#CbMkOh zYin-ooh&cCeBQ7bI8f8n@QYLB&dX=4UQ1S`+&?9B$3eDY1yL7!yPlfS(N^6a{k6B> zDe+mE4a;5ahon}0 z)kzfoA$6fXA(LBth&{T1EYZt<7$Y)OvTMv_r|s?7iQ_%`LuKuWRoy6h*RX}zQ;Nni zix03hMPy+%akvJij7;8nuPjf{_XE_%;Y77Vw8ne(&kFXXxJspffN9l9kGj3^~?oVImavS>Iwyt^2K39gK0+ z`^syktt`)~QFN{F78?>*B;No2z=lMaP4}OYR|sXJ{yH$!uuY0*MF`Y0@+-m^XVn+# z_I9$!I1UeNNa0O;^fOF`EV6&4<*tQIBMCh;P}^czHS&%rtC!eru3UU@i6I>#M(BY7 zm+M?@%hX6dzP38h(H_HL7G~f+d_D|sq$RW+A2a#R?j^?q^v_6~n98Rg)f1}^4gCFSKI(1*f#%UR7+jn??(q>I971gZX9|zU4`ab^pPS&uHP!1(vA2e;?(tXi7 zps|S-&i73a?ojynI*5gj`v;ve%~?|--K{kc391dO9&7;pGHHH&B;RKp?d(A-(1Q~w zDZUfDSaPrjf5RSRT+)NO|UeiE`_IE88{YF4W~O)}=40G2z7TgF+q-Sso`gqk+$gFjg1i6~l1aw5`$<-UJ18 z=s2nFlJ-5Qo^-MEbeE=M85q*p7}pUWR-ucOzA#(L3XA}UVzi;v>^pkiyu1yx{BYcE2 z&xb+!ZXBiYxqz)7O#m(Fq&&fvGv>{>AgXu81*NVaeOc2vD6h4RWnPq@wBbHvT4U&2y1-aXh6 zM{N*ZBmY!rEkZB@YJ&3Pxx{uCg`$yb6GD-d`p5y6N&GxV1)sHA)ok8_E*5(i8mc(;HL(vlq-VtHnd^Qg+imy z<%B2b@A8WvoUDO1_2mjdI?VRyKG)NQDB$6wnZd?Z^OHO7q<`;6M>t98zceot2Z!>) zb*KY*;n{x73loEb1yL1s?<0shef=;Kr+Hj1+}i-B&LouwX(_6^+WqYq!) zXvH`p-KHrw4t1Z-M8VIB<6*gg8-`<#7oogAkI=ic*4%dz--ie`?Iig1{Wi=3mRN3rtS*9`JX! z_n&I-_df0J&5KnYA>wnW;9sE@-l~&%u@&h(uz>)*YAY`WE~3S!FA#ESVS(v!q+v;K z@0YJBOgBBIkq!OwJ%#DxH)`bOes~qw?b+Umj6Ggd=T!4_ohI-|zkHzZ3e)XKg70U3 zm47OqV4r_S>>Z;EVzZ7#dWo?Sb6`w!;Jb!@Mc*2Hw(baJ$y;C4v0|9miw5 zsj6+D3S^!gpvSQG+ssL7$sLx;(RkhXO8VANE!nneATS|lyMeSby&ov;OyFnOwW|kq z^}s+$=KPLVWAF+)E-#y8b9TmfRyec3E)ZeW0s_CwQwkaB`54_Bt9^OcsrFcRdu(Zv zuRT^(z)0bQ-W7vG^sZP{ zF5_#CbvMVnC%X6~dYAgi0cxVP>O(qxOatQgbh=5Sci>%=)qb~#X`(ltTnlIbKv{;(FqzNkS%@(>k z*2+M>g-q^VP6A!T>rFjb&q#Lw3`J2_o3MuoyalNKG@vUkLJwI2m4j1`-imD<%9WPl zy(JfZS~o~H4}P53pwh+C;!6SP_k&+6RDovc1}OcTr3Hg%GpaR9*U394XFBJ^gq>!s z{JNpxPf3r7SI1xr2lW-66N|Cg)=p_=tg+clufi#%y_!0CBR{&dZWHp?ENEtE@kPuv z4cn7uQAf-*OSPjHbI?w+pBBbko6ThfvC?^F*DPF_^RoQ#TeLzD^I}$(Nh?p-+gp~7 z(o5DkVo~|`Q*vexM{@2O$MBea5)Ns}8l>Gt`-n!n9R^iICt6}cws0LD3G#H5An4)7 z1<#3K>GdfG(%PbMW*s)b4}%jY%clqa7ml+wUiK7^(eH}(8s+DT#ZkwwRDP@JrToO@ z9ax=SW$xeKK#di35id;A`89a%M^1sJ&6BrFyMGJhzH# zqL3|mV?lXo$>@>3=#CvtM*WjJ9Vc5Yt~OWS4$D_N<+_qWrcpjvGEa1><#JYhGz#B4 zg`sp9bs|4Z9lkJluC@Ry2B2PkJnOKcq31s>1cD`#l!_ zzNa*BNz^4DnVQNhl0TlhEK!IG9znFrS5323DXaF^$ z@gu8~4SYsHePAbXj8PlZiI;=2*~*L+hQ6ojq){r*D2|Tvviq#e;IRz7G>XZ{$fbhK zRyw3+6xGiR9@a4|YA;sPJPy2vO?H?7P-hBjWrRqlm?)P_AD3o(n0WJrqr*w>zaSU9 zmRh~6s8{=vK(|J;9Gn16H7C$TKx5zP654gtgSB^cr$>?|LhjxiNdbUv zRNaE)%6^;j9bGB6UUdbtM*ifgLT9h7U)v(lKWG8CedvP(ScQNr{|$ZPZ|Ft8p)-I+ zhv1k4BSo)QU1A~grPKNNOlN7{tokX-q1E*0JgxD$zcDsjGd39Xa{0xXb5o&-CTyaG z!(9Y!BcuY^Qkv?_jlj`zT-^Tp4Jp!C)vS^J7>;kWVb`hcJETmFl?7jF)OVUOb1Tnx zdi8#9HN6ZSEf~gU;s&9bjzsc3?+$)`*J}a-76c&U?Tzz?X(V?dP8;RDrQ(VKwdBf4 z1iT%ZIJuk@#S-i#-b2O2ZeN#{Y!G`;r>aW(N%&D=laN6XT(T2*CsK8png zbzi(`Fr=bS?kLMJ?m!8c25-tAmgSAwic}rz_Z86H@g^YnqDLNCE;t**(BM}1fw6|2 zq4air>Vdf2S2`z!HQ31V zJCU)(P$q{_WN$qiSd z`l^Jod%~p^s$v2^mEI&Txq7AL+PK!bL9IFRiK~U#GZFpVz)z2xnx>L^ercSXf@I(; z<;2vbc<%Lky)+jgaYDER_r>wfjF26(Y)pZ?c-8~goW_E@N9WoyGH0|E|F@^Oh9?da zx>Yom*zMbk-e3Y}6?^>=*znXO6URPOP+6&IE18@WF=y=fDo(L+a@y>2<6EjZPWnk+ zK0D2M7^ys154fi;D1(pV#A<;U)2{{@agW+r`XyFseg8nb+2r1f$K<32f=~GaYtMSCYr^ENay0=nhqrbDRj-OK=`TZ6n|eD&H1m(mx@qm=j+Q z!Dl~lZb%r5kw&+m1ogPaJft#jxtIw~FXd{JEpD&3HaXet?W;{r#k0UU*p~BiA!G9C z{M;G_!_2z9iPDW|YLC(PAl?s|q^F&s#y^`EsQ(24NS(>I203t)eI|re0QikB8g;xo*imbsx-B2s#?*Inxs14YQ%79>B4uDCc6b>oo2dqNZ7X^ z)calBucHzp_*bW~tnEC?;IdndhCM9QgG+DlSj2lm`5x(xP@~81 za(@UFdm+~y7sM}vzx~@*D*f$sC3Ae4bXop;5ApwaZT<^)zWv7e557P9^U0#BZP(xX Ee_9fPI{*Lx diff --git a/tools/sdk/bin/bootloader_qio_80m.bin b/tools/sdk/bin/bootloader_qio_80m.bin index 944f4947edf5a1186b77fa734d62a9ede153e890..ddc2b8983d86f7182dc086401ff0b2444bf63c97 100644 GIT binary patch delta 11013 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 delta 10231 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 E1D%|T9smFU diff --git a/tools/sdk/bin/bootloader_qout_40m.bin b/tools/sdk/bin/bootloader_qout_40m.bin index 07a6be715c063be4b0156f385d0d7c13c88bed09..0c0aaed10ef9bb6de1f59ff0c4de9397906bfc07 100644 GIT binary patch delta 10964 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 delta 10214 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 delta 10231 zcmZu%3w#q**1t1J+etb=(v|{!$V_NTDJ>-B)$(jBl!vg3uogsI0c}NbeE=@3vL-h? zn%1J74z4W=YZ8r=N`)2`)Md9tL`1rRPd-0&Q8$Xu?JC$buldfIObfVQf4|Ax^FNP! z?(59G=eFl@rl*EEbWZ1J8N`+Df+w*_r_9<*O3B*;hzF2=1ESmm{N?Z%S^zmkR$YZ0 z07Mv8tSCX?ccL8ve+vGU0#yJH^PVTEv=^R_;JEN}R-B z_9vBsRp$QBL$hQqsdRb)SkuEph@J>sbOM^q5P|G~xToX&|q z7wZoMD~1yO$I(seM4Q6rxyp&FoT2%s-NIQ85+UC-wpnOK{u-ahu;VsTJ#T`Ps3|!TR4x54w3uILRV;x{tzK@Ig0Z;S-WXQ)bL`s6eggWM z%4QRKId*{~mAg&vc*xmqp~I8Fze4|m7(b|c5bwz3AEG~~B+p~{y8+f%zK(vSaj+a1 z;M~Bs($6#wmj5}xna1y?A88ycpT~0h+p5#a^fWpxoryKHVqfe}ZhtH0z~&?aJb=9s z7rq*L?Z2VFUx9Y3Bb+RCsE`4Az}p`4xUU|B=YP>JRo9bjnB8P@nS)fP%%O)=RZcn> zYuIf9kD57ji<1rjty<@3Yg}Z@o7YJ2WBLWMd+1Y|mHJ;;*?YxGvu35F--_CPj<3C9 z2E78Oa-~OASp%&@=fR&^gH#)bww&rmvU?<|iQRie%&CbLUl9YF^dW@Z+?k>R1I*(r z11v15@IeG?4O({)aYIa4Qz{601VG8z$OtVD(tB~tqHc=XN zb2X{6cq5c>c^IiveUDr?_!FD1>)|M$+?GtYAXa}GxDR6qtr9{vL`yh;evgoCa_8#% z<-ZLP9cz*Fc?i7|3#BK7W4bohznUpDg6tiLwXsz{DcF^2XP2#tmg`C7#Kf}OqEjZW zF1smOT5b}Ym+B_aTcULnY_`jww-oi@y#(J;9XO}&x+(74uMnzl1?D0wEmOzANEfIY z!|n5!%g=QlbksN>B!n{Cc-be--_ zZ?^n`dE#O-!Vo1*(f&Y22dfY#4T?5Euz+7}1)?A)83$;}pL$Nml3EnI)gadu!=dwqzzjra65xYdAQq#g3RsWTkU#GUdyhvfZ8cSEy>gw!4FVf1ja21klJKg zEB`6&I>#!N&q>Zme~3eQPP%1)R^x)p!lYj$w!=aj8#qeNJalc`SWW)Gz$~5-iBI+E z>N}}I5B)&bMVvLBMlS)g&0OXtmq*#u@--bFac(f#Y?mBUCzef$EWowmw3yW8!FDI9 zE4KixTtWB@IvNqX7_sG=R@pACWu{J66=_z)c~e|Bp_^58vj=ol#OGn?aD>X{VRMW1 z_pA{nU{99}*W2eHR6dFbIfz(p$Hh80BG;vl9yKMhTP~X%d2*tu@l=k`>}e?(+axp} zIyL{8PAWp4JtDuCo;UKm(#Bf*6bw}D)`+(+Y<*gpVNAc9>t^^&zfaB__K?HsQ?Szp zVr>`kSxEXfh7Jp3kA#m*V0TzaRTHXBH54RtCmb`HyaN3>3|@C9bi8X?;iW$z(Wdk7 zRf?HvoxYgn>hwjH+%p^UEa^pw7}`K3ut`Z@!T7p_s!dA$>0)Lcwawm;JlnyiCK?Iy zA5_wJlX8(H&*oDr5(r2JHY(|@0CD9f6u@B5q}#LAV#yV9K99#?%fY?bJ?am-ACI9h z!7=*0jXuHHbmQCi^hLT23({Z0bW0ezvzbd&uwPimmVeEaiyv+G9XI*kR?-)cN4?g7 zf?tHNQu+c+D{B(j&%A7Qo9jOai9z5+I!acR9O zU2Lv@O_e^aN?R`|vnHW7~w1nB$YbY)UsJh-eTl_|`* z+rwRVhdVq@@9kme$Uq&J{zY=xN_j@cNXKpAu3Ld6dn=LUui@Hn3B$LnN1=&rn82WHeFz*BG!jyX7>O+Q?-qK4FOU@*%?My zwx25BwbHuK=%ao@WB$MkJU z{=@QT*~3}?|H$ENyRAAjH<$k%v*rWm+}!&rl5onW)7wKeqZvMN)vAp!g3@n8bI0JQ z*6g?`Fj-!C-TXl_aG<8C-7ij+JFc6tZUb4H`oNUXok!S;HAG$PZF*`#M_Y9J^*7vc zm&9jh)vtO<2;?fiGgf|-zDA$9Cq1xN`J*xYp%Gd2N2RL2C^&NKJ!HvhMRO>leR>kki{)K%AQc)_X$;dlp=j*`c~GLLyB^y zOl>VlhLQ2}_%#S674XN5KF@{LXXqP!&={BkDN5xBiMf^=U?LRuSYBsKEr%=?9gK0+ zyUJgUJ6WDpd(pYZQ=FKzCh389`!*-RYO=2YIeUq8c`m`x7dZoYd-<4{76_SH0-*ABgN%DUy&6_v}5EKkgU9wYQ{ zpVN7%rg>^4A3s~|=xBH1F&1XvK`bAGFVb?_hQ%ztqigwTKm9WjXQuKQC-ubQg~LEz zLbbeHv^jS7IU7wi%^StheGm?sSh}LmS*z}g*f=c%jT^99R$@`aZ4jA0!EF+E_6d2& z7=wp-w*iw1fJTBAmQ1q+Ka#{>ON8RxDqk?zqdhy>LN*7a9_ei=2tK9KLX40m*+6==a3 zloa0zUM<<*f;X@Qnb)-7*IEVtj92h#zgl+BS8Jw8N8?7dijJWA!`Ge=FNG9dqA+&X%~2_^{fGhJkq?C2GF@N&aC}#=QH3E{^%@@Cp;* z4K#{6jcbY28l+(?H*>U4wZm1;Q|M(ZHgWDHF!^d3HnFS9!)5Ll1!eK|P}+BrSAtmQY2UWJ~I*W=u3mOj8D zoO#|4(zoL%jn4(F{bT}YNoVD8*4&XN;)1B&85fi~gY;!h=ZL()I*NHwe$txnfHTK) zLF*4nhi4LeXQ(#_E6g>Dz%jg57eBRP_=YX~w+d}S{UT`n;voGKmZ2x8j0I>?WwCQpuMZFf^f3>Th)&%bkZ@lTla~cEhSi$Oq}L+I&p6UoLZw)9;BtH+RUBY0;B)oMYduo zkvg!#iw5r(y`JZ>@%u5h0WAbQ&!ggg!=@mcm`~_Vv>4e85FF4y?d|U>Z@%WvR@I#$ zad*~Yg`lvSS$-b_t-qpD2)-?rR`6(?Wa6z^b7t)^Gb9y{z; zh9FIdR|MasuhtHc5`&b91L_u6(gkT0D{tnc^_mlPSDd(v5OnCTR3|=>#r&a;`B>@0 zS65mwnn<^4$_)d}r?XJ-mH_!4T zoMYtv{iO7_UixZWPd$M{z&g@TlF6{tC6$D+o;KiwbQmQ7>KK5)9L(mQ%NO}4CwUJ0 zy4rfrwe@~DZJQ%^nTbtfL^tQ7yVb!;?q|MIjyk3_!!c# zq<8ho3koxg+cmPjSH8C}W9$}<+|~=90-G(zGl8+ilj@vmo^I3x{@5!YE*x*X14;1x z;?MGTh1QG}D#}SzkQCY%9V^3yD2+p3c++7WB%GjuY9l z!{z74{m6WA*gJk1qbJ3LG}?zxSKd&R#oOUNh!BpvZ~_w+Cc&E&kCN6y!9t_!;NF^y zB-rt;R3Mn*;6Qg`YcdRwjGfV*as=)YcClh;{9Yt<3c9i&^s->WkGB4La8n z>+;1`j`jLtfxLd~nON7}7@V;8#{8ohZ&R$RDdsuT$tTmh)%yrYnAWI;47yzd;_nQ) zRik&~Ta?vyv$QeRzbS-lgp4fg50>r(T>WUU-g>!m(sh+zzz(y_iaWFQ1;2 z>9{`zv7~9lex}*n=pl`ej&Cy4b+Hx(f-!`7*J|SLBpy%N**ZqL6JW@gI$MSPjQ@2& z^%nqLa}|2j?62&far9QK>u8>|65q{v@YAwcTG4-Vv00^yrDfLw(r@~&GE{*k=|;F0 zFiDI1(I!-Dk`~E(CTBV3#)Lg4EjPQl{)y!6;`K4u-$C+)=fq;HwxvUw6>DfR(U~}< zwC`32Z{UZQ)^0`q`o&EQExwAmzJ6EoY-*1=XRCJfVlLWg^3lSWbDOEGAXYlxEf-Hxg2wTa%xqg9FW7saE}w?_lIz6&hbr%!=3DfS&p zfUCF{<*br1!wy6t(dw}X@xUvtk3z5r#Den5lHo(W(cQZn4f-ed*w40@ovqHE-R95s z$h9SfOoM!+WWMN7bLp)3NE9wZg}p=RA0f|fa*iE($Ynk|#wpyz@_UHoxI#ZgUD#AE42qw~KTOX^|1bjEWBNg) zrZE8$(18*%dc%^dTLErQXdg(9dOrX&rI0C^)(O;`Bu@Lw&=t3;h*_t=!?{Nk*6X;4KYR?*Di9s)NJQh{tPO>^W$;Mh4jZhzC}RB4oI)nt9pmUqxi&!_KTCLVHnFCep+1+}el zHSr_O-2cdrl%;34sLJd@7LyO^o_TA3mx^Awy)4tP8zo>GoRHry8#8PtQnjqlTR`{4 ztANfI-SW_K!O;+g3U|T}j5X{U#Rt`*Iy!$)jTq?7Fb*cTV7Ea8(UMC(kB;t)n^H$o zyccC5&J`x8hvjl_>D*K{aTK}nE@Z4tD3imb71)^h30cp~O_^1&ZEi|Z*0#BFclrET z$34l~5Uxj??|8QHd*WkqFVcxQFkNn(qZztyzz{!`-hzC&vph?7Uw^%MQCxdtzxI6j zer232LDKrUa%SpEJSF=)9-5DkXbYF%E;`;kvs^aY$`s0X z&VF#g=a{~C>zt1c%^hyR{{$-D!4rEjx>q!c*lfFsUSs?}DYm-fumjqWLhS9Rpt91^ zZ)b8-#oSS21DxXLhvfQRbjtxo5z{?oL#Ed+6!z8`YdbvRvi&n&ym-I?sRx1dI?j_y%4 zIeT}=R)RAdG9i9PQ2DYb3-aJV7jxpN5L^<93qryu9J+Yzv_WHbsmxoiW`ffzxtbKS z%i~dhdumcla5kvA9ODg%7)?e%7dLuXdNbO9SmWKII$@-3A #include "esp_err.h" #include "esp_partition.h" +#include "esp_image_format.h" +#include "esp_flash_data_types.h" #ifdef __cplusplus extern "C" @@ -32,6 +34,10 @@ extern "C" #define ESP_ERR_OTA_PARTITION_CONFLICT (ESP_ERR_OTA_BASE + 0x01) /*!< Error if request was to write or erase the current running partition */ #define ESP_ERR_OTA_SELECT_INFO_INVALID (ESP_ERR_OTA_BASE + 0x02) /*!< Error if OTA data partition contains invalid content */ #define ESP_ERR_OTA_VALIDATE_FAILED (ESP_ERR_OTA_BASE + 0x03) /*!< Error if OTA app image is invalid */ +#define ESP_ERR_OTA_SMALL_SEC_VER (ESP_ERR_OTA_BASE + 0x04) /*!< Error if the firmware has a secure version less than the running firmware. */ +#define ESP_ERR_OTA_ROLLBACK_FAILED (ESP_ERR_OTA_BASE + 0x05) /*!< Error if flash does not have valid firmware in passive partition and hence rollback is not possible */ +#define ESP_ERR_OTA_ROLLBACK_INVALID_STATE (ESP_ERR_OTA_BASE + 0x06) /*!< Error if current active firmware is still marked in pending validation state (ESP_OTA_IMG_PENDING_VERIFY), essentially first boot of firmware image post upgrade and hence firmware upgrade is not possible */ + /** * @brief Opaque handle for an application OTA update @@ -41,6 +47,24 @@ extern "C" */ typedef uint32_t esp_ota_handle_t; +/** + * @brief Return esp_app_desc structure. This structure includes app version. + * + * Return description for running app. + * @return Pointer to esp_app_desc structure. + */ +const esp_app_desc_t *esp_ota_get_app_description(void); + +/** + * @brief Fill the provided buffer with SHA256 of the ELF file, formatted as hexadecimal, null-terminated. + * If the buffer size is not sufficient to fit the entire SHA256 in hex plus a null terminator, + * the largest possible number of bytes will be written followed by a null. + * @param dst Destination buffer + * @param size Size of the buffer + * @return Number of bytes written to dst (including null terminator) + */ +int esp_ota_get_app_elf_sha256(char* dst, size_t size); + /** * @brief Commence an OTA update writing to the specified partition. @@ -52,6 +76,10 @@ typedef uint32_t esp_ota_handle_t; * On success, this function allocates memory that remains in use * until esp_ota_end() is called with the returned handle. * + * Note: If the rollback option is enabled and the running application has the ESP_OTA_IMG_PENDING_VERIFY state then + * it will lead to the ESP_ERR_OTA_ROLLBACK_INVALID_STATE error. Confirm the running app before to run download a new app, + * use esp_ota_mark_app_valid_cancel_rollback() function for it (this should be done as early as possible when you first download a new application). + * * @param partition Pointer to info for partition which will receive the OTA update. Required. * @param image_size Size of new OTA app image. Partition will be erased in order to receive this size of image. If 0 or OTA_SIZE_UNKNOWN, the entire partition is erased. * @param out_handle On success, returns a handle which should be used for subsequent esp_ota_write() and esp_ota_end() calls. @@ -65,6 +93,7 @@ typedef uint32_t esp_ota_handle_t; * - ESP_ERR_OTA_SELECT_INFO_INVALID: The OTA data partition contains invalid data. * - ESP_ERR_INVALID_SIZE: Partition doesn't fit in configured flash size. * - ESP_ERR_FLASH_OP_TIMEOUT or ESP_ERR_FLASH_OP_FAIL: Flash write failed. + * - ESP_ERR_OTA_ROLLBACK_INVALID_STATE: If the running app has not confirmed state. Before performing an update, the application must be valid. */ esp_err_t esp_ota_begin(const esp_partition_t* partition, size_t image_size, esp_ota_handle_t* out_handle); @@ -170,6 +199,83 @@ const esp_partition_t* esp_ota_get_running_partition(void); */ const esp_partition_t* esp_ota_get_next_update_partition(const esp_partition_t *start_from); +/** + * @brief Returns esp_app_desc structure for app partition. This structure includes app version. + * + * Returns a description for the requested app partition. + * @param[in] partition Pointer to app partition. (only app partition) + * @param[out] app_desc Structure of info about app. + * @return + * - ESP_OK Successful. + * - ESP_ERR_NOT_FOUND app_desc structure is not found. Magic word is incorrect. + * - ESP_ERR_NOT_SUPPORTED Partition is not application. + * - ESP_ERR_INVALID_ARG Arguments is NULL or if partition's offset exceeds partition size. + * - ESP_ERR_INVALID_SIZE Read would go out of bounds of the partition. + * - or one of error codes from lower-level flash driver. + */ +esp_err_t esp_ota_get_partition_description(const esp_partition_t *partition, esp_app_desc_t *app_desc); + +/** + * @brief This function is called to indicate that the running app is working well. + * + * @return + * - ESP_OK: if successful. + */ +esp_err_t esp_ota_mark_app_valid_cancel_rollback(); + +/** + * @brief This function is called to roll back to the previously workable app with reboot. + * + * If rollback is successful then device will reset else API will return with error code. + * Checks applications on a flash drive that can be booted in case of rollback. + * If the flash does not have at least one app (except the running app) then rollback is not possible. + * @return + * - ESP_FAIL: if not successful. + * - ESP_ERR_OTA_ROLLBACK_FAILED: The rollback is not possible due to flash does not have any apps. + */ +esp_err_t esp_ota_mark_app_invalid_rollback_and_reboot(); + +/** + * @brief Returns last partition with invalid state (ESP_OTA_IMG_INVALID or ESP_OTA_IMG_ABORTED). + * + * @return partition. + */ +const esp_partition_t* esp_ota_get_last_invalid_partition(); + +/** + * @brief Returns state for given partition. + * + * @param[in] partition Pointer to partition. + * @param[out] ota_state state of partition (if this partition has a record in otadata). + * @return + * - ESP_OK: Successful. + * - ESP_ERR_INVALID_ARG: partition or ota_state arguments were NULL. + * - ESP_ERR_NOT_SUPPORTED: partition is not ota. + * - ESP_ERR_NOT_FOUND: Partition table does not have otadata or state was not found for given partition. + */ +esp_err_t esp_ota_get_state_partition(const esp_partition_t *partition, esp_ota_img_states_t *ota_state); + +/** + * @brief Erase previous boot app partition and corresponding otadata select for this partition. + * + * When current app is marked to as valid then you can erase previous app partition. + * @return + * - ESP_OK: Successful, otherwise ESP_ERR. + */ +esp_err_t esp_ota_erase_last_boot_app_partition(void); + +/** + * @brief Checks applications on the slots which can be booted in case of rollback. + * + * These applications should be valid (marked in otadata as not UNDEFINED, INVALID or ABORTED and crc is good) and be able booted, + * and secure_version of app >= secure_version of efuse (if anti-rollback is enabled). + * + * @return + * - True: Returns true if the slots have at least one app (except the running app). + * - False: The rollback is not possible. + */ +bool esp_ota_check_rollback_is_possible(void); + #ifdef __cplusplus } #endif diff --git a/tools/sdk/include/bootloader_support/bootloader_common.h b/tools/sdk/include/bootloader_support/bootloader_common.h index e884856f6d2..405c94c02b7 100644 --- a/tools/sdk/include/bootloader_support/bootloader_common.h +++ b/tools/sdk/include/bootloader_support/bootloader_common.h @@ -24,21 +24,29 @@ typedef enum { } esp_comm_gpio_hold_t; /** - * @brief Calculate crc for the OTA data partition. + * @brief Calculate crc for the OTA data select. * - * @param[in] ota_data The OTA data partition. + * @param[in] s The OTA data select. * @return Returns crc value. */ uint32_t bootloader_common_ota_select_crc(const esp_ota_select_entry_t *s); /** - * @brief Verifies the validity of the OTA data partition + * @brief Verifies the validity of the OTA data select * - * @param[in] ota_data The OTA data partition. + * @param[in] s The OTA data select. * @return Returns true on valid, false otherwise. */ bool bootloader_common_ota_select_valid(const esp_ota_select_entry_t *s); +/** + * @brief Returns true if OTADATA is not marked as bootable partition. + * + * @param[in] s The OTA data select. + * @return Returns true if OTADATA invalid, false otherwise. + */ +bool bootloader_common_ota_select_invalid(const esp_ota_select_entry_t *s); + /** * @brief Check if the GPIO input is a long hold or a short hold. * @@ -94,25 +102,42 @@ bool bootloader_common_label_search(const char *list, char *label); esp_err_t bootloader_common_get_sha256_of_partition(uint32_t address, uint32_t size, int type, uint8_t *out_sha_256); /** - * @brief Check if the image (bootloader and application) has valid chip ID and revision + * @brief Returns the number of active otadata. * - * @param img_hdr: image header - * @return - * - ESP_OK: image and chip are matched well - * - ESP_FAIL: image doesn't match to the chip + * @param[in] two_otadata Pointer on array from two otadata structures. + * + * @return The number of active otadata (0 or 1). + * - -1: If it does not have active otadata. */ -esp_err_t bootloader_common_check_chip_validity(const esp_image_header_t* img_hdr); +int bootloader_common_get_active_otadata(esp_ota_select_entry_t *two_otadata); +/** + * @brief Returns the number of active otadata. + * + * @param[in] two_otadata Pointer on array from two otadata structures. + * @param[in] valid_two_otadata Pointer on array from two bools. True means select. + * @param[in] max True - will select the maximum ota_seq number, otherwise the minimum. + * + * @return The number of active otadata (0 or 1). + * - -1: If it does not have active otadata. + */ +int bootloader_common_select_otadata(const esp_ota_select_entry_t *two_otadata, bool *valid_two_otadata, bool max); /** - * @brief Configure VDDSDIO, call this API to rise VDDSDIO to 1.9V when VDDSDIO regulator is enabled as 1.8V mode. + * @brief Returns esp_app_desc structure for app partition. This structure includes app version. + * + * Returns a description for the requested app partition. + * @param[in] partition App partition description. + * @param[out] app_desc Structure of info about app. + * @return + * - ESP_OK: Successful. + * - ESP_ERR_INVALID_ARG: The arguments passed are not valid. + * - ESP_ERR_NOT_FOUND: app_desc structure is not found. Magic word is incorrect. + * - ESP_FAIL: mapping is fail. */ -void bootloader_common_vddsdio_configure(); +esp_err_t bootloader_common_get_partition_description(const esp_partition_pos_t *partition, esp_app_desc_t *app_desc); /** - * @brief Set the flash CS setup and hold time. - * - * CS setup time is recomemded to be 1.5T, and CS hold time is recommended to be 2.5T. - * cs_setup = 1, cs_setup_time = 0; cs_hold = 1, cs_hold_time = 1 + * @brief Configure VDDSDIO, call this API to rise VDDSDIO to 1.9V when VDDSDIO regulator is enabled as 1.8V mode. */ -void bootloader_common_set_flash_cs_timing(); +void bootloader_common_vddsdio_configure(); diff --git a/tools/sdk/include/bootloader_support/bootloader_flash_config.h b/tools/sdk/include/bootloader_support/bootloader_flash_config.h new file mode 100644 index 00000000000..2f716cce2a4 --- /dev/null +++ b/tools/sdk/include/bootloader_support/bootloader_flash_config.h @@ -0,0 +1,71 @@ +// Copyright 2018 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 + +#include "esp_image_format.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Update the flash id in g_rom_flashchip(global esp_rom_spiflash_chip_t structure). + * + * @return None + */ +void bootloader_flash_update_id(); + +/** + * @brief Set the flash CS setup and hold time. + * + * @note CS setup time is recomemded to be 1.5T, and CS hold time is recommended to be 2.5T. + * cs_setup = 1, cs_setup_time = 0; cs_hold = 1, cs_hold_time = 1. + * + * @return None + */ +void bootloader_flash_cs_timing_config(); + +/** + * @brief Configure SPI flash clock. + * + * @note This function only set clock frequency for SPI0. + * + * @param pfhdr Pointer to App image header, from where to fetch flash settings. + * + * @return None + */ +void bootloader_flash_clock_config(const esp_image_header_t* pfhdr); + +/** + * @brief Configure SPI flash gpio, include the IO matrix and drive strength configuration. + * + * @param pfhdr Pointer to App image header, from where to fetch flash settings. + * + * @return None + */ +void bootloader_flash_gpio_config(const esp_image_header_t* pfhdr); + +/** + * @brief Configure SPI flash read dummy based on different mode and frequency. + * + * @param pfhdr Pointer to App image header, from where to fetch flash settings. + * + * @return None + */ +void bootloader_flash_dummy_config(const esp_image_header_t* pfhdr); + +#ifdef __cplusplus +} +#endif diff --git a/tools/sdk/include/bootloader_support/esp_efuse.h b/tools/sdk/include/bootloader_support/esp_efuse.h deleted file mode 100644 index 047a971a4c1..00000000000 --- a/tools/sdk/include/bootloader_support/esp_efuse.h +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2015-2016 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. -#ifndef _ESP_EFUSE_H -#define _ESP_EFUSE_H - -#include "soc/efuse_reg.h" -#include "esp_err.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* @brief Permanently update values written to the efuse write registers - * - * After updating EFUSE_BLKx_WDATAx_REG registers with new values to - * write, call this function to permanently write them to efuse. - * - * @note Setting bits in efuse is permanent, they cannot be unset. - * - * @note Due to this restriction you don't need to copy values to - * Efuse write registers from the matching read registers, bits which - * are set in the read register but unset in the matching write - * register will be unchanged when new values are burned. - * - * @note This function is not threadsafe, if calling code updates - * efuse values from multiple tasks then this is caller's - * responsibility to serialise. - * - * After burning new efuses, the read registers are updated to match - * the new efuse values. - */ -void esp_efuse_burn_new_values(void); - -/* @brief Reset efuse write registers - * - * Efuse write registers are written to zero, to negate - * any changes that have been staged here. - */ -void esp_efuse_reset(void); - -/* @brief Disable BASIC ROM Console via efuse - * - * By default, if booting from flash fails the ESP32 will boot a - * BASIC console in ROM. - * - * Call this function (from bootloader or app) to permanently - * disable the console on this chip. - */ -void esp_efuse_disable_basic_rom_console(void); - -/* @brief Encode one or more sets of 6 byte sequences into - * 8 bytes suitable for 3/4 Coding Scheme. - * - * This function is only useful if the CODING_SCHEME efuse - * is set to value 1 for 3/4 Coding Scheme. - * - * @param[in] in_bytes Pointer to a sequence of bytes to encode for 3/4 Coding Scheme. Must have length in_bytes_len. After being written to hardware, these bytes will read back as little-endian words. - * @param[out] out_words Pointer to array of words suitable for writing to efuse write registers. Array must contain 2 words (8 bytes) for every 6 bytes in in_bytes_len. Can be a pointer to efuse write registers. - * @param in_bytes_len. Length of array pointed to by in_bytes, in bytes. Must be a multiple of 6. - * - * @return ESP_ERR_INVALID_ARG if either pointer is null or in_bytes_len is not a multiple of 6. ESP_OK otherwise. - */ -esp_err_t esp_efuse_apply_34_encoding(const uint8_t *in_bytes, uint32_t *out_words, size_t in_bytes_len); - -/* @brief Write random data to efuse key block write registers - * - * @note Caller is responsible for ensuring efuse - * block is empty and not write protected, before calling. - * - * @note Behaviour depends on coding scheme: a 256-bit key is - * generated and written for Coding Scheme "None", a 192-bit key - * is generated, extended to 256-bits by the Coding Scheme, - * and then writtten for 3/4 Coding Scheme. - * - * @note This function does not burn the new values, caller should - * call esp_efuse_burn_new_values() when ready to do this. - * - * @param blk_wdata0_reg Address of the first data write register - * in the block - */ -void esp_efuse_write_random_key(uint32_t blk_wdata0_reg); - -/** - * @brief Returns chip version from efuse - * - * @return chip version - */ -uint8_t esp_efuse_get_chip_ver(void); - -#ifdef __cplusplus -} -#endif - -#endif /* __ESP_EFUSE_H */ - diff --git a/tools/sdk/include/bootloader_support/esp_image_format.h b/tools/sdk/include/bootloader_support/esp_image_format.h index 0e2bb5283dd..7006cae98d4 100644 --- a/tools/sdk/include/bootloader_support/esp_image_format.h +++ b/tools/sdk/include/bootloader_support/esp_image_format.h @@ -55,19 +55,6 @@ typedef enum { #define ESP_IMAGE_HEADER_MAGIC 0xE9 -/** - * @brief ESP chip ID - * - */ -typedef enum { - ESP_CHIP_ID_ESP32 = 0x0000, /*!< chip ID: ESP32 */ - ESP_CHIP_ID_INVALID = 0xFFFF /*!< Invalid chip ID (we defined it to make sure the esp_chip_id_t is 2 bytes size) */ -} __attribute__((packed)) esp_chip_id_t; - -/** @cond */ -_Static_assert(sizeof(esp_chip_id_t) == 2, "esp_chip_id_t should be 16 bit"); - - /* Main header of binary image */ typedef struct { uint8_t magic; @@ -84,12 +71,8 @@ typedef struct { uint8_t wp_pin; /* Drive settings for the SPI flash pins (read by ROM bootloader) */ uint8_t spi_pin_drv[3]; - /*!< Chip identification number */ - esp_chip_id_t chip_id; - /*!< Minimum chip revision supported by image */ - uint8_t min_chip_rev; - /*!< Reserved bytes in additional header space, currently unused */ - uint8_t reserved[8]; + /* Reserved bytes in ESP32 additional header space, currently unused */ + uint8_t reserved[11]; /* If 1, a SHA256 digest "simple hash" (of the entire image) is appended after the checksum. Included in image length. This digest * is separate to secure boot and only used for detecting corruption. For secure boot signed images, the signature * is appended after this (and the simple hash is included in the signed data). */ @@ -106,6 +89,25 @@ typedef struct { uint32_t data_len; } esp_image_segment_header_t; +#define ESP_APP_DESC_MAGIC_WORD 0xABCD5432 /*!< The magic word for the esp_app_desc structure that is in DROM. */ + +/** + * @brief Description about application. + */ +typedef struct { + uint32_t magic_word; /*!< Magic word ESP_APP_DESC_MAGIC_WORD */ + uint32_t secure_version; /*!< Secure version */ + uint32_t reserv1[2]; /*!< --- */ + char version[32]; /*!< Application version */ + char project_name[32]; /*!< Project name */ + char time[16]; /*!< Compile time */ + char date[16]; /*!< Compile date*/ + char idf_ver[32]; /*!< Version IDF */ + uint8_t app_elf_sha256[32]; /*!< sha256 of elf file */ + uint32_t reserv2[20]; /*!< --- */ +} esp_app_desc_t; +_Static_assert(sizeof(esp_app_desc_t) == 256, "esp_app_desc_t should be 256 bytes"); + #define ESP_IMAGE_MAX_SEGMENTS 16 /* Structure to hold on-flash image metadata */ diff --git a/tools/sdk/include/bootloader_support/esp_secure_boot.h b/tools/sdk/include/bootloader_support/esp_secure_boot.h index 370bdd36332..17b405e4fab 100644 --- a/tools/sdk/include/bootloader_support/esp_secure_boot.h +++ b/tools/sdk/include/bootloader_support/esp_secure_boot.h @@ -46,6 +46,25 @@ static inline bool esp_secure_boot_enabled(void) { return REG_READ(EFUSE_BLK0_RDATA6_REG) & EFUSE_RD_ABS_DONE_0; } +/** @brief Generate secure digest from bootloader image + * + * @important This function is intended to be called from bootloader code only. + * + * If secure boot is not yet enabled for bootloader, this will: + * 1) generate the secure boot key and burn it on EFUSE + * (without enabling R/W protection) + * 2) generate the digest from bootloader and save it + * to flash address 0x0 + * + * If first boot gets interrupted after calling this function + * but before esp_secure_boot_permanently_enable() is called, then + * the key burned on EFUSE will not be regenerated, unless manually + * done using espefuse.py tool + * + * @return ESP_OK if secure boot digest is generated + * successfully or found to be already present + */ +esp_err_t esp_secure_boot_generate_digest(void); /** @brief Enable secure boot if it is not already enabled. * @@ -54,9 +73,13 @@ static inline bool esp_secure_boot_enabled(void) { * * @important This function is intended to be called from bootloader code only. * + * @important This will enable r/w protection of secure boot key on EFUSE, + * therefore it is to be ensured that esp_secure_boot_generate_digest() + * is called before this + * * If secure boot is not yet enabled for bootloader, this will - * generate the secure boot digest and enable secure boot by blowing - * the EFUSE_RD_ABS_DONE_0 efuse. + * 1) enable R/W protection of secure boot key on EFUSE + * 2) enable secure boot by blowing the EFUSE_RD_ABS_DONE_0 efuse. * * This function does not verify secure boot of the bootloader (the * ROM bootloader does this.) @@ -64,7 +87,6 @@ static inline bool esp_secure_boot_enabled(void) { * Will fail if efuses have been part-burned in a way that indicates * secure boot should not or could not be correctly enabled. * - * * @return ESP_ERR_INVALID_STATE if efuse state doesn't allow * secure boot to be enabled cleanly. ESP_OK if secure boot * is enabled on this chip from now on. diff --git a/tools/sdk/include/bt/esp_bt.h b/tools/sdk/include/bt/esp_bt.h index a0648645ccf..1ee7edf9525 100644 --- a/tools/sdk/include/bt/esp_bt.h +++ b/tools/sdk/include/bt/esp_bt.h @@ -117,7 +117,7 @@ the adv packet will be discarded until the memory is restored. */ .mode = BTDM_CONTROLLER_MODE_EFF, \ .ble_max_conn = CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN_EFF, \ .bt_max_acl_conn = CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN_EFF, \ - .bt_sco_datapath = CONFIG_BTDM_CONTROLLER_BR_EDR_SCO_DATA_PATH_EFF, \ + .bt_sco_datapath = CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF, \ .bt_max_sync_conn = CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN_EFF, \ .magic = ESP_BT_CONTROLLER_CONFIG_MAGIC_VAL, \ }; diff --git a/tools/sdk/include/bt/esp_gap_ble_api.h b/tools/sdk/include/bt/esp_gap_ble_api.h index ff30f5f354a..12bc48f1b10 100644 --- a/tools/sdk/include/bt/esp_gap_ble_api.h +++ b/tools/sdk/include/bt/esp_gap_ble_api.h @@ -54,6 +54,7 @@ typedef uint8_t esp_ble_key_type_t; #define ESP_LE_AUTH_NO_BOND 0x00 /*!< 0*/ /* relate to BTM_LE_AUTH_NO_BOND in stack/btm_api.h */ #define ESP_LE_AUTH_BOND 0x01 /*!< 1 << 0 */ /* relate to BTM_LE_AUTH_BOND in stack/btm_api.h */ #define ESP_LE_AUTH_REQ_MITM (1 << 2) /*!< 1 << 2 */ /* relate to BTM_LE_AUTH_REQ_MITM in stack/btm_api.h */ +#define ESP_LE_AUTH_REQ_BOND_MITM (ESP_LE_AUTH_BOND | ESP_LE_AUTH_REQ_MITM)/*!< 0101*/ #define ESP_LE_AUTH_REQ_SC_ONLY (1 << 3) /*!< 1 << 3 */ /* relate to BTM_LE_AUTH_REQ_SC_ONLY in stack/btm_api.h */ #define ESP_LE_AUTH_REQ_SC_BOND (ESP_LE_AUTH_BOND | ESP_LE_AUTH_REQ_SC_ONLY) /*!< 1001 */ /* relate to BTM_LE_AUTH_REQ_SC_BOND in stack/btm_api.h */ #define ESP_LE_AUTH_REQ_SC_MITM (ESP_LE_AUTH_REQ_MITM | ESP_LE_AUTH_REQ_SC_ONLY) /*!< 1100 */ /* relate to BTM_LE_AUTH_REQ_SC_MITM in stack/btm_api.h */ @@ -63,6 +64,9 @@ typedef uint8_t esp_ble_auth_req_t; /*!< combination of the above bit #define ESP_BLE_ONLY_ACCEPT_SPECIFIED_AUTH_DISABLE 0 #define ESP_BLE_ONLY_ACCEPT_SPECIFIED_AUTH_ENABLE 1 +#define ESP_BLE_OOB_DISABLE 0 +#define ESP_BLE_OOB_ENABLE 1 + /* relate to BTM_IO_CAP_xxx in stack/btm_api.h */ #define ESP_IO_CAP_OUT 0 /*!< DisplayOnly */ /* relate to BTM_IO_CAP_OUT in stack/btm_api.h */ #define ESP_IO_CAP_IO 1 /*!< DisplayYesNo */ /* relate to BTM_IO_CAP_IO in stack/btm_api.h */ @@ -263,14 +267,26 @@ typedef enum { typedef enum { ESP_BLE_SM_PASSKEY = 0, + /* Authentication requirements of local device */ ESP_BLE_SM_AUTHEN_REQ_MODE, + /* The IO capability of local device */ ESP_BLE_SM_IOCAP_MODE, + /* Initiator Key Distribution/Generation */ ESP_BLE_SM_SET_INIT_KEY, + /* Responder Key Distribution/Generation */ ESP_BLE_SM_SET_RSP_KEY, + /* Maximum Encryption key size to support */ ESP_BLE_SM_MAX_KEY_SIZE, + /* Minimum Encryption key size requirement from Peer */ + ESP_BLE_SM_MIN_KEY_SIZE, + /* Set static Passkey */ ESP_BLE_SM_SET_STATIC_PASSKEY, + /* Reset static Passkey */ ESP_BLE_SM_CLEAR_STATIC_PASSKEY, + /* Accept only specified SMP Authentication requirement */ ESP_BLE_SM_ONLY_ACCEPT_SPECIFIED_SEC_AUTH, + /* Enable/Disable OOB support */ + ESP_BLE_SM_OOB_SUPPORT, ESP_BLE_SM_MAX_PARAM, } esp_ble_sm_param_t; @@ -584,7 +600,7 @@ typedef enum { typedef enum { ESP_BLE_DUPLICATE_SCAN_EXCEPTIONAL_INFO_ADV_ADDR = 0, /*!< BLE advertising address , device info will be added into ESP_BLE_DUPLICATE_SCAN_EXCEPTIONAL_ADDR_LIST */ ESP_BLE_DUPLICATE_SCAN_EXCEPTIONAL_INFO_MESH_LINK_ID, /*!< BLE mesh link ID, it is for BLE mesh, device info will be added into ESP_BLE_DUPLICATE_SCAN_EXCEPTIONAL_MESH_LINK_ID_LIST */ - ESP_BLE_DUPLICATE_SCAN_EXCEPTIONAL_INFO_MESH_BEACON_TYPE, /*!< BLE mesh beacon AD type, the format is | Len | 0x2B | Beacon Type | Beacon Data | */ + ESP_BLE_DUPLICATE_SCAN_EXCEPTIONAL_INFO_MESH_BEACON_TYPE, /*!< BLE mesh beacon AD type, the format is | Len | 0x2B | Beacon Type | Beacon Data | */ ESP_BLE_DUPLICATE_SCAN_EXCEPTIONAL_INFO_MESH_PROV_SRV_ADV, /*!< BLE mesh provisioning service uuid, the format is | 0x02 | 0x01 | flags | 0x03 | 0x03 | 0x1827 | .... |` */ ESP_BLE_DUPLICATE_SCAN_EXCEPTIONAL_INFO_MESH_PROXY_SRV_ADV, /*!< BLE mesh adv with proxy service uuid, the format is | 0x02 | 0x01 | flags | 0x03 | 0x03 | 0x1828 | .... |` */ } esp_ble_duplicate_exceptional_info_type_t; @@ -1145,7 +1161,7 @@ esp_err_t esp_ble_passkey_reply(esp_bd_addr_t bd_addr, bool accept, uint32_t pas /** -* @brief Reply the confirm value to the peer device in the legacy connection stage. +* @brief Reply the confirm value to the peer device in the secure connection stage. * * @param[in] bd_addr : BD address of the peer device * @param[in] accept : numbers to compare are the same or different. @@ -1194,6 +1210,20 @@ int esp_ble_get_bond_device_num(void); */ esp_err_t esp_ble_get_bond_device_list(int *dev_num, esp_ble_bond_dev_t *dev_list); +/** +* @brief This function is called to provide the OOB data for +* SMP in response to ESP_GAP_BLE_OOB_REQ_EVT +* +* @param[in] bd_addr: BD address of the peer device. +* @param[in] TK: TK value, the TK value shall be a 128-bit random number +* @param[in] len: length of tk, should always be 128-bit +* +* @return - ESP_OK : success +* - other : failed +* +*/ +esp_err_t esp_ble_oob_req_reply(esp_bd_addr_t bd_addr, uint8_t *TK, uint8_t len); + #endif /* #if (SMP_INCLUDED == TRUE) */ /** diff --git a/tools/sdk/include/config/sdkconfig.h b/tools/sdk/include/config/sdkconfig.h index 444fb1a682a..9ff93dedb29 100644 --- a/tools/sdk/include/config/sdkconfig.h +++ b/tools/sdk/include/config/sdkconfig.h @@ -24,6 +24,7 @@ #define CONFIG_SPIFFS_USE_MAGIC_LENGTH 1 #define CONFIG_ESPTOOLPY_FLASHSIZE_4MB 1 #define CONFIG_IPC_TASK_STACK_SIZE 1024 +#define CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES 16 #define CONFIG_FATFS_PER_FILE_CACHE 1 #define CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY 1 #define CONFIG_ESPTOOLPY_FLASHFREQ "40m" @@ -65,6 +66,7 @@ #define CONFIG_MBEDTLS_PEM_WRITE_C 1 #define CONFIG_BT_SPP_ENABLED 1 #define CONFIG_BT_RESERVE_DRAM 0xdb5c +#define CONFIG_APP_COMPILE_TIME_DATE 1 #define CONFIG_CXX_EXCEPTIONS 1 #define CONFIG_D2WD_PSRAM_CLK_IO 9 #define CONFIG_FATFS_FS_LOCK 0 @@ -81,12 +83,14 @@ #define CONFIG_SPIRAM_SUPPORT 1 #define CONFIG_LWIP_MAX_SOCKETS 10 #define CONFIG_LWIP_NETIF_LOOPBACK 1 +#define CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT "pthread" #define CONFIG_EMAC_TASK_PRIORITY 20 #define CONFIG_TIMER_TASK_STACK_DEPTH 2048 #define CONFIG_TCP_MSS 1436 #define CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED 1 #define CONFIG_BTDM_CONTROLLER_MODE_BTDM 1 #define CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN_EFF 3 +#define CONFIG_EFUSE_CODE_SCHEME_COMPAT_3_4 1 #define CONFIG_TCPIP_TASK_AFFINITY_CPU0 1 #define CONFIG_FATFS_CODEPAGE 850 #define CONFIG_SPIRAM_SPIWP_SD3_PIN 7 @@ -124,12 +128,15 @@ #define CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE 1 #define CONFIG_SPIRAM_BANKSWITCH_ENABLE 1 #define CONFIG_MBEDTLS_X509_CRL_PARSE_C 1 +#define CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER 1 #define CONFIG_HTTPD_PURGE_BUF_LEN 32 #define CONFIG_SCAN_DUPLICATE_BY_DEVICE_ADDR 1 +#define CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER 1 #define CONFIG_MB_SERIAL_TASK_STACK_SIZE 2048 #define CONFIG_MBEDTLS_PSK_MODES 1 #define CONFIG_GATTS_SEND_SERVICE_CHANGE_AUTO 1 #define CONFIG_LWIP_DHCPS_LEASE_UNIT 60 +#define CONFIG_EFUSE_MAX_BLK_LEN 192 #define CONFIG_SPIFFS_USE_MAGIC 1 #define CONFIG_OV7725_SUPPORT 1 #define CONFIG_TCPIP_TASK_STACK_SIZE 2560 @@ -174,6 +181,7 @@ #define CONFIG_MDNS_MAX_SERVICES 10 #define CONFIG_ULP_COPROC_ENABLED 1 #define CONFIG_HFP_AUDIO_DATA_PATH_PCM 1 +#define CONFIG_IDF_TARGET_ESP32 1 #define CONFIG_EMAC_CHECK_LINK_PERIOD_MS 2000 #define CONFIG_BTDM_LPCLK_SEL_MAIN_XTAL 1 #define CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED 1 @@ -203,6 +211,7 @@ #define CONFIG_ESP32_WIFI_MGMT_SBUF_NUM 32 #define CONFIG_PARTITION_TABLE_SINGLE_APP 1 #define CONFIG_XTENSA_IMPL 1 +#define CONFIG_UNITY_ENABLE_FLOAT 1 #define CONFIG_ESP32_WIFI_RX_BA_WIN 16 #define CONFIG_MBEDTLS_X509_CSR_PARSE_C 1 #define CONFIG_SPIFFS_USE_MTIME 1 @@ -223,7 +232,6 @@ #define CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V 1 #define CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY 2000 #define CONFIG_BROWNOUT_DET_LVL 0 -#define CONFIG_BTDM_CONTROLLER_BR_EDR_SCO_DATA_PATH_PCM 1 #define CONFIG_MBEDTLS_PEM_PARSE_C 1 #define CONFIG_SPIFFS_GC_MAX_RUNS 10 #define CONFIG_ARDUINO_RUN_CORE1 1 @@ -249,6 +257,7 @@ #define CONFIG_D2WD_PSRAM_CS_IO 10 #define CONFIG_MBEDTLS_TLS_ENABLED 1 #define CONFIG_LWIP_MAX_RAW_PCBS 16 +#define CONFIG_BTU_TASK_STACK_SIZE 4096 #define CONFIG_SMP_ENABLE 1 #define CONFIG_SPIRAM_SIZE -1 #define CONFIG_MBEDTLS_SSL_SESSION_TICKETS 1 @@ -286,23 +295,25 @@ #define CONFIG_PPP_PAP_SUPPORT 1 #define CONFIG_MBEDTLS_TLS_CLIENT 1 #define CONFIG_BTDM_CONTROLLER_HCI_MODE_VHCI 1 -#define CONFIG_BTDM_CONTROLLER_BR_EDR_SCO_DATA_PATH_EFF 1 #define CONFIG_BT_ENABLED 1 +#define CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY 1 #define CONFIG_D0WD_PSRAM_CLK_IO 17 +#define CONFIG_BT_SSP_ENABLED 1 #define CONFIG_SW_COEXIST_PREFERENCE_BALANCE 1 #define CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED 1 #define CONFIG_MONITOR_BAUD 115200 +#define CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT -1 #define CONFIG_ESP32_DEBUG_STUBS_ENABLE 1 #define CONFIG_BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT 30 #define CONFIG_TCPIP_LWIP 1 #define CONFIG_REDUCE_PHY_TX_POWER 1 #define CONFIG_BOOTLOADER_WDT_TIME_MS 9000 #define CONFIG_FREERTOS_CORETIMER_0 1 -#define CONFIG_IDF_FIRMWARE_CHIP_ID 0x0000 #define CONFIG_PARTITION_TABLE_CUSTOM_FILENAME "partitions.csv" #define CONFIG_MBEDTLS_HAVE_TIME 1 #define CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY 1 #define CONFIG_TCP_QUEUE_OOSEQ 1 +#define CONFIG_FATFS_ALLOC_PREFER_EXTRAM 1 #define CONFIG_GATTS_ENABLE 1 #define CONFIG_CXX_EXCEPTIONS_EMG_POOL_SIZE 0 #define CONFIG_ADC_CAL_EFUSE_VREF_ENABLE 1 @@ -315,10 +326,12 @@ #define CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK 1 #define CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_PSK 1 #define CONFIG_OPENSSL_ASSERT_DO_NOTHING 1 +#define CONFIG_IDF_TARGET "esp32" #define CONFIG_WL_SECTOR_SIZE_4096 1 #define CONFIG_OPTIMIZATION_LEVEL_DEBUG 1 #define CONFIG_FREERTOS_NO_AFFINITY 0x7FFFFFFF #define CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED 1 +#define CONFIG_HTTPD_ERR_RESP_NO_DELAY 1 #define CONFIG_MB_TIMER_INDEX 0 #define CONFIG_SCAN_DUPLICATE_TYPE 0 #define CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED 1 @@ -352,13 +365,15 @@ #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_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF 0 #define CONFIG_TASK_WDT_PANIC 1 #define CONFIG_OV3660_SUPPORT 1 +#define CONFIG_UNITY_ENABLE_DOUBLE 1 #define CONFIG_BLE_ADV_REPORT_DISCARD_THRSHOLD 20 #define CONFIG_BLUEDROID_PINNED_TO_CORE 0 #define CONFIG_BTDM_MODEM_SLEEP_MODE_ORIG 1 #define CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_ERROR 1 #define CONFIG_ESP32_WIFI_IRAM_OPT 1 #define CONFIG_FATFS_API_ENCODING_ANSI_OEM 1 -#define CONFIG_ARDUINO_IDF_COMMIT "d3e562907" -#define CONFIG_ARDUINO_IDF_BRANCH "release/v3.2" +#define CONFIG_ARDUINO_IDF_COMMIT "46b12a560" +#define CONFIG_ARDUINO_IDF_BRANCH "release/v3.3" diff --git a/tools/sdk/include/driver/driver/can.h b/tools/sdk/include/driver/driver/can.h index af7b66e0b57..da0613aaca6 100644 --- a/tools/sdk/include/driver/driver/can.h +++ b/tools/sdk/include/driver/driver/can.h @@ -19,6 +19,7 @@ extern "C" { #endif +#include "freertos/FreeRTOS.h" #include "esp_types.h" #include "esp_intr.h" #include "esp_err.h" @@ -105,7 +106,7 @@ extern "C" { #define CAN_EXTD_ID_MASK 0x1FFFFFFF /**< Bit mask for 29 bit Extended Frame Format ID */ #define CAN_STD_ID_MASK 0x7FF /**< Bit mask for 11 bit Standard Frame Format ID */ #define CAN_MAX_DATA_LEN 8 /**< Maximum number of data bytes in a CAN2.0B frame */ -#define CAN_IO_UNUSED (-1) /**< Marks GPIO as unused in CAN configuration */ +#define CAN_IO_UNUSED ((gpio_num_t) -1) /**< Marks GPIO as unused in CAN configuration */ /** @endcond */ /* ----------------------- Enum and Struct Definitions ---------------------- */ @@ -392,6 +393,34 @@ esp_err_t can_initiate_recovery(); */ esp_err_t can_get_status_info(can_status_info_t *status_info); +/** + * @brief Clear the transmit queue + * + * This function will clear the transmit queue of all messages. + * + * @note The transmit queue is automatically cleared when can_stop() or + * can_initiate_recovery() is called. + * + * @return + * - ESP_OK: Transmit queue cleared + * - ESP_ERR_INVALID_STATE: CAN driver is not installed or TX queue is disabled + */ +esp_err_t can_clear_transmit_queue(); + +/** + * @brief Clear the receive queue + * + * This function will clear the receive queue of all messages. + * + * @note The receive queue is automatically cleared when can_start() is + * called. + * + * @return + * - ESP_OK: Transmit queue cleared + * - ESP_ERR_INVALID_STATE: CAN driver is not installed + */ +esp_err_t can_clear_receive_queue(); + #ifdef __cplusplus } #endif diff --git a/tools/sdk/include/driver/driver/i2s.h b/tools/sdk/include/driver/driver/i2s.h index 1f73e1f5566..6179ec3c15f 100644 --- a/tools/sdk/include/driver/driver/i2s.h +++ b/tools/sdk/include/driver/driver/i2s.h @@ -189,6 +189,14 @@ typedef struct { int data_in_num; /*!< DATA in pin*/ } i2s_pin_config_t; +/** + * @brief I2S PDM RX downsample mode + */ +typedef enum { + I2S_PDM_DSR_8S = 0, /*!< downsampling number is 8 for PDM RX mode*/ + I2S_PDM_DSR_16S, /*!< downsampling number is 16 for PDM RX mode*/ + I2S_PDM_DSR_MAX, +} i2s_pdm_dsr_t; typedef intr_handle_t i2s_isr_handle_t; /** @@ -215,6 +223,25 @@ typedef intr_handle_t i2s_isr_handle_t; */ esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin); +/** + * @brief Set PDM mode down-sample rate + * In PDM RX mode, there would be 2 rounds of downsample process in hardware. + * In the first downsample process, the sampling number can be 16 or 8. + * In the second downsample process, the sampling number is fixed as 8. + * So the clock frequency in PDM RX mode would be (fpcm * 64) or (fpcm * 128) accordingly. + * @param i2s_num I2S_NUM_0, I2S_NUM_1 + * @param dsr i2s RX down sample rate for PDM mode. + * + * @note After calling this function, it would call i2s_set_clk inside to update the clock frequency. + * Please call this function after I2S driver has been initialized. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM Out of memory + */ +esp_err_t i2s_set_pdm_rx_down_sample(i2s_port_t i2s_num, i2s_pdm_dsr_t dsr); + /** * @brief Set I2S dac mode, I2S built-in DAC is disabled by default * @@ -476,6 +503,16 @@ esp_err_t i2s_zero_dma_buffer(i2s_port_t i2s_num); */ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t bits, i2s_channel_t ch); +/** + * @brief get clock set on particular port number. + * + * @param i2s_num I2S_NUM_0, I2S_NUM_1 + * + * @return + * - actual clock set by i2s driver + */ +float i2s_get_clk(i2s_port_t i2s_num); + /** * @brief Set built-in ADC mode for I2S DMA, this function will initialize ADC pad, * and set ADC parameters. diff --git a/tools/sdk/include/driver/driver/rmt.h b/tools/sdk/include/driver/driver/rmt.h index bf6632f5d1e..87916b3756b 100644 --- a/tools/sdk/include/driver/driver/rmt.h +++ b/tools/sdk/include/driver/driver/rmt.h @@ -80,6 +80,19 @@ typedef enum { RMT_CARRIER_LEVEL_MAX } rmt_carrier_level_t; +typedef enum { + RMT_CHANNEL_UNINIT = 0, /*!< RMT channel uninitialized */ + RMT_CHANNEL_IDLE = 1, /*!< RMT channel status idle */ + RMT_CHANNEL_BUSY = 2, /*!< RMT channel status busy */ +} rmt_channel_status_t; + +/** + * @brief Data struct of RMT channel status + */ +typedef struct { + rmt_channel_status_t status[RMT_CHANNEL_MAX]; /*!< Store the current status of each channel */ +} rmt_channel_status_result_t; + /** * @brief Data struct of RMT TX configure parameters */ @@ -479,6 +492,7 @@ esp_err_t rmt_get_idle_level(rmt_channel_t channel, bool* idle_out_en, rmt_idle_ * * @param channel RMT channel (0-7) * @param status Pointer to accept channel status. + * Please refer to RMT_CHnSTATUS_REG(n=0~7) in `rmt_reg.h` for more details of each field. * * @return * - ESP_ERR_INVALID_ARG Parameter error @@ -650,6 +664,19 @@ esp_err_t rmt_driver_install(rmt_channel_t channel, size_t rx_buf_size, int intr */ esp_err_t rmt_driver_uninstall(rmt_channel_t channel); +/** + * @brief Get the current status of eight channels. + * + * @note Do not call this function if it is possible that `rmt_driver_uninstall` will be called at the same time. + * + * @param[out] channel_status store the current status of each channel + * + * @return + * - ESP_ERR_INVALID_ARG Parameter is NULL + * - ESP_OK Success + */ +esp_err_t rmt_get_channel_status(rmt_channel_status_result_t *channel_status); + /** * @brief RMT send waveform from rmt_item array. * diff --git a/tools/sdk/include/driver/driver/spi_common.h b/tools/sdk/include/driver/driver/spi_common.h index b3a92613616..c2d645566e9 100644 --- a/tools/sdk/include/driver/driver/spi_common.h +++ b/tools/sdk/include/driver/driver/spi_common.h @@ -42,11 +42,11 @@ extern "C" * * Then points tx_buffer to ``&data``. * - * @param data Data to be sent, can be uint8_t, uint16_t or uint32_t. @param - * len Length of data to be sent, since the SPI peripheral sends from the MSB, - * this helps to shift the data to the MSB. + * @param DATA Data to be sent, can be uint8_t, uint16_t or uint32_t. + * @param LEN Length of data to be sent, since the SPI peripheral sends from + * the MSB, this helps to shift the data to the MSB. */ -#define SPI_SWAP_DATA_TX(data, len) __builtin_bswap32((uint32_t)data<<(32-len)) +#define SPI_SWAP_DATA_TX(DATA, LEN) __builtin_bswap32((uint32_t)(DATA)<<(32-(LEN))) /** * Transform received data of length <= 32 bits to the format of an unsigned integer. @@ -55,11 +55,11 @@ extern "C" * * uint16_t data = SPI_SWAP_DATA_RX(*(uint32_t*)t->rx_data, 15); * - * @param data Data to be rearranged, can be uint8_t, uint16_t or uint32_t. - * @param len Length of data received, since the SPI peripheral writes from + * @param DATA Data to be rearranged, can be uint8_t, uint16_t or uint32_t. + * @param LEN Length of data received, since the SPI peripheral writes from * the MSB, this helps to shift the data to the LSB. */ -#define SPI_SWAP_DATA_RX(data, len) (__builtin_bswap32(data)>>(32-len)) +#define SPI_SWAP_DATA_RX(DATA, LEN) (__builtin_bswap32(DATA)>>(32-(LEN))) /** * @brief Enum with the three SPI peripherals that are software-accessible in it @@ -101,9 +101,32 @@ typedef struct { * Call this if your driver wants to manage a SPI peripheral. * * @param host Peripheral to claim + * @param source The caller indentification string. + * * @return True if peripheral is claimed successfully; false if peripheral already is claimed. */ -bool spicommon_periph_claim(spi_host_device_t host); +bool spicommon_periph_claim(spi_host_device_t host, const char* source); + +// The macro is to keep the back-compatibility of IDF v3.2 and before +// In this way we can call spicommon_periph_claim with two arguments, or the host with the source set to the calling function name +// When two arguments (host, func) are given, __spicommon_periph_claim2 is called +// or if only one arguments (host) is given, __spicommon_periph_claim1 is called +#define spicommon_periph_claim(host...) __spicommon_periph_claim(host, 2, 1) +#define __spicommon_periph_claim(host, source, n, ...) __spicommon_periph_claim ## n(host, source) +#define __spicommon_periph_claim1(host, _) ({ \ + char* warning_str = "calling spicommon_periph_claim without source string is deprecated.";\ + spicommon_periph_claim(host, __FUNCTION__); }) + +#define __spicommon_periph_claim2(host, func) spicommon_periph_claim(host, func) + +/** + * @brief Check whether the spi periph is in use. + * + * @param host Peripheral to check. + * + * @return True if in use, otherwise false. + */ +bool spicommon_periph_in_use(spi_host_device_t host); /** * @brief Return the SPI peripheral so another driver can claim it. @@ -124,6 +147,15 @@ bool spicommon_periph_free(spi_host_device_t host); */ bool spicommon_dma_chan_claim(int dma_chan); +/** + * @brief Check whether the spi DMA channel is in use. + * + * @param dma_chan DMA channel to check. + * + * @return True if in use, otherwise false. + */ +bool spicommon_dma_chan_in_use(int dma_chan); + /** * @brief Return the SPI DMA channel so other driver can claim it, or just to power down DMA. * diff --git a/tools/sdk/include/driver/driver/spi_master.h b/tools/sdk/include/driver/driver/spi_master.h index 46085d6251b..b2acee0d0ec 100644 --- a/tools/sdk/include/driver/driver/spi_master.h +++ b/tools/sdk/include/driver/driver/spi_master.h @@ -168,6 +168,10 @@ typedef struct spi_device_t* spi_device_handle_t; ///< Handle for a device on a * @warning If a DMA channel is selected, any transmit and receive buffer used should be allocated in * DMA-capable memory. * + * @warning The ISR of SPI is always executed on the core which calls this + * function. Never starve the ISR on this core or the SPI transactions will not + * be handled. + * * @return * - ESP_ERR_INVALID_ARG if configuration is invalid * - ESP_ERR_INVALID_STATE if host already is in use diff --git a/tools/sdk/include/driver/driver/spi_slave.h b/tools/sdk/include/driver/driver/spi_slave.h index 546f3b67336..522c9fb8ab0 100644 --- a/tools/sdk/include/driver/driver/spi_slave.h +++ b/tools/sdk/include/driver/driver/spi_slave.h @@ -73,7 +73,10 @@ struct spi_slave_transaction_t { size_t length; ///< Total data length, in bits size_t trans_len; ///< Transaction data length, in bits const void *tx_buffer; ///< Pointer to transmit buffer, or NULL for no MOSI phase - void *rx_buffer; ///< Pointer to receive buffer, or NULL for no MISO phase + void *rx_buffer; /**< Pointer to receive buffer, or NULL for no MISO phase. + * When the DMA is anabled, must start at WORD boundary (``rx_buffer%4==0``), + * and has length of a multiple of 4 bytes. + */ void *user; ///< User-defined variable. Can be used to store eg transaction ID. }; @@ -89,10 +92,14 @@ struct spi_slave_transaction_t { * it. The SPI hardware has two DMA channels to share. This parameter indicates which * one to use. * - * @warning If a DMA channel is selected, any transmit and receive buffer used should be allocated in + * @warning If a DMA channel is selected, any transmit and receive buffer used should be allocated in * DMA-capable memory. * - * @return + * @warning The ISR of SPI is always executed on the core which calls this + * function. Never starve the ISR on this core or the SPI transactions will not + * be handled. + * + * @return * - ESP_ERR_INVALID_ARG if configuration is invalid * - ESP_ERR_INVALID_STATE if host already is in use * - ESP_ERR_NO_MEM if out of memory @@ -104,7 +111,7 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b * @brief Free a SPI bus claimed as a SPI slave interface * * @param host SPI peripheral to free - * @return + * @return * - ESP_ERR_INVALID_ARG if parameter is invalid * - ESP_ERR_INVALID_STATE if not all devices on the bus are freed * - ESP_OK on success @@ -128,7 +135,7 @@ esp_err_t spi_slave_free(spi_host_device_t host); * into the transaction description. * @param ticks_to_wait Ticks to wait until there's room in the queue; use portMAX_DELAY to * never time out. - * @return + * @return * - ESP_ERR_INVALID_ARG if parameter is invalid * - ESP_OK on success */ @@ -138,19 +145,19 @@ esp_err_t spi_slave_queue_trans(spi_host_device_t host, const spi_slave_transact /** * @brief Get the result of a SPI transaction queued earlier * - * This routine will wait until a transaction to the given device (queued earlier with + * This routine will wait until a transaction to the given device (queued earlier with * spi_slave_queue_trans) has succesfully completed. It will then return the description of the - * completed transaction so software can inspect the result and e.g. free the memory or + * completed transaction so software can inspect the result and e.g. free the memory or * re-use the buffers. * * It is mandatory to eventually use this function for any transaction queued by ``spi_slave_queue_trans``. * * @param host SPI peripheral to that is acting as a slave - * @param[out] trans_desc Pointer to variable able to contain a pointer to the description of the + * @param[out] trans_desc Pointer to variable able to contain a pointer to the description of the * transaction that is executed * @param ticks_to_wait Ticks to wait until there's a returned item; use portMAX_DELAY to never time * out. - * @return + * @return * - ESP_ERR_INVALID_ARG if parameter is invalid * - ESP_OK on success */ @@ -161,16 +168,16 @@ esp_err_t spi_slave_get_trans_result(spi_host_device_t host, spi_slave_transacti * @brief Do a SPI transaction * * Essentially does the same as spi_slave_queue_trans followed by spi_slave_get_trans_result. Do - * not use this when there is still a transaction queued that hasn't been finalized + * not use this when there is still a transaction queued that hasn't been finalized * using spi_slave_get_trans_result. * * @param host SPI peripheral to that is acting as a slave - * @param trans_desc Pointer to variable able to contain a pointer to the description of the + * @param trans_desc Pointer to variable able to contain a pointer to the description of the * transaction that is executed. Not const because we may want to write status back * into the transaction description. * @param ticks_to_wait Ticks to wait until there's a returned item; use portMAX_DELAY to never time * out. - * @return + * @return * - ESP_ERR_INVALID_ARG if parameter is invalid * - ESP_OK on success */ diff --git a/tools/sdk/include/driver/driver/uart.h b/tools/sdk/include/driver/driver/uart.h index 93c65c66f39..e716e542458 100644 --- a/tools/sdk/include/driver/driver/uart.h +++ b/tools/sdk/include/driver/driver/uart.h @@ -801,7 +801,7 @@ esp_err_t uart_get_collision_flag(uart_port_t uart_num, bool* collision_flag); * light sleep. This function allows setting the threshold value. * * Stop bit and parity bits (if enabled) also contribute to the number of edges. - * For example, letter 'a' with ASCII code 97 is encoded as 010001101 on the wire + * For example, letter 'a' with ASCII code 97 is encoded as 0100001101 on the wire * (with 8n1 configuration), start and stop bits included. This sequence has 3 * positive edges (transitions from 0 to 1). Therefore, to wake up the system * when 'a' is sent, set wakeup_threshold=3. @@ -813,7 +813,10 @@ esp_err_t uart_get_collision_flag(uart_port_t uart_num, bool* collision_flag); * correct baud rate all the time, select REF_TICK as UART clock source, * by setting use_ref_tick field in uart_config_t to true. * - * @note in ESP32, UART2 does not support light sleep wakeup feature. + * @note in ESP32, the wakeup signal can only be input via IO_MUX (i.e. + * GPIO3 should be configured as function_1 to wake up UART0, + * GPIO9 should be configured as function_5 to wake up UART1), UART2 + * does not support light sleep wakeup feature. * * @param uart_num UART number * @param wakeup_threshold number of RX edges for light sleep wakeup, value is 3 .. 0x3ff. diff --git a/tools/sdk/include/efuse/esp_efuse.h b/tools/sdk/include/efuse/esp_efuse.h new file mode 100644 index 00000000000..68f8491e49e --- /dev/null +++ b/tools/sdk/include/efuse/esp_efuse.h @@ -0,0 +1,362 @@ +// Copyright 2017-2018 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. + +#ifndef _ESP_EFUSE_MANAGER_H_ +#define _ESP_EFUSE_MANAGER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "esp_err.h" +#include "esp_log.h" + +#define ESP_ERR_EFUSE 0x1600 /*!< Base error code for efuse api. */ +#define ESP_OK_EFUSE_CNT (ESP_ERR_EFUSE + 0x01) /*!< OK the required number of bits is set. */ +#define ESP_ERR_EFUSE_CNT_IS_FULL (ESP_ERR_EFUSE + 0x02) /*!< Error field is full. */ +#define ESP_ERR_EFUSE_REPEATED_PROG (ESP_ERR_EFUSE + 0x03) /*!< Error repeated programming of programmed bits is strictly forbidden. */ +#define ESP_ERR_CODING (ESP_ERR_EFUSE + 0x04) /*!< Error while a encoding operation. */ + +/** + * @brief Type of eFuse blocks + */ +typedef enum { + EFUSE_BLK0 = 0, /**< Number of eFuse block. Reserved. */ + EFUSE_BLK1 = 1, /**< Number of eFuse block. Used for Flash Encryption. If not using that Flash Encryption feature, they can be used for another purpose. */ + EFUSE_BLK2 = 2, /**< Number of eFuse block. Used for Secure Boot. If not using that Secure Boot feature, they can be used for another purpose. */ + EFUSE_BLK3 = 3 /**< Number of eFuse block. Uses for the purpose of the user. */ +} esp_efuse_block_t; + +/** + * @brief Type of coding scheme + */ +typedef enum { + EFUSE_CODING_SCHEME_NONE = 0, /**< None */ + EFUSE_CODING_SCHEME_3_4 = 1, /**< 3/4 coding */ + EFUSE_CODING_SCHEME_REPEAT = 2, /**< Repeat coding */ +} esp_efuse_coding_scheme_t; + +/** +* @brief Structure eFuse field + */ +typedef struct { + esp_efuse_block_t efuse_block: 8; /**< Block of eFuse */ + uint8_t bit_start; /**< Start bit [0..255] */ + uint16_t bit_count; /**< Length of bit field [1..-]*/ +} esp_efuse_desc_t; + +/** + * @brief Reads bits from EFUSE field and writes it into an array. + * + * The number of read bits will be limited to the minimum value + * from the description of the bits in "field" structure or "dst_size_bits" required size. + * Use "esp_efuse_get_field_size()" function to determine the length of the field. + * @param[in] field A pointer to the structure describing the fields of efuse. + * @param[out] dst A pointer to array that will contain the result of reading. + * @param[in] dst_size_bits The number of bits required to read. + * If the requested number of bits is greater than the field, + * the number will be limited to the field size. + * + * @return + * - ESP_OK: The operation was successfully completed. + * - ESP_ERR_INVALID_ARG: Error in the passed arguments. + */ +esp_err_t esp_efuse_read_field_blob(const esp_efuse_desc_t* field[], void* dst, size_t dst_size_bits); + +/** + * @brief Reads bits from EFUSE field and returns number of bits programmed as "1". + * + * If the bits are set not sequentially, they will still be counted. + * @param[in] field A pointer to the structure describing the fields of efuse. + * @param[out] out_cnt A pointer that will contain the number of programmed as "1" bits. + * + * @return + * - ESP_OK: The operation was successfully completed. + * - ESP_ERR_INVALID_ARG: Error in the passed arguments. + */ +esp_err_t esp_efuse_read_field_cnt(const esp_efuse_desc_t* field[], size_t* out_cnt); + +/** + * @brief Writes array to EFUSE field. + * + * The number of write bits will be limited to the minimum value + * from the description of the bits in "field" structure or "src_size_bits" required size. + * Use "esp_efuse_get_field_size()" function to determine the length of the field. + * After the function is completed, the writing registers are cleared. + * @param[in] field A pointer to the structure describing the fields of efuse. + * @param[in] src A pointer to array that contains the data for writing. + * @param[in] src_size_bits The number of bits required to write. + * + * @return + * - ESP_OK: The operation was successfully completed. + * - ESP_ERR_INVALID_ARG: Error in the passed arguments. + * - ESP_ERR_EFUSE_REPEATED_PROG: Error repeated programming of programmed bits is strictly forbidden. + * - ESP_ERR_CODING: Error range of data does not match the coding scheme. + */ +esp_err_t esp_efuse_write_field_blob(const esp_efuse_desc_t* field[], const void* src, size_t src_size_bits); + +/** + * @brief Writes a required count of bits as "1" to EFUSE field. + * + * If there are no free bits in the field to set the required number of bits to "1", + * ESP_ERR_EFUSE_CNT_IS_FULL error is returned, the field will not be partially recorded. + * After the function is completed, the writing registers are cleared. + * @param[in] field A pointer to the structure describing the fields of efuse. + * @param[in] cnt Required number of programmed as "1" bits. + * + * @return + * - ESP_OK: The operation was successfully completed. + * - ESP_ERR_INVALID_ARG: Error in the passed arguments. + * - ESP_ERR_EFUSE_CNT_IS_FULL: Not all requested cnt bits is set. + */ +esp_err_t esp_efuse_write_field_cnt(const esp_efuse_desc_t* field[], size_t cnt); + +/** + * @brief Sets a write protection for the whole block. + * + * After that, it is impossible to write to this block. + * The write protection does not apply to block 0. + * @param[in] blk Block number of eFuse. (EFUSE_BLK1, EFUSE_BLK2 and EFUSE_BLK3) + * + * @return + * - ESP_OK: The operation was successfully completed. + * - ESP_ERR_INVALID_ARG: Error in the passed arguments. + * - ESP_ERR_EFUSE_CNT_IS_FULL: Not all requested cnt bits is set. + * - ESP_ERR_NOT_SUPPORTED: The block does not support this command. + */ +esp_err_t esp_efuse_set_write_protect(esp_efuse_block_t blk); + +/** + * @brief Sets a read protection for the whole block. + * + * After that, it is impossible to read from this block. + * The read protection does not apply to block 0. + * @param[in] blk Block number of eFuse. (EFUSE_BLK1, EFUSE_BLK2 and EFUSE_BLK3) + * + * @return + * - ESP_OK: The operation was successfully completed. + * - ESP_ERR_INVALID_ARG: Error in the passed arguments. + * - ESP_ERR_EFUSE_CNT_IS_FULL: Not all requested cnt bits is set. + * - ESP_ERR_NOT_SUPPORTED: The block does not support this command. + */ +esp_err_t esp_efuse_set_read_protect(esp_efuse_block_t blk); + +/** + * @brief Returns the number of bits used by field. + * + * @param[in] field A pointer to the structure describing the fields of efuse. + * + * @return Returns the number of bits used by field. + */ +int esp_efuse_get_field_size(const esp_efuse_desc_t* field[]); + +/** + * @brief Returns value of efuse register. + * + * This is a thread-safe implementation. + * Example: EFUSE_BLK2_RDATA3_REG where (blk=2, num_reg=3) + * @param[in] blk Block number of eFuse. + * @param[in] num_reg The register number in the block. + * + * @return Value of register + */ +uint32_t esp_efuse_read_reg(esp_efuse_block_t blk, unsigned int num_reg); + +/** + * @brief Write value to efuse register. + * + * Apply a coding scheme if necessary. + * This is a thread-safe implementation. + * Example: EFUSE_BLK3_WDATA0_REG where (blk=3, num_reg=0) + * @param[in] blk Block number of eFuse. + * @param[in] num_reg The register number in the block. + * @param[in] val Value to write. + * + * @return + * - ESP_OK: The operation was successfully completed. + * - ESP_ERR_EFUSE_REPEATED_PROG: Error repeated programming of programmed bits is strictly forbidden. + */ +esp_err_t esp_efuse_write_reg(esp_efuse_block_t blk, unsigned int num_reg, uint32_t val); + +/** + * @brief Return efuse coding scheme for blocks. + * + * Note: The coding scheme is applicable only to 1, 2 and 3 blocks. For 0 block, the coding scheme is always ``NONE``. + * + * @param[in] blk Block number of eFuse. + * @return Return efuse coding scheme for blocks + */ +esp_efuse_coding_scheme_t esp_efuse_get_coding_scheme(esp_efuse_block_t blk); + +/** + * @brief Read key to efuse block starting at the offset and the required size. + * + * @param[in] blk Block number of eFuse. + * @param[in] dst_key A pointer to array that will contain the result of reading. + * @param[in] offset_in_bits Start bit in block. + * @param[in] size_bits The number of bits required to read. + * + * @return + * - ESP_OK: The operation was successfully completed. + * - ESP_ERR_INVALID_ARG: Error in the passed arguments. + * - ESP_ERR_CODING: Error range of data does not match the coding scheme. + */ +esp_err_t esp_efuse_read_block(esp_efuse_block_t blk, void* dst_key, size_t offset_in_bits, size_t size_bits); + +/** + * @brief Write key to efuse block starting at the offset and the required size. + * + * @param[in] blk Block number of eFuse. + * @param[in] src_key A pointer to array that contains the key for writing. + * @param[in] offset_in_bits Start bit in block. + * @param[in] size_bits The number of bits required to write. + * + * @return + * - ESP_OK: The operation was successfully completed. + * - ESP_ERR_INVALID_ARG: Error in the passed arguments. + * - ESP_ERR_CODING: Error range of data does not match the coding scheme. + * - ESP_ERR_EFUSE_REPEATED_PROG: Error repeated programming of programmed bits + */ +esp_err_t esp_efuse_write_block(esp_efuse_block_t blk, const void* src_key, size_t offset_in_bits, size_t size_bits); + +/** + * @brief Returns chip version from efuse + * + * @return chip version + */ +uint8_t esp_efuse_get_chip_ver(void); + +/** + * @brief Returns chip package from efuse + * + * @return chip package + */ +uint32_t esp_efuse_get_pkg_ver(void); + +/* @brief Permanently update values written to the efuse write registers + * + * After updating EFUSE_BLKx_WDATAx_REG registers with new values to + * write, call this function to permanently write them to efuse. + * + * @note Setting bits in efuse is permanent, they cannot be unset. + * + * @note Due to this restriction you don't need to copy values to + * Efuse write registers from the matching read registers, bits which + * are set in the read register but unset in the matching write + * register will be unchanged when new values are burned. + * + * @note This function is not threadsafe, if calling code updates + * efuse values from multiple tasks then this is caller's + * responsibility to serialise. + * + * After burning new efuses, the read registers are updated to match + * the new efuse values. + */ +void esp_efuse_burn_new_values(void); + +/* @brief Reset efuse write registers + * + * Efuse write registers are written to zero, to negate + * any changes that have been staged here. + * + * @note This function is not threadsafe, if calling code updates + * efuse values from multiple tasks then this is caller's + * responsibility to serialise. + */ +void esp_efuse_reset(void); + +/* @brief Disable BASIC ROM Console via efuse + * + * By default, if booting from flash fails the ESP32 will boot a + * BASIC console in ROM. + * + * Call this function (from bootloader or app) to permanently + * disable the console on this chip. + */ +void esp_efuse_disable_basic_rom_console(void); + +/* @brief Encode one or more sets of 6 byte sequences into + * 8 bytes suitable for 3/4 Coding Scheme. + * + * This function is only useful if the CODING_SCHEME efuse + * is set to value 1 for 3/4 Coding Scheme. + * + * @param[in] in_bytes Pointer to a sequence of bytes to encode for 3/4 Coding Scheme. Must have length in_bytes_len. After being written to hardware, these bytes will read back as little-endian words. + * @param[out] out_words Pointer to array of words suitable for writing to efuse write registers. Array must contain 2 words (8 bytes) for every 6 bytes in in_bytes_len. Can be a pointer to efuse write registers. + * @param in_bytes_len. Length of array pointed to by in_bytes, in bytes. Must be a multiple of 6. + * + * @return ESP_ERR_INVALID_ARG if either pointer is null or in_bytes_len is not a multiple of 6. ESP_OK otherwise. + */ +esp_err_t esp_efuse_apply_34_encoding(const uint8_t *in_bytes, uint32_t *out_words, size_t in_bytes_len); + +/* @brief Write random data to efuse key block write registers + * + * @note Caller is responsible for ensuring efuse + * block is empty and not write protected, before calling. + * + * @note Behaviour depends on coding scheme: a 256-bit key is + * generated and written for Coding Scheme "None", a 192-bit key + * is generated, extended to 256-bits by the Coding Scheme, + * and then writtten for 3/4 Coding Scheme. + * + * @note This function does not burn the new values, caller should + * call esp_efuse_burn_new_values() when ready to do this. + * + * @param blk_wdata0_reg Address of the first data write register + * in the block + */ +void esp_efuse_write_random_key(uint32_t blk_wdata0_reg); + +/* @brief Return secure_version from efuse field. + * @return Secure version from efuse field + */ +uint32_t esp_efuse_read_secure_version(); + +/* @brief Check secure_version from app and secure_version and from efuse field. + * + * @param secure_version Secure version from app. + * @return + * - True: If version of app is equal or more then secure_version from efuse. + */ +bool esp_efuse_check_secure_version(uint32_t secure_version); + +/* @brief Write efuse field by secure_version value. + * + * Update the secure_version value is available if the coding scheme is None. + * Note: Do not use this function in your applications. This function is called as part of the other API. + * + * @param[in] secure_version Secure version from app. + * @return + * - ESP_OK: Successful. + * - ESP_FAIL: secure version of app cannot be set to efuse field. + * - ESP_ERR_NOT_SUPPORTED: Anti rollback is not supported with the 3/4 and Repeat coding scheme. + */ +esp_err_t esp_efuse_update_secure_version(uint32_t secure_version); + +/* @brief Initializes variables: offset and size to simulate the work of an eFuse. + * + * Note: To simulate the work of an eFuse need to set CONFIG_EFUSE_SECURE_VERSION_EMULATE option + * and to add in the partition.csv file a line `efuse_em, data, efuse, , 0x2000,`. + * + * @param[in] offset The starting address of the partition where the eFuse data will be located. + * @param[in] size The size of the partition. + */ +void esp_efuse_init(uint32_t offset, uint32_t size); + +#ifdef __cplusplus +} +#endif + +#endif // _ESP_EFUSE_MANAGER_H_ diff --git a/tools/sdk/include/efuse/esp_efuse_table.h b/tools/sdk/include/efuse/esp_efuse_table.h new file mode 100644 index 00000000000..a0137c012f3 --- /dev/null +++ b/tools/sdk/include/efuse/esp_efuse_table.h @@ -0,0 +1,69 @@ +// Copyright 2017-2018 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 + +#ifdef __cplusplus +extern "C" { +#endif + + +// md5_digest_table 2e23344575b3d07f01ecb695294e9770 +// This file was generated from the file esp_efuse_table.csv. DO NOT CHANGE THIS FILE MANUALLY. +// If you want to change some fields, you need to change esp_efuse_table.csv file +// then run `efuse_common_table` or `efuse_custom_table` command it will generate this file. +// To show efuse_table run the command 'show_efuse_table'. + + +extern const esp_efuse_desc_t* ESP_EFUSE_MAC_FACTORY[]; +extern const esp_efuse_desc_t* ESP_EFUSE_MAC_FACTORY_CRC[]; +extern const esp_efuse_desc_t* ESP_EFUSE_MAC_CUSTOM_CRC[]; +extern const esp_efuse_desc_t* ESP_EFUSE_MAC_CUSTOM[]; +extern const esp_efuse_desc_t* ESP_EFUSE_MAC_CUSTOM_VER[]; +extern const esp_efuse_desc_t* ESP_EFUSE_SECURE_BOOT_KEY[]; +extern const esp_efuse_desc_t* ESP_EFUSE_ABS_DONE_0[]; +extern const esp_efuse_desc_t* ESP_EFUSE_ENCRYPT_FLASH_KEY[]; +extern const esp_efuse_desc_t* ESP_EFUSE_ENCRYPT_CONFIG[]; +extern const esp_efuse_desc_t* ESP_EFUSE_DISABLE_DL_ENCRYPT[]; +extern const esp_efuse_desc_t* ESP_EFUSE_DISABLE_DL_DECRYPT[]; +extern const esp_efuse_desc_t* ESP_EFUSE_DISABLE_DL_CACHE[]; +extern const esp_efuse_desc_t* ESP_EFUSE_DISABLE_JTAG[]; +extern const esp_efuse_desc_t* ESP_EFUSE_CONSOLE_DEBUG_DISABLE[]; +extern const esp_efuse_desc_t* ESP_EFUSE_FLASH_CRYPT_CNT[]; +extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT[]; +extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_BLK1[]; +extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_BLK2[]; +extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_BLK3[]; +extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_BLK1[]; +extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_BLK2[]; +extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_BLK3[]; +extern const esp_efuse_desc_t* ESP_EFUSE_CHIP_VER_DIS_APP_CPU[]; +extern const esp_efuse_desc_t* ESP_EFUSE_CHIP_VER_DIS_BT[]; +extern const esp_efuse_desc_t* ESP_EFUSE_CHIP_VER_PKG[]; +extern const esp_efuse_desc_t* ESP_EFUSE_CHIP_CPU_FREQ_LOW[]; +extern const esp_efuse_desc_t* ESP_EFUSE_CHIP_CPU_FREQ_RATED[]; +extern const esp_efuse_desc_t* ESP_EFUSE_CHIP_VER_REV1[]; +extern const esp_efuse_desc_t* ESP_EFUSE_CHIP_VER_REV2[]; +extern const esp_efuse_desc_t* ESP_EFUSE_XPD_SDIO_REG[]; +extern const esp_efuse_desc_t* ESP_EFUSE_SDIO_TIEH[]; +extern const esp_efuse_desc_t* ESP_EFUSE_SDIO_FORCE[]; +extern const esp_efuse_desc_t* ESP_EFUSE_ADC_VREF_AND_SDIO_DREF[]; +extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_TP_LOW[]; +extern const esp_efuse_desc_t* ESP_EFUSE_ADC2_TP_LOW[]; +extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_TP_HIGH[]; +extern const esp_efuse_desc_t* ESP_EFUSE_ADC2_TP_HIGH[]; +extern const esp_efuse_desc_t* ESP_EFUSE_SECURE_VERSION[]; + +#ifdef __cplusplus +} +#endif + diff --git a/tools/sdk/include/esp-tls/esp_tls.h b/tools/sdk/include/esp-tls/esp_tls.h index 15830d5a3cc..38538ed0a39 100644 --- a/tools/sdk/include/esp-tls/esp_tls.h +++ b/tools/sdk/include/esp-tls/esp_tls.h @@ -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); diff --git a/tools/sdk/include/esp32/esp_attr.h b/tools/sdk/include/esp32/esp_attr.h index 6d2d5ea84d4..c9e3879eea3 100644 --- a/tools/sdk/include/esp32/esp_attr.h +++ b/tools/sdk/include/esp32/esp_attr.h @@ -14,17 +14,19 @@ #ifndef __ESP_ATTR_H__ #define __ESP_ATTR_H__ +#include "sdkconfig.h" + #define ROMFN_ATTR //Normally, the linker script will put all code and rodata in flash, //and all variables in shared RAM. These macros can be used to redirect //particular functions/variables to other memory regions. -// Forces code into IRAM instead of flash. -#define IRAM_ATTR __attribute__((section(".iram1"))) +// Forces code into IRAM instead of flash +#define IRAM_ATTR _SECTION_ATTR_IMPL(".iram1", __COUNTER__) // Forces data into DRAM instead of flash -#define DRAM_ATTR __attribute__((section(".dram1"))) +#define DRAM_ATTR _SECTION_ATTR_IMPL(".dram1", __COUNTER__) // Forces data to be 4 bytes aligned #define WORD_ALIGNED_ATTR __attribute__((aligned(4))) @@ -37,11 +39,11 @@ #define DRAM_STR(str) (__extension__({static const DRAM_ATTR char __c[] = (str); (const char *)&__c;})) // Forces code into RTC fast memory. See "docs/deep-sleep-stub.rst" -#define RTC_IRAM_ATTR __attribute__((section(".rtc.text"))) +#define RTC_IRAM_ATTR _SECTION_ATTR_IMPL(".rtc.text", __COUNTER__) #if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY // Forces bss variable into external memory. " -#define EXT_RAM_ATTR __attribute__((section(".ext_ram.bss"))) +#define EXT_RAM_ATTR _SECTION_ATTR_IMPL(".ext_ram.bss", __COUNTER__) #else #define EXT_RAM_ATTR #endif @@ -49,26 +51,37 @@ // Forces data into RTC slow memory. See "docs/deep-sleep-stub.rst" // Any variable marked with this attribute will keep its value // during a deep sleep / wake cycle. -#define RTC_DATA_ATTR __attribute__((section(".rtc.data"))) +#define RTC_DATA_ATTR _SECTION_ATTR_IMPL(".rtc.data", __COUNTER__) // Forces read-only data into RTC memory. See "docs/deep-sleep-stub.rst" -#define RTC_RODATA_ATTR __attribute__((section(".rtc.rodata"))) +#define RTC_RODATA_ATTR _SECTION_ATTR_IMPL(".rtc.rodata", __COUNTER__) // Allows to place data into RTC_SLOW memory. -#define RTC_SLOW_ATTR __attribute__((section(".rtc.force_slow"))) +#define RTC_SLOW_ATTR _SECTION_ATTR_IMPL(".rtc.force_slow", __COUNTER__) // Allows to place data into RTC_FAST memory. -#define RTC_FAST_ATTR __attribute__((section(".rtc.force_fast"))) +#define RTC_FAST_ATTR _SECTION_ATTR_IMPL(".rtc.force_fast", __COUNTER__) // Forces data into noinit section to avoid initialization after restart. -#define __NOINIT_ATTR __attribute__((section(".noinit"))) +#define __NOINIT_ATTR _SECTION_ATTR_IMPL(".noinit", __COUNTER__) // Forces data into RTC slow memory of .noinit section. // Any variable marked with this attribute will keep its value // after restart or during a deep sleep / wake cycle. -#define RTC_NOINIT_ATTR __attribute__((section(".rtc_noinit"))) +#define RTC_NOINIT_ATTR _SECTION_ATTR_IMPL(".rtc_noinit", __COUNTER__) // Forces to not inline function #define NOINLINE_ATTR __attribute__((noinline)) +// Implementation for a unique custom section +// +// This prevents gcc producing "x causes a section type conflict with y" +// errors if two variables in the same source file have different linkage (maybe const & non-const) but are placed in the same custom section +// +// Using unique sections also means --gc-sections can remove unused +// data with a custom section type set +#define _SECTION_ATTR_IMPL(SECTION, COUNTER) __attribute__((section(SECTION "." _COUNTER_STRINGIFY(COUNTER)))) + +#define _COUNTER_STRINGIFY(COUNTER) #COUNTER + #endif /* __ESP_ATTR_H__ */ diff --git a/tools/sdk/include/esp32/esp_clk.h b/tools/sdk/include/esp32/esp_clk.h index 1a91d26f91c..99e4f3078c6 100644 --- a/tools/sdk/include/esp32/esp_clk.h +++ b/tools/sdk/include/esp32/esp_clk.h @@ -13,6 +13,7 @@ // limitations under the License. #pragma once +#include /** * @file esp_clk.h diff --git a/tools/sdk/include/esp32/esp_core_dump.h b/tools/sdk/include/esp32/esp_core_dump.h deleted file mode 100644 index c6634364c52..00000000000 --- a/tools/sdk/include/esp32/esp_core_dump.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2015-2016 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. -#ifndef ESP_CORE_DUMP_H_ -#define ESP_CORE_DUMP_H_ - -/** - * @brief Initializes core dump module internal data. - * - * @note Should be called at system startup. - */ -void esp_core_dump_init(); - -/** - * @brief Saves core dump to flash. - * - * The structure of data stored in flash is as follows: - * | MAGIC1 | - * | TOTAL_LEN | TASKS_NUM | TCB_SIZE | - * | TCB_ADDR_1 | STACK_TOP_1 | STACK_END_1 | TCB_1 | STACK_1 | - * . . . . - * . . . . - * | TCB_ADDR_N | STACK_TOP_N | STACK_END_N | TCB_N | STACK_N | - * | MAGIC2 | - * Core dump in flash consists of header and data for every task in the system at the moment of crash. - * For flash data integrity control two magic numbers are used at the beginning and the end of core dump. - * The structure of core dump data is described below in details. - * 1) MAGIC1 and MAGIC2 are special numbers stored at the beginning and the end of core dump. - * They are used to control core dump data integrity. Size of every number is 4 bytes. - * 2) Core dump starts with header: - * 2.1) TOTAL_LEN is total length of core dump data in flash including magic numbers. Size is 4 bytes. - * 2.2) TASKS_NUM is the number of tasks for which data are stored. Size is 4 bytes. - * 2.3) TCB_SIZE is the size of task's TCB structure. Size is 4 bytes. - * 3) Core dump header is followed by the data for every task in the system. - * Task data are started with task header: - * 3.1) TCB_ADDR is the address of TCB in memory. Size is 4 bytes. - * 3.2) STACK_TOP is the top of task's stack (address of the topmost stack item). Size is 4 bytes. - * 3.2) STACK_END is the end of task's stack (address from which task's stack starts). Size is 4 bytes. - * 4) Task header is followed by TCB data. Size is TCB_SIZE bytes. - * 5) Task's stack is placed after TCB data. Size is (STACK_END - STACK_TOP) bytes. - */ -void esp_core_dump_to_flash(); - -/** - * @brief Print base64-encoded core dump to UART. - * - * The structure of core dump data is the same as for data stored in flash (@see esp_core_dump_to_flash) with some notes: - * 1) Magic numbers are not present in core dump printed to UART. - * 2) Since magic numbers are omitted TOTAL_LEN does not include their size. - * 3) Printed base64 data are surrounded with special messages to help user recognize the start and end of actual data. - */ -void esp_core_dump_to_uart(); - -#endif diff --git a/tools/sdk/include/esp32/esp_event_legacy.h b/tools/sdk/include/esp32/esp_event_legacy.h index a2518841819..0ee6046c7ed 100644 --- a/tools/sdk/include/esp32/esp_event_legacy.h +++ b/tools/sdk/include/esp32/esp_event_legacy.h @@ -121,6 +121,10 @@ typedef struct { uint8_t mac[6]; /**< MAC address of the station which send probe request */ } system_event_ap_probe_req_rx_t; +typedef struct { + ip4_addr_t ip; +} system_event_ap_staipassigned_t; + typedef union { system_event_sta_connected_t connected; /**< ESP32 station connected to AP */ system_event_sta_disconnected_t disconnected; /**< ESP32 station disconnected to AP */ @@ -132,6 +136,7 @@ typedef union { system_event_ap_staconnected_t sta_connected; /**< a station connected to ESP32 soft-AP */ system_event_ap_stadisconnected_t sta_disconnected; /**< a station disconnected to ESP32 soft-AP */ system_event_ap_probe_req_rx_t ap_probereqrecved; /**< ESP32 soft-AP receive probe request packet */ + system_event_ap_staipassigned_t ap_staipassigned; /**< ESP32 soft-AP assign an IP to the station*/ system_event_got_ip6_t got_ip6; /**< ESP32 station or ap or ethernet ipv6 addr state change to preferred */ } system_event_info_t; diff --git a/tools/sdk/include/esp32/esp_flash_data_types.h b/tools/sdk/include/esp32/esp_flash_data_types.h index 9a26281b0a8..998e522f068 100644 --- a/tools/sdk/include/esp32/esp_flash_data_types.h +++ b/tools/sdk/include/esp32/esp_flash_data_types.h @@ -24,11 +24,22 @@ extern "C" #define ESP_PARTITION_MAGIC 0x50AA #define ESP_PARTITION_MAGIC_MD5 0xEBEB +/// OTA_DATA states for checking operability of the app. +typedef enum { + ESP_OTA_IMG_NEW = 0x0U, /*!< Monitor the first boot. In bootloader this state is changed to ESP_OTA_IMG_PENDING_VERIFY. */ + ESP_OTA_IMG_PENDING_VERIFY = 0x1U, /*!< First boot for this app was. If while the second boot this state is then it will be changed to ABORTED. */ + ESP_OTA_IMG_VALID = 0x2U, /*!< App was confirmed as workable. App can boot and work without limits. */ + ESP_OTA_IMG_INVALID = 0x3U, /*!< App was confirmed as non-workable. This app will not selected to boot at all. */ + ESP_OTA_IMG_ABORTED = 0x4U, /*!< App could not confirm the workable or non-workable. In bootloader IMG_PENDING_VERIFY state will be changed to IMG_ABORTED. This app will not selected to boot at all. */ + ESP_OTA_IMG_UNDEFINED = 0xFFFFFFFFU, /*!< Undefined. App can boot and work without limits. */ +} esp_ota_img_states_t; + /* OTA selection structure (two copies in the OTA data partition.) Size of 32 bytes is friendly to flash encryption */ typedef struct { uint32_t ota_seq; - uint8_t seq_label[24]; + uint8_t seq_label[20]; + uint32_t ota_state; uint32_t crc; /* CRC32 of ota_seq field only */ } esp_ota_select_entry_t; @@ -61,6 +72,7 @@ typedef struct { #define PART_SUBTYPE_DATA_RF 0x01 #define PART_SUBTYPE_DATA_WIFI 0x02 #define PART_SUBTYPE_DATA_NVS_KEYS 0x04 +#define PART_SUBTYPE_DATA_EFUSE_EM 0x05 #define PART_TYPE_END 0xff #define PART_SUBTYPE_END 0xff diff --git a/tools/sdk/include/esp32/esp_phy_init.h b/tools/sdk/include/esp32/esp_phy_init.h index 2dfb7447da4..6783ff54b47 100644 --- a/tools/sdk/include/esp32/esp_phy_init.h +++ b/tools/sdk/include/esp32/esp_phy_init.h @@ -156,6 +156,18 @@ esp_err_t esp_phy_load_cal_data_from_nvs(esp_phy_calibration_data_t* out_cal_dat */ esp_err_t esp_phy_store_cal_data_to_nvs(const esp_phy_calibration_data_t* cal_data); +/** + * @brief Erase PHY calibration data which is stored in the NVS + * + * This is a function which can be used to trigger full calibration as a last-resort remedy + * if partial calibration is used. It can be called in the application based on some conditions + * (e.g. an option provided in some diagnostic mode). + * + * @return ESP_OK on success + * @return others on fail. Please refer to NVS API return value error number. + */ +esp_err_t esp_phy_erase_cal_data_in_nvs(void); + /** * @brief Initialize PHY and RF module * diff --git a/tools/sdk/include/esp32/esp_wifi_internal.h b/tools/sdk/include/esp32/esp_wifi_internal.h index d41b099db60..468a1809373 100644 --- a/tools/sdk/include/esp32/esp_wifi_internal.h +++ b/tools/sdk/include/esp32/esp_wifi_internal.h @@ -46,6 +46,40 @@ typedef struct { void *storage; /**< storage for FreeRTOS queue */ } wifi_static_queue_t; +/** + * @brief WiFi log level + * + */ +typedef enum { + WIFI_LOG_ERROR = 0, /*enabled by default*/ + WIFI_LOG_WARNING, /*enabled by default*/ + WIFI_LOG_INFO, /*enabled by default*/ + WIFI_LOG_DEBUG, /*can be set in menuconfig*/ + WIFI_LOG_VERBOSE, /*can be set in menuconfig*/ +} wifi_log_level_t; + +/** + * @brief WiFi log module definition + * + */ +typedef enum { + WIFI_LOG_MODULE_ALL = 0, /*all log modules */ + WIFI_LOG_MODULE_WIFI, /*logs related to WiFi*/ + WIFI_LOG_MODULE_COEX, /*logs related to WiFi and BT(or BLE) coexist*/ + WIFI_LOG_MODULE_MESH, /*logs related to Mesh*/ +} wifi_log_module_t; + +/** + * @brief WiFi log submodule definition + * + */ +#define WIFI_LOG_SUBMODULE_ALL (0) /*all log submodules*/ +#define WIFI_LOG_SUBMODULE_INIT (1) /*logs related to initialization*/ +#define WIFI_LOG_SUBMODULE_IOCTL (1<<1) /*logs related to API calling*/ +#define WIFI_LOG_SUBMODULE_CONN (1<<2) /*logs related to connecting*/ +#define WIFI_LOG_SUBMODULE_SCAN (1<<3) /*logs related to scaning*/ + + /** * @brief Initialize Wi-Fi Driver * Alloc resource for WiFi driver, such as WiFi control structure, RX/TX buffer, @@ -245,16 +279,44 @@ typedef esp_err_t (* wifi_mac_time_update_cb_t)( uint32_t time_delta ); esp_err_t esp_wifi_internal_update_mac_time( uint32_t time_delta ); /** - * @brief A general API to set/get WiFi internal configuration, it's for debug only - * - * @param cmd : ioctl command type - * @param cfg : configuration for the command - * - * @return - * - ESP_OK: succeed - * - others: failed - */ -esp_err_t esp_wifi_internal_ioctl(int cmd, wifi_ioctl_config_t *cfg); + * @brief Set current WiFi log level + * + * @param level Log level. + * + * @return + * - ESP_OK: succeed + * - ESP_FAIL: level is invalid + */ +esp_err_t esp_wifi_internal_set_log_level(wifi_log_level_t level); + +/** + * @brief Set current log module and submodule + * + * @param module Log module + * @param submodule Log submodule + * @param enable enable or disable + * If module == 0 && enable == 0, all log modules are disabled. + * If module == 0 && enable == 1, all log modules are enabled. + * If submodule == 0 && enable == 0, all log submodules are disabled. + * If submodule == 0 && enable == 1, all log submodules are enabled. + * + * @return + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init + * - ESP_ERR_WIFI_ARG: invalid argument + */ +esp_err_t esp_wifi_internal_set_log_mod(wifi_log_module_t module, uint32_t submodule, bool enable); + +/** + * @brief Get current WiFi log info + * + * @param log_level the return log level. + * @param log_mod the return log module and submodule + * + * @return + * - ESP_OK: succeed + */ +esp_err_t esp_wifi_internal_get_log(wifi_log_level_t *log_level, uint32_t *log_mod); #ifdef __cplusplus } diff --git a/tools/sdk/include/esp32/rom/crc.h b/tools/sdk/include/esp32/rom/crc.h index 84e17882de5..faa1e8c351b 100644 --- a/tools/sdk/include/esp32/rom/crc.h +++ b/tools/sdk/include/esp32/rom/crc.h @@ -30,15 +30,48 @@ extern "C" { */ -/* Standard CRC8/16/32 algorithms. */ -// CRC-8 x8+x2+x1+1 0x07 -// CRC16-CCITT x16+x12+x5+1 1021 ISO HDLC, ITU X.25, V.34/V.41/V.42, PPP-FCS -// CRC32: -//G(x) = x32 +x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x1 + 1 -//If your buf is not continuous, you can use the first result to be the second parameter. +/* Notes about CRC APIs usage + * The ESP32 ROM include some CRC tables and CRC APIs to speed up CRC calculation. + * The CRC APIs include CRC8, CRC16, CRC32 algorithms for both little endian and big endian modes. + * Here are the polynomials for the algorithms: + * CRC-8 x8+x2+x1+1 0x07 + * CRC16-CCITT x16+x12+x5+1 0x1021 + * CRC32 x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x1+1 0x04c11db7 + * + * These group of CRC APIs are designed to calculate the data in buffers either continuous or not. + * To make it easy, we had added a `~` at the beginning and the end of the functions. + * To calculate non-continuous buffers, we can write the code like this: + * init = ~init; + * crc = crc32_le(init, buf0, length0); + * crc = crc32_le(crc, buf1, length1); + * crc = ~crc; + * + * However, it is not easy to select which API to use and give the correct parameters. + * A specific CRC algorithm will include this parameters: width, polynomials, init, refin, refout, xorout + * refin and refout show the endian of the algorithm: + * if both of them are true, please use the little endian API. + * if both of them are false, please use the big endian API. + * xorout is the value which you need to be xored to the raw result. + * However, these group of APIs need one '~' before and after the APIs. + * + * Here are some examples for CRC16: + * CRC-16/CCITT, poly = 0x1021, init = 0x0000, refin = true, refout = true, xorout = 0x0000 + * crc = ~crc16_le((uint16_t)~0x0000, buf, length); + * + * CRC-16/CCITT-FALSE, poly = 0x1021, init = 0xffff, refin = false, refout = false, xorout = 0x0000 + * crc = ~crc16_be((uint16_t)~0xffff, buf, length); + * + * CRC-16/X25, poly = 0x1021, init = 0xffff, refin = true, refout = true, xorout = 0xffff + * crc = (~crc16_le((uint16_t)~(0xffff), buf, length))^0xffff; + * + * CRC-16/XMODEM, poly= 0x1021, init = 0x0000, refin = false, refout = false, xorout = 0x0000 + * crc = ~crc16_be((uint16_t)~0x0000, buf, length); + * + * + */ /** - * @brief Crc32 value that is in little endian. + * @brief CRC32 value that is in little endian. * * @param uint32_t crc : init crc value, use 0 at the first use. * @@ -51,7 +84,7 @@ extern "C" { uint32_t crc32_le(uint32_t crc, uint8_t const *buf, uint32_t len); /** - * @brief Crc32 value that is in big endian. + * @brief CRC32 value that is in big endian. * * @param uint32_t crc : init crc value, use 0 at the first use. * @@ -64,7 +97,7 @@ uint32_t crc32_le(uint32_t crc, uint8_t const *buf, uint32_t len); uint32_t crc32_be(uint32_t crc, uint8_t const *buf, uint32_t len); /** - * @brief Crc16 value that is in little endian. + * @brief CRC16 value that is in little endian. * * @param uint16_t crc : init crc value, use 0 at the first use. * @@ -77,7 +110,7 @@ uint32_t crc32_be(uint32_t crc, uint8_t const *buf, uint32_t len); uint16_t crc16_le(uint16_t crc, uint8_t const *buf, uint32_t len); /** - * @brief Crc16 value that is in big endian. + * @brief CRC16 value that is in big endian. * * @param uint16_t crc : init crc value, use 0 at the first use. * @@ -90,7 +123,7 @@ uint16_t crc16_le(uint16_t crc, uint8_t const *buf, uint32_t len); uint16_t crc16_be(uint16_t crc, uint8_t const *buf, uint32_t len); /** - * @brief Crc8 value that is in little endian. + * @brief CRC8 value that is in little endian. * * @param uint8_t crc : init crc value, use 0 at the first use. * @@ -103,7 +136,7 @@ uint16_t crc16_be(uint16_t crc, uint8_t const *buf, uint32_t len); uint8_t crc8_le(uint8_t crc, uint8_t const *buf, uint32_t len); /** - * @brief Crc8 value that is in big endian. + * @brief CRC8 value that is in big endian. * * @param uint32_t crc : init crc value, use 0 at the first use. * diff --git a/tools/sdk/include/esp32/rom/spi_flash.h b/tools/sdk/include/esp32/rom/spi_flash.h index 165aaefe66b..a6ed793d6c6 100644 --- a/tools/sdk/include/esp32/rom/spi_flash.h +++ b/tools/sdk/include/esp32/rom/spi_flash.h @@ -118,6 +118,11 @@ extern "C" { #define ESP_ROM_SPIFLASH_WR_PROTECT (ESP_ROM_SPIFLASH_BP0|ESP_ROM_SPIFLASH_BP1|ESP_ROM_SPIFLASH_BP2) #define ESP_ROM_SPIFLASH_QE BIT9 +//Extra dummy for flash read +#define ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_20M 0 +#define ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_40M 1 +#define ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_80M 2 + #define FLASH_ID_GD25LQ32C 0xC86016 typedef enum { diff --git a/tools/sdk/include/esp32/rom/uart.h b/tools/sdk/include/esp32/rom/uart.h index 87224457343..a010bfbca47 100644 --- a/tools/sdk/include/esp32/rom/uart.h +++ b/tools/sdk/include/esp32/rom/uart.h @@ -36,7 +36,7 @@ extern "C" { #define RX_BUFF_SIZE 0x100 #define TX_BUFF_SIZE 100 -//uart int enalbe register ctrl bits +//uart int enable register ctrl bits #define UART_RCV_INTEN BIT0 #define UART_TRX_INTEN BIT1 #define UART_LINE_STATUS_INTEN BIT2 @@ -301,14 +301,14 @@ char uart_rx_one_char_block(void); * * @param uint8_t *pString : the pointer to store the string. * - * @param uint8_t MaxStrlen : the max string length, incude '\0'. + * @param uint8_t MaxStrlen : the max string length, include '\0'. * * @return OK. */ STATUS UartRxString(uint8_t *pString, uint8_t MaxStrlen); /** - * @brief Process uart recevied information in the interrupt handler. + * @brief Process uart received information in the interrupt handler. * Please do not call this function in SDK. * * @param void *para : the message receive buffer. diff --git a/tools/sdk/include/esp_event/esp_event.h b/tools/sdk/include/esp_event/esp_event.h index f095844a72b..f97deaf8b4a 100644 --- a/tools/sdk/include/esp_event/esp_event.h +++ b/tools/sdk/include/esp_event/esp_event.h @@ -33,11 +33,11 @@ extern "C" { /// Configuration for creating event loops typedef struct { int32_t queue_size; /**< size of the event loop queue */ - const char* task_name; /**< name of the event loop task; if NULL, + const char* task_name; /**< name of the event loop task; if NULL, a dedicated task is not created for event loop*/ UBaseType_t task_priority; /**< priority of the event loop task, ignored if task name is NULL */ uint32_t task_stack_size; /**< stack size of the event loop task, ignored if task name is NULL */ - BaseType_t task_core_id; /**< core to which the event loop task is pinned to, + BaseType_t task_core_id; /**< core to which the event loop task is pinned to, ignored if task name is NULL */ } esp_event_loop_args_t; @@ -47,7 +47,7 @@ typedef struct { * @param[in] event_loop_args configuration structure for the event loop to create * @param[out] event_loop handle to the created event loop * - * @return + * @return * - ESP_OK: Success * - ESP_ERR_NO_MEM: Cannot allocate memory for event loops list * - ESP_FAIL: Failed to create task loop @@ -60,7 +60,7 @@ esp_err_t esp_event_loop_create(const esp_event_loop_args_t* event_loop_args, es * * @param[in] event_loop event loop to delete * - * @return + * @return * - ESP_OK: Success * - Others: Fail */ @@ -68,8 +68,8 @@ esp_err_t esp_event_loop_delete(esp_event_loop_handle_t event_loop); /** * @brief Create default event loop - * - * @return + * + * @return * - ESP_OK: Success * - ESP_ERR_NO_MEM: Cannot allocate memory for event loops list * - ESP_FAIL: Failed to create task loop @@ -79,8 +79,8 @@ esp_err_t esp_event_loop_create_default(); /** * @brief Delete the default event loop - * - * @return + * + * @return * - ESP_OK: Success * - Others: Fail */ @@ -89,18 +89,18 @@ esp_err_t esp_event_loop_delete_default(); /** * @brief Dispatch events posted to an event loop. * - * This function is used to dispatch events posted to a loop with no dedicated task, i.e task name was set to NULL - * in event_loop_args argument during loop creation. This function includes an argument to limit the amount of time - * it runs, returning control to the caller when that time expires (or some time afterwards). There is no guarantee - * that a call to this function will exit at exactly the time of expiry. There is also no guarantee that events have + * This function is used to dispatch events posted to a loop with no dedicated task, i.e task name was set to NULL + * in event_loop_args argument during loop creation. This function includes an argument to limit the amount of time + * it runs, returning control to the caller when that time expires (or some time afterwards). There is no guarantee + * that a call to this function will exit at exactly the time of expiry. There is also no guarantee that events have * been dispatched during the call, as the function might have spent all of the alloted time waiting on the event queue. - * Once an event has been unqueued, however, it is guaranteed to be dispatched. This guarantee contributes to not being - * able to exit exactly at time of expiry as (1) blocking on internal mutexes is necessary for dispatching the unqueued - * event, and (2) during dispatch of the unqueued event there is no way to control the time occupied by handler code + * Once an event has been unqueued, however, it is guaranteed to be dispatched. This guarantee contributes to not being + * able to exit exactly at time of expiry as (1) blocking on internal mutexes is necessary for dispatching the unqueued + * event, and (2) during dispatch of the unqueued event there is no way to control the time occupied by handler code * execution. The guaranteed time of exit is therefore the alloted time + amount of time required to dispatch * the last unqueued event. * - * In cases where waiting on the queue times out, ESP_OK is returned and not ESP_ERR_TIMEOUT, since it is + * In cases where waiting on the queue times out, ESP_OK is returned and not ESP_ERR_TIMEOUT, since it is * normal behavior. * * @param[in] event_loop event loop to dispatch posted events from @@ -108,7 +108,7 @@ esp_err_t esp_event_loop_delete_default(); * * @note encountering an unknown event that has been posted to the loop will only generate a warning, not an error. * - * @return + * @return * - ESP_OK: Success * - Others: Fail */ @@ -124,8 +124,8 @@ esp_err_t esp_event_loop_run(esp_event_loop_handle_t event_loop, TickType_t tick * - all events of a certain base: specify exact event_base and use ESP_EVENT_ANY_ID as the event_id * - all events known by the loop: use ESP_EVENT_ANY_BASE for event_base and ESP_EVENT_ANY_ID as the event_id * - * Registering multiple handlers to events is possible. Registering a single handler to multiple events is - * also possible. However, registering the same handler to the same event multiple times would cause the + * Registering multiple handlers to events is possible. Registering a single handler to multiple events is + * also possible. However, registering the same handler to the same event multiple times would cause the * previous registrations to be overwritten. * * @param[in] event_base the base id of the event to register the handler for @@ -133,24 +133,24 @@ esp_err_t esp_event_loop_run(esp_event_loop_handle_t event_loop, TickType_t tick * @param[in] event_handler the handler function which gets called when the event is dispatched * @param[in] event_handler_arg data, aside from event data, that is passed to the handler when it is called * - * @note the event loop library does not maintain a copy of event_handler_arg, therefore the user should + * @note the event loop library does not maintain a copy of event_handler_arg, therefore the user should * ensure that event_handler_arg still points to a valid location by the time the handler gets called * - * @return + * @return * - ESP_OK: Success * - ESP_ERR_NO_MEM: Cannot allocate memory for the handler - * - ESP_ERR_INVALIG_ARG: Invalid combination of event base and event id + * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id * - Others: Fail */ -esp_err_t esp_event_handler_register(esp_event_base_t event_base, - int32_t event_id, - esp_event_handler_t event_handler, +esp_err_t esp_event_handler_register(esp_event_base_t event_base, + int32_t event_id, + esp_event_handler_t event_handler, void* event_handler_arg); /** * @brief Register an event handler to a specific loop. * - * This function behaves in the same manner as esp_event_handler_register, except the additional + * This function behaves in the same manner as esp_event_handler_register, except the additional * specification of the event loop to register the handler to. * * @param[in] event_loop the event loop to register this handler function to @@ -159,23 +159,26 @@ esp_err_t esp_event_handler_register(esp_event_base_t event_base, * @param[in] event_handler the handler function which gets called when the event is dispatched * @param[in] event_handler_arg data, aside from event data, that is passed to the handler when it is called * - * @return + * @note the event loop library does not maintain a copy of event_handler_arg, therefore the user should + * ensure that event_handler_arg still points to a valid location by the time the handler gets called + * + * @return * - ESP_OK: Success * - ESP_ERR_NO_MEM: Cannot allocate memory for the handler - * - ESP_ERR_INVALIG_ARG: Invalid combination of event base and event id + * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id * - Others: Fail */ -esp_err_t esp_event_handler_register_with(esp_event_loop_handle_t event_loop, - esp_event_base_t event_base, - int32_t event_id, - esp_event_handler_t event_handler, +esp_err_t esp_event_handler_register_with(esp_event_loop_handle_t event_loop, + esp_event_base_t event_base, + int32_t event_id, + esp_event_handler_t event_handler, void* event_handler_arg); /** * @brief Unregister a handler with the system event loop. * * This function can be used to unregister a handler so that it no longer gets called during dispatch. - * Handlers can be unregistered for either: (1) specific events, (2) all events of a certain event base, + * Handlers can be unregistered for either: (1) specific events, (2) all events of a certain event base, * or (3) all events known by the system event loop * * - specific events: specify exact event_base and event_id @@ -189,7 +192,7 @@ esp_err_t esp_event_handler_register_with(esp_event_loop_handle_t event_loop, * @param[in] event_handler the handler to unregister * * @return ESP_OK success - * @return ESP_ERR_INVALIG_ARG invalid combination of event base and event id + * @return ESP_ERR_INVALID_ARG invalid combination of event base and event id * @return others fail */ esp_err_t esp_event_handler_unregister(esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler); @@ -197,7 +200,7 @@ esp_err_t esp_event_handler_unregister(esp_event_base_t event_base, int32_t even /** * @brief Unregister a handler with the system event loop. * - * This function behaves in the same manner as esp_event_handler_unregister, except the additional specification of + * This function behaves in the same manner as esp_event_handler_unregister, except the additional specification of * the event loop to unregister the handler with. * * @param[in] event_loop the event loop with which to unregister this handler function @@ -205,21 +208,21 @@ esp_err_t esp_event_handler_unregister(esp_event_base_t event_base, int32_t even * @param[in] event_id the id of the event with which to unregister the handler * @param[in] event_handler the handler to unregister * - * @return + * @return * - ESP_OK: Success - * - ESP_ERR_INVALIG_ARG: Invalid combination of event base and event id + * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id * - Others: Fail */ -esp_err_t esp_event_handler_unregister_with(esp_event_loop_handle_t event_loop, - esp_event_base_t event_base, - int32_t event_id, +esp_err_t esp_event_handler_unregister_with(esp_event_loop_handle_t event_loop, + esp_event_base_t event_base, + int32_t event_id, esp_event_handler_t event_handler); /** - * @brief Posts an event to the system default event loop. The event loop library keeps a copy of event_data and manages - * the copy's lifetime automatically (allocation + deletion); this ensures that the data the + * @brief Posts an event to the system default event loop. The event loop library keeps a copy of event_data and manages + * the copy's lifetime automatically (allocation + deletion); this ensures that the data the * handler recieves is always valid. - * + * * @param[in] event_base the event base that identifies the event * @param[in] event_id the the event id that identifies the event * @param[in] event_data the data, specific to the event occurence, that gets passed to the handler @@ -228,21 +231,21 @@ esp_err_t esp_event_handler_unregister_with(esp_event_loop_handle_t event_loop, * * @note posting events from an ISR is not supported * - * @return + * @return * - ESP_OK: Success * - ESP_ERR_TIMEOUT: Time to wait for event queue to unblock expired - * - ESP_ERR_INVALIG_ARG: Invalid combination of event base and event id + * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id * - Others: Fail */ -esp_err_t esp_event_post(esp_event_base_t event_base, - int32_t event_id, - void* event_data, - size_t event_data_size, +esp_err_t esp_event_post(esp_event_base_t event_base, + int32_t event_id, + void* event_data, + size_t event_data_size, TickType_t ticks_to_wait); /** - * @brief Posts an event to the specified event loop. The event loop library keeps a copy of event_data and manages - * the copy's lifetime automatically (allocation + deletion); this ensures that the data the + * @brief Posts an event to the specified event loop. The event loop library keeps a copy of event_data and manages + * the copy's lifetime automatically (allocation + deletion); this ensures that the data the * handler recieves is always valid. * * This function behaves in the same manner as esp_event_post_to, except the additional specification of the event loop @@ -256,73 +259,60 @@ esp_err_t esp_event_post(esp_event_base_t event_base, * @param[in] ticks_to_wait number of ticks to block on a full event queue * * @note posting events from an ISR is not supported - * - * @return + * + * @return * - ESP_OK: Success * - ESP_ERR_TIMEOUT: Time to wait for event queue to unblock expired - * - ESP_ERR_INVALIG_ARG: Invalid combination of event base and event id + * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id * - Others: Fail */ -esp_err_t esp_event_post_to(esp_event_loop_handle_t event_loop, - esp_event_base_t event_base, - int32_t event_id, - void* event_data, - size_t event_data_size, +esp_err_t esp_event_post_to(esp_event_loop_handle_t event_loop, + esp_event_base_t event_base, + int32_t event_id, + void* event_data, + size_t event_data_size, TickType_t ticks_to_wait); /** * @brief Dumps statistics of all event loops. * * Dumps event loop info in the format: - * + * @verbatim event loop - event - handler - handler - event - handler - handler + handler + handler + ... event loop - event - handler - ... + handler + handler ... - ... - + where: - + event loop - format: address,name rx:total_recieved dr:total_dropped inv:total_number_of_invocations run:total_runtime + format: address,name rx:total_recieved dr:total_dropped where: address - memory address of the event loop - name - name of the event loop + name - name of the event loop, 'none' if no dedicated task total_recieved - number of successfully posted events - total_number_of_invocations - total number of handler invocations performed so far - total_runtime - total runtime of all invocations so far - - event - format: base:id proc:total_processed run:total_runtime - where: - base - event base - id - event id - total_processed - number of instances of this event that has been processed - total_runtime - total amount of time in microseconds used for invoking handlers of this event - + total_dropped - number of events unsucessfully posted due to queue being full + handler - format: address inv:total_invoked run:total_runtime + format: address ev:base,id inv:total_invoked run:total_runtime where: address - address of the handler function + base,id - the event specified by event base and id this handler executes total_invoked - number of times this handler has been invoked total_runtime - total amount of time used for invoking this handler - + @endverbatim * * @param[in] file the file stream to output to * * @note this function is a noop when CONFIG_EVENT_LOOP_PROFILING is disabled * - * @return + * @return * - ESP_OK: Success * - ESP_ERR_NO_MEM: Cannot allocate memory for event loops list * - Others: Fail diff --git a/tools/sdk/include/esp_http_client/esp_http_client.h b/tools/sdk/include/esp_http_client/esp_http_client.h index 18b68b88334..102bf9e3ea2 100644 --- a/tools/sdk/include/esp_http_client/esp_http_client.h +++ b/tools/sdk/include/esp_http_client/esp_http_client.h @@ -235,13 +235,43 @@ esp_err_t esp_http_client_set_header(esp_http_client_handle_t client, const char */ esp_err_t esp_http_client_get_header(esp_http_client_handle_t client, const char *key, char **value); +/** + * @brief Get http request username. + * The address of username buffer will be assigned to value parameter. + * This function must be called after `esp_http_client_init`. + * + * @param[in] client The esp_http_client handle + * @param[out] value The username value + * + * @return + * - ESP_OK + * - ESP_ERR_INVALID_ARG + */ +esp_err_t esp_http_client_get_username(esp_http_client_handle_t client, char **value); + +/** + * @brief Get http request password. + * The address of password buffer will be assigned to value parameter. + * This function must be called after `esp_http_client_init`. + * + * @param[in] client The esp_http_client handle + * @param[out] value The password value + * + * @return + * - ESP_OK + * - ESP_ERR_INVALID_ARG + */ +esp_err_t esp_http_client_get_password(esp_http_client_handle_t client, char **value); + /** * @brief Set http request method * * @param[in] client The esp_http_client handle * @param[in] method The method * - * @return ESP_OK + * @return + * - ESP_OK + * - ESP_ERR_INVALID_ARG */ esp_err_t esp_http_client_set_method(esp_http_client_handle_t client, esp_http_client_method_t method); diff --git a/tools/sdk/include/esp_http_server/esp_http_server.h b/tools/sdk/include/esp_http_server/esp_http_server.h index 7d4b1a63e02..fc448500ede 100644 --- a/tools/sdk/include/esp_http_server/esp_http_server.h +++ b/tools/sdk/include/esp_http_server/esp_http_server.h @@ -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,9 +97,11 @@ 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 - * @return status + * @param[in] hd server instance + * @param[in] sockfd session socket file descriptor + * @return + * - ESP_OK : On success + * - Any value other than ESP_OK will signal the server to close the socket immediately */ typedef esp_err_t (*httpd_open_func_t)(httpd_handle_t hd, int sockfd); @@ -104,11 +111,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 * @@ -179,6 +201,8 @@ typedef struct httpd_config { * * If a context needs to be maintained between these functions, store it in the session using * httpd_sess_set_transport_ctx() and retrieve it later with httpd_sess_get_transport_ctx() + * + * Returning a value other than ESP_OK will immediately close the new socket. */ httpd_open_func_t open_fn; @@ -195,6 +219,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 +269,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) @@ -445,6 +487,122 @@ esp_err_t httpd_unregister_uri(httpd_handle_t handle, const char* uri); * @} */ +/* ************** Group: HTTP Error ************** */ +/** @name HTTP Error + * Prototype for HTTP errors and error handling functions + * @{ + */ + +/** + * @brief Error codes sent as HTTP response in case of errors + * encountered during processing of an HTTP request + */ +typedef enum { + /* For any unexpected errors during parsing, like unexpected + * state transitions, or unhandled errors. + */ + HTTPD_500_INTERNAL_SERVER_ERROR = 0, + + /* For methods not supported by http_parser. Presently + * http_parser halts parsing when such methods are + * encountered and so the server responds with 400 Bad + * Request error instead. + */ + HTTPD_501_METHOD_NOT_IMPLEMENTED, + + /* When HTTP version is not 1.1 */ + HTTPD_505_VERSION_NOT_SUPPORTED, + + /* Returned when http_parser halts parsing due to incorrect + * syntax of request, unsupported method in request URI or + * due to chunked encoding / upgrade field present in headers + */ + HTTPD_400_BAD_REQUEST, + + /* When requested URI is not found */ + HTTPD_404_NOT_FOUND, + + /* When URI found, but method has no handler registered */ + HTTPD_405_METHOD_NOT_ALLOWED, + + /* Intended for recv timeout. Presently it's being sent + * for other recv errors as well. Client should expect the + * server to immediately close the connection after + * responding with this. + */ + HTTPD_408_REQ_TIMEOUT, + + /* Intended for responding to chunked encoding, which is + * not supported currently. Though unhandled http_parser + * callback for chunked request returns "400 Bad Request" + */ + HTTPD_411_LENGTH_REQUIRED, + + /* URI length greater than CONFIG_HTTPD_MAX_URI_LEN */ + HTTPD_414_URI_TOO_LONG, + + /* Headers section larger than CONFIG_HTTPD_MAX_REQ_HDR_LEN */ + HTTPD_431_REQ_HDR_FIELDS_TOO_LARGE, + + /* Used internally for retrieving the total count of errors */ + HTTPD_ERR_CODE_MAX +} httpd_err_code_t; + +/** + * @brief Function prototype for HTTP error handling. + * + * This function is executed upon HTTP errors generated during + * internal processing of an HTTP request. This is used to override + * the default behavior on error, which is to send HTTP error response + * and close the underlying socket. + * + * @note + * - If implemented, the server will not automatically send out HTTP + * error response codes, therefore, httpd_resp_send_err() must be + * invoked inside this function if user wishes to generate HTTP + * error responses. + * - When invoked, the validity of `uri`, `method`, `content_len` + * and `user_ctx` fields of the httpd_req_t parameter is not + * guaranteed as the HTTP request may be partially received/parsed. + * - The function must return ESP_OK if underlying socket needs to + * be kept open. Any other value will ensure that the socket is + * closed. The return value is ignored when error is of type + * `HTTPD_500_INTERNAL_SERVER_ERROR` and the socket closed anyway. + * + * @param[in] req HTTP request for which the error needs to be handled + * @param[in] error Error type + * + * @return + * - ESP_OK : error handled successful + * - ESP_FAIL : failure indicates that the underlying socket needs to be closed + */ +typedef esp_err_t (*httpd_err_handler_func_t)(httpd_req_t *req, + httpd_err_code_t error); + +/** + * @brief Function for registering HTTP error handlers + * + * This function maps a handler function to any supported error code + * given by `httpd_err_code_t`. See prototype `httpd_err_handler_func_t` + * above for details. + * + * @param[in] handle HTTP server handle + * @param[in] error Error type + * @param[in] handler_fn User implemented handler function + * (Pass NULL to unset any previously set handler) + * + * @return + * - ESP_OK : handler registered successfully + * - ESP_ERR_INVALID_ARG : invalid error code or server handle + */ +esp_err_t httpd_register_err_handler(httpd_handle_t handle, + httpd_err_code_t error, + httpd_err_handler_func_t handler_fn); + +/** End of HTTP Error + * @} + */ + /* ************** Group: TX/RX ************** */ /** @name TX / RX * Prototype for HTTPDs low-level send/recv functions @@ -463,11 +621,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 @@ -484,11 +642,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 @@ -506,8 +664,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 @@ -759,6 +917,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. * @@ -787,7 +969,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 @@ -826,7 +1008,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 @@ -837,6 +1019,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 + */ +static 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 + */ +static 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 */ @@ -925,6 +1149,30 @@ esp_err_t httpd_resp_set_type(httpd_req_t *r, const char *type); */ esp_err_t httpd_resp_set_hdr(httpd_req_t *r, const char *field, const char *value); +/** + * @brief For sending out error code in response to HTTP request. + * + * @note + * - This API is supposed to be called only from the context of + * a URI handler where httpd_req_t* request pointer is valid. + * - Once this API is called, all request headers are purged, so + * request headers need be copied into separate buffers if + * they are required later. + * - If you wish to send additional data in the body of the + * response, please use the lower-level functions directly. + * + * @param[in] req Pointer to the HTTP request for which the response needs to be sent + * @param[in] error Error type to send + * @param[in] msg Error message string (pass NULL for default message) + * + * @return + * - ESP_OK : On successfully sending the response packet + * - ESP_ERR_INVALID_ARG : Null arguments + * - ESP_ERR_HTTPD_RESP_SEND : Error in raw send + * - ESP_ERR_HTTPD_INVALID_REQ : Invalid request pointer + */ +esp_err_t httpd_resp_send_err(httpd_req_t *req, httpd_err_code_t error, const char *msg); + /** * @brief Helper function for HTTP 404 * @@ -946,7 +1194,9 @@ esp_err_t httpd_resp_set_hdr(httpd_req_t *r, const char *field, const char *valu * - ESP_ERR_HTTPD_RESP_SEND : Error in raw send * - ESP_ERR_HTTPD_INVALID_REQ : Invalid request pointer */ -esp_err_t httpd_resp_send_404(httpd_req_t *r); +static inline esp_err_t httpd_resp_send_404(httpd_req_t *r) { + return httpd_resp_send_err(r, HTTPD_404_NOT_FOUND, NULL); +} /** * @brief Helper function for HTTP 408 @@ -969,7 +1219,9 @@ esp_err_t httpd_resp_send_404(httpd_req_t *r); * - ESP_ERR_HTTPD_RESP_SEND : Error in raw send * - ESP_ERR_HTTPD_INVALID_REQ : Invalid request pointer */ -esp_err_t httpd_resp_send_408(httpd_req_t *r); +static inline esp_err_t httpd_resp_send_408(httpd_req_t *r) { + return httpd_resp_send_err(r, HTTPD_408_REQ_TIMEOUT, NULL); +} /** * @brief Helper function for HTTP 500 @@ -992,7 +1244,9 @@ esp_err_t httpd_resp_send_408(httpd_req_t *r); * - ESP_ERR_HTTPD_RESP_SEND : Error in raw send * - ESP_ERR_HTTPD_INVALID_REQ : Invalid request pointer */ -esp_err_t httpd_resp_send_500(httpd_req_t *r); +static inline esp_err_t httpd_resp_send_500(httpd_req_t *r) { + return httpd_resp_send_err(r, HTTPD_500_INTERNAL_SERVER_ERROR, NULL); +} /** * @brief Raw HTTP send diff --git a/tools/sdk/include/esp_https_ota/esp_https_ota.h b/tools/sdk/include/esp_https_ota/esp_https_ota.h index 157195601c7..c87ec3bdf4d 100644 --- a/tools/sdk/include/esp_https_ota/esp_https_ota.h +++ b/tools/sdk/include/esp_https_ota/esp_https_ota.h @@ -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. diff --git a/tools/sdk/include/esp_https_server/esp_https_server.h b/tools/sdk/include/esp_https_server/esp_https_server.h new file mode 100644 index 00000000000..e69a5a294e9 --- /dev/null +++ b/tools/sdk/include/esp_https_server/esp_https_server.h @@ -0,0 +1,130 @@ +// Copyright 2018 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. + +#ifndef _ESP_HTTPS_SERVER_H_ +#define _ESP_HTTPS_SERVER_H_ + +#include +#include "esp_err.h" +#include "esp_http_server.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + HTTPD_SSL_TRANSPORT_SECURE, // SSL Enabled + HTTPD_SSL_TRANSPORT_INSECURE // SSL disabled +} httpd_ssl_transport_mode_t; + +/** + * HTTPS server config struct + * + * Please use HTTPD_SSL_CONFIG_DEFAULT() to initialize it. + */ +struct httpd_ssl_config { + /** + * Underlying HTTPD server config + * + * Parameters like task stack size and priority can be adjusted here. + */ + httpd_config_t httpd; + + /** CA certificate */ + const uint8_t *cacert_pem; + + /** CA certificate byte length */ + size_t cacert_len; + + /** Private key */ + const uint8_t *prvtkey_pem; + + /** Private key byte length */ + size_t prvtkey_len; + + /** Transport Mode (default secure) */ + httpd_ssl_transport_mode_t transport_mode; + + /** Port used when transport mode is secure (default 443) */ + uint16_t port_secure; + + /** Port used when transport mode is insecure (default 80) */ + uint16_t port_insecure; +}; + +typedef struct httpd_ssl_config httpd_ssl_config_t; + +/** + * Default config struct init + * + * (http_server default config had to be copied for customization) + * + * Notes: + * - port is set when starting the server, according to 'transport_mode' + * - one socket uses ~ 40kB RAM with SSL, we reduce the default socket count to 4 + * - SSL sockets are usually long-lived, closing LRU prevents pool exhaustion DOS + * - Stack size may need adjustments depending on the user application + */ +#define HTTPD_SSL_CONFIG_DEFAULT() { \ + .httpd = { \ + .task_priority = tskIDLE_PRIORITY+5, \ + .stack_size = 10240, \ + .server_port = 0, \ + .ctrl_port = 32768, \ + .max_open_sockets = 4, \ + .max_uri_handlers = 8, \ + .max_resp_headers = 8, \ + .backlog_conn = 5, \ + .lru_purge_enable = true, \ + .recv_wait_timeout = 5, \ + .send_wait_timeout = 5, \ + .global_user_ctx = NULL, \ + .global_user_ctx_free_fn = NULL, \ + .global_transport_ctx = NULL, \ + .global_transport_ctx_free_fn = NULL, \ + .open_fn = NULL, \ + .close_fn = NULL, \ + .uri_match_fn = NULL \ + }, \ + .cacert_pem = NULL, \ + .cacert_len = 0, \ + .prvtkey_pem = NULL, \ + .prvtkey_len = 0, \ + .transport_mode = HTTPD_SSL_TRANSPORT_SECURE, \ + .port_secure = 443, \ + .port_insecure = 80, \ +} + +/** + * Create a SSL capable HTTP server (secure mode may be disabled in config) + * + * @param[in,out] config - server config, must not be const. Does not have to stay valid after + * calling this function. + * @param[out] handle - storage for the server handle, must be a valid pointer + * @return success + */ +esp_err_t httpd_ssl_start(httpd_handle_t *handle, httpd_ssl_config_t *config); + +/** + * Stop the server. Blocks until the server is shut down. + * + * @param[in] handle + */ +void httpd_ssl_stop(httpd_handle_t handle); + +#ifdef __cplusplus +} +#endif + +#endif // _ESP_HTTPS_SERVER_H_ diff --git a/tools/sdk/include/espcoredump/esp_core_dump.h b/tools/sdk/include/espcoredump/esp_core_dump.h new file mode 100644 index 00000000000..e19b45c98ad --- /dev/null +++ b/tools/sdk/include/espcoredump/esp_core_dump.h @@ -0,0 +1,89 @@ +// Copyright 2015-2016 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. +#ifndef ESP_CORE_DUMP_H_ +#define ESP_CORE_DUMP_H_ + +#include +#include "esp_err.h" +#include "freertos/xtensa_context.h" + +/**************************************************************************************/ +/******************************** EXCEPTION MODE API **********************************/ +/**************************************************************************************/ + +/** + * @brief Initializes core dump module internal data. + * + * @note Should be called at system startup. + */ +void esp_core_dump_init(); + +/** + * @brief Saves core dump to flash. + * + * The structure of data stored in flash is as follows: + * + * | TOTAL_LEN | VERSION | TASKS_NUM | TCB_SIZE | + * | TCB_ADDR_1 | STACK_TOP_1 | STACK_END_1 | TCB_1 | STACK_1 | + * . . . . + * . . . . + * | TCB_ADDR_N | STACK_TOP_N | STACK_END_N | TCB_N | STACK_N | + * | CRC32 | + * + * Core dump in flash consists of header and data for every task in the system at the moment of crash. + * For flash data integrity control CRC is used at the end of core the dump data. + * The structure of core dump data is described below in details. + * 1) Core dump starts with header: + * 1.1) TOTAL_LEN is total length of core dump data in flash including CRC. Size is 4 bytes. + * 1.2) VERSION field keeps 4 byte version of core dump. + * 1.2) TASKS_NUM is the number of tasks for which data are stored. Size is 4 bytes. + * 1.3) TCB_SIZE is the size of task's TCB structure. Size is 4 bytes. + * 2) Core dump header is followed by the data for every task in the system. + * Task data are started with task header: + * 2.1) TCB_ADDR is the address of TCB in memory. Size is 4 bytes. + * 2.2) STACK_TOP is the top of task's stack (address of the topmost stack item). Size is 4 bytes. + * 2.2) STACK_END is the end of task's stack (address from which task's stack starts). Size is 4 bytes. + * 3) Task header is followed by TCB data. Size is TCB_SIZE bytes. + * 4) Task's stack is placed after TCB data. Size is (STACK_END - STACK_TOP) bytes. + * 5) CRC is placed at the end of the data. + */ +void esp_core_dump_to_flash(XtExcFrame *frame); + +/** + * @brief Print base64-encoded core dump to UART. + * + * The structure of core dump data is the same as for data stored in flash (@see esp_core_dump_to_flash) with some notes: + * 1) CRC is not present in core dump printed to UART. + * 2) Since CRC is omitted TOTAL_LEN does not include its size. + * 3) Printed base64 data are surrounded with special messages to help user recognize the start and end of actual data. + */ +void esp_core_dump_to_uart(XtExcFrame *frame); + + +/**************************************************************************************/ +/*********************************** USER MODE API ************************************/ +/**************************************************************************************/ + +/** + * @brief Retrieves address and size of coredump data in flash. + * This function is always available, even when core dump is disabled in menuconfig. + * + * @param out_addr pointer to store image address in flash. + * @param out_size pointer to store image size in flash (including CRC). In bytes. + * + * @return ESP_OK on success, otherwise \see esp_err_t + */ +esp_err_t esp_core_dump_image_get(size_t* out_addr, size_t *out_size); + +#endif diff --git a/tools/sdk/include/fatfs/ffconf.h b/tools/sdk/include/fatfs/ffconf.h index 1b1cf8c85ca..9513b51608d 100644 --- a/tools/sdk/include/fatfs/ffconf.h +++ b/tools/sdk/include/fatfs/ffconf.h @@ -52,7 +52,7 @@ /* This option switches f_expand function. (0:Disable or 1:Enable) */ -#define FF_USE_CHMOD 0 +#define FF_USE_CHMOD 1 /* This option switches attribute manipulation functions, f_chmod() and f_utime(). / (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */ @@ -301,4 +301,11 @@ #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" +/* Some memory allocation functions are declared here in addition to ff.h, so that + they can be used also by external code when LFN feature is disabled. + */ +void* ff_memalloc (UINT msize); +void* ff_memcalloc (UINT num, UINT size); + + /*--- End of configuration options ---*/ diff --git a/tools/sdk/include/freemodbus/mbcontroller.h b/tools/sdk/include/freemodbus/mbcontroller.h index b6b206e2a68..267fa34aed1 100644 --- a/tools/sdk/include/freemodbus/mbcontroller.h +++ b/tools/sdk/include/freemodbus/mbcontroller.h @@ -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 diff --git a/tools/sdk/include/freertos/freertos/FreeRTOSConfig.h b/tools/sdk/include/freertos/freertos/FreeRTOSConfig.h index aa33917e2c0..80185f9e045 100644 --- a/tools/sdk/include/freertos/freertos/FreeRTOSConfig.h +++ b/tools/sdk/include/freertos/freertos/FreeRTOSConfig.h @@ -300,7 +300,12 @@ extern void vPortCleanUpTCB ( void *pxTCB ); #define configXT_BOARD 1 /* Board mode */ #define configXT_SIMULATOR 0 -#define configENABLE_TASK_SNAPSHOT 1 +#if CONFIG_ESP32_ENABLE_COREDUMP +#define configENABLE_TASK_SNAPSHOT 1 +#endif +#ifndef configENABLE_TASK_SNAPSHOT +#define configENABLE_TASK_SNAPSHOT 1 +#endif #if CONFIG_SYSVIEW_ENABLE #ifndef __ASSEMBLER__ diff --git a/tools/sdk/include/freertos/freertos/portmacro.h b/tools/sdk/include/freertos/freertos/portmacro.h index adeb3bb0097..7fd94d5a0b9 100644 --- a/tools/sdk/include/freertos/freertos/portmacro.h +++ b/tools/sdk/include/freertos/freertos/portmacro.h @@ -209,8 +209,34 @@ void vPortCPUReleaseMutex(portMUX_TYPE *mux, const char *function, int line); void vTaskEnterCritical( portMUX_TYPE *mux, const char *function, int line ); void vTaskExitCritical( portMUX_TYPE *mux, const char *function, int line ); + +#ifdef CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE +/* Calling port*_CRITICAL from ISR context would cause an assert failure. + * If the parent function is called from both ISR and Non-ISR context then call port*_CRITICAL_SAFE + */ +#define portENTER_CRITICAL(mux) do { \ + if(!xPortInIsrContext()) { \ + vTaskEnterCritical(mux, __FUNCTION__, __LINE__); \ + } else { \ + ets_printf("%s:%d (%s)- port*_CRITICAL called from ISR context!\n", __FILE__, __LINE__, \ + __FUNCTION__); \ + abort(); \ + } \ + } while(0) + +#define portEXIT_CRITICAL(mux) do { \ + if(!xPortInIsrContext()) { \ + vTaskExitCritical(mux, __FUNCTION__, __LINE__); \ + } else { \ + ets_printf("%s:%d (%s)- port*_CRITICAL called from ISR context!\n", __FILE__, __LINE__, \ + __FUNCTION__); \ + abort(); \ + } \ + } while(0) +#else #define portENTER_CRITICAL(mux) vTaskEnterCritical(mux, __FUNCTION__, __LINE__) #define portEXIT_CRITICAL(mux) vTaskExitCritical(mux, __FUNCTION__, __LINE__) +#endif #define portENTER_CRITICAL_ISR(mux) vTaskEnterCritical(mux, __FUNCTION__, __LINE__) #define portEXIT_CRITICAL_ISR(mux) vTaskExitCritical(mux, __FUNCTION__, __LINE__) #else @@ -229,12 +255,54 @@ void vPortCPUAcquireMutex(portMUX_TYPE *mux); bool vPortCPUAcquireMutexTimeout(portMUX_TYPE *mux, int timeout_cycles); void vPortCPUReleaseMutex(portMUX_TYPE *mux); +#ifdef CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE +/* Calling port*_CRITICAL from ISR context would cause an assert failure. + * If the parent function is called from both ISR and Non-ISR context then call port*_CRITICAL_SAFE + */ +#define portENTER_CRITICAL(mux) do { \ + if(!xPortInIsrContext()) { \ + vTaskEnterCritical(mux); \ + } else { \ + ets_printf("%s:%d (%s)- port*_CRITICAL called from ISR context!\n", __FILE__, __LINE__, \ + __FUNCTION__); \ + abort(); \ + } \ + } while(0) + +#define portEXIT_CRITICAL(mux) do { \ + if(!xPortInIsrContext()) { \ + vTaskExitCritical(mux); \ + } else { \ + ets_printf("%s:%d (%s)- port*_CRITICAL called from ISR context!\n", __FILE__, __LINE__, \ + __FUNCTION__); \ + abort(); \ + } \ + } while(0) +#else #define portENTER_CRITICAL(mux) vTaskEnterCritical(mux) #define portEXIT_CRITICAL(mux) vTaskExitCritical(mux) +#endif #define portENTER_CRITICAL_ISR(mux) vTaskEnterCritical(mux) #define portEXIT_CRITICAL_ISR(mux) vTaskExitCritical(mux) #endif +#define portENTER_CRITICAL_SAFE(mux) do { \ + if (xPortInIsrContext()) { \ + portENTER_CRITICAL_ISR(mux); \ + } else { \ + portENTER_CRITICAL(mux); \ + } \ + } while(0) + +#define portEXIT_CRITICAL_SAFE(mux) do { \ + if (xPortInIsrContext()) { \ + portEXIT_CRITICAL_ISR(mux); \ + } else { \ + portEXIT_CRITICAL(mux); \ + } \ + } while(0) + + // Critical section management. NW-TODO: replace XTOS_SET_INTLEVEL with more efficient version, if any? // These cannot be nested. They should be used with a lot of care and cannot be called from interrupt level. // diff --git a/tools/sdk/include/idf_test/idf_performance.h b/tools/sdk/include/idf_test/idf_performance.h index e864b293299..ad60009f016 100644 --- a/tools/sdk/include/idf_test/idf_performance.h +++ b/tools/sdk/include/idf_test/idf_performance.h @@ -1,12 +1,4 @@ - -/* @brief macro to print IDF performance - * @param mode : performance item name. a string pointer. - * @param value_fmt: print format and unit of the value, for example: "%02fms", "%dKB" - * @param value : the performance value. -*/ -#define IDF_LOG_PERFORMANCE(item, value_fmt, value) \ - printf("[Performance][%s]: "value_fmt"\n", item, value) - +#pragma once /* declare the performance here */ #define IDF_PERFORMANCE_MAX_HTTPS_REQUEST_BIN_SIZE 800 @@ -20,8 +12,8 @@ #define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING_NO_DMA 15 /* Due to code size & linker layout differences interacting with cache, VFS microbenchmark currently runs slower with PSRAM enabled. */ -#define IDF_PERFORMANCE_MAX_VFS_OPEN_WRITE_CLOSE_TIME 50000 -#define IDF_PERFORMANCE_MAX_VFS_OPEN_WRITE_CLOSE_TIME_PSRAM 40000 +#define IDF_PERFORMANCE_MAX_VFS_OPEN_WRITE_CLOSE_TIME 20000 +#define IDF_PERFORMANCE_MAX_VFS_OPEN_WRITE_CLOSE_TIME_PSRAM 25000 // throughput performance by iperf #define IDF_PERFORMANCE_MIN_TCP_RX_THROUGHPUT 50 #define IDF_PERFORMANCE_MIN_TCP_TX_THROUGHPUT 40 diff --git a/tools/sdk/include/lwip/lwipopts.h b/tools/sdk/include/lwip/lwipopts.h index 13a3632d43a..883abe55740 100644 --- a/tools/sdk/include/lwip/lwipopts.h +++ b/tools/sdk/include/lwip/lwipopts.h @@ -1,8 +1,8 @@ /* * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, @@ -11,21 +11,21 @@ * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. + * derived from this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * * This file is part of the lwIP TCP/IP stack. - * + * * Author: Simon Goldschmidt * */ @@ -316,7 +316,7 @@ * scenario happens: 192.168.0.2 -> 0.0.0.0 -> 192.168.0.2 or 192.168.0.2 -> 0.0.0.0 */ -#define ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES +#define ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES /* * LWIP_EVENT_API==1: The user defines lwip_tcp_event() to receive all * events (accept, sent, etc) that happen in the system. @@ -589,6 +589,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. */ @@ -769,11 +774,10 @@ #define ESP_AUTO_RECV 1 #define ESP_GRATUITOUS_ARP CONFIG_ESP_GRATUITOUS_ARP -#if CONFIG_LWIP_IRAM_OPTIMIZATION -#define ESP_IRAM_ATTR IRAM_ATTR -#else -#define ESP_IRAM_ATTR +#ifdef ESP_IRAM_ATTR +#undef ESP_IRAM_ATTR #endif +#define ESP_IRAM_ATTR #if ESP_PERF #define DBG_PERF_PATH_SET(dir, point) @@ -795,7 +799,7 @@ enum { }; #else -#define DBG_PERF_PATH_SET(dir, point) +#define DBG_PERF_PATH_SET(dir, point) #define DBG_PERF_FILTER_LEN 1000 #endif diff --git a/tools/sdk/include/mbedtls/mbedtls/aes.h b/tools/sdk/include/mbedtls/mbedtls/aes.h index 4c8dab31519..94e7282d36d 100644 --- a/tools/sdk/include/mbedtls/mbedtls/aes.h +++ b/tools/sdk/include/mbedtls/mbedtls/aes.h @@ -60,7 +60,11 @@ /* Error codes in range 0x0021-0x0025 */ #define MBEDTLS_ERR_AES_BAD_INPUT_DATA -0x0021 /**< Invalid input data. */ + +/* MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE is deprecated and should not be used. */ #define MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE -0x0023 /**< Feature not available. For example, an unsupported AES key size. */ + +/* MBEDTLS_ERR_AES_HW_ACCEL_FAILED is deprecated and should not be used. */ #define MBEDTLS_ERR_AES_HW_ACCEL_FAILED -0x0025 /**< AES hardware accelerator failed. */ #if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ @@ -117,7 +121,7 @@ typedef struct mbedtls_aes_xts_context * It must be the first API called before using * the context. * - * \param ctx The AES context to initialize. + * \param ctx The AES context to initialize. This must not be \c NULL. */ void mbedtls_aes_init( mbedtls_aes_context *ctx ); @@ -125,6 +129,8 @@ void mbedtls_aes_init( mbedtls_aes_context *ctx ); * \brief This function releases and clears the specified AES context. * * \param ctx The AES context to clear. + * If this is \c NULL, this function does nothing. + * Otherwise, the context must have been at least initialized. */ void mbedtls_aes_free( mbedtls_aes_context *ctx ); @@ -135,7 +141,7 @@ void mbedtls_aes_free( mbedtls_aes_context *ctx ); * It must be the first API called before using * the context. * - * \param ctx The AES XTS context to initialize. + * \param ctx The AES XTS context to initialize. This must not be \c NULL. */ void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx ); @@ -143,6 +149,8 @@ void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx ); * \brief This function releases and clears the specified AES XTS context. * * \param ctx The AES XTS context to clear. + * If this is \c NULL, this function does nothing. + * Otherwise, the context must have been at least initialized. */ void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx ); #endif /* MBEDTLS_CIPHER_MODE_XTS */ @@ -151,7 +159,9 @@ void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx ); * \brief This function sets the encryption key. * * \param ctx The AES context to which the key should be bound. + * It must be initialized. * \param key The encryption key. + * This must be a readable buffer of size \p keybits bits. * \param keybits The size of data passed in bits. Valid options are: *