diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 953f3f4d2..3e3437fda 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -42,7 +42,7 @@ build_ssc: - git clone $GITLAB_SSH_SERVER/yinling/SSC.git - cd SSC # try checkout same branch - - git checkout "${CI_BUILD_REF_NAME}_8266" || echo "Using default branch..." + - git checkout "release/v3.1_8266" || echo "Using default branch..." - ./gen_misc_rtos.sh push_master_to_github: diff --git a/README.md b/README.md index 43d57f9db..1c761482e 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ +# ESP8266 RTOS Software Development Kit + +[![Documentation Status](https://readthedocs.com/projects/espressif-esp8266-rtos-sdk/badge/?version=release-v3.1)](https://docs.espressif.com/projects/esp8266-rtos-sdk/en/release-v3.1/?badge=release-v3.1) + + # ** IMPORTANT NOTICE ** ## About this repository diff --git a/SUPPORT_POLICY_CN.md b/SUPPORT_POLICY_CN.md new file mode 100644 index 000000000..4dceb76ab --- /dev/null +++ b/SUPPORT_POLICY_CN.md @@ -0,0 +1,54 @@ +有关 ESP8266 RTOS SDK 的最新支持政策,详见 [支持期限政策](./SUPPORT_POLICY_CN.md)。 +支持期限政策 +================= + +* [English Version](./SUPPORT_POLICY_EN.md) + +ESP8266 RTOS SDK 的每个主要版本和次要版本(如 V3.0、V3.1 等)自其首次稳定版本发布之日起将维护 18 个月。 + +维护意味着 ESP8266 RTOS SDK 团队将会对 GitHub 上的发布分支继续进行 bug 修复、安全修补等,并根据需求定期发布新的 bugfix 版本。 + +在某一版本支持期限结束,停止更新维护 (EOL) 前,建议用户升级到较新的 ESP8266 RTOS SDK 版本。根据《支持期限政策》,我们将停止对 EOL 版本进行 bug 修复。 + +《支持期限政策》不适用于预发布版本(包括 beta、preview、`-rc` 和 `-dev` 版本等)。有时,在发布的版本中存在被标记为 "Preview" 的特定功能,则该功能也不在支持期限内。 + +长期支持版本 +------------ + +有些发布版本(例如 ESP8266 RTOS SDK V3.1)属于长期支持 (LTS) 版本。LTS 版本将自其首次稳定版本发布之日起维护 30 个月(2.5 年)。 + +关于长期维护版本,在 github 上面正式的`第1次`发布该版本 release 的时候,会在标题上额外标注 `(LTS)`,例如: + +``` +ESP8266 RTOS SDK Release v3.4 (LTS) +``` + +后续的维护版本不会再额外标注 `(LTS)`,例如: + +``` +ESP8266 RTOS SDK Release v3.4.1 +``` + +示例 +----- + +ESP8266 RTOS SDK V3.1 于 2019 年 01 月发布,属于 LTS 版本,自正式发布日开始将维护 30 个月至 2021 年 07 月停止。 + +- V3.1 的首个发布版本为 2019 年 01 月发布的 `v3.1`。 +- ESP8266 RTOS SDK 团队将持续进行 bug 修复、安全修补等更新,并 backport 至分支 `release/v3.1`。 +- 定期从 release 分支创建稳定的 bugfix 版本,比如,`v3.1.1`、`v3.1.2` 等,并建议用户保持使用最新的 bugfix 版本。 +- V3.1 的 bugfix 版本发布将持续 30 个月至 2021 年 07 月,届时所有 V3.1.x 将停止更新维护。 + +现有版本 +-------- + +ESP8266 RTOS SDK V3.3 及所有后续更新版本都将遵守该《支持期限政策》。每一版本发布时将同时公布其支持期限。 + +对于该政策公布之日前发布的其他版本,应适用下述支持期限: + +- ESP8266 RTOS SDK V3.3.x 将维护至 2021 年 12 月。 +- ESP8266 RTOS SDK V3.2.x 将维护至 2020 年 12 月。 +- ESP8266 RTOS SDK V3.1.x 作为长期维护版本,将维护至 2021 年 7 月。 +- ESP8266 RTOS SDK V3.0.x 将维护至 2020 年 10 月。 +- ESP8266 RTOS SDK V2.1.x 作为长期维护版本,将维护至 2021 年 4 月。 +- ESP8266 RTOS SDK V2.0.x 及之前的版本均已停止更新维护 (EOL)。 \ No newline at end of file diff --git a/SUPPORT_POLICY_EN.md b/SUPPORT_POLICY_EN.md new file mode 100644 index 000000000..cb8c5533e --- /dev/null +++ b/SUPPORT_POLICY_EN.md @@ -0,0 +1,56 @@ +The latest support policy for ESP8266 RTOS SDK can be found at [Support Policy](./SUPPORT_POLICY_EN.md). + +Support Period Policy +================= + +* [中文版](./SUPPORT_POLICY_CN.md) + +Each ESP8266 RTOS SDK major and minor release (V3.0, V3.1, etc) is supported for 18 months after the initial stable release date. + +Supported means that the ESP8266 RTOS SDK team will continue to apply bug fixes, security fixes, etc to the release branch on GitHub, and periodically make new bugfix releases as needed. + +Users are encouraged to upgrade to a newer ESP8266 RTOS SDK release before the support period finishes and the release becomes End of Life (EOL). It is our policy to not continue fixing bugs in End of Life releases. + +Pre-release versions (betas, previews, -rc and -dev versions, etc) are not covered by any support period. Sometimes a particular feature is marked as "Preview" in a release, which means it is also not covered by the support period. + + +Long Term Support releases +------------ + +Some releases (for example, ESP8266 RTOS SDK V3.1) are designated Long Term Support (LTS). LTS releases are supported for 30 months (2.5 years) after the initial stable release date. + +We will add a `(LTS)` tag when we release a long term support version on GitHub at the first time. For example: + +``` +ESP8266 RTOS SDK Release v3.4 (LTS) +``` + +But we will not add `(LTS)` tag to the following bug fix versions. For example: + +``` +ESP8266 RTOS SDK Release v3.4.1 +``` + +Example +----- + +ESP8266 RTOS SDK V3.1 was released in January 2019 and is a Long Term Support (LTS) release, meaning it will be supported for 30 months until July 2021. + +- The first V3.1 release was `v3.1` in January 2019. +- The ESP8266 RTOS SDK team continues to backport bug fixes, security fixes, etc to the release branch `release/v3.1`。 +- Periodically stable bugfix releases are created from the release branch. For example `v3.1.1`、`v3.1.2`, etc. Users are encouraged to always update to the latest bugfix release. +- V3.1 bugfix releases continue until July 2021, when all V3.1.x releases become End of Life. + +Existing Releases +-------- + +ESP8266 RTOS SDK V3.3 and all newer releases will follow this support period policy. The support period for each release will be announced when the release is made. + +For releases made before the support period policy was announced, the following support periods apply: + +- ESP8266 RTOS SDK V3.2.x will be supported until December 2021. +- ESP8266 RTOS SDK V3.2.x will be supported until December 2020. +- ESP8266 RTOS SDK V3.1.x is Long Term Support (LTS) release, will be supported until July 2021. +- ESP8266 RTOS SDK V3.0.x will be supported until October 2020. +- ESP8266 RTOS SDK V2.1.x is Long Term Support (LTS) release, will be supported until April 2021. +- ESP8266 RTOS SDK V2.0.x and earlier versions are already End of Life. diff --git a/components/app_update/esp_ota_ops.c b/components/app_update/esp_ota_ops.c index 9f41cda7d..b9072340d 100644 --- a/components/app_update/esp_ota_ops.c +++ b/components/app_update/esp_ota_ops.c @@ -69,6 +69,28 @@ static ota_select s_ota_select[2]; const static char *TAG = "esp_ota_ops"; +#ifndef CONFIG_ESP8266_BOOT_COPY_APP +static inline int esp_ota_verify_binary(const esp_partition_pos_t *pos, esp_image_header_t *image) +{ + const int32_t entry = image->entry_addr - 0x40200010; + + ESP_LOGD(TAG, "OTA binary start entry 0x%x, partition start from 0x%x to 0x%x\n", entry, pos->offset, + pos->offset + pos->size); + + if (pos->offset + pos->size <= 0x100000) { + if (entry <= 0 || entry <= pos->offset || entry >= pos->offset + pos->size) { + const char *doc_str = "<>"; + + ESP_LOGE(TAG, "**Important**: The OTA binary link data is error, " + "please refer to document %s for how to generate OTA binaries", doc_str); + return ESP_ERR_INVALID_ARG; + } + } + + return ESP_OK; +} +#endif + /* Return true if this is an OTA app partition */ static bool is_ota_partition(const esp_partition_t *p) { @@ -244,6 +266,13 @@ esp_err_t esp_ota_end(esp_ota_handle_t handle) goto cleanup; } +#ifndef CONFIG_ESP8266_BOOT_COPY_APP + if (esp_ota_verify_binary(&part_pos, &data.image) != ESP_OK) { + ret = ESP_ERR_OTA_VALIDATE_FAILED; + goto cleanup; + } +#endif + #ifdef CONFIG_SECURE_BOOT_ENABLED ret = esp_secure_boot_verify_signature(it->part->address, data.image_len); if (ret != ESP_OK) { diff --git a/components/aws_iot/include/network_platform.h b/components/aws_iot/include/network_platform.h index a5e87d71a..2fdf238fc 100644 --- a/components/aws_iot/include/network_platform.h +++ b/components/aws_iot/include/network_platform.h @@ -16,27 +16,14 @@ #ifndef IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "mbedtls/platform.h" -#include "mbedtls/net_sockets.h" -#include "mbedtls/ssl.h" -#include "mbedtls/entropy.h" -#include "mbedtls/ctr_drbg.h" -#include "mbedtls/certs.h" -#include "mbedtls/x509.h" -#include "mbedtls/error.h" -#include "mbedtls/debug.h" -#include "mbedtls/timing.h" +#include #ifdef __cplusplus extern "C" { #endif +typedef size_t esp_network_handle_t; + /** * @brief TLS Connection Parameters * @@ -44,15 +31,9 @@ extern "C" { * TLS networking layer to create a TLS secured socket. */ typedef struct _TLSDataParams { - mbedtls_entropy_context entropy; - mbedtls_ctr_drbg_context ctr_drbg; - mbedtls_ssl_context ssl; - mbedtls_ssl_config conf; + esp_network_handle_t handle; uint32_t flags; - mbedtls_x509_crt cacert; - mbedtls_x509_crt clicert; - mbedtls_pk_context pkey; - mbedtls_net_context server_fd; + uint32_t timeout; }TLSDataParams; #define IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H diff --git a/components/aws_iot/port/network_mbedtls_wrapper.c b/components/aws_iot/port/network_mbedtls_wrapper.c index 2b078da91..2ec6d21c0 100644 --- a/components/aws_iot/port/network_mbedtls_wrapper.c +++ b/components/aws_iot/port/network_mbedtls_wrapper.c @@ -17,51 +17,22 @@ #include #include #include -#include #include "aws_iot_config.h" #include "aws_iot_error.h" #include "network_interface.h" #include "network_platform.h" -#include "mbedtls/esp_debug.h" - #include "esp_log.h" #include "esp_system.h" -#ifdef CONFIG_USE_VFS -#include "esp_vfs.h" -#endif +#include "esp_tls.h" static const char *TAG = "aws_iot"; /* This is the value used for ssl read timeout */ #define IOT_SSL_READ_TIMEOUT 10 -/* - * This is a function to do further verification if needed on the cert received. - * - * Currently used to print debug-level information about each cert. - */ -static int _iot_tls_verify_cert(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) { - char buf[256]; - ((void) data); - - if (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) { - ESP_LOGD(TAG, "Verify requested for (Depth %d):", depth); - mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt); - ESP_LOGD(TAG, "%s", buf); - - if((*flags) == 0) { - ESP_LOGD(TAG, " This certificate has no flags"); - } else { - ESP_LOGD(TAG, "Verify result:%s", buf); - } - } - - return 0; -} - static void _iot_tls_set_connect_params(Network *pNetwork, const char *pRootCALocation, const char *pDeviceCertLocation, const char *pDevicePrivateKeyLocation, const char *pDestinationURL, uint16_t destinationPort, uint32_t timeout_ms, bool ServerVerificationFlag) { @@ -100,8 +71,6 @@ IoT_Error_t iot_tls_is_connected(Network *pNetwork) { IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *params) { int ret = SUCCESS; TLSDataParams *tlsDataParams = NULL; - char portBuffer[6]; - char info_buf[256]; if(NULL == pNetwork) { return NULL_VALUE_ERROR; @@ -115,218 +84,35 @@ IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *params) { tlsDataParams = &(pNetwork->tlsDataParams); - mbedtls_net_init(&(tlsDataParams->server_fd)); - mbedtls_ssl_init(&(tlsDataParams->ssl)); - mbedtls_ssl_config_init(&(tlsDataParams->conf)); - -#ifdef CONFIG_MBEDTLS_DEBUG - mbedtls_esp_enable_debug_log(&(tlsDataParams->conf), 4); -#endif - - mbedtls_ctr_drbg_init(&(tlsDataParams->ctr_drbg)); - mbedtls_x509_crt_init(&(tlsDataParams->cacert)); - mbedtls_x509_crt_init(&(tlsDataParams->clicert)); - mbedtls_pk_init(&(tlsDataParams->pkey)); - - ESP_LOGD(TAG, "Seeding the random number generator..."); - mbedtls_entropy_init(&(tlsDataParams->entropy)); - if((ret = mbedtls_ctr_drbg_seed(&(tlsDataParams->ctr_drbg), mbedtls_entropy_func, &(tlsDataParams->entropy), - (const unsigned char *) TAG, strlen(TAG))) != 0) { - ESP_LOGE(TAG, "failed! mbedtls_ctr_drbg_seed returned -0x%x", -ret); - return NETWORK_MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED; - } - - /* Load root CA... - - Certs/keys can be paths or they can be raw data. These use a - very basic heuristic: if the cert starts with '/' then it's a - path, if it's longer than this then it's raw cert data (PEM or DER, - neither of which can start with a slash. */ - if (pNetwork->tlsConnectParams.pRootCALocation[0] == '/') { -#ifdef CONFIG_USE_VFS - ESP_LOGD(TAG, "Loading CA root certificate from file ..."); - ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->cacert), pNetwork->tlsConnectParams.pRootCALocation); -#else - ESP_LOGE(TAG, "Not to support load CA root certificate from file ..."); - return NETWORK_SSL_CERT_ERROR; -#endif - } else { - ESP_LOGD(TAG, "Loading embedded CA root certificate ..."); - ret = mbedtls_x509_crt_parse(&(tlsDataParams->cacert), (const unsigned char *)pNetwork->tlsConnectParams.pRootCALocation, - strlen(pNetwork->tlsConnectParams.pRootCALocation)+1); - } - - if(ret < 0) { - ESP_LOGE(TAG, "failed! mbedtls_x509_crt_parse returned -0x%x while parsing root cert", -ret); - return NETWORK_X509_ROOT_CRT_PARSE_ERROR; - } - ESP_LOGD(TAG, "ok (%d skipped)", ret); - - /* Load client certificate... */ - if (pNetwork->tlsConnectParams.pDeviceCertLocation[0] == '/') { -#ifdef CONFIG_USE_VFS - ESP_LOGD(TAG, "Loading client cert from file..."); - ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->clicert), - pNetwork->tlsConnectParams.pDeviceCertLocation); -#else - ESP_LOGE(TAG, "Not support to load client cert from file..."); - return NETWORK_SSL_CERT_ERROR; -#endif - } else { - ESP_LOGD(TAG, "Loading embedded client certificate..."); - ret = mbedtls_x509_crt_parse(&(tlsDataParams->clicert), - (const unsigned char *)pNetwork->tlsConnectParams.pDeviceCertLocation, - strlen(pNetwork->tlsConnectParams.pDeviceCertLocation)+1); - } - if(ret != 0) { - ESP_LOGE(TAG, "failed! mbedtls_x509_crt_parse returned -0x%x while parsing device cert", -ret); - return NETWORK_X509_DEVICE_CRT_PARSE_ERROR; - } - - /* Parse client private key... */ - if (pNetwork->tlsConnectParams.pDevicePrivateKeyLocation[0] == '/') { -#ifdef CONFIG_USE_VFS - ESP_LOGD(TAG, "Loading client private key from file..."); - ret = mbedtls_pk_parse_keyfile(&(tlsDataParams->pkey), - pNetwork->tlsConnectParams.pDevicePrivateKeyLocation, - ""); -#else - ESP_LOGE(TAG, "Not support to load client private key from file..."); - return NETWORK_SSL_CERT_ERROR; -#endif - } else { - ESP_LOGD(TAG, "Loading embedded client private key..."); - ret = mbedtls_pk_parse_key(&(tlsDataParams->pkey), - (const unsigned char *)pNetwork->tlsConnectParams.pDevicePrivateKeyLocation, - strlen(pNetwork->tlsConnectParams.pDevicePrivateKeyLocation)+1, - (const unsigned char *)"", 0); - } - if(ret != 0) { - ESP_LOGE(TAG, "failed! mbedtls_pk_parse_key returned -0x%x while parsing private key", -ret); - return NETWORK_PK_PRIVATE_KEY_PARSE_ERROR; - } - - /* Done parsing certs */ - ESP_LOGD(TAG, "ok"); - snprintf(portBuffer, 6, "%d", pNetwork->tlsConnectParams.DestinationPort); - ESP_LOGD(TAG, "Connecting to %s/%s...", pNetwork->tlsConnectParams.pDestinationURL, portBuffer); - if((ret = mbedtls_net_connect(&(tlsDataParams->server_fd), pNetwork->tlsConnectParams.pDestinationURL, - portBuffer, MBEDTLS_NET_PROTO_TCP)) != 0) { - ESP_LOGE(TAG, "failed! mbedtls_net_connect returned -0x%x", -ret); - switch(ret) { - case MBEDTLS_ERR_NET_SOCKET_FAILED: - return NETWORK_ERR_NET_SOCKET_FAILED; - case MBEDTLS_ERR_NET_UNKNOWN_HOST: - return NETWORK_ERR_NET_UNKNOWN_HOST; - case MBEDTLS_ERR_NET_CONNECT_FAILED: - default: - return NETWORK_ERR_NET_CONNECT_FAILED; - }; - } - - ret = mbedtls_net_set_block(&(tlsDataParams->server_fd)); - if(ret != 0) { - ESP_LOGE(TAG, "failed! net_set_(non)block() returned -0x%x", -ret); - return SSL_CONNECTION_ERROR; - } ESP_LOGD(TAG, "ok"); - - ESP_LOGD(TAG, "Setting up the SSL/TLS structure..."); - if((ret = mbedtls_ssl_config_defaults(&(tlsDataParams->conf), MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, - MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { - ESP_LOGE(TAG, "failed! mbedtls_ssl_config_defaults returned -0x%x", -ret); - return SSL_CONNECTION_ERROR; - } - - mbedtls_ssl_conf_verify(&(tlsDataParams->conf), _iot_tls_verify_cert, NULL); - - if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) { - mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_REQUIRED); - } else { - mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_OPTIONAL); - } - mbedtls_ssl_conf_rng(&(tlsDataParams->conf), mbedtls_ctr_drbg_random, &(tlsDataParams->ctr_drbg)); - - mbedtls_ssl_conf_ca_chain(&(tlsDataParams->conf), &(tlsDataParams->cacert), NULL); - ret = mbedtls_ssl_conf_own_cert(&(tlsDataParams->conf), &(tlsDataParams->clicert), &(tlsDataParams->pkey)); - if(ret != 0) { - ESP_LOGE(TAG, "failed! mbedtls_ssl_conf_own_cert returned %d", ret); - return SSL_CONNECTION_ERROR; - } - - mbedtls_ssl_conf_read_timeout(&(tlsDataParams->conf), pNetwork->tlsConnectParams.timeout_ms); + esp_tls_cfg_t cfg = { + .cacert_pem_buf = (const unsigned char *)pNetwork->tlsConnectParams.pRootCALocation, + .cacert_pem_bytes = strlen(pNetwork->tlsConnectParams.pRootCALocation) + 1, + .clientcert_pem_buf = (const unsigned char *)pNetwork->tlsConnectParams.pDeviceCertLocation, + .clientcert_pem_bytes = strlen(pNetwork->tlsConnectParams.pDeviceCertLocation) + 1, + .clientkey_pem_buf = (const unsigned char *)pNetwork->tlsConnectParams.pDevicePrivateKeyLocation, + .clientkey_pem_bytes = strlen(pNetwork->tlsConnectParams.pDevicePrivateKeyLocation) + 1, + .timeout_ms = pNetwork->tlsConnectParams.timeout_ms, + .non_block = true + }; /* Use the AWS IoT ALPN extension for MQTT, if port 443 is requested */ if (pNetwork->tlsConnectParams.DestinationPort == 443) { const char *alpnProtocols[] = { "x-amzn-mqtt-ca", NULL }; - if ((ret = mbedtls_ssl_conf_alpn_protocols(&(tlsDataParams->conf), alpnProtocols)) != 0) { - ESP_LOGE(TAG, "failed! mbedtls_ssl_conf_alpn_protocols returned -0x%x", -ret); - return SSL_CONNECTION_ERROR; - } - } - - if((ret = mbedtls_ssl_setup(&(tlsDataParams->ssl), &(tlsDataParams->conf))) != 0) { - ESP_LOGE(TAG, "failed! mbedtls_ssl_setup returned -0x%x", -ret); - return SSL_CONNECTION_ERROR; + cfg.alpn_protos = alpnProtocols; } - if((ret = mbedtls_ssl_set_hostname(&(tlsDataParams->ssl), pNetwork->tlsConnectParams.pDestinationURL)) != 0) { - ESP_LOGE(TAG, "failed! mbedtls_ssl_set_hostname returned %d", ret); - return SSL_CONNECTION_ERROR; - } - ESP_LOGD(TAG, "SSL state connect : %d ", tlsDataParams->ssl.state); - mbedtls_ssl_set_bio(&(tlsDataParams->ssl), &(tlsDataParams->server_fd), mbedtls_net_send, NULL, - mbedtls_net_recv_timeout); - ESP_LOGD(TAG, "ok"); - - ESP_LOGD(TAG, "SSL state connect : %d ", tlsDataParams->ssl.state); - ESP_LOGD(TAG, "Performing the SSL/TLS handshake..."); rtc_clk_cpu_freq_set(RTC_CPU_FREQ_160M); - while((ret = mbedtls_ssl_handshake(&(tlsDataParams->ssl))) != 0) { - if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { - rtc_clk_cpu_freq_set(RTC_CPU_FREQ_80M); - ESP_LOGE(TAG, "failed! mbedtls_ssl_handshake returned -0x%x", -ret); - if(ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { - ESP_LOGE(TAG, " Unable to verify the server's certificate. "); - } - return SSL_CONNECTION_ERROR; - } - } - - rtc_clk_cpu_freq_set(RTC_CPU_FREQ_80M); + struct esp_tls *tls = esp_tls_conn_new(pNetwork->tlsConnectParams.pDestinationURL, strlen(pNetwork->tlsConnectParams.pDestinationURL), pNetwork->tlsConnectParams.DestinationPort, &cfg); - ESP_LOGD(TAG, "ok [ Protocol is %s ] [ Ciphersuite is %s ]", mbedtls_ssl_get_version(&(tlsDataParams->ssl)), - mbedtls_ssl_get_ciphersuite(&(tlsDataParams->ssl))); - if((ret = mbedtls_ssl_get_record_expansion(&(tlsDataParams->ssl))) >= 0) { - ESP_LOGD(TAG, " [ Record expansion is %d ]", ret); - } else { - ESP_LOGD(TAG, " [ Record expansion is unknown (compression) ]"); + if (!tls) { + ret = SSL_CONNECTION_ERROR; } - ESP_LOGD(TAG, "Verifying peer X.509 certificate..."); - - if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) { - if((tlsDataParams->flags = mbedtls_ssl_get_verify_result(&(tlsDataParams->ssl))) != 0) { - ESP_LOGE(TAG, "failed"); - mbedtls_x509_crt_verify_info(info_buf, sizeof(info_buf), " ! ", tlsDataParams->flags); - ESP_LOGE(TAG, "%s", info_buf); - ret = SSL_CONNECTION_ERROR; - } else { - ESP_LOGD(TAG, "ok"); - ret = SUCCESS; - } - } else { - ESP_LOGW(TAG, " Server Verification skipped"); - ret = SUCCESS; - } + tlsDataParams->timeout = pNetwork->tlsConnectParams.timeout_ms; + tlsDataParams->handle = (esp_network_handle_t)tls; - if(LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) { - if (mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl)) != NULL) { - ESP_LOGD(TAG, "Peer certificate information:"); - mbedtls_x509_crt_info((char *) info_buf, sizeof(info_buf) - 1, " ", mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl))); - ESP_LOGD(TAG, "%s", info_buf); - } - } + rtc_clk_cpu_freq_set(RTC_CPU_FREQ_80M); return (IoT_Error_t) ret; } @@ -336,11 +122,15 @@ IoT_Error_t iot_tls_write(Network *pNetwork, unsigned char *pMsg, size_t len, Ti bool isErrorFlag = false; int frags, ret = 0; TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams); + struct esp_tls *tls = (struct esp_tls *)tlsDataParams->handle; + if (!tls) { + return NULL_VALUE_ERROR; + } for(written_so_far = 0, frags = 0; written_so_far < len && !has_timer_expired(timer); written_so_far += ret, frags++) { while(!has_timer_expired(timer) && - (ret = mbedtls_ssl_write(&(tlsDataParams->ssl), pMsg + written_so_far, len - written_so_far)) <= 0) { + (ret = esp_tls_conn_write(tls, pMsg + written_so_far, len - written_so_far)) <= 0) { if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { ESP_LOGE(TAG, "failed! mbedtls_ssl_write returned -0x%x", -ret); /* All other negative return values indicate connection needs to be reset. @@ -367,24 +157,27 @@ IoT_Error_t iot_tls_write(Network *pNetwork, unsigned char *pMsg, size_t len, Ti IoT_Error_t iot_tls_read(Network *pNetwork, unsigned char *pMsg, size_t len, Timer *timer, size_t *read_len) { TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams); - mbedtls_ssl_context *ssl = &(tlsDataParams->ssl); - mbedtls_ssl_config *ssl_conf = &(tlsDataParams->conf); - uint32_t read_timeout; + struct esp_tls *tls = (struct esp_tls *)tlsDataParams->handle; + uint32_t read_timeout = tlsDataParams->timeout; size_t rxLen = 0; int ret; - - read_timeout = ssl_conf->read_timeout; + struct timeval timeout; + if (!tls) { + return NULL_VALUE_ERROR; + } while (len > 0) { - /* Make sure we never block on read for longer than timer has left, - but also that we don't block indefinitely (ie read_timeout > 0) */ - mbedtls_ssl_conf_read_timeout(ssl_conf, MAX(1, MIN(read_timeout, left_ms(timer)))); + but also that we don't block indefinitely (ie read_timeout > 0) */ + read_timeout = MAX(1, MIN(read_timeout, left_ms(timer))); + timeout.tv_sec = read_timeout / 1000; + timeout.tv_usec = (read_timeout % 1000) * 1000; - ret = mbedtls_ssl_read(ssl, pMsg, len); + ret = setsockopt(tls->sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval)); + ret = esp_tls_conn_read(tls, pMsg, len); /* Restore the old timeout */ - mbedtls_ssl_conf_read_timeout(ssl_conf, read_timeout); + tlsDataParams->timeout = read_timeout; if (ret > 0) { rxLen += ret; @@ -413,11 +206,13 @@ IoT_Error_t iot_tls_read(Network *pNetwork, unsigned char *pMsg, size_t len, Tim } IoT_Error_t iot_tls_disconnect(Network *pNetwork) { - mbedtls_ssl_context *ssl = &(pNetwork->tlsDataParams.ssl); - int ret = 0; - do { - ret = mbedtls_ssl_close_notify(ssl); - } while(ret == MBEDTLS_ERR_SSL_WANT_WRITE); + TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams); + struct esp_tls *tls = (struct esp_tls *)tlsDataParams->handle; + if (!tls) { + return NULL_VALUE_ERROR; + } + + esp_tls_conn_delete(tls); /* All other negative return values indicate connection needs to be reset. * No further action required since this is disconnect call */ @@ -427,16 +222,12 @@ IoT_Error_t iot_tls_disconnect(Network *pNetwork) { IoT_Error_t iot_tls_destroy(Network *pNetwork) { TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams); + struct esp_tls *tls = (struct esp_tls *)tlsDataParams->handle; + if (!tls) { + return NULL_VALUE_ERROR; + } - mbedtls_net_free(&(tlsDataParams->server_fd)); - - mbedtls_x509_crt_free(&(tlsDataParams->clicert)); - mbedtls_x509_crt_free(&(tlsDataParams->cacert)); - mbedtls_pk_free(&(tlsDataParams->pkey)); - mbedtls_ssl_free(&(tlsDataParams->ssl)); - mbedtls_ssl_config_free(&(tlsDataParams->conf)); - mbedtls_ctr_drbg_free(&(tlsDataParams->ctr_drbg)); - mbedtls_entropy_free(&(tlsDataParams->entropy)); + esp_tls_conn_delete(tls); return SUCCESS; } diff --git a/components/bootloader/Kconfig.projbuild b/components/bootloader/Kconfig.projbuild index b85b28876..d4b218221 100644 --- a/components/bootloader/Kconfig.projbuild +++ b/components/bootloader/Kconfig.projbuild @@ -10,6 +10,15 @@ config BOOTLOADER_INIT_SPI_FLASH If your system bootloader is based on v3.0, the option must not be enable, because the v3.0 bootloader don't support this function. +config BOOTLOADER_DISABLE_JTAG_IO + bool "Bootloader disable JTAG I/O" + default n + help + Enable this option, when SoC brings up and bootloader initializes hardware, it will + disable JTAG's I/O and set these GPIOs to be normal I/O with inputting mode. + + If users use JTAG to help develop, please disable this option. + choice LOG_BOOTLOADER_LEVEL bool "Bootloader log verbosity" default LOG_BOOTLOADER_LEVEL_INFO diff --git a/components/bootloader_support/include_priv/bootloader_config.h b/components/bootloader_support/include_priv/bootloader_config.h index dc5c6a6b2..78160341d 100644 --- a/components/bootloader_support/include_priv/bootloader_config.h +++ b/components/bootloader_support/include_priv/bootloader_config.h @@ -22,6 +22,7 @@ extern "C" { #endif +#include "sdkconfig.h" #include "esp_flash_data_types.h" #define SPI_SEC_SIZE 0x1000 @@ -34,6 +35,9 @@ typedef struct { esp_partition_pos_t ota_info; esp_partition_pos_t factory; esp_partition_pos_t test; +#ifdef CONFIG_LOAD_OLD_RF_PARAMETER + esp_partition_pos_t rf; +#endif esp_partition_pos_t ota[MAX_OTA_SLOTS]; uint32_t app_count; uint32_t selected_subtype; diff --git a/components/bootloader_support/src/bootloader_init.c b/components/bootloader_support/src/bootloader_init.c index 2ecf0a581..4348d5701 100644 --- a/components/bootloader_support/src/bootloader_init.c +++ b/components/bootloader_support/src/bootloader_init.c @@ -613,6 +613,17 @@ esp_err_t bootloader_init() static esp_err_t bootloader_main() { +#ifdef CONFIG_BOOTLOADER_DISABLE_JTAG_IO + /* Set GPIO 12-15 to be normal GPIO */ + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_GPIO13); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, FUNC_GPIO14); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_GPIO15); + + /* Set GPIO 12-15 to be input mode */ + GPIO_REG_WRITE(GPIO_ENABLE_W1TC_ADDRESS, BIT12 | BIT13 | BIT14 | BIT15); +#endif + uart_console_configure(); esp_image_header_t fhdr; diff --git a/components/bootloader_support/src/bootloader_utility.c b/components/bootloader_support/src/bootloader_utility.c index c6855c1a1..af587ce64 100644 --- a/components/bootloader_support/src/bootloader_utility.c +++ b/components/bootloader_support/src/bootloader_utility.c @@ -590,6 +590,9 @@ bool bootloader_utility_load_partition_table(bootloader_state_t* bs) partition_usage = "OTA data"; break; case PART_SUBTYPE_DATA_RF: +#ifdef CONFIG_LOAD_OLD_RF_PARAMETER + bs->rf = partition->pos; +#endif partition_usage = "RF data"; break; case PART_SUBTYPE_DATA_WIFI: @@ -613,7 +616,6 @@ bool bootloader_utility_load_partition_table(bootloader_state_t* bs) bootloader_munmap(partitions); #ifdef CONFIG_ESP8266_OTA_FROM_OLD - ESP_LOGI(TAG, "Copy firmware ..."); if (esp_patition_table_init_data(bs)) { ESP_LOGE(TAG,"Failed to update partition data"); return false; diff --git a/components/esp-tls/component.mk b/components/esp-tls/component.mk index 680168b73..52aa5d7e8 100644 --- a/components/esp-tls/component.mk +++ b/components/esp-tls/component.mk @@ -1,7 +1,12 @@ -ifdef CONFIG_SSL_USING_MBEDTLS -COMPONENT_SRCDIRS := . -COMPONENT_ADD_INCLUDEDIRS := . -else COMPONENT_SRCDIRS := COMPONENT_ADD_INCLUDEDIRS := + +ifdef CONFIG_SSL_USING_MBEDTLS +COMPONENT_SRCDIRS := . +COMPONENT_ADD_INCLUDEDIRS := . endif + +ifdef CONFIG_SSL_USING_WOLFSSL +COMPONENT_SRCDIRS := . +COMPONENT_ADD_INCLUDEDIRS := . +endif \ No newline at end of file diff --git a/components/esp-tls/esp_tls.c b/components/esp-tls/esp_tls.c index b97f4ebc0..039dc31a4 100644 --- a/components/esp-tls/esp_tls.c +++ b/components/esp-tls/esp_tls.c @@ -28,7 +28,12 @@ #endif static const char *TAG = "esp-tls"; +#if CONFIG_SSL_USING_MBEDTLS static mbedtls_x509_crt *global_cacert = NULL; +#else +static unsigned char *global_cacert = NULL; +static unsigned int global_cacert_pem_bytes = 0; +#endif #ifdef ESP_PLATFORM #include @@ -67,6 +72,7 @@ static ssize_t tcp_read(esp_tls_t *tls, char *data, size_t datalen) static ssize_t tls_read(esp_tls_t *tls, char *data, size_t datalen) { +#if CONFIG_SSL_USING_MBEDTLS ssize_t ret = mbedtls_ssl_read(&tls->ssl, (unsigned char *)data, datalen); if (ret < 0) { if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { @@ -76,6 +82,20 @@ static ssize_t tls_read(esp_tls_t *tls, char *data, size_t datalen) ESP_LOGE(TAG, "read error :%d:", ret); } } +#else + size_t ret = wolfSSL_read(tls->ssl, (unsigned char *)data, datalen); + if (ret < 0) { + ret = wolfSSL_get_error(tls->ssl, ret); + /* peer sent close notify */ + if (ret == WOLFSSL_ERROR_ZERO_RETURN) { + return 0; + } + + if (ret != WOLFSSL_ERROR_WANT_READ && ret != WOLFSSL_ERROR_WANT_WRITE) { + ESP_LOGE(TAG, "read error :%d:", ret); + } + } +#endif return ret; } @@ -146,12 +166,14 @@ static int esp_tcp_connect(const char *host, int hostlen, int port, int *sockfd, return ret; } + esp_err_t esp_tls_set_global_ca_store(const unsigned char *cacert_pem_buf, const unsigned int cacert_pem_bytes) { if (cacert_pem_buf == NULL) { ESP_LOGE(TAG, "cacert_pem_buf is null"); return ESP_ERR_INVALID_ARG; } +#if CONFIG_SSL_USING_MBEDTLS if (global_cacert != NULL) { mbedtls_x509_crt_free(global_cacert); } @@ -171,23 +193,43 @@ esp_err_t esp_tls_set_global_ca_store(const unsigned char *cacert_pem_buf, const ESP_LOGE(TAG, "mbedtls_x509_crt_parse was partly successful. No. of failed certificates: %d", ret); } return ESP_OK; +#else + if (global_cacert != NULL) { + esp_tls_free_global_ca_store(global_cacert); + } + + global_cacert = (unsigned char *)strndup((const char *)cacert_pem_buf, cacert_pem_bytes); + if (!global_cacert) + return ESP_FAIL; + + global_cacert_pem_bytes = cacert_pem_bytes; + + return ESP_OK; +#endif } -mbedtls_x509_crt *esp_tls_get_global_ca_store() +void *esp_tls_get_global_ca_store() { - return global_cacert; + return (void*)global_cacert; } void esp_tls_free_global_ca_store() { if (global_cacert) { +#if CONFIG_SSL_USING_MBEDTLS mbedtls_x509_crt_free(global_cacert); global_cacert = NULL; +#else + free(global_cacert); + global_cacert = NULL; + global_cacert_pem_bytes = 0; +#endif } } static void verify_certificate(esp_tls_t *tls) { +#if CONFIG_SSL_USING_MBEDTLS int flags; char buf[100]; if ((flags = mbedtls_ssl_get_verify_result(&tls->ssl)) != 0) { @@ -198,13 +240,22 @@ static void verify_certificate(esp_tls_t *tls) } else { ESP_LOGI(TAG, "Certificate verified."); } +#else + int flags; + if ((flags = wolfSSL_get_verify_result(tls->ssl)) != WOLFSSL_SUCCESS) { + ESP_LOGE(TAG, "Failed to verify peer certificate %d!", flags); + } else { + ESP_LOGI(TAG, "Certificate verified."); + } +#endif } -static void mbedtls_cleanup(esp_tls_t *tls) +static void esp_tls_cleanup(esp_tls_t *tls) { if (!tls) { return; } +#if CONFIG_SSL_USING_MBEDTLS if (tls->cacert_ptr != global_cacert) { mbedtls_x509_crt_free(tls->cacert_ptr); } @@ -217,12 +268,19 @@ static void mbedtls_cleanup(esp_tls_t *tls) mbedtls_ctr_drbg_free(&tls->ctr_drbg); mbedtls_ssl_free(&tls->ssl); mbedtls_net_free(&tls->server_fd); +#else + wolfSSL_shutdown(tls->ssl); + wolfSSL_free(tls->ssl); + close(tls->sockfd); + wolfSSL_CTX_free(tls->ctx); + wolfSSL_Cleanup(); +#endif } static int create_ssl_handle(esp_tls_t *tls, const char *hostname, size_t hostlen, const esp_tls_cfg_t *cfg) { int ret; - +#if CONFIG_SSL_USING_MBEDTLS mbedtls_net_init(&tls->server_fd); tls->server_fd.fd = tls->sockfd; mbedtls_ssl_init(&tls->ssl); @@ -326,8 +384,74 @@ static int create_ssl_handle(esp_tls_t *tls, const char *hostname, size_t hostle return 0; exit: - mbedtls_cleanup(tls); + esp_tls_cleanup(tls); + return -1; +#else + ret = wolfSSL_Init(); + if (ret != WOLFSSL_SUCCESS) { + ESP_LOGE(TAG, "Init wolfSSL failed: %d", ret); + goto exit; + } + + tls->ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()); + if (!tls->ctx) { + ESP_LOGE(TAG, "Set wolfSSL ctx failed"); + goto exit; + } + +#ifdef HAVE_ALPN + if (cfg->alpn_protos) { + char **alpn_list = (char **)cfg->alpn_protos; + for (; *alpn_list != NULL; alpn_list ++) { + if (wolfSSL_UseALPN(tls->ssl, *alpn_list, strlen(*alpn_list), WOLFSSL_ALPN_FAILED_ON_MISMATCH) != WOLFSSL_SUCCESS) { + ESP_LOGE(TAG, "Use wolfSSL ALPN failed"); + goto exit; + } + } + } +#endif + + if (cfg->use_global_ca_store == true) { + wolfSSL_CTX_load_verify_buffer(tls->ctx, global_cacert, global_cacert_pem_bytes, WOLFSSL_FILETYPE_PEM); + wolfSSL_CTX_set_verify(tls->ctx, SSL_VERIFY_PEER, NULL); + } else if (cfg->cacert_pem_buf != NULL) { + wolfSSL_CTX_load_verify_buffer(tls->ctx, cfg->cacert_pem_buf, cfg->cacert_pem_bytes, WOLFSSL_FILETYPE_PEM); + wolfSSL_CTX_set_verify(tls->ctx, SSL_VERIFY_PEER, NULL); + } else { + wolfSSL_CTX_set_verify(tls->ctx, SSL_VERIFY_NONE, NULL); + } + + if (cfg->clientcert_pem_buf != NULL && cfg->clientkey_pem_buf != NULL) { + wolfSSL_CTX_use_certificate_buffer(tls->ctx, cfg->clientcert_pem_buf, cfg->clientcert_pem_bytes, WOLFSSL_FILETYPE_PEM); + wolfSSL_CTX_use_PrivateKey_buffer(tls->ctx, cfg->clientkey_pem_buf, cfg->clientkey_pem_bytes, WOLFSSL_FILETYPE_PEM); + } else if (cfg->clientcert_pem_buf != NULL || cfg->clientkey_pem_buf != NULL) { + ESP_LOGE(TAG, "You have to provide both clientcert_pem_buf and clientkey_pem_buf for mutual authentication\n\n"); + goto exit; + } + + tls->ssl = wolfSSL_new(tls->ctx); + if (!tls->ssl) { + ESP_LOGE(TAG, "Create wolfSSL failed"); + goto exit; + } + +#ifdef HAVE_SNI + /* Hostname set here should match CN in server certificate */ + char *use_host = strndup(hostname, hostlen); + if (!use_host) { + goto exit; + } + wolfSSL_set_tlsext_host_name(tls->ssl, use_host); + free(use_host); +#endif + + wolfSSL_set_fd(tls->ssl, tls->sockfd); + + return 0; +exit: + esp_tls_cleanup(tls); return -1; +#endif } /** @@ -336,7 +460,7 @@ static int create_ssl_handle(esp_tls_t *tls, const char *hostname, size_t hostle void esp_tls_conn_delete(esp_tls_t *tls) { if (tls != NULL) { - mbedtls_cleanup(tls); + esp_tls_cleanup(tls); if (tls->sockfd) { close(tls->sockfd); } @@ -351,6 +475,7 @@ static ssize_t tcp_write(esp_tls_t *tls, const char *data, size_t datalen) static ssize_t tls_write(esp_tls_t *tls, const char *data, size_t datalen) { +#if CONFIG_SSL_USING_MBEDTLS ssize_t ret = mbedtls_ssl_write(&tls->ssl, (unsigned char*) data, datalen); if (ret < 0) { if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { @@ -358,6 +483,15 @@ static ssize_t tls_write(esp_tls_t *tls, const char *data, size_t datalen) } } return ret; +#else + ssize_t ret = wolfSSL_write(tls->ssl, (unsigned char*) data, datalen); + if (ret < 0) { + if (ret != WOLFSSL_ERROR_WANT_READ && ret != WOLFSSL_ERROR_WANT_WRITE) { + ESP_LOGE(TAG, "write error :%d:", ret); + } + } + return ret; +#endif } static int esp_tls_low_level_conn(const char *hostname, int hostlen, int port, const esp_tls_cfg_t *cfg, esp_tls_t *tls) @@ -427,6 +561,7 @@ static int esp_tls_low_level_conn(const char *hostname, int hostlen, int port, c /* falls through */ case ESP_TLS_HANDSHAKE: ESP_LOGD(TAG, "handshake in progress..."); +#if CONFIG_SSL_USING_MBEDTLS ret = mbedtls_ssl_handshake(&tls->ssl); if (ret == 0) { tls->conn_state = ESP_TLS_DONE; @@ -445,6 +580,26 @@ static int esp_tls_low_level_conn(const char *hostname, int hostlen, int port, c or MBEDTLS_ERR_SSL_WANT_WRITE during handshake */ return 0; } +#else + ret = wolfSSL_connect(tls->ssl); + if (ret == WOLFSSL_SUCCESS) { + tls->conn_state = ESP_TLS_DONE; + return 1; + } else { + if (ret != WOLFSSL_ERROR_WANT_READ && ret != WOLFSSL_ERROR_WANT_WRITE) { + ESP_LOGE(TAG, "wolfSSL_connect returned -0x%x", -ret); + if (cfg->cacert_pem_buf != NULL || cfg->use_global_ca_store == true) { + /* This is to check whether handshake failed due to invalid certificate*/ + verify_certificate(tls); + } + tls->conn_state = ESP_TLS_FAIL; + return -1; + } + /* Irrespective of blocking or non-blocking I/O, we return on getting wolfSSL_want_read + or wolfSSL_want_write during handshake */ + return 0; + } +#endif break; case ESP_TLS_FAIL: ESP_LOGE(TAG, "failed to open a new connection");; @@ -490,9 +645,13 @@ int esp_tls_conn_new_async(const char *hostname, int hostlen, int port, const es size_t esp_tls_get_bytes_avail(esp_tls_t *tls) { +#if CONFIG_SSL_USING_MBEDTLS if (!tls) { ESP_LOGE(TAG, "empty arg passed to esp_tls_get_bytes_avail()"); return ESP_FAIL; } return mbedtls_ssl_get_bytes_avail(&tls->ssl); +#else + return 0; +#endif } diff --git a/components/esp-tls/esp_tls.h b/components/esp-tls/esp_tls.h index 3782c0e96..246d7e816 100644 --- a/components/esp-tls/esp_tls.h +++ b/components/esp-tls/esp_tls.h @@ -18,6 +18,7 @@ #include #include +#if CONFIG_SSL_USING_MBEDTLS #include "mbedtls/platform.h" #include "mbedtls/net_sockets.h" #include "mbedtls/esp_debug.h" @@ -26,6 +27,9 @@ #include "mbedtls/ctr_drbg.h" #include "mbedtls/error.h" #include "mbedtls/certs.h" +#else +#include "wolfssl/ssl.h" +#endif #ifdef __cplusplus extern "C" { @@ -90,6 +94,7 @@ typedef struct esp_tls_cfg { * @brief ESP-TLS Connection Handle */ typedef struct esp_tls { +#if CONFIG_SSL_USING_MBEDTLS mbedtls_ssl_context ssl; /*!< TLS/SSL context */ mbedtls_entropy_context entropy; /*!< mbedTLS entropy context structure */ @@ -112,7 +117,10 @@ typedef struct esp_tls { mbedtls_pk_context clientkey; /*!< Container for the private key of the client certificate */ - +#else + WOLFSSL_CTX *ctx; + WOLFSSL *ssl; +#endif int sockfd; /*!< Underlying socket file descriptor. */ ssize_t (*esp_tls_read)(struct esp_tls *tls, char *data, size_t datalen); /*!< Callback function for reading data from TLS/SSL @@ -258,7 +266,7 @@ esp_err_t esp_tls_set_global_ca_store(const unsigned char *cacert_pem_buf, const * - Pointer to the global CA store currently being used if successful. * - NULL if there is no global CA store set. */ -mbedtls_x509_crt *esp_tls_get_global_ca_store(); +void *esp_tls_get_global_ca_store(); /** * @brief Free the global CA store currently being used. diff --git a/components/esp8266/Kconfig b/components/esp8266/Kconfig index 1427e193d..5bb004ae7 100644 --- a/components/esp8266/Kconfig +++ b/components/esp8266/Kconfig @@ -217,7 +217,7 @@ config ESP8266_OTA_FROM_OLD bool "(**Expected**)ESP8266 update from old SDK by OTA" default n depends on TARGET_PLATFORM_ESP8266 - select ESP8266_BOOT_COPY_APP + select ESP8266_BOOT_COPY_APP if ESPTOOLPY_FLASHSIZE_1MB help The function is not released. @@ -226,6 +226,19 @@ config ESP8266_OTA_FROM_OLD The old RTOS SDK(before V3.0) or NonOS SDK can download the firmware to its partition and run it as it self's application. +config LOAD_OLD_RF_PARAMETER + bool "(**Expected**)Load old RF Parameters" + default n + depends on ESP8266_OTA_FROM_OLD + select ESP_PHY_INIT_DATA_IN_PARTITION + help + The function is not released. + + Enable this option, after updating from old SDK to new SDK, bootloader will copy RF + parameters from old SDK partition to new SDK partition. + + Then application can read the RF parameters from new partition directly. + config ESP8266_BOOT_COPY_APP bool "(**Expected**)Boot copy app" default n @@ -265,9 +278,12 @@ config ESP_PHY_CALIBRATION_AND_DATA_STORAGE default y help If this option is enabled, NVS will be initialized and calibration data will be loaded from there. - PHY calibration will be skipped on deep sleep wakeup. If calibration data is not found, full calibration - will be performed and stored in NVS. Normally, only partial calibration will be performed. - If this option is disabled, full calibration will be performed. + If calibration data is not found, full calibration will be performed and stored in NVS. Normally, + only partial calibration will be performed. If this option is disabled, full calibration will be performed. + + Full calibration needs 170 - 180ms. + Partial calibration needs 35 - 40ms. + No calibration needs 3.260 - 3.264ms. If it's easy that your board calibrate bad data, choose 'n'. Two cases for example, you should choose 'n': diff --git a/components/esp8266/Makefile.projbuild b/components/esp8266/Makefile.projbuild index 735d0ae94..06bc333cc 100644 --- a/components/esp8266/Makefile.projbuild +++ b/components/esp8266/Makefile.projbuild @@ -35,14 +35,14 @@ PHY_INIT_DATA_OBJ = $(BUILD_DIR_BASE)/phy_init_data.o PHY_INIT_DATA_BIN = $(BUILD_DIR_BASE)/phy_init_data.bin # Command to flash PHY init data partition -PHY_INIT_DATA_FLASH_CMD = $(ESPTOOLPY_SERIAL) write_flash $(CONFIG_PHY_DATA_OFFSET) $(PHY_INIT_DATA_BIN) -ESPTOOL_ALL_FLASH_ARGS += $(CONFIG_PHY_DATA_OFFSET) $(PHY_INIT_DATA_BIN) +PHY_INIT_DATA_FLASH_CMD = $(ESPTOOLPY_SERIAL) write_flash $(PHY_DATA_OFFSET) $(PHY_INIT_DATA_BIN) +ESPTOOL_ALL_FLASH_ARGS += $(PHY_DATA_OFFSET) $(PHY_INIT_DATA_BIN) ESP8266_COMPONENT_PATH := $(COMPONENT_PATH) -$(PHY_INIT_DATA_OBJ): $(ESP8266_COMPONENT_PATH)/source/phy_init_data.h $(BUILD_DIR_BASE)/include/sdkconfig.h +$(PHY_INIT_DATA_OBJ): $(ESP8266_COMPONENT_PATH)/include/internal/phy_init_data.h $(BUILD_DIR_BASE)/include/sdkconfig.h $(summary) CC $(notdir $@) - printf "#include \"source/phy_init_data.h\"\n" | $(CC) -I $(BUILD_DIR_BASE)/include -I $(ESP8266_COMPONENT_PATH) -I $(ESP8266_COMPONENT_PATH)/include -c -o $@ -xc - + printf "#include \"internal/phy_init_data.h\"\n" | $(CC) -I $(BUILD_DIR_BASE)/include -I $(ESP8266_COMPONENT_PATH) -I $(ESP8266_COMPONENT_PATH)/include -c -o $@ -xc - $(PHY_INIT_DATA_BIN): $(PHY_INIT_DATA_OBJ) $(summary) BIN $(notdir $@) @@ -91,46 +91,35 @@ OTA2_BIN := ./build/$(PROJECT_NAME).app2.bin OTA_V2_TO_V3_BIN := ./build/$(PROJECT_NAME).v2_to_v3.ota.bin -CONFIG_APP2_OFFSET ?= $(CONFIG_APP1_OFFSET) -CONFIG_APP2_SIZE ?= $(CONFIG_APP1_SIZE) - -OTA1_OFFSET := CONFIG_APP1_OFFSET -ifdef CONFIG_ESP8266_BOOT_COPY_APP -OTA2_LINK_OFFSET := $(CONFIG_APP1_OFFSET) -else -OTA2_LINK_OFFSET := $(CONFIG_APP2_OFFSET) +ifndef CONFIG_ESP8266_BOOT_COPY_APP +ifdef CONFIG_ESPTOOLPY_FLASHSIZE_1MB +__COMBILE_OTA_BIN := 1 endif - -$(OTA2_BIN): all_binaries -ifeq ($(CONFIG_ESPTOOLPY_FLASHSIZE), "1MB") - @rm -f ./build/esp8266/esp8266_out.ld - @make APP_OFFSET=$(OTA2_LINK_OFFSET) APP_SIZE=$(CONFIG_APP2_SIZE) CFLAGS= CXXFLAGS= endif - @cp $(RAW_BIN) $(OTA2_BIN) - @echo [GEN] $(OTA2_BIN) $(OTA1_BIN): all_binaries -ifeq ($(CONFIG_ESPTOOLPY_FLASHSIZE), "1MB") - @rm -f ./build/esp8266/esp8266_out.ld -endif - @make APP_OFFSET=$(CONFIG_APP1_OFFSET) APP_SIZE=$(CONFIG_APP1_SIZE) CFLAGS= CXXFLAGS= @cp $(RAW_BIN) $(OTA1_BIN) @echo [GEN] $(OTA1_BIN) -$(OTA_BIN): $(OTA1_BIN) $(OTA2_BIN) +$(OTA2_BIN): $(OTA1_BIN) +ifdef __COMBILE_OTA_BIN + @rm -f ./build/esp8266/esp8266_out.ld + @export CFLAGS= && export CXXFLAGS= && make APP_OFFSET=$(APP2_OFFSET) APP_SIZE=$(APP2_SIZE) +endif + @cp $(RAW_BIN) $(OTA2_BIN) + @echo [GEN] $(OTA2_BIN) + +$(OTA_BIN): $(OTA2_BIN) @cp $(OTA1_BIN) $(OTA_BIN) -ifeq ($(CONFIG_ESPTOOLPY_FLASHSIZE), "1MB") +ifdef __COMBILE_OTA_BIN @cat $(OTA2_BIN) >> $(OTA_BIN) -endif @cp $(OTA1_BIN) $(RAW_BIN) +endif @echo [GEN] $(OTA_BIN) ifdef CONFIG_ESP8266_OTA_FROM_OLD -$(OTA_V2_TO_V3_BIN): $(OTA_BIN) - @cp $(RAW_BIN) $(RAW_BIN).tmp.bak - @cp $(OTA1_BIN) $(RAW_BIN) - @python $(IDF_PATH)/tools/pack_fw.py --output $(OTA_V2_TO_V3_BIN) pack3 $(ESPTOOL_ALL_FLASH_ARGS) - @cp $(RAW_BIN).tmp.bak $(RAW_BIN) +$(OTA_V2_TO_V3_BIN): all + @python $(IDF_PATH)/tools/pack_fw.py --output $(OTA_V2_TO_V3_BIN) --app $(PROJECT_NAME).bin pack3 $(ESPTOOL_ALL_FLASH_ARGS) @echo [GEN] $(OTA_V2_TO_V3_BIN) endif diff --git a/components/esp8266/component.mk b/components/esp8266/component.mk index 3f55a7d6f..6b7d027e6 100644 --- a/components/esp8266/component.mk +++ b/components/esp8266/component.mk @@ -41,10 +41,8 @@ COMPONENT_ADD_LINKER_DEPS := $(ALL_LIB_FILES) $(addprefix ld/,$(LINKER_SCRIPTS)) # saves us from having to add the target to a Makefile.projbuild $(COMPONENT_LIBRARY): esp8266_out.ld esp8266_common_out.ld -OUTLD_CFLAGS := -DAPP_OFFSET=$(APP_OFFSET) -DAPP_SIZE=$(APP_SIZE) - esp8266_out.ld: $(COMPONENT_PATH)/ld/esp8266.ld ../include/sdkconfig.h - $(CC) $(OUTLD_CFLAGS) -I ../include -C -P -x c -E $< -o $@ + $(CC) $(CFLAGS) -I ../include -C -P -x c -E $< -o $@ esp8266_common_out.ld: $(COMPONENT_PATH)/ld/esp8266.common.ld ../include/sdkconfig.h $(CC) -I ../include -C -P -x c -E $< -o $@ diff --git a/components/esp8266/driver/gpio.c b/components/esp8266/driver/gpio.c index a1c5d5460..aee84cca9 100644 --- a/components/esp8266/driver/gpio.c +++ b/components/esp8266/driver/gpio.c @@ -86,7 +86,10 @@ static gpio_isr_func_t *gpio_isr_func = NULL; esp_err_t gpio_pullup_en(gpio_num_t gpio_num) { GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG); - GPIO_CHECK(!RTC_GPIO_IS_VALID_GPIO(gpio_num), "The RTC GPIO of esp8266 can not be pulled up.", ESP_ERR_INVALID_ARG); + + if (RTC_GPIO_IS_VALID_GPIO(gpio_num)) { + return ESP_OK; + } gpio_pin_reg_t pin_reg; pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(gpio_num)); @@ -98,7 +101,10 @@ esp_err_t gpio_pullup_en(gpio_num_t gpio_num) esp_err_t gpio_pullup_dis(gpio_num_t gpio_num) { GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG); - GPIO_CHECK(!RTC_GPIO_IS_VALID_GPIO(gpio_num), "The RTC GPIO of esp8266 can not be pulled up.", ESP_ERR_INVALID_ARG); + + if (RTC_GPIO_IS_VALID_GPIO(gpio_num)) { + return ESP_OK; + } gpio_pin_reg_t pin_reg; pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(gpio_num)); @@ -110,7 +116,10 @@ esp_err_t gpio_pullup_dis(gpio_num_t gpio_num) esp_err_t gpio_pulldown_en(gpio_num_t gpio_num) { GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG); - GPIO_CHECK(RTC_GPIO_IS_VALID_GPIO(gpio_num), "The GPIO of esp8266 can not be pulled down except RTC GPIO.", ESP_ERR_INVALID_ARG); + + if (!RTC_GPIO_IS_VALID_GPIO(gpio_num)) { + return ESP_OK; + } gpio_pin_reg_t pin_reg; pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(gpio_num)); @@ -122,7 +131,10 @@ esp_err_t gpio_pulldown_en(gpio_num_t gpio_num) esp_err_t gpio_pulldown_dis(gpio_num_t gpio_num) { GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG); - GPIO_CHECK(RTC_GPIO_IS_VALID_GPIO(gpio_num), "The GPIO of esp8266 can not be pulled down except RTC GPIO.", ESP_ERR_INVALID_ARG); + + if (!RTC_GPIO_IS_VALID_GPIO(gpio_num)) { + return ESP_OK; + } gpio_pin_reg_t pin_reg; pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(gpio_num)); diff --git a/components/esp8266/driver/uart.c b/components/esp8266/driver/uart.c index 2db832b7c..b0eec59fc 100644 --- a/components/esp8266/driver/uart.c +++ b/components/esp8266/driver/uart.c @@ -562,7 +562,11 @@ static void uart_rx_intr_handler_default(void *param) } if (p_uart->tx_len_tot == 0) { - en_tx_flg = false; + if (tx_fifo_rem == 0) { + en_tx_flg = true; + } else{ + en_tx_flg = false; + } xSemaphoreGiveFromISR(p_uart->tx_done_sem, &task_woken); if (task_woken == pdTRUE) { portYIELD_FROM_ISR(); diff --git a/components/esp8266/include/esp8266/rom_functions.h b/components/esp8266/include/esp8266/rom_functions.h index 80d8a593d..246622a8b 100644 --- a/components/esp8266/include/esp8266/rom_functions.h +++ b/components/esp8266/include/esp8266/rom_functions.h @@ -4,6 +4,8 @@ #include #include +#define ROM_FLASH_BUF_DECLARE(__name, __size) uint8_t __name[__size] __attribute__((aligned(4))) + typedef struct esp_spi_flash_chip { uint32_t deviceId; uint32_t chip_size; // chip size in byte diff --git a/components/esp8266/source/phy_init_data.h b/components/esp8266/include/internal/phy_init_data.h similarity index 100% rename from components/esp8266/source/phy_init_data.h rename to components/esp8266/include/internal/phy_init_data.h diff --git a/components/esp8266/ld/esp8266.common.ld b/components/esp8266/ld/esp8266.common.ld index f35ca08ae..772e3743b 100644 --- a/components/esp8266/ld/esp8266.common.ld +++ b/components/esp8266/ld/esp8266.common.ld @@ -106,6 +106,7 @@ SECTIONS *(.init) *(.iram1 .iram1.*) *libspi_flash.a:spi_flash_raw.o(.literal .text .literal.* .text.*) + *libpp.a:lmac.o(.literal .text .literal.* .text.*) *(.literal .text .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) *(.fini.literal) *(.fini) @@ -133,6 +134,8 @@ SECTIONS *libesp8266.a:ets_printf.o(.literal .text .literal.* .text.* .rodata.* .rodata) #endif + *libheap.a:(.literal .text .literal.* .text.*) + _text_end = ABSOLUTE(.); _etext = .; } >iram1_0_seg :iram1_0_phdr diff --git a/components/esp8266/lib/VERSION b/components/esp8266/lib/VERSION index 4ffe8bdd9..16f162f51 100644 --- a/components/esp8266/lib/VERSION +++ b/components/esp8266/lib/VERSION @@ -1,10 +1,10 @@ gwen: - core: 5550687 - net80211: 8d274fc - pp: 7a71e86 - wpa: 4e2372f - espnow: eeb16c6 - wps: 4e2372f + core: f91b7e5 + net80211: 23a826d + pp: f91b7e5 + wpa: f91b7e5 + espnow: f91b7e5 + wps: f91b7e5 smartconfig: 2.8.1 - phy: 1055_8 + phy: 1058.15 diff --git a/components/esp8266/lib/libcore.a b/components/esp8266/lib/libcore.a index 3d3c548a0..7f5942d6f 100644 Binary files a/components/esp8266/lib/libcore.a and b/components/esp8266/lib/libcore.a differ diff --git a/components/esp8266/lib/libespnow.a b/components/esp8266/lib/libespnow.a index 0d8a05351..5c344096d 100644 Binary files a/components/esp8266/lib/libespnow.a and b/components/esp8266/lib/libespnow.a differ diff --git a/components/esp8266/lib/libnet80211.a b/components/esp8266/lib/libnet80211.a index c650797ed..3d1033e4e 100644 Binary files a/components/esp8266/lib/libnet80211.a and b/components/esp8266/lib/libnet80211.a differ diff --git a/components/esp8266/lib/libphy.a b/components/esp8266/lib/libphy.a index 12ce50f71..8af1692af 100644 Binary files a/components/esp8266/lib/libphy.a and b/components/esp8266/lib/libphy.a differ diff --git a/components/esp8266/lib/libpp.a b/components/esp8266/lib/libpp.a index eb99ef112..4565cc91b 100644 Binary files a/components/esp8266/lib/libpp.a and b/components/esp8266/lib/libpp.a differ diff --git a/components/esp8266/lib/libssc.a b/components/esp8266/lib/libssc.a index f0d047e7d..a445095df 100644 Binary files a/components/esp8266/lib/libssc.a and b/components/esp8266/lib/libssc.a differ diff --git a/components/esp8266/lib/libwpa.a b/components/esp8266/lib/libwpa.a index c337f36c7..12ac73184 100644 Binary files a/components/esp8266/lib/libwpa.a and b/components/esp8266/lib/libwpa.a differ diff --git a/components/esp8266/lib/libwps.a b/components/esp8266/lib/libwps.a index a35f96086..7efa34fc2 100644 Binary files a/components/esp8266/lib/libwps.a and b/components/esp8266/lib/libwps.a differ diff --git a/components/esp8266/source/esp_timer.c b/components/esp8266/source/esp_timer.c index a2e1ccc22..6d966c30e 100644 --- a/components/esp8266/source/esp_timer.c +++ b/components/esp8266/source/esp_timer.c @@ -21,6 +21,14 @@ #define ESP_TIMER_HZ CONFIG_FREERTOS_HZ +typedef enum { + ESP_TIMER_INIT = 0, + ESP_TIMER_ONCE, + ESP_TIMER_CYCLE, + ESP_TIMER_STOP, + ESP_TIMER_DELETE, +} esp_timer_state_t; + struct esp_timer { TimerHandle_t os_timer; @@ -28,26 +36,64 @@ struct esp_timer { void *arg; - TickType_t period_ticks; + esp_timer_state_t state; }; static const char *TAG = "esp_timer"; +static esp_err_t delete_timer(esp_timer_handle_t timer) +{ + BaseType_t ret = xTimerDelete(timer->os_timer, portMAX_DELAY); + if (ret == pdPASS) + heap_caps_free(timer); + + return ret == pdPASS ? ESP_OK : ESP_ERR_NO_MEM; +} + /** * @brief FreeRTOS callback function */ static void esp_timer_callback(TimerHandle_t xTimer) { - BaseType_t os_ret; struct esp_timer *timer = (struct esp_timer *)pvTimerGetTimerID(xTimer); timer->cb(timer->arg); - if (!timer->period_ticks) { - os_ret = xTimerStop(timer->os_timer, 0); - if (os_ret != pdPASS) { - ESP_LOGE(TAG, "Set timer from periodic to once error"); + switch (timer->state) { + case ESP_TIMER_INIT: + case ESP_TIMER_STOP: + break; + case ESP_TIMER_CYCLE: { + BaseType_t ret = xTimerReset(timer->os_timer, portMAX_DELAY); + if (ret != pdPASS) { + ESP_LOGE(TAG, "start timer at callback error"); + } else { + ESP_LOGD(TAG, "start timer at callback OK"); + } + break; + } + case ESP_TIMER_ONCE: { + BaseType_t ret = xTimerStop(timer->os_timer, portMAX_DELAY); + if (ret != pdPASS) { + ESP_LOGE(TAG, "stop timer at callback error"); + } else { + timer->state = ESP_TIMER_STOP; + ESP_LOGD(TAG, "stop timer at callback OK"); + } + break; + } + case ESP_TIMER_DELETE: { + esp_err_t ret = delete_timer(timer); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "delete timer at callback error"); + } else { + ESP_LOGD(TAG, "delete timer at callback OK"); + } + break; } + default: + ESP_LOGE(TAG, "timer state error is %d", timer->state); + break; } } @@ -83,17 +129,16 @@ esp_err_t esp_timer_create(const esp_timer_create_args_t* create_args, if (!esp_timer) return ESP_ERR_NO_MEM; - esp_timer->cb = create_args->callback; - esp_timer->arg = create_args->arg; - esp_timer->period_ticks = 0; - os_timer = xTimerCreate(create_args->name, portMAX_DELAY, - pdTRUE, + pdFALSE, esp_timer, esp_timer_callback); if (os_timer) { esp_timer->os_timer = os_timer; + esp_timer->cb = create_args->callback; + esp_timer->arg = create_args->arg; + esp_timer->state = ESP_TIMER_INIT; *out_handle = (esp_timer_handle_t)esp_timer; } else { heap_caps_free(esp_timer); @@ -120,14 +165,7 @@ esp_err_t esp_timer_start_once(esp_timer_handle_t timer, uint64_t timeout_us) os_ret = xTimerChangePeriod(os_timer, ticks, portMAX_DELAY); if (os_ret == pdPASS) { - TickType_t period_ticks = timer->period_ticks; - - timer->period_ticks = 0; - os_ret = xTimerStart(os_timer, portMAX_DELAY); - if (os_ret != pdPASS) { - timer->period_ticks = period_ticks; - return ESP_ERR_INVALID_STATE; - } + timer->state = ESP_TIMER_ONCE; } else { return ESP_ERR_INVALID_STATE; } @@ -152,14 +190,7 @@ esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period) os_ret = xTimerChangePeriod(os_timer, ticks, portMAX_DELAY); if (os_ret == pdPASS) { - TickType_t period_ticks = timer->period_ticks; - - timer->period_ticks = ticks; - os_ret = xTimerStart(os_timer, portMAX_DELAY); - if (os_ret != pdPASS) { - timer->period_ticks = period_ticks; - return ESP_ERR_INVALID_STATE; - } + timer->state = ESP_TIMER_CYCLE; } else { return ESP_ERR_INVALID_STATE; } @@ -178,6 +209,8 @@ esp_err_t esp_timer_stop(esp_timer_handle_t timer) BaseType_t os_ret; os_ret = xTimerStop(os_timer, portMAX_DELAY); + if (os_ret == pdPASS) + timer->state = ESP_TIMER_STOP; return os_ret == pdPASS ? ESP_OK : ESP_ERR_INVALID_STATE; } @@ -187,14 +220,25 @@ esp_err_t esp_timer_stop(esp_timer_handle_t timer) */ esp_err_t esp_timer_delete(esp_timer_handle_t timer) { + esp_err_t ret; + assert(timer); - TimerHandle_t os_timer = timer->os_timer; - BaseType_t os_ret; + if (xTimerGetTimerDaemonTaskHandle() == xTaskGetCurrentTaskHandle()) { + timer->state = ESP_TIMER_DELETE; + ret = ESP_OK; + } else { + UBaseType_t prio = uxTaskPriorityGet(NULL); + if (prio >= configTIMER_TASK_PRIORITY) + vTaskPrioritySet(NULL, configTIMER_TASK_PRIORITY - 1); + else + prio = 0; - os_ret = xTimerDelete(os_timer, portMAX_DELAY); - if (os_ret == pdPASS) - heap_caps_free(timer); + ret = delete_timer(timer); + + if (prio) + vTaskPrioritySet(NULL, prio); + } - return os_ret == pdPASS ? ESP_OK : ESP_ERR_INVALID_STATE; + return ret; } diff --git a/components/esp8266/source/esp_wifi_os_adapter.c b/components/esp8266/source/esp_wifi_os_adapter.c index 519dc899f..6964928dd 100644 --- a/components/esp8266/source/esp_wifi_os_adapter.c +++ b/components/esp8266/source/esp_wifi_os_adapter.c @@ -50,7 +50,7 @@ static void task_yield_wrapper(void) portYIELD(); } -static void task_yield_from_isr_wrapper(void) +static void IRAM_ATTR task_yield_from_isr_wrapper(void) { portYIELD(); } @@ -75,12 +75,12 @@ static uint32_t task_ms_to_tick_wrapper(uint32_t ms) return (uint32_t)(ms / portTICK_RATE_MS); } -static void task_suspend_all_wrapper(void) +static void IRAM_ATTR task_suspend_all_wrapper(void) { vTaskSuspendAll(); } -static void task_resume_all_wrapper(void) +static void IRAM_ATTR task_resume_all_wrapper(void) { xTaskResumeAll(); } @@ -206,7 +206,7 @@ static bool queue_send_wrapper(void *queue, void *item, uint32_t block_time_tick return ret == pdPASS ? true : false; } -static bool queue_send_from_isr_wrapper(void *queue, void *item, int *hptw) +static bool IRAM_ATTR queue_send_from_isr_wrapper(void *queue, void *item, int *hptw) { signed portBASE_TYPE ret; @@ -272,7 +272,7 @@ static bool timer_delete_wrapper(void *timer, uint32_t ticks) return xTimerDelete(timer, ticks); } -static void *malloc_wrapper(uint32_t s, uint32_t cap, const char *file, size_t line) +static void IRAM_ATTR *malloc_wrapper(uint32_t s, uint32_t cap, const char *file, size_t line) { uint32_t os_caps; @@ -284,7 +284,7 @@ static void *malloc_wrapper(uint32_t s, uint32_t cap, const char *file, size_t l return _heap_caps_malloc(s, os_caps, file, line); } -static void *zalloc_wrapper(uint32_t s, uint32_t cap, const char *file, size_t line) +static void IRAM_ATTR *zalloc_wrapper(uint32_t s, uint32_t cap, const char *file, size_t line) { uint32_t os_caps; @@ -296,7 +296,7 @@ static void *zalloc_wrapper(uint32_t s, uint32_t cap, const char *file, size_t l return _heap_caps_zalloc(s, os_caps, file, line); } -static void *realloc_wrapper(void *ptr, uint32_t s, uint32_t cap, const char *file, size_t line) +static void IRAM_ATTR *realloc_wrapper(void *ptr, uint32_t s, uint32_t cap, const char *file, size_t line) { uint32_t os_caps; @@ -308,7 +308,7 @@ static void *realloc_wrapper(void *ptr, uint32_t s, uint32_t cap, const char *fi return _heap_caps_realloc(ptr, s, os_caps, file, line); } -static void *calloc_wrapper(uint32_t cnt, uint32_t s, uint32_t cap, const char *file, size_t line) +static void IRAM_ATTR *calloc_wrapper(uint32_t cnt, uint32_t s, uint32_t cap, const char *file, size_t line) { uint32_t os_caps; @@ -320,7 +320,7 @@ static void *calloc_wrapper(uint32_t cnt, uint32_t s, uint32_t cap, const char * return _heap_caps_calloc(cnt , s, os_caps, file, line); } -static void free_wrapper(void *ptr, const char *file, size_t line) +static void IRAM_ATTR free_wrapper(void *ptr, const char *file, size_t line) { _heap_caps_free(ptr, file, line); } @@ -342,7 +342,7 @@ void *osi_task_top_sp(void) return pxCurrentTCB[0]; } -const wifi_osi_funcs_t s_wifi_osi_funcs = { +wifi_osi_funcs_t s_wifi_osi_funcs = { .version = ESP_WIFI_OS_ADAPTER_VERSION, .task_create = task_create_wrapper, diff --git a/components/esp8266/source/phy.h b/components/esp8266/source/phy.h index 32c5376d4..b3cd5fd10 100644 --- a/components/esp8266/source/phy.h +++ b/components/esp8266/source/phy.h @@ -26,6 +26,8 @@ uint8_t phy_check_data_table(uint32_t *table, uint8_t, uint8_t); void phy_afterwake_set_rfoption(uint8_t); +void phy_set_powerup_option(uint8_t); + void write_data_to_rtc(uint8_t *); void get_data_from_rtc(uint8_t *); diff --git a/components/esp8266/source/phy_init.c b/components/esp8266/source/phy_init.c index 19a2d0246..f5814dffa 100644 --- a/components/esp8266/source/phy_init.c +++ b/components/esp8266/source/phy_init.c @@ -27,7 +27,7 @@ #include "nvs_flash.h" #include "sdkconfig.h" -#include "phy_init_data.h" +#include "internal/phy_init_data.h" #include "phy.h" static const char *TAG = "phy_init"; @@ -76,6 +76,7 @@ esp_err_t esp_phy_rf_init(const esp_phy_init_data_t *init_data, esp_phy_calibrat #endif memcpy(local_init_data, init_data->params, 128); + memcpy(local_init_data + 128, calibration_data->rf_cal_data, 128); extern uint32_t *phy_rx_gain_dc_table; phy_rx_gain_dc_table = calibration_data->rx_gain_dc_table; @@ -85,7 +86,10 @@ esp_err_t esp_phy_rf_init(const esp_phy_init_data_t *init_data, esp_phy_calibrat phy_afterwake_set_rfoption(1); if (!cal_data_check) { + phy_set_powerup_option(1); write_data_to_rtc(calibration_data->rf_cal_data); + } else { + phy_set_powerup_option(3); } esp_efuse_mac_get_default(sta_mac); diff --git a/components/esp8266/source/system_api.c b/components/esp8266/source/system_api.c index a308d8721..e8437cf5e 100644 --- a/components/esp8266/source/system_api.c +++ b/components/esp8266/source/system_api.c @@ -36,7 +36,7 @@ esp_err_t esp_base_mac_addr_set(uint8_t *mac) { if (mac == NULL) { ESP_LOGE(TAG, "Base MAC address is NULL"); - abort(); + return ESP_ERR_INVALID_ARG; } memcpy(base_mac_addr, mac, 6); @@ -65,6 +65,7 @@ esp_err_t esp_efuse_mac_get_default(uint8_t* mac) uint8_t efuse_crc = 0; uint8_t calc_crc = 0; uint8_t version; + uint8_t use_default = 1; efuse[0] = REG_READ(EFUSE_DATA0_REG); efuse[1] = REG_READ(EFUSE_DATA1_REG); @@ -82,6 +83,8 @@ esp_err_t esp_efuse_mac_get_default(uint8_t* mac) mac[1] = efuse[3] >> 8; mac[2] = efuse[3]; + use_default = 0; + tmp_mac[0] = mac[2]; tmp_mac[1] = mac[1]; tmp_mac[2] = mac[0]; @@ -89,28 +92,28 @@ esp_err_t esp_efuse_mac_get_default(uint8_t* mac) efuse_crc = efuse[2] >> 24; calc_crc = esp_crc8(tmp_mac, 3); - if (efuse_crc != calc_crc) { - ESP_LOGE(TAG, "High MAC CRC error, efuse_crc = 0x%02x; calc_crc = 0x%02x", efuse_crc, calc_crc); - return ESP_ERR_INVALID_MAC; - } + if (efuse_crc != calc_crc) + use_default = 1; - version = (efuse[1] >> EFUSE_VERSION_S) & EFUSE_VERSION_V; + if (!use_default) { + version = (efuse[1] >> EFUSE_VERSION_S) & EFUSE_VERSION_V; - if (version == EFUSE_VERSION_1 || version == EFUSE_VERSION_2) { - tmp_mac[0] = mac[5]; - tmp_mac[1] = mac[4]; - tmp_mac[2] = mac[3]; - tmp_mac[3] = efuse[1] >> 16; + if (version == EFUSE_VERSION_1 || version == EFUSE_VERSION_2) { + tmp_mac[0] = mac[5]; + tmp_mac[1] = mac[4]; + tmp_mac[2] = mac[3]; + tmp_mac[3] = efuse[1] >> 16; - efuse_crc = efuse[0] >> 16; - calc_crc = esp_crc8(tmp_mac, 4); + efuse_crc = efuse[0] >> 16; + calc_crc = esp_crc8(tmp_mac, 4); - if (efuse_crc != calc_crc) { - ESP_LOGE(TAG, "CRC8 error, efuse_crc = 0x%02x; calc_crc = 0x%02x", efuse_crc, calc_crc); - return ESP_ERR_INVALID_MAC; + if (efuse_crc != calc_crc) + use_default = 1; } } - } else { + } + + if (use_default) { mac[0] = 0x18; mac[1] = 0xFE; mac[2] = 0x34; diff --git a/components/esp8266/source/task_wdt.c b/components/esp8266/source/task_wdt.c index 40cd8c307..c8dc9d6f4 100644 --- a/components/esp8266/source/task_wdt.c +++ b/components/esp8266/source/task_wdt.c @@ -14,6 +14,7 @@ #include +#include "esp_attr.h" #include "esp_log.h" #include "esp_libc.h" #include "esp_wifi_osi.h" @@ -78,7 +79,7 @@ esp_err_t esp_task_wdt_init(void) * @brief Reset(Feed) the Task Watchdog Timer (TWDT) on behalf of the currently * running task */ -void esp_task_wdt_reset(void) +void IRAM_ATTR esp_task_wdt_reset(void) { WDT_FEED(); } @@ -88,7 +89,7 @@ void esp_task_wdt_reset(void) */ void pp_soft_wdt_stop(void) { - + WDT_FEED(); } /** @@ -96,5 +97,5 @@ void pp_soft_wdt_stop(void) */ void pp_soft_wdt_restart(void) { - + WDT_FEED(); } diff --git a/components/freertos/Kconfig b/components/freertos/Kconfig index 114b9bcc6..6075e05fc 100644 --- a/components/freertos/Kconfig +++ b/components/freertos/Kconfig @@ -45,5 +45,13 @@ config FREERTOS_TIMER_STACKSIZE default 2048 help The size of the stack used by the timer in FreeRTOS. + +config ENABLE_FREERTOS_SLEEP + bool "Enable FreeRTOS SLEEP" + default n + help + Enable this option, FreeRTOS sleep module at idle task will be enable. + The module is not working now, so if users want to make it work, they should do this themselves. + endmenu diff --git a/components/freertos/freertos/list.c b/components/freertos/freertos/list.c index 758523a3d..bfc2f87a2 100644 --- a/components/freertos/freertos/list.c +++ b/components/freertos/freertos/list.c @@ -71,7 +71,7 @@ void vListInitialiseItem( ListItem_t * const pxItem ) } /*-----------------------------------------------------------*/ -void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem ) +void IRAM_ATTR vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem ) { ListItem_t * const pxIndex = pxList->pxIndex; @@ -167,7 +167,7 @@ const TickType_t xValueOfInsertion = pxNewListItem->xItemValue; } /*-----------------------------------------------------------*/ -UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) +UBaseType_t IRAM_ATTR uxListRemove( ListItem_t * const pxItemToRemove ) { /* The list item knows which list it is in. Obtain the list from the list item. */ diff --git a/components/freertos/freertos/queue.c b/components/freertos/freertos/queue.c index c37d285f3..463a33a23 100644 --- a/components/freertos/freertos/queue.c +++ b/components/freertos/freertos/queue.c @@ -920,7 +920,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue; } /*-----------------------------------------------------------*/ -BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, const void * const pvItemToQueue, BaseType_t * const pxHigherPriorityTaskWoken, const BaseType_t xCopyPosition ) +BaseType_t IRAM_ATTR xQueueGenericSendFromISR( QueueHandle_t xQueue, const void * const pvItemToQueue, BaseType_t * const pxHigherPriorityTaskWoken, const BaseType_t xCopyPosition ) { BaseType_t xReturn; UBaseType_t uxSavedInterruptStatus; @@ -2037,7 +2037,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue; #endif /* configUSE_MUTEXES */ /*-----------------------------------------------------------*/ -static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition ) +static BaseType_t IRAM_ATTR prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition ) { BaseType_t xReturn = pdFALSE; UBaseType_t uxMessagesWaiting; @@ -2843,7 +2843,7 @@ BaseType_t xReturn; #if ( configUSE_QUEUE_SETS == 1 ) - static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue, const BaseType_t xCopyPosition ) + static BaseType_t IRAM_ATTR prvNotifyQueueSetContainer( const Queue_t * const pxQueue, const BaseType_t xCopyPosition ) { Queue_t *pxQueueSetContainer = pxQueue->pxQueueSetContainer; BaseType_t xReturn = pdFALSE; diff --git a/components/freertos/freertos/tasks.c b/components/freertos/freertos/tasks.c index 70e2eaa7c..2a3e662f7 100644 --- a/components/freertos/freertos/tasks.c +++ b/components/freertos/freertos/tasks.c @@ -2054,7 +2054,7 @@ void vTaskEndScheduler( void ) } /*----------------------------------------------------------*/ -void vTaskSuspendAll( void ) +void IRAM_ATTR vTaskSuspendAll( void ) { /* A critical section is not required as the variable is of type BaseType_t. Please read Richard Barry's reply in the following link to a @@ -2127,7 +2127,7 @@ void vTaskSuspendAll( void ) #endif /* configUSE_TICKLESS_IDLE */ /*----------------------------------------------------------*/ -BaseType_t xTaskResumeAll( void ) +BaseType_t IRAM_ATTR xTaskResumeAll( void ) { TCB_t *pxTCB = NULL; BaseType_t xAlreadyYielded = pdFALSE; @@ -2611,7 +2611,7 @@ implementations require configUSE_TICKLESS_IDLE to be set to a value other than #endif /* INCLUDE_xTaskAbortDelay */ /*----------------------------------------------------------*/ -BaseType_t xTaskIncrementTick( void ) +BaseType_t IRAM_ATTR xTaskIncrementTick( void ) { TCB_t * pxTCB; TickType_t xItemValue; @@ -2873,7 +2873,7 @@ BaseType_t xSwitchRequired = pdFALSE; #endif /* configUSE_APPLICATION_TASK_TAG */ /*-----------------------------------------------------------*/ -void vTaskSwitchContext( void ) +void IRAM_ATTR vTaskSwitchContext( void ) { if( uxSchedulerSuspended != ( UBaseType_t ) pdFALSE ) { @@ -3006,7 +3006,7 @@ void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xIte #endif /* configUSE_TIMERS */ /*-----------------------------------------------------------*/ -BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList ) +BaseType_t IRAM_ATTR xTaskRemoveFromEventList( const List_t * const pxEventList ) { TCB_t *pxUnblockedTCB; BaseType_t xReturn; @@ -3310,6 +3310,7 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) } #endif /* configUSE_IDLE_HOOK */ + #if CONFIG_ENABLE_FREERTOS_SLEEP /* This conditional compilation should use inequality to 0, not equality to 1. This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when user defined low power mode implementations require @@ -3359,6 +3360,7 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) } } #endif /* configUSE_TICKLESS_IDLE */ + #endif /* CONFIG_ENABLE_FREERTOS_SLEEP */ } } /*-----------------------------------------------------------*/ @@ -3779,7 +3781,7 @@ static void prvCheckTasksWaitingTermination( void ) #endif /* INCLUDE_vTaskDelete */ /*-----------------------------------------------------------*/ -static void prvResetNextTaskUnblockTime( void ) +static void IRAM_ATTR prvResetNextTaskUnblockTime( void ) { TCB_t *pxTCB; @@ -3937,7 +3939,7 @@ TCB_t *pxTCB; #if ( configUSE_MUTEXES == 1 ) - BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) + BaseType_t IRAM_ATTR xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) { TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder; BaseType_t xReturn = pdFALSE; diff --git a/components/freertos/port/esp8266/include/freertos/portmacro.h b/components/freertos/port/esp8266/include/freertos/portmacro.h index 709c7771d..e220ca2a8 100644 --- a/components/freertos/port/esp8266/include/freertos/portmacro.h +++ b/components/freertos/port/esp8266/include/freertos/portmacro.h @@ -151,7 +151,7 @@ void PortEnableInt_NoNest( void ); not necessary for to use this port. They are defined so the common demo files (which build with all the ports) will build. */ #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) -#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void IRAM_ATTR vFunction( void *pvParameters ) /*-----------------------------------------------------------*/ void _xt_user_exit (void); diff --git a/components/freertos/port/esp8266/port.c b/components/freertos/port/esp8266/port.c index 70e077c44..7ed7b0751 100644 --- a/components/freertos/port/esp8266/port.c +++ b/components/freertos/port/esp8266/port.c @@ -49,8 +49,8 @@ #define PORT_ASSERT(x) do { if (!(x)) {ets_printf("%s %u\n", "rtos_port", __LINE__); while(1){}; }} while (0) extern char NMIIrqIsOn; -static uint8_t HdlMacSig = 0; -static uint8_t SWReq = 0; +static uint32_t HdlMacSig = 0; +static uint32_t SWReq = 0; unsigned cpu_sr; @@ -118,7 +118,7 @@ void IRAM_ATTR HDL_MAC_SIG_IN_LV1_ISR(void) extern portBASE_TYPE MacIsrSigPostDefHdl(void); -void SoftIsrHdl(void* arg) +void IRAM_ATTR SoftIsrHdl(void* arg) { ETS_NMI_LOCK(); @@ -130,7 +130,7 @@ void SoftIsrHdl(void* arg) } if (xHigherPriorityTaskWoken || (SWReq == 1)) { - _xt_timer_int1(); + _xt_timer_int1(); // call vTaskSwitchContext SWReq = 0; } @@ -344,7 +344,7 @@ BaseType_t xQueueGenericReceive(QueueHandle_t xQueue, void * const pvBuffer, return xQueueReceive(xQueue, pvBuffer, xTicksToWait); } -void vApplicationIdleHook(void) +void IRAM_ATTR vApplicationIdleHook(void) { extern void pmIdleHook(void); extern void esp_task_wdt_reset(void); diff --git a/components/heap/port/esp8266/include/esp_heap_port.h b/components/heap/port/esp8266/include/esp_heap_port.h index d820a6c40..7294612cb 100644 --- a/components/heap/port/esp8266/include/esp_heap_port.h +++ b/components/heap/port/esp8266/include/esp_heap_port.h @@ -16,14 +16,26 @@ #define _heap_caps_lock(_num) \ { \ + extern int esp_wifi_is_sniffer(void); \ extern void vPortETSIntrLock(void); \ - vPortETSIntrLock(); \ + extern void vPortEnterCritical(void); \ + \ + if (esp_wifi_is_sniffer()) \ + vPortETSIntrLock(); \ + else \ + vPortEnterCritical(); \ } #define _heap_caps_unlock(_num) \ { \ + extern int esp_wifi_is_sniffer(void); \ extern void vPortETSIntrUnlock(void); \ - vPortETSIntrUnlock(); \ + extern void vPortExitCritical(void); \ + \ + if (esp_wifi_is_sniffer()) \ + vPortETSIntrUnlock(); \ + else \ + vPortExitCritical(); \ } #define _heap_caps_feed_wdt(_num) \ diff --git a/components/lwip/Kconfig b/components/lwip/Kconfig index 420b78ed9..bf5c6823b 100644 --- a/components/lwip/Kconfig +++ b/components/lwip/Kconfig @@ -223,6 +223,12 @@ config LWIP_DHCPS_MAX_STATION_NUM After this number is exceeded, DHCP server removes of the oldest device from it's address pool, without notification. +config LWIP_ESP_DHCP_OPTION + bool "Enable DHCP option60 and option61 in discovery and request state" + default n + help + Maybe some routers need add those option to get IP address. + Enable this config to add option60 and option61 in discovery and request state endmenu #DHCP menuconfig LWIP_AUTOIP diff --git a/components/lwip/lwip/src/core/ipv4/dhcp.c b/components/lwip/lwip/src/core/ipv4/dhcp.c index 0cf97b034..2aff669b7 100644 --- a/components/lwip/lwip/src/core/ipv4/dhcp.c +++ b/components/lwip/lwip/src/core/ipv4/dhcp.c @@ -209,6 +209,12 @@ static void dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif); /* always add the DHCP options trailer to end and pad */ static void dhcp_option_trailer(struct dhcp *dhcp); +#if ESP_DHCP_OPTION +/* set dhcp option61 */ +static void dhcp_option_clientid(struct dhcp *dhcp, struct netif *netif); +/* set dhcp option60 */ +static void dhcp_option_vendor(struct dhcp *dhcp, struct netif *netif); +#endif /** Ensure DHCP PCB is allocated and bound */ static err_t dhcp_inc_pcb_refcount(void) @@ -362,6 +368,10 @@ dhcp_select(struct netif *netif) /* create and initialize the DHCP message header */ result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); if (result == ERR_OK) { +#if ESP_DHCP_OPTION + dhcp_option_clientid(dhcp, netif); + dhcp_option_vendor(dhcp, netif); +#endif dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); @@ -972,6 +982,10 @@ dhcp_discover(struct netif *netif) if (result == ERR_OK) { LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: making request\n")); +#if ESP_DHCP_OPTION + dhcp_option_clientid(dhcp, netif); + dhcp_option_vendor(dhcp, netif); +#endif dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); @@ -979,6 +993,11 @@ dhcp_discover(struct netif *netif) for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) { dhcp_option_byte(dhcp, dhcp_discover_request_options[i]); } + +#if LWIP_NETIF_HOSTNAME + dhcp_option_hostname(dhcp, netif); +#endif /* LWIP_NETIF_HOSTNAME */ + dhcp_option_trailer(dhcp); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: realloc()ing\n")); @@ -1136,6 +1155,10 @@ dhcp_renew(struct netif *netif) /* create and initialize the DHCP message header */ result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); if (result == ERR_OK) { +#if ESP_DHCP_OPTION + dhcp_option_clientid(dhcp, netif); + dhcp_option_vendor(dhcp, netif); +#endif dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); @@ -1188,6 +1211,10 @@ dhcp_rebind(struct netif *netif) /* create and initialize the DHCP message header */ result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); if (result == ERR_OK) { +#if ESP_DHCP_OPTION + dhcp_option_clientid(dhcp, netif); + dhcp_option_vendor(dhcp, netif); +#endif dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); @@ -1238,6 +1265,10 @@ dhcp_reboot(struct netif *netif) /* create and initialize the DHCP message header */ result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); if (result == ERR_OK) { +#if ESP_DHCP_OPTION + dhcp_option_clientid(dhcp, netif); + dhcp_option_vendor(dhcp, netif); +#endif dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN_MIN_REQUIRED); @@ -1249,6 +1280,10 @@ dhcp_reboot(struct netif *netif) dhcp_option_byte(dhcp, dhcp_discover_request_options[i]); } +#if LWIP_NETIF_HOSTNAME + dhcp_option_hostname(dhcp, netif); +#endif /* LWIP_NETIF_HOSTNAME */ + dhcp_option_trailer(dhcp); pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); @@ -1446,6 +1481,76 @@ dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif) } #endif /* LWIP_NETIF_HOSTNAME */ +#if ESP_DHCP_OPTION +static void dhcp_option_clientid(struct dhcp *dhcp, struct netif *netif) +{ + if (netif) { + u8_t id_len = NETIF_MAX_HWADDR_LEN + 1; + dhcp_option(dhcp, DHCP_OPTION_CLIENT_ID, id_len); + dhcp_option_byte(dhcp, DHCP_HTYPE_ETH); + for (u8_t i = 0; i < NETIF_MAX_HWADDR_LEN; i++) { + dhcp_option_byte(dhcp, netif->hwaddr[i]); + } + } +} + +static u8_t vendor_class_len = 0; +static char *vendor_class_buf = NULL; +err_t dhcp_set_vendor_class_identifier(u8_t len, char *str) +{ + if (len == 0 || str == NULL) { + return ERR_ARG; + } + + if (vendor_class_buf) { + mem_free(vendor_class_buf); + vendor_class_buf = NULL; + } + + vendor_class_buf = (char *)mem_malloc(len + 1); + + if (vendor_class_buf == NULL) { + return ERR_MEM; + } + + vendor_class_len = len; + memcpy(vendor_class_buf, str, len); + return ERR_OK; +} + +static void dhcp_option_vendor(struct dhcp *dhcp, struct netif *netif) +{ + const char *p = NULL; + u8_t len = 0; + /* Shrink len to available bytes (need 2 bytes for OPTION_HOSTNAME + and 1 byte for trailer) */ + size_t available = DHCP_OPTIONS_LEN - dhcp->options_out_len - 3; + if (vendor_class_buf && vendor_class_len) { + p = vendor_class_buf; + LWIP_ASSERT("DHCP: vendor_class_len is too long!", vendor_class_len <= available); + len = vendor_class_len; + } else { //use hostname as vendor +#if LWIP_NETIF_HOSTNAME + if (netif->hostname != NULL) { + size_t namelen = strlen(netif->hostname); + if ((namelen > 0) && (namelen < 0xFF)) { + p = netif->hostname; + LWIP_ASSERT("DHCP: hostname is too long!", namelen <= available); + len = (u8_t) namelen; + } + } +#endif + } + + if (p) { + dhcp_option(dhcp, DHCP_OPTION_US, (u8_t)len); + while (len--) { + dhcp_option_byte(dhcp, *p++); + } + } +} +#endif + /** * Extract the DHCP message and the DHCP options. * diff --git a/components/lwip/lwip/src/include/lwip/prot/dhcp.h b/components/lwip/lwip/src/include/lwip/prot/dhcp.h index 112953cb8..02ed51d0a 100644 --- a/components/lwip/lwip/src/include/lwip/prot/dhcp.h +++ b/components/lwip/lwip/src/include/lwip/prot/dhcp.h @@ -175,6 +175,9 @@ typedef enum { #define DHCP_OVERLOAD_SNAME 2 #define DHCP_OVERLOAD_SNAME_FILE 3 +#if ESP_DHCP_OPTION +err_t dhcp_set_vendor_class_identifier(u8_t len, char *str); +#endif #ifdef __cplusplus } diff --git a/components/lwip/port/esp8266/freertos/udp_sync.c b/components/lwip/port/esp8266/freertos/udp_sync.c index 844728554..ca31ae087 100644 --- a/components/lwip/port/esp8266/freertos/udp_sync.c +++ b/components/lwip/port/esp8266/freertos/udp_sync.c @@ -256,6 +256,11 @@ void udp_sync_ack_sock(void *in_msg) struct api_msg *msg = (struct api_msg *)in_msg; struct udp_pcb *pcb = _get_msg_pcb(msg); + if (UDP_SYNC_NONE == s_msg_type) { + TCPIP_APIMSG_ACK(msg); + return ; + } + ret = _udp_sync_ack_sock_ret(msg, 0); if (ret == ERR_OK && _udp_need_proc(pcb)) { udp_sync_method_t *method = (udp_sync_method_t *)_udp_priv_data(pcb); diff --git a/components/lwip/port/esp8266/include/lwipopts.h b/components/lwip/port/esp8266/include/lwipopts.h index fcc071471..dc0019260 100644 --- a/components/lwip/port/esp8266/include/lwipopts.h +++ b/components/lwip/port/esp8266/include/lwipopts.h @@ -1291,21 +1291,21 @@ size_t memp_malloc_get_size(size_t type); * The stack size value itself is platform-dependent, but is passed to * sys_thread_new() when the thread is created. */ -#define DEFAULT_THREAD_STACKSIZE 0 +#define DEFAULT_THREAD_STACKSIZE TCPIP_THREAD_STACKSIZE /** * DEFAULT_THREAD_PRIO: The priority assigned to any other lwIP thread. * The priority value itself is platform-dependent, but is passed to * sys_thread_new() when the thread is created. */ -#define DEFAULT_THREAD_PRIO 1 +#define DEFAULT_THREAD_PRIO TCPIP_THREAD_PRIO /** * DEFAULT_RAW_RECVMBOX_SIZE: The mailbox size for the incoming packets on a * NETCONN_RAW. The queue size value itself is platform-dependent, but is passed * to sys_mbox_new() when the recvmbox is created. */ -#define DEFAULT_RAW_RECVMBOX_SIZE 0 +#define DEFAULT_RAW_RECVMBOX_SIZE 6 /** * DEFAULT_UDP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a @@ -2243,4 +2243,5 @@ size_t memp_malloc_get_size(size_t type); #define ESP_PING 1 +#define ESP_DHCP_OPTION CONFIG_LWIP_ESP_DHCP_OPTION #endif /* __LWIP_HDR_LWIPOPTS_H__ */ diff --git a/components/newlib/newlib/port/syscall.c b/components/newlib/newlib/port/syscall.c index b71e52737..28651f4e5 100644 --- a/components/newlib/newlib/port/syscall.c +++ b/components/newlib/newlib/port/syscall.c @@ -110,7 +110,7 @@ void _exit(int status) void abort(void) { - ESP_LOGE("ABORT","Error found and abort!"); + ets_printf("abort() was called at PC %p on core %d\r\n", __builtin_return_address(0) - 3, xPortGetCoreID()); /* cause a exception to jump into panic function */ while (1) { diff --git a/components/nvs_flash/src/nvs_item_hash_list.cpp b/components/nvs_flash/src/nvs_item_hash_list.cpp index e483c5969..845dd0910 100644 --- a/components/nvs_flash/src/nvs_item_hash_list.cpp +++ b/components/nvs_flash/src/nvs_item_hash_list.cpp @@ -60,7 +60,7 @@ void HashList::insert(const Item& item, size_t index) newBlock->mCount++; } -void HashList::erase(size_t index) +void HashList::erase(size_t index, bool itemShouldExist) { for (auto it = mBlockList.begin(); it != mBlockList.end();) { bool haveEntries = false; @@ -82,7 +82,9 @@ void HashList::erase(size_t index) ++it; } } - assert(false && "item should have been present in cache"); + if (itemShouldExist) { + assert(false && "item should have been present in cache"); + } } size_t HashList::find(size_t start, const Item& item) diff --git a/components/nvs_flash/src/nvs_item_hash_list.hpp b/components/nvs_flash/src/nvs_item_hash_list.hpp index 3f8dcc850..e759cd818 100644 --- a/components/nvs_flash/src/nvs_item_hash_list.hpp +++ b/components/nvs_flash/src/nvs_item_hash_list.hpp @@ -29,7 +29,7 @@ class HashList ~HashList(); void insert(const Item& item, size_t index); - void erase(const size_t index); + void erase(const size_t index, bool itemShouldExist=true); size_t find(size_t start, const Item& item); void clear(); diff --git a/components/nvs_flash/src/nvs_page.cpp b/components/nvs_flash/src/nvs_page.cpp index 2a17cff24..efadc1855 100644 --- a/components/nvs_flash/src/nvs_page.cpp +++ b/components/nvs_flash/src/nvs_page.cpp @@ -318,7 +318,6 @@ esp_err_t Page::eraseEntryAndSpan(size_t index) { auto state = mEntryTable.get(index); assert(state == EntryState::WRITTEN || state == EntryState::EMPTY); - mHashList.erase(index); size_t span = 1; if (state == EntryState::WRITTEN) { @@ -328,6 +327,7 @@ esp_err_t Page::eraseEntryAndSpan(size_t index) return rc; } if (item.calculateCrc32() != item.crc32) { + mHashList.erase(index, false); rc = alterEntryState(index, EntryState::ERASED); --mUsedEntryCount; ++mErasedEntryCount; @@ -335,6 +335,7 @@ esp_err_t Page::eraseEntryAndSpan(size_t index) return rc; } } else { + mHashList.erase(index); span = item.span; for (ptrdiff_t i = index + span - 1; i >= static_cast(index); --i) { if (mEntryTable.get(i) == EntryState::WRITTEN) { @@ -385,7 +386,7 @@ void Page::updateFirstUsedEntry(size_t index, size_t span) } } -esp_err_t Page::moveItem(Page& other) +esp_err_t Page::copyItems(Page& other) { if (mFirstUsedEntry == INVALID_ENTRY) { return ESP_ERR_NVS_NOT_FOUND; @@ -399,29 +400,41 @@ esp_err_t Page::moveItem(Page& other) } Item entry; - auto err = readEntry(mFirstUsedEntry, entry); - if (err != ESP_OK) { - return err; - } - other.mHashList.insert(entry, other.mNextFreeEntry); - err = other.writeEntry(entry); - if (err != ESP_OK) { - return err; - } + size_t readEntryIndex = mFirstUsedEntry; - size_t span = entry.span; - size_t end = mFirstUsedEntry + span; + while (readEntryIndex < ENTRY_COUNT) { - assert(mFirstUsedEntry != INVALID_ENTRY || span == 1); + if (mEntryTable.get(readEntryIndex) != EntryState::WRITTEN) { + assert(readEntryIndex != mFirstUsedEntry); + readEntryIndex++; + continue; + } + auto err = readEntry(readEntryIndex, entry); + if (err != ESP_OK) { + return err; + } - for (size_t i = mFirstUsedEntry + 1; i < end; ++i) { - readEntry(i, entry); + other.mHashList.insert(entry, other.mNextFreeEntry); err = other.writeEntry(entry); if (err != ESP_OK) { return err; } + size_t span = entry.span; + size_t end = readEntryIndex + span; + + assert(end <= ENTRY_COUNT); + + for (size_t i = readEntryIndex + 1; i < end; ++i) { + readEntry(i, entry); + err = other.writeEntry(entry); + if (err != ESP_OK) { + return err; + } + } + readEntryIndex = end; + } - return eraseEntryAndSpan(mFirstUsedEntry); + return ESP_OK; } esp_err_t Page::mLoadEntryTable() @@ -515,11 +528,6 @@ esp_err_t Page::mLoadEntryTable() return err; } - mHashList.insert(item, i); - - // search for potential duplicate item - size_t duplicateIndex = mHashList.find(0, item); - if (item.crc32 != item.calculateCrc32()) { err = eraseEntryAndSpan(i); if (err != ESP_OK) { @@ -529,6 +537,10 @@ esp_err_t Page::mLoadEntryTable() continue; } + mHashList.insert(item, i); + + // search for potential duplicate item + size_t duplicateIndex = mHashList.find(0, item); if (item.datatype == ItemType::BLOB || item.datatype == ItemType::SZ) { span = item.span; @@ -580,8 +592,6 @@ esp_err_t Page::mLoadEntryTable() return err; } - mHashList.insert(item, i); - if (item.crc32 != item.calculateCrc32()) { err = eraseEntryAndSpan(i); if (err != ESP_OK) { @@ -590,10 +600,20 @@ esp_err_t Page::mLoadEntryTable() } continue; } - assert(item.span > 0); + mHashList.insert(item, i); size_t span = item.span; + + if (item.datatype == ItemType::BLOB || item.datatype == ItemType::SZ) { + for (size_t j = i + 1; j < i + span; ++j) { + if (mEntryTable.get(j) != EntryState::WRITTEN) { + eraseEntryAndSpan(i); + break; + } + } + } + i += span - 1; } @@ -730,7 +750,11 @@ esp_err_t Page::findItem(uint8_t nsIndex, ItemType datatype, const char* key, si auto crc32 = item.calculateCrc32(); if (item.crc32 != crc32) { - eraseEntryAndSpan(i); + rc = eraseEntryAndSpan(i); + if (rc != ESP_OK) { + mState = PageState::INVALID; + return rc; + } continue; } diff --git a/components/nvs_flash/src/nvs_page.hpp b/components/nvs_flash/src/nvs_page.hpp index 7731e403a..413da4589 100644 --- a/components/nvs_flash/src/nvs_page.hpp +++ b/components/nvs_flash/src/nvs_page.hpp @@ -127,7 +127,7 @@ class Page : public intrusive_list_node esp_err_t markFreeing(); - esp_err_t moveItem(Page& other); + esp_err_t copyItems(Page& other); esp_err_t erase(); diff --git a/components/nvs_flash/src/nvs_pagemanager.cpp b/components/nvs_flash/src/nvs_pagemanager.cpp index 943f54f2f..31240d98b 100644 --- a/components/nvs_flash/src/nvs_pagemanager.cpp +++ b/components/nvs_flash/src/nvs_pagemanager.cpp @@ -67,7 +67,9 @@ esp_err_t PageManager::load(uint32_t baseSector, uint32_t sectorCount) if (lastItemIndex != SIZE_MAX) { auto last = PageManager::TPageListIterator(&lastPage); for (auto it = begin(); it != last; ++it) { - if (it->eraseItem(item.nsIndex, item.datatype, item.key) == ESP_OK) { + + if ((it->state() != Page::PageState::FREEING) && + (it->eraseItem(item.nsIndex, item.datatype, item.key) == ESP_OK)) { break; } } @@ -77,23 +79,26 @@ esp_err_t PageManager::load(uint32_t baseSector, uint32_t sectorCount) for (auto it = begin(); it!= end(); ++it) { if (it->state() == Page::PageState::FREEING) { Page* newPage = &mPageList.back(); - if (newPage->state() != Page::PageState::ACTIVE) { - auto err = activatePage(); + if (newPage->state() == Page::PageState::ACTIVE) { + auto err = newPage->erase(); if (err != ESP_OK) { return err; } - newPage = &mPageList.back(); + mPageList.erase(newPage); + mFreePageList.push_back(newPage); } - while (true) { - auto err = it->moveItem(*newPage); - if (err == ESP_ERR_NVS_NOT_FOUND) { - break; - } else if (err != ESP_OK) { - return err; - } + auto err = activatePage(); + if (err != ESP_OK) { + return err; + } + newPage = &mPageList.back(); + + err = it->copyItems(*newPage); + if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) { + return err; } - auto err = it->erase(); + err = it->erase(); if (err != ESP_OK) { return err; } @@ -109,7 +114,7 @@ esp_err_t PageManager::load(uint32_t baseSector, uint32_t sectorCount) if (mFreePageList.size() == 0) { return ESP_ERR_NVS_NO_FREE_PAGES; } - + return ESP_OK; } @@ -125,17 +130,18 @@ esp_err_t PageManager::requestNewPage() } // find the page with the higest number of erased items - TPageListIterator maxErasedItemsPageIt; - size_t maxErasedItems = 0; + TPageListIterator maxUnusedItemsPageIt; + size_t maxUnusedItems = 0; for (auto it = begin(); it != end(); ++it) { - auto erased = it->getErasedEntryCount(); - if (erased > maxErasedItems) { - maxErasedItemsPageIt = it; - maxErasedItems = erased; + + auto unused = Page::ENTRY_COUNT - it->getUsedEntryCount(); + if (unused > maxUnusedItems) { + maxUnusedItemsPageIt = it; + maxUnusedItems = unused; } } - if (maxErasedItems == 0) { + if (maxUnusedItems == 0) { return ESP_ERR_NVS_NOT_ENOUGH_SPACE; } @@ -146,7 +152,8 @@ esp_err_t PageManager::requestNewPage() Page* newPage = &mPageList.back(); - Page* erasedPage = maxErasedItemsPageIt; + Page* erasedPage = maxUnusedItemsPageIt; + #ifndef NDEBUG size_t usedEntries = erasedPage->getUsedEntryCount(); #endif @@ -154,13 +161,9 @@ esp_err_t PageManager::requestNewPage() if (err != ESP_OK) { return err; } - while (true) { - err = erasedPage->moveItem(*newPage); - if (err == ESP_ERR_NVS_NOT_FOUND) { - break; - } else if (err != ESP_OK) { - return err; - } + err = erasedPage->copyItems(*newPage); + if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) { + return err; } err = erasedPage->erase(); @@ -171,8 +174,8 @@ esp_err_t PageManager::requestNewPage() #ifndef NDEBUG assert(usedEntries == newPage->getUsedEntryCount()); #endif - - mPageList.erase(maxErasedItemsPageIt); + + mPageList.erase(maxUnusedItemsPageIt); mFreePageList.push_back(erasedPage); return ESP_OK; diff --git a/components/nvs_flash/test_nvs_host/test_nvs.cpp b/components/nvs_flash/test_nvs_host/test_nvs.cpp index f419256cf..c23f5d661 100644 --- a/components/nvs_flash/test_nvs_host/test_nvs.cpp +++ b/components/nvs_flash/test_nvs_host/test_nvs.cpp @@ -132,14 +132,14 @@ TEST_CASE("when writing and erasing, used/erased counts are updated correctly", CHECK(page.getErasedEntryCount() == 1); for (size_t i = 0; i < Page::ENTRY_COUNT - 2; ++i) { char name[16]; - snprintf(name, sizeof(name), "i%ld", i); + snprintf(name, sizeof(name), "i%ld", (long int)i); CHECK(page.writeItem(1, name, i) == ESP_OK); } CHECK(page.getUsedEntryCount() == Page::ENTRY_COUNT - 1); CHECK(page.getErasedEntryCount() == 1); for (size_t i = 0; i < Page::ENTRY_COUNT - 2; ++i) { char name[16]; - snprintf(name, sizeof(name), "i%ld", i); + snprintf(name, sizeof(name), "i%ld", (long int)i); CHECK(page.eraseItem(1, itemTypeOf(), name) == ESP_OK); } CHECK(page.getUsedEntryCount() == 1); @@ -153,7 +153,7 @@ TEST_CASE("when page is full, adding an element fails", "[nvs]") CHECK(page.load(0) == ESP_OK); for (size_t i = 0; i < Page::ENTRY_COUNT; ++i) { char name[16]; - snprintf(name, sizeof(name), "i%ld", i); + snprintf(name, sizeof(name), "i%ld", (long int)i); CHECK(page.writeItem(1, name, i) == ESP_OK); } CHECK(page.writeItem(1, "foo", 64UL) == ESP_ERR_NVS_PAGE_FULL); @@ -259,6 +259,25 @@ TEST_CASE("Page validates blob size", "[nvs]") TEST_ESP_OK(page.writeItem(1, ItemType::BLOB, "2", buf, Page::BLOB_MAX_SIZE)); } +TEST_CASE("Page handles invalid CRC of variable length items", "[nvs][cur]") +{ + SpiFlashEmulator emu(4); + { + Page page; + TEST_ESP_OK(page.load(0)); + char buf[128] = {0}; + TEST_ESP_OK(page.writeItem(1, ItemType::BLOB, "1", buf, sizeof(buf))); + } + // corrupt header of the item (64 is the offset of the first item in page) + uint32_t overwrite_buf = 0; + emu.write(64, &overwrite_buf, 4); + // load page again + { + Page page; + TEST_ESP_OK(page.load(0)); + } +} + TEST_CASE("can init PageManager in empty flash", "[nvs]") { SpiFlashEmulator emu(4); @@ -1123,7 +1142,7 @@ TEST_CASE("crc errors in item header are handled", "[nvs]") // add more items to make the page full for (size_t i = 0; i < Page::ENTRY_COUNT; ++i) { char item_name[Item::MAX_KEY_LENGTH + 1]; - snprintf(item_name, sizeof(item_name), "item_%ld", i); + snprintf(item_name, sizeof(item_name), "item_%ld", (long int)i); TEST_ESP_OK(storage.writeItem(1, item_name, static_cast(i))); } @@ -1246,6 +1265,27 @@ TEST_CASE("multiple partitions access check", "[nvs]") CHECK(v2 == 0xcafebabe); } +TEST_CASE("nvs page selection takes into account free entries also not just erased entries", "[nvs]") +{ + const size_t blob_size = Page::BLOB_MAX_SIZE; + uint8_t blob[blob_size] = {0}; + SpiFlashEmulator emu(3); + TEST_ESP_OK( nvs_flash_init_custom(NVS_DEFAULT_PART_NAME, 0, 3) ); + nvs_handle handle; + TEST_ESP_OK( nvs_open("test", NVS_READWRITE, &handle) ); + // Fill first page + TEST_ESP_OK( nvs_set_blob(handle, "1a", blob, blob_size/3) ); + TEST_ESP_OK( nvs_set_blob(handle, "1b", blob, blob_size) ); + // Fill second page + TEST_ESP_OK( nvs_set_blob(handle, "2a", blob, blob_size) ); + TEST_ESP_OK( nvs_set_blob(handle, "2b", blob, blob_size) ); + + // The item below should be able to fit the first page. + TEST_ESP_OK( nvs_set_blob(handle, "3a", blob, 4) ); + TEST_ESP_OK( nvs_commit(handle) ); + nvs_close(handle); +} + TEST_CASE("dump all performance data", "[nvs]") { std::cout << "====================" << std::endl << "Dumping benchmarks" << std::endl; diff --git a/components/partition_table/Kconfig.projbuild b/components/partition_table/Kconfig.projbuild index eed3820da..2fd122d1c 100644 --- a/components/partition_table/Kconfig.projbuild +++ b/components/partition_table/Kconfig.projbuild @@ -33,15 +33,6 @@ config PARTITION_TABLE_OFFSET help The partition table cannot be placed at application address. -config PARTITION_TABLE_CUSTOM_PHY_DATA_OFFSET - hex "PHY data partition offset" if PARTITION_TABLE_CUSTOM - depends on ESP_PHY_INIT_DATA_IN_PARTITION - default 0xf000 - help - If using a custom partition table, specify the offset in the flash - where 'make flash' should write the initial PHY data file. - - config PARTITION_TABLE_FILENAME string default partitions_singleapp.csv if PARTITION_TABLE_SINGLE_APP && !ESP32_ENABLE_COREDUMP_TO_FLASH @@ -51,56 +42,6 @@ config PARTITION_TABLE_FILENAME default partitions_two_ota_coredump.csv if PARTITION_TABLE_TWO_OTA && ESP32_ENABLE_COREDUMP_TO_FLASH default PARTITION_TABLE_CUSTOM_FILENAME if PARTITION_TABLE_CUSTOM -config PHY_DATA_OFFSET - depends on ESP_PHY_INIT_DATA_IN_PARTITION - hex - default PARTITION_TABLE_CUSTOM_PHY_DATA_OFFSET if PARTITION_TABLE_CUSTOM - default 0xf000 # this is the factory app offset used by the default tables - -config APP2_SUPPORT - depends on ESPTOOLPY_FLASHSIZE_1MB && (PARTITION_TABLE_TWO_OTA || PARTITION_TABLE_CUSTOM) - bool "Support to setup partition parameter of APP2" if PARTITION_TABLE_CUSTOM - default y - help - Enable this option, if you want to have APP1 & APP2 in 1MB SPI Flash. - -config APP1_OFFSET - hex "APP1 partition offset" if PARTITION_TABLE_CUSTOM - default 0x10000 - help - If using a custom partition table, specify the offset in the flash - where the APP1 located. - - It should be same as the value in the custom partition table CSV. - -config APP1_SIZE - hex "APP1 partition size(by bytes)" if PARTITION_TABLE_CUSTOM - default 0x70000 if APP2_SUPPORT - default 0xF0000 - help - APP1 partition size by bytes. - - It should be same as the value in the custom partition table CSV. - -config APP2_OFFSET - depends on APP2_SUPPORT - hex "APP2 partition offset" if PARTITION_TABLE_CUSTOM - default 0x80000 - help - If using a custom partition table, specify the offset in the flash - where the APP2 located. - - It should be same as the value in the custom partition table CSV. - -config APP2_SIZE - depends on APP2_SUPPORT - hex "APP2 partition size(by bytes)" if PARTITION_TABLE_CUSTOM - default 0x70000 - help - APP2 partition size by bytes. - - It should be same as the value in the custom partition table CSV. - endmenu diff --git a/components/partition_table/Makefile.projbuild b/components/partition_table/Makefile.projbuild index 841495b90..40581cc5e 100644 --- a/components/partition_table/Makefile.projbuild +++ b/components/partition_table/Makefile.projbuild @@ -6,14 +6,24 @@ # the partition table binary as part of the build process. This # binary is then added to the list of files for esptool.py to flash. # -.PHONY: partition_table partition_table-flash partition_table-clean +.PHONY: partition_table partition_table-flash partition_table-clean partition_table_get_info -# NB: gen_esp32part.py lives in the sdk/bin/ dir not component dir -GEN_ESP32PART := $(PYTHON) $(COMPONENT_PATH)/gen_esp32part.py -q +PARTITION_MD5_OPT := "--disable-md5sum" + +PARTITION_FLASHSIZE_OPT := +ifneq ("$(CONFIG_ESPTOOLPY_FLASHSIZE)", "") +PARTITION_FLASHSIZE_OPT := --flash-size $(CONFIG_ESPTOOLPY_FLASHSIZE) +endif -# Has a matching value in bootloader_support esp_flash_partitions.h +PARTITION_SECURE_OPT := +# Address of partition table PARTITION_TABLE_OFFSET := $(CONFIG_PARTITION_TABLE_OFFSET) +PARTITION_TABLE_OFFSET_ARG := --offset $(PARTITION_TABLE_OFFSET) + +# NB: gen_esp32part.py lives in the sdk/bin/ dir not component dir +GEN_ESP32PART := $(PYTHON) $(COMPONENT_PATH)/gen_esp32part.py -q $(PARTITION_MD5_OPT) $(PARTITION_FLASHSIZE_OPT) $(PARTITION_TABLE_OFFSET_ARG) $(PARTITION_SECURE_OPT) +GET_PART_INFO := $(COMPONENT_PATH)/parttool.py -q # if CONFIG_PARTITION_TABLE_FILENAME is unset, means we haven't re-generated config yet... ifneq ("$(CONFIG_PARTITION_TABLE_FILENAME)","") @@ -43,17 +53,22 @@ $(PARTITION_TABLE_BIN_UNSIGNED): $(PARTITION_TABLE_CSV_PATH) $(SDKCONFIG_MAKEFIL @echo "Building partitions from $(PARTITION_TABLE_CSV_PATH)..." $(GEN_ESP32PART) $< $@ -all_binaries: $(PARTITION_TABLE_BIN) +all_binaries: $(PARTITION_TABLE_BIN) partition_table_get_info -APP_OFFSET ?= $(CONFIG_APP1_OFFSET) -APP_SIZE ?= $(CONFIG_APP1_SIZE) +partition_table_get_info: $(PARTITION_TABLE_BIN) + $(eval PHY_DATA_OFFSET:=$(shell $(GET_PART_INFO) --type data --subtype phy --offset $(PARTITION_TABLE_BIN))) + $(eval APP_OFFSET:=$(shell $(GET_PART_INFO) --default-boot-partition --offset $(PARTITION_TABLE_BIN))) + $(eval APP_SIZE:=$(shell $(GET_PART_INFO) --default-boot-partition --size $(PARTITION_TABLE_BIN))) + $(eval APP2_OFFSET:=$(shell $(GET_PART_INFO) --type app --subtype ota_1 --offset $(PARTITION_TABLE_BIN))) + $(eval APP2_SIZE:=$(shell $(GET_PART_INFO) --type app --subtype ota_1 --size $(PARTITION_TABLE_BIN))) + $(eval CFLAGS += -DAPP_OFFSET=$(APP_OFFSET) -DAPP_SIZE=$(APP_SIZE)) -export APP_OFFSET APP_SIZE +export PHY_DATA_OFFSET APP_OFFSET APP_SIZE APP2_OFFSET APP2_SIZE PARTITION_TABLE_FLASH_CMD = $(ESPTOOLPY_SERIAL) write_flash $(PARTITION_TABLE_OFFSET) $(PARTITION_TABLE_BIN) ESPTOOL_ALL_FLASH_ARGS += $(PARTITION_TABLE_OFFSET) $(PARTITION_TABLE_BIN) -partition_table: $(PARTITION_TABLE_BIN) +partition_table: $(PARTITION_TABLE_BIN) partition_table_get_info @echo "Partition table binary generated. Contents:" @echo $(SEPARATOR) $(GEN_ESP32PART) $< @@ -68,6 +83,8 @@ partition_table-flash: $(PARTITION_TABLE_BIN) partition_table-clean: rm -f $(PARTITION_TABLE_BIN) +global-macro: partition_table_get_info + clean: partition_table-clean endif diff --git a/components/partition_table/gen_esp32part.py b/components/partition_table/gen_esp32part.py index e789261f2..732eff6da 100755 --- a/components/partition_table/gen_esp32part.py +++ b/components/partition_table/gen_esp32part.py @@ -4,7 +4,7 @@ # # Converts partition tables to/from CSV and binary formats. # -# See http://esp-idf.readthedocs.io/en/latest/api-guides/partition-tables.html +# See https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/partition-tables.html # for explanation of partition table structure and uses. # # Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD @@ -26,12 +26,19 @@ import re import struct import sys +import hashlib +import binascii MAX_PARTITION_LENGTH = 0xC00 # 3K for partition data (96 entries) leaves 1K in a 4K sector for signature +MD5_PARTITION_BEGIN = b"\xEB\xEB" + b"\xFF" * 14 # The first 2 bytes are like magic numbers for MD5 sum +PARTITION_TABLE_SIZE = 0x1000 # Size of partition table -__version__ = '1.0' +__version__ = '1.1' quiet = False +md5sum = True +secure = False +offset_part_table = 0 def status(msg): """ Print status message to stderr """ @@ -73,8 +80,11 @@ def expand_vars(f): raise # fix up missing offsets & negative sizes - last_end = 0x5000 # first offset after partition table + last_end = offset_part_table + PARTITION_TABLE_SIZE # first offset after partition table for e in res: + if offset_part_table != 0 and e.offset is not None and e.offset < last_end: + critical("WARNING: 0x%x address in the partition table is below 0x%x" % (e.offset, last_end)) + e.offset = None if e.offset is None: pad_to = 0x10000 if e.type == PartitionDefinition.APP_TYPE else 4 if last_end % pad_to != 0: @@ -97,6 +107,38 @@ def __getitem__(self, item): else: return super(PartitionTable, self).__getitem__(item) + def find_by_type(self, ptype, subtype): + """ Return a partition by type & subtype, returns + None if not found """ + TYPES = PartitionDefinition.TYPES + SUBTYPES = PartitionDefinition.SUBTYPES + # convert ptype & subtypes names (if supplied this way) to integer values + try: + ptype = TYPES[ptype] + except KeyError: + try: + ptypes = int(ptype, 0) + except TypeError: + pass + try: + subtype = SUBTYPES[int(ptype)][subtype] + except KeyError: + try: + ptypes = int(ptype, 0) + except TypeError: + pass + + for p in self: + if p.type == ptype and p.subtype == subtype: + return p + return None + + def find_by_name(self, name): + for p in self: + if p.name == name: + return p + return None + def verify(self): # verify each partition individually for p in self: @@ -104,14 +146,25 @@ def verify(self): # check for overlaps last = None for p in sorted(self, key=lambda x:x.offset): - if p.offset < 0x5000: - raise InputError("Partition offset 0x%x is below 0x5000" % p.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)) last = p + def flash_size(self): + """ Return the size that partitions will occupy in flash + (ie the offset the last partition ends at) + """ + try: + last = sorted(self, reverse=True)[0] + except IndexError: + return 0 # empty table! + return last.offset + last.size + @classmethod def from_binary(cls, b): + md5 = hashlib.md5(); result = cls() for o in range(0,len(b),32): data = b[o:o+32] @@ -119,11 +172,20 @@ def from_binary(cls, b): raise InputError("Partition table length must be a multiple of 32 bytes") 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 data[16:] == md5.digest(): + 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: + md5.update(data) result.append(PartitionDefinition.from_binary(data)) raise InputError("Partition table is missing an end-of-table marker") 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: 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 @@ -154,6 +216,7 @@ class PartitionDefinition(object): "phy" : 0x01, "nvs" : 0x02, "coredump" : 0x03, + "nvs_keys" : 0x04, "esphttpd" : 0x80, "fat" : 0x81, "spiffs" : 0x82, @@ -173,7 +236,7 @@ class PartitionDefinition(object): "encrypted" : 0 } - # add subtypes for the 16 OTA slot values ("ota_XXX, etc.") + # 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 @@ -226,6 +289,18 @@ def __str__(self): def __cmp__(self, other): return self.offset - other.offset + def __lt__(self, other): + return self.offset < other.offset + + def __gt__(self, other): + return self.offset > other.offset + + def __le__(self, other): + return self.offset <= other.offset + + def __ge__(self, other): + return self.offset >= other.offset + def parse_type(self, strval): if strval == "": raise InputError("Field 'type' can't be left empty.") @@ -251,6 +326,8 @@ def verify(self): align = self.ALIGNMENT.get(self.type, 4) if self.offset % align: raise ValidationError(self, "Offset 0x%x is not aligned to 0x%x" % (self.offset, align)) + if self.size % align and secure: + raise ValidationError(self, "Size 0x%x is not aligned to 0x%x" % (self.size, align)) if self.size is None: raise ValidationError(self, "Size field is not set") @@ -333,11 +410,18 @@ def parse_int(v, keywords={}): def main(): global quiet + global md5sum + global offset_part_table + global secure parser = argparse.ArgumentParser(description='ESP32 partition table utility') + parser.add_argument('--flash-size', help='Optional flash size limit, checks partition table fits in flash', + nargs='?', choices=[ '1MB', '2MB', '4MB', '8MB', '16MB' ]) + parser.add_argument('--disable-md5sum', help='Disable md5 checksum for the partition table', default=False, action='store_true') parser.add_argument('--verify', '-v', help='Verify partition table fields', default=True, action='store_false') parser.add_argument('--quiet', '-q', help="Don't print status messages to stderr", action='store_true') - + parser.add_argument('--offset', '-o', help='Set offset partition table', default='0x8000') + parser.add_argument('--secure', help="Require app partitions to be suitable for secure boot", action='store_true') parser.add_argument('input', help='Path to CSV or binary file to parse. Will use stdin if omitted.', type=argparse.FileType('rb'), default=sys.stdin) parser.add_argument('output', help='Path to output converted binary or CSV file. Will use stdout if omitted, unless the --display argument is also passed (in which case only the summary is printed.)', nargs='?', @@ -346,6 +430,9 @@ def main(): args = parser.parse_args() quiet = args.quiet + md5sum = not args.disable_md5sum + secure = args.secure + offset_part_table = int(args.offset, 0) input = args.input.read() input_is_binary = input[0:2] == PartitionDefinition.MAGIC_BYTES if input_is_binary: @@ -360,6 +447,14 @@ def main(): status("Verifying table...") table.verify() + if args.flash_size: + size_mb = int(args.flash_size.replace("MB", "")) + size = size_mb * 1024 * 1024 # flash memory uses honest megabytes! + table_size = table.flash_size() + if size < table_size: + raise InputError("Partitions defined in '%s' occupy %.1fMB of flash (%d bytes) which does not fit in configured flash size %dMB. Change the flash size in menuconfig under the 'Serial Flasher Config' menu." % + (args.input.name, table_size / 1024.0 / 1024.0, table_size, size_mb)) + if input_is_binary: output = table.to_csv() with sys.stdout if args.output == '-' else open(args.output, 'w') as f: diff --git a/components/partition_table/parttool.py b/components/partition_table/parttool.py new file mode 100755 index 000000000..145fb8d3c --- /dev/null +++ b/components/partition_table/parttool.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python +# +# parttool returns info about the required partition. +# +# This utility is used by the make system to get information +# about the start addresses: partition table, factory area, phy area. +# +# 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. +from __future__ import print_function, division +import argparse +import os +import re +import struct +import sys +import hashlib +import binascii +import gen_esp32part as gen + +__version__ = '1.0' + +quiet = False + +def status(msg): + """ Print status message to stderr """ + if not quiet: + critical(msg) + +def critical(msg): + """ Print critical message to stderr """ + if not quiet: + sys.stderr.write(msg) + sys.stderr.write('\n') + +def main(): + global quiet + parser = argparse.ArgumentParser(description='Returns info about the required partition.') + + parser.add_argument('--quiet', '-q', help="Don't print status messages to stderr", action='store_true') + + parser.add_argument('--partition-table-offset', help='The offset of the partition table in flash. Only consulted if partition table is in CSV format.', type=str, default='0x8000') + + search_type = parser.add_mutually_exclusive_group() + search_type.add_argument('--partition-name', '-p', help='The name of the required partition', type=str, default=None) + search_type.add_argument('--type', '-t', help='The type of the required partition', type=str, default=None) + search_type.add_argument('--default-boot-partition', help='Select the default boot partition, '+ + 'using the same fallback logic as the IDF bootloader', action="store_true") + + parser.add_argument('--subtype', '-s', help='The subtype of the required partition', type=str, default=None) + + parser.add_argument('--offset', '-o', help='Return offset of required partition', action="store_true") + parser.add_argument('--size', help='Return size of required partition', action="store_true") + + parser.add_argument('input', help='Path to CSV or binary file to parse. Will use stdin if omitted.', + type=argparse.FileType('rb'), default=sys.stdin) + + args = parser.parse_args() + + if args.type is not None and args.subtype is None: + status("If --type is specified, --subtype is required") + return 2 + if args.type is None and args.subtype is not None: + status("--subtype is only used with --type") + return 2 + + quiet = args.quiet + + gen.offset_part_table = int(args.partition_table_offset, 0) + + input = args.input.read() + input_is_binary = input[0:2] == gen.PartitionDefinition.MAGIC_BYTES + if input_is_binary: + status("Parsing binary partition input...") + table = gen.PartitionTable.from_binary(input) + else: + input = input.decode() + status("Parsing CSV input...") + table = gen.PartitionTable.from_csv(input) + + found_partition = None + + if args.default_boot_partition: + search = [ "factory" ] + [ "ota_%d" % d for d in range(16) ] + for subtype in search: + found_partition = table.find_by_type("app", subtype) + if found_partition is not None: + break + elif args.partition_name is not None: + found_partition = table.find_by_name(args.partition_name) + elif args.type is not None: + found_partition = table.find_by_type(args.type, args.subtype) + else: + raise RuntimeError("invalid partition selection choice") + + if found_partition is None: + return 1 # nothing found + + if args.offset: + print('0x%x ' % (found_partition.offset)) + if args.size: + print('0x%x' % (found_partition.size)) + + return 0 + +class InputError(RuntimeError): + def __init__(self, e): + super(InputError, self).__init__(e) + + +class ValidationError(InputError): + def __init__(self, partition, message): + super(ValidationError, self).__init__( + "Partition %s invalid: %s" % (partition.name, message)) + + +if __name__ == '__main__': + try: + r = main() + sys.exit(r) + except InputError as e: + print(e, file=sys.stderr) + sys.exit(2) diff --git a/components/spi_flash/component.mk b/components/spi_flash/component.mk index b9bbbd330..6e3dda5c5 100644 --- a/components/spi_flash/component.mk +++ b/components/spi_flash/component.mk @@ -10,9 +10,7 @@ endif CFLAGS += -DPARTITION_QUEUE_HEADER=\"sys/queue.h\" -ifdef CONFIG_ESP8266_OTA_FROM_OLD ifdef IS_BOOTLOADER_BUILD COMPONENT_SRCDIRS += port COMPONENT_OBJS += port/port.o endif -endif diff --git a/components/spi_flash/port/port.c b/components/spi_flash/port/port.c index 67dc67bb5..db2d5a1c8 100644 --- a/components/spi_flash/port/port.c +++ b/components/spi_flash/port/port.c @@ -14,7 +14,7 @@ #include "sdkconfig.h" -#if defined(CONFIG_ESP8266_OTA_FROM_OLD) && defined(BOOTLOADER_BUILD) +#if (defined(CONFIG_ESP8266_OTA_FROM_OLD) || defined(CONFIG_ESP8266_BOOT_COPY_APP)) && defined(BOOTLOADER_BUILD) #include #include @@ -26,8 +26,9 @@ #include "esp_libc.h" #include "esp8266/rom_functions.h" #include "esp8266/eagle_soc.h" +#include "internal/phy_init_data.h" -#define PARTITION_DATA_OFFSET (CONFIG_SPI_FLASH_SIZE / 2) +#define PARTITION_DATA_OFFSET (s_v2_flash_bin_size / 2) typedef struct s_sys_param { uint8_t flag; @@ -59,12 +60,15 @@ typedef union s_boot_param { uint8_t enhance_boot_flag : 1; } boot_base; - uint8_t data[4096]; + ROM_FLASH_BUF_DECLARE(__data, 32); } boot_param_t; static const char *TAG = "partition_port"; static uint32_t s_partition_offset; -static uint8_t s_cache_buf[SPI_FLASH_SEC_SIZE]; +static ROM_FLASH_BUF_DECLARE(s_cache_buf, SPI_FLASH_SEC_SIZE); +static ROM_FLASH_BUF_DECLARE(check_buf, SPI_FLASH_SEC_SIZE); +static uint32_t s_v2_flash_bin_size; +static uint32_t s_v2_flash_size; static sys_param_t s_sys_param; static boot_param_t s_boot_param; static esp_spi_flash_chip_t s_flash_chip = { @@ -76,12 +80,43 @@ static esp_spi_flash_chip_t s_flash_chip = { 0xffff }; -static inline void esp_hw_reset(void) +#define FLASH_KB(_x) (_x) * 1024 +#define FLASH_MB(_x) (_x) * 1024 * 1024 + +static const uint32_t s_v2_flash_bin_size_map_table[] = { + FLASH_KB(512), + FLASH_KB(256), + FLASH_MB(1), + FLASH_MB(2), + FLASH_MB(4), + FLASH_MB(2), + FLASH_MB(4), + FLASH_MB(4), + FLASH_MB(8), + FLASH_MB(16) +}; + +static const uint32_t s_v2_flash_bin_map_table[] = { + FLASH_KB(512), + FLASH_KB(0), + FLASH_MB(1), + FLASH_MB(1), + FLASH_MB(1), + FLASH_MB(2), + FLASH_MB(2), + FLASH_MB(0), + FLASH_MB(2), + FLASH_MB(2) +}; + +static const uint32_t s_v2_flash_bin_size_map_size = sizeof(s_v2_flash_bin_map_table) / sizeof(s_v2_flash_bin_map_table[0]); + +static void esp_hw_reset(uint32_t t, int block) { CLEAR_WDT_REG_MASK(WDT_CTL_ADDRESS, BIT0); - WDT_REG_WRITE(WDT_OP_ADDRESS, 8); - WDT_REG_WRITE(WDT_OP_ND_ADDRESS, 8); + WDT_REG_WRITE(WDT_OP_ADDRESS, t); + WDT_REG_WRITE(WDT_OP_ND_ADDRESS, t); SET_PERI_REG_BITS(PERIPHS_WDT_BASEADDR + WDT_CTL_ADDRESS, WDT_CTL_RSTLEN_MASK, 7 << WDT_CTL_RSTLEN_LSB, 0); // interrupt then reset @@ -89,32 +124,54 @@ static inline void esp_hw_reset(void) // start task watch dog1 SET_PERI_REG_BITS(PERIPHS_WDT_BASEADDR + WDT_CTL_ADDRESS, WDT_CTL_EN_MASK, 1 << WDT_CTL_EN_LSB, 0); - while (1); + WDT_FEED(); + + if (block) + while (1); +} + +static void esp_hw_feed_wdt(void) +{ + WDT_FEED(); } -static inline int spi_flash_read_data(uint32_t addr, void *buf, size_t n) +static int spi_flash_read_data(uint32_t addr, void *buf, size_t n) { int ret; + if (addr & 3 || (uint32_t)buf & 3 || n & 3) { + ESP_LOGE(TAG, "flash read parameters is not align, value is %p %x %x", buf, n ,addr); + return -1; + } + ESP_LOGD(TAG, "read buffer %p total %d from 0x%x", buf, n ,addr); ret = SPI_read_data(&s_flash_chip, addr, buf, n); + esp_hw_feed_wdt(); + return ret; } -static inline int spi_flash_write_data(uint32_t addr, const void *buf, uint32_t n) +static int spi_flash_write_data(uint32_t addr, const void *buf, uint32_t n) { int ret; + if (addr & 3 || (uint32_t)buf & 3 || n & 3) { + ESP_LOGE(TAG, "flash write parameters is not align, value is %p %x %x", buf, n ,addr); + return -1; + } + ESP_LOGD(TAG, "write buffer %p total %d to 0x%x", buf, n ,addr); ret = SPIWrite(addr, (void *)buf, n); + esp_hw_feed_wdt(); + return ret; } -static inline int spi_flash_erase(uint32_t addr) +static int spi_flash_erase(uint32_t addr) { int ret; @@ -122,19 +179,58 @@ static inline int spi_flash_erase(uint32_t addr) ret = SPIEraseSector(addr / SPI_FLASH_SEC_SIZE); + esp_hw_feed_wdt(); + return ret; } -static inline uint32_t esp_get_updated_partition_table_addr(void) +static int get_v2_flash_map_size(void) +{ + int ret; + esp_image_header_t header; + + ret = spi_flash_read_data(0, &header, sizeof(esp_image_header_t)); + if (ret) { + ESP_LOGE(TAG, "read V2 header error %d", ret); + return -1; + } + + if (header.spi_size >= s_v2_flash_bin_size_map_size) { + ESP_LOGE(TAG, "V2 header flash size is error"); + return -1; + } + + s_v2_flash_bin_size = s_v2_flash_bin_map_table[header.spi_size]; + if (!s_v2_flash_bin_size) { + ESP_LOGE(TAG, "V2 header flash size mapped value is error"); + return -1; + } + + s_v2_flash_size = s_v2_flash_bin_size_map_table[header.spi_size]; + + ESP_LOGD(TAG, "V2 flash size is %d %x %x", header.spi_size, s_v2_flash_size, s_v2_flash_bin_size); + + return 0; +} + +static uint32_t esp_get_updated_partition_table_addr(void) { int ret; size_t offset; uint8_t user_bin; - const uint32_t sect = CONFIG_SPI_FLASH_SIZE / SPI_FLASH_SEC_SIZE - 3; + uint32_t sect; if (s_partition_offset) return s_partition_offset; + ret = get_v2_flash_map_size(); + if (ret) { + ESP_LOGE(TAG, "read V2 flash header error %d", ret); + return -1UL; + } + + sect = s_v2_flash_size / SPI_FLASH_SEC_SIZE - 3; + ret = spi_flash_read_data((sect + 2) * SPI_FLASH_SEC_SIZE, &s_sys_param, sizeof(sys_param_t)); if (ret) { ESP_LOGE(TAG, "read V2 system param error %d", ret); @@ -179,10 +275,9 @@ static inline uint32_t esp_get_updated_partition_table_addr(void) return s_partition_offset; } -static inline int spi_flash_write_data_safe(uint32_t addr, const void *buf, size_t n) +static int spi_flash_write_data_safe(uint32_t addr, const void *buf, size_t n) { - int ret; - static uint8_t check_buf[SPI_FLASH_SEC_SIZE]; + int ret; ret = spi_flash_erase(addr); if (ret) { @@ -233,11 +328,83 @@ static int esp_flash_sector_copy(uint32_t dest, uint32_t src, uint32_t total_siz return 0; } -static inline int esp_set_v2boot_app1(void) +#ifdef CONFIG_LOAD_OLD_RF_PARAMETER + +static bool esp_rf_param_need_unpack(size_t rf_dest, size_t rf_src, size_t rf_size) +{ + bool ret; + const uint32_t rf_magic_size = sizeof(phy_init_magic_pre); + const uint32_t rf_new_size = rf_size + rf_magic_size * 2; + + ret = spi_flash_read_data(rf_dest, check_buf, rf_new_size); + if (ret) { + ESP_LOGE(TAG, "Fail to read RF parameters from 0x%x", rf_src); + return -1; + } + + ret = spi_flash_read_data(rf_src, ((uint8_t *)s_cache_buf) + rf_magic_size, rf_size); + if (ret) { + ESP_LOGE(TAG, "Fail to read RF parameters from 0x%x", rf_src); + return -1; + } + memcpy(s_cache_buf, phy_init_magic_pre, rf_magic_size); + memcpy(((uint8_t *)s_cache_buf) + rf_magic_size + rf_size, phy_init_magic_pre, rf_magic_size); + + if (!memcmp(check_buf, s_cache_buf, rf_new_size)) + ret = false; + else + ret = true; + + return ret; +} + +static int esp_unpack_old_rf_param(size_t rf_dest, size_t rf_src, size_t rf_size) { int ret; - size_t offset = s_sys_param.flag ? 1 : 0; - const uint32_t base_addr = CONFIG_SPI_FLASH_SIZE / SPI_FLASH_SEC_SIZE - 3; + const uint32_t rf_magic_size = sizeof(phy_init_magic_pre); + const uint32_t rf_new_size = rf_size + rf_magic_size * 2; + + ret = spi_flash_erase(rf_dest); + if (ret) { + ESP_LOGE(TAG, "Fail to erase new RF parameters from 0x%x", rf_src); + return -1; + } + + ret = spi_flash_read_data(rf_src, ((uint8_t *)s_cache_buf) + rf_magic_size, rf_size); + if (ret) { + ESP_LOGE(TAG, "Fail to read old RF parameters from 0x%x", rf_src); + return -1; + } + memcpy(s_cache_buf, phy_init_magic_pre, rf_magic_size); + memcpy(((uint8_t *)s_cache_buf) + rf_magic_size + rf_size, phy_init_magic_pre, rf_magic_size); + + ret = spi_flash_write_data(rf_dest, s_cache_buf , rf_new_size); + if (ret) { + ESP_LOGE(TAG, "Fail to write new RF parameters from 0x%x", rf_src); + return -1; + } + + ret = spi_flash_read_data(rf_dest, check_buf, rf_new_size); + if (ret) { + ESP_LOGE(TAG, "Fail to read new RF parameters from 0x%x", rf_src); + return -1; + } + + if (memcmp(check_buf, s_cache_buf, rf_new_size)) { + ESP_LOGE(TAG, "Check RF parameters error"); + return -1; + } + + return 0; +} + +#endif + +static int esp_set_v2boot_app1(void) +{ + int ret; + const size_t offset = s_sys_param.flag ? 1 : 0; + const uint32_t base_addr = s_v2_flash_size / SPI_FLASH_SEC_SIZE - 3; const uint32_t sys_addr = (base_addr + 2) * SPI_FLASH_SEC_SIZE; const uint32_t to_addr = (base_addr + 1 - offset) * SPI_FLASH_SEC_SIZE; @@ -280,7 +447,7 @@ static inline int esp_set_v2boot_app1(void) return 0; } -static inline int esp_sdk_update_from_v2(void) +static int esp_sdk_update_from_v2(void) { const int segment_cnt = 3; const size_t v2_max_size = 4096; @@ -317,6 +484,8 @@ int esp_patition_table_init_location(void) { uint32_t addr; + esp_hw_reset(14, 0); + if (!esp_sdk_update_from_v2()) return 0; @@ -353,31 +522,60 @@ int esp_patition_copy_ota1_to_ota0(const void *partition_info) int esp_patition_table_init_data(void *partition_info) { int ret; + int reboot = 0; const uint32_t boot_base = 0x1000; - const uint32_t boot_size = CONFIG_SPI_FLASH_SIZE / 2 - boot_base - 4 * SPI_FLASH_SEC_SIZE; + const bootloader_state_t *bs = (const bootloader_state_t *)partition_info; + const uint32_t boot_size = bs->ota[0].offset + bs->ota[0].size - boot_base; if (!esp_sdk_update_from_v2()) return 0; - if (esp_get_updated_partition_table_addr() == CONFIG_PARTITION_TABLE_OFFSET) - return 0; + if (esp_get_updated_partition_table_addr() != CONFIG_PARTITION_TABLE_OFFSET) { + ESP_LOGD(TAG, "Copy firmware1 from %d total %d", boot_base + PARTITION_DATA_OFFSET, boot_size); - ESP_LOGD(TAG, "Copy firmware1 from %d total %d", boot_base + PARTITION_DATA_OFFSET, boot_size); + ESP_LOGI(TAG, "Start unpacking V3 firmware ..."); - ret = esp_flash_sector_copy(boot_base, boot_base + PARTITION_DATA_OFFSET, boot_size); - if (ret) { - ESP_LOGE(TAG, "Fail to copy V3 bootloader from 0x%x to 0x%x total %d", boot_base + PARTITION_DATA_OFFSET, - boot_base, boot_size); - return -1; + ret = esp_flash_sector_copy(boot_base, boot_base + PARTITION_DATA_OFFSET, boot_size); + if (ret) { + ESP_LOGE(TAG, "Fail to copy V3 firmware from 0x%x to 0x%x total %d", boot_base + PARTITION_DATA_OFFSET, + boot_base, boot_size); + return -1; + } + + ret = esp_set_v2boot_app1(); + if (ret) { + ESP_LOGE(TAG, "Fail to set V2 app1 default"); + return -1; + } + + ESP_LOGI(TAG, "Pack V3 firmware successfully and start to reboot"); + + reboot = 1; } - ret = esp_set_v2boot_app1(); - if (ret) { - ESP_LOGE(TAG, "Fail to update V2 bootloader data"); - return -1; +#ifdef CONFIG_LOAD_OLD_RF_PARAMETER + const uint32_t rf_dest = bs->rf.offset; + const uint32_t rf_src = s_v2_flash_bin_size - 4 * 4096; + const uint32_t rf_size = 128; + + if (esp_rf_param_need_unpack(rf_dest, rf_src, rf_size)) { + + ESP_LOGI(TAG, "Start unpacking RF parameters from 0x%x to 0x%x total size 0x%x ...", rf_src, rf_dest, rf_size); + + ret = esp_unpack_old_rf_param(rf_dest, rf_src, rf_size); + if (ret) { + ESP_LOGE(TAG, "Fail to copy RF parameters from 0x%x to 0x%x total %d", rf_src, rf_dest, rf_size); + return -1; + } + + reboot = 1; + } else { + ESP_LOGD(TAG, "RF parameters is same"); } +#endif - esp_hw_reset(); + if (reboot) + esp_hw_reset(4, 1); return 0; } diff --git a/components/spi_flash/src/spi_flash.c b/components/spi_flash/src/spi_flash.c index a2103f8a0..deec0fdd1 100644 --- a/components/spi_flash/src/spi_flash.c +++ b/components/spi_flash/src/spi_flash.c @@ -431,7 +431,7 @@ void user_spi_flash_dio_to_qio_pre_init(void) to_qio = true; } //ENABLE FLASH QIO 0X31H+BIT2 - } else if (((flash_id & 0xFFFFFF) == 0x1640C8) || ((flash_id & 0xFFFFFF) == 0x1840C8)) { + } else if ((flash_id & 0xFFFF) == 0x40C8) { if (flash_gd25q32c_enable_QIO_mode() == true) { to_qio = true; } diff --git a/components/ssl/Kconfig b/components/ssl/Kconfig index 52fee4f0c..c08f79e31 100644 --- a/components/ssl/Kconfig +++ b/components/ssl/Kconfig @@ -13,7 +13,7 @@ config SSL_USING_MBEDTLS config SSL_USING_AXTLS bool "axTLS" config SSL_USING_WOLFSSL - bool "wolfSSL" + bool "wolfSSL (License info in wolfssl subdirectory README)" endchoice menu "wolfSSL" diff --git a/components/ssl/wolfssl/README b/components/ssl/wolfssl/README new file mode 100644 index 000000000..429dd11ac --- /dev/null +++ b/components/ssl/wolfssl/README @@ -0,0 +1,8 @@ +Espressif has a license to distribute wolfSSL royalty-free in binary form on all Espressif MCU products. +You can use the binary wolfSSL library on Espressif devices in products, without additional royalty costs. +The binary library does not include wolfSSL features for TLS 1.3, FIPS or DTLS 1.2. + +Updates to these wolfSSL binary libraries will be available until at least March 2021. + +To discuss additional features, additional support and updates, or to obtain a quote for +other individual licensing options then please contact licensing@wolfssl.com diff --git a/components/ssl/wolfssl/include/user_settings.h b/components/ssl/wolfssl/include/user_settings.h index a20a8221c..a4488ff0a 100644 --- a/components/ssl/wolfssl/include/user_settings.h +++ b/components/ssl/wolfssl/include/user_settings.h @@ -5,7 +5,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * http://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/asn1.h b/components/ssl/wolfssl/wolfssl/wolfssl/openssl/asn1.h index f0a365383..6d22c4b10 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/asn1.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/openssl/asn1.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/bn.h b/components/ssl/wolfssl/wolfssl/wolfssl/openssl/bn.h index 7521c3e5f..dc6f12715 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/bn.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/openssl/bn.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/crypto.h b/components/ssl/wolfssl/wolfssl/wolfssl/openssl/crypto.h index 4e987e5a0..0f195b1c6 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/crypto.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/openssl/crypto.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/dsa.h b/components/ssl/wolfssl/wolfssl/wolfssl/openssl/dsa.h index 978e8ecf4..16fd2d336 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/dsa.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/openssl/dsa.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/ec.h b/components/ssl/wolfssl/wolfssl/wolfssl/openssl/ec.h index 832ea3d6d..e3497143e 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/ec.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/openssl/ec.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/evp.h b/components/ssl/wolfssl/wolfssl/wolfssl/openssl/evp.h index a4fa59e4e..674951732 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/evp.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/openssl/evp.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/hmac.h b/components/ssl/wolfssl/wolfssl/wolfssl/openssl/hmac.h index da32fed4e..31702f7cc 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/hmac.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/openssl/hmac.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/md5.h b/components/ssl/wolfssl/wolfssl/wolfssl/openssl/md5.h index 80e58df91..8eab49a11 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/md5.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/openssl/md5.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/opensslv.h b/components/ssl/wolfssl/wolfssl/wolfssl/openssl/opensslv.h index 15cbe51f2..9955bf38e 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/opensslv.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/openssl/opensslv.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/ripemd.h b/components/ssl/wolfssl/wolfssl/wolfssl/openssl/ripemd.h index 3b5422e01..22dfcc571 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/ripemd.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/openssl/ripemd.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/rsa.h b/components/ssl/wolfssl/wolfssl/wolfssl/openssl/rsa.h index a135fc060..1b406e50b 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/rsa.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/openssl/rsa.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/sha.h b/components/ssl/wolfssl/wolfssl/wolfssl/openssl/sha.h index 6712585ed..63bd5e723 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/sha.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/openssl/sha.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/ssl.h b/components/ssl/wolfssl/wolfssl/wolfssl/openssl/ssl.h index b3da6dac8..2fb088c81 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/ssl.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/openssl/ssl.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/ssl.h b/components/ssl/wolfssl/wolfssl/wolfssl/ssl.h index 8dc693519..fffefc82a 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/ssl.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/ssl.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/version.h b/components/ssl/wolfssl/wolfssl/wolfssl/version.h index 3f636b3fc..19377a212 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/version.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/version.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/aes.h b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/aes.h index 0361beabc..60d3467f8 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/aes.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/aes.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/arc4.h b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/arc4.h index df9a61803..cbb9b198d 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/arc4.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/arc4.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/asn_public.h b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/asn_public.h index b1971f7c3..7199ce29f 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/asn_public.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/asn_public.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/des3.h b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/des3.h index e125c71d0..95254c34a 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/des3.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/des3.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/ecc.h b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/ecc.h index 9dbf0e02e..0048968b3 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/ecc.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/ecc.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/hash.h b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/hash.h index 43760ca52..9435b8f75 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/hash.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/hash.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/hmac.h b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/hmac.h index 6272da317..a539e571c 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/hmac.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/hmac.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/integer.h b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/integer.h index e5330de8d..cd677bb6f 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/integer.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/integer.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/logging.h b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/logging.h index acfafed78..0a2d7f6b1 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/logging.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/logging.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/md5.h b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/md5.h index d43a89bdf..9386b388a 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/md5.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/md5.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/mpi_class.h b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/mpi_class.h index 6f1c43794..2d5b23e1a 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/mpi_class.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/mpi_class.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/mpi_superclass.h b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/mpi_superclass.h index 173ce0e3f..049d90018 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/mpi_superclass.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/mpi_superclass.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/pwdbased.h b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/pwdbased.h index 26982335f..132d8d2bb 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/pwdbased.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/pwdbased.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/random.h b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/random.h index 513317f07..361532729 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/random.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/random.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/settings.h b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/settings.h index 7f7a11671..e8a0085fb 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/settings.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/settings.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/sha.h b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/sha.h index 9d506570a..d9814d677 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/sha.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/sha.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/sha256.h b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/sha256.h index 73c9578d1..9565652e5 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/sha256.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/sha256.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/types.h b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/types.h index f49161a46..4fe68a412 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/types.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/types.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/visibility.h b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/visibility.h index 9cf925a01..905d44c5e 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/visibility.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/visibility.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/wc_port.h b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/wc_port.h index 8492fccf7..aac872b50 100755 --- a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/wc_port.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/wc_port.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/wolfmath.h b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/wolfmath.h index 8be26bc6b..5699be6f1 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/wolfmath.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/wolfmath.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/wolfio.h b/components/ssl/wolfssl/wolfssl/wolfssl/wolfio.h index 322225df6..6993bd079 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/wolfio.h +++ b/components/ssl/wolfssl/wolfssl/wolfssl/wolfio.h @@ -4,7 +4,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * https://www.wolfssl.com */ diff --git a/docs/Doxyfile b/docs/Doxyfile index 1262877de..4c503d3bf 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -52,7 +52,10 @@ INPUT = \ ../../components/esp8266/include/driver/gpio.h \ ../../components/esp8266/include/driver/i2c.h \ ../../components/esp8266/include/driver/pwm.h \ - ../../components/esp8266/include/driver/uart.h + ../../components/esp8266/include/driver/uart.h \ + ../../components/esp8266/include/driver/adc.h \ + ../../components/esp8266/include/driver/spi.h \ + ../../components/esp8266/include/driver/hw_timer.h ## ## Get warnings for functions that have no documentation for their parameters or return value diff --git a/docs/_static/general-notes.gif b/docs/_static/general-notes.gif new file mode 100644 index 000000000..e413b0e9a Binary files /dev/null and b/docs/_static/general-notes.gif differ diff --git a/docs/_static/multi-ota-urls.gif b/docs/_static/multi-ota-urls.gif new file mode 100644 index 000000000..ebd878a35 Binary files /dev/null and b/docs/_static/multi-ota-urls.gif differ diff --git a/docs/_static/single_ota_url.gif b/docs/_static/single_ota_url.gif new file mode 100644 index 000000000..68a0022a9 Binary files /dev/null and b/docs/_static/single_ota_url.gif differ diff --git a/docs/en/api-guides/fota-from-old-new.rst b/docs/en/api-guides/fota-from-old-new.rst new file mode 100644 index 000000000..d5ca61dc7 --- /dev/null +++ b/docs/en/api-guides/fota-from-old-new.rst @@ -0,0 +1,152 @@ +FOTA from an Old SDK to the New ESP8266 RTOS SDK (IDF Style) +************************************************************* + +FOTA: firmware over the air, herein it means the firmware upgrading through Wi-Fi. +Since the ESP8266 RTOS SDK V3.0, we refactored the SDK to be the ESP-IDF style. This document introduces the FOTA from a non-OS (or an old RTOS that earlier than V3.0) firmware to the new IDF style RTOS firmware. +Please note that users need to make modifications to the application, because the new APIs are not compatible with the old SDKs', due to underlying changes in the architecture. + +SDK Partition Map +================= + +Here are the partition maps of the old SDK and the new IDF style RTOS SDK: + +1. The Old ESP8266 SDK +---------------------- + ++------------+------------+------------+-------------------------+ +| Boot/4KB | APP1 | APP2 | System Parameter/16KB | ++------------+------------+------------+-------------------------+ + +2. The New ESP8266 SDK (IDF Style) +---------------------------------- + ++-------------+-----------------------+-----------+------------+------------+ +| Boot/16KB | Partition Table/4KB | NVS | APP1 | APP2 | ++-------------+-----------------------+-----------+------------+------------+ + +In the new IDF style ESP8266 RTOS SDK SDK, each partition's base address is configurable in menuconfig, except boot's. + +Firmware Compatibility +====================== + +To implement FOTA from an old SDK firmware to the new one, users need to download all necessary partitions of the new firmware (including new boot, new partition table, and new application), into the old one's APP partition. + +Then the new bootloader will unpack the packed new firmware, and copy each partition data to the target partition address. + +When FOTA completing, the partition map may look like the following graph (what will it be is based on your actual partition table): + ++--------------------+-----------------+---------------------------+---------------+----------------+----------------+-------------------------+ +| old SDK Boot/4KB | new Boot/16KB | new Partition Table/4KB | new NVS | new APP1 | new APP2 | System Parameter/16KB | ++--------------------+-----------------+-------------------------------------------+----------------+----------------+-------------------------+ + +In this case, there are about 40KB(4KB + 16KB + 4KB + 16KB) flash size cannot be used by users. + +FOTA by Single Firmware URL +--------------------------- + +|single_ota_url| + +.. |single_ota_url| image:: ../../_static/single_ota_url.gif + +FOTA by Multi Firmware URLs +--------------------------- + +|multi-ota-urls| + +.. |multi-ota-urls| image:: ../../_static/multi-ota-urls.gif + +Workflow +======== + +Herein we provide an example of the FOTA. + +Step 1: Connect to AP +---------------------- + +Connect your host PC and the ESP8266 to the same AP. + +Step 2: Configure and Build +----------------------------- + +Here, we use the `SP8266_RTOS_SDK/examples/system/ota `_ example. + +Open a new terminal on your PC, set the following configurations, and then compile the example: + +1. Enter the target directory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + cd $IDF_PATH/examples/system/ota + + +2. Enable the OTA compatibility function +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + Component config ---> + ESP8266-specific ---> + [*] (**Expected**)ESP8266 update from old SDK by OTA + + +3. ESP8285(ESP8266 + 1MB flash) configuration: +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Configure the flash size according to your actual development board's flash. + +:: + + Serial flasher config ---> + Flash size (x MB) ---> real flash size + + +4. Configure example's parameters +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + Example Configuration ---> + (myssid) WiFi SSID + (mypassword) WiFi Password + (192.168.0.3) HTTP Server IP + (8070)HTTP Server Port + (/project_template.ota.bin) HTTP GET Filename + +- WiFi SSID: Wi-Fi SSID of router +- WiFi Password: Wi-Fi password of router +- HTTP Server IP: It may be the PC's IP address +- HTTP Server Port: HTTP server port +- HTTP GET Filename: Using "ota.ota.bin" which is the target firmware of the example + +5. Build the project +^^^^^^^^^^^^^^^^^^^^ + +Input following command to start building:: + + make ota + +After compiling, the final firmware "ota.v2_to_v3.ota.bin" will be generated. Then users can download and update to this new firmware when running an old SDK OTA application. + +- Note: The finally firmware's name mentioned above will be as "xxx.v2_to_v3.ota.bin", "xxx" is the name of your project. + +4. Start HTTP Server +^^^^^^^^^^^^^^^^^^^^ + +:: + + cd build + python -m SimpleHTTPServer 8070 + + +Note +==== + +- It will take a lot of time for the new bootloader unpacking the firmware at the first time, please wait a while. + +- The terminal will print some log that shows the progress: + - log "I (281) boot: Start unpacking V3 firmware ...", it means that bootloader starts unpacking. + - log "Pack V3 firmware successfully and start to reboot", it means that bootloader unpacked firmware successfully. + +- This "unpacking workflow" will only be executed when it is an old SDK firmware that upgrade to the new SDK firmware, for example, V2.0 upgrade to V3.1. After that, the FOTA in later versions (for example, V3.1 upgrade to later) will be the `normal FOTA workflow `_. + diff --git a/docs/en/api-guides/index.rst b/docs/en/api-guides/index.rst index 332d95023..a65df3923 100644 --- a/docs/en/api-guides/index.rst +++ b/docs/en/api-guides/index.rst @@ -6,3 +6,6 @@ API Guides Build System Partition Tables + System Task + PWM and Sniffer Coexists + FOTA from an Old SDK to the New ESP8266 RTOS SDK (IDF Style) diff --git a/docs/en/api-guides/pwm-and-sniffer-coexists.md b/docs/en/api-guides/pwm-and-sniffer-coexists.rst similarity index 62% rename from docs/en/api-guides/pwm-and-sniffer-coexists.md rename to docs/en/api-guides/pwm-and-sniffer-coexists.rst index 1fa2abac5..1f5c32bac 100644 --- a/docs/en/api-guides/pwm-and-sniffer-coexists.md +++ b/docs/en/api-guides/pwm-and-sniffer-coexists.rst @@ -1,30 +1,35 @@ PWM & Sniffer Co-exists -======================= +*********************** 1. Overview ------------ +=========== Without hardware PWM, ESP8266 has to use the hardware timer to simulate the PWM. We are using the Wi-Fi internal timer to drive the PWM, so there may be resource competition issue when using PWM and sniffer/SmartConfig at the same time. - 2. Root Cause -------------- +============= + +To ensure the high precision of the PWM, the hardware Timer1 will trigger the interrupt AHEAD_TICKS1(6us by default) earlier. And in the interrupt, it will poll to wait for AHEAD_TICKS1(6us by default). +After handling the GPIO invert in one channel, the system will check the remaining time (T1) to the next channel invert. + +If the T1 < AHEAD_TICKS2(8us by default), the system will not exit the interrupt, but poll to wait till timeout, and then invert the GPIO in the next channel; then the system will repeat these steps until all channels inverted. + +So theoretically, the max time that PWM may occupy the CPU is 6 + 8 * n, n means the channel count. For example, if there are 3 channels, then PWM may take 30us at most. -To ensure the high precision of the PWM, the hardware Timer1 will trigger the interrupt AHEAD_TICKS1(6us by default) earlier. And in the interrupt, it will poll to wait for AHEAD_TICKS1(6us by default). After handling the GPIO invert in one channel, the system will check the remaining time (T1) to the next channel invert. If the T1 < AHEAD_TICKS2(8us by default), the system will not exit the interrupt, but poll to wait till timeout, and then invert the GPIO in the next channel; then the system will repeat these steps until all channels inverted. -So theoretically, the max time that PWM may occupy the CPU is 6 + 8 * n, n means the channel count. For example, if there are 3 channels, then PWM may take 30us at most. In this case, PWM will affect the Wi-Fi sniffer/SmartConfig function, especially for the capture of the LDPC packets, or HT40 packets which require the CPU to handle them in time, otherwise those packets will loss. +In this case, PWM will affect the Wi-Fi sniffer/SmartConfig function, especially for the capture of the LDPC packets, or HT40 packets which require the CPU to handle them in time, otherwise those packets will loss. 3. Issue that may happen ------------------------- +======================== If your application used both PWM and sniffer/SmartConfig, the sniffer/SmartConfig may take a long time to connect to an AP. You can stop the PWM and try it again. If the sniffer/SmartConfig becomes much faster, then it is the PWM that affect the sniffer/SmartConfig. In this case, you should adjust the frequency, duty cycle and phase of the PWM. 4. Suggestion -------------- +============= When using the PWM and SmartConfig at the same time, please note: 1. The PWM's frequency cannot be too high, 2KHz at most. -2. Revise the PWM's duty cycle and phase, make the time intervals (Tn) between each channel inverting be equal to 0 or be larger than 50us (Tn = 0, or Tn > 50). \ No newline at end of file +2. Revise the PWM's duty cycle and phase, make the time intervals (Tn) between each channel inverting be equal to 0 or be larger than 50us (Tn = 0, or Tn > 50). diff --git a/docs/en/api-reference/peripherals/adc.rst b/docs/en/api-reference/peripherals/adc.rst new file mode 100644 index 000000000..3f69faecd --- /dev/null +++ b/docs/en/api-reference/peripherals/adc.rst @@ -0,0 +1,7 @@ +ADC +=== + +API Reference +------------- + +.. include:: /_build/inc/adc.inc \ No newline at end of file diff --git a/docs/en/api-reference/peripherals/hw_timer.rst b/docs/en/api-reference/peripherals/hw_timer.rst new file mode 100644 index 000000000..50f2a9ec3 --- /dev/null +++ b/docs/en/api-reference/peripherals/hw_timer.rst @@ -0,0 +1,7 @@ +Hardware Timer +============== + +API Reference +------------- + +.. include:: /_build/inc/hw_timer.inc \ No newline at end of file diff --git a/docs/en/api-reference/peripherals/index.rst b/docs/en/api-reference/peripherals/index.rst index 7b5d157f7..0c75709aa 100644 --- a/docs/en/api-reference/peripherals/index.rst +++ b/docs/en/api-reference/peripherals/index.rst @@ -6,8 +6,11 @@ Peripherals API GPIO I2C + SPI PWM UART + ADC + Hardware Timer Example code for this API section is provided in :example:`peripherals` directory of ESP-IDF examples. diff --git a/docs/en/api-reference/peripherals/spi.rst b/docs/en/api-reference/peripherals/spi.rst new file mode 100644 index 000000000..23519a9b2 --- /dev/null +++ b/docs/en/api-reference/peripherals/spi.rst @@ -0,0 +1,7 @@ +SPI +=== + +API Reference +------------- + +.. include:: /_build/inc/spi.inc \ No newline at end of file diff --git a/docs/en/api-reference/wifi/esp_wifi.rst b/docs/en/api-reference/wifi/esp_wifi.rst index 9c4ef5930..3a335e0d8 100644 --- a/docs/en/api-reference/wifi/esp_wifi.rst +++ b/docs/en/api-reference/wifi/esp_wifi.rst @@ -14,6 +14,12 @@ The WiFi libraries provide support for configuring and monitoring the ESP8266 Wi - Scanning for access points (active & passive scanning). - Promiscuous mode monitoring of IEEE802.11 WiFi packets. +Important +^^^^^^^^^ + +Since the ESP8266 RTOS SDK V3.0, we moved some functions from IRAM to flash, including `malloc` and `free` fucntions, to save more memory. +In this case, please do not read/write/erase flash during sniffer or promiscuous mode. You need to disable the sniffer or promiscuous mode at first, then read/write/erase flash. + Application Examples -------------------- diff --git a/docs/en/conf.py b/docs/en/conf.py index a7dde4b1d..9d39e7499 100644 --- a/docs/en/conf.py +++ b/docs/en/conf.py @@ -11,8 +11,8 @@ from conf_common import * # General information about the project. -project = u'ESP-IDF Programming Guide' -copyright = u'2016 - 2018, Espressif Systems (Shanghai) PTE LTD' +project = u'ESP8266 RTOS SDK Programming Guide' +copyright = u'2016 - 2019, Espressif Systems (Shanghai) PTE LTD' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/en/general-notes/index.rst b/docs/en/general-notes/index.rst new file mode 100644 index 000000000..54a5b4b22 --- /dev/null +++ b/docs/en/general-notes/index.rst @@ -0,0 +1,40 @@ +************* +General Notes +************* + +Adding this content here is to improve the user's development efficiency and avoid stepping into known problems. + +1. Bootloader +^^^^^^^^^^^^^ + +V3.1 updated the bootloader to initialize SPI flash I/O mode and clock. So if you are using the V3.0 bootloader, +and now upgrade to the new SDK, please disable the following configuration in the menuconfig: + +:: + + "Bootloader config ---> + [ ] Bootloader init SPI flash" + +2. Sniffer or Smartconfig +^^^^^^^^^^^^^^^^^^^^^^^^^ + +We moved some functions from IRAM to flash, including `malloc` and `free` fucntions, to save more memory. +In this case, please do not read/write/erase flash during sniffer/promiscuous mode. + +You need to disable the sniffer/promiscuous mode at first, then read/write/erase flash. + +3. ESP8285 or ESP8266 + 1MB flash +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +ESP8285 or ESP8266 + 1MB flash can use "Copy OTA Mode" for OTA, more details are in the `examples/system/ota `_. + +4. JTAG I/O +^^^^^^^^^^^ + +In some cases, if enable JTAG I/O (default options), it will cost some more current so that the hardware will cost more power. +So if users don't use Jtag or these GPIOs directly and want to save more power, please enable this option in the menuconfig: + +:: + + "Bootloader config ---> + [ ] Bootloader disable JTAG I/O" diff --git a/docs/en/index.rst b/docs/en/index.rst index ff3291950..d1992a91e 100644 --- a/docs/en/index.rst +++ b/docs/en/index.rst @@ -1,13 +1,13 @@ ESP8266\_RTOS\_SDK (IDF Style) Programming Guide ================================================ -This is the documentation for the new `ESP8266_RTOS_SDK `_ which refacted to be ESP-IDF Style. ESP8266\_RTOS\_SDK is the official development framework for the `ESP8266EX `_ chip. +This is the documentation for the new `ESP8266_RTOS_SDK `_ which refactored to be ESP-IDF Style. ESP8266\_RTOS\_SDK is the official development framework for the `ESP8266EX `_ chip. -================== ================== ================== -|Get Started|_ |API Reference|_ |API Guides|_ ------------------- ------------------ ------------------ -`Get Started`_ `API Reference`_ `API Guides`_ -================== ================== ================== +================== ================== ================== ================== +|Get Started|_ |API Reference|_ |API Guides|_ |General Notes|_ +------------------ ------------------ ------------------ ------------------ +`Get Started`_ `API Reference`_ `API Guides`_ `General Notes`_ +================== ================== ================== ================== .. |Get Started| image:: ../_static/get-started.gif .. _Get Started: get-started/index.html @@ -18,11 +18,15 @@ This is the documentation for the new `ESP8266_RTOS_SDK API Reference API Guides + General Notes * :ref:`genindex` diff --git a/docs/requirements.txt b/docs/requirements.txt index 5474fdb37..6a4de8f3f 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,12 +1,12 @@ # This is a list of python packages used to generate documentation. This file is used with pip: # pip install --user -r requirements.txt # -#sphinx==1.6.5 -#sphinx-rtd-theme -#breathe==4.7.3 -#sphinxcontrib-blockdiag==1.5.3 -#sphinxcontrib-seqdiag==0.8.5 -#sphinxcontrib-actdiag==0.8.5 -#sphinxcontrib-nwdiag==0.9.5 -#recommonmark -#future>=0.16.0 # for ../tools/gen_esp_err_to_name.py +sphinx==1.6.5 +sphinx-rtd-theme +breathe==4.7.3 +sphinxcontrib-blockdiag==1.5.3 +sphinxcontrib-seqdiag==0.8.5 +sphinxcontrib-actdiag==0.8.5 +sphinxcontrib-nwdiag==0.9.5 +recommonmark +future>=0.16.0 # for ../tools/gen_esp_err_to_name.py diff --git a/examples/peripherals/spi_master/README.md b/examples/peripherals/spi_master/README.md index c57c8915e..ebda9bce5 100644 --- a/examples/peripherals/spi_master/README.md +++ b/examples/peripherals/spi_master/README.md @@ -121,6 +121,6 @@ I (1478) spi_master_example: read_data[7]: 0x2 ![wave](wave_write_to_slave.png) - - SPI_MASTER_READ_DATA_FROM + - SPI_MASTER_READ_DATA_FROM_SLAVE ![wave](wave_read_from_slave.png) \ No newline at end of file diff --git a/examples/peripherals/spi_master/wave_read_from_slave.png b/examples/peripherals/spi_master/wave_read_from_slave.png index 5bdf5fcf1..a4fa4651e 100644 Binary files a/examples/peripherals/spi_master/wave_read_from_slave.png and b/examples/peripherals/spi_master/wave_read_from_slave.png differ diff --git a/examples/peripherals/spi_master/wave_write_to_slave.png b/examples/peripherals/spi_master/wave_write_to_slave.png index af0e0477d..b258e2812 100644 Binary files a/examples/peripherals/spi_master/wave_write_to_slave.png and b/examples/peripherals/spi_master/wave_write_to_slave.png differ diff --git a/examples/peripherals/spi_slave/README.md b/examples/peripherals/spi_slave/README.md index d1a1ce51c..1c457a30d 100644 --- a/examples/peripherals/spi_slave/README.md +++ b/examples/peripherals/spi_slave/README.md @@ -121,6 +121,6 @@ I (2741) spi_slave_example: read_data[7]: 0x77777777 ![wave](wave_write_to_slave.png) - - SPI_MASTER_READ_DATA_FROM + - SPI_MASTER_READ_DATA_FROM_SLAVE ![wave](wave_read_from_slave.png) \ No newline at end of file diff --git a/examples/peripherals/spi_slave/main/spi_slave_example_main.c b/examples/peripherals/spi_slave/main/spi_slave_example_main.c index 5e953a635..77a993f7c 100644 --- a/examples/peripherals/spi_slave/main/spi_slave_example_main.c +++ b/examples/peripherals/spi_slave/main/spi_slave_example_main.c @@ -149,6 +149,7 @@ static void spi_slave_read_master_task(void *arg) trans.bits.addr = 32 * 1; trans.bits.mosi = 32 * 8; + spi_trans(HSPI_HOST, trans); // init spi slave buf while (1) { spi_slave_set_status(HSPI_HOST, &status); xSemaphoreTake(spi_wr_buf_done_sem, portMAX_DELAY); diff --git a/examples/peripherals/spi_slave/wave_read_from_slave.png b/examples/peripherals/spi_slave/wave_read_from_slave.png index 5bdf5fcf1..a4fa4651e 100644 Binary files a/examples/peripherals/spi_slave/wave_read_from_slave.png and b/examples/peripherals/spi_slave/wave_read_from_slave.png differ diff --git a/examples/peripherals/spi_slave/wave_write_to_slave.png b/examples/peripherals/spi_slave/wave_write_to_slave.png index af0e0477d..b258e2812 100644 Binary files a/examples/peripherals/spi_slave/wave_write_to_slave.png and b/examples/peripherals/spi_slave/wave_write_to_slave.png differ diff --git a/examples/protocols/https_request/main/https_request_example_main.c b/examples/protocols/https_request/main/https_request_example_main.c index 4450a8fbb..d270eb576 100644 --- a/examples/protocols/https_request/main/https_request_example_main.c +++ b/examples/protocols/https_request/main/https_request_example_main.c @@ -38,6 +38,10 @@ #include "lwip/netdb.h" #include "lwip/dns.h" +#if CONFIG_SSL_USING_WOLFSSL +#include "lwip/apps/sntp.h" +#endif + #include "esp_tls.h" /* The examples use simple WiFi configuration that you can set via @@ -123,11 +127,50 @@ static void initialise_wifi(void) ESP_ERROR_CHECK( esp_wifi_start() ); } +#if CONFIG_SSL_USING_WOLFSSL +static void get_time() +{ + struct timeval now; + int sntp_retry_cnt = 0; + int sntp_retry_time = 0; + + sntp_setoperatingmode(0); + sntp_setservername(0, "pool.ntp.org"); + sntp_init(); + + while (1) { + for (int32_t i = 0; (i < (SNTP_RECV_TIMEOUT / 100)) && now.tv_sec < 1525952900; i++) { + vTaskDelay(100 / portTICK_RATE_MS); + gettimeofday(&now, NULL); + } + + if (now.tv_sec < 1525952900) { + sntp_retry_time = SNTP_RECV_TIMEOUT << sntp_retry_cnt; + + if (SNTP_RECV_TIMEOUT << (sntp_retry_cnt + 1) < SNTP_RETRY_TIMEOUT_MAX) { + sntp_retry_cnt ++; + } + + printf("SNTP get time failed, retry after %d ms\n", sntp_retry_time); + vTaskDelay(sntp_retry_time / portTICK_RATE_MS); + } else { + printf("SNTP get time success\n"); + break; + } + } +} +#endif + static void https_get_task(void *pvParameters) { char buf[512]; int ret, len; +#if CONFIG_SSL_USING_WOLFSSL + /* CA date verification need system time */ + get_time(); +#endif + while(1) { /* Wait for the callback to set the CONNECTED_BIT in the event group. @@ -157,7 +200,13 @@ static void https_get_task(void *pvParameters) if (ret >= 0) { ESP_LOGI(TAG, "%d bytes written", ret); written_bytes += ret; - } else if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + } else if +#if CONFIG_SSL_USING_MBEDTLS + (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) +#else + (ret != WOLFSSL_ERROR_WANT_READ && ret != WOLFSSL_ERROR_WANT_WRITE) +#endif + { ESP_LOGE(TAG, "esp_tls_conn_write returned 0x%x", ret); goto exit; } @@ -170,8 +219,13 @@ static void https_get_task(void *pvParameters) len = sizeof(buf) - 1; bzero(buf, sizeof(buf)); ret = esp_tls_conn_read(tls, (char *)buf, len); - - if(ret == MBEDTLS_ERR_SSL_WANT_WRITE || ret == MBEDTLS_ERR_SSL_WANT_READ) + + if +#if CONFIG_SSL_USING_MBEDTLS + (ret == MBEDTLS_ERR_SSL_WANT_WRITE || ret == MBEDTLS_ERR_SSL_WANT_READ) +#else + (ret == WOLFSSL_ERROR_WANT_READ && ret == WOLFSSL_ERROR_WANT_WRITE) +#endif continue; if(ret < 0) diff --git a/examples/system/ota/README.md b/examples/system/ota/README.md index 4c61207e7..4786f258c 100644 --- a/examples/system/ota/README.md +++ b/examples/system/ota/README.md @@ -1,4 +1,10 @@ +# Important + +If your development board is based on **ESP8285** or **ESP8266 + 1MB flash**, you should read this document carefully, especially the Chapter **"Principle"**. + +--- + # Simple OTA Demo This example demonstrates a working OTA (over the air) firmware update workflow. @@ -11,10 +17,43 @@ This example is a *simplified demonstration*, for production firmware updates yo An app running on ESP8266 can upgrade itself by downloading a new app "image" binary file, and storing it in flash. -In this example, the ESP8266 has 3 images in flash: factory, OTA_0, OTA_1. Each of these is a self-contained partition. The number of OTA image partition is determined by the partition table layout. +In this example, the ESP8266 has 2 images in flash: OTA_0, OTA_1. Each of these is a self-contained partition. The number of OTA image partition is determined by the partition table layout. + +Flash the example through serial port with command "make flash" to update the OTA_0 app image. In first boot, the bootloader loads this OTA_0 app image which then will execute an OTA update (triggered in the example code). The OTA update will download a new image from an http server and save it into the OTA_1 partition. After that, the example code will update the ota_data partition to indicate the new app partition, and then reboot, which leads to the second boot. During the second boot, the bootloader will read the ota_data, and select to run the new OTA image. + +# Custom partition configuration -Flashing the example over serial with "make flash" updates the factory app image. On first boot, the bootloader loads this factory app image which then performs an OTA update (triggered in the example code). The update downloads a new image from an http server and saves it into the OTA_0 partition. At this point the example code updates the ota_data partition to indicate the new app partition, and resets. The bootloader reads ota_data, determines the new OTA image has been selected, and runs it. +If customers want to use their own partition tables with specific partition location. Please see following steps: +## Step 1: Create partition file + +Create a partition managment file with "cvs" formate, please refer to "doc/en/api-guides/partition-tables.rst" + +## Step 2: Select custom partition mode + +1. Select custom partition tables at "menuconfig": + +``` +Partition Table ---> + Partition Table (XXXXXX) ---> + (X) Custom partition table CSV +``` + +2. Configurate custom partition location at: + +``` +(XXXXXX)Custom partition CSV file +``` + +Note: System will add the absolute path of the project to the head of the "Custom partition CSV file" automatically when compling. + +3. Configurate patition table location if necessary: + +``` +(XXXXXX)Partition table offset address at flash +``` + +**make ota flash** will only download the app1 at **APP1 partition offset**. # Workflow @@ -32,11 +71,26 @@ Python has a built-in HTTP server that can be used for example purposes. For our upgrade example OTA file, we're going to use the `get-started/project_template` example. -Open a new terminal to run the HTTP server, then run these commands to build the example and start the server: +Open a new terminal to run the HTTP server, then run these commands to build the example and start the server, if your board's flash size is "1 MB", you should firstly configure flash size to be "1 MB"(default is "2 MB") at "menuconfig" and then build project: + +Configure 1MB flash if it is needed: + +``` +Serial flasher config ---> + Flash size (2 MB) ---> + (X) 1 MB +``` + +Build project: ``` cd $IDF_PATH/examples/get-started/project_template -make +make ota +``` + +Start http server at the directory of "build": + +``` cd build python -m SimpleHTTPServer 8070 ``` @@ -45,8 +99,6 @@ While the server is running, the contents of the build directory can be browsed NB: On some systems, the command may be `python2 -m SimpleHTTPServer`. -NB: You've probably noticed there is nothing special about the "project_template" example when used for OTA updates. This is because any .bin app file which is built by esp-idf can be used as an app image for OTA. The only difference is whether it is written to a factory partition or an OTA partition. - If you have any firewall software running that will block incoming access to port 8070, configure it to allow access while running the example. ## Step 3: Build OTA Example @@ -59,6 +111,16 @@ Change back to the OTA example directory, and type `make menuconfig` to configur If serving the "project_template" example, you can leave the default filename as-is. +Configure 1MB flash if need: + +``` +Serial flasher config ---> + Flash size (2 MB) ---> + (X) 1 MB +``` + +Configurate the application partition table information and it must be the same as the OTA example's information, you can refer to the **Custom partition configuration**. + Save your changes, and type `make` to build the example. ## Step 4: Flash OTA Example @@ -80,11 +142,29 @@ When the example starts up, it will print "ota: Starting OTA example..." then: 3. Write the image to flash, and configure the next boot from this image. 4. Reboot +# Principle + +Command "make ota" will generate 3 binaries: "xxx(project name).app1.bin", "xxx(project name).app2.bin" and "xxx(project name).ota.bin". You should only upload the "xxx(project name).ota.bin" to your OTA server and let the app download it as the example. + +"xxx.app1.bin" is for downloading to OTA_0 partition, and "xxx.app2.bin" is for downloading to OTA_1 partition. If your board's flash size is larger than "1 MB" or you select "Copy OTA" function, then "xxx.app1.bin" = "xxx.app2.bin" = "xxx.ota.bin". Otherwise If your board's flash size is "1 MB" and you don't select "Copy OTA" function, "xxx.app1.bin" != "xxx.app2.bin" != "xxx.ota.bin", "xxx.ota.bin" = "xxx.app1.bin" + "xxx.app2.bin". So the flash size configuration is very important. Otherwise if and at the last The example will select the binary it needs and download it into flash. + +Based on the above theory, we can see that for ESP8266 + 2MB flash(or larger size), app1 and app2 are the same, you can download it directly without any distinction. But for ESP8285 (ESP8266 + 1MB flash), the ota0 (app1) and ota1 (app2) are different, you need to distinguish which one should be downloaded, and to what location, during FOTA. Now, the way in the example code is to synthesize app1 and app2 into an "xxxx (project name).ota.bin". And only write the target app (app1 or app2) into the flash, according to the location of download, when FOTA; the other part will be discarded. + +On the other hand, if you want to use ESP8285(ESP8266 + 1MB flash) and don't want to upload 2 binaries for OTA, you can enable the "Copy OTA" function in menuconfig. + +``` +Component config ---> + ESP8266-specific ---> + [*] (**Expected**)Boot copy app +``` + +After enabling "Copy OTA" mode, the system will always download the app bin into ota_1 partition and then re-boot. After reboot, the bootloader will unpack the app bin and copy it to the ota_0 partition, then run the application in ota_0 partition. + # Troubleshooting -* Check your PC can ping the ESP8266 at its IP, and that the IP, AP and other configuration settings are correct in menuconfig. -* Check if any firewall software is preventing incoming connections on the PC. -* Check you can see the configured file (default project_template.bin) if you browse the file listing at http://127.0.0.1/ +* Check whether your PC can ping the ESP8266 at its IP, and make sure that the IP, AP and other configuration settings are correct in menuconfig. +* Check if there is any firewall software on the PC that prevents incoming connections. +* Check whether you can see the configured file (default project_template.ota.bin) when browsing the file listing at http://127.0.0.1/ * If you have another PC or a phone, try viewing the file listing from the separate host. ## Error "ota_begin error err=0x104" diff --git a/examples/system/ota/main/Kconfig.projbuild b/examples/system/ota/main/Kconfig.projbuild index 8727d1b76..c5a0b69ff 100644 --- a/examples/system/ota/main/Kconfig.projbuild +++ b/examples/system/ota/main/Kconfig.projbuild @@ -32,7 +32,7 @@ config SERVER_PORT config EXAMPLE_FILENAME string "HTTP GET Filename" - default "/hello-world.bin" + default "/project_template.ota.bin" help Filename of the app image file to download for the OTA update. diff --git a/examples/system/ota/main/ota_example_main.c b/examples/system/ota/main/ota_example_main.c index cfbfc76d9..7e62e6093 100644 --- a/examples/system/ota/main/ota_example_main.c +++ b/examples/system/ota/main/ota_example_main.c @@ -32,6 +32,50 @@ #define BUFFSIZE 1500 #define TEXT_BUFFSIZE 1024 +#ifdef CONFIG_ESP8266_OTA_FROM_OLD +/* + * Users should add your real firmware information here. + * And the real infoarmation will be generated by "script". + */ +#ifdef CONFIG_ESPTOOLPY_FLASHSIZE_1MB +/* + * The configuration is related to file "partitions_two_ota_v2tov3.1MB". + */ +#define OTA_EXAMPLE_APP_OFFSET 0x6000UL +#else +/* + * The configuration is related to file "partitions_two_ota_v2tov3.2MB". + */ +#define OTA_EXAMPLE_APP_OFFSET 0xf000UL +#endif +#endif + +typedef enum esp_ota_firm_state { + ESP_OTA_INIT = 0, + ESP_OTA_PREPARE, + ESP_OTA_START, + ESP_OTA_RECVED, + ESP_OTA_FINISH, +} esp_ota_firm_state_t; + +typedef struct esp_ota_firm { + uint8_t ota_num; + uint8_t update_ota_num; + + esp_ota_firm_state_t state; + + size_t content_len; + + size_t read_bytes; + size_t write_bytes; + + size_t ota_size; + size_t ota_offset; + + const char *buf; + size_t bytes; +} esp_ota_firm_t; + static const char *TAG = "ota"; /*an ota data write buffer ready to write to the flash*/ static char ota_write_data[BUFFSIZE + 1] = { 0 }; @@ -50,6 +94,10 @@ static EventGroupHandle_t wifi_event_group; to the AP with an IP? */ const int CONNECTED_BIT = BIT0; +#ifdef CONFIG_ESP8266_OTA_FROM_OLD +static const uint32_t s_ota_app_offset = OTA_EXAMPLE_APP_OFFSET; +#endif + static esp_err_t event_handler(void *ctx, system_event_t *event) { switch (event->event_id) { @@ -92,7 +140,7 @@ static void initialise_wifi(void) } /*read buffer by byte still delim ,return read bytes counts*/ -static int read_until(char *buffer, char delim, int len) +static int read_until(const char *buffer, char delim, int len) { // /*TODO: delim check,buffer check,further: do an buffer length limited*/ int i = 0; @@ -102,38 +150,6 @@ static int read_until(char *buffer, char delim, int len) return i + 1; } -/* resolve a packet from http socket - * return true if packet including \r\n\r\n that means http packet header finished,start to receive packet body - * otherwise return false - * */ -static bool read_past_http_header(char text[], int total_len, esp_ota_handle_t update_handle) -{ - /* i means current position */ - int i = 0, i_read_len = 0; - while (text[i] != 0 && i < total_len) { - i_read_len = read_until(&text[i], '\n', total_len); - // if we resolve \r\n line,we think packet header is finished - if (i_read_len == 2) { - int i_write_len = total_len - (i + 2); - memset(ota_write_data, 0, BUFFSIZE); - /*copy first http packet body to write buffer*/ - memcpy(ota_write_data, &(text[i + 2]), i_write_len); - - esp_err_t err = esp_ota_write( update_handle, (const void *)ota_write_data, i_write_len); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Error: esp_ota_write failed! err=0x%x", err); - return false; - } else { - ESP_LOGI(TAG, "esp_ota_write header OK"); - binary_file_length += i_write_len; - } - return true; - } - i += i_read_len; - } - return false; -} - static bool connect_to_http_server() { ESP_LOGI(TAG, "Server IP: %s Server Port:%s", EXAMPLE_SERVER_IP, EXAMPLE_SERVER_PORT); @@ -177,6 +193,158 @@ static void __attribute__((noreturn)) task_fatal_error() } } +bool _esp_ota_firm_parse_http(esp_ota_firm_t *ota_firm, const char *text, size_t total_len, size_t *parse_len) +{ + /* i means current position */ + int i = 0, i_read_len = 0; + char *ptr = NULL, *ptr2 = NULL; + char length_str[32]; + + while (text[i] != 0 && i < total_len) { + if (ota_firm->content_len == 0 && (ptr = (char *)strstr(text, "Content-Length")) != NULL) { + ptr += 16; + ptr2 = (char *)strstr(ptr, "\r\n"); + memset(length_str, 0, sizeof(length_str)); + memcpy(length_str, ptr, ptr2 - ptr); + ota_firm->content_len = atoi(length_str); +#ifdef CONFIG_ESP8266_OTA_FROM_OLD + ota_firm->ota_size = ota_firm->content_len - s_ota_app_offset; + ota_firm->ota_offset = s_ota_app_offset; +#else +#if defined(CONFIG_ESPTOOLPY_FLASHSIZE_1MB) && !defined(CONFIG_ESP8266_BOOT_COPY_APP) + ota_firm->ota_size = ota_firm->content_len / ota_firm->ota_num; + ota_firm->ota_offset = ota_firm->ota_size * ota_firm->update_ota_num; +#else + ota_firm->ota_size = ota_firm->content_len; + ota_firm->ota_offset = 0; +#endif +#endif + ESP_LOGI(TAG, "parse Content-Length:%d, ota_size %d", ota_firm->content_len, ota_firm->ota_size); + } + + i_read_len = read_until(&text[i], '\n', total_len - i); + + if (i_read_len > total_len - i) { + ESP_LOGE(TAG, "recv malformed http header"); + task_fatal_error(); + } + + // if resolve \r\n line, http header is finished + if (i_read_len == 2) { + if (ota_firm->content_len == 0) { + ESP_LOGE(TAG, "did not parse Content-Length item"); + task_fatal_error(); + } + + *parse_len = i + 2; + + return true; + } + + i += i_read_len; + } + + return false; +} + +static size_t esp_ota_firm_do_parse_msg(esp_ota_firm_t *ota_firm, const char *in_buf, size_t in_len) +{ + size_t tmp; + size_t parsed_bytes = in_len; + + switch (ota_firm->state) { + case ESP_OTA_INIT: + if (_esp_ota_firm_parse_http(ota_firm, in_buf, in_len, &tmp)) { + ota_firm->state = ESP_OTA_PREPARE; + ESP_LOGD(TAG, "Http parse %d bytes", tmp); + parsed_bytes = tmp; + } + break; + case ESP_OTA_PREPARE: + ota_firm->read_bytes += in_len; + + if (ota_firm->read_bytes >= ota_firm->ota_offset) { + ota_firm->buf = &in_buf[in_len - (ota_firm->read_bytes - ota_firm->ota_offset)]; + ota_firm->bytes = ota_firm->read_bytes - ota_firm->ota_offset; + ota_firm->write_bytes += ota_firm->read_bytes - ota_firm->ota_offset; + ota_firm->state = ESP_OTA_START; + ESP_LOGD(TAG, "Receive %d bytes and start to update", ota_firm->read_bytes); + ESP_LOGD(TAG, "Write %d total %d", ota_firm->bytes, ota_firm->write_bytes); + } + + break; + case ESP_OTA_START: + if (ota_firm->write_bytes + in_len > ota_firm->ota_size) { + ota_firm->bytes = ota_firm->ota_size - ota_firm->write_bytes; + ota_firm->state = ESP_OTA_RECVED; + } else + ota_firm->bytes = in_len; + + ota_firm->buf = in_buf; + + ota_firm->write_bytes += ota_firm->bytes; + + ESP_LOGD(TAG, "Write %d total %d", ota_firm->bytes, ota_firm->write_bytes); + + break; + case ESP_OTA_RECVED: + parsed_bytes = 0; + ota_firm->state = ESP_OTA_FINISH; + break; + default: + parsed_bytes = 0; + ESP_LOGD(TAG, "State is %d", ota_firm->state); + break; + } + + return parsed_bytes; +} + +static void esp_ota_firm_parse_msg(esp_ota_firm_t *ota_firm, const char *in_buf, size_t in_len) +{ + size_t parse_bytes = 0; + + ESP_LOGD(TAG, "Input %d bytes", in_len); + + do { + size_t bytes = esp_ota_firm_do_parse_msg(ota_firm, in_buf + parse_bytes, in_len - parse_bytes); + ESP_LOGD(TAG, "Parse %d bytes", bytes); + if (bytes) + parse_bytes += bytes; + } while (parse_bytes != in_len); +} + +static inline int esp_ota_firm_is_finished(esp_ota_firm_t *ota_firm) +{ + return (ota_firm->state == ESP_OTA_FINISH || ota_firm->state == ESP_OTA_RECVED); +} + +static inline int esp_ota_firm_can_write(esp_ota_firm_t *ota_firm) +{ + return (ota_firm->state == ESP_OTA_START || ota_firm->state == ESP_OTA_RECVED); +} + +static inline const char* esp_ota_firm_get_write_buf(esp_ota_firm_t *ota_firm) +{ + return ota_firm->buf; +} + +static inline size_t esp_ota_firm_get_write_bytes(esp_ota_firm_t *ota_firm) +{ + return ota_firm->bytes; +} + +static void esp_ota_firm_init(esp_ota_firm_t *ota_firm, const esp_partition_t *update_partition) +{ + memset(ota_firm, 0, sizeof(esp_ota_firm_t)); + ota_firm->state = ESP_OTA_INIT; + ota_firm->ota_num = get_ota_partition_count(); + ota_firm->update_ota_num = update_partition->subtype - ESP_PARTITION_SUBTYPE_APP_OTA_0; + + ESP_LOGI(TAG, "Totoal OTA number %d update to %d part", ota_firm->ota_num, ota_firm->update_ota_num); + +} + static void ota_example_task(void *pvParameter) { esp_err_t err; @@ -184,7 +352,7 @@ static void ota_example_task(void *pvParameter) esp_ota_handle_t update_handle = 0 ; const esp_partition_t *update_partition = NULL; - ESP_LOGI(TAG, "Starting OTA example..."); + ESP_LOGI(TAG, "Starting OTA example... @ %p flash %s", ota_example_task, CONFIG_ESPTOOLPY_FLASHSIZE); const esp_partition_t *configured = esp_ota_get_boot_partition(); const esp_partition_t *running = esp_ota_get_running_partition(); @@ -246,7 +414,11 @@ static void ota_example_task(void *pvParameter) } ESP_LOGI(TAG, "esp_ota_begin succeeded"); - bool resp_body_start = false, flag = true; + bool flag = true; + esp_ota_firm_t ota_firm; + + esp_ota_firm_init(&ota_firm, update_partition); + /*deal with all receive packet*/ while (flag) { memset(text, 0, TEXT_BUFFSIZE); @@ -255,11 +427,15 @@ static void ota_example_task(void *pvParameter) if (buff_len < 0) { /*receive error*/ ESP_LOGE(TAG, "Error: receive data error! errno=%d", errno); task_fatal_error(); - } else if (buff_len > 0 && !resp_body_start) { /*deal with response header*/ - memcpy(ota_write_data, text, buff_len); - resp_body_start = read_past_http_header(text, buff_len, update_handle); - } else if (buff_len > 0 && resp_body_start) { /*deal with response body*/ - memcpy(ota_write_data, text, buff_len); + } else if (buff_len > 0) { /*deal with response body*/ + esp_ota_firm_parse_msg(&ota_firm, text, buff_len); + + if (!esp_ota_firm_can_write(&ota_firm)) + continue; + + memcpy(ota_write_data, esp_ota_firm_get_write_buf(&ota_firm), esp_ota_firm_get_write_bytes(&ota_firm)); + buff_len = esp_ota_firm_get_write_bytes(&ota_firm); + err = esp_ota_write( update_handle, (const void *)ota_write_data, buff_len); if (err != ESP_OK) { ESP_LOGE(TAG, "Error: esp_ota_write failed! err=0x%x", err); @@ -274,6 +450,9 @@ static void ota_example_task(void *pvParameter) } else { ESP_LOGE(TAG, "Unexpected recv result"); } + + if (esp_ota_firm_is_finished(&ota_firm)) + break; } ESP_LOGI(TAG, "Total Write binary data length : %d", binary_file_length); diff --git a/examples/system/universal_ota/partitions_two_ota.1MB.mini.csv b/examples/system/ota/partitions_two_ota.1MB.mini.csv similarity index 100% rename from examples/system/universal_ota/partitions_two_ota.1MB.mini.csv rename to examples/system/ota/partitions_two_ota.1MB.mini.csv diff --git a/examples/system/ota/partitions_two_ota_v2tov3.1MB.csv b/examples/system/ota/partitions_two_ota_v2tov3.1MB.csv new file mode 100644 index 000000000..55a38b101 --- /dev/null +++ b/examples/system/ota/partitions_two_ota_v2tov3.1MB.csv @@ -0,0 +1,10 @@ +# Name, Type, SubType, Offset, Size, Flags +# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild +# Bootloader is at 0x1000 - 0x5000, total 16KB +# Partition table is at 0x5000 - 0x6000, total 4KB +# Reserve 4 sectors at the end flash address for V2 updating to V3 and system can read V2 parameters. +phy_init, data, phy, 0x6000, 0x1000 +ota_0, 0, ota_0, 0x7000, 0x77000 +nvs, data, nvs, 0x7f000, 0x4000 +otadata, data, ota, 0x83000, 0x2000 +ota_1, 0, ota_1, 0x85000, 0x77000 diff --git a/examples/system/universal_ota/partitions_two_ota_v2tov3.1MB.csv b/examples/system/ota/partitions_two_ota_v2tov3.2MB.csv similarity index 75% rename from examples/system/universal_ota/partitions_two_ota_v2tov3.1MB.csv rename to examples/system/ota/partitions_two_ota_v2tov3.2MB.csv index 6d3a3a19b..8eb78894c 100644 --- a/examples/system/universal_ota/partitions_two_ota_v2tov3.1MB.csv +++ b/examples/system/ota/partitions_two_ota_v2tov3.2MB.csv @@ -3,9 +3,8 @@ # Bootloader is at 0x1000 - 0x8000, total 28KB # Partition table is at 0x8000 - 0x9000, total 4KB # Reserve 4 sectors at the end flash address for V2 updating to V3 and system can read V2 parameters. -# If you don't need read v2 parameters, don't reserve the 4 sectors. nvs, data, nvs, 0x9000, 0x4000 otadata, data, ota, 0xd000, 0x2000 phy_init, data, phy, 0xf000, 0x1000 -ota_0, 0, ota_0, 0x10000, 0x6C000 -ota_1, 0, ota_1, 0x90000, 0x6C000 +ota_0, 0, ota_0, 0x10000, 0xEC000 +ota_1, 0, ota_1, 0x110000,0xEC000 diff --git a/examples/system/ota/sdkconfig.defaults b/examples/system/ota/sdkconfig.defaults index 50f320c69..2476365ab 100644 --- a/examples/system/ota/sdkconfig.defaults +++ b/examples/system/ota/sdkconfig.defaults @@ -1,4 +1,8 @@ # Default sdkconfig parameters to use the ESP8266 OTA -CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y -CONFIG_PARTITION_TABLE_TWO_OTA=y CONFIG_LWIP_SOCKET_MULTITHREAD= + +CONFIG_ESPTOOLPY_FLASHSIZE_1MB=y + +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_two_ota.1MB.mini.csv" +CONFIG_PARTITION_TABLE_OFFSET=0x4000 diff --git a/examples/system/universal_ota/Makefile b/examples/system/universal_ota/Makefile deleted file mode 100644 index 7ffb10234..000000000 --- a/examples/system/universal_ota/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# This is a project Makefile. It is assumed the directory this Makefile resides in is a -# project subdirectory. -# - -PROJECT_NAME := ota - -include $(IDF_PATH)/make/project.mk - diff --git a/examples/system/universal_ota/OTA_workflow.png b/examples/system/universal_ota/OTA_workflow.png deleted file mode 100644 index 5fd4c3e91..000000000 Binary files a/examples/system/universal_ota/OTA_workflow.png and /dev/null differ diff --git a/examples/system/universal_ota/README.md b/examples/system/universal_ota/README.md deleted file mode 100644 index d0d2a61ca..000000000 --- a/examples/system/universal_ota/README.md +++ /dev/null @@ -1,187 +0,0 @@ - -# Simple OTA Demo - -This example demonstrates a working OTA (over the air) firmware update workflow. - -This example is a *simplified demonstration*, for production firmware updates you should use a secure protocol such as HTTPS. - ---- - -# Aim - -An app running on ESP8266 can upgrade itself by downloading a new app "image" binary file, and storing it in flash. - -In this example, the ESP8266 has 2 images in flash: OTA_0, OTA_1. Each of these is a self-contained partition. The number of OTA image partition is determined by the partition table layout. - -Flashing the example over serial with "make flash" updates the OTA_0 app image. On first boot, the bootloader loads this OTA_0 app image which then performs an OTA update (triggered in the example code). The update downloads a new image from an http server and saves it into the OTA_1 partition. At this point the example code updates the ota_data partition to indicate the new app partition, and reboots. The bootloader reads ota_data, determines the new OTA image has been selected, and runs it. - - -# Custom partition configuration - -If customers want to use their own partition tables with specific partition location. Please see following steps: - -## Step 1: Create partition file - -Create a partition managment file with "cvs" formate, please refer to "doc/en/api-guides/partition-tables.rst" - -## Step 2: Select custom partition mode - -1. Select custom partition tables at "menuconfig": - -``` -Partition Table ---> - Partition Table (XXXXXX) ---> - (X) Custom partition table CSV -``` - -2. Configurate custom partition location at: - -``` -(XXXXXX)Custom partition CSV file -``` - -Note: System will add the absolute path of the project to the head of the "Custom partition CSV file" automatically when compling. - -3. Configurate patition table location if necessary: - -``` -(XXXXXX)Partition table offset address at flash -``` - -## Step 3: Configurate application location: - -Configurate application location at "mennuconfig" like following base on partition table file. - -If you select 1MB flash, application location configuration menu is like following: - -``` -Partition Table ---> - - [*] Support to setup partition parameter of APP2 - (0x5000) App1 offset address - (0x7B000) App1 size by bytes - (0x85000) App2 offset address - (0x7b000) App2 size by bytes -``` - -If you select 2MB flash and above size, application location configuration menu is like following: - -``` -Partition Table ---> - - (0x10000) APP1 partition offset - (0xF0000) APP1 partition size(by bytes) -``` - -Note: The firmware location information must be same as partition table file. **make ota flash** will only download the app1 at **APP1 partition offset**. - -# Workflow - -The OTA_workflow.png diagram demonstrates the overall workflow: - -![OTA Workflow diagram](OTA_workflow.png) - -## Step 1: Connect to AP - -Connect your host PC to the same AP that you will use for the ESP8266. - -## Step 2: Run HTTP Server - -Python has a built-in HTTP server that can be used for example purposes. - -For our upgrade example OTA file, we're going to use the `get-started/project_template` example. - -Open a new terminal to run the HTTP server, then run these commands to build the example and start the server, if your board's flash size is "1 MB", you should firstly configure flash size to be "1 MB"(default is "2 MB") at "menuconfig" and then build project: - -Configure 1MB flash if need: - -``` -Serial flasher config ---> - Flash size (2 MB) ---> - (X) 1 MB -``` - -Build project: - -``` -cd $IDF_PATH/examples/get-started/project_template -make ota -``` - -Start http server at the directory of "build": - -``` -cd build -python -m SimpleHTTPServer 8070 -``` - -While the server is running, the contents of the build directory can be browsed at http://localhost:8070/ - -NB: On some systems, the command may be `python2 -m SimpleHTTPServer`. - -NB: Command "make ota" will generate 3 binaries: "xxx(project name).app1.bin", "xxx(project name).app2.bin" and "xxx(project name).ota.bin". You should only upload the "xxx(project name).ota.bin" to your OTA server and let the app download it by the example. - -NB: "xxx.app1.bin" is for downloading to OTA_0 partition, and "xxx.app2.bin" is for downloading to OTA_1 partition. If your board's flash size is larger than "1 MB", then "xxx.app1.bin" = "xxx.app2.bin" = "xxx.ota.bin". Otherwise "xxx.ota.bin" = "xxx.app1.bin" + "xxx.app2.bin". So the flash size configuration is very important. The example will select the binary it needs and store it to flash. - -If you have any firewall software running that will block incoming access to port 8070, configure it to allow access while running the example. - -## Step 3: Build OTA Example - -Change back to the OTA example directory, and type `make menuconfig` to configure the OTA example. Under the "Example Configuration" submenu, fill in the following details: - -* WiFi SSID & Password -* IP address of your host PC as "HTTP Server" -* HTTP Port number (if using the Python HTTP server above, the default is correct) - -If serving the "project_template" example, you can leave the default filename as-is. - -Configure 1MB flash if need: - -``` -Serial flasher config ---> - Flash size (2 MB) ---> - (X) 1 MB -``` - -Configurate the application location information and it must be same as the OTA example's information, how to do refer to **Step 3: Configurate application location** of **Custom partition configuration**. - -Save your changes, and type `make` to build the example. - -## Step 4: Flash OTA Example - -When flashing, use the `erase_flash` target first to erase the entire flash (this deletes any leftover data in the ota_data partition). Then flash the factory image over serial: - -``` -make erase_flash flash -``` - -(The `make erase_flash flash` means "erase everything, then flash". `make flash` only erases the parts of flash which are being rewritten.) - -## Step 5: Run the OTA Example - -When the example starts up, it will print "ota: Starting OTA example..." then: - -1. Connect to the AP with configured SSID and password. -2. Connect to the HTTP server and download the new image. -3. Write the image to flash, and configure the next boot from this image. -4. Reboot - -# Troubleshooting - -* Check your PC can ping the ESP8266 at its IP, and that the IP, AP and other configuration settings are correct in menuconfig. -* Check if any firewall software is preventing incoming connections on the PC. -* Check you can see the configured file (default project_template.ota.bin) if you browse the file listing at http://127.0.0.1/ -* If you have another PC or a phone, try viewing the file listing from the separate host. - -## Error "ota_begin error err=0x104" - -If you see this error then check that the configured (and actual) flash size is large enough for the partitions in the partition table. The default "two OTA slots" partition table only works with 4MB flash size. To use OTA with smaller flash sizes, create a custom partition table CSV (look in components/partition_table) and configure it in menuconfig. - -If changing partition layout, it is usually wise to run "make erase_flash" between steps. - -## Production Implementation - -If scaling this example for production use, please consider: - -* Using an encrypted communications channel such as HTTPS. -* Dealing with timeouts or WiFi disconnections while flashing. diff --git a/examples/system/universal_ota/main/Kconfig.projbuild b/examples/system/universal_ota/main/Kconfig.projbuild deleted file mode 100644 index c5a0b69ff..000000000 --- a/examples/system/universal_ota/main/Kconfig.projbuild +++ /dev/null @@ -1,40 +0,0 @@ -menu "Example Configuration" - -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "myssid" - help - WiFi password (WPA or WPA2) for the example to use. - - Can be left blank if the network has no security set. - -config SERVER_IP - string "HTTP Server IP" - default "192.168.0.3" - help - HTTP Server IP to download the image file from. - - See example README.md for details. - -config SERVER_PORT - string "HTTP Server Port" - default "8070" - help - HTTP Server port to connect to. - Should be chosen not to conflict with any other port used - on the system. - -config EXAMPLE_FILENAME - string "HTTP GET Filename" - default "/project_template.ota.bin" - help - Filename of the app image file to download for - the OTA update. - -endmenu diff --git a/examples/system/universal_ota/main/component.mk b/examples/system/universal_ota/main/component.mk deleted file mode 100644 index a98f634ea..000000000 --- a/examples/system/universal_ota/main/component.mk +++ /dev/null @@ -1,4 +0,0 @@ -# -# "main" pseudo-component makefile. -# -# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) diff --git a/examples/system/universal_ota/main/ota_example_main.c b/examples/system/universal_ota/main/ota_example_main.c deleted file mode 100644 index b51372879..000000000 --- a/examples/system/universal_ota/main/ota_example_main.c +++ /dev/null @@ -1,462 +0,0 @@ -/* OTA example - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ -#include -#include -#include -#include - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/event_groups.h" - -#include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" -#include "esp_log.h" -#include "esp_ota_ops.h" - -#include "nvs.h" -#include "nvs_flash.h" - -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD -#define EXAMPLE_SERVER_IP CONFIG_SERVER_IP -#define EXAMPLE_SERVER_PORT CONFIG_SERVER_PORT -#define EXAMPLE_FILENAME CONFIG_EXAMPLE_FILENAME -#define BUFFSIZE 1500 -#define TEXT_BUFFSIZE 1024 - -typedef enum esp_ota_firm_state { - ESP_OTA_INIT = 0, - ESP_OTA_PREPARE, - ESP_OTA_START, - ESP_OTA_RECVED, - ESP_OTA_FINISH, -} esp_ota_firm_state_t; - -typedef struct esp_ota_firm { - uint8_t ota_num; - uint8_t update_ota_num; - - esp_ota_firm_state_t state; - - size_t content_len; - - size_t read_bytes; - size_t write_bytes; - - size_t ota_size; - size_t ota_offset; - - const char *buf; - size_t bytes; -} esp_ota_firm_t; - -static const char *TAG = "ota"; -/*an ota data write buffer ready to write to the flash*/ -static char ota_write_data[BUFFSIZE + 1] = { 0 }; -/*an packet receive buffer*/ -static char text[BUFFSIZE + 1] = { 0 }; -/* an image total length*/ -static int binary_file_length = 0; -/*socket id*/ -static int socket_id = -1; - -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ -const int CONNECTED_BIT = BIT0; - -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - switch (event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - /* This is a workaround as ESP32 WiFi libs don't currently - auto-reassociate. */ - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); - break; - default: - break; - } - return ESP_OK; -} - -static void initialise_wifi(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); -} - -/*read buffer by byte still delim ,return read bytes counts*/ -static int read_until(const char *buffer, char delim, int len) -{ -// /*TODO: delim check,buffer check,further: do an buffer length limited*/ - int i = 0; - while (buffer[i] != delim && i < len) { - ++i; - } - return i + 1; -} - -static bool connect_to_http_server() -{ - ESP_LOGI(TAG, "Server IP: %s Server Port:%s", EXAMPLE_SERVER_IP, EXAMPLE_SERVER_PORT); - - int http_connect_flag = -1; - struct sockaddr_in sock_info; - - socket_id = socket(AF_INET, SOCK_STREAM, 0); - if (socket_id == -1) { - ESP_LOGE(TAG, "Create socket failed!"); - return false; - } - - // set connect info - memset(&sock_info, 0, sizeof(struct sockaddr_in)); - sock_info.sin_family = AF_INET; - sock_info.sin_addr.s_addr = inet_addr(EXAMPLE_SERVER_IP); - sock_info.sin_port = htons(atoi(EXAMPLE_SERVER_PORT)); - - // connect to http server - http_connect_flag = connect(socket_id, (struct sockaddr *)&sock_info, sizeof(sock_info)); - if (http_connect_flag == -1) { - ESP_LOGE(TAG, "Connect to server failed! errno=%d", errno); - close(socket_id); - return false; - } else { - ESP_LOGI(TAG, "Connected to server"); - return true; - } - return false; -} - -static void __attribute__((noreturn)) task_fatal_error() -{ - ESP_LOGE(TAG, "Exiting task due to fatal error..."); - close(socket_id); - (void)vTaskDelete(NULL); - - while (1) { - ; - } -} - -bool _esp_ota_firm_parse_http(esp_ota_firm_t *ota_firm, const char *text, size_t total_len, size_t *parse_len) -{ - /* i means current position */ - int i = 0, i_read_len = 0; - char *ptr = NULL, *ptr2 = NULL; - char length_str[32]; - - while (text[i] != 0 && i < total_len) { - if (ota_firm->content_len == 0 && (ptr = (char *)strstr(text, "Content-Length")) != NULL) { - ptr += 16; - ptr2 = (char *)strstr(ptr, "\r\n"); - memset(length_str, 0, sizeof(length_str)); - memcpy(length_str, ptr, ptr2 - ptr); - ota_firm->content_len = atoi(length_str); -#ifdef CONFIG_ESPTOOLPY_FLASHSIZE_1MB - ota_firm->ota_size = ota_firm->content_len / ota_firm->ota_num; - ota_firm->ota_offset = ota_firm->ota_size * ota_firm->update_ota_num; -#else - ota_firm->ota_size = ota_firm->content_len; - ota_firm->ota_offset = 0; -#endif - ESP_LOGI(TAG, "parse Content-Length:%d, ota_size %d", ota_firm->content_len, ota_firm->ota_size); - } - - i_read_len = read_until(&text[i], '\n', total_len - i); - - if (i_read_len > total_len - i) { - ESP_LOGE(TAG, "recv malformed http header"); - task_fatal_error(); - } - - // if resolve \r\n line, http header is finished - if (i_read_len == 2) { - if (ota_firm->content_len == 0) { - ESP_LOGE(TAG, "did not parse Content-Length item"); - task_fatal_error(); - } - - *parse_len = i + 2; - - return true; - } - - i += i_read_len; - } - - return false; -} - -static size_t esp_ota_firm_do_parse_msg(esp_ota_firm_t *ota_firm, const char *in_buf, size_t in_len) -{ - size_t tmp; - size_t parsed_bytes = in_len; - - switch (ota_firm->state) { - case ESP_OTA_INIT: - if (_esp_ota_firm_parse_http(ota_firm, in_buf, in_len, &tmp)) { - ota_firm->state = ESP_OTA_PREPARE; - ESP_LOGD(TAG, "Http parse %d bytes", tmp); - parsed_bytes = tmp; - } - break; - case ESP_OTA_PREPARE: - ota_firm->read_bytes += in_len; - - if (ota_firm->read_bytes >= ota_firm->ota_offset) { - ota_firm->buf = &in_buf[in_len - (ota_firm->read_bytes - ota_firm->ota_offset)]; - ota_firm->bytes = ota_firm->read_bytes - ota_firm->ota_offset; - ota_firm->write_bytes += ota_firm->read_bytes - ota_firm->ota_offset; - ota_firm->state = ESP_OTA_START; - ESP_LOGD(TAG, "Receive %d bytes and start to update", ota_firm->read_bytes); - ESP_LOGD(TAG, "Write %d total %d", ota_firm->bytes, ota_firm->write_bytes); - } - - break; - case ESP_OTA_START: - if (ota_firm->write_bytes + in_len > ota_firm->ota_size) { - ota_firm->bytes = ota_firm->ota_size - ota_firm->write_bytes; - ota_firm->state = ESP_OTA_RECVED; - } else - ota_firm->bytes = in_len; - - ota_firm->buf = in_buf; - - ota_firm->write_bytes += ota_firm->bytes; - - ESP_LOGD(TAG, "Write %d total %d", ota_firm->bytes, ota_firm->write_bytes); - - break; - case ESP_OTA_RECVED: - parsed_bytes = 0; - ota_firm->state = ESP_OTA_FINISH; - break; - default: - parsed_bytes = 0; - ESP_LOGD(TAG, "State is %d", ota_firm->state); - break; - } - - return parsed_bytes; -} - -static void esp_ota_firm_parse_msg(esp_ota_firm_t *ota_firm, const char *in_buf, size_t in_len) -{ - size_t parse_bytes = 0; - - ESP_LOGD(TAG, "Input %d bytes", in_len); - - do { - size_t bytes = esp_ota_firm_do_parse_msg(ota_firm, in_buf + parse_bytes, in_len - parse_bytes); - ESP_LOGD(TAG, "Parse %d bytes", bytes); - if (bytes) - parse_bytes += bytes; - } while (parse_bytes != in_len); -} - -static inline int esp_ota_firm_is_finished(esp_ota_firm_t *ota_firm) -{ - return (ota_firm->state == ESP_OTA_FINISH || ota_firm->state == ESP_OTA_RECVED); -} - -static inline int esp_ota_firm_can_write(esp_ota_firm_t *ota_firm) -{ - return (ota_firm->state == ESP_OTA_START || ota_firm->state == ESP_OTA_RECVED); -} - -static inline const char* esp_ota_firm_get_write_buf(esp_ota_firm_t *ota_firm) -{ - return ota_firm->buf; -} - -static inline size_t esp_ota_firm_get_write_bytes(esp_ota_firm_t *ota_firm) -{ - return ota_firm->bytes; -} - -static void esp_ota_firm_init(esp_ota_firm_t *ota_firm, const esp_partition_t *update_partition) -{ - memset(ota_firm, 0, sizeof(esp_ota_firm_t)); - ota_firm->state = ESP_OTA_INIT; - ota_firm->ota_num = get_ota_partition_count(); - ota_firm->update_ota_num = update_partition->subtype - ESP_PARTITION_SUBTYPE_APP_OTA_0; - - ESP_LOGI(TAG, "Totoal OTA number %d update to %d part", ota_firm->ota_num, ota_firm->update_ota_num); - -} - -static void ota_example_task(void *pvParameter) -{ - esp_err_t err; - /* update handle : set by esp_ota_begin(), must be freed via esp_ota_end() */ - esp_ota_handle_t update_handle = 0 ; - const esp_partition_t *update_partition = NULL; - - ESP_LOGI(TAG, "Starting OTA example... @ %p flash %s", ota_example_task, CONFIG_ESPTOOLPY_FLASHSIZE); - - const esp_partition_t *configured = esp_ota_get_boot_partition(); - const esp_partition_t *running = esp_ota_get_running_partition(); - - if (configured != running) { - ESP_LOGW(TAG, "Configured OTA boot partition at offset 0x%08x, but running from offset 0x%08x", - configured->address, running->address); - ESP_LOGW(TAG, "(This can happen if either the OTA boot data or preferred boot image become corrupted somehow.)"); - } - ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08x)", - running->type, running->subtype, running->address); - - /* Wait for the callback to set the CONNECTED_BIT in the - event group. - */ - xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, - false, true, portMAX_DELAY); - ESP_LOGI(TAG, "Connect to Wifi ! Start to Connect to Server...."); - - /*connect to http server*/ - if (connect_to_http_server()) { - ESP_LOGI(TAG, "Connected to http server"); - } else { - ESP_LOGE(TAG, "Connect to http server failed!"); - task_fatal_error(); - } - - /*send GET request to http server*/ - const char *GET_FORMAT = - "GET %s HTTP/1.0\r\n" - "Host: %s:%s\r\n" - "User-Agent: esp-idf/1.0 esp32\r\n\r\n"; - - char *http_request = NULL; - int get_len = asprintf(&http_request, GET_FORMAT, EXAMPLE_FILENAME, EXAMPLE_SERVER_IP, EXAMPLE_SERVER_PORT); - if (get_len < 0) { - ESP_LOGE(TAG, "Failed to allocate memory for GET request buffer"); - task_fatal_error(); - } - int res = send(socket_id, http_request, get_len, 0); - free(http_request); - - if (res < 0) { - ESP_LOGE(TAG, "Send GET request to server failed"); - task_fatal_error(); - } else { - ESP_LOGI(TAG, "Send GET request to server succeeded"); - } - - update_partition = esp_ota_get_next_update_partition(NULL); - ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%x", - update_partition->subtype, update_partition->address); - assert(update_partition != NULL); - - err = esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle); - if (err != ESP_OK) { - ESP_LOGE(TAG, "esp_ota_begin failed, error=%d", err); - task_fatal_error(); - } - ESP_LOGI(TAG, "esp_ota_begin succeeded"); - - bool flag = true; - esp_ota_firm_t ota_firm; - - esp_ota_firm_init(&ota_firm, update_partition); - - /*deal with all receive packet*/ - while (flag) { - memset(text, 0, TEXT_BUFFSIZE); - memset(ota_write_data, 0, BUFFSIZE); - int buff_len = recv(socket_id, text, TEXT_BUFFSIZE, 0); - if (buff_len < 0) { /*receive error*/ - ESP_LOGE(TAG, "Error: receive data error! errno=%d", errno); - task_fatal_error(); - } else if (buff_len > 0) { /*deal with response body*/ - esp_ota_firm_parse_msg(&ota_firm, text, buff_len); - - if (!esp_ota_firm_can_write(&ota_firm)) - continue; - - memcpy(ota_write_data, esp_ota_firm_get_write_buf(&ota_firm), esp_ota_firm_get_write_bytes(&ota_firm)); - buff_len = esp_ota_firm_get_write_bytes(&ota_firm); - - err = esp_ota_write( update_handle, (const void *)ota_write_data, buff_len); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Error: esp_ota_write failed! err=0x%x", err); - task_fatal_error(); - } - binary_file_length += buff_len; - ESP_LOGI(TAG, "Have written image length %d", binary_file_length); - } else if (buff_len == 0) { /*packet over*/ - flag = false; - ESP_LOGI(TAG, "Connection closed, all packets received"); - close(socket_id); - } else { - ESP_LOGE(TAG, "Unexpected recv result"); - } - - if (esp_ota_firm_is_finished(&ota_firm)) - break; - } - - ESP_LOGI(TAG, "Total Write binary data length : %d", binary_file_length); - - if (esp_ota_end(update_handle) != ESP_OK) { - ESP_LOGE(TAG, "esp_ota_end failed!"); - task_fatal_error(); - } - err = esp_ota_set_boot_partition(update_partition); - if (err != ESP_OK) { - ESP_LOGE(TAG, "esp_ota_set_boot_partition failed! err=0x%x", err); - task_fatal_error(); - } - ESP_LOGI(TAG, "Prepare to restart system!"); - esp_restart(); - return ; -} - -void app_main() -{ - // Initialize NVS. - esp_err_t err = nvs_flash_init(); - if (err == ESP_ERR_NVS_NO_FREE_PAGES) { - // OTA app partition table has a smaller NVS partition size than the non-OTA - // partition table. This size mismatch may cause NVS initialization to fail. - // If this happens, we erase NVS partition and initialize NVS again. - ESP_ERROR_CHECK(nvs_flash_erase()); - err = nvs_flash_init(); - } - ESP_ERROR_CHECK( err ); - - initialise_wifi(); - xTaskCreate(&ota_example_task, "ota_example_task", 8192, NULL, 5, NULL); -} diff --git a/examples/system/universal_ota/sdkconfig.defaults b/examples/system/universal_ota/sdkconfig.defaults deleted file mode 100644 index 5afc779bb..000000000 --- a/examples/system/universal_ota/sdkconfig.defaults +++ /dev/null @@ -1,12 +0,0 @@ -# Default sdkconfig parameters to use the ESP8266 OTA -CONFIG_LWIP_SOCKET_MULTITHREAD= - -CONFIG_ESPTOOLPY_FLASHSIZE_1MB=y - -CONFIG_PARTITION_TABLE_CUSTOM=y -CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_two_ota.1MB.mini.csv" -CONFIG_PARTITION_TABLE_OFFSET=0x4000 -CONFIG_APP1_OFFSET=0x6000 -CONFIG_APP1_SIZE=0x7A000 -CONFIG_APP2_OFFSET=0x86000 -CONFIG_APP2_SIZE=0x7A000 diff --git a/make/project.mk b/make/project.mk index 6abcf722b..1b7277c01 100644 --- a/make/project.mk +++ b/make/project.mk @@ -131,6 +131,9 @@ ifndef COMPONENT_DIRS EXTRA_COMPONENT_DIRS ?= COMPONENT_DIRS := $(PROJECT_PATH)/components $(EXTRA_COMPONENT_DIRS) $(IDF_PATH)/components $(PROJECT_PATH)/main endif +# Make sure that every directory in the list is an absolute path without trailing slash. +# This is necessary to split COMPONENT_DIRS into SINGLE_COMPONENT_DIRS and MULTI_COMPONENT_DIRS below. +COMPONENT_DIRS := $(foreach cd,$(COMPONENT_DIRS),$(abspath $(cd))) export COMPONENT_DIRS ifdef SRCDIRS @@ -138,32 +141,55 @@ $(warning SRCDIRS variable is deprecated. These paths can be added to EXTRA_COMP COMPONENT_DIRS += $(abspath $(SRCDIRS)) endif -# The project Makefile can define a list of components, but if it does not do this we just take all available components -# in the component dirs. A component is COMPONENT_DIRS directory, or immediate subdirectory, +# List of component directories, i.e. directories which contain a component.mk file +SINGLE_COMPONENT_DIRS := $(abspath $(dir $(dir $(foreach cd,$(COMPONENT_DIRS),\ + $(wildcard $(cd)/component.mk))))) + +# List of components directories, i.e. directories which may contain components +MULTI_COMPONENT_DIRS := $(filter-out $(SINGLE_COMPONENT_DIRS),$(COMPONENT_DIRS)) + +# The project Makefile can define a list of components, but if it does not do this +# we just take all available components in the component dirs. +# A component is COMPONENT_DIRS directory, or immediate subdirectory, # which contains a component.mk file. # # Use the "make list-components" target to debug this step. ifndef COMPONENTS # Find all component names. The component names are the same as the # directories they're in, so /bla/components/mycomponent/component.mk -> mycomponent. -COMPONENTS := $(dir $(foreach cd,$(COMPONENT_DIRS), \ - $(wildcard $(cd)/*/component.mk) $(wildcard $(cd)/component.mk) \ - )) +# We need to do this for MULTI_COMPONENT_DIRS only, since SINGLE_COMPONENT_DIRS +# are already known to contain component.mk. +COMPONENTS := $(dir $(foreach cd,$(MULTI_COMPONENT_DIRS),$(wildcard $(cd)/*/component.mk))) \ + $(SINGLE_COMPONENT_DIRS) COMPONENTS := $(sort $(foreach comp,$(COMPONENTS),$(lastword $(subst /, ,$(comp))))) endif -# After a full manifest of component names is determined, subtract the ones explicitly omitted by the project Makefile. +# After a full manifest of component names is determined, subtract the ones explicitly +# omitted by the project Makefile. +EXCLUDE_COMPONENTS ?= ifdef EXCLUDE_COMPONENTS -COMPONENTS := $(filter-out $(EXCLUDE_COMPONENTS), $(COMPONENTS)) +COMPONENTS := $(filter-out $(subst ",,$(EXCLUDE_COMPONENTS)), $(COMPONENTS)) +# to keep syntax highlighters happy: ")) endif export COMPONENTS # Resolve all of COMPONENTS into absolute paths in COMPONENT_PATHS. +# For each entry in COMPONENT_DIRS: +# - either this is directory with multiple components, in which case check that +# a subdirectory with component name exists, and it contains a component.mk file. +# - or, this is a directory of a single component, in which case the name of this +# directory has to match the component name # # If a component name exists in multiple COMPONENT_DIRS, we take the first match. # # NOTE: These paths must be generated WITHOUT a trailing / so we # can use $(notdir x) to get the component name. -COMPONENT_PATHS := $(foreach comp,$(COMPONENTS),$(firstword $(foreach cd,$(COMPONENT_DIRS),$(wildcard $(dir $(cd))$(comp) $(cd)/$(comp))))) +COMPONENT_PATHS := $(foreach comp,$(COMPONENTS),\ + $(firstword $(foreach cd,$(COMPONENT_DIRS),\ + $(if $(findstring $(cd),$(MULTI_COMPONENT_DIRS)),\ + $(abspath $(dir $(wildcard $(cd)/$(comp)/component.mk))),)\ + $(if $(findstring $(cd),$(SINGLE_COMPONENT_DIRS)),\ + $(if $(filter $(comp),$(notdir $(cd))),$(cd),),)\ + ))) export COMPONENT_PATHS TEST_COMPONENTS ?= @@ -192,6 +218,8 @@ COMPONENT_LDFLAGS := COMPONENT_SUBMODULES := COMPONENT_LIBRARIES := +global-macro: + # COMPONENT_PROJECT_VARS is the list of component_project_vars.mk generated makefiles # for each component. # @@ -437,7 +465,7 @@ endef define GenerateComponentTargets .PHONY: component-$(2)-build component-$(2)-clean -component-$(2)-build: check-submodules $(call prereq_if_explicit, component-$(2)-clean) | $(BUILD_DIR_BASE)/$(2) +component-$(2)-build: check-submodules global-macro $(call prereq_if_explicit, component-$(2)-clean) | $(BUILD_DIR_BASE)/$(2) $(call ComponentMake,$(1),$(2)) build component-$(2)-clean: | $(BUILD_DIR_BASE)/$(2) $(BUILD_DIR_BASE)/$(2)/component_project_vars.mk diff --git a/tools/check_python_dependencies.py b/tools/check_python_dependencies.py index d8767004b..45baee62e 100755 --- a/tools/check_python_dependencies.py +++ b/tools/check_python_dependencies.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # Copyright 2018 Espressif Systems (Shanghai) PTE LTD # diff --git a/tools/idf_monitor.py b/tools/idf_monitor.py index 86b53538c..772b2fc84 100755 --- a/tools/idf_monitor.py +++ b/tools/idf_monitor.py @@ -98,11 +98,6 @@ def esp_openlog(project_name): DEFAULT_TOOLCHAIN_PREFIX = "xtensa-esp32-elf-" -def is_ascii(b): - if b > '\x7f': - return False - return True - def get_time_stamp(): ct = time.time() local_time = time.localtime(ct) @@ -334,8 +329,6 @@ def handle_serial_input(self, data): # this may need to be made more efficient, as it pushes out a byte # at a time to the console for b in data: - if is_ascii(b) == False: - continue if self.enable_time == 'y' and self.next_line == True: self.console.write_bytes(get_time_stamp() + ": ") self.next_line = False diff --git a/tools/pack_fw.py b/tools/pack_fw.py index c94d2246c..652cc4d1b 100644 --- a/tools/pack_fw.py +++ b/tools/pack_fw.py @@ -19,8 +19,9 @@ import sys import binascii import struct +import logging -__version__ = "1.0.1" +__version__ = "1.0.2" FLASH_SECTOR_SIZE = 0x1000 @@ -52,6 +53,8 @@ def __call__(self, parser, namespace, values, option_string=None): for i in range(0, len(values) ,2): try: address = int(values[i], 0) + if address == 0: + address = 0x1000 except ValueError: raise argparse.ArgumentError(self, 'Address "%s" must be a number' % values[i]) try: @@ -83,10 +86,10 @@ def pack3(args): print(e) end_addr = None + prev_addr = 0 + prec_file = '' + app_offset = 0 for address, argfile in args.addr_filename: - if address == 0: - address = 4096 - if end_addr is not None and address > end_addr: data = (address - end_addr) * ['ff'] filled = binascii.a2b_hex(''.join(data)) @@ -98,10 +101,20 @@ def pack3(args): fw_data += data argfile.seek(0, 2) - end_addr = address + argfile.tell() + prev_addr = address + prec_file = argfile.name + end_addr = address + argfile.tell() + if app_offset is not 0: + raise Exception('Partition %s can be put behind %s'%(argfile.name, args.app)) + else: + if args.app in argfile.name: + app_offset = address - 0x1000 except IOError as e: raise e + if app_offset is 0: + raise Exception('Failed to find application binary %s in all arguments'%args.app) + crc32 = esp8266_crc32(fw_data) fw_data += struct.pack(' pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy