From 57009aaa7f9138958678d08bc9ecc2f037f4e9da Mon Sep 17 00:00:00 2001 From: Jeroen Domburg Date: Fri, 11 Nov 2016 19:20:54 +0800 Subject: [PATCH 01/48] Add a more scalable mechanism for the FreeRTOS tick- and idle hooks; idle handler now uses WAITI to reduce power --- components/esp32/freertos_hooks.c | 81 +++++++++++++++++++ components/esp32/include/esp_freertos_hooks.h | 58 +++++++++++++ components/esp32/int_wdt.c | 64 ++++++++------- components/esp32/task_wdt.c | 24 ++++-- components/freertos/Kconfig | 29 +++++++ .../include/freertos/FreeRTOSConfig.h | 4 +- components/freertos/tasks.c | 20 +++-- 7 files changed, 234 insertions(+), 46 deletions(-) create mode 100644 components/esp32/freertos_hooks.c create mode 100644 components/esp32/include/esp_freertos_hooks.h diff --git a/components/esp32/freertos_hooks.c b/components/esp32/freertos_hooks.c new file mode 100644 index 000000000..50ebd3d05 --- /dev/null +++ b/components/esp32/freertos_hooks.c @@ -0,0 +1,81 @@ +#include +#include +#include +#include "esp_attr.h" +#include "esp_freertos_hooks.h" + +//We use just a static array here because it's not expected many components will need +//an idle or tick hook. +#define MAX_HOOKS 8 + +static esp_freertos_idle_cb_t idle_cb[MAX_HOOKS]={0}; +static esp_freertos_tick_cb_t tick_cb[MAX_HOOKS]={0}; + +void IRAM_ATTR esp_vApplicationTickHook() +{ + int n; + for (n=0; n +#include "esp_err.h" + + +/* + Definitions for the tickhook and idlehook callbacks +*/ +typedef bool (*esp_freertos_idle_cb_t)(); +typedef void (*esp_freertos_tick_cb_t)(); + +/** + * @brief Register a callback to be called on the freertos idle hook + * The callback should return true if it's okay for the core to + * sleep until an interrupt (or FreeRTOS tick) happens and false + * if it should be called again as fast as possible. + * + * @param esp_freertos_idle_cb_t new_idle_cb : Callback to be called + * + * @return ESP_OK : Callback registered + * @return ESP_ERR_NO_MEM : No more space to register hook + */ +esp_err_t esp_register_freertos_idle_hook(esp_freertos_idle_cb_t new_idle_cb); + +/** + * @brief Register a callback to be called on the freertos tick hook + * + * @param esp_freertos_tick_cb_t new_tick_cb : Callback to be called + * + * @return ESP_OK : Callback registered + * @return ESP_ERR_NO_MEM : No more space to register hook + */ +esp_err_t esp_register_freertos_tick_hook(esp_freertos_tick_cb_t tick_cb); + + +/** + * @brief Unregister an idle callback registered earlier + * + * @param esp_freertos_idle_cb_t new_idle_cb : Callback to be unregistered + * + * @return void + */ +void esp_deregister_freertos_idle_hook(esp_freertos_idle_cb_t old_idle_cb); + + +/** + * @brief Unregister a tick callback registered earlier + * + * @param esp_freertos_idle_cb_t new_idle_cb : Callback to be unregistered + * + * @return void + */ +void esp_deregister_freertos_tick_hook(esp_freertos_tick_cb_t old_tick_cb); + + +#endif \ No newline at end of file diff --git a/components/esp32/int_wdt.c b/components/esp32/int_wdt.c index 11de8f20d..fe3ddab37 100644 --- a/components/esp32/int_wdt.c +++ b/components/esp32/int_wdt.c @@ -25,6 +25,7 @@ #include "esp_err.h" #include "esp_intr.h" #include "esp_attr.h" +#include "esp_freertos_hooks.h" #include "soc/timer_group_struct.h" #include "soc/timer_group_reg.h" @@ -36,6 +37,38 @@ #define WDT_INT_NUM 24 +//Take care: the tick hook can also be called before esp_int_wdt_init() is called. +#if CONFIG_INT_WDT_CHECK_CPU1 +//Not static; the ISR assembly checks this. +bool int_wdt_app_cpu_ticked=false; + +static void IRAM_ATTR tick_hook(void) { + if (xPortGetCoreID()!=0) { + int_wdt_app_cpu_ticked=true; + } else { + //Only feed wdt if app cpu also ticked. + if (int_wdt_app_cpu_ticked) { + TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE; + TIMERG1.wdt_config2=CONFIG_INT_WDT_TIMEOUT_MS*2; //Set timeout before interrupt + TIMERG1.wdt_config3=CONFIG_INT_WDT_TIMEOUT_MS*4; //Set timeout before reset + TIMERG1.wdt_feed=1; + TIMERG1.wdt_wprotect=0; + int_wdt_app_cpu_ticked=false; + } + } +} +#else +static void IRAM_ATTR tick_hook(void) { + if (xPortGetCoreID()!=0) return; + TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE; + TIMERG1.wdt_config2=CONFIG_INT_WDT_TIMEOUT_MS*2; //Set timeout before interrupt + TIMERG1.wdt_config3=CONFIG_INT_WDT_TIMEOUT_MS*4; //Set timeout before reset + TIMERG1.wdt_feed=1; + TIMERG1.wdt_wprotect=0; +} +#endif + + void esp_int_wdt_init() { TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE; TIMERG1.wdt_config0.sys_reset_length=7; //3.2uS @@ -53,6 +86,7 @@ void esp_int_wdt_init() { TIMERG1.wdt_wprotect=0; TIMERG1.int_clr_timers.wdt=1; TIMERG1.int_ena.wdt=1; + esp_register_freertos_tick_hook(tick_hook); ESP_INTR_DISABLE(WDT_INT_NUM); intr_matrix_set(xPortGetCoreID(), ETS_TG1_WDT_LEVEL_INTR_SOURCE, WDT_INT_NUM); //We do not register a handler for the interrupt because it is interrupt level 4 which @@ -62,35 +96,5 @@ void esp_int_wdt_init() { } -//Take care: the tick hook can also be called before esp_int_wdt_init() is called. -#if CONFIG_INT_WDT_CHECK_CPU1 -//Not static; the ISR assembly checks this. -bool int_wdt_app_cpu_ticked=false; - -void IRAM_ATTR vApplicationTickHook(void) { - if (xPortGetCoreID()!=0) { - int_wdt_app_cpu_ticked=true; - } else { - //Only feed wdt if app cpu also ticked. - if (int_wdt_app_cpu_ticked) { - TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE; - TIMERG1.wdt_config2=CONFIG_INT_WDT_TIMEOUT_MS*2; //Set timeout before interrupt - TIMERG1.wdt_config3=CONFIG_INT_WDT_TIMEOUT_MS*4; //Set timeout before reset - TIMERG1.wdt_feed=1; - TIMERG1.wdt_wprotect=0; - int_wdt_app_cpu_ticked=false; - } - } -} -#else -void IRAM_ATTR vApplicationTickHook(void) { - if (xPortGetCoreID()!=0) return; - TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE; - TIMERG1.wdt_config2=CONFIG_INT_WDT_TIMEOUT_MS*2; //Set timeout before interrupt - TIMERG1.wdt_config3=CONFIG_INT_WDT_TIMEOUT_MS*4; //Set timeout before reset - TIMERG1.wdt_feed=1; - TIMERG1.wdt_wprotect=0; -} -#endif #endif \ No newline at end of file diff --git a/components/esp32/task_wdt.c b/components/esp32/task_wdt.c index bec1cadaa..f8cfdef26 100644 --- a/components/esp32/task_wdt.c +++ b/components/esp32/task_wdt.c @@ -26,6 +26,7 @@ #include "esp_err.h" #include "esp_intr.h" #include "esp_attr.h" +#include "esp_freertos_hooks.h" #include "soc/timer_group_struct.h" #include "soc/timer_group_reg.h" #include "esp_log.h" @@ -140,6 +141,18 @@ void esp_task_wdt_delete() { } } + +#if CONFIG_TASK_WDT_CHECK_IDLE_TASK +static bool idle_hook(void) { +#if !CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1 + if (xPortGetCoreID()!=0) return; +#endif + esp_task_wdt_feed(); + return true; +} +#endif + + void esp_task_wdt_init() { TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; TIMERG0.wdt_config0.sys_reset_length=7; //3.2uS @@ -153,6 +166,9 @@ void esp_task_wdt_init() { TIMERG0.wdt_config0.en=1; TIMERG0.wdt_feed=1; TIMERG0.wdt_wprotect=0; +#if CONFIG_TASK_WDT_CHECK_IDLE_TASK + esp_register_freertos_idle_hook(idle_hook); +#endif ESP_INTR_DISABLE(ETS_T0_WDT_INUM); intr_matrix_set(xPortGetCoreID(), ETS_TG0_WDT_LEVEL_INTR_SOURCE, ETS_T0_WDT_INUM); xt_set_interrupt_handler(ETS_T0_WDT_INUM, task_wdt_isr, NULL); @@ -161,13 +177,5 @@ void esp_task_wdt_init() { ESP_INTR_ENABLE(ETS_T0_WDT_INUM); } -#if CONFIG_TASK_WDT_CHECK_IDLE_TASK -void vApplicationIdleHook(void) { -#if !CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1 - if (xPortGetCoreID()!=0) return; -#endif - esp_task_wdt_feed(); -} -#endif #endif \ No newline at end of file diff --git a/components/freertos/Kconfig b/components/freertos/Kconfig index 91e824b2d..b9db00e50 100644 --- a/components/freertos/Kconfig +++ b/components/freertos/Kconfig @@ -141,6 +141,35 @@ config FREERTOS_ISR_STACKSIZE The interrupt handlers have their own stack. The size of the stack can be defined here. Each processor has its own stack, so the total size occupied will be twice this. +config FREERTOS_LEGACY_HOOKS + bool "Use FreeRTOS legacy hooks" + default n + help + FreeRTOS offers a number of hooks/callback functions that are called when a timer + tick happens, the idle thread runs etc. esp-idf replaces these by runtime registerable + hooks using the esp_register_freertos_xxx_hook system, but for legacy reasons the old + hooks can also still be enabled. Please enable this only if you have code that for some + reason can't be migrated to the esp_register_freertos_xxx_hook system. + +if FREERTOS_LEGACY_HOOKS + +config FREERTOS_LEGACY_IDLE_HOOK + bool "Enable legacy idle hook" + default n + help + If enabled, FreeRTOS will call a function called vApplicationIdleHook when the idle thread + on a CPU is running. Please make sure your code defines such a function. + +config FREERTOS_LEGACY_TICK_HOOK + bool "Enable legacy tick hook" + default n + help + If enabled, FreeRTOS will call a function called vApplicationTickHook when a FreeRTOS + tick is executed. Please make sure your code defines such a function. + +endif #FREERTOS_LEGACY_HOOKS + + menuconfig FREERTOS_DEBUG_INTERNALS bool "Debug FreeRTOS internals" default n diff --git a/components/freertos/include/freertos/FreeRTOSConfig.h b/components/freertos/include/freertos/FreeRTOSConfig.h index 47566ab3b..13ce73e0a 100644 --- a/components/freertos/include/freertos/FreeRTOSConfig.h +++ b/components/freertos/include/freertos/FreeRTOSConfig.h @@ -152,9 +152,9 @@ *----------------------------------------------------------*/ #define configUSE_PREEMPTION 1 -#define configUSE_IDLE_HOOK ( CONFIG_TASK_WDT_CHECK_IDLE_TASK ) +#define configUSE_IDLE_HOOK ( CONFIG_FREERTOS_LEGACY_IDLE_HOOK ) -#define configUSE_TICK_HOOK ( CONFIG_INT_WDT ) +#define configUSE_TICK_HOOK ( CONFIG_FREERTOS_LEGACY_TICK_HOOK ) #define configTICK_RATE_HZ ( CONFIG_FREERTOS_HZ ) diff --git a/components/freertos/tasks.c b/components/freertos/tasks.c index b79d3a98b..88aa8d3ef 100644 --- a/components/freertos/tasks.c +++ b/components/freertos/tasks.c @@ -476,6 +476,7 @@ to its original value when it is released. */ #if configUSE_TICK_HOOK > 0 extern void vApplicationTickHook( void ); #endif +extern void esp_vApplicationTickHook( void ); #if portFIRST_TASK_HOOK extern void vPortFirstTaskHook(TaskFunction_t taskfn); @@ -2360,22 +2361,21 @@ BaseType_t xSwitchRequired = pdFALSE; We can't really calculate what we need, that's done on core 0... just assume we need a switch. ToDo: Make this more intelligent? -- JD */ - //We do need the tick hook to satisfy the int watchdog. - #if ( configUSE_TICK_HOOK == 1 ) { /* Guard against the tick hook being called when the pended tick count is being unwound (when the scheduler is being unlocked). */ if( ( uxSchedulerSuspended[ xPortGetCoreID() ] != ( UBaseType_t ) pdFALSE ) || uxPendedTicks == ( UBaseType_t ) 0U ) { + #if ( configUSE_TICK_HOOK == 1 ) vApplicationTickHook(); + #endif /* configUSE_TICK_HOOK */ + esp_vApplicationTickHook(); } else { mtCOVERAGE_TEST_MARKER(); } } - #endif /* configUSE_TICK_HOOK */ - return pdTRUE; } @@ -2506,20 +2506,21 @@ BaseType_t xSwitchRequired = pdFALSE; } #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */ - #if ( configUSE_TICK_HOOK == 1 ) { /* Guard against the tick hook being called when the pended tick count is being unwound (when the scheduler is being unlocked). */ if( uxPendedTicks == ( UBaseType_t ) 0U ) { + #if ( configUSE_TICK_HOOK == 1 ) vApplicationTickHook(); + #endif /* configUSE_TICK_HOOK */ + esp_vApplicationTickHook(); } else { mtCOVERAGE_TEST_MARKER(); } } - #endif /* configUSE_TICK_HOOK */ taskEXIT_CRITICAL_ISR(&xTaskQueueMutex); } else @@ -2533,6 +2534,7 @@ BaseType_t xSwitchRequired = pdFALSE; vApplicationTickHook(); } #endif + esp_vApplicationTickHook(); } #if ( configUSE_PREEMPTION == 1 ) @@ -3270,6 +3272,12 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) vApplicationIdleHook(); } #endif /* configUSE_IDLE_HOOK */ + { + /* Call the esp-idf hook system */ + extern void esp_vApplicationIdleHook( void ); + esp_vApplicationIdleHook(); + } + /* This conditional compilation should use inequality to 0, not equality to 1. This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when From 734c1dd954a37cc859962f567b2d4b9c148b7657 Mon Sep 17 00:00:00 2001 From: Dong Heng Date: Mon, 14 Nov 2016 09:40:12 +0800 Subject: [PATCH 02/48] components/openssl: sync the code form esp8266 sdk --- components/openssl/include/internal/ssl_dbg.h | 7 ++-- components/openssl/platform/ssl_pm.c | 35 ++++++++++++++++++- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/components/openssl/include/internal/ssl_dbg.h b/components/openssl/include/internal/ssl_dbg.h index 887fe2e82..b4c075463 100644 --- a/components/openssl/include/internal/ssl_dbg.h +++ b/components/openssl/include/internal/ssl_dbg.h @@ -55,16 +55,17 @@ #else #ifdef SSL_PRINT_LOG #undef SSL_PRINT_LOG - #define SSL_PRINT_LOG(...) #endif + #define SSL_PRINT_LOG(...) + #ifdef SSL_ERROR_LOG #undef SSL_ERROR_LOG - #define SSL_ERROR_LOG(...) #endif + #define SSL_ERROR_LOG(...) #ifdef SSL_LOCAL_LOG #undef SSL_LOCAL_LOG - #define SSL_LOCAL_LOG(...) #endif + #define SSL_LOCAL_LOG(...) #endif #if SSL_DEBUG_LOCATION_ENABLE diff --git a/components/openssl/platform/ssl_pm.c b/components/openssl/platform/ssl_pm.c index 92e72bfdb..091402cda 100644 --- a/components/openssl/platform/ssl_pm.c +++ b/components/openssl/platform/ssl_pm.c @@ -215,6 +215,31 @@ static int ssl_pm_reload_crt(SSL *ssl) return 0; } +/* + * Perform the mbedtls SSL handshake instead of mbedtls_ssl_handshake. + * We can add debug here. + */ +LOCAL int mbedtls_handshake( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + + if (ssl == NULL || ssl->conf == NULL) + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + + while (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) + { + ret = mbedtls_ssl_handshake_step(ssl); + + SSL_DEBUG(1, "ssl ret %d state %d heap %d\n", + ret, ssl->state, system_get_free_heap_size()); + + if (ret != 0) + break; + } + + return ret; +} + int ssl_pm_handshake(SSL *ssl) { int ret, mbed_ret; @@ -224,13 +249,19 @@ int ssl_pm_handshake(SSL *ssl) if (mbed_ret) return 0; + SSL_DEBUG(1, "ssl_speed_up_enter "); ssl_speed_up_enter(); - while((mbed_ret = mbedtls_ssl_handshake(&ssl_pm->ssl)) != 0) { + SSL_DEBUG(1, "OK\n"); + + while((mbed_ret = mbedtls_handshake(&ssl_pm->ssl)) != 0) { if (mbed_ret != MBEDTLS_ERR_SSL_WANT_READ && mbed_ret != MBEDTLS_ERR_SSL_WANT_WRITE) { break; } } + + SSL_DEBUG(1, "ssl_speed_up_exit "); ssl_speed_up_exit(); + SSL_DEBUG(1, "OK\n"); if (!mbed_ret) { struct x509_pm *x509_pm = (struct x509_pm *)ssl->session->peer->x509_pm; @@ -492,6 +523,7 @@ int x509_pm_load(X509 *x, const unsigned char *buffer, int len) return 0; failed2: + mbedtls_x509_crt_free(x509_pm->x509_crt); ssl_mem_free(x509_pm->x509_crt); x509_pm->x509_crt = NULL; failed1: @@ -567,6 +599,7 @@ int pkey_pm_load(EVP_PKEY *pk, const unsigned char *buffer, int len) return 0; failed2: + mbedtls_pk_free(pkey_pm->pkey); ssl_mem_free(pkey_pm->pkey); pkey_pm->pkey = NULL; failed1: From 045a53a7e5aeb1263ee24671473e3a705d9df6e3 Mon Sep 17 00:00:00 2001 From: Jeroen Domburg Date: Mon, 14 Nov 2016 10:20:49 +0800 Subject: [PATCH 03/48] Fix wdt idle hook --- components/esp32/task_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esp32/task_wdt.c b/components/esp32/task_wdt.c index f8cfdef26..549b7f58b 100644 --- a/components/esp32/task_wdt.c +++ b/components/esp32/task_wdt.c @@ -145,7 +145,7 @@ void esp_task_wdt_delete() { #if CONFIG_TASK_WDT_CHECK_IDLE_TASK static bool idle_hook(void) { #if !CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1 - if (xPortGetCoreID()!=0) return; + if (xPortGetCoreID()!=0) return true; #endif esp_task_wdt_feed(); return true; From 794b4ff578c6c79416d616659250299d6eab087b Mon Sep 17 00:00:00 2001 From: Dong Heng Date: Mon, 14 Nov 2016 15:11:22 +0800 Subject: [PATCH 04/48] components/openssl: add client and server demo --- examples/09_openssl/Makefile | 9 + examples/09_openssl/README.md | 21 + examples/09_openssl/main/Kconfig.projbuild | 27 ++ examples/09_openssl/main/component.mk | 10 + examples/09_openssl/main/openssl_demo.c | 430 +++++++++++++++++++++ examples/09_openssl/main/openssl_demo.h | 66 ++++ 6 files changed, 563 insertions(+) create mode 100644 examples/09_openssl/Makefile create mode 100644 examples/09_openssl/README.md create mode 100644 examples/09_openssl/main/Kconfig.projbuild create mode 100644 examples/09_openssl/main/component.mk create mode 100644 examples/09_openssl/main/openssl_demo.c create mode 100644 examples/09_openssl/main/openssl_demo.h diff --git a/examples/09_openssl/Makefile b/examples/09_openssl/Makefile new file mode 100644 index 000000000..8987be554 --- /dev/null +++ b/examples/09_openssl/Makefile @@ -0,0 +1,9 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := openssl + +include $(IDF_PATH)/make/project.mk + diff --git a/examples/09_openssl/README.md b/examples/09_openssl/README.md new file mode 100644 index 000000000..54b013342 --- /dev/null +++ b/examples/09_openssl/README.md @@ -0,0 +1,21 @@ +# Openssl Example + +The Example contains of OpenSSL client and server demo. + +First you should config the project by "menuconfig": + Example Configuration -> + 1. Openssl demo: select your demo (client or server) + 2. WiFi SSID: you own wifi, which you pc is connected to alse. + 3. WiFi Password: wifi password + +If you want to test the OpenSSL client demo: + 1. compile the code and load the firmware + 2. you can see it will download the "www.baidu.com" main page and print the context + +IF you want to test the openSSL client demo: + 1. compile the code and load the firmware + 2. You should input the context of "https://192.168.17.128", the IP of your module may not be 192.168.17.128, you should input your module's IP + 3. You may see that it shows the website is not able to be trusted, but you should select that "go on to visit it" + 4. You should wait for a moment until your see the "OpenSSL server demo!" in your IE page + +See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/09_openssl/main/Kconfig.projbuild b/examples/09_openssl/main/Kconfig.projbuild new file mode 100644 index 000000000..b42529ca1 --- /dev/null +++ b/examples/09_openssl/main/Kconfig.projbuild @@ -0,0 +1,27 @@ +menu "Example Configuration" + +choice OPENSSL_DEMO + prompt "Openssl demo" + default OPENSSL_CLIENT_DEMO + help + Openssl test demo mode, client or server. + +config OPENSSL_CLIENT_DEMO + bool "client demo" +config OPENSSL_SERVER_DEMO + bool "server demon" +endchoice + +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. + +endmenu \ No newline at end of file diff --git a/examples/09_openssl/main/component.mk b/examples/09_openssl/main/component.mk new file mode 100644 index 000000000..24356f23e --- /dev/null +++ b/examples/09_openssl/main/component.mk @@ -0,0 +1,10 @@ +# +# Main Makefile. This is basically the same as a component makefile. +# +# This Makefile should, at the very least, just include $(SDK_PATH)/make/component_common.mk. By default, +# this will take the sources in the src/ directory, compile them and link them into +# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, +# please read the ESP-IDF documents if you need to do this. +# + +include $(IDF_PATH)/make/component_common.mk diff --git a/examples/09_openssl/main/openssl_demo.c b/examples/09_openssl/main/openssl_demo.c new file mode 100644 index 000000000..d541b2625 --- /dev/null +++ b/examples/09_openssl/main/openssl_demo.c @@ -0,0 +1,430 @@ +#include +#include + +#include "openssl_demo.h" +#include "openssl/ssl.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" + +#include "esp_types.h" +#include "esp_system.h" +#include "esp_wifi.h" +#include "esp_event_loop.h" +#include "esp_log.h" + +#include "lwip/sockets.h" +#include "lwip/api.h" + +#include "nvs_flash.h" + + +#define os_printf(fmt, ...) ESP_LOGI("openssl_demo", fmt, ##__VA_ARGS__) + +#define IP_ADDR(ip) ip.u_addr.ip4.addr + +/* The examples use simple WiFi configuration that you can set via + 'make menuconfig'. + + If you'd rather not, just change the below entries to strings with + the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" +*/ +#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID +#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD + +#define OPENSSL_DEMO_THREAD_STACK_WORDS 8192 +#define OPENSSL_DEMO_THREAD_PRORIOTY 6 + +#define OPENSSL_DEMO_FRAGMENT_SIZE 8192 + +#define OPENSSL_DEMO_RECV_BUF_LEN 1024 + +#define OPENSSL_DEMO_LOCAL_TCP_PORT 443 + +#ifdef CONFIG_OPENSSL_CLIENT_DEMO + +#define OPENSSL_DEMO_THREAD_NAME "ssl_client" + +#define OPENSSL_DEMO_TARGET_NAME "www.baidu.com" +#define OPENSSL_DEMO_TARGET_TCP_PORT 443 + +#define OPENSSL_DEMO_REQUEST "{\"path\": \"/v1/ping/\", \"method\": \"GET\"}\r\n" + +LOCAL void openssl_demo_thread(void *p) +{ + int ret; + + SSL_CTX *ctx; + SSL *ssl; + + int socket; + struct sockaddr_in sock_addr; + + ip_addr_t target_ip; + + int recv_bytes = 0; + + LOCAL char send_data[] = OPENSSL_DEMO_REQUEST; + LOCAL int send_bytes = sizeof(send_data); + + LOCAL char recv_buf[OPENSSL_DEMO_RECV_BUF_LEN]; + + os_printf("OpenSSL demo thread start\n"); + + do { + ret = netconn_gethostbyname(OPENSSL_DEMO_TARGET_NAME, &target_ip); + } while(ret); + os_printf("get target IP is %d.%d.%d.%d\n", + (unsigned char)((IP_ADDR(target_ip) & 0x000000ff) >> 0), + (unsigned char)((IP_ADDR(target_ip) & 0x0000ff00) >> 8), + (unsigned char)((IP_ADDR(target_ip) & 0x00ff0000) >> 16), + (unsigned char)((IP_ADDR(target_ip) & 0xff000000) >> 24)); + + os_printf("create SSL context ......"); + ctx = SSL_CTX_new(TLSv1_1_client_method()); + if (!ctx) { + os_printf("failed\n"); + goto failed1; + } + os_printf("OK\n"); + + /** + * The openssl does not support "SSL_CTX_set_default_read_buffer_len" + * at the platform of ESP32 esp_idf now. + * + * So you should not care it now. And We my let it work later. + */ + os_printf("set SSL context read buffer size ......"); + SSL_CTX_set_default_read_buffer_len(ctx, OPENSSL_DEMO_FRAGMENT_SIZE); + ret = 0; + if (ret) { + os_printf("failed, return %d\n", ret); + goto failed2; + } + os_printf("OK\n"); + + os_printf("create socket ......"); + socket = socket(AF_INET, SOCK_STREAM, 0); + if (socket < 0) { + os_printf("failed\n"); + goto failed3; + } + os_printf("OK\n"); + + os_printf("bind socket ......"); + memset(&sock_addr, 0, sizeof(sock_addr)); + sock_addr.sin_family = AF_INET; + sock_addr.sin_addr.s_addr = 0; + sock_addr.sin_port = htons(OPENSSL_DEMO_LOCAL_TCP_PORT); + ret = bind(socket, (struct sockaddr*)&sock_addr, sizeof(sock_addr)); + if (ret) { + os_printf("failed\n"); + goto failed4; + } + os_printf("OK\n"); + + os_printf("socket connect to remote %s ......", OPENSSL_DEMO_TARGET_NAME); + memset(&sock_addr, 0, sizeof(sock_addr)); + sock_addr.sin_family = AF_INET; + sock_addr.sin_addr.s_addr = IP_ADDR(target_ip); + sock_addr.sin_port = htons(OPENSSL_DEMO_TARGET_TCP_PORT); + ret = connect(socket, (struct sockaddr*)&sock_addr, sizeof(sock_addr)); + if (ret) { + os_printf("failed\n"); + goto failed5; + } + os_printf("OK\n"); + + os_printf("create SSL ......"); + ssl = SSL_new(ctx); + if (!ssl) { + os_printf("failed\n"); + goto failed6; + } + os_printf("OK\n"); + + SSL_set_fd(ssl, socket); + + os_printf("SSL connected to %s port %d ......", + OPENSSL_DEMO_TARGET_NAME, OPENSSL_DEMO_TARGET_TCP_PORT); + ret = SSL_connect(ssl); + if (!ret) { + os_printf("failed, return [-0x%x]\n", -ret); + goto failed7; + } + os_printf("OK\n"); + + os_printf("send https request to %s port %d ......", + OPENSSL_DEMO_TARGET_NAME, OPENSSL_DEMO_TARGET_TCP_PORT); + ret = SSL_write(ssl, send_data, send_bytes); + if (ret <= 0) { + os_printf("failed\n"); + goto failed8; + } + os_printf("OK\n\n"); + + do { + ret = SSL_read(ssl, recv_buf, OPENSSL_DEMO_RECV_BUF_LEN - 1); + if (ret <= 0) { + break; + } + recv_bytes += ret; + os_printf("%s", recv_buf); + } while (1); + + os_printf("\r\ntotaly read %d bytes data from %s ......\n", recv_bytes, OPENSSL_DEMO_TARGET_NAME); + +failed8: + SSL_shutdown(ssl); +failed7: + SSL_free(ssl); + ssl = NULL; +failed6: +failed5: +failed4: + close(socket); + socket = -1; +failed3: +failed2: + SSL_CTX_free(ctx); + ctx = NULL; +failed1: + vTaskDelete(NULL); + + os_printf("task exit\n"); + + return ; +} + +#elif defined(CONFIG_OPENSSL_SERVER_DEMO) + +#define OPENSSL_DEMO_THREAD_NAME "openssl_server" + +#define OPENSSL_DEMO_CLIENT_REQUEST "{\"path\": \"/v1/ping/\", \"method\": \"GET\"}\r\n" + +#define OPENSSL_DEMO_SERVER_ACK "HTTP/1.1 200 OK\r\n" \ + "Content-Type: text/html\r\n" \ + "Content-Length: 98\r\n" \ + "\r\n" \ + "\r\n" \ + "openSSL demo\r\n" \ + "OpenSSL server demo!\r\n" \ + "\r\n" \ + "\r\n" + +LOCAL void openssl_demo_thread(void *p) +{ + int ret; + + SSL_CTX *ctx; + SSL *ssl; + + int socket, new_socket; + socklen_t addr_len; + struct sockaddr_in sock_addr; + + LOCAL char send_data[] = OPENSSL_DEMO_SERVER_ACK; + LOCAL int send_bytes = sizeof(send_data); + + LOCAL char recv_buf[OPENSSL_DEMO_RECV_BUF_LEN]; + + os_printf("server SSL context create ......"); + ctx = SSL_CTX_new(SSLv3_server_method()); + if (!ctx) { + os_printf("failed\n"); + goto failed1; + } + os_printf("OK\n"); + + /** + * The openssl does not support "SSL_CTX_set_default_read_buffer_len" + * at the platform of ESP32 esp_idf now. + * + * So you should not care it now. And We my let it work later. + */ + os_printf("server SSL context set fragment ......"); + SSL_CTX_set_default_read_buffer_len(ctx, OPENSSL_DEMO_FRAGMENT_SIZE); + ret = 0; + if (ret) { + os_printf("failed, return %d\n", ret); + goto failed2; + } + os_printf("OK\n"); + + os_printf("server SSL context set own certification......"); + ret = SSL_CTX_use_certificate_ASN1(ctx, cert_bytes, cert_ctx); + if (!ret) { + os_printf("failed, return %d\n", ret); + goto failed2; + } + os_printf("OK\n"); + + os_printf("server SSL context set private key......"); + ret = SSL_CTX_use_PrivateKey_ASN1(0, ctx, key_ctx, key_bytes); + if (!ret) { + os_printf("failed, return %d\n", ret); + goto failed2; + } + os_printf("OK\n"); + + os_printf("server create socket ......"); + socket = socket(AF_INET, SOCK_STREAM, 0); + if (socket < 0) { + os_printf("failed\n"); + goto failed2; + } + os_printf("OK\n"); + + os_printf("server socket bind ......"); + memset(&sock_addr, 0, sizeof(sock_addr)); + sock_addr.sin_family = AF_INET; + sock_addr.sin_addr.s_addr = 0; + sock_addr.sin_port = htons(OPENSSL_DEMO_LOCAL_TCP_PORT); + ret = bind(socket, (struct sockaddr*)&sock_addr, sizeof(sock_addr)); + if (ret) { + os_printf("failed\n"); + goto failed3; + } + os_printf("OK\n"); + + os_printf("server socket listen ......"); + ret = listen(socket, 32); + if (ret) { + os_printf("failed\n"); + goto failed3; + } + os_printf("OK\n"); + +reconnect: + os_printf("server SSL create ......"); + ssl = SSL_new(ctx); + if (!ssl) { + os_printf("failed\n"); + goto failed3; + } + os_printf("OK\n"); + + os_printf("server socket accept client ......"); + new_socket = accept(socket, (struct sockaddr *)&sock_addr, &addr_len); + if (new_socket < 0) { + os_printf("failed, return [-0x%x]\n", -new_socket); + goto failed4; + } + os_printf("OK\n"); + + SSL_set_fd(ssl, new_socket); + + os_printf("server SSL accept client ......"); + ret = SSL_accept(ssl); + if (!ret) { + os_printf("failed\n"); + goto failed5; + } + os_printf("OK\n"); + + os_printf("server SSL read message ......"); + do { + memset(recv_buf, 0, OPENSSL_DEMO_RECV_BUF_LEN); + ret = SSL_read(ssl, recv_buf, OPENSSL_DEMO_RECV_BUF_LEN - 1); + if (ret <= 0) { + break; + } + if (strstr(recv_buf, "GET / HTTP/1.1")) { + SSL_write(ssl, send_data, send_bytes); + break; + } + } while (1); + + os_printf("result %d\n", ret); + + SSL_shutdown(ssl); +failed5: + close(new_socket); + new_socket = -1; +failed4: + SSL_free(ssl); + ssl = NULL; + goto reconnect; +failed3: + close(socket); + socket = -1; +failed2: + SSL_CTX_free(ctx); + ctx = NULL; +failed1: + vTaskDelete(NULL); + + return ; +} + +#else + #error "you must choose the right demo type" +#endif + +LOCAL void demo_init(void) +{ + int ret = pdFALSE; + +#if defined(CONFIG_OPENSSL_CLIENT_DEMO) || defined(CONFIG_OPENSSL_SERVER_DEMO) + xTaskHandle openssl_handle; + + ret = xTaskCreate(openssl_demo_thread, + OPENSSL_DEMO_THREAD_NAME, + OPENSSL_DEMO_THREAD_STACK_WORDS, + NULL, + OPENSSL_DEMO_THREAD_PRORIOTY, + &openssl_handle); +#endif + + if (ret != pdPASS) { + os_printf("create thread %s failed\n", OPENSSL_DEMO_THREAD_NAME); + return ; + } +} + +LOCAL esp_err_t wifi_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: + demo_init(); + break; + case SYSTEM_EVENT_STA_DISCONNECTED: + /* This is a workaround as ESP32 WiFi libs don't currently + auto-reassociate. */ + esp_wifi_connect(); + break; + default: + break; + } + return ESP_OK; +} + +LOCAL void wifi_conn_init(void) +{ + tcpip_adapter_init(); + ESP_ERROR_CHECK( esp_event_loop_init(wifi_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_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); + ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) ); + os_printf("start the WIFI SSID:[%s] password:[%s]\n", EXAMPLE_WIFI_SSID, EXAMPLE_WIFI_PASS); + ESP_ERROR_CHECK( esp_wifi_start() ); +} + +void app_main(void) +{ + nvs_flash_init(); + wifi_conn_init(); +} + diff --git a/examples/09_openssl/main/openssl_demo.h b/examples/09_openssl/main/openssl_demo.h new file mode 100644 index 000000000..89cd264b4 --- /dev/null +++ b/examples/09_openssl/main/openssl_demo.h @@ -0,0 +1,66 @@ +#ifndef _OPENSSL_DEMO_H_ +#define _OPENSSL_DEMO_H_ + +const static unsigned char key_ctx[] = + "-----BEGIN PRIVATE KEY-----\r\n" + "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDQyyF0WBb2XbkL\r\n" + "wYFgyoPOanYvbb/qwbAkGf1zSPX35xruZmjszjcverMoyF6x2MBxD3gP1ijBR0Rr\r\n" + "0J0CfluABDLkzqpF5smOVX9k8W7ePClm91NhcASuF+CaZOe6B+6vOYShYjhe6eFG\r\n" + "AGk8SP4zSrG2XHNKXlR3w8duK9fyOOZLWRjL3T6+++HEaly1p4ujKZhrm5wHzywA\r\n" + "DvjDdvIWBCW1Z+8j7Q9qUITjlsDWHjrXCpyEfclE1WQxTP/W7rBLxNVxTfwbrdcD\r\n" + "HNrKTOXtN+oDmCruvmBnTkz9x4Te6wJuvtFd0fBtW1kWsMzomvOlKmvHo0gmpqfh\r\n" + "CwEPoKCNAgMBAAECggEBAIVr+LHXBL1kQLZhbiKC5t1FrMY8FLKYGM3JCevciMlk\r\n" + "lhIXwR7p29vsRYZfHBv7zWWyI9/C04JG31MiGOMaCbBxfnA2HBrVEqFwwxqnKVi8\r\n" + "CxzwGQkfwu3Y9j7TEj0PipfQYo+aKzmDrN/FrXnHjyEJryxAQbAZPVLW+Z7OR41R\r\n" + "ZOwtZLeVqmbeARGpu2Xd9SKAhbjdLSz96IdUcNrwbP/lzUgrKaiUioBMVFfIG5ce\r\n" + "4Mm2seCwaWxI8k24q0keSjsjV+5IxatVUNtJ9vYv6Tzo+3oqGvPeUBO7w9xhbLKf\r\n" + "jw1uEykcs0wcftWb1iB7r78bMPZ/KYhnSFsjT+vnIOECgYEA9LM5p63sn6OWrULd\r\n" + "doBBLaIw1ZK9rDUFLLRwv0e6+7tuuB08ok6D7PSfOpx0bb10lIx7epOE8ogGSmLS\r\n" + "w0rMbmcKAlTLAJ/0nX1ierZkb+Ay21F398tKL3igEfnaB9CzuOHF8XhbsTqeGFDJ\r\n" + "HFBMXxTbo4kfkUmZNYxwTombzkkCgYEA2m9teqjEOVZItqghOicWZ68JhWxBJFme\r\n" + "oSfzJKLd8atfUOnBLqAhPzvg1PvdIxjLWBqy28tEJf+jdSQCNe9BmhlptOwbFrJy\r\n" + "IyCXj6QTApSKTxyzIjMvzQkv1m8CxeCq5T64hvJ2++i7dlhumh21c7oL8aLeTnoe\r\n" + "AG1dBLJ9UCUCgYAhSlDJsyvB/Ct/nt0qRgCYCLzEEZakWwI9Nr8wBr41iSZi/fdF\r\n" + "zZC9J/qRqr9cPq4hl4sk/fTUWhUhAZjS4NY3HuWJs6d6ikhpNKm1MCMx5TqGA+ti\r\n" + "VtHc63g7edZjwczxliWr2EgBMIxZmoQByhrZxKis8vbMeUrSsiyFQstjoQKBgD3k\r\n" + "2Paqn39Hra7kERYzQSv78wy1UfgE1OgBM+orpAv4bTe2JKEbipAqXVi8TTrGqce7\r\n" + "OPcCr7q8pwpoO6AgvUv263byd/KEecbuU0PGUASpJk+oaDHGo0LL2Zw/NF/xezsd\r\n" + "/JdwWLqkhYnRIPXWeTXjf8LmTWubOqkQVA0irlNpAoGAJ+9N/NF3XAW0BroiVYLZ\r\n" + "p0Btcgt+b4LWrBlm0XqHhzKUlqhfibAr3OtUkFjo/509ncYPiuOzVSNosyjXFJ86\r\n" + "2kQ88fB3eeLnBAcbBXQKiOBPU2y6bCCfgdo+JEOK/cxVslaxMAyKSnFi9gdgzScd\r\n" + "k+hOlkflXQVkic3W358kFto=\r\n" + "-----END PRIVATE KEY-----\r\n" + ; +static int key_bytes = sizeof(key_ctx); + +const static unsigned char cert_ctx[] = + "-----BEGIN CERTIFICATE-----\r\n" + "MIID7jCCAtYCAQEwDQYJKoZIhvcNAQELBQAwgbwxCzAJBgNVBAYTAkNOMRAwDgYD\r\n" + "VQQIDAdKaWFuZ3N1MQ0wCwYDVQQHDARXdXhpMSYwJAYDVQQKDB1Fc3ByZXNzaWYg\r\n" + "Um9vdCBSU0EyMDQ4IHNoYTI1NjEcMBoGA1UECwwTUm9vdCBSU0EyMDQ4IHNoYTI1\r\n" + "NjEfMB0GA1UEAwwWcm9vdGNlcnQuZXNwcmVzc2lmLmNvbTElMCMGCSqGSIb3DQEJ\r\n" + "ARYWcm9vdGNlcnRAZXNwcmVzc2lmLmNvbTAeFw0xNjA2MjgwMjMxMjlaFw0yNjA2\r\n" + "MjYwMjMxMjlaMIG8MQswCQYDVQQGEwJDTjEQMA4GA1UECAwHSmlhbmdzdTENMAsG\r\n" + "A1UEBwwEV3V4aTEmMCQGA1UECgwdRXNwcmVzc2lmIFJvb3QgUlNBMjA0OCBzaGEy\r\n" + "NTYxHDAaBgNVBAsME1Jvb3QgUlNBMjA0OCBzaGEyNTYxHzAdBgNVBAMMFnJvb3Rj\r\n" + "ZXJ0LmVzcHJlc3NpZi5jb20xJTAjBgkqhkiG9w0BCQEWFnJvb3RjZXJ0QGVzcHJl\r\n" + "c3NpZi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDQyyF0WBb2\r\n" + "XbkLwYFgyoPOanYvbb/qwbAkGf1zSPX35xruZmjszjcverMoyF6x2MBxD3gP1ijB\r\n" + "R0Rr0J0CfluABDLkzqpF5smOVX9k8W7ePClm91NhcASuF+CaZOe6B+6vOYShYjhe\r\n" + "6eFGAGk8SP4zSrG2XHNKXlR3w8duK9fyOOZLWRjL3T6+++HEaly1p4ujKZhrm5wH\r\n" + "zywADvjDdvIWBCW1Z+8j7Q9qUITjlsDWHjrXCpyEfclE1WQxTP/W7rBLxNVxTfwb\r\n" + "rdcDHNrKTOXtN+oDmCruvmBnTkz9x4Te6wJuvtFd0fBtW1kWsMzomvOlKmvHo0gm\r\n" + "pqfhCwEPoKCNAgMBAAEwDQYJKoZIhvcNAQELBQADggEBABTYZLiFHq51lqaa0nHI\r\n" + "aDMAb29DfO93fqp+oHZYO4xKyEeLr8EhD39GjnQmhz710wO0TBCYV7nD+xnJ1h5F\r\n" + "IbQUAQZO9NIy3ns4mYVRUWjnWYAo+evGeKgRrxvh7sjNLPBPzs9tg/u7XjBp/nor\r\n" + "8JnnFFT0wXPyi/qg8J3QutqJvWRQGRRx2AP93F44+Zcj7ReFMVSmOXyzT4aNJL0+\r\n" + "Ls+baKwA4pnyVRoAaKbs/JYDgd0/DunuktVKuhyvK/qOGjJSRLPhdrXbvSAegpiM\r\n" + "4xIm6ZWKtTv8VvkGgXUVQ7RpruP6nV6506gDcUgecbEq7H2VDhEzUYcMmGCUQZlG\r\n" + "sJ8=\r\n" + "-----END CERTIFICATE-----\r\n" + ; +static int cert_bytes = sizeof(cert_ctx); + + + +#endif From 64a2f0ee0bf31f7921069f601515f9bc638ccfff Mon Sep 17 00:00:00 2001 From: Jeroen Domburg Date: Tue, 15 Nov 2016 10:29:52 +0800 Subject: [PATCH 05/48] Amend gpio driver to work around SoC bug with some pullups/pulldowns in the GPIO peripheral; mark existing function that does not always work as deprecated --- components/driver/gpio.c | 92 ++++++++++++++++++++--- components/driver/include/driver/gpio.h | 84 +++++++++++++++++++-- components/esp32/gdbstub.c | 3 +- components/esp32/include/soc/io_mux_reg.h | 39 +++++++++- 4 files changed, 194 insertions(+), 24 deletions(-) diff --git a/components/driver/gpio.c b/components/driver/gpio.c index b445d3df0..ddbcb352c 100644 --- a/components/driver/gpio.c +++ b/components/driver/gpio.c @@ -69,6 +69,74 @@ const uint32_t GPIO_PIN_MUX_REG[GPIO_PIN_COUNT] = { GPIO_PIN_REG_39 }; +const gpio_pu_pd_desc_t gpio_pu_pd_desc[GPIO_PIN_COUNT]={ + {RTC_IO_TOUCH_PAD1_REG, RTC_IO_TOUCH_PAD1_RUE_M, RTC_IO_TOUCH_PAD1_RDE_M}, + {PERIPHS_IO_MUX_U0TXD_U, FUN_PU, FUN_PD}, + {RTC_IO_TOUCH_PAD2_REG, RTC_IO_TOUCH_PAD2_RUE_M, RTC_IO_TOUCH_PAD2_RDE_M}, + {PERIPHS_IO_MUX_U0RXD_U, FUN_PU, FUN_PD}, + {RTC_IO_TOUCH_PAD0_REG, RTC_IO_TOUCH_PAD0_RUE_M, RTC_IO_TOUCH_PAD0_RDE_M}, + {PERIPHS_IO_MUX_GPIO5_U, FUN_PU, FUN_PD}, + {PERIPHS_IO_MUX_SD_CLK_U, FUN_PU, FUN_PD}, + {PERIPHS_IO_MUX_SD_DATA0_U, FUN_PU, FUN_PD}, + {PERIPHS_IO_MUX_SD_DATA1_U, FUN_PU, FUN_PD}, + {PERIPHS_IO_MUX_SD_DATA2_U, FUN_PU, FUN_PD}, + {PERIPHS_IO_MUX_SD_DATA3_U, FUN_PU, FUN_PD}, + {PERIPHS_IO_MUX_SD_CMD_U, FUN_PU, FUN_PD}, + {RTC_IO_TOUCH_PAD5_REG, RTC_IO_TOUCH_PAD5_RUE_M, RTC_IO_TOUCH_PAD5_RDE_M}, + {RTC_IO_TOUCH_PAD4_REG, RTC_IO_TOUCH_PAD4_RUE_M, RTC_IO_TOUCH_PAD4_RDE_M}, + {RTC_IO_TOUCH_PAD6_REG, RTC_IO_TOUCH_PAD6_RUE_M, RTC_IO_TOUCH_PAD6_RDE_M}, + {RTC_IO_TOUCH_PAD3_REG, RTC_IO_TOUCH_PAD3_RUE_M, RTC_IO_TOUCH_PAD3_RDE_M}, + {PERIPHS_IO_MUX_GPIO16_U, FUN_PU, FUN_PD}, + {PERIPHS_IO_MUX_GPIO17_U, FUN_PU, FUN_PD}, + {PERIPHS_IO_MUX_GPIO18_U, FUN_PU, FUN_PD}, + {PERIPHS_IO_MUX_GPIO19_U, FUN_PU, FUN_PD}, + {0,0,0}, + {PERIPHS_IO_MUX_GPIO21_U, FUN_PU, FUN_PD}, + {PERIPHS_IO_MUX_GPIO22_U, FUN_PU, FUN_PD}, + {PERIPHS_IO_MUX_GPIO23_U, FUN_PU, FUN_PD}, + {0,0,0}, + {RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_RUE_M, RTC_IO_PDAC1_RDE_M}, + {RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_RUE_M, RTC_IO_PDAC2_RDE_M}, + {RTC_IO_TOUCH_PAD7_REG, RTC_IO_TOUCH_PAD7_RUE_M, RTC_IO_TOUCH_PAD7_RDE_M}, + {0,0,0}, + {0,0,0}, + {0,0,0}, + {0,0,0}, + {RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32P_RUE_M, RTC_IO_X32P_RDE_M}, + {RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32N_RUE_M, RTC_IO_X32N_RDE_M}, + {PERIPHS_IO_MUX_GPIO34_U, FUN_PU, FUN_PD}, + {PERIPHS_IO_MUX_GPIO35_U, FUN_PU, FUN_PD}, + {PERIPHS_IO_MUX_GPIO36_U, FUN_PU, FUN_PD}, + {PERIPHS_IO_MUX_GPIO37_U, FUN_PU, FUN_PD}, + {PERIPHS_IO_MUX_GPIO38_U, FUN_PU, FUN_PD}, + {PERIPHS_IO_MUX_GPIO39_U, FUN_PU, FUN_PD} +}; + + +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); + REG_SET_BIT(gpio_pu_pd_desc[gpio_num].reg, gpio_pu_pd_desc[gpio_num].pu); + return ESP_OK; +} + +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); + REG_CLR_BIT(gpio_pu_pd_desc[gpio_num].reg, gpio_pu_pd_desc[gpio_num].pu); + return ESP_OK; +} + +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); + REG_SET_BIT(gpio_pu_pd_desc[gpio_num].reg, gpio_pu_pd_desc[gpio_num].pd); + return ESP_OK; +} + +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); + REG_CLR_BIT(gpio_pu_pd_desc[gpio_num].reg, gpio_pu_pd_desc[gpio_num].pd); + return ESP_OK; +} + esp_err_t gpio_set_intr_type(gpio_num_t gpio_num, gpio_int_type_t intr_type) { GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG); @@ -152,20 +220,20 @@ esp_err_t gpio_set_pull_mode(gpio_num_t gpio_num, gpio_pull_mode_t pull) esp_err_t ret = ESP_OK; switch(pull) { case GPIO_PULLUP_ONLY: - PIN_PULLUP_EN(GPIO_PIN_MUX_REG[gpio_num]); - PIN_PULLDWN_DIS(GPIO_PIN_MUX_REG[gpio_num]); + REG_SET_BIT(gpio_pu_pd_desc[gpio_num].reg, gpio_pu_pd_desc[gpio_num].pu); + REG_CLR_BIT(gpio_pu_pd_desc[gpio_num].reg, gpio_pu_pd_desc[gpio_num].pd); break; case GPIO_PULLDOWN_ONLY: - PIN_PULLUP_DIS(GPIO_PIN_MUX_REG[gpio_num]); - PIN_PULLDWN_EN(GPIO_PIN_MUX_REG[gpio_num]); + REG_CLR_BIT(gpio_pu_pd_desc[gpio_num].reg, gpio_pu_pd_desc[gpio_num].pu); + REG_SET_BIT(gpio_pu_pd_desc[gpio_num].reg, gpio_pu_pd_desc[gpio_num].pd); break; case GPIO_PULLUP_PULLDOWN: - PIN_PULLUP_EN(GPIO_PIN_MUX_REG[gpio_num]); - PIN_PULLDWN_EN(GPIO_PIN_MUX_REG[gpio_num]); + REG_SET_BIT(gpio_pu_pd_desc[gpio_num].reg, gpio_pu_pd_desc[gpio_num].pu); + REG_SET_BIT(gpio_pu_pd_desc[gpio_num].reg, gpio_pu_pd_desc[gpio_num].pd); break; case GPIO_FLOATING: - PIN_PULLUP_DIS(GPIO_PIN_MUX_REG[gpio_num]); - PIN_PULLDWN_DIS(GPIO_PIN_MUX_REG[gpio_num]); + REG_CLR_BIT(gpio_pu_pd_desc[gpio_num].reg, gpio_pu_pd_desc[gpio_num].pu); + REG_CLR_BIT(gpio_pu_pd_desc[gpio_num].reg, gpio_pu_pd_desc[gpio_num].pd); break; default: ESP_LOGE(GPIO_TAG, "Unknown pull up/down mode,gpio_num=%u,pull=%u",gpio_num,pull); @@ -253,15 +321,15 @@ esp_err_t gpio_config(gpio_config_t *pGPIOConfig) } if(pGPIOConfig->pull_up_en) { pu_en = 1; - PIN_PULLUP_EN(io_reg); + REG_SET_BIT(gpio_pu_pd_desc[io_num].reg, gpio_pu_pd_desc[io_num].pd); } else { - PIN_PULLUP_DIS(io_reg); + REG_CLR_BIT(gpio_pu_pd_desc[io_num].reg, gpio_pu_pd_desc[io_num].pd); } if(pGPIOConfig->pull_down_en) { pd_en = 1; - PIN_PULLDWN_EN(io_reg); + REG_SET_BIT(gpio_pu_pd_desc[io_num].reg, gpio_pu_pd_desc[io_num].pd); } else { - PIN_PULLDWN_DIS(io_reg); + REG_CLR_BIT(gpio_pu_pd_desc[io_num].reg, gpio_pu_pd_desc[io_num].pd); } ESP_LOGI(GPIO_TAG, "GPIO[%d]| InputEn: %d| OutputEn: %d| OpenDrain: %d| Pullup: %d| Pulldown: %d| Intr:%d ", io_num, input_en, output_en, od_en, pu_en, pd_en, pGPIOConfig->intr_type); gpio_set_intr_type(io_num, pGPIOConfig->intr_type); diff --git a/components/driver/include/driver/gpio.h b/components/driver/include/driver/gpio.h index 73efeaa34..5dad11f2f 100644 --- a/components/driver/include/driver/gpio.h +++ b/components/driver/include/driver/gpio.h @@ -117,6 +117,29 @@ extern const uint32_t GPIO_PIN_MUX_REG[GPIO_PIN_COUNT]; #define GPIO_IS_VALID_GPIO(gpio_num) ((gpio_num < GPIO_PIN_COUNT && GPIO_PIN_MUX_REG[gpio_num] != 0)) //to decide whether it is a valid GPIO number #define GPIO_IS_VALID_OUTPUT_GPIO(gpio_num) ((GPIO_IS_VALID_GPIO(gpio_num)) && (gpio_num < 34)) //to decide whether it can be a valid GPIO number of output mode +typedef struct { + uint32_t reg; /*!< Register to modify to enable or disable pullups or pulldowns */ + uint32_t pu; /*!< Bit to set or clear in the above register to enable or disable the pullup, respectively */ + uint32_t pd; /*!< Bit to set or clear in the above register to enable or disable the pulldown, respectively */ +} gpio_pu_pd_desc_t; + + +/** + * Per-GPIO pullup/pulldown information + * On the ESP32, some GPIOs need their pullups and pulldowns enabled and disabled in the RTC + * peripheral instead of in the GPIO peripheral. This array documents for every GPIO what bit + * to set or clear. + * + * This array is non-static, so if you need a very quick way of toggling the pull-up/downs, you can just + * do e.g. REG_SET_BIT(gpio_pu_pd_desc[gpio_num].reg, gpio_pu_pd_desc[gpio_num].pu); inline. + * + * ToDo: Functions using the contents of this array will do a read/modify/write on GPIO as well as RTC + * registers. We may need to look into muxes/locks for other code that accesses these RTC registers when we + * write drivers for the RTC stuff. + */ +extern const gpio_pu_pd_desc_t gpio_pu_pd_desc[GPIO_PIN_COUNT]; + + typedef enum { GPIO_NUM_0 = 0, /*!< GPIO0, input and output */ GPIO_NUM_1 = 1, /*!< GPIO1, input and output */ @@ -220,7 +243,7 @@ esp_err_t gpio_config(gpio_config_t *pGPIOConfig); /** * @brief GPIO set interrupt trigger type * - * @param gpio_num GPIO number. If you want to set output level of GPIO16, gpio_num should be GPIO_NUM_16 (16); + * @param gpio_num GPIO number. If you want to set the trigger type of e.g. of GPIO16, gpio_num should be GPIO_NUM_16 (16); * @param intr_type Interrupt type, select from gpio_int_type_t * * @return @@ -233,7 +256,7 @@ esp_err_t gpio_set_intr_type(gpio_num_t gpio_num, gpio_int_type_t intr_type); /** * @brief Enable GPIO module interrupt signal * - * @param gpio_num GPIO number. If you want to set output level of GPIO16, gpio_num should be GPIO_NUM_16 (16); + * @param gpio_num GPIO number. If you want to enable an interrupt on e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16); * * @return * - ESP_OK Success @@ -245,7 +268,7 @@ esp_err_t gpio_intr_enable(gpio_num_t gpio_num); /** * @brief Disable GPIO module interrupt signal * - * @param gpio_num GPIO number. If you want to set output level of GPIO16, gpio_num should be GPIO_NUM_16 (16); + * @param gpio_num GPIO number. If you want to disable the interrupt of e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16); * * @return * - ESP_OK success @@ -257,7 +280,7 @@ esp_err_t gpio_intr_disable(gpio_num_t gpio_num); /** * @brief GPIO set output level * - * @param gpio_num GPIO number. If you want to set output level of GPIO16, gpio_num should be GPIO_NUM_16 (16); + * @param gpio_num GPIO number. If you want to set the output level of e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16); * @param level Output level. 0: low ; 1: high * * @return @@ -270,7 +293,7 @@ esp_err_t gpio_set_level(gpio_num_t gpio_num, uint32_t level); /** * @brief GPIO get input level * - * @param gpio_num GPIO number. If you want to get level of pin GPIO16, gpio_num should be GPIO_NUM_16 (16); + * @param gpio_num GPIO number. If you want to get the logic level of e.g. pin GPIO16, gpio_num should be GPIO_NUM_16 (16); * * @return * - 0 the GPIO input level is 0 @@ -284,7 +307,7 @@ int gpio_get_level(gpio_num_t gpio_num); * * Configure GPIO direction,such as output_only,input_only,output_and_input * - * @param gpio_num Configure GPIO pins number, it should be GPIO number. If you want to set direction of GPIO16, gpio_num should be GPIO_NUM_16 (16); + * @param gpio_num Configure GPIO pins number, it should be GPIO number. If you want to set direction of e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16); * @param mode GPIO direction * * @return @@ -299,7 +322,7 @@ esp_err_t gpio_set_direction(gpio_num_t gpio_num, gpio_mode_t mode); * * User this Function,configure GPIO pull mode,such as pull-up,pull-down * - * @param gpio_num GPIO number. If you want to set pull up or down mode for GPIO16,gpio_num should be GPIO_NUM_16 (16); + * @param gpio_num GPIO number. If you want to set pull up or down mode for e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16); * @param pull GPIO pull up/down mode. * * @return @@ -354,6 +377,53 @@ esp_err_t gpio_wakeup_disable(gpio_num_t gpio_num); */ esp_err_t gpio_isr_register(uint32_t gpio_intr_num, void (*fn)(void*), void * arg); + + +/** + * @brief Enable pull-up on GPIO. + * + * @param gpio_num GPIO number + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t gpio_pullup_en(gpio_num_t gpio_num); + +/** + * @brief Disable pull-up on GPIO. + * + * @param gpio_num GPIO number + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t gpio_pullup_dis(gpio_num_t gpio_num); + +/** + * @brief Enable pull-down on GPIO. + * + * @param gpio_num GPIO number + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t gpio_pulldown_en(gpio_num_t gpio_num); + +/** + * @brief Disable pull-down on GPIO. + * + * @param gpio_num GPIO number + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t gpio_pulldown_dis(gpio_num_t gpio_num); + + /** * *************** ATTENTION ********************/ /** diff --git a/components/esp32/gdbstub.c b/components/esp32/gdbstub.c index a43793f83..819944a90 100644 --- a/components/esp32/gdbstub.c +++ b/components/esp32/gdbstub.c @@ -25,6 +25,7 @@ #include "soc/io_mux_reg.h" #include "esp_gdbstub.h" +#include "driver/gpio.h" //Length of buffer used to reserve GDB commands. Has to be at least able to fit the G command, which //implies a minimum size of about 320 bytes. @@ -354,7 +355,7 @@ static int gdbReadCommand() { void esp_gdbstub_panic_handler(XtExcFrame *frame) { dumpHwToRegfile(frame); //Make sure txd/rxd are enabled - PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U); + gpio_pullup_dis(1); PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_U0RXD); PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_U0TXD); diff --git a/components/esp32/include/soc/io_mux_reg.h b/components/esp32/include/soc/io_mux_reg.h index 208a60703..de8fe7ec9 100644 --- a/components/esp32/include/soc/io_mux_reg.h +++ b/components/esp32/include/soc/io_mux_reg.h @@ -34,10 +34,41 @@ #define PIN_INPUT_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,FUN_IE) #define PIN_INPUT_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,FUN_IE) #define PIN_SET_DRV(PIN_NAME, drv) REG_SET_FIELD(PIN_NAME, FUN_DRV, (drv)); -#define PIN_PULLUP_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FUN_PU) -#define PIN_PULLUP_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FUN_PU) -#define PIN_PULLDWN_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FUN_PD) -#define PIN_PULLDWN_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FUN_PD) + +/* + * @attention + * The PIN_PULL[UP|DWN]_[EN|DIS]() functions used to exist as macros in previous SDK versions. + * Unfortunately, however, they do not work for some GPIOs on the ESP32 chip, which needs pullups + * and -downs turned on and off through RTC registers. The functions still exist for compatibility + * with older code, but are marked as deprecated in order to generate a warning. + * Please replace them in this fashion: (make sure to include driver/gpio.h as well) + * PIN_PULLUP_EN(GPIO_PIN_MUX_REG[x]) -> gpio_pullup_en(x) + * PIN_PULLUP_DIS(GPIO_PIN_MUX_REG[x]) -> gpio_pullup_dis(x) + * PIN_PULLDWN_EN(GPIO_PIN_MUX_REG[x]) -> gpio_pulldown_en(x) + * PIN_PULLDWN_DIS(GPIO_PIN_MUX_REG[x]) -> gpio_pulldown_dis(x) + * +*/ +static inline void __attribute__ ((deprecated)) PIN_PULLUP_DIS(uint32_t PIN_NAME) +{ + REG_CLR_BIT(PIN_NAME, FUN_PU); +} + +static inline void __attribute__ ((deprecated)) PIN_PULLUP_EN(uint32_t PIN_NAME) +{ + REG_SET_BIT(PIN_NAME, FUN_PU); +} + +static inline void __attribute__ ((deprecated)) PIN_PULLDWN_DIS(uint32_t PIN_NAME) +{ + REG_CLR_BIT(PIN_NAME, FUN_PD); +} + +static inline void __attribute__ ((deprecated)) PIN_PULLDWN_EN(uint32_t PIN_NAME) +{ + REG_SET_BIT(PIN_NAME, FUN_PD); +} + + #define PIN_FUNC_SELECT(PIN_NAME, FUNC) REG_SET_FIELD(PIN_NAME, MCU_SEL, FUNC) #define PIN_FUNC_GPIO 2 From 858fe9815b37068bef9abd8b99e534876d7e3caa Mon Sep 17 00:00:00 2001 From: Dong Heng Date: Tue, 15 Nov 2016 11:12:58 +0800 Subject: [PATCH 06/48] feature/openssl: add openssl client demo --- examples/09_openssl/README.md | 21 - examples/09_openssl/main/Kconfig.projbuild | 27 -- examples/09_openssl/main/openssl_demo.c | 430 ------------------ examples/09_openssl/main/openssl_demo.h | 66 --- .../Makefile | 2 +- examples/09_openssl_client/README.md | 16 + .../09_openssl_client/main/Kconfig.projbuild | 28 ++ .../main/component.mk | 2 +- .../09_openssl_client/main/openssl_client.c | 235 ++++++++++ .../09_openssl_client/main/openssl_client.h | 34 ++ 10 files changed, 315 insertions(+), 546 deletions(-) delete mode 100644 examples/09_openssl/README.md delete mode 100644 examples/09_openssl/main/Kconfig.projbuild delete mode 100644 examples/09_openssl/main/openssl_demo.c delete mode 100644 examples/09_openssl/main/openssl_demo.h rename examples/{09_openssl => 09_openssl_client}/Makefile (83%) create mode 100644 examples/09_openssl_client/README.md create mode 100644 examples/09_openssl_client/main/Kconfig.projbuild rename examples/{09_openssl => 09_openssl_client}/main/component.mk (86%) create mode 100644 examples/09_openssl_client/main/openssl_client.c create mode 100644 examples/09_openssl_client/main/openssl_client.h diff --git a/examples/09_openssl/README.md b/examples/09_openssl/README.md deleted file mode 100644 index 54b013342..000000000 --- a/examples/09_openssl/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# Openssl Example - -The Example contains of OpenSSL client and server demo. - -First you should config the project by "menuconfig": - Example Configuration -> - 1. Openssl demo: select your demo (client or server) - 2. WiFi SSID: you own wifi, which you pc is connected to alse. - 3. WiFi Password: wifi password - -If you want to test the OpenSSL client demo: - 1. compile the code and load the firmware - 2. you can see it will download the "www.baidu.com" main page and print the context - -IF you want to test the openSSL client demo: - 1. compile the code and load the firmware - 2. You should input the context of "https://192.168.17.128", the IP of your module may not be 192.168.17.128, you should input your module's IP - 3. You may see that it shows the website is not able to be trusted, but you should select that "go on to visit it" - 4. You should wait for a moment until your see the "OpenSSL server demo!" in your IE page - -See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/09_openssl/main/Kconfig.projbuild b/examples/09_openssl/main/Kconfig.projbuild deleted file mode 100644 index b42529ca1..000000000 --- a/examples/09_openssl/main/Kconfig.projbuild +++ /dev/null @@ -1,27 +0,0 @@ -menu "Example Configuration" - -choice OPENSSL_DEMO - prompt "Openssl demo" - default OPENSSL_CLIENT_DEMO - help - Openssl test demo mode, client or server. - -config OPENSSL_CLIENT_DEMO - bool "client demo" -config OPENSSL_SERVER_DEMO - bool "server demon" -endchoice - -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. - -endmenu \ No newline at end of file diff --git a/examples/09_openssl/main/openssl_demo.c b/examples/09_openssl/main/openssl_demo.c deleted file mode 100644 index d541b2625..000000000 --- a/examples/09_openssl/main/openssl_demo.c +++ /dev/null @@ -1,430 +0,0 @@ -#include -#include - -#include "openssl_demo.h" -#include "openssl/ssl.h" - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/event_groups.h" - -#include "esp_types.h" -#include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" -#include "esp_log.h" - -#include "lwip/sockets.h" -#include "lwip/api.h" - -#include "nvs_flash.h" - - -#define os_printf(fmt, ...) ESP_LOGI("openssl_demo", fmt, ##__VA_ARGS__) - -#define IP_ADDR(ip) ip.u_addr.ip4.addr - -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD - -#define OPENSSL_DEMO_THREAD_STACK_WORDS 8192 -#define OPENSSL_DEMO_THREAD_PRORIOTY 6 - -#define OPENSSL_DEMO_FRAGMENT_SIZE 8192 - -#define OPENSSL_DEMO_RECV_BUF_LEN 1024 - -#define OPENSSL_DEMO_LOCAL_TCP_PORT 443 - -#ifdef CONFIG_OPENSSL_CLIENT_DEMO - -#define OPENSSL_DEMO_THREAD_NAME "ssl_client" - -#define OPENSSL_DEMO_TARGET_NAME "www.baidu.com" -#define OPENSSL_DEMO_TARGET_TCP_PORT 443 - -#define OPENSSL_DEMO_REQUEST "{\"path\": \"/v1/ping/\", \"method\": \"GET\"}\r\n" - -LOCAL void openssl_demo_thread(void *p) -{ - int ret; - - SSL_CTX *ctx; - SSL *ssl; - - int socket; - struct sockaddr_in sock_addr; - - ip_addr_t target_ip; - - int recv_bytes = 0; - - LOCAL char send_data[] = OPENSSL_DEMO_REQUEST; - LOCAL int send_bytes = sizeof(send_data); - - LOCAL char recv_buf[OPENSSL_DEMO_RECV_BUF_LEN]; - - os_printf("OpenSSL demo thread start\n"); - - do { - ret = netconn_gethostbyname(OPENSSL_DEMO_TARGET_NAME, &target_ip); - } while(ret); - os_printf("get target IP is %d.%d.%d.%d\n", - (unsigned char)((IP_ADDR(target_ip) & 0x000000ff) >> 0), - (unsigned char)((IP_ADDR(target_ip) & 0x0000ff00) >> 8), - (unsigned char)((IP_ADDR(target_ip) & 0x00ff0000) >> 16), - (unsigned char)((IP_ADDR(target_ip) & 0xff000000) >> 24)); - - os_printf("create SSL context ......"); - ctx = SSL_CTX_new(TLSv1_1_client_method()); - if (!ctx) { - os_printf("failed\n"); - goto failed1; - } - os_printf("OK\n"); - - /** - * The openssl does not support "SSL_CTX_set_default_read_buffer_len" - * at the platform of ESP32 esp_idf now. - * - * So you should not care it now. And We my let it work later. - */ - os_printf("set SSL context read buffer size ......"); - SSL_CTX_set_default_read_buffer_len(ctx, OPENSSL_DEMO_FRAGMENT_SIZE); - ret = 0; - if (ret) { - os_printf("failed, return %d\n", ret); - goto failed2; - } - os_printf("OK\n"); - - os_printf("create socket ......"); - socket = socket(AF_INET, SOCK_STREAM, 0); - if (socket < 0) { - os_printf("failed\n"); - goto failed3; - } - os_printf("OK\n"); - - os_printf("bind socket ......"); - memset(&sock_addr, 0, sizeof(sock_addr)); - sock_addr.sin_family = AF_INET; - sock_addr.sin_addr.s_addr = 0; - sock_addr.sin_port = htons(OPENSSL_DEMO_LOCAL_TCP_PORT); - ret = bind(socket, (struct sockaddr*)&sock_addr, sizeof(sock_addr)); - if (ret) { - os_printf("failed\n"); - goto failed4; - } - os_printf("OK\n"); - - os_printf("socket connect to remote %s ......", OPENSSL_DEMO_TARGET_NAME); - memset(&sock_addr, 0, sizeof(sock_addr)); - sock_addr.sin_family = AF_INET; - sock_addr.sin_addr.s_addr = IP_ADDR(target_ip); - sock_addr.sin_port = htons(OPENSSL_DEMO_TARGET_TCP_PORT); - ret = connect(socket, (struct sockaddr*)&sock_addr, sizeof(sock_addr)); - if (ret) { - os_printf("failed\n"); - goto failed5; - } - os_printf("OK\n"); - - os_printf("create SSL ......"); - ssl = SSL_new(ctx); - if (!ssl) { - os_printf("failed\n"); - goto failed6; - } - os_printf("OK\n"); - - SSL_set_fd(ssl, socket); - - os_printf("SSL connected to %s port %d ......", - OPENSSL_DEMO_TARGET_NAME, OPENSSL_DEMO_TARGET_TCP_PORT); - ret = SSL_connect(ssl); - if (!ret) { - os_printf("failed, return [-0x%x]\n", -ret); - goto failed7; - } - os_printf("OK\n"); - - os_printf("send https request to %s port %d ......", - OPENSSL_DEMO_TARGET_NAME, OPENSSL_DEMO_TARGET_TCP_PORT); - ret = SSL_write(ssl, send_data, send_bytes); - if (ret <= 0) { - os_printf("failed\n"); - goto failed8; - } - os_printf("OK\n\n"); - - do { - ret = SSL_read(ssl, recv_buf, OPENSSL_DEMO_RECV_BUF_LEN - 1); - if (ret <= 0) { - break; - } - recv_bytes += ret; - os_printf("%s", recv_buf); - } while (1); - - os_printf("\r\ntotaly read %d bytes data from %s ......\n", recv_bytes, OPENSSL_DEMO_TARGET_NAME); - -failed8: - SSL_shutdown(ssl); -failed7: - SSL_free(ssl); - ssl = NULL; -failed6: -failed5: -failed4: - close(socket); - socket = -1; -failed3: -failed2: - SSL_CTX_free(ctx); - ctx = NULL; -failed1: - vTaskDelete(NULL); - - os_printf("task exit\n"); - - return ; -} - -#elif defined(CONFIG_OPENSSL_SERVER_DEMO) - -#define OPENSSL_DEMO_THREAD_NAME "openssl_server" - -#define OPENSSL_DEMO_CLIENT_REQUEST "{\"path\": \"/v1/ping/\", \"method\": \"GET\"}\r\n" - -#define OPENSSL_DEMO_SERVER_ACK "HTTP/1.1 200 OK\r\n" \ - "Content-Type: text/html\r\n" \ - "Content-Length: 98\r\n" \ - "\r\n" \ - "\r\n" \ - "openSSL demo\r\n" \ - "OpenSSL server demo!\r\n" \ - "\r\n" \ - "\r\n" - -LOCAL void openssl_demo_thread(void *p) -{ - int ret; - - SSL_CTX *ctx; - SSL *ssl; - - int socket, new_socket; - socklen_t addr_len; - struct sockaddr_in sock_addr; - - LOCAL char send_data[] = OPENSSL_DEMO_SERVER_ACK; - LOCAL int send_bytes = sizeof(send_data); - - LOCAL char recv_buf[OPENSSL_DEMO_RECV_BUF_LEN]; - - os_printf("server SSL context create ......"); - ctx = SSL_CTX_new(SSLv3_server_method()); - if (!ctx) { - os_printf("failed\n"); - goto failed1; - } - os_printf("OK\n"); - - /** - * The openssl does not support "SSL_CTX_set_default_read_buffer_len" - * at the platform of ESP32 esp_idf now. - * - * So you should not care it now. And We my let it work later. - */ - os_printf("server SSL context set fragment ......"); - SSL_CTX_set_default_read_buffer_len(ctx, OPENSSL_DEMO_FRAGMENT_SIZE); - ret = 0; - if (ret) { - os_printf("failed, return %d\n", ret); - goto failed2; - } - os_printf("OK\n"); - - os_printf("server SSL context set own certification......"); - ret = SSL_CTX_use_certificate_ASN1(ctx, cert_bytes, cert_ctx); - if (!ret) { - os_printf("failed, return %d\n", ret); - goto failed2; - } - os_printf("OK\n"); - - os_printf("server SSL context set private key......"); - ret = SSL_CTX_use_PrivateKey_ASN1(0, ctx, key_ctx, key_bytes); - if (!ret) { - os_printf("failed, return %d\n", ret); - goto failed2; - } - os_printf("OK\n"); - - os_printf("server create socket ......"); - socket = socket(AF_INET, SOCK_STREAM, 0); - if (socket < 0) { - os_printf("failed\n"); - goto failed2; - } - os_printf("OK\n"); - - os_printf("server socket bind ......"); - memset(&sock_addr, 0, sizeof(sock_addr)); - sock_addr.sin_family = AF_INET; - sock_addr.sin_addr.s_addr = 0; - sock_addr.sin_port = htons(OPENSSL_DEMO_LOCAL_TCP_PORT); - ret = bind(socket, (struct sockaddr*)&sock_addr, sizeof(sock_addr)); - if (ret) { - os_printf("failed\n"); - goto failed3; - } - os_printf("OK\n"); - - os_printf("server socket listen ......"); - ret = listen(socket, 32); - if (ret) { - os_printf("failed\n"); - goto failed3; - } - os_printf("OK\n"); - -reconnect: - os_printf("server SSL create ......"); - ssl = SSL_new(ctx); - if (!ssl) { - os_printf("failed\n"); - goto failed3; - } - os_printf("OK\n"); - - os_printf("server socket accept client ......"); - new_socket = accept(socket, (struct sockaddr *)&sock_addr, &addr_len); - if (new_socket < 0) { - os_printf("failed, return [-0x%x]\n", -new_socket); - goto failed4; - } - os_printf("OK\n"); - - SSL_set_fd(ssl, new_socket); - - os_printf("server SSL accept client ......"); - ret = SSL_accept(ssl); - if (!ret) { - os_printf("failed\n"); - goto failed5; - } - os_printf("OK\n"); - - os_printf("server SSL read message ......"); - do { - memset(recv_buf, 0, OPENSSL_DEMO_RECV_BUF_LEN); - ret = SSL_read(ssl, recv_buf, OPENSSL_DEMO_RECV_BUF_LEN - 1); - if (ret <= 0) { - break; - } - if (strstr(recv_buf, "GET / HTTP/1.1")) { - SSL_write(ssl, send_data, send_bytes); - break; - } - } while (1); - - os_printf("result %d\n", ret); - - SSL_shutdown(ssl); -failed5: - close(new_socket); - new_socket = -1; -failed4: - SSL_free(ssl); - ssl = NULL; - goto reconnect; -failed3: - close(socket); - socket = -1; -failed2: - SSL_CTX_free(ctx); - ctx = NULL; -failed1: - vTaskDelete(NULL); - - return ; -} - -#else - #error "you must choose the right demo type" -#endif - -LOCAL void demo_init(void) -{ - int ret = pdFALSE; - -#if defined(CONFIG_OPENSSL_CLIENT_DEMO) || defined(CONFIG_OPENSSL_SERVER_DEMO) - xTaskHandle openssl_handle; - - ret = xTaskCreate(openssl_demo_thread, - OPENSSL_DEMO_THREAD_NAME, - OPENSSL_DEMO_THREAD_STACK_WORDS, - NULL, - OPENSSL_DEMO_THREAD_PRORIOTY, - &openssl_handle); -#endif - - if (ret != pdPASS) { - os_printf("create thread %s failed\n", OPENSSL_DEMO_THREAD_NAME); - return ; - } -} - -LOCAL esp_err_t wifi_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: - demo_init(); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - /* This is a workaround as ESP32 WiFi libs don't currently - auto-reassociate. */ - esp_wifi_connect(); - break; - default: - break; - } - return ESP_OK; -} - -LOCAL void wifi_conn_init(void) -{ - tcpip_adapter_init(); - ESP_ERROR_CHECK( esp_event_loop_init(wifi_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_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) ); - os_printf("start the WIFI SSID:[%s] password:[%s]\n", EXAMPLE_WIFI_SSID, EXAMPLE_WIFI_PASS); - ESP_ERROR_CHECK( esp_wifi_start() ); -} - -void app_main(void) -{ - nvs_flash_init(); - wifi_conn_init(); -} - diff --git a/examples/09_openssl/main/openssl_demo.h b/examples/09_openssl/main/openssl_demo.h deleted file mode 100644 index 89cd264b4..000000000 --- a/examples/09_openssl/main/openssl_demo.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef _OPENSSL_DEMO_H_ -#define _OPENSSL_DEMO_H_ - -const static unsigned char key_ctx[] = - "-----BEGIN PRIVATE KEY-----\r\n" - "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDQyyF0WBb2XbkL\r\n" - "wYFgyoPOanYvbb/qwbAkGf1zSPX35xruZmjszjcverMoyF6x2MBxD3gP1ijBR0Rr\r\n" - "0J0CfluABDLkzqpF5smOVX9k8W7ePClm91NhcASuF+CaZOe6B+6vOYShYjhe6eFG\r\n" - "AGk8SP4zSrG2XHNKXlR3w8duK9fyOOZLWRjL3T6+++HEaly1p4ujKZhrm5wHzywA\r\n" - "DvjDdvIWBCW1Z+8j7Q9qUITjlsDWHjrXCpyEfclE1WQxTP/W7rBLxNVxTfwbrdcD\r\n" - "HNrKTOXtN+oDmCruvmBnTkz9x4Te6wJuvtFd0fBtW1kWsMzomvOlKmvHo0gmpqfh\r\n" - "CwEPoKCNAgMBAAECggEBAIVr+LHXBL1kQLZhbiKC5t1FrMY8FLKYGM3JCevciMlk\r\n" - "lhIXwR7p29vsRYZfHBv7zWWyI9/C04JG31MiGOMaCbBxfnA2HBrVEqFwwxqnKVi8\r\n" - "CxzwGQkfwu3Y9j7TEj0PipfQYo+aKzmDrN/FrXnHjyEJryxAQbAZPVLW+Z7OR41R\r\n" - "ZOwtZLeVqmbeARGpu2Xd9SKAhbjdLSz96IdUcNrwbP/lzUgrKaiUioBMVFfIG5ce\r\n" - "4Mm2seCwaWxI8k24q0keSjsjV+5IxatVUNtJ9vYv6Tzo+3oqGvPeUBO7w9xhbLKf\r\n" - "jw1uEykcs0wcftWb1iB7r78bMPZ/KYhnSFsjT+vnIOECgYEA9LM5p63sn6OWrULd\r\n" - "doBBLaIw1ZK9rDUFLLRwv0e6+7tuuB08ok6D7PSfOpx0bb10lIx7epOE8ogGSmLS\r\n" - "w0rMbmcKAlTLAJ/0nX1ierZkb+Ay21F398tKL3igEfnaB9CzuOHF8XhbsTqeGFDJ\r\n" - "HFBMXxTbo4kfkUmZNYxwTombzkkCgYEA2m9teqjEOVZItqghOicWZ68JhWxBJFme\r\n" - "oSfzJKLd8atfUOnBLqAhPzvg1PvdIxjLWBqy28tEJf+jdSQCNe9BmhlptOwbFrJy\r\n" - "IyCXj6QTApSKTxyzIjMvzQkv1m8CxeCq5T64hvJ2++i7dlhumh21c7oL8aLeTnoe\r\n" - "AG1dBLJ9UCUCgYAhSlDJsyvB/Ct/nt0qRgCYCLzEEZakWwI9Nr8wBr41iSZi/fdF\r\n" - "zZC9J/qRqr9cPq4hl4sk/fTUWhUhAZjS4NY3HuWJs6d6ikhpNKm1MCMx5TqGA+ti\r\n" - "VtHc63g7edZjwczxliWr2EgBMIxZmoQByhrZxKis8vbMeUrSsiyFQstjoQKBgD3k\r\n" - "2Paqn39Hra7kERYzQSv78wy1UfgE1OgBM+orpAv4bTe2JKEbipAqXVi8TTrGqce7\r\n" - "OPcCr7q8pwpoO6AgvUv263byd/KEecbuU0PGUASpJk+oaDHGo0LL2Zw/NF/xezsd\r\n" - "/JdwWLqkhYnRIPXWeTXjf8LmTWubOqkQVA0irlNpAoGAJ+9N/NF3XAW0BroiVYLZ\r\n" - "p0Btcgt+b4LWrBlm0XqHhzKUlqhfibAr3OtUkFjo/509ncYPiuOzVSNosyjXFJ86\r\n" - "2kQ88fB3eeLnBAcbBXQKiOBPU2y6bCCfgdo+JEOK/cxVslaxMAyKSnFi9gdgzScd\r\n" - "k+hOlkflXQVkic3W358kFto=\r\n" - "-----END PRIVATE KEY-----\r\n" - ; -static int key_bytes = sizeof(key_ctx); - -const static unsigned char cert_ctx[] = - "-----BEGIN CERTIFICATE-----\r\n" - "MIID7jCCAtYCAQEwDQYJKoZIhvcNAQELBQAwgbwxCzAJBgNVBAYTAkNOMRAwDgYD\r\n" - "VQQIDAdKaWFuZ3N1MQ0wCwYDVQQHDARXdXhpMSYwJAYDVQQKDB1Fc3ByZXNzaWYg\r\n" - "Um9vdCBSU0EyMDQ4IHNoYTI1NjEcMBoGA1UECwwTUm9vdCBSU0EyMDQ4IHNoYTI1\r\n" - "NjEfMB0GA1UEAwwWcm9vdGNlcnQuZXNwcmVzc2lmLmNvbTElMCMGCSqGSIb3DQEJ\r\n" - "ARYWcm9vdGNlcnRAZXNwcmVzc2lmLmNvbTAeFw0xNjA2MjgwMjMxMjlaFw0yNjA2\r\n" - "MjYwMjMxMjlaMIG8MQswCQYDVQQGEwJDTjEQMA4GA1UECAwHSmlhbmdzdTENMAsG\r\n" - "A1UEBwwEV3V4aTEmMCQGA1UECgwdRXNwcmVzc2lmIFJvb3QgUlNBMjA0OCBzaGEy\r\n" - "NTYxHDAaBgNVBAsME1Jvb3QgUlNBMjA0OCBzaGEyNTYxHzAdBgNVBAMMFnJvb3Rj\r\n" - "ZXJ0LmVzcHJlc3NpZi5jb20xJTAjBgkqhkiG9w0BCQEWFnJvb3RjZXJ0QGVzcHJl\r\n" - "c3NpZi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDQyyF0WBb2\r\n" - "XbkLwYFgyoPOanYvbb/qwbAkGf1zSPX35xruZmjszjcverMoyF6x2MBxD3gP1ijB\r\n" - "R0Rr0J0CfluABDLkzqpF5smOVX9k8W7ePClm91NhcASuF+CaZOe6B+6vOYShYjhe\r\n" - "6eFGAGk8SP4zSrG2XHNKXlR3w8duK9fyOOZLWRjL3T6+++HEaly1p4ujKZhrm5wH\r\n" - "zywADvjDdvIWBCW1Z+8j7Q9qUITjlsDWHjrXCpyEfclE1WQxTP/W7rBLxNVxTfwb\r\n" - "rdcDHNrKTOXtN+oDmCruvmBnTkz9x4Te6wJuvtFd0fBtW1kWsMzomvOlKmvHo0gm\r\n" - "pqfhCwEPoKCNAgMBAAEwDQYJKoZIhvcNAQELBQADggEBABTYZLiFHq51lqaa0nHI\r\n" - "aDMAb29DfO93fqp+oHZYO4xKyEeLr8EhD39GjnQmhz710wO0TBCYV7nD+xnJ1h5F\r\n" - "IbQUAQZO9NIy3ns4mYVRUWjnWYAo+evGeKgRrxvh7sjNLPBPzs9tg/u7XjBp/nor\r\n" - "8JnnFFT0wXPyi/qg8J3QutqJvWRQGRRx2AP93F44+Zcj7ReFMVSmOXyzT4aNJL0+\r\n" - "Ls+baKwA4pnyVRoAaKbs/JYDgd0/DunuktVKuhyvK/qOGjJSRLPhdrXbvSAegpiM\r\n" - "4xIm6ZWKtTv8VvkGgXUVQ7RpruP6nV6506gDcUgecbEq7H2VDhEzUYcMmGCUQZlG\r\n" - "sJ8=\r\n" - "-----END CERTIFICATE-----\r\n" - ; -static int cert_bytes = sizeof(cert_ctx); - - - -#endif diff --git a/examples/09_openssl/Makefile b/examples/09_openssl_client/Makefile similarity index 83% rename from examples/09_openssl/Makefile rename to examples/09_openssl_client/Makefile index 8987be554..7e2f4fe7f 100644 --- a/examples/09_openssl/Makefile +++ b/examples/09_openssl_client/Makefile @@ -3,7 +3,7 @@ # project subdirectory. # -PROJECT_NAME := openssl +PROJECT_NAME := openssl_client include $(IDF_PATH)/make/project.mk diff --git a/examples/09_openssl_client/README.md b/examples/09_openssl_client/README.md new file mode 100644 index 000000000..85d9575d6 --- /dev/null +++ b/examples/09_openssl_client/README.md @@ -0,0 +1,16 @@ +# Openssl Example + +The Example contains of OpenSSL client demo. + +First you should config the project by "make menuconfig": + Example Configuration -> + 1. Target Domain : the domain that you want to connect to, and default is "www.baidu.com". + 2. Target port number : the port number of the target domain, and default is 443. + 3. WiFi SSID : you own wifi, which you pc is connected to alse, and default is "myssid". + 4. WiFi Password : wifi password, and default is "mypassword" + +If you want to test the OpenSSL client demo: + 1. compile the code and load the firmware + 2. open the UART TTY, then you can see it print the context of target domain + +See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/09_openssl_client/main/Kconfig.projbuild b/examples/09_openssl_client/main/Kconfig.projbuild new file mode 100644 index 000000000..1767923ad --- /dev/null +++ b/examples/09_openssl_client/main/Kconfig.projbuild @@ -0,0 +1,28 @@ +menu "Example Configuration" + +config TARGET_DOMAIN + string "Target Domain" + default "www.baidu.com" + help + Target domain for the example to connect to. + +config TARGET_PORT_NUMBER + int "Target port number" + range 0 65535 + default 433 + help + Target port number for the example to connect to. + +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 "mypassword" + help + WiFi password (WPA or WPA2) for the example to use. + +endmenu \ No newline at end of file diff --git a/examples/09_openssl/main/component.mk b/examples/09_openssl_client/main/component.mk similarity index 86% rename from examples/09_openssl/main/component.mk rename to examples/09_openssl_client/main/component.mk index 24356f23e..973de1d6f 100644 --- a/examples/09_openssl/main/component.mk +++ b/examples/09_openssl_client/main/component.mk @@ -1,7 +1,7 @@ # # Main Makefile. This is basically the same as a component makefile. # -# This Makefile should, at the very least, just include $(SDK_PATH)/make/component_common.mk. By default, +# This Makefile should, at the very least, just include $(IDF_PATH)/make/component_common.mk. By default, # this will take the sources in the src/ directory, compile them and link them into # lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, # please read the ESP-IDF documents if you need to do this. diff --git a/examples/09_openssl_client/main/openssl_client.c b/examples/09_openssl_client/main/openssl_client.c new file mode 100644 index 000000000..9d4b8b395 --- /dev/null +++ b/examples/09_openssl_client/main/openssl_client.c @@ -0,0 +1,235 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "openssl_client.h" + +#include + +#include "openssl/ssl.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" + +#include "esp_types.h" +#include "esp_log.h" +#include "esp_system.h" +#include "esp_wifi.h" +#include "esp_event_loop.h" +#include "esp_log.h" + +#include "nvs_flash.h" +#include "tcpip_adapter.h" + +#include "lwip/sockets.h" +#include "lwip/netdb.h" + +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 static int CONNECTED_BIT = BIT0; + +const static char *TAG = "Openssl_demo"; + +void openssl_demo_thread(void *p) +{ + int ret; + SSL_CTX *ctx; + SSL *ssl; + int socket; + struct sockaddr_in sock_addr; + struct hostent *hp; + struct ip4_addr *ip4_addr; + + int recv_bytes = 0; + char send_data[] = OPENSSL_DEMO_REQUEST; + int send_bytes = sizeof(send_data); + char recv_buf[OPENSSL_DEMO_RECV_BUF_LEN]; + + ESP_LOGI(TAG, "OpenSSL demo thread start OK"); + + ESP_LOGI(TAG, "get target IP address"); + hp = gethostbyname(OPENSSL_DEMO_TARGET_NAME); + if (!hp) { + ESP_LOGI(TAG, "failed"); + goto failed1; + } + ESP_LOGI(TAG, "OK"); + + ip4_addr = (struct ip4_addr *)hp->h_addr; + ESP_LOGI(TAG, IPSTR, IP2STR(ip4_addr)); + + ESP_LOGI(TAG, "create SSL context ......"); + ctx = SSL_CTX_new(TLSv1_1_client_method()); + if (!ctx) { + ESP_LOGI(TAG, "failed"); + goto failed1; + } + ESP_LOGI(TAG, "OK"); + + ESP_LOGI(TAG, "create socket ......"); + socket = socket(AF_INET, SOCK_STREAM, 0); + if (socket < 0) { + ESP_LOGI(TAG, "failed"); + goto failed2; + } + ESP_LOGI(TAG, "OK"); + + ESP_LOGI(TAG, "bind socket ......"); + memset(&sock_addr, 0, sizeof(sock_addr)); + sock_addr.sin_family = AF_INET; + sock_addr.sin_addr.s_addr = 0; + sock_addr.sin_port = htons(OPENSSL_DEMO_LOCAL_TCP_PORT); + ret = bind(socket, (struct sockaddr*)&sock_addr, sizeof(sock_addr)); + if (ret) { + ESP_LOGI(TAG, "failed"); + goto failed3; + } + ESP_LOGI(TAG, "OK"); + + ESP_LOGI(TAG, "socket connect to remote %s ......", OPENSSL_DEMO_TARGET_NAME); + memset(&sock_addr, 0, sizeof(sock_addr)); + sock_addr.sin_family = AF_INET; + sock_addr.sin_addr.s_addr = ip4_addr->addr; + sock_addr.sin_port = htons(OPENSSL_DEMO_TARGET_TCP_PORT); + ret = connect(socket, (struct sockaddr*)&sock_addr, sizeof(sock_addr)); + if (ret) { + ESP_LOGI(TAG, "failed"); + goto failed3; + } + ESP_LOGI(TAG, "OK"); + + ESP_LOGI(TAG, "create SSL ......"); + ssl = SSL_new(ctx); + if (!ssl) { + ESP_LOGI(TAG, "failed"); + goto failed3; + } + ESP_LOGI(TAG, "OK"); + + SSL_set_fd(ssl, socket); + + ESP_LOGI(TAG, "SSL connected to %s port %d ......", + OPENSSL_DEMO_TARGET_NAME, OPENSSL_DEMO_TARGET_TCP_PORT); + ret = SSL_connect(ssl); + if (!ret) { + ESP_LOGI(TAG, "failed " ); + goto failed4; + } + ESP_LOGI(TAG, "OK"); + + ESP_LOGI(TAG, "send https request to %s port %d ......", + OPENSSL_DEMO_TARGET_NAME, OPENSSL_DEMO_TARGET_TCP_PORT); + ret = SSL_write(ssl, send_data, send_bytes); + if (ret <= 0) { + ESP_LOGI(TAG, "failed"); + goto failed5; + } + ESP_LOGI(TAG, "OK"); + + do { + ret = SSL_read(ssl, recv_buf, OPENSSL_DEMO_RECV_BUF_LEN - 1); + if (ret <= 0) { + break; + } + recv_bytes += ret; + ESP_LOGI(TAG, "%s", recv_buf); + } while (1); + + ESP_LOGI(TAG, "totaly read %d bytes data from %s ......", recv_bytes, OPENSSL_DEMO_TARGET_NAME); + +failed5: + SSL_shutdown(ssl); +failed4: + SSL_free(ssl); + ssl = NULL; +failed3: + close(socket); + socket = -1; +failed2: + SSL_CTX_free(ctx); + ctx = NULL; +failed1: + vTaskDelete(NULL); + return ; +} + +static void openssl_client_init(void) +{ + int ret; + xTaskHandle openssl_handle; + extern void openssl_demo_thread(void *p); + + ret = xTaskCreate(openssl_demo_thread, + OPENSSL_DEMO_THREAD_NAME, + OPENSSL_DEMO_THREAD_STACK_WORDS, + NULL, + OPENSSL_DEMO_THREAD_PRORIOTY, + &openssl_handle); + + if (ret != pdPASS) { + ESP_LOGI(TAG, "create thread %s failed", OPENSSL_DEMO_THREAD_NAME); + return ; + } +} + +static esp_err_t wifi_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); + openssl_client_init(); + 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 wifi_conn_init(void) +{ + tcpip_adapter_init(); + wifi_event_group = xEventGroupCreate(); + ESP_ERROR_CHECK( esp_event_loop_init(wifi_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_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); + ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) ); + ESP_LOGI(TAG, "start the WIFI SSID:[%s] password:[%s]\n", EXAMPLE_WIFI_SSID, EXAMPLE_WIFI_PASS); + ESP_ERROR_CHECK( esp_wifi_start() ); +} + +void app_main(void) +{ + nvs_flash_init(); + wifi_conn_init(); +} diff --git a/examples/09_openssl_client/main/openssl_client.h b/examples/09_openssl_client/main/openssl_client.h new file mode 100644 index 000000000..5bc69a0ac --- /dev/null +++ b/examples/09_openssl_client/main/openssl_client.h @@ -0,0 +1,34 @@ +#ifndef _OPENSSL_DEMO_H_ +#define _OPENSSL_DEMO_H_ + +/* The examples use simple WiFi configuration that you can set via + 'make menuconfig'. + + If you'd rather not, just change the below entries to strings with + the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" +*/ +#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID +#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD + +/* The examples use domain of "www.baidu.com" and port number of 433 that + you can set via 'make menuconfig'. + + If you'd rather not, just change the below entries to strings with + the config you want - ie #define OPENSSL_DEMO_TARGET_NAME "www.baidu.com" + and ie #define OPENSSL_DEMO_TARGET_TCP_PORT 433 +*/ +#define OPENSSL_DEMO_TARGET_NAME CONFIG_TARGET_DOMAIN +#define OPENSSL_DEMO_TARGET_TCP_PORT CONFIG_TARGET_PORT_NUMBER + +#define OPENSSL_DEMO_REQUEST "{\"path\": \"/v1/ping/\", \"method\": \"GET\"}\r\n" + +#define OPENSSL_DEMO_THREAD_NAME "OpenSSL_demo" +#define OPENSSL_DEMO_THREAD_STACK_WORDS 10240 +#define OPENSSL_DEMO_THREAD_PRORIOTY 8 + +#define OPENSSL_DEMO_RECV_BUF_LEN 1024 + +#define OPENSSL_DEMO_LOCAL_TCP_PORT 443 + +#endif + From fa1d5bfbc78797ac261ab5d63662cdbf1b68f254 Mon Sep 17 00:00:00 2001 From: liuhan Date: Thu, 3 Nov 2016 13:30:32 +0800 Subject: [PATCH 07/48] tcpip_adapter: add set hostname interface --- .../tcpip_adapter/include/tcpip_adapter.h | 13 +++++++++ components/tcpip_adapter/tcpip_adapter_lwip.c | 28 +++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/components/tcpip_adapter/include/tcpip_adapter.h b/components/tcpip_adapter/include/tcpip_adapter.h index e84701688..45d6ade30 100644 --- a/components/tcpip_adapter/include/tcpip_adapter.h +++ b/components/tcpip_adapter/include/tcpip_adapter.h @@ -372,6 +372,19 @@ wifi_interface_t tcpip_adapter_get_wifi_if(void *dev); */ esp_err_t tcpip_adapter_get_sta_list(wifi_sta_list_t *wifi_sta_list, tcpip_adapter_sta_list_t *tcpip_sta_list); +#define TCPIP_HOSTNAME_MAX_SIZE 31 +/** + * @brief Set the hostname to the interface + * + * @param[in] tcpip_if: the interface which we will set the hostname + * @param[in] hostname: the host name for set the interfce + * + * @return ESP_OK:success + * ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY:interface status error + * ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS:parameter error + */ +esp_err_t tcpip_adapter_set_hostname(tcpip_adapter_if_t tcpip_if, const char *hostname); + #ifdef __cplusplus } #endif diff --git a/components/tcpip_adapter/tcpip_adapter_lwip.c b/components/tcpip_adapter/tcpip_adapter_lwip.c index 9b6e9d94f..3edc90509 100644 --- a/components/tcpip_adapter/tcpip_adapter_lwip.c +++ b/components/tcpip_adapter/tcpip_adapter_lwip.c @@ -607,4 +607,32 @@ esp_err_t tcpip_adapter_get_sta_list(wifi_sta_list_t *wifi_sta_list, tcpip_adapt return ESP_OK; } +esp_err_t tcpip_adapter_set_hostname(tcpip_adapter_if_t tcpip_if, const char *hostname) +{ + struct netif *p_netif; + static char hostinfo[TCPIP_HOSTNAME_MAX_SIZE + 1]; + + if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || hostname == NULL) { + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + if (strlen(hostname) >= TCPIP_HOSTNAME_MAX_SIZE) { + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + p_netif = esp_netif[tcpip_if]; + if (p_netif != NULL) { + if (netif_is_up(p_netif)) { + return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; + } else { + memset(hostinfo, 0, sizeof(hostinfo)); + memcpy(hostinfo, hostname, strlen(hostname)); + p_netif->hostname = hostinfo; + return ESP_OK; + } + } else { + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } +} + #endif From 9a2887c458c20b05ffad8f7ef8dbd54a20b97920 Mon Sep 17 00:00:00 2001 From: Jeroen Domburg Date: Tue, 15 Nov 2016 12:10:02 +0800 Subject: [PATCH 08/48] Add comments/headers according to merge request comments --- components/esp32/freertos_hooks.c | 15 ++++++++++ components/esp32/include/esp_freertos_hooks.h | 29 +++++++++++++++++-- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/components/esp32/freertos_hooks.c b/components/esp32/freertos_hooks.c index 50ebd3d05..d59a20363 100644 --- a/components/esp32/freertos_hooks.c +++ b/components/esp32/freertos_hooks.c @@ -1,3 +1,18 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + #include #include #include diff --git a/components/esp32/include/esp_freertos_hooks.h b/components/esp32/include/esp_freertos_hooks.h index 1bb5ab194..45a164972 100644 --- a/components/esp32/include/esp_freertos_hooks.h +++ b/components/esp32/include/esp_freertos_hooks.h @@ -1,9 +1,27 @@ -#ifndef ESP_FREERTOS_HOOKS_H -#define ESP_FREERTOS_HOOKS_H +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef __ESP_FREERTOS_HOOKS_H__ +#define __ESP_FREERTOS_HOOKS_H__ #include #include "esp_err.h" +#ifdef __cplusplus +extern "C" +{ +#endif /* Definitions for the tickhook and idlehook callbacks @@ -17,6 +35,9 @@ typedef void (*esp_freertos_tick_cb_t)(); * sleep until an interrupt (or FreeRTOS tick) happens and false * if it should be called again as fast as possible. * + * @warning Idle callbacks MUST NOT, UNDER ANY CIRCUMSTANCES, CALL + * A FUNCTION THAT MIGHT BLOCK. + * * @param esp_freertos_idle_cb_t new_idle_cb : Callback to be called * * @return ESP_OK : Callback registered @@ -54,5 +75,9 @@ void esp_deregister_freertos_idle_hook(esp_freertos_idle_cb_t old_idle_cb); */ void esp_deregister_freertos_tick_hook(esp_freertos_tick_cb_t old_tick_cb); +#ifdef __cplusplus +} +#endif + #endif \ No newline at end of file From a8a51a2786a3b2f1814a111af10f66d45f47a4c1 Mon Sep 17 00:00:00 2001 From: Wangjialin Date: Tue, 15 Nov 2016 13:47:51 +0800 Subject: [PATCH 09/48] bugfix/uart_isr_switch_context: add switching context in uart ISR. 1. add switching context in uart ISR 2. remove duplicated #include in uart.c 3. modify example in uart.h(will later add examples to idf/examples) --- components/driver/include/driver/uart.h | 13 ++++++---- components/driver/uart.c | 34 +++++++++++++++++++------ 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/components/driver/include/driver/uart.h b/components/driver/include/driver/uart.h index 7dccf1666..906bdcb9e 100644 --- a/components/driver/include/driver/uart.h +++ b/components/driver/include/driver/uart.h @@ -686,13 +686,14 @@ esp_err_t uart_flush(uart_port_t uart_num); * { * int uart_num = (int)pvParameters; * uart_event_t event; - * uint8_t dtmp[1000]; + * size_t size = 1024; + * uint8_t* dtmp = (uint8_t*)malloc(size); * for(;;) { * //Waiting for UART event. * if(xQueueReceive(uart0_queue, (void * )&event, (portTickType)portMAX_DELAY)) { * ESP_LOGI(TAG, "uart[%d] event:", uart_num); * switch(event.type) { - * memset(dtmp, 0, sizeof(dtmp)); + * memset(dtmp, 0, size); * //Event of UART receving data * case UART_DATA: * ESP_LOGI(TAG,"data, len: %d", event.size); @@ -727,6 +728,8 @@ esp_err_t uart_flush(uart_port_t uart_num); * } * } * } + * free(dtmp); + * dtmp = NULL; * vTaskDelete(NULL); * } * @@ -744,13 +747,13 @@ esp_err_t uart_flush(uart_port_t uart_num); * //Set UART parameters * uart_param_config(uart_num, &uart_config); * //Set UART pins,(-1: default pin, no change.) - * uart_set_pin(uart_num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, 15, 13); + * uart_set_pin(uart_num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); * //Set UART log level * esp_log_level_set(TAG, ESP_LOG_INFO); * //Install UART driver, and get the queue. - * uart_driver_install(uart_num, 1024 * 2, 1024*4, 10, 17, &uart0_queue, RINGBUF_TYPE_BYTEBUF); + * uart_driver_install(uart_num, 1024 * 2, 1024*4, 10, 17, &uart0_queue); * //Create a task to handler UART event from ISR - * xTaskCreate(uart_task, "uTask", 2048*8, (void*)uart_num, 10, NULL); + * xTaskCreate(uart_task, "uTask", 1024, (void*)uart_num, 10, NULL); * } * @endcode * diff --git a/components/driver/uart.c b/components/driver/uart.c index d9e3fd64c..a8d28ff29 100644 --- a/components/driver/uart.c +++ b/components/driver/uart.c @@ -23,11 +23,9 @@ #include "freertos/task.h" #include "freertos/ringbuf.h" #include "soc/dport_reg.h" -#include "rom/ets_sys.h" #include "soc/uart_struct.h" #include "driver/uart.h" #include "driver/gpio.h" -#include "soc/uart_struct.h" static const char* UART_TAG = "UART"; #define UART_CHECK(a, str, ret) if (!(a)) { \ @@ -458,17 +456,20 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) uart_reg->int_clr.txfifo_empty = 1; UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); if(p_uart->tx_waiting_brk) { - return; + continue; } //TX semaphore will only be used when tx_buf_size is zero. if(p_uart->tx_waiting_fifo == true && p_uart->tx_buf_size == 0) { p_uart->tx_waiting_fifo = false; - xSemaphoreGiveFromISR(p_uart->tx_fifo_sem, NULL); + xSemaphoreGiveFromISR(p_uart->tx_fifo_sem, &HPTaskAwoken); + if(HPTaskAwoken == pdTRUE) { + portYIELD_FROM_ISR() ; + } } else { - //We don't use TX ring buffer, because the size if zero. + //We don't use TX ring buffer, because the size is zero. if(p_uart->tx_buf_size == 0) { - return; + continue; } int tx_fifo_rem = UART_FIFO_LEN - UART[uart_num]->status.txfifo_cnt; bool en_tx_flg = false; @@ -492,6 +493,9 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) } //We have saved the data description from the 1st item, return buffer. vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, p_uart->tx_head, &HPTaskAwoken); + if(HPTaskAwoken == pdTRUE) { + portYIELD_FROM_ISR() ; + } }else if(p_uart->tx_ptr == NULL) { //Update the TX item pointer, we will need this to return item to buffer. p_uart->tx_ptr = (uint8_t*) p_uart->tx_head; @@ -501,7 +505,7 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) } else { //Can not get data from ring buffer, return; - return; + break; } } if(p_uart->tx_len_tot > 0 && p_uart->tx_ptr && p_uart->tx_len_cur > 0) { @@ -516,6 +520,9 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) if(p_uart->tx_len_cur == 0) { //Return item to ring buffer. vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, p_uart->tx_head, &HPTaskAwoken); + if(HPTaskAwoken == pdTRUE) { + portYIELD_FROM_ISR() ; + } p_uart->tx_head = NULL; p_uart->tx_ptr = NULL; //Sending item done, now we need to send break if there is a record. @@ -529,7 +536,6 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) uart_reg->int_ena.tx_brk_done = 1; UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); p_uart->tx_waiting_brk = 1; - return; } else { //enable TX empty interrupt en_tx_flg = true; @@ -576,6 +582,9 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) } else { uart_event.type = UART_DATA; } + if(HPTaskAwoken == pdTRUE) { + portYIELD_FROM_ISR() ; + } } else { UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]); uart_reg->int_ena.rxfifo_full = 0; @@ -614,6 +623,9 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) p_uart->tx_waiting_brk = 0; } else { xSemaphoreGiveFromISR(p_uart->tx_brk_sem, &HPTaskAwoken); + if(HPTaskAwoken == pdTRUE) { + portYIELD_FROM_ISR() ; + } } } else if(uart_intr_status & UART_TX_BRK_IDLE_DONE_INT_ST_M) { UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]); @@ -626,6 +638,9 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) uart_reg->int_clr.tx_done = 1; UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); xSemaphoreGiveFromISR(p_uart_obj[uart_num]->tx_done_sem, &HPTaskAwoken); + if(HPTaskAwoken == pdTRUE) { + portYIELD_FROM_ISR() ; + } } else { uart_reg->int_clr.val = uart_intr_status; /*simply clear all other intr status*/ @@ -634,6 +649,9 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) if(uart_event.type != UART_EVENT_MAX && p_uart->xQueueUart) { xQueueSendFromISR(p_uart->xQueueUart, (void * )&uart_event, &HPTaskAwoken); + if(HPTaskAwoken == pdTRUE) { + portYIELD_FROM_ISR() ; + } } uart_intr_status = uart_reg->int_st.val; } From dfaac25a37340a37ae808d2c12c9a37d268cbc48 Mon Sep 17 00:00:00 2001 From: Dong Heng Date: Tue, 15 Nov 2016 15:04:21 +0800 Subject: [PATCH 10/48] feature/openssl: add openssl server demo and remove some check function --- components/openssl/platform/ssl_pm.c | 4 ---- examples/09_openssl_client/main/component.mk | 2 -- 2 files changed, 6 deletions(-) diff --git a/components/openssl/platform/ssl_pm.c b/components/openssl/platform/ssl_pm.c index 091402cda..a5986dc3e 100644 --- a/components/openssl/platform/ssl_pm.c +++ b/components/openssl/platform/ssl_pm.c @@ -90,10 +90,6 @@ int ssl_pm_new(SSL *ssl) if (!ssl_pm) SSL_ERR(ret, failed1, "ssl_mem_zalloc\n"); - if (ssl->ctx->read_buffer_len < 2048 || - ssl->ctx->read_buffer_len > 8192) - return -1; - max_content_len = ssl->ctx->read_buffer_len; mbedtls_net_init(&ssl_pm->fd); diff --git a/examples/09_openssl_client/main/component.mk b/examples/09_openssl_client/main/component.mk index 973de1d6f..9c21f4a8d 100644 --- a/examples/09_openssl_client/main/component.mk +++ b/examples/09_openssl_client/main/component.mk @@ -6,5 +6,3 @@ # lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, # please read the ESP-IDF documents if you need to do this. # - -include $(IDF_PATH)/make/component_common.mk From a2b1f4221b39e61d0ad41c55f523b08d4a6a2605 Mon Sep 17 00:00:00 2001 From: Dong Heng Date: Tue, 15 Nov 2016 15:08:51 +0800 Subject: [PATCH 11/48] feature/openssl: add the openssl server demo --- examples/10_openssl_server/Makefile | 9 + examples/10_openssl_server/README.md | 20 ++ .../10_openssl_server/main/Kconfig.projbuild | 15 + examples/10_openssl_server/main/cacert.pem | 21 ++ examples/10_openssl_server/main/component.mk | 11 + .../10_openssl_server/main/openssl_server.c | 258 ++++++++++++++++++ .../10_openssl_server/main/openssl_server.h | 22 ++ examples/10_openssl_server/main/prvtkey.pem | 27 ++ 8 files changed, 383 insertions(+) create mode 100644 examples/10_openssl_server/Makefile create mode 100644 examples/10_openssl_server/README.md create mode 100644 examples/10_openssl_server/main/Kconfig.projbuild create mode 100644 examples/10_openssl_server/main/cacert.pem create mode 100644 examples/10_openssl_server/main/component.mk create mode 100644 examples/10_openssl_server/main/openssl_server.c create mode 100644 examples/10_openssl_server/main/openssl_server.h create mode 100644 examples/10_openssl_server/main/prvtkey.pem diff --git a/examples/10_openssl_server/Makefile b/examples/10_openssl_server/Makefile new file mode 100644 index 000000000..f65f11a56 --- /dev/null +++ b/examples/10_openssl_server/Makefile @@ -0,0 +1,9 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := openssl_server + +include $(IDF_PATH)/make/project.mk + diff --git a/examples/10_openssl_server/README.md b/examples/10_openssl_server/README.md new file mode 100644 index 000000000..ae5c8da0c --- /dev/null +++ b/examples/10_openssl_server/README.md @@ -0,0 +1,20 @@ +# Openssl Example + +The Example contains of OpenSSL server demo. + +First you should configure the project by "make menuconfig": + Example Configuration -> + 1. WiFi SSID: you own wifi that you pc is connected to alse. + 1. WiFi Password: wifi password + +IF you want to test the OpenSSL server demo: + 1. compile the code and load the firmware + 2. input the context of "https://192.168.17.128" into your web browser, the IP of your module may not be 192.168.17.128, you should input your module's IP + 3. You may see that it shows the website is not able to be trusted, but you should select that "go on to visit it" + 4. You should wait for a moment until your see the "OpenSSL server demo!" in your web browser + +Note: + The private key and certification at the example are not trusted by web browser, because they are not created by CA official, just by ourselves. + You can alse create your own private key and ceritification by "openssl at ubuntu or others". + +See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/10_openssl_server/main/Kconfig.projbuild b/examples/10_openssl_server/main/Kconfig.projbuild new file mode 100644 index 000000000..7a9cb97a0 --- /dev/null +++ b/examples/10_openssl_server/main/Kconfig.projbuild @@ -0,0 +1,15 @@ +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 "mypassword" + help + WiFi password (WPA or WPA2) for the example to use. + +endmenu \ No newline at end of file diff --git a/examples/10_openssl_server/main/cacert.pem b/examples/10_openssl_server/main/cacert.pem new file mode 100644 index 000000000..e09c3989c --- /dev/null +++ b/examples/10_openssl_server/main/cacert.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDezCCAmOgAwIBAgIJAPMMNobNczaUMA0GCSqGSIb3DQEBBAUAMHQxEzARBgNV +BAMTCk15IFRlc3QgQ0ExCzAJBgNVBAgTAkhaMQswCQYDVQQGEwJDTjEcMBoGCSqG +SIb3DQEJARYNdGVzdEBjZXJ0LmNvbTElMCMGA1UEChMcUm9vdCBDZXJ0aWZpY2F0 +aW9uIEF1dGhvcml0eTAeFw0xNjExMTUwNTA0MThaFw0xOTExMTUwNTA0MThaMHQx +EzARBgNVBAMTCk15IFRlc3QgQ0ExCzAJBgNVBAgTAkhaMQswCQYDVQQGEwJDTjEc +MBoGCSqGSIb3DQEJARYNdGVzdEBjZXJ0LmNvbTElMCMGA1UEChMcUm9vdCBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBALDjSPDlomepHCzbw4MUrquQAU0xTV4/Npb27k9I5TRVTjIoOs/5hNI2LPFW +e4CREx09ZrT8K3NFOBoSy7bhPAsjGaFxCYYWc9tiX1m5gq3ToVRSmbZ65fE3kvnI +8E/d5VyzA0OMmWbfaolBSTMoWgqRynEaT+z1Eh2yDTzVFy9eov1DdQFUqGDqbH5b +QYvTY5Fyem7UcKWAe2yS0j3H4dVtVBKNY7qV3Px08yGAs5fQFgUwhyB5+qwhvkeL +JdgapGaSTwLgoQKWHbe/lA3NiBIB9hznFUGKo3hmniAvYZbrQcn3tc0l/J4I39v2 +Pm29FAyjWvQyBkGktz2q4elOZYkCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkq +hkiG9w0BAQQFAAOCAQEAJCJ+97oae/FcOLbPpjCpUQnWqYydgSChgalkZNvr4fVp +TnuNg471l0Y2oTJLoWn2YcbPSFVOEeKkU47mpjMzucHHp0zGaW9SdzhZalWwmbgK +q2ijecIbuFHFNedYTk/03K7eaAcjVhD8e0oOJImeLOL6DAFivA1LUnSgXsdGPDtD +zhISsCPTu+cL1j0yP6HBvLeAyb8kaCWJ05RtiVLRANNHQn/keHajJYpMwnEEbJdG +cqN3whfJoGVbZ6isEf2RQJ0pYRnP7uGLW3wGkLWxfdto8uER8HVDx7fZpevLIqGd +1OoSEi3cIJXWBAjx0TLzzhtb6aeIxBJWQqHThtkKdg== +-----END CERTIFICATE----- diff --git a/examples/10_openssl_server/main/component.mk b/examples/10_openssl_server/main/component.mk new file mode 100644 index 000000000..4a891d52f --- /dev/null +++ b/examples/10_openssl_server/main/component.mk @@ -0,0 +1,11 @@ +# +# Main Makefile. This is basically the same as a component makefile. +# +# This Makefile should, at the very least, just include $(IDF_PATH)/make/component_common.mk. By default, +# this will take the sources in the src/ directory, compile them and link them into +# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, +# please read the ESP-IDF documents if you need to do this. +# + +COMPONENT_EMBED_TXTFILES := cacert.pem +COMPONENT_EMBED_TXTFILES += prvtkey.pem diff --git a/examples/10_openssl_server/main/openssl_server.c b/examples/10_openssl_server/main/openssl_server.c new file mode 100644 index 000000000..4fc841ac7 --- /dev/null +++ b/examples/10_openssl_server/main/openssl_server.c @@ -0,0 +1,258 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "openssl_server.h" + +#include + +#include "openssl/ssl.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" + +#include "esp_types.h" +#include "esp_log.h" +#include "esp_system.h" +#include "esp_wifi.h" +#include "esp_event_loop.h" +#include "esp_log.h" + +#include "nvs_flash.h" +#include "tcpip_adapter.h" + +#include "lwip/sockets.h" +#include "lwip/netdb.h" + +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 static int CONNECTED_BIT = BIT0; + +const static char *TAG = "Openssl_demo"; + +#define OPENSSL_DEMO_SERVER_ACK "HTTP/1.1 200 OK\r\n" \ + "Content-Type: text/html\r\n" \ + "Content-Length: 98\r\n" \ + "\r\n" \ + "\r\n" \ + "OpenSSL demo\r\n" \ + "OpenSSL server demo!\r\n" \ + "\r\n" \ + "\r\n" + +static void openssl_demo_thread(void *p) +{ + int ret; + + SSL_CTX *ctx; + SSL *ssl; + + int socket, new_socket; + socklen_t addr_len; + struct sockaddr_in sock_addr; + + char send_data[] = OPENSSL_DEMO_SERVER_ACK; + int send_bytes = sizeof(send_data); + char recv_buf[OPENSSL_DEMO_RECV_BUF_LEN]; + + extern const unsigned char cacert_pem_start[] asm("_binary_cacert_pem_start"); + extern const unsigned char cacert_pem_end[] asm("_binary_cacert_pem_end"); + const unsigned int cacert_pem_bytes = cacert_pem_end - cacert_pem_start; + + extern const unsigned char prvtkey_pem_start[] asm("_binary_prvtkey_pem_start"); + extern const unsigned char prvtkey_pem_end[] asm("_binary_prvtkey_pem_end"); + const unsigned int prvtkey_pem_bytes = prvtkey_pem_end - prvtkey_pem_start; + + ESP_LOGI(TAG, "SSL server context create ......"); + ctx = SSL_CTX_new(SSLv3_server_method()); + if (!ctx) { + ESP_LOGI(TAG, "failed"); + goto failed1; + } + ESP_LOGI(TAG, "OK"); + + ESP_LOGI(TAG, "SSL server context set own certification......"); + ret = SSL_CTX_use_certificate_ASN1(ctx, cacert_pem_bytes, cacert_pem_start); + if (!ret) { + ESP_LOGI(TAG, "failed"); + goto failed2; + } + ESP_LOGI(TAG, "OK"); + + ESP_LOGI(TAG, "SSL server context set private key......"); + ret = SSL_CTX_use_PrivateKey_ASN1(0, ctx, prvtkey_pem_start, prvtkey_pem_bytes); + if (!ret) { + ESP_LOGI(TAG, "failed"); + goto failed2; + } + ESP_LOGI(TAG, "OK"); + + ESP_LOGI(TAG, "SSL server create socket ......"); + socket = socket(AF_INET, SOCK_STREAM, 0); + if (socket < 0) { + ESP_LOGI(TAG, "failed"); + goto failed2; + } + ESP_LOGI(TAG, "OK"); + + ESP_LOGI(TAG, "SSL server socket bind ......"); + memset(&sock_addr, 0, sizeof(sock_addr)); + sock_addr.sin_family = AF_INET; + sock_addr.sin_addr.s_addr = 0; + sock_addr.sin_port = htons(OPENSSL_DEMO_LOCAL_TCP_PORT); + ret = bind(socket, (struct sockaddr*)&sock_addr, sizeof(sock_addr)); + if (ret) { + ESP_LOGI(TAG, "failed"); + goto failed3; + } + ESP_LOGI(TAG, "OK"); + + ESP_LOGI(TAG, "SSL server socket listen ......"); + ret = listen(socket, 32); + if (ret) { + ESP_LOGI(TAG, "failed"); + goto failed3; + } + ESP_LOGI(TAG, "OK"); + +reconnect: + ESP_LOGI(TAG, "SSL server create ......"); + ssl = SSL_new(ctx); + if (!ssl) { + ESP_LOGI(TAG, "failed"); + goto failed3; + } + ESP_LOGI(TAG, "OK"); + + ESP_LOGI(TAG, "SSL server socket accept client ......"); + new_socket = accept(socket, (struct sockaddr *)&sock_addr, &addr_len); + if (new_socket < 0) { + ESP_LOGI(TAG, "failed" ); + goto failed4; + } + ESP_LOGI(TAG, "OK"); + + SSL_set_fd(ssl, new_socket); + + ESP_LOGI(TAG, "SSL server accept client ......"); + ret = SSL_accept(ssl); + if (!ret) { + ESP_LOGI(TAG, "failed"); + goto failed5; + } + ESP_LOGI(TAG, "OK"); + + ESP_LOGI(TAG, "SSL server read message ......"); + do { + memset(recv_buf, 0, OPENSSL_DEMO_RECV_BUF_LEN); + ret = SSL_read(ssl, recv_buf, OPENSSL_DEMO_RECV_BUF_LEN - 1); + if (ret <= 0) { + break; + } + if (strstr(recv_buf, "GET / HTTP/1.1")) { + SSL_write(ssl, send_data, send_bytes); + break; + } + } while (1); + + ESP_LOGI(TAG, "result %d", ret); + + SSL_shutdown(ssl); +failed5: + close(new_socket); + new_socket = -1; +failed4: + SSL_free(ssl); + ssl = NULL; + goto reconnect; +failed3: + close(socket); + socket = -1; +failed2: + SSL_CTX_free(ctx); + ctx = NULL; +failed1: + vTaskDelete(NULL); + return ; +} + +static void openssl_client_init(void) +{ + int ret; + xTaskHandle openssl_handle; + extern void openssl_demo_thread(void *p); + + ret = xTaskCreate(openssl_demo_thread, + OPENSSL_DEMO_THREAD_NAME, + OPENSSL_DEMO_THREAD_STACK_WORDS, + NULL, + OPENSSL_DEMO_THREAD_PRORIOTY, + &openssl_handle); + + if (ret != pdPASS) { + ESP_LOGI(TAG, "create thread %s failed", OPENSSL_DEMO_THREAD_NAME); + return ; + } +} + +static esp_err_t wifi_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); + openssl_client_init(); + 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 wifi_conn_init(void) +{ + tcpip_adapter_init(); + wifi_event_group = xEventGroupCreate(); + ESP_ERROR_CHECK( esp_event_loop_init(wifi_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_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); + ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) ); + ESP_LOGI(TAG, "start the WIFI SSID:[%s] password:[%s]\n", EXAMPLE_WIFI_SSID, EXAMPLE_WIFI_PASS); + ESP_ERROR_CHECK( esp_wifi_start() ); +} + +void app_main(void) +{ + nvs_flash_init(); + wifi_conn_init(); +} diff --git a/examples/10_openssl_server/main/openssl_server.h b/examples/10_openssl_server/main/openssl_server.h new file mode 100644 index 000000000..e87f5e482 --- /dev/null +++ b/examples/10_openssl_server/main/openssl_server.h @@ -0,0 +1,22 @@ +#ifndef _OPENSSL_DEMO_H_ +#define _OPENSSL_DEMO_H_ + +/* The examples use simple WiFi configuration that you can set via + 'make menuconfig'. + + If you'd rather not, just change the below entries to strings with + the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" +*/ +#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID +#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD + +#define OPENSSL_DEMO_THREAD_NAME "OpenSSL_demo" +#define OPENSSL_DEMO_THREAD_STACK_WORDS 10240 +#define OPENSSL_DEMO_THREAD_PRORIOTY 8 + +#define OPENSSL_DEMO_RECV_BUF_LEN 1024 + +#define OPENSSL_DEMO_LOCAL_TCP_PORT 443 + +#endif + diff --git a/examples/10_openssl_server/main/prvtkey.pem b/examples/10_openssl_server/main/prvtkey.pem new file mode 100644 index 000000000..4ead61f6f --- /dev/null +++ b/examples/10_openssl_server/main/prvtkey.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAsONI8OWiZ6kcLNvDgxSuq5ABTTFNXj82lvbuT0jlNFVOMig6 +z/mE0jYs8VZ7gJETHT1mtPwrc0U4GhLLtuE8CyMZoXEJhhZz22JfWbmCrdOhVFKZ +tnrl8TeS+cjwT93lXLMDQ4yZZt9qiUFJMyhaCpHKcRpP7PUSHbINPNUXL16i/UN1 +AVSoYOpsfltBi9NjkXJ6btRwpYB7bJLSPcfh1W1UEo1jupXc/HTzIYCzl9AWBTCH +IHn6rCG+R4sl2BqkZpJPAuChApYdt7+UDc2IEgH2HOcVQYqjeGaeIC9hlutByfe1 +zSX8ngjf2/Y+bb0UDKNa9DIGQaS3Parh6U5liQIDAQABAoIBAB9K9jp3xXVlO3DM +KBhmbkg3n6NSV4eW00d9w8cO9E1/0eeZql3knJS7tNO1IwApqiIAHM1j1yP7WONz +88oUqpSlzwD6iF7KVhC3pHqxEOdDi0Tpn/viXg+Ab2X1IF5guRTfLnKiyviiCazi +edqtBtDb3d6Icx9Oc7gBKcpbQFDGt++wSOb5L+xhRm9B5B4l/6byikiPeKqIK5tC +SoP9Zr1mvpNoGm1P4LvEunFJcRBqVI010VNwfO9P98oVyzJu9/FZZrQxXoY9JdXF +OM6nbl+hMDM3TkEOda9NvBhImozEAvuc97CaaXyR3XivxMqNqNIb4+syUPa2PCS3 +ZztI5qECgYEA1gbVG6ifpvpbBkDPi3Im8fM3F7FLLrQc48FdFjdMvDhHD9lVKucD +Uaa8PF9dbbvlu2cwMyfBOKSuWaXxRxRsiqiPmTunS1MvPzQcSrGwUrL2AogGucn6 ++NrLQf5P4H5IpkDQ9ih3zwjO6xKFK1WeYnYpHM8qUBtl6q0YFyVBPu0CgYEA05Pn +StWA4D7VSbNnVi6lvFyEOUsTrK3v419598TFiq4eXLq6aV8/CQYzKsSzoG+aOZhX +Li+0uyT5cNzUcXYhTsW1hA/pNhMfxMrYiB1x14zlLp2WRGg4vd/+SxX6d9Yd3acX +7QzPKgdDicXs9QN8ozJOICKvNbUI53AJdATVEY0CgYEAwvpGeoQLrdq1weSZLrg3 +soOX1QW3MDz1dKdbXjnStkWut0mOxR7fbysuoPFf8/ARQcCnsHKvHCMqkpESVWbN +2yPkbfxiU8Tcbf/TJljqAOz4ISY6ula/RKZONTixHBrvpEW4GAiV3Q5xMsYUe33s +ZFaw7YXtTj0ng7tdDvjpj6ECgYEApHdUU9ejVq2BHslWiqe4LbO9FMxHfvO2hgix +xugupp6y+2Irhb2EQn+PRq+g8hXOzPaezkhHNTKItDL08T3iplkJwJ6dqmszRsZn +i2dYFzZu8M2PAZ4CfZahFbz/9id7D9HTx3EtmH4NAgvZJpyPRkzUbiaIDDettDpj +Hsyi1AECgYAPLvjBzQj4kPF8Zo9pQEUcz4pmupRVfv3aRfjnahDK4qZHEePDRj+J +W7pzayrs1dyN9QLB8pTc424z7f8MB3llCICN+ohs8CR/eW0NEobE9ldDOeoCr1Vh +NhNSbrN1iZ8U4oLkRTMaDKkVngGffvjGi/q0tOU7hJdZOqNlk2Iahg== +-----END RSA PRIVATE KEY----- From d7599ab16d1504e2d75211f05562548665d905d3 Mon Sep 17 00:00:00 2001 From: Wangjialin Date: Wed, 16 Nov 2016 01:31:02 +0800 Subject: [PATCH 12/48] driver: fix header file warnings for Doxygen. --- components/driver/include/driver/gpio.h | 2 +- components/driver/include/driver/ledc.h | 2 + components/driver/include/driver/uart.h | 233 ++++++++++++------------ 3 files changed, 122 insertions(+), 115 deletions(-) diff --git a/components/driver/include/driver/gpio.h b/components/driver/include/driver/gpio.h index 73efeaa34..2d92dc50a 100644 --- a/components/driver/include/driver/gpio.h +++ b/components/driver/include/driver/gpio.h @@ -314,7 +314,7 @@ esp_err_t gpio_set_pull_mode(gpio_num_t gpio_num, gpio_pull_mode_t pull); * * @param gpio_num GPIO number. * - * @param intr_type GPIO wake-up type. Only GPIO_INTR_LOW_LEVEL\GPIO_INTR_HIGH_LEVEL can be used. + * @param intr_type GPIO wake-up type. Only GPIO_INTR_LOW_LEVEL or GPIO_INTR_HIGH_LEVEL can be used. * * @return * - ESP_OK Success diff --git a/components/driver/include/driver/ledc.h b/components/driver/include/driver/ledc.h index 3ab0ebff1..317a599fb 100644 --- a/components/driver/include/driver/ledc.h +++ b/components/driver/include/driver/ledc.h @@ -150,6 +150,8 @@ esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel); * * @param channel LEDC channel(0-7), select from ledc_channel_t * + * @param idle_level Set output idle level after LEDC stops. + * * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error diff --git a/components/driver/include/driver/uart.h b/components/driver/include/driver/uart.h index 906bdcb9e..687ae71aa 100644 --- a/components/driver/include/driver/uart.h +++ b/components/driver/include/driver/uart.h @@ -113,11 +113,11 @@ typedef struct { } uart_event_t; /** - * @brief Set UART data bits. + * @brief Set UART data bits. * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @param data_bit UART data bits + * @param data_bit UART data bits * * @return * - ESP_OK Success @@ -126,9 +126,11 @@ typedef struct { esp_err_t uart_set_word_length(uart_port_t uart_num, uart_word_length_t data_bit); /** - * @brief Get UART data bits. + * @brief Get UART data bits. * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * + * @param data_bit Pointer to accept value of UART data bits. * * @return * - ESP_FAIL Parameter error @@ -137,22 +139,24 @@ esp_err_t uart_set_word_length(uart_port_t uart_num, uart_word_length_t data_bit esp_err_t uart_get_word_length(uart_port_t uart_num, uart_word_length_t* data_bit); /** - * @brief Set UART stop bits. + * @brief Set UART stop bits. * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @param bit_num UART stop bits + * @param bit_num UART stop bits * * @return * - ESP_OK Success * - ESP_FAIL Fail */ -esp_err_t uart_set_stop_bits(uart_port_t uart_no, uart_stop_bits_t bit_num); +esp_err_t uart_set_stop_bits(uart_port_t uart_num, uart_stop_bits_t bit_num); /** - * @brief Set UART stop bits. + * @brief Set UART stop bits. * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * + * @param stop_bit Pointer to accept value of UART stop bits. * * @return * - ESP_FAIL Parameter error @@ -161,22 +165,24 @@ esp_err_t uart_set_stop_bits(uart_port_t uart_no, uart_stop_bits_t bit_num); esp_err_t uart_get_stop_bits(uart_port_t uart_num, uart_stop_bits_t* stop_bit); /** - * @brief Set UART parity. + * @brief Set UART parity. * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @param parity_mode the enum of uart parity configuration + * @param parity_mode the enum of uart parity configuration * * @return * - ESP_FAIL Parameter error * - ESP_OK Success */ -esp_err_t uart_set_parity(uart_port_t uart_no, uart_parity_t parity_mode); +esp_err_t uart_set_parity(uart_port_t uart_num, uart_parity_t parity_mode); /** - * @brief Get UART parity mode. + * @brief Get UART parity mode. * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * + * @param parity_mode Pointer to accept value of UART parity mode. * * @return * - ESP_FAIL Parameter error @@ -186,22 +192,24 @@ esp_err_t uart_set_parity(uart_port_t uart_no, uart_parity_t parity_mode); esp_err_t uart_get_parity(uart_port_t uart_num, uart_parity_t* parity_mode); /** - * @brief Set UART baud rate. + * @brief Set UART baud rate. * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @param baud_rate UART baud-rate. + * @param baud_rate UART baud-rate. * * @return * - ESP_FAIL Parameter error * - ESP_OK Success */ -esp_err_t uart_set_baudrate(uart_port_t uart_no, uint32_t baud_rate); +esp_err_t uart_set_baudrate(uart_port_t uart_num, uint32_t baud_rate); /** - * @brief Get UART bit-rate. + * @brief Get UART bit-rate. * - * @param uart_no: UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * + * @param baudrate Pointer to accept value of UART baud rate * * @return * - ESP_FAIL Parameter error @@ -211,11 +219,11 @@ esp_err_t uart_set_baudrate(uart_port_t uart_no, uint32_t baud_rate); esp_err_t uart_get_baudrate(uart_port_t uart_num, uint32_t* baudrate); /** - * @brief Set UART line inverse mode + * @brief Set UART line inverse mode * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @param inverse_mask Choose the wires that need to be inversed. + * @param Inverse_mask Choose the wires that need to be inversed. * * (inverse_mask should be chosen from UART_INVERSE_RXD/UART_INVERSE_TXD/UART_INVERSE_RTS/UART_INVERSE_CTS, combine with OR-OPERATION) * @@ -223,16 +231,16 @@ esp_err_t uart_get_baudrate(uart_port_t uart_num, uint32_t* baudrate); * - ESP_OK Success * - ESP_FAIL Parameter error */ -esp_err_t uart_set_line_inverse(uart_port_t uart_no, uint32_t inverse_mask); +esp_err_t uart_set_line_inverse(uart_port_t uart_num, uint32_t inverse_mask); /** - * @brief Set hardware flow control. + * @brief Set hardware flow control. * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @param flow_ctrl Hardware flow control mode + * @param flow_ctrl Hardware flow control mode * - * @param rx_thresh Threshold of Hardware RX flow control(0 ~ UART_FIFO_LEN) + * @param rx_thresh Threshold of Hardware RX flow control(0 ~ UART_FIFO_LEN) * * Only when UART_HW_FLOWCTRL_RTS is set , will the rx_thresh value be set. * @@ -240,12 +248,14 @@ esp_err_t uart_set_line_inverse(uart_port_t uart_no, uint32_t inverse_mask); * - ESP_OK Success * - ESP_FAIL Parameter error */ -esp_err_t uart_set_hw_flow_ctrl(uart_port_t uart_no, uart_hw_flowcontrol_t flow_ctrl, uint8_t rx_thresh); +esp_err_t uart_set_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t flow_ctrl, uint8_t rx_thresh); /** - * @brief Get hardware flow control mode + * @brief Get hardware flow control mode * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * + * @param flow_ctrl Option for different flow control mode. * * @return * - ESP_FAIL Parameter error @@ -254,11 +264,11 @@ esp_err_t uart_set_hw_flow_ctrl(uart_port_t uart_no, uart_hw_flowcontrol_t flow_ esp_err_t uart_get_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t* flow_ctrl); /** - * @brief Clear UART interrupt status + * @brief Clear UART interrupt status * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @param clr_mask Bit mask of the status that to be cleared. + * @param clr_mask Bit mask of the status that to be cleared. * * (enable_mask should be chosen from the fields of register UART_INT_CLR_REG) * @@ -269,11 +279,11 @@ esp_err_t uart_get_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t* flo esp_err_t uart_clear_intr_status(uart_port_t uart_num, uint32_t clr_mask); /** - * @brief Set UART interrupt enable + * @brief Set UART interrupt enable * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @param enable_mask Bit mask of the enable bits. + * @param enable_mask Bit mask of the enable bits. * * (enable_mask should be chosen from the fields of register UART_INT_ENA_REG) * @@ -284,11 +294,11 @@ esp_err_t uart_clear_intr_status(uart_port_t uart_num, uint32_t clr_mask); esp_err_t uart_enable_intr_mask(uart_port_t uart_num, uint32_t enable_mask); /** - * @brief Clear UART interrupt enable bits + * @brief Clear UART interrupt enable bits * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @param disable_mask Bit mask of the disable bits. + * @param disable_mask Bit mask of the disable bits. * * (disable_mask should be chosen from the fields of register UART_INT_ENA_REG) * @@ -300,9 +310,9 @@ esp_err_t uart_disable_intr_mask(uart_port_t uart_num, uint32_t disable_mask); /** - * @brief Enable UART RX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT) + * @brief Enable UART RX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT) * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 * * @return * - ESP_OK Success @@ -311,9 +321,9 @@ esp_err_t uart_disable_intr_mask(uart_port_t uart_num, uint32_t disable_mask); esp_err_t uart_enable_rx_intr(uart_port_t uart_num); /** - * @brief Disable UART RX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT) + * @brief Disable UART RX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT) * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 * * @return * - ESP_OK Success @@ -322,9 +332,9 @@ esp_err_t uart_enable_rx_intr(uart_port_t uart_num); esp_err_t uart_disable_rx_intr(uart_port_t uart_num); /** - * @brief Disable UART TX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT) + * @brief Disable UART TX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT) * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 * * @return * - ESP_OK Success @@ -333,13 +343,13 @@ esp_err_t uart_disable_rx_intr(uart_port_t uart_num); esp_err_t uart_disable_tx_intr(uart_port_t uart_num); /** - * @brief Enable UART TX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT) + * @brief Enable UART TX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT) * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @param enable 1: enable; 0: disable + * @param enable 1: enable; 0: disable * - * @param thresh Threshold of TX interrupt, 0 ~ UART_FIFO_LEN + * @param thresh Threshold of TX interrupt, 0 ~ UART_FIFO_LEN * * @return * - ESP_OK Success @@ -348,21 +358,20 @@ esp_err_t uart_disable_tx_intr(uart_port_t uart_num); esp_err_t uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh); /** -* @brief register UART interrupt handler(ISR). +* @brief register UART interrupt handler(ISR). * @note * UART ISR handler will be attached to the same CPU core that this function is running on. * Users should know that which CPU is running and then pick a INUM that is not used by system. * We can find the information of INUM and interrupt level in soc.h. * + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_intr_num UART interrupt number,check the info in soc.h, and please refer to core-isa.h for more details * - * @param uart_intr_num UART interrupt number,check the info in soc.h, and please refer to core-isa.h for more details - * - * @param fn Interrupt handler function. + * @param fn Interrupt handler function. * @attention * The ISR handler function MUST be defined with attribution of "IRAM_ATTR" for now. - * @param arg parameter for handler function + * @param arg parameter for handler function * * @return * - ESP_OK Success @@ -371,21 +380,21 @@ esp_err_t uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh); esp_err_t uart_isr_register(uart_port_t uart_num, uint8_t uart_intr_num, void (*fn)(void*), void * arg); /** - * @brief Set UART pin number + * @brief Set UART pin number * * @note * Internal signal can be output to multiple GPIO pads * Only one GPIO pad can connect with input signal * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @param tx_io_num UART TX pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin. + * @param tx_io_num UART TX pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin. * - * @param rx_io_num UART RX pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin. + * @param rx_io_num UART RX pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin. * - * @param rts_io_num UART RTS pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin. + * @param rts_io_num UART RTS pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin. * - * @param cts_io_num UART CTS pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin. + * @param cts_io_num UART CTS pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin. * * @return * - ESP_OK Success @@ -394,12 +403,12 @@ esp_err_t uart_isr_register(uart_port_t uart_num, uint8_t uart_intr_num, void (* esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int rts_io_num, int cts_io_num); /** - * @brief UART set RTS level (before inverse) + * @brief UART set RTS level (before inverse) * UART rx hardware flow control should not be set. * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @param level 1: RTS output low(active); 0: RTS output high(block) + * @param level 1: RTS output low(active); 0: RTS output high(block) * * @return * - ESP_OK Success @@ -408,11 +417,11 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r esp_err_t uart_set_rts(uart_port_t uart_num, int level); /** - * @brief UART set DTR level (before inverse) + * @brief UART set DTR level (before inverse) * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @param level 1: DTR output low; 0: DTR output high + * @param level 1: DTR output low; 0: DTR output high * * @return * - ESP_OK Success @@ -421,11 +430,11 @@ esp_err_t uart_set_rts(uart_port_t uart_num, int level); esp_err_t uart_set_dtr(uart_port_t uart_num, int level); /** -* @brief UART parameter configure +* @brief UART parameter configure * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @param uart_config UART parameter settings + * @param uart_config UART parameter settings * * @return * - ESP_OK Success @@ -434,11 +443,11 @@ esp_err_t uart_set_dtr(uart_port_t uart_num, int level); esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_config); /** -* @brief UART interrupt configure +* @brief UART interrupt configure * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @param intr_conf UART interrupt settings + * @param intr_conf UART interrupt settings * * @return * - ESP_OK Success @@ -447,25 +456,25 @@ esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_conf esp_err_t uart_intr_config(uart_port_t uart_num, const uart_intr_config_t *intr_conf); /** - * @brief Install UART driver. + * @brief Install UART driver. * * UART ISR handler will be attached to the same CPU core that this function is running on. * Users should know that which CPU is running and then pick a INUM that is not used by system. * We can find the information of INUM and interrupt level in soc.h. * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @param rx_buffer_size UART RX ring buffer size + * @param rx_buffer_size UART RX ring buffer size * - * @param tx_buffer_size UART TX ring buffer size. + * @param tx_buffer_size UART TX ring buffer size. * * If set to zero, driver will not use TX buffer, TX function will block task until all data have been sent out.. * - * @param queue_size UART event queue size/depth. + * @param queue_size UART event queue size/depth. * - * @param uart_intr_num UART interrupt number,check the info in soc.h, and please refer to core-isa.h for more details + * @param uart_intr_num UART interrupt number,check the info in soc.h, and please refer to core-isa.h for more details * - * @param uart_queue UART event queue handle, if set NULL, driver will not use an event queue. + * @param uart_queue UART event queue handle, if set NULL, driver will not use an event queue. * * @return * - ESP_OK Success @@ -474,9 +483,9 @@ esp_err_t uart_intr_config(uart_port_t uart_num, const uart_intr_config_t *intr_ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, int uart_intr_num, void* uart_queue); /** - * @brief Uninstall UART driver. + * @brief Uninstall UART driver. * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 * * @return * - ESP_OK Success @@ -485,11 +494,11 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b esp_err_t uart_driver_delete(uart_port_t uart_num); /** - * @brief Wait UART TX FIFO empty + * @brief Wait UART TX FIFO empty * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @param ticks_to_wait Timeout, count in RTOS ticks + * @param ticks_to_wait Timeout, count in RTOS ticks * * @return * - ESP_OK Success @@ -499,26 +508,25 @@ esp_err_t uart_driver_delete(uart_port_t uart_num); esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait); /** - * @brief Send data to the UART port from a given buffer and length, + * @brief Send data to the UART port from a given buffer and length, * This function will not wait for the space in TX FIFO, just fill the TX FIFO and return when the FIFO is full. * @note * This function should only be used when UART TX buffer is not enabled. * + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param buffer data buffer address * - * @param buffer data buffer address - * - * @param len data length to send + * @param len data length to send * * @return * - (-1) Parameter error * - OTHERS(>=0) The number of data that pushed to the TX FIFO */ -int uart_tx_chars(uart_port_t uart_no, const char* buffer, uint32_t len); +int uart_tx_chars(uart_port_t uart_num, const char* buffer, uint32_t len); /** - * @brief Send data to the UART port from a given buffer and length, + * @brief Send data to the UART port from a given buffer and length, * * If parameter tx_buffer_size is set to zero: * This function will not return until all the data have been sent out, or at least pushed into TX FIFO. @@ -526,11 +534,11 @@ int uart_tx_chars(uart_port_t uart_no, const char* buffer, uint32_t len); * Otherwise, if tx_buffer_size > 0, this function will return after copying all the data to tx ringbuffer, * then, UART ISR will move data from ring buffer to TX FIFO gradually. * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @param src data buffer address + * @param src data buffer address * - * @param size data length to send + * @param size data length to send * * @return * - (-1) Parameter error @@ -539,7 +547,7 @@ int uart_tx_chars(uart_port_t uart_no, const char* buffer, uint32_t len); int uart_write_bytes(uart_port_t uart_num, const char* src, size_t size); /** - * @brief Send data to the UART port from a given buffer and length, + * @brief Send data to the UART port from a given buffer and length, * * If parameter tx_buffer_size is set to zero: * This function will not return until all the data and the break signal have been sent out. @@ -549,15 +557,13 @@ int uart_write_bytes(uart_port_t uart_num, const char* src, size_t size); * then, UART ISR will move data from ring buffer to TX FIFO gradually. * After all data send out, send a break signal. * + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 * + * @param src data buffer address * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param size data length to send * - * @param src data buffer address - * - * @param size data length to send - * - * @param brk_len break signal length (unit: one bit's time@current_baudrate) + * @param brk_len break signal length (unit: time of one data bit at current_baudrate) * * @return * - (-1) Parameter error @@ -567,16 +573,15 @@ int uart_write_bytes(uart_port_t uart_num, const char* src, size_t size); int uart_write_bytes_with_break(uart_port_t uart_num, const char* src, size_t size, int brk_len); /** -* @brief UART read bytes from UART buffer + * @brief UART read bytes from UART buffer * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @param buf pointer to the buffer. + * @param buf pointer to the buffer. * - * @param length data length - * - * @param ticks_to_wait sTimeout, count in RTOS ticks + * @param length data length * + * @param ticks_to_wait sTimeout, count in RTOS ticks * * @return * - (-1) Error @@ -585,9 +590,9 @@ int uart_write_bytes_with_break(uart_port_t uart_num, const char* src, size_t si int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickType_t ticks_to_wait); /** - * @brief UART ring buffer flush + * @brief UART ring buffer flush * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 * * @return * - ESP_OK Success From 656543c5ca9838497da76673ebd408e22d3d3baf Mon Sep 17 00:00:00 2001 From: Dong Heng Date: Wed, 16 Nov 2016 10:46:03 +0800 Subject: [PATCH 13/48] feature/openssl: fixup some insufficient --- examples/09_openssl_client/README.md | 2 +- examples/09_openssl_client/main/component.mk | 5 ----- examples/09_openssl_client/main/openssl_client.c | 7 +++---- examples/10_openssl_server/README.md | 2 +- examples/10_openssl_server/main/component.mk | 5 ----- examples/10_openssl_server/main/openssl_server.c | 7 +++---- 6 files changed, 8 insertions(+), 20 deletions(-) diff --git a/examples/09_openssl_client/README.md b/examples/09_openssl_client/README.md index 85d9575d6..a131cb247 100644 --- a/examples/09_openssl_client/README.md +++ b/examples/09_openssl_client/README.md @@ -6,7 +6,7 @@ First you should config the project by "make menuconfig": Example Configuration -> 1. Target Domain : the domain that you want to connect to, and default is "www.baidu.com". 2. Target port number : the port number of the target domain, and default is 443. - 3. WiFi SSID : you own wifi, which you pc is connected to alse, and default is "myssid". + 3. WiFi SSID : you own wifi, which is connected to the Internet, and default is "myssid". 4. WiFi Password : wifi password, and default is "mypassword" If you want to test the OpenSSL client demo: diff --git a/examples/09_openssl_client/main/component.mk b/examples/09_openssl_client/main/component.mk index 9c21f4a8d..44bd2b527 100644 --- a/examples/09_openssl_client/main/component.mk +++ b/examples/09_openssl_client/main/component.mk @@ -1,8 +1,3 @@ # # Main Makefile. This is basically the same as a component makefile. # -# This Makefile should, at the very least, just include $(IDF_PATH)/make/component_common.mk. By default, -# this will take the sources in the src/ directory, compile them and link them into -# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, -# please read the ESP-IDF documents if you need to do this. -# diff --git a/examples/09_openssl_client/main/openssl_client.c b/examples/09_openssl_client/main/openssl_client.c index 9d4b8b395..890962f5d 100644 --- a/examples/09_openssl_client/main/openssl_client.c +++ b/examples/09_openssl_client/main/openssl_client.c @@ -55,9 +55,10 @@ void openssl_demo_thread(void *p) struct ip4_addr *ip4_addr; int recv_bytes = 0; - char send_data[] = OPENSSL_DEMO_REQUEST; - int send_bytes = sizeof(send_data); char recv_buf[OPENSSL_DEMO_RECV_BUF_LEN]; + + const char send_data[] = OPENSSL_DEMO_REQUEST; + const int send_bytes = sizeof(send_data); ESP_LOGI(TAG, "OpenSSL demo thread start OK"); @@ -171,7 +172,6 @@ static void openssl_client_init(void) { int ret; xTaskHandle openssl_handle; - extern void openssl_demo_thread(void *p); ret = xTaskCreate(openssl_demo_thread, OPENSSL_DEMO_THREAD_NAME, @@ -182,7 +182,6 @@ static void openssl_client_init(void) if (ret != pdPASS) { ESP_LOGI(TAG, "create thread %s failed", OPENSSL_DEMO_THREAD_NAME); - return ; } } diff --git a/examples/10_openssl_server/README.md b/examples/10_openssl_server/README.md index ae5c8da0c..a8c16d4ed 100644 --- a/examples/10_openssl_server/README.md +++ b/examples/10_openssl_server/README.md @@ -4,7 +4,7 @@ The Example contains of OpenSSL server demo. First you should configure the project by "make menuconfig": Example Configuration -> - 1. WiFi SSID: you own wifi that you pc is connected to alse. + 1. WiFi SSID: WiFi network to which your PC is also connected to. 1. WiFi Password: wifi password IF you want to test the OpenSSL server demo: diff --git a/examples/10_openssl_server/main/component.mk b/examples/10_openssl_server/main/component.mk index 4a891d52f..80af01cb5 100644 --- a/examples/10_openssl_server/main/component.mk +++ b/examples/10_openssl_server/main/component.mk @@ -1,11 +1,6 @@ # # Main Makefile. This is basically the same as a component makefile. # -# This Makefile should, at the very least, just include $(IDF_PATH)/make/component_common.mk. By default, -# this will take the sources in the src/ directory, compile them and link them into -# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, -# please read the ESP-IDF documents if you need to do this. -# COMPONENT_EMBED_TXTFILES := cacert.pem COMPONENT_EMBED_TXTFILES += prvtkey.pem diff --git a/examples/10_openssl_server/main/openssl_server.c b/examples/10_openssl_server/main/openssl_server.c index 4fc841ac7..6dc28182d 100644 --- a/examples/10_openssl_server/main/openssl_server.c +++ b/examples/10_openssl_server/main/openssl_server.c @@ -65,10 +65,11 @@ static void openssl_demo_thread(void *p) socklen_t addr_len; struct sockaddr_in sock_addr; - char send_data[] = OPENSSL_DEMO_SERVER_ACK; - int send_bytes = sizeof(send_data); char recv_buf[OPENSSL_DEMO_RECV_BUF_LEN]; + const char send_data[] = OPENSSL_DEMO_SERVER_ACK; + const int send_bytes = sizeof(send_data); + extern const unsigned char cacert_pem_start[] asm("_binary_cacert_pem_start"); extern const unsigned char cacert_pem_end[] asm("_binary_cacert_pem_end"); const unsigned int cacert_pem_bytes = cacert_pem_end - cacert_pem_start; @@ -194,7 +195,6 @@ static void openssl_client_init(void) { int ret; xTaskHandle openssl_handle; - extern void openssl_demo_thread(void *p); ret = xTaskCreate(openssl_demo_thread, OPENSSL_DEMO_THREAD_NAME, @@ -205,7 +205,6 @@ static void openssl_client_init(void) if (ret != pdPASS) { ESP_LOGI(TAG, "create thread %s failed", OPENSSL_DEMO_THREAD_NAME); - return ; } } From 2ed9e2d9a8712df9bf8f00d9d23d6f3522fe6e50 Mon Sep 17 00:00:00 2001 From: Dong Heng Date: Wed, 16 Nov 2016 11:11:01 +0800 Subject: [PATCH 14/48] feature/openssl: fixup the file and code style --- examples/09_openssl_client/README.md | 4 +- .../09_openssl_client/main/openssl_client.c | 464 ++++++++-------- examples/10_openssl_server/README.md | 7 +- .../10_openssl_server/main/openssl_server.c | 510 +++++++++--------- 4 files changed, 489 insertions(+), 496 deletions(-) diff --git a/examples/09_openssl_client/README.md b/examples/09_openssl_client/README.md index a131cb247..2a6ac1988 100644 --- a/examples/09_openssl_client/README.md +++ b/examples/09_openssl_client/README.md @@ -6,8 +6,8 @@ First you should config the project by "make menuconfig": Example Configuration -> 1. Target Domain : the domain that you want to connect to, and default is "www.baidu.com". 2. Target port number : the port number of the target domain, and default is 443. - 3. WiFi SSID : you own wifi, which is connected to the Internet, and default is "myssid". - 4. WiFi Password : wifi password, and default is "mypassword" + 3. WIFI SSID : your own WIFI, which is connected to the Internet, and default is "myssid". + 4. WIFI Password : WIFI password, and default is "mypassword" If you want to test the OpenSSL client demo: 1. compile the code and load the firmware diff --git a/examples/09_openssl_client/main/openssl_client.c b/examples/09_openssl_client/main/openssl_client.c index 890962f5d..c804b6c4f 100644 --- a/examples/09_openssl_client/main/openssl_client.c +++ b/examples/09_openssl_client/main/openssl_client.c @@ -1,234 +1,230 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "openssl_client.h" - -#include - -#include "openssl/ssl.h" - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/event_groups.h" - -#include "esp_types.h" -#include "esp_log.h" -#include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" -#include "esp_log.h" - -#include "nvs_flash.h" -#include "tcpip_adapter.h" - -#include "lwip/sockets.h" -#include "lwip/netdb.h" - -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 static int CONNECTED_BIT = BIT0; - -const static char *TAG = "Openssl_demo"; - -void openssl_demo_thread(void *p) -{ - int ret; - SSL_CTX *ctx; - SSL *ssl; - int socket; - struct sockaddr_in sock_addr; - struct hostent *hp; - struct ip4_addr *ip4_addr; - - int recv_bytes = 0; - char recv_buf[OPENSSL_DEMO_RECV_BUF_LEN]; - - const char send_data[] = OPENSSL_DEMO_REQUEST; - const int send_bytes = sizeof(send_data); - - ESP_LOGI(TAG, "OpenSSL demo thread start OK"); - - ESP_LOGI(TAG, "get target IP address"); - hp = gethostbyname(OPENSSL_DEMO_TARGET_NAME); - if (!hp) { - ESP_LOGI(TAG, "failed"); - goto failed1; - } - ESP_LOGI(TAG, "OK"); - - ip4_addr = (struct ip4_addr *)hp->h_addr; - ESP_LOGI(TAG, IPSTR, IP2STR(ip4_addr)); - - ESP_LOGI(TAG, "create SSL context ......"); - ctx = SSL_CTX_new(TLSv1_1_client_method()); - if (!ctx) { - ESP_LOGI(TAG, "failed"); - goto failed1; - } - ESP_LOGI(TAG, "OK"); - - ESP_LOGI(TAG, "create socket ......"); - socket = socket(AF_INET, SOCK_STREAM, 0); - if (socket < 0) { - ESP_LOGI(TAG, "failed"); - goto failed2; - } - ESP_LOGI(TAG, "OK"); - - ESP_LOGI(TAG, "bind socket ......"); - memset(&sock_addr, 0, sizeof(sock_addr)); - sock_addr.sin_family = AF_INET; - sock_addr.sin_addr.s_addr = 0; - sock_addr.sin_port = htons(OPENSSL_DEMO_LOCAL_TCP_PORT); - ret = bind(socket, (struct sockaddr*)&sock_addr, sizeof(sock_addr)); - if (ret) { - ESP_LOGI(TAG, "failed"); - goto failed3; - } - ESP_LOGI(TAG, "OK"); - - ESP_LOGI(TAG, "socket connect to remote %s ......", OPENSSL_DEMO_TARGET_NAME); - memset(&sock_addr, 0, sizeof(sock_addr)); - sock_addr.sin_family = AF_INET; - sock_addr.sin_addr.s_addr = ip4_addr->addr; - sock_addr.sin_port = htons(OPENSSL_DEMO_TARGET_TCP_PORT); - ret = connect(socket, (struct sockaddr*)&sock_addr, sizeof(sock_addr)); - if (ret) { - ESP_LOGI(TAG, "failed"); - goto failed3; - } - ESP_LOGI(TAG, "OK"); - - ESP_LOGI(TAG, "create SSL ......"); - ssl = SSL_new(ctx); - if (!ssl) { - ESP_LOGI(TAG, "failed"); - goto failed3; - } - ESP_LOGI(TAG, "OK"); - - SSL_set_fd(ssl, socket); - - ESP_LOGI(TAG, "SSL connected to %s port %d ......", - OPENSSL_DEMO_TARGET_NAME, OPENSSL_DEMO_TARGET_TCP_PORT); - ret = SSL_connect(ssl); - if (!ret) { - ESP_LOGI(TAG, "failed " ); - goto failed4; - } - ESP_LOGI(TAG, "OK"); - - ESP_LOGI(TAG, "send https request to %s port %d ......", - OPENSSL_DEMO_TARGET_NAME, OPENSSL_DEMO_TARGET_TCP_PORT); - ret = SSL_write(ssl, send_data, send_bytes); - if (ret <= 0) { - ESP_LOGI(TAG, "failed"); - goto failed5; - } - ESP_LOGI(TAG, "OK"); - - do { - ret = SSL_read(ssl, recv_buf, OPENSSL_DEMO_RECV_BUF_LEN - 1); - if (ret <= 0) { - break; - } - recv_bytes += ret; - ESP_LOGI(TAG, "%s", recv_buf); - } while (1); - - ESP_LOGI(TAG, "totaly read %d bytes data from %s ......", recv_bytes, OPENSSL_DEMO_TARGET_NAME); - -failed5: - SSL_shutdown(ssl); -failed4: - SSL_free(ssl); - ssl = NULL; -failed3: - close(socket); - socket = -1; -failed2: - SSL_CTX_free(ctx); - ctx = NULL; -failed1: - vTaskDelete(NULL); - return ; -} - -static void openssl_client_init(void) -{ - int ret; - xTaskHandle openssl_handle; - - ret = xTaskCreate(openssl_demo_thread, - OPENSSL_DEMO_THREAD_NAME, - OPENSSL_DEMO_THREAD_STACK_WORDS, - NULL, - OPENSSL_DEMO_THREAD_PRORIOTY, - &openssl_handle); - - if (ret != pdPASS) { - ESP_LOGI(TAG, "create thread %s failed", OPENSSL_DEMO_THREAD_NAME); - } -} - -static esp_err_t wifi_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); - openssl_client_init(); - 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 wifi_conn_init(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(wifi_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_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) ); - ESP_LOGI(TAG, "start the WIFI SSID:[%s] password:[%s]\n", EXAMPLE_WIFI_SSID, EXAMPLE_WIFI_PASS); - ESP_ERROR_CHECK( esp_wifi_start() ); -} - -void app_main(void) -{ - nvs_flash_init(); - wifi_conn_init(); -} +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "openssl_client.h" + +#include + +#include "openssl/ssl.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" + +#include "esp_log.h" +#include "esp_wifi.h" +#include "esp_event_loop.h" + +#include "nvs_flash.h" + +#include "lwip/sockets.h" +#include "lwip/netdb.h" + +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 static int CONNECTED_BIT = BIT0; + +const static char *TAG = "Openssl_demo"; + +void openssl_demo_thread(void *p) +{ + int ret; + SSL_CTX *ctx; + SSL *ssl; + int socket; + struct sockaddr_in sock_addr; + struct hostent *hp; + struct ip4_addr *ip4_addr; + + int recv_bytes = 0; + char recv_buf[OPENSSL_DEMO_RECV_BUF_LEN]; + + const char send_data[] = OPENSSL_DEMO_REQUEST; + const int send_bytes = sizeof(send_data); + + ESP_LOGI(TAG, "OpenSSL demo thread start OK"); + + ESP_LOGI(TAG, "get target IP address"); + hp = gethostbyname(OPENSSL_DEMO_TARGET_NAME); + if (!hp) { + ESP_LOGI(TAG, "failed"); + goto failed1; + } + ESP_LOGI(TAG, "OK"); + + ip4_addr = (struct ip4_addr *)hp->h_addr; + ESP_LOGI(TAG, IPSTR, IP2STR(ip4_addr)); + + ESP_LOGI(TAG, "create SSL context ......"); + ctx = SSL_CTX_new(TLSv1_1_client_method()); + if (!ctx) { + ESP_LOGI(TAG, "failed"); + goto failed1; + } + ESP_LOGI(TAG, "OK"); + + ESP_LOGI(TAG, "create socket ......"); + socket = socket(AF_INET, SOCK_STREAM, 0); + if (socket < 0) { + ESP_LOGI(TAG, "failed"); + goto failed2; + } + ESP_LOGI(TAG, "OK"); + + ESP_LOGI(TAG, "bind socket ......"); + memset(&sock_addr, 0, sizeof(sock_addr)); + sock_addr.sin_family = AF_INET; + sock_addr.sin_addr.s_addr = 0; + sock_addr.sin_port = htons(OPENSSL_DEMO_LOCAL_TCP_PORT); + ret = bind(socket, (struct sockaddr*)&sock_addr, sizeof(sock_addr)); + if (ret) { + ESP_LOGI(TAG, "failed"); + goto failed3; + } + ESP_LOGI(TAG, "OK"); + + ESP_LOGI(TAG, "socket connect to remote %s ......", OPENSSL_DEMO_TARGET_NAME); + memset(&sock_addr, 0, sizeof(sock_addr)); + sock_addr.sin_family = AF_INET; + sock_addr.sin_addr.s_addr = ip4_addr->addr; + sock_addr.sin_port = htons(OPENSSL_DEMO_TARGET_TCP_PORT); + ret = connect(socket, (struct sockaddr*)&sock_addr, sizeof(sock_addr)); + if (ret) { + ESP_LOGI(TAG, "failed"); + goto failed3; + } + ESP_LOGI(TAG, "OK"); + + ESP_LOGI(TAG, "create SSL ......"); + ssl = SSL_new(ctx); + if (!ssl) { + ESP_LOGI(TAG, "failed"); + goto failed3; + } + ESP_LOGI(TAG, "OK"); + + SSL_set_fd(ssl, socket); + + ESP_LOGI(TAG, "SSL connected to %s port %d ......", + OPENSSL_DEMO_TARGET_NAME, OPENSSL_DEMO_TARGET_TCP_PORT); + ret = SSL_connect(ssl); + if (!ret) { + ESP_LOGI(TAG, "failed " ); + goto failed4; + } + ESP_LOGI(TAG, "OK"); + + ESP_LOGI(TAG, "send https request to %s port %d ......", + OPENSSL_DEMO_TARGET_NAME, OPENSSL_DEMO_TARGET_TCP_PORT); + ret = SSL_write(ssl, send_data, send_bytes); + if (ret <= 0) { + ESP_LOGI(TAG, "failed"); + goto failed5; + } + ESP_LOGI(TAG, "OK"); + + do { + ret = SSL_read(ssl, recv_buf, OPENSSL_DEMO_RECV_BUF_LEN - 1); + if (ret <= 0) { + break; + } + recv_bytes += ret; + ESP_LOGI(TAG, "%s", recv_buf); + } while (1); + + ESP_LOGI(TAG, "totaly read %d bytes data from %s ......", recv_bytes, OPENSSL_DEMO_TARGET_NAME); + +failed5: + SSL_shutdown(ssl); +failed4: + SSL_free(ssl); + ssl = NULL; +failed3: + close(socket); + socket = -1; +failed2: + SSL_CTX_free(ctx); + ctx = NULL; +failed1: + vTaskDelete(NULL); + return ; +} + +static void openssl_client_init(void) +{ + int ret; + xTaskHandle openssl_handle; + + ret = xTaskCreate(openssl_demo_thread, + OPENSSL_DEMO_THREAD_NAME, + OPENSSL_DEMO_THREAD_STACK_WORDS, + NULL, + OPENSSL_DEMO_THREAD_PRORIOTY, + &openssl_handle); + + if (ret != pdPASS) { + ESP_LOGI(TAG, "create thread %s failed", OPENSSL_DEMO_THREAD_NAME); + } +} + +static esp_err_t wifi_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); + openssl_client_init(); + 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 wifi_conn_init(void) +{ + tcpip_adapter_init(); + wifi_event_group = xEventGroupCreate(); + ESP_ERROR_CHECK( esp_event_loop_init(wifi_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_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); + ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) ); + ESP_LOGI(TAG, "start the WIFI SSID:[%s] password:[%s]\n", EXAMPLE_WIFI_SSID, EXAMPLE_WIFI_PASS); + ESP_ERROR_CHECK( esp_wifi_start() ); +} + +void app_main(void) +{ + nvs_flash_init(); + wifi_conn_init(); +} diff --git a/examples/10_openssl_server/README.md b/examples/10_openssl_server/README.md index a8c16d4ed..333cb3d6a 100644 --- a/examples/10_openssl_server/README.md +++ b/examples/10_openssl_server/README.md @@ -4,8 +4,8 @@ The Example contains of OpenSSL server demo. First you should configure the project by "make menuconfig": Example Configuration -> - 1. WiFi SSID: WiFi network to which your PC is also connected to. - 1. WiFi Password: wifi password + 1. WIFI SSID: WIFI network to which your PC is also connected to. + 1. WIFI Password: WIFI password IF you want to test the OpenSSL server demo: 1. compile the code and load the firmware @@ -15,6 +15,7 @@ IF you want to test the OpenSSL server demo: Note: The private key and certification at the example are not trusted by web browser, because they are not created by CA official, just by ourselves. - You can alse create your own private key and ceritification by "openssl at ubuntu or others". + You can alse create your own private key and ceritification by "openssl at ubuntu or others". + We have the document of "ESP8266_SDKSSL_User_Manual_EN_v1.4.pdf" at "http://www.espressif.com/en/support/download/documents". By it you can gernerate the private key and certification with the fomate of ".pem" See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/10_openssl_server/main/openssl_server.c b/examples/10_openssl_server/main/openssl_server.c index 6dc28182d..7f4b7d6b6 100644 --- a/examples/10_openssl_server/main/openssl_server.c +++ b/examples/10_openssl_server/main/openssl_server.c @@ -1,257 +1,253 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "openssl_server.h" - -#include - -#include "openssl/ssl.h" - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/event_groups.h" - -#include "esp_types.h" -#include "esp_log.h" -#include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" -#include "esp_log.h" - -#include "nvs_flash.h" -#include "tcpip_adapter.h" - -#include "lwip/sockets.h" -#include "lwip/netdb.h" - -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 static int CONNECTED_BIT = BIT0; - -const static char *TAG = "Openssl_demo"; - -#define OPENSSL_DEMO_SERVER_ACK "HTTP/1.1 200 OK\r\n" \ - "Content-Type: text/html\r\n" \ - "Content-Length: 98\r\n" \ - "\r\n" \ - "\r\n" \ - "OpenSSL demo\r\n" \ - "OpenSSL server demo!\r\n" \ - "\r\n" \ - "\r\n" - -static void openssl_demo_thread(void *p) -{ - int ret; - - SSL_CTX *ctx; - SSL *ssl; - - int socket, new_socket; - socklen_t addr_len; - struct sockaddr_in sock_addr; - - char recv_buf[OPENSSL_DEMO_RECV_BUF_LEN]; - - const char send_data[] = OPENSSL_DEMO_SERVER_ACK; - const int send_bytes = sizeof(send_data); - - extern const unsigned char cacert_pem_start[] asm("_binary_cacert_pem_start"); - extern const unsigned char cacert_pem_end[] asm("_binary_cacert_pem_end"); - const unsigned int cacert_pem_bytes = cacert_pem_end - cacert_pem_start; - - extern const unsigned char prvtkey_pem_start[] asm("_binary_prvtkey_pem_start"); - extern const unsigned char prvtkey_pem_end[] asm("_binary_prvtkey_pem_end"); - const unsigned int prvtkey_pem_bytes = prvtkey_pem_end - prvtkey_pem_start; - - ESP_LOGI(TAG, "SSL server context create ......"); - ctx = SSL_CTX_new(SSLv3_server_method()); - if (!ctx) { - ESP_LOGI(TAG, "failed"); - goto failed1; - } - ESP_LOGI(TAG, "OK"); - - ESP_LOGI(TAG, "SSL server context set own certification......"); - ret = SSL_CTX_use_certificate_ASN1(ctx, cacert_pem_bytes, cacert_pem_start); - if (!ret) { - ESP_LOGI(TAG, "failed"); - goto failed2; - } - ESP_LOGI(TAG, "OK"); - - ESP_LOGI(TAG, "SSL server context set private key......"); - ret = SSL_CTX_use_PrivateKey_ASN1(0, ctx, prvtkey_pem_start, prvtkey_pem_bytes); - if (!ret) { - ESP_LOGI(TAG, "failed"); - goto failed2; - } - ESP_LOGI(TAG, "OK"); - - ESP_LOGI(TAG, "SSL server create socket ......"); - socket = socket(AF_INET, SOCK_STREAM, 0); - if (socket < 0) { - ESP_LOGI(TAG, "failed"); - goto failed2; - } - ESP_LOGI(TAG, "OK"); - - ESP_LOGI(TAG, "SSL server socket bind ......"); - memset(&sock_addr, 0, sizeof(sock_addr)); - sock_addr.sin_family = AF_INET; - sock_addr.sin_addr.s_addr = 0; - sock_addr.sin_port = htons(OPENSSL_DEMO_LOCAL_TCP_PORT); - ret = bind(socket, (struct sockaddr*)&sock_addr, sizeof(sock_addr)); - if (ret) { - ESP_LOGI(TAG, "failed"); - goto failed3; - } - ESP_LOGI(TAG, "OK"); - - ESP_LOGI(TAG, "SSL server socket listen ......"); - ret = listen(socket, 32); - if (ret) { - ESP_LOGI(TAG, "failed"); - goto failed3; - } - ESP_LOGI(TAG, "OK"); - -reconnect: - ESP_LOGI(TAG, "SSL server create ......"); - ssl = SSL_new(ctx); - if (!ssl) { - ESP_LOGI(TAG, "failed"); - goto failed3; - } - ESP_LOGI(TAG, "OK"); - - ESP_LOGI(TAG, "SSL server socket accept client ......"); - new_socket = accept(socket, (struct sockaddr *)&sock_addr, &addr_len); - if (new_socket < 0) { - ESP_LOGI(TAG, "failed" ); - goto failed4; - } - ESP_LOGI(TAG, "OK"); - - SSL_set_fd(ssl, new_socket); - - ESP_LOGI(TAG, "SSL server accept client ......"); - ret = SSL_accept(ssl); - if (!ret) { - ESP_LOGI(TAG, "failed"); - goto failed5; - } - ESP_LOGI(TAG, "OK"); - - ESP_LOGI(TAG, "SSL server read message ......"); - do { - memset(recv_buf, 0, OPENSSL_DEMO_RECV_BUF_LEN); - ret = SSL_read(ssl, recv_buf, OPENSSL_DEMO_RECV_BUF_LEN - 1); - if (ret <= 0) { - break; - } - if (strstr(recv_buf, "GET / HTTP/1.1")) { - SSL_write(ssl, send_data, send_bytes); - break; - } - } while (1); - - ESP_LOGI(TAG, "result %d", ret); - - SSL_shutdown(ssl); -failed5: - close(new_socket); - new_socket = -1; -failed4: - SSL_free(ssl); - ssl = NULL; - goto reconnect; -failed3: - close(socket); - socket = -1; -failed2: - SSL_CTX_free(ctx); - ctx = NULL; -failed1: - vTaskDelete(NULL); - return ; -} - -static void openssl_client_init(void) -{ - int ret; - xTaskHandle openssl_handle; - - ret = xTaskCreate(openssl_demo_thread, - OPENSSL_DEMO_THREAD_NAME, - OPENSSL_DEMO_THREAD_STACK_WORDS, - NULL, - OPENSSL_DEMO_THREAD_PRORIOTY, - &openssl_handle); - - if (ret != pdPASS) { - ESP_LOGI(TAG, "create thread %s failed", OPENSSL_DEMO_THREAD_NAME); - } -} - -static esp_err_t wifi_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); - openssl_client_init(); - 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 wifi_conn_init(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(wifi_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_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) ); - ESP_LOGI(TAG, "start the WIFI SSID:[%s] password:[%s]\n", EXAMPLE_WIFI_SSID, EXAMPLE_WIFI_PASS); - ESP_ERROR_CHECK( esp_wifi_start() ); -} - -void app_main(void) -{ - nvs_flash_init(); - wifi_conn_init(); -} +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "openssl_server.h" + +#include + +#include "openssl/ssl.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" + +#include "esp_log.h" +#include "esp_wifi.h" +#include "esp_event_loop.h" + +#include "nvs_flash.h" + +#include "lwip/sockets.h" +#include "lwip/netdb.h" + +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 static int CONNECTED_BIT = BIT0; + +const static char *TAG = "Openssl_demo"; + +#define OPENSSL_DEMO_SERVER_ACK "HTTP/1.1 200 OK\r\n" \ + "Content-Type: text/html\r\n" \ + "Content-Length: 98\r\n" \ + "\r\n" \ + "\r\n" \ + "OpenSSL demo\r\n" \ + "OpenSSL server demo!\r\n" \ + "\r\n" \ + "\r\n" + +static void openssl_demo_thread(void *p) +{ + int ret; + + SSL_CTX *ctx; + SSL *ssl; + + int socket, new_socket; + socklen_t addr_len; + struct sockaddr_in sock_addr; + + char recv_buf[OPENSSL_DEMO_RECV_BUF_LEN]; + + const char send_data[] = OPENSSL_DEMO_SERVER_ACK; + const int send_bytes = sizeof(send_data); + + extern const unsigned char cacert_pem_start[] asm("_binary_cacert_pem_start"); + extern const unsigned char cacert_pem_end[] asm("_binary_cacert_pem_end"); + const unsigned int cacert_pem_bytes = cacert_pem_end - cacert_pem_start; + + extern const unsigned char prvtkey_pem_start[] asm("_binary_prvtkey_pem_start"); + extern const unsigned char prvtkey_pem_end[] asm("_binary_prvtkey_pem_end"); + const unsigned int prvtkey_pem_bytes = prvtkey_pem_end - prvtkey_pem_start; + + ESP_LOGI(TAG, "SSL server context create ......"); + ctx = SSL_CTX_new(SSLv3_server_method()); + if (!ctx) { + ESP_LOGI(TAG, "failed"); + goto failed1; + } + ESP_LOGI(TAG, "OK"); + + ESP_LOGI(TAG, "SSL server context set own certification......"); + ret = SSL_CTX_use_certificate_ASN1(ctx, cacert_pem_bytes, cacert_pem_start); + if (!ret) { + ESP_LOGI(TAG, "failed"); + goto failed2; + } + ESP_LOGI(TAG, "OK"); + + ESP_LOGI(TAG, "SSL server context set private key......"); + ret = SSL_CTX_use_PrivateKey_ASN1(0, ctx, prvtkey_pem_start, prvtkey_pem_bytes); + if (!ret) { + ESP_LOGI(TAG, "failed"); + goto failed2; + } + ESP_LOGI(TAG, "OK"); + + ESP_LOGI(TAG, "SSL server create socket ......"); + socket = socket(AF_INET, SOCK_STREAM, 0); + if (socket < 0) { + ESP_LOGI(TAG, "failed"); + goto failed2; + } + ESP_LOGI(TAG, "OK"); + + ESP_LOGI(TAG, "SSL server socket bind ......"); + memset(&sock_addr, 0, sizeof(sock_addr)); + sock_addr.sin_family = AF_INET; + sock_addr.sin_addr.s_addr = 0; + sock_addr.sin_port = htons(OPENSSL_DEMO_LOCAL_TCP_PORT); + ret = bind(socket, (struct sockaddr*)&sock_addr, sizeof(sock_addr)); + if (ret) { + ESP_LOGI(TAG, "failed"); + goto failed3; + } + ESP_LOGI(TAG, "OK"); + + ESP_LOGI(TAG, "SSL server socket listen ......"); + ret = listen(socket, 32); + if (ret) { + ESP_LOGI(TAG, "failed"); + goto failed3; + } + ESP_LOGI(TAG, "OK"); + +reconnect: + ESP_LOGI(TAG, "SSL server create ......"); + ssl = SSL_new(ctx); + if (!ssl) { + ESP_LOGI(TAG, "failed"); + goto failed3; + } + ESP_LOGI(TAG, "OK"); + + ESP_LOGI(TAG, "SSL server socket accept client ......"); + new_socket = accept(socket, (struct sockaddr *)&sock_addr, &addr_len); + if (new_socket < 0) { + ESP_LOGI(TAG, "failed" ); + goto failed4; + } + ESP_LOGI(TAG, "OK"); + + SSL_set_fd(ssl, new_socket); + + ESP_LOGI(TAG, "SSL server accept client ......"); + ret = SSL_accept(ssl); + if (!ret) { + ESP_LOGI(TAG, "failed"); + goto failed5; + } + ESP_LOGI(TAG, "OK"); + + ESP_LOGI(TAG, "SSL server read message ......"); + do { + memset(recv_buf, 0, OPENSSL_DEMO_RECV_BUF_LEN); + ret = SSL_read(ssl, recv_buf, OPENSSL_DEMO_RECV_BUF_LEN - 1); + if (ret <= 0) { + break; + } + if (strstr(recv_buf, "GET / HTTP/1.1")) { + SSL_write(ssl, send_data, send_bytes); + break; + } + } while (1); + + ESP_LOGI(TAG, "result %d", ret); + + SSL_shutdown(ssl); +failed5: + close(new_socket); + new_socket = -1; +failed4: + SSL_free(ssl); + ssl = NULL; + goto reconnect; +failed3: + close(socket); + socket = -1; +failed2: + SSL_CTX_free(ctx); + ctx = NULL; +failed1: + vTaskDelete(NULL); + return ; +} + +static void openssl_client_init(void) +{ + int ret; + xTaskHandle openssl_handle; + + ret = xTaskCreate(openssl_demo_thread, + OPENSSL_DEMO_THREAD_NAME, + OPENSSL_DEMO_THREAD_STACK_WORDS, + NULL, + OPENSSL_DEMO_THREAD_PRORIOTY, + &openssl_handle); + + if (ret != pdPASS) { + ESP_LOGI(TAG, "create thread %s failed", OPENSSL_DEMO_THREAD_NAME); + } +} + +static esp_err_t wifi_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); + openssl_client_init(); + 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 wifi_conn_init(void) +{ + tcpip_adapter_init(); + wifi_event_group = xEventGroupCreate(); + ESP_ERROR_CHECK( esp_event_loop_init(wifi_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_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); + ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) ); + ESP_LOGI(TAG, "start the WIFI SSID:[%s] password:[%s]\n", EXAMPLE_WIFI_SSID, EXAMPLE_WIFI_PASS); + ESP_ERROR_CHECK( esp_wifi_start() ); +} + +void app_main(void) +{ + nvs_flash_init(); + wifi_conn_init(); +} From 9ae07082ff97ed712a4ee99c38c3a8d874454c17 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 16 Nov 2016 14:20:47 +1100 Subject: [PATCH 15/48] examples: Update component.mk for new conventions --- examples/01_hello_world/main/component.mk | 2 +- examples/02_blink/main/component.mk | 2 +- examples/03_http_request/main/component.mk | 2 +- examples/04_https_request/main/component.mk | 2 +- examples/05_ble_adv/main/component.mk | 2 +- examples/06_sntp/main/component.mk | 2 +- examples/07_nvs_rw_value/main/component.mk | 5 ++++- examples/08_nvs_rw_blob/main/component.mk | 5 ++++- 8 files changed, 14 insertions(+), 8 deletions(-) diff --git a/examples/01_hello_world/main/component.mk b/examples/01_hello_world/main/component.mk index 4d3b30caf..0b9d7585e 100644 --- a/examples/01_hello_world/main/component.mk +++ b/examples/01_hello_world/main/component.mk @@ -1,5 +1,5 @@ # -# Main Makefile. This is basically the same as a component makefile. +# "main" pseudo-component makefile. # # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) diff --git a/examples/02_blink/main/component.mk b/examples/02_blink/main/component.mk index b4fa72791..a98f634ea 100644 --- a/examples/02_blink/main/component.mk +++ b/examples/02_blink/main/component.mk @@ -1,4 +1,4 @@ # -# Main Makefile. This is basically the same as a component makefile. +# "main" pseudo-component makefile. # # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) diff --git a/examples/03_http_request/main/component.mk b/examples/03_http_request/main/component.mk index b4fa72791..a98f634ea 100644 --- a/examples/03_http_request/main/component.mk +++ b/examples/03_http_request/main/component.mk @@ -1,4 +1,4 @@ # -# Main Makefile. This is basically the same as a component makefile. +# "main" pseudo-component makefile. # # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) diff --git a/examples/04_https_request/main/component.mk b/examples/04_https_request/main/component.mk index f4502c25d..818e2a182 100644 --- a/examples/04_https_request/main/component.mk +++ b/examples/04_https_request/main/component.mk @@ -1,5 +1,5 @@ # -# Main Makefile. This is basically the same as a component makefile. +# "main" pseudo-component makefile. # # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) diff --git a/examples/05_ble_adv/main/component.mk b/examples/05_ble_adv/main/component.mk index b4fa72791..a98f634ea 100644 --- a/examples/05_ble_adv/main/component.mk +++ b/examples/05_ble_adv/main/component.mk @@ -1,4 +1,4 @@ # -# Main Makefile. This is basically the same as a component makefile. +# "main" pseudo-component makefile. # # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) diff --git a/examples/06_sntp/main/component.mk b/examples/06_sntp/main/component.mk index b4fa72791..a98f634ea 100644 --- a/examples/06_sntp/main/component.mk +++ b/examples/06_sntp/main/component.mk @@ -1,4 +1,4 @@ # -# Main Makefile. This is basically the same as a component makefile. +# "main" pseudo-component makefile. # # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) diff --git a/examples/07_nvs_rw_value/main/component.mk b/examples/07_nvs_rw_value/main/component.mk index d33485c26..0b9d7585e 100644 --- a/examples/07_nvs_rw_value/main/component.mk +++ b/examples/07_nvs_rw_value/main/component.mk @@ -1,2 +1,5 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) -include $(IDF_PATH)/make/component_common.mk diff --git a/examples/08_nvs_rw_blob/main/component.mk b/examples/08_nvs_rw_blob/main/component.mk index d33485c26..0b9d7585e 100644 --- a/examples/08_nvs_rw_blob/main/component.mk +++ b/examples/08_nvs_rw_blob/main/component.mk @@ -1,2 +1,5 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) -include $(IDF_PATH)/make/component_common.mk From 60f29236f607c81929c391da263e10f2cc495063 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 16 Nov 2016 15:42:38 +1100 Subject: [PATCH 16/48] Build system: Raise warning level Default esp-idf builds now show -Wextra warnings (except for a few: signed/unsigned comparison, unused parameters, old-style C declarations.) CI building of examples runs with that level raised to -Werror, to catch those changes going into the main repo. --- .../bootloader_support/src/esp_image_format.c | 2 +- .../src/secure_boot_signatures.c | 7 ++- components/expat/port/minicheck.c | 63 ++++++++++--------- components/freertos/ringbuf.c | 4 +- components/freertos/tasks.c | 4 +- make/build_examples.sh | 9 ++- make/project.mk | 16 +++-- 7 files changed, 58 insertions(+), 47 deletions(-) diff --git a/components/bootloader_support/src/esp_image_format.c b/components/bootloader_support/src/esp_image_format.c index 42a3e4ffe..ca75f6ae4 100644 --- a/components/bootloader_support/src/esp_image_format.c +++ b/components/bootloader_support/src/esp_image_format.c @@ -17,7 +17,7 @@ #include #include -const static char *TAG = "esp_image"; +static const char *TAG = "esp_image"; #define SIXTEEN_MB 0x1000000 #define ESP_ROM_CHECKSUM_INITIAL 0xEF diff --git a/components/bootloader_support/src/secure_boot_signatures.c b/components/bootloader_support/src/secure_boot_signatures.c index 6d47651b2..f7e435e86 100644 --- a/components/bootloader_support/src/secure_boot_signatures.c +++ b/components/bootloader_support/src/secure_boot_signatures.c @@ -45,10 +45,13 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length) sha_context sha; uint8_t digest[32]; ptrdiff_t keylen; - const uint8_t *data, *digest_data; - uint32_t digest_len; + const uint8_t *data; const signature_block_t *sigblock; bool is_valid; +#ifdef BOOTLOADER_BUILD + const uint8_t *digest_data; + uint32_t digest_len; +#endif ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length); diff --git a/components/expat/port/minicheck.c b/components/expat/port/minicheck.c index 5a1f5ed0e..95a4939bd 100644 --- a/components/expat/port/minicheck.c +++ b/components/expat/port/minicheck.c @@ -108,44 +108,45 @@ add_failure(SRunner *runner, int verbosity) } } +static void run_test(SRunner *runner, int verbosity, TCase *tc, int i) +{ + if (tc->setup != NULL) { + /* setup */ + if (setjmp(env)) { + add_failure(runner, verbosity); + return; + } + tc->setup(); + } + /* test */ + if (setjmp(env)) { + add_failure(runner, verbosity); + return; + } + (tc->tests[i])(); + + /* teardown */ + if (tc->teardown != NULL) { + if (setjmp(env)) { + add_failure(runner, verbosity); + return; + } + tc->teardown(); + } +} + void srunner_run_all(SRunner *runner, int verbosity) { - Suite *suite; - TCase *tc; assert(runner != NULL); - suite = runner->suite; - tc = suite->tests; + assert(runner->suite != NULL); + TCase *tc = runner->suite->tests; while (tc != NULL) { - int i; - for (i = 0; i < tc->ntests; ++i) { + for (int i = 0; i < tc->ntests; ++i) { runner->nchecks++; - - if (tc->setup != NULL) { - /* setup */ - if (setjmp(env)) { - add_failure(runner, verbosity); - continue; - } - tc->setup(); - } - /* test */ - if (setjmp(env)) { - add_failure(runner, verbosity); - continue; - } - (tc->tests[i])(); - - /* teardown */ - if (tc->teardown != NULL) { - if (setjmp(env)) { - add_failure(runner, verbosity); - continue; - } - tc->teardown(); - } + run_test(runner, verbosity, tc, i); + tc = tc->next_tcase; } - tc = tc->next_tcase; } if (verbosity) { int passed = runner->nchecks - runner->nfailures; diff --git a/components/freertos/ringbuf.c b/components/freertos/ringbuf.c index a4205d88d..062c52023 100644 --- a/components/freertos/ringbuf.c +++ b/components/freertos/ringbuf.c @@ -495,8 +495,8 @@ BaseType_t xRingbufferSend(RingbufHandle_t ringbuf, void *data, size_t dataSize, //we will need to wait some more. ticks_to_wait = ticks_end - xTaskGetTickCount(); } - } while (ringbufferFreeMem(rb) < needed_size && ticks_to_wait>=0); - + } while (ringbufferFreeMem(rb) < needed_size && ticks_end >= xTaskGetTickCount()); + //Lock the mux in order to make sure no one else is messing with the ringbuffer and do the copy. portENTER_CRITICAL(&rb->mux); //Another thread may have been able to sneak its write first. Check again now we locked the ringbuff, and retry diff --git a/components/freertos/tasks.c b/components/freertos/tasks.c index 88aa8d3ef..26103ee23 100644 --- a/components/freertos/tasks.c +++ b/components/freertos/tasks.c @@ -2704,7 +2704,7 @@ void vTaskSwitchContext( void ) taskENTER_CRITICAL_ISR(&xTaskQueueMutex); unsigned portBASE_TYPE foundNonExecutingWaiter = pdFALSE, ableToSchedule = pdFALSE, resetListHead; - unsigned portBASE_TYPE uxDynamicTopReady = uxTopReadyPriority; + portBASE_TYPE uxDynamicTopReady = uxTopReadyPriority; unsigned portBASE_TYPE holdTop=pdFALSE; /* @@ -2717,8 +2717,6 @@ void vTaskSwitchContext( void ) while ( ableToSchedule == pdFALSE && uxDynamicTopReady >= 0 ) { - configASSERT( uxTopReadyPriority>=0 ); - configASSERT( uxDynamicTopReady>=0 ); resetListHead = pdFALSE; // Nothing to do for empty lists if (!listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxDynamicTopReady ] ) )) { diff --git a/make/build_examples.sh b/make/build_examples.sh index a522666a9..8345dab50 100755 --- a/make/build_examples.sh +++ b/make/build_examples.sh @@ -20,8 +20,13 @@ for example in ${IDF_PATH}/examples/*; do mkdir ${EXAMPLE_NUM} cp -r ${example} ${EXAMPLE_NUM} pushd ${EXAMPLE_NUM}/`basename ${example}` - # build non-verbose first, only build verbose if there's an error - make defconfig all || (RESULT=$?; make V=1) + + # be stricter in the CI build than the default IDF settings + export EXTRA_CFLAGS="-Werror -Werror=deprecated-declarations" + export EXTRA_CXXFLAGS=${EXTRA_CFLAGS} + + # build non-verbose first, only build verbose if there's an error + (make clean defconfig && make all ) || (RESULT=$?; make V=1) popd EXAMPLE_NUM=$(( $EXAMPLE_NUM + 1 )) done diff --git a/make/project.mk b/make/project.mk index 08c7dd89a..a08199280 100644 --- a/make/project.mk +++ b/make/project.mk @@ -158,14 +158,16 @@ LDFLAGS ?= -nostdlib \ # CPPFLAGS used by C preprocessor # If any flags are defined in application Makefile, add them at the end. -CPPFLAGS := -DESP_PLATFORM $(CPPFLAGS) +CPPFLAGS := -DESP_PLATFORM $(CPPFLAGS) $(EXTRA_CPPFLAGS) # Warnings-related flags relevant both for C and C++ -COMMON_WARNING_FLAGS = -Wall -Werror \ +COMMON_WARNING_FLAGS = -Wall -Werror=all \ -Wno-error=unused-function \ -Wno-error=unused-but-set-variable \ -Wno-error=unused-variable \ - -Wno-error=deprecated-declarations + -Wno-error=deprecated-declarations \ + -Wextra \ + -Wno-unused-parameter -Wno-sign-compare # Flags which control code generation and dependency generation, both for C and C++ COMMON_FLAGS = \ @@ -192,8 +194,9 @@ CFLAGS := $(strip \ -std=gnu99 \ $(OPTIMIZATION_FLAGS) \ $(COMMON_FLAGS) \ - $(COMMON_WARNING_FLAGS) \ - $(CFLAGS)) + $(COMMON_WARNING_FLAGS) -Wno-old-style-declaration \ + $(CFLAGS) \ + $(EXTRA_CFLAGS)) # List of flags to pass to C++ compiler # If any flags are defined in application Makefile, add them at the end. @@ -204,7 +207,8 @@ CXXFLAGS := $(strip \ $(OPTIMIZATION_FLAGS) \ $(COMMON_FLAGS) \ $(COMMON_WARNING_FLAGS) \ - $(CXXFLAGS)) + $(CXXFLAGS) \ + $(EXTRA_CXXFLAGS)) export CFLAGS CPPFLAGS CXXFLAGS From 7dbf01b2107376e6f6c047bd64221b4f16976b19 Mon Sep 17 00:00:00 2001 From: Liu Zhi Fu Date: Wed, 16 Nov 2016 13:20:49 +0800 Subject: [PATCH 17/48] esp32: softap supports bridge Softap supports bridge, then the stations associated with esp32 softap can send/receive traffic from each other --- components/esp32/lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esp32/lib b/components/esp32/lib index 01f5c068e..41da160a5 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit 01f5c068e1ac3968add98439ee2f1748b9e391fa +Subproject commit 41da160a5dbf9e13b4fb51f31acf372f50c28270 From 37cbb0bdea302783f3bca43356f806402845322f Mon Sep 17 00:00:00 2001 From: Wangjialin Date: Wed, 16 Nov 2016 14:44:06 +0800 Subject: [PATCH 18/48] driver: bugfix/fix uart parity and frame error bug 1. modify definition for uart_parity_t 2. fix bugs in uart interrupt handler for parity err and frame err. --- components/driver/include/driver/uart.h | 4 ++-- components/driver/uart.c | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/components/driver/include/driver/uart.h b/components/driver/include/driver/uart.h index 687ae71aa..749cd6564 100644 --- a/components/driver/include/driver/uart.h +++ b/components/driver/include/driver/uart.h @@ -68,8 +68,8 @@ typedef enum { typedef enum { UART_PARITY_DISABLE = 0x0, /*!< Disable UART parity*/ - UART_PARITY_EVEN = 0x10, /*!< Enable UART even parity*/ - UART_PARITY_ODD = 0x11 /*!< Enable UART odd parity*/ + UART_PARITY_EVEN = 0x2, /*!< Enable UART even parity*/ + UART_PARITY_ODD = 0x3 /*!< Enable UART odd parity*/ } uart_parity_t; typedef enum { diff --git a/components/driver/uart.c b/components/driver/uart.c index a8d28ff29..02610e7b4 100644 --- a/components/driver/uart.c +++ b/components/driver/uart.c @@ -603,10 +603,10 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) } else if(uart_intr_status & UART_BRK_DET_INT_ST_M) { uart_reg->int_clr.brk_det = 1; uart_event.type = UART_BREAK; - } else if(uart_intr_status & UART_FRM_ERR_INT_ST_M) { + } else if(uart_intr_status & UART_PARITY_ERR_INT_ST_M ) { uart_reg->int_clr.parity_err = 1; uart_event.type = UART_FRAME_ERR; - } else if(uart_intr_status & UART_PARITY_ERR_INT_ST_M) { + } else if(uart_intr_status & UART_FRM_ERR_INT_ST_M) { uart_reg->int_clr.frm_err = 1; uart_event.type = UART_PARITY_ERR; } else if(uart_intr_status & UART_TX_BRK_DONE_INT_ST_M) { @@ -964,7 +964,8 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b | UART_RXFIFO_TOUT_INT_ENA_M | UART_FRM_ERR_INT_ENA_M | UART_RXFIFO_OVF_INT_ENA_M - | UART_BRK_DET_INT_ENA_M, + | UART_BRK_DET_INT_ENA_M + | UART_PARITY_ERR_INT_ENA_M, .rxfifo_full_thresh = UART_FULL_THRESH_DEFAULT, .rx_timeout_thresh = UART_TOUT_THRESH_DEFAULT, .txfifo_empty_intr_thresh = UART_EMPTY_THRESH_DEFAULT From 8b7d1cdc272acce928f053ec64eefb55a46f44c4 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 16 Nov 2016 17:15:55 +1100 Subject: [PATCH 19/48] ringbuf: Fix case where xTaskGetTickCount() overflows but task timeout point doesn't --- components/freertos/ringbuf.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/components/freertos/ringbuf.c b/components/freertos/ringbuf.c index 062c52023..67323e327 100644 --- a/components/freertos/ringbuf.c +++ b/components/freertos/ringbuf.c @@ -471,7 +471,8 @@ BaseType_t xRingbufferSend(RingbufHandle_t ringbuf, void *data, size_t dataSize, ringbuf_t *rb=(ringbuf_t *)ringbuf; size_t needed_size=dataSize+sizeof(buf_entry_hdr_t); BaseType_t done=pdFALSE; - portTickType ticks_end=xTaskGetTickCount() + ticks_to_wait; + TickType_t ticks_end = xTaskGetTickCount() + ticks_to_wait; + TickType_t ticks_remaining = ticks_to_wait; configASSERT(rb); @@ -486,16 +487,25 @@ BaseType_t xRingbufferSend(RingbufHandle_t ringbuf, void *data, size_t dataSize, if (ringbufferFreeMem(rb) < needed_size) { //Data does not fit yet. Wait until the free_space_sem is given, then re-evaluate. - BaseType_t r = xSemaphoreTake(rb->free_space_sem, ticks_to_wait); + BaseType_t r = xSemaphoreTake(rb->free_space_sem, ticks_remaining); if (r == pdFALSE) { //Timeout. return pdFALSE; } - //Adjust ticks_to_wait; we may have waited less than that and in the case the free memory still is not enough, + //Adjust ticks_remaining; we may have waited less than that and in the case the free memory still is not enough, //we will need to wait some more. - ticks_to_wait = ticks_end - xTaskGetTickCount(); + if (ticks_to_wait != portMAX_DELAY) { + ticks_remaining = ticks_end - xTaskGetTickCount(); + } + + // ticks_remaining will always be less than or equal to the original ticks_to_wait, + // unless the timeout is reached - in which case it unsigned underflows to a much + // higher value. + // + // (Check is written this non-intuitive way to allow for the case where xTaskGetTickCount() + // has overflowed but the ticks_end value has not overflowed.) } - } while (ringbufferFreeMem(rb) < needed_size && ticks_end >= xTaskGetTickCount()); + } while (ringbufferFreeMem(rb) < needed_size && ticks_remaining > 0 && ticks_remaining <= ticks_to_wait); //Lock the mux in order to make sure no one else is messing with the ringbuffer and do the copy. portENTER_CRITICAL(&rb->mux); From 69dbc36a1c9338d5829256c8bf69cffaebbb83a8 Mon Sep 17 00:00:00 2001 From: Liu Zhi Fu Date: Wed, 16 Nov 2016 16:24:41 +0800 Subject: [PATCH 20/48] lwip: add option to memcopy packet from L2 to L3 Menuconfig add an option to copy the packet from layer2 (WIFI driver) to layer3 (LWIP), default not copy --- components/lwip/Kconfig | 10 +++++ components/lwip/include/lwip/lwip/opt.h | 7 ++++ components/lwip/include/lwip/port/lwipopts.h | 1 + components/lwip/port/netif/wlanif.c | 41 +++++++++----------- 4 files changed, 37 insertions(+), 22 deletions(-) diff --git a/components/lwip/Kconfig b/components/lwip/Kconfig index 801fa0b51..90b7c5b5c 100644 --- a/components/lwip/Kconfig +++ b/components/lwip/Kconfig @@ -1,5 +1,15 @@ menu "LWIP" +config L2_TO_L3_COPY + bool "Enable copy between Layer2 and Layer3 packets" + default 0 + help + If this feature is enabled, then all traffic from layer2(WIFI Driver) + to layer3(LWIP stack) will make a copy, the layer2 buffer will be + freed and the copy will be sent to layer3. Please make sure you fully + understand this feature before you enable this feature. + + config LWIP_MAX_SOCKETS int "Max number of open sockets" range 1 16 diff --git a/components/lwip/include/lwip/lwip/opt.h b/components/lwip/include/lwip/lwip/opt.h index 51d340e00..9a1d10afb 100755 --- a/components/lwip/include/lwip/lwip/opt.h +++ b/components/lwip/include/lwip/lwip/opt.h @@ -3008,6 +3008,13 @@ #define LWIP_PERF 0 #endif +/** + * ESP_L2_TO_L3_COPY: enable memcpy when receiving packet from L2 + */ +#ifndef ESP_L2_TO_L3_COPY +#define ESP_L2_TO_L3_COPY 1 +#endif + #ifndef ESP_THREAD_SAFE_DEBUG #define ESP_THREAD_SAFE_DEBUG 0 #endif diff --git a/components/lwip/include/lwip/port/lwipopts.h b/components/lwip/include/lwip/port/lwipopts.h index d06e75685..26bdc3a4e 100755 --- a/components/lwip/include/lwip/port/lwipopts.h +++ b/components/lwip/include/lwip/port/lwipopts.h @@ -525,6 +525,7 @@ extern unsigned long os_random(void); #define ESP_RANDOM_TCP_PORT 1 #define ESP_IP4_ATON 1 #define ESP_LIGHT_SLEEP 1 +#define ESP_L2_TO_L3_COPY CONFIG_L2_TO_L3_COPY #define TCP_WND_DEFAULT (4*TCP_MSS) #define TCP_SND_BUF_DEFAULT (2*TCP_MSS) diff --git a/components/lwip/port/netif/wlanif.c b/components/lwip/port/netif/wlanif.c index ffad69cd4..3fd2a3192 100755 --- a/components/lwip/port/netif/wlanif.c +++ b/components/lwip/port/netif/wlanif.c @@ -161,40 +161,37 @@ low_level_output(struct netif *netif, struct pbuf *p) * @param netif the lwip network interface structure for this ethernetif */ void -#if ESP_LWIP wlanif_input(struct netif *netif, void *buffer, u16_t len, void* eb) -#else -wlanif_input(struct netif *netif, void *buffer, uint16 len) -#endif { struct pbuf *p; -#if ESP_LWIP - if(buffer== NULL) + if(!buffer || !netif) goto _exit; - if(netif == NULL) - goto _exit; -#endif -#if ESP_LWIP - p = pbuf_alloc(PBUF_RAW, len, PBUF_REF); - if (p == NULL){ -#if ESP_PERF - g_rx_alloc_pbuf_fail_cnt++; -#endif - return; - } - p->payload = buffer; - p->eb = eb; -#else - p = pbuf_alloc(PBUF_IP, len, PBUF_POOL); +#if (ESP_L2_TO_L3_COPY == 1) + //p = pbuf_alloc(PBUF_IP, len, PBUF_POOL); + p = pbuf_alloc(PBUF_RAW, len, PBUF_RAM); if (p == NULL) { + #if ESP_PERF + g_rx_alloc_pbuf_fail_cnt++; + #endif + esp_wifi_internal_free_rx_buffer(eb); return; } memcpy(p->payload, buffer, len); + esp_wifi_internal_free_rx_buffer(eb); +#else + p = pbuf_alloc(PBUF_RAW, len, PBUF_REF); + if (p == NULL){ + #if ESP_PERF + g_rx_alloc_pbuf_fail_cnt++; + #endif + return; + } + p->payload = buffer; + p->eb = eb; #endif - /* full packet send to tcpip_thread to process */ if (netif->input(p, netif) != ERR_OK) { LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); From a023b005c67c80c7cf5cc4e2666ff34fe99e5baf Mon Sep 17 00:00:00 2001 From: Jeroen Domburg Date: Wed, 16 Nov 2016 17:53:50 +0800 Subject: [PATCH 21/48] taskwdt fixes: better handling of empty/emptying wdt task list, lock task struct while feeding --- components/esp32/task_wdt.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/components/esp32/task_wdt.c b/components/esp32/task_wdt.c index 549b7f58b..de5f9f54f 100644 --- a/components/esp32/task_wdt.c +++ b/components/esp32/task_wdt.c @@ -22,6 +22,8 @@ #include "sdkconfig.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" #include #include "esp_err.h" #include "esp_intr.h" @@ -45,6 +47,7 @@ struct wdt_task_t { }; static wdt_task_t *wdt_task_list=NULL; +static portMUX_TYPE taskwdt_spinlock = portMUX_INITIALIZER_UNLOCKED; static void IRAM_ATTR task_wdt_isr(void *arg) { wdt_task_t *wdttask; @@ -55,13 +58,23 @@ static void IRAM_ATTR task_wdt_isr(void *arg) { TIMERG0.wdt_wprotect=0; //Ack interrupt TIMERG0.int_clr_timers.wdt=1; + //We are taking a spinlock while doing I/O (ets_printf) here. Normally, that is a pretty + //bad thing, possibly (temporarily) hanging up the 2nd core and stopping FreeRTOS. In this case, + //something bad already happened and reporting this is considered more important + //than the badness caused by a spinlock here. + portENTER_CRITICAL(&taskwdt_spinlock); + if (!wdt_task_list) { + //No task on list. Maybe none registered yet. + portEXIT_CRITICAL(&taskwdt_spinlock); + return; + } //Watchdog got triggered because at least one task did not report in. ets_printf("Task watchdog got triggered. The following tasks did not feed the watchdog in time:\n"); for (wdttask=wdt_task_list; wdttask!=NULL; wdttask=wdttask->next) { if (!wdttask->fed_watchdog) { cpu=xTaskGetAffinity(wdttask->task_handle)==0?"CPU 0":"CPU 1"; if (xTaskGetAffinity(wdttask->task_handle)==tskNO_AFFINITY) cpu="CPU 0/1"; - printf(" - %s (%s)\n", pcTaskGetTaskName(wdttask->task_handle), cpu); + ets_printf(" - %s (%s)\n", pcTaskGetTaskName(wdttask->task_handle), cpu); } } ets_printf("Tasks currently running:\n"); @@ -73,6 +86,7 @@ static void IRAM_ATTR task_wdt_isr(void *arg) { ets_printf("Aborting.\n"); abort(); #endif + portEXIT_CRITICAL(&taskwdt_spinlock); } @@ -80,6 +94,8 @@ void esp_task_wdt_feed() { wdt_task_t *wdttask=wdt_task_list; bool found_task=false, do_feed_wdt=true; TaskHandle_t handle=xTaskGetCurrentTaskHandle(); + portENTER_CRITICAL(&taskwdt_spinlock); + //Walk the linked list of wdt tasks to find this one, as well as see if we need to feed //the real watchdog timer. for (wdttask=wdt_task_list; wdttask!=NULL; wdttask=wdttask->next) { @@ -114,14 +130,18 @@ void esp_task_wdt_feed() { //Reset fed_watchdog status for (wdttask=wdt_task_list; wdttask->next!=NULL; wdttask=wdttask->next) wdttask->fed_watchdog=false; } + portEXIT_CRITICAL(&taskwdt_spinlock); } void esp_task_wdt_delete() { TaskHandle_t handle=xTaskGetCurrentTaskHandle(); wdt_task_t *wdttask=wdt_task_list; + portENTER_CRITICAL(&taskwdt_spinlock); + //Wdt task list can't be empty if (!wdt_task_list) { ESP_LOGE(TAG, "task_wdt_delete: No tasks in list?"); + portEXIT_CRITICAL(&taskwdt_spinlock); return; } if (handle==wdt_task_list) { @@ -130,15 +150,25 @@ void esp_task_wdt_delete() { free(wdttask); } else { //Find current task in list + if (wdt_task_list->task_handle==handle) { + //Task is the very first one. + wdt_task_t *freeme=wdt_task_list; + wdt_task_list=wdt_task_list->next; + free(freeme); + portEXIT_CRITICAL(&taskwdt_spinlock); + return; + } while (wdttask->next!=NULL && wdttask->next->task_handle!=handle) wdttask=wdttask->next; if (!wdttask->next) { ESP_LOGE(TAG, "task_wdt_delete: Task never called task_wdt_feed!"); + portEXIT_CRITICAL(&taskwdt_spinlock); return; } wdt_task_t *freeme=wdttask->next; wdttask->next=wdttask->next->next; free(freeme); } + portEXIT_CRITICAL(&taskwdt_spinlock); } From 0b2cea6e9f757191be0bfc83a6fe3ed15981ccf2 Mon Sep 17 00:00:00 2001 From: Liu Zhi Fu Date: Wed, 16 Nov 2016 21:11:17 +0800 Subject: [PATCH 22/48] lwip: modify menuconfig comments according to review --- components/lwip/Kconfig | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/components/lwip/Kconfig b/components/lwip/Kconfig index 90b7c5b5c..7661fe6cb 100644 --- a/components/lwip/Kconfig +++ b/components/lwip/Kconfig @@ -6,9 +6,14 @@ config L2_TO_L3_COPY help If this feature is enabled, then all traffic from layer2(WIFI Driver) to layer3(LWIP stack) will make a copy, the layer2 buffer will be - freed and the copy will be sent to layer3. Please make sure you fully - understand this feature before you enable this feature. - + freed and the copy will be sent to layer3. Please be notified that the + total layer2 receiving buffer is fixed and ESP32 currently supports 25 + layer2 receiving buffer, when layer2 buffer runs out of memory, then the + incoming packets will be dropped in hardware. The layer3 buffer is + allocated from the heap, so the total layer3 receiving buffer depends + on the available heap size, when heap runs out of memory, no copy will + be sent to layer3 and packet will be dropped in layer2. Please make sure + you fully understand the impact of this feature before enabling it. config LWIP_MAX_SOCKETS int "Max number of open sockets" From 8713155e669fd19db23e9b20364910240c3f15c9 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Mon, 14 Nov 2016 15:40:54 +0800 Subject: [PATCH 23/48] docs: add description of ESP-IDF application startup flow and memory layout --- docs/general-notes.rst | 127 +++++++++++++++++++++++++++++++++++++++++ docs/index.rst | 1 + 2 files changed, 128 insertions(+) create mode 100644 docs/general-notes.rst diff --git a/docs/general-notes.rst b/docs/general-notes.rst new file mode 100644 index 000000000..519a03b28 --- /dev/null +++ b/docs/general-notes.rst @@ -0,0 +1,127 @@ +General Notes About ESP-IDF Programming +======================================= + +Application startup flow +------------------------ + +This note explains various steps which happen before ``app_main`` function of an ESP-IDF application is called. + +The high level view of startup process is as follows: + +1. First-stage bootloader in ROM loads second-stage bootloader image to RAM (IRAM & DRAM) from flash offset 0x1000. +2. Second-stage bootloader loads partition table and main app image from flash. Main app incorporates both RAM segments and read-only segments mapped via flash cache. +3. Main app image executes. At this point the second CPU and RTOS scheduler can be started. + +This process is explained in detail in the following sections. + +First stage bootloader +^^^^^^^^^^^^^^^^^^^^^^ + +After SoC reset, PRO CPU will start running immediately, executing reset vector code, while APP CPU will be held in reset. During startup process, PRO CPU does all the initialization. APP CPU reset is de-asserted in the ``call_start_cpu0`` function of application startup code. Reset vector code is located at address 0x40000400 in the mask ROM of the ESP32 chip and can not be modified. + +Startup code called from the reset vector determines the boot mode by checking ``GPIO_STRAP_REG`` register for bootstrap pin states. Depending on the reset reason, the following takes place: + +1. Reset from deep sleep: if the value in ``RTC_CNTL_STORE6_REG`` is non-zero, and CRC value of RTC memory in ``RTC_CNTL_STORE7_REG`` is valid, use ``RTC_CNTL_STORE6_REG`` as an entry point address and jump immediately to it. If ``RTC_CNTL_STORE6_REG`` is zero, or ``RTC_CNTL_STORE7_REG`` contains invalid CRC, or once the code called via ``RTC_CNTL_STORE6_REG`` returns, proceed with boot as if it was a power-on reset. **Note**: to run customized code at this point, a deep sleep stub mechanism is provided. Please see deep sleep documentation for this: deep-sleep-stub_. + +2. For power-on reset, software SOC reset, and watchdog SOC reset: check the ``GPIO_STRAP_REG`` register if UART or SDIO download mode is requested. If this is the case, configure UART or SDIO, and wait for code to be downloaded. Otherwise, proceed with boot as if it was due to software CPU reset. + +3. For software CPU reset and watchdog CPU reset: configure SPI flash based on EFUSE values, and attempt to load the code from flash. This step is described in more detail in the next paragraphs. If loading code from flash fails, unpack BASIC interpreter into the RAM and start it. Note that RTC watchdog is still enabled when this happens, so unless any input is received by the interpreter, watchdog will reset the SOC in a few hundred milliseconds, repeating the whole process. If the interpreter receives any input from the UART, it disables the watchdog. + +Application binary image is loaded from flash starting at address 0x1000. First 4kB sector of flash is used to store secure boot IV and signature of the application image. Please check secure boot documentation for details about this. + +.. TODO: describe application binary image format, describe optional flash configuration commands. + +Second stage bootloader +^^^^^^^^^^^^^^^^^^^^^^^ + +In ESP-IDF, the binary image which resides at offset 0x1000 in flash is the second stage bootloader. Second stage bootloader source code is available in components/bootloader directory of ESP-IDF. Note that this arrangement is not the only one possible with the ESP32 chip. It is possible to write a fully featured application which would work when flashed to offset 0x1000, but this is out of scope of this document. Second stage bootloader is used in ESP-IDF to add flexibility to flash layout (using partition tables), and allow for various flows associated with flash encryption, secure boot, and over-the-air updates (OTA) to take place. + +When the first stage bootloader is finished checking and loading the second stage bootloader, it jumps to the second stage bootloader entry point found in the binary image header. + +Second stage bootloader reads the partition table found at offset 0x8000. For more information about partition tables, see partition-tables_. It finds factory and OTA partitions, and decides which one to boot based on data found in *OTA info* partition. + +For the selected partition, second stage bootloader copies data and code sections which are mapped into IRAM and DRAM to their load addresses. For sections which have load addresses in DROM and IROM regions, flash MMU is configured to provide the correct mapping. Note that the second stage bootloader configures flash MMU for both PRO and APP CPUs, but it only enables flash MMU for PRO CPU. Reason for this is that second stage bootloader code is loaded into the memory region used by APP CPU cache. The duty of enabling cache for APP CPU is passed on to the application. Once code is loaded and flash MMU is set up, second stage bootloader jumps to the application entry point found in the binary image header. + +Currently it is not possible to add application-defined hooks to the bootloader to customize application partition selection logic. This may be required to load different application image depending on a state of a GPIO, for example. Such customization features will be added to ESP-IDF in the future. For now, bootloader can be customized by copying bootloader component into application directory and making necessary changes there. ESP-IDF build system will compile the component in application directory instead of ESP-IDF components directory in this case. + +Application startup +^^^^^^^^^^^^^^^^^^^ + +ESP-IDF application entry point is ``call_start_cpu0`` function found in ``components/esp32/cpu_start.c``. Two main things this function does are to enable heap allocator and to make APP CPU jump to its entry point, ``call_start_cpu1``. The code on PRO CPU sets the entry point for APP CPU, de-asserts APP CPU reset, and waits for a global flag to be set by the code running on APP CPU, indicating that it has started. Once this is done, PRO CPU jumps to ``start_cpu0`` function, and APP CPU jumps to ``start_cpu1`` function. + +Both ``start_cpu0`` and ``start_cpu1`` are weak functions, meaning that they can be overridden in the application, if some application-specific change to initialization sequence is needed. Default implementation of ``start_cpu0`` enables or initializes components depending on choices made in ``menuconfig``. Please see source code of this function in ``components/esp32/cpu_start.c`` for an up to date list of steps performed. Note that any C++ global constructors present in the application will be called at this stage. Once all essential components are initialized, *main task* is created and FreeRTOS scheduler is started. + +While PRO CPU does initialization in ``start_cpu0`` function, APP CPU spins in ``start_cpu1`` function, waiting for the scheduler to be started on the PRO CPU. Once the scheduler is started on the PRO CPU, code on the APP CPU starts the scheduler as well. + +Main task is the task which runs ``app_main`` function. Main task stack size and priority can be configured in ``menuconfig``. Application can use this task for initial application-specific setup, for example to launch other tasks. Application can also use main task for event loops and other general purpose activities. If ``app_main`` function returns, main task is deleted. + + +Application memory layout +------------------------- + +ESP32 chip has flexible memory mapping features. This section describes how ESP-IDF uses these features by default. + +Application code in ESP-IDF can be placed into one of the following memory regions. + +IRAM (instruction RAM) +^^^^^^^^^^^^^^^^^^^^^^ + +ESP-IDF allocates part of `Internal SRAM0` region (defined in the Technical Reference Manual) for instruction RAM. Except for the first 64 kB block which is used for PRO and APP CPU caches, the rest of this memory range (i.e. from ``0x40080000`` to ``0x400A0000``) is used to store parts of application which need to run from RAM. + +A few components of ESP-IDF and parts of WiFi stack are placed into this region using the linker script. + +If some application code needs to be placed into IRAM, it can be done using ``IRAM_ATTR`` define:: + + #include "esp_attr.h" + + void IRAM_ATTR gpio_isr_handler(void* arg) + { + // ... + } + +Here are the cases when parts of application may or should be placed into IRAM. + +- ISR handlers must always be placed into IRAM. Furthermore, ISR handlers may only call functions placed into IRAM or functions present in ROM. *Note 1:* all FreeRTOS APIs are currently placed into IRAM, so are safe to call from ISR handlers. *Note 1:* all constant data used by ISR handlers and functions called from ISR handlers (including, but not limited to, ``const char`` arrays), must be placed into DRAM using ``DRAM_ATTR``. + +- Some timing critical code may be placed into IRAM to reduce the penalty associated with loading the code from flash. ESP32 reads code and data from flash via a 32 kB cache. In some cases, placing a function into IRAM may reduce delays caused by a cache miss. + +IROM (code executed from Flash) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If a function is not explicitly placed into IRAM or RTC memory, it is placed into flash. The mechanism by which Flash MMU is used to allow code execution from flash is described in the Technical Reference Manual. ESP-IDF places the code which should be executed from flash starting from the beginning of ``0x400D0000 — 0x40400000`` region. Upon startup, second stage bootloader initializes Flash MMU to map the location in flash where code is located into the beginning of this region. Access to this region is transparently cached using two 32kB blocks in ``0x40070000`` — ``0x40080000`` range. + +Note that the code outside ``0x40000000 — 0x40400000`` region may not be reachable with Window ABI ``CALLx`` instructions, so special care is required if ``0x40400000 — 0x40800000`` or ``0x40800000 — 0x40C00000`` regions are used by the application. ESP-IDF doesn't use these regions by default. + +RTC fast memory +^^^^^^^^^^^^^^^ + +The code which has to run after wake-up from deep sleep mode has to be placed into RTC memory. Please check detailed description in deep-sleep-stub_. + +DRAM (data RAM) +^^^^^^^^^^^^^^^ + +Non-constant static data and zero-initialized data is placed by the linker into 200 kB ``0x3FFB0000 — 0x3FFF0000`` region. Note that this region is reduced by 64kB (by shifting start address to ``0x3FFC0000``) if Bluetooth stack is used. Length of this region is also reduced by 16 kB or 32kB if trace memory is used. All space which is left in this region after placing static data there is used for the runtime heap. + +Constant data may also be placed into DRAM, for example if it is used in an ISR handler (see notes in IRAM section above). To do that, ``DRAM_ATTR`` define can be used:: + + DRAM_ATTR const char[] format_string = "%p %x"; + char buffer[64]; + sprintf(buffer, format_string, ptr, val); + +Needless to say, it is not advised to use ``printf`` and other output functions in ISR handlers. For debugging purposes, use ``ESP_EARLY_LOGx`` macros when logging from ISR handlers. Make sure that both ``TAG`` and format string are placed into ``DRAM`` in that case. + +DROM (data stored in Flash) +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +By default, constant data is placed by the linker into a 4 MB region (``0x3F400000 — 0x3F800000``) which is used to access external flash memory via Flash MMU and cache. Exceptions to this are literal constants which are embedded by the compiler into application code. + +RTC slow memory +^^^^^^^^^^^^^^^ + +Global and static variables used by code which runs from RTC memory (i.e. deep sleep stub code) must be placed into RTC slow memory. Please check the detailed description in deep-sleep-stub_. + + +.. _deep-sleep-stub: deep-sleep-stub.rst +.. _partition-tables: partition-tables.rst + + diff --git a/docs/index.rst b/docs/index.rst index 1ca6e28ee..fb5e0c7c9 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -28,6 +28,7 @@ Contents: :caption: What Else? :maxdepth: 1 + General Notes partition-tables build_system openocd From ca202cbb4605f97bedd884b3acd807e6b4102797 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 16 Nov 2016 21:33:04 +0800 Subject: [PATCH 24/48] docs: fix broken links, formatting, add SPI flash and partition APIs --- docs/Doxyfile | 8 ++++- docs/api/nvs_flash.rst | 5 ++- docs/api/spi_flash.rst | 67 +++++++++++++++++++++++++++++++++++ docs/doxygen_xml_to_rst.xslt | 56 +++++++++++++++++++++++++++++ docs/general-notes.rst | 10 +++--- docs/index.rst | 2 +- docs/security/secure-boot.rst | 12 +++---- 7 files changed, 145 insertions(+), 15 deletions(-) create mode 100644 docs/api/spi_flash.rst create mode 100644 docs/doxygen_xml_to_rst.xslt diff --git a/docs/Doxyfile b/docs/Doxyfile index 6ff4c4586..a46f014a5 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -1,6 +1,12 @@ PROJECT_NAME = "ESP32 Programming Guide" -INPUT = ../components/esp32/include/esp_wifi.h ../components/driver/include/driver ../components/bt/include ../components/nvs_flash/include ../components/log/include ../components/vfs/include +INPUT = ../components/esp32/include/esp_wifi.h \ + ../components/driver/include/driver \ + ../components/bt/include \ + ../components/nvs_flash/include \ + ../components/log/include \ + ../components/vfs/include \ + ../components/spi_flash/include WARN_NO_PARAMDOC = YES diff --git a/docs/api/nvs_flash.rst b/docs/api/nvs_flash.rst index 0768fa559..5d3634355 100644 --- a/docs/api/nvs_flash.rst +++ b/docs/api/nvs_flash.rst @@ -3,7 +3,10 @@ Application Example ------------------- -`Instructions `_ +Two examples are provided in ESP-IDF examples directory: + +- `07_nvs_rw_value `_ demostrates how to read and write integer values +- `08_nvs_rw_blob `_ demostrates how to read and write variable length binary values API Reference ------------- diff --git a/docs/api/spi_flash.rst b/docs/api/spi_flash.rst new file mode 100644 index 000000000..5903c0902 --- /dev/null +++ b/docs/api/spi_flash.rst @@ -0,0 +1,67 @@ +.. include:: ../../components/spi_flash/README.rst + +Application Example +------------------- + +`Instructions`_ + +.. _Instructions: template.html + +API Reference +------------- + +Header Files +^^^^^^^^^^^^ + + * `spi_flash/include/esp_spi_flash.h `_ + * `spi_flash/include/esp_partition.h `_ + +Macros +^^^^^^ + +.. doxygendefine:: ESP_ERR_FLASH_BASE +.. doxygendefine:: ESP_ERR_FLASH_OP_FAIL +.. doxygendefine:: ESP_ERR_FLASH_OP_TIMEOUT +.. doxygendefine:: SPI_FLASH_SEC_SIZE +.. doxygendefine:: ESP_PARTITION_SUBTYPE_OTA + +Type Definitions +^^^^^^^^^^^^^^^^ + +.. doxygentypedef:: spi_flash_mmap_handle_t +.. doxygentypedef:: esp_partition_iterator_t + +Enumerations +^^^^^^^^^^^^ + +.. doxygenenum:: spi_flash_mmap_memory_t +.. doxygenenum:: esp_partition_type_t +.. doxygenenum:: esp_partition_subtype_t + +Structures +^^^^^^^^^^ + +.. doxygenstruct:: esp_partition_t + +Functions +^^^^^^^^^ + +.. doxygenfunction:: spi_flash_init +.. doxygenfunction:: spi_flash_get_chip_size +.. doxygenfunction:: spi_flash_erase_sector +.. doxygenfunction:: spi_flash_erase_range +.. doxygenfunction:: spi_flash_write +.. doxygenfunction:: spi_flash_read +.. doxygenfunction:: spi_flash_mmap +.. doxygenfunction:: spi_flash_munmap +.. doxygenfunction:: spi_flash_mmap_dump +.. doxygenfunction:: esp_partition_find +.. doxygenfunction:: esp_partition_find_first +.. doxygenfunction:: esp_partition_get +.. doxygenfunction:: esp_partition_next +.. doxygenfunction:: esp_partition_iterator_release +.. doxygenfunction:: esp_partition_read +.. doxygenfunction:: esp_partition_write +.. doxygenfunction:: esp_partition_erase_range +.. doxygenfunction:: esp_partition_mmap + diff --git a/docs/doxygen_xml_to_rst.xslt b/docs/doxygen_xml_to_rst.xslt new file mode 100644 index 000000000..c4570a9df --- /dev/null +++ b/docs/doxygen_xml_to_rst.xslt @@ -0,0 +1,56 @@ + + + + + + + + + Macros + ^^^^^^ + + .. doxygendefine:: + + + + + + Type Definitions + ^^^^^^^^^^^^^^^^ + + .. doxygentypedef:: + + + + + + Enumerations + ^^^^^^^^^^^^ + + .. doxygenenum:: + + + + + + + Structures + ^^^^^^^^^^ + + .. doxygenstruct:: + + + + + + Functions + ^^^^^^^^^ + + .. doxygenfunction:: + + + + + + + diff --git a/docs/general-notes.rst b/docs/general-notes.rst index 519a03b28..a68346700 100644 --- a/docs/general-notes.rst +++ b/docs/general-notes.rst @@ -21,7 +21,7 @@ After SoC reset, PRO CPU will start running immediately, executing reset vector Startup code called from the reset vector determines the boot mode by checking ``GPIO_STRAP_REG`` register for bootstrap pin states. Depending on the reset reason, the following takes place: -1. Reset from deep sleep: if the value in ``RTC_CNTL_STORE6_REG`` is non-zero, and CRC value of RTC memory in ``RTC_CNTL_STORE7_REG`` is valid, use ``RTC_CNTL_STORE6_REG`` as an entry point address and jump immediately to it. If ``RTC_CNTL_STORE6_REG`` is zero, or ``RTC_CNTL_STORE7_REG`` contains invalid CRC, or once the code called via ``RTC_CNTL_STORE6_REG`` returns, proceed with boot as if it was a power-on reset. **Note**: to run customized code at this point, a deep sleep stub mechanism is provided. Please see deep sleep documentation for this: deep-sleep-stub_. +1. Reset from deep sleep: if the value in ``RTC_CNTL_STORE6_REG`` is non-zero, and CRC value of RTC memory in ``RTC_CNTL_STORE7_REG`` is valid, use ``RTC_CNTL_STORE6_REG`` as an entry point address and jump immediately to it. If ``RTC_CNTL_STORE6_REG`` is zero, or ``RTC_CNTL_STORE7_REG`` contains invalid CRC, or once the code called via ``RTC_CNTL_STORE6_REG`` returns, proceed with boot as if it was a power-on reset. **Note**: to run customized code at this point, a deep sleep stub mechanism is provided. Please see :doc:`deep sleep ` documentation for this. 2. For power-on reset, software SOC reset, and watchdog SOC reset: check the ``GPIO_STRAP_REG`` register if UART or SDIO download mode is requested. If this is the case, configure UART or SDIO, and wait for code to be downloaded. Otherwise, proceed with boot as if it was due to software CPU reset. @@ -38,7 +38,7 @@ In ESP-IDF, the binary image which resides at offset 0x1000 in flash is the seco When the first stage bootloader is finished checking and loading the second stage bootloader, it jumps to the second stage bootloader entry point found in the binary image header. -Second stage bootloader reads the partition table found at offset 0x8000. For more information about partition tables, see partition-tables_. It finds factory and OTA partitions, and decides which one to boot based on data found in *OTA info* partition. +Second stage bootloader reads the partition table found at offset 0x8000. See :doc:`partition tables ` documentation for more information. The bootloader finds factory and OTA partitions, and decides which one to boot based on data found in *OTA info* partition. For the selected partition, second stage bootloader copies data and code sections which are mapped into IRAM and DRAM to their load addresses. For sections which have load addresses in DROM and IROM regions, flash MMU is configured to provide the correct mapping. Note that the second stage bootloader configures flash MMU for both PRO and APP CPUs, but it only enables flash MMU for PRO CPU. Reason for this is that second stage bootloader code is loaded into the memory region used by APP CPU cache. The duty of enabling cache for APP CPU is passed on to the application. Once code is loaded and flash MMU is set up, second stage bootloader jumps to the application entry point found in the binary image header. @@ -95,7 +95,7 @@ Note that the code outside ``0x40000000 — 0x40400000`` region may not be reach RTC fast memory ^^^^^^^^^^^^^^^ -The code which has to run after wake-up from deep sleep mode has to be placed into RTC memory. Please check detailed description in deep-sleep-stub_. +The code which has to run after wake-up from deep sleep mode has to be placed into RTC memory. Please check detailed description in :doc:`deep sleep ` documentation. DRAM (data RAM) ^^^^^^^^^^^^^^^ @@ -118,10 +118,8 @@ By default, constant data is placed by the linker into a 4 MB region (``0x3F4000 RTC slow memory ^^^^^^^^^^^^^^^ -Global and static variables used by code which runs from RTC memory (i.e. deep sleep stub code) must be placed into RTC slow memory. Please check the detailed description in deep-sleep-stub_. +Global and static variables used by code which runs from RTC memory (i.e. deep sleep stub code) must be placed into RTC slow memory. Please check detailed description in :doc:`deep sleep ` documentation. -.. _deep-sleep-stub: deep-sleep-stub.rst -.. _partition-tables: partition-tables.rst diff --git a/docs/index.rst b/docs/index.rst index fb5e0c7c9..f777d10ca 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -97,7 +97,7 @@ Contents: api/gpio api/uart api/ledc - + SPI Flash and Partition APIs Logging Non-Volatile Storage Virtual Filesystem diff --git a/docs/security/secure-boot.rst b/docs/security/secure-boot.rst index bdc1b7169..b352b3964 100644 --- a/docs/security/secure-boot.rst +++ b/docs/security/secure-boot.rst @@ -14,7 +14,7 @@ Background - Efuses are used to store the secure bootloader key (in efuse block 2), and also a single Efuse bit (ABS_DONE_0) is burned (written to 1) to permanently enable secure boot on the chip. For more details about efuse, see the (forthcoming) chapter in the Technical Reference Manual. -- To understand the secure boot process, first familiarise yourself with the standard `esp-idf boot process`. +- To understand the secure boot process, first familiarise yourself with the standard :doc:`ESP-IDF boot process <../general-notes>`. - Both stages of the boot process (initial software bootloader load, and subsequent partition & app loading) are verified by the secure boot process, in a "chain of trust" relationship. @@ -30,10 +30,11 @@ This is a high level overview of the secure boot process. Step by step instructi 2. The software bootloader image is built by esp-idf with secure boot support enabled and the public key (signature verification) portion of the secure boot signing key compiled in. This software bootloader image is flashed at offset 0x1000. 3. On first boot, the software bootloader follows the following process to enable secure boot: - - Hardware secure boot support generates a device secure bootloader key (generated via hardware RNG, then stored read/write protected in efuse), and a secure digest. The digest is derived from the key, an IV, and the bootloader image contents. - - The secure digest is flashed at offset 0x0 in the flash. - - Depending on Secure Boot Configuration, efuses are burned to disable JTAG and the ROM BASIC interpreter (it is strongly recommended these options are turned on.) - - Bootloader permanently enables secure boot by burning the ABS_DONE_0 efuse. The software bootloader then becomes protected (the chip will only boot a bootloader image if the digest matches.) + + - Hardware secure boot support generates a device secure bootloader key (generated via hardware RNG, then stored read/write protected in efuse), and a secure digest. The digest is derived from the key, an IV, and the bootloader image contents. + - The secure digest is flashed at offset 0x0 in the flash. + - Depending on Secure Boot Configuration, efuses are burned to disable JTAG and the ROM BASIC interpreter (it is strongly recommended these options are turned on.) + - Bootloader permanently enables secure boot by burning the ABS_DONE_0 efuse. The software bootloader then becomes protected (the chip will only boot a bootloader image if the digest matches.) 4. On subsequent boots the ROM bootloader sees that the secure boot efuse is burned, reads the saved digest at 0x0 and uses hardware secure boot support to compare it with a newly calculated digest. If the digest does not match then booting will not continue. The digest and comparison are performed entirely by hardware, and the calculated digest is not readable by software. For technical details see `Hardware Secure Boot Support`. @@ -175,5 +176,4 @@ Deterministic ECDSA as specified by `RFC6979`. - Image signature is 68 bytes - a 4 byte version word (currently zero), followed by a 64 bytes of signature data. These 68 bytes are appended to an app image or partition table data. -.. _esp-idf boot process: ../boot-process.rst .. _RFC6979: https://tools.ietf.org/html/rfc6979 From 13d47343992a861de7e04ae8191a630ee5b21016 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 16 Nov 2016 01:35:09 +0800 Subject: [PATCH 25/48] docs: fix Doxygen warnings, fail CI build on Doxygen warnings --- .gitlab-ci.yml | 3 + components/bt/include/bt.h | 7 +- components/driver/include/driver/gpio.h | 6 + components/driver/include/driver/ledc.h | 6 + components/driver/include/driver/uart.h | 155 +++---- components/esp32/include/esp_wifi.h | 433 +++++++++---------- components/nvs_flash/include/nvs.h | 107 ++++- components/spi_flash/include/esp_partition.h | 95 ++-- components/spi_flash/include/esp_spi_flash.h | 6 +- components/vfs/include/esp_vfs.h | 10 +- docs/Doxyfile | 3 +- 11 files changed, 444 insertions(+), 387 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1e09b55c4..1352bd6c9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -118,6 +118,9 @@ build_docs: - build_docs script: - cd docs + - doxygen + # If not building master branch, and there are Doxygen warnings, print them and bail out + - test "${CI_BUILD_REF_NAME}" = "master" || test $(cat doxygen-warning-log.txt | wc -l) -eq 0 || ( echo "Doxygen pass had some warnings:" && cat doxygen-warning-log.txt && false ) - make html artifacts: paths: diff --git a/components/bt/include/bt.h b/components/bt/include/bt.h index f476334b1..d7e0496c5 100644 --- a/components/bt/include/bt.h +++ b/components/bt/include/bt.h @@ -32,13 +32,10 @@ void bt_controller_init(void); /** @brief vhci_host_callback * used for vhci call host function to notify what host need to do - * - * notify_host_send_available: notify host can send packet to controller - * notify_host_recv: notify host that controller has packet send to host */ typedef struct vhci_host_callback { - void (*notify_host_send_available)(void); - int (*notify_host_recv)(uint8_t *data, uint16_t len); + void (*notify_host_send_available)(void); /*!< callback used to notify that the host can send packet to controller */ + int (*notify_host_recv)(uint8_t *data, uint16_t len); /*!< callback used to notify that the controller has a packet to send to the host*/ } vhci_host_callback_t; /** @brief API_vhci_host_check_send_available diff --git a/components/driver/include/driver/gpio.h b/components/driver/include/driver/gpio.h index 03eb7588f..de34ac4e3 100644 --- a/components/driver/include/driver/gpio.h +++ b/components/driver/include/driver/gpio.h @@ -117,6 +117,9 @@ extern const uint32_t GPIO_PIN_MUX_REG[GPIO_PIN_COUNT]; #define GPIO_IS_VALID_GPIO(gpio_num) ((gpio_num < GPIO_PIN_COUNT && GPIO_PIN_MUX_REG[gpio_num] != 0)) //to decide whether it is a valid GPIO number #define GPIO_IS_VALID_OUTPUT_GPIO(gpio_num) ((GPIO_IS_VALID_GPIO(gpio_num)) && (gpio_num < 34)) //to decide whether it can be a valid GPIO number of output mode +/** + * @brief Pullup/pulldown information for a single GPIO pad + */ typedef struct { uint32_t reg; /*!< Register to modify to enable or disable pullups or pulldowns */ uint32_t pu; /*!< Bit to set or clear in the above register to enable or disable the pullup, respectively */ @@ -208,6 +211,9 @@ typedef enum { GPIO_PULLDOWN_ENABLE = 0x1, /*!< Enable GPIO pull-down resistor */ } gpio_pulldown_t; +/** + * @brief Configuration parameters of GPIO pad for gpio_config function + */ typedef struct { uint64_t pin_bit_mask; /*!< GPIO pin: set with bit mask, each bit maps to a GPIO */ gpio_mode_t mode; /*!< GPIO mode: set input/output mode */ diff --git a/components/driver/include/driver/ledc.h b/components/driver/include/driver/ledc.h index 317a599fb..e07787b2b 100644 --- a/components/driver/include/driver/ledc.h +++ b/components/driver/include/driver/ledc.h @@ -78,6 +78,9 @@ typedef enum { LEDC_TIMER_15_BIT = 15, /*!< LEDC PWM depth 15Bit */ } ledc_timer_bit_t; +/** + * @brief Configuration parameters of LEDC channel for ledc_channel_config function + */ typedef struct { int gpio_num; /*!< the LEDC output gpio_num, if you want to use gpio16, gpio_num = 16*/ ledc_mode_t speed_mode; /*!< LEDC speed speed_mode, high-speed mode or low-speed mode*/ @@ -87,6 +90,9 @@ typedef struct { uint32_t duty; /*!< LEDC channel duty, the duty range is [0, (2**bit_num) - 1], */ } ledc_channel_config_t; +/** + * @brief Configuration parameters of LEDC Timer timer for ledc_timer_config function + */ typedef struct { ledc_mode_t speed_mode; /*!< LEDC speed speed_mode, high-speed mode or low-speed mode*/ ledc_timer_bit_t bit_num; /*!< LEDC channel duty depth*/ diff --git a/components/driver/include/driver/uart.h b/components/driver/include/driver/uart.h index 749cd6564..905c28826 100644 --- a/components/driver/include/driver/uart.h +++ b/components/driver/include/driver/uart.h @@ -32,11 +32,11 @@ extern "C" { #include "freertos/ringbuf.h" #include -#define UART_FIFO_LEN (128) /*< Length of the hardware FIFO buffers */ -#define UART_INTR_MASK 0x1ff -#define UART_LINE_INV_MASK (0x3f << 19) -#define UART_BITRATE_MAX 5000000 -#define UART_PIN_NO_CHANGE (-1) +#define UART_FIFO_LEN (128) /*!< Length of the hardware FIFO buffers */ +#define UART_INTR_MASK 0x1ff /*!< mask of all UART interrupts */ +#define UART_LINE_INV_MASK (0x3f << 19) /*!< TBD */ +#define UART_BITRATE_MAX 5000000 /*!< Max bit rate supported by UART */ +#define UART_PIN_NO_CHANGE (-1) /*!< Constant for uart_set_pin function which indicates that UART pin should not be changed */ #define UART_INVERSE_DISABLE (0x0) /*!< Disable UART signal inverse*/ #define UART_INVERSE_RXD (UART_RXD_INV_M) /*!< UART RXD input inverse*/ @@ -44,6 +44,9 @@ extern "C" { #define UART_INVERSE_TXD (UART_TXD_INV_M) /*!< UART TXD output inverse*/ #define UART_INVERSE_RTS (UART_RTS_INV_M) /*!< UART RTS output inverse*/ +/** + * @brief UART word length constants + */ typedef enum { UART_DATA_5_BITS = 0x0, /*!< word length: 5bits*/ UART_DATA_6_BITS = 0x1, /*!< word length: 6bits*/ @@ -52,6 +55,9 @@ typedef enum { UART_DATA_BITS_MAX = 0X4, } uart_word_length_t; +/** + * @brief UART stop bits number + */ typedef enum { UART_STOP_BITS_1 = 0x1, /*!< stop bit: 1bit*/ UART_STOP_BITS_1_5 = 0x2, /*!< stop bit: 1.5bits*/ @@ -59,6 +65,9 @@ typedef enum { UART_STOP_BITS_MAX = 0x4, } uart_stop_bits_t; +/** + * @brief UART peripheral number + */ typedef enum { UART_NUM_0 = 0x0, /*!< UART base address 0x3ff40000*/ UART_NUM_1 = 0x1, /*!< UART base address 0x3ff50000*/ @@ -66,12 +75,18 @@ typedef enum { UART_NUM_MAX, } uart_port_t; +/** + * @brief UART parity constants + */ typedef enum { UART_PARITY_DISABLE = 0x0, /*!< Disable UART parity*/ UART_PARITY_EVEN = 0x2, /*!< Enable UART even parity*/ UART_PARITY_ODD = 0x3 /*!< Enable UART odd parity*/ } uart_parity_t; +/** + * @brief UART hardware flow control modes + */ typedef enum { UART_HW_FLOWCTRL_DISABLE = 0x0, /*!< disable hardware flow control*/ UART_HW_FLOWCTRL_RTS = 0x1, /*!< enable RX hardware flow control (rts)*/ @@ -80,6 +95,9 @@ typedef enum { UART_HW_FLOWCTRL_MAX = 0x4, } uart_hw_flowcontrol_t; +/** + * @brief UART configuration parameters for uart_param_config function + */ typedef struct { int baud_rate; /*!< UART baudrate*/ uart_word_length_t data_bits; /*!< UART byte size*/ @@ -89,6 +107,9 @@ typedef struct { uint8_t rx_flow_ctrl_thresh ; /*!< UART HW RTS threshold*/ } uart_config_t; +/** + * @brief UART interrupt configuration parameters for uart_intr_config function + */ typedef struct { uint32_t intr_enable_mask; /*!< UART interrupt enable mask, choose from UART_XXXX_INT_ENA_M under UART_INT_ENA_REG(i), connect with bit-or operator*/ uint8_t rx_timeout_thresh; /*!< UART timeout interrupt threshold(unit: time of sending one byte)*/ @@ -96,6 +117,9 @@ typedef struct { uint8_t rxfifo_full_thresh; /*!< UART RX full interrupt threshold.*/ } uart_intr_config_t; +/** + * @brief UART event types used in the ringbuffer + */ typedef enum { UART_DATA, /*!< UART data event*/ UART_BREAK, /*!< UART break event*/ @@ -107,6 +131,9 @@ typedef enum { UART_EVENT_MAX, /*!< UART event max index*/ } uart_event_type_t; +/** + * @brief Event structure used in UART event queue + */ typedef struct { uart_event_type_t type; /*!< UART event type */ size_t size; /*!< UART data size for UART_DATA event*/ @@ -116,7 +143,6 @@ typedef struct { * @brief Set UART data bits. * * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * * @param data_bit UART data bits * * @return @@ -129,7 +155,6 @@ esp_err_t uart_set_word_length(uart_port_t uart_num, uart_word_length_t data_bit * @brief Get UART data bits. * * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * * @param data_bit Pointer to accept value of UART data bits. * * @return @@ -142,7 +167,6 @@ esp_err_t uart_get_word_length(uart_port_t uart_num, uart_word_length_t* data_bi * @brief Set UART stop bits. * * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * * @param bit_num UART stop bits * * @return @@ -155,7 +179,6 @@ esp_err_t uart_set_stop_bits(uart_port_t uart_num, uart_stop_bits_t bit_num); * @brief Set UART stop bits. * * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * * @param stop_bit Pointer to accept value of UART stop bits. * * @return @@ -168,7 +191,6 @@ esp_err_t uart_get_stop_bits(uart_port_t uart_num, uart_stop_bits_t* stop_bit); * @brief Set UART parity. * * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * * @param parity_mode the enum of uart parity configuration * * @return @@ -181,7 +203,6 @@ esp_err_t uart_set_parity(uart_port_t uart_num, uart_parity_t parity_mode); * @brief Get UART parity mode. * * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * * @param parity_mode Pointer to accept value of UART parity mode. * * @return @@ -195,7 +216,6 @@ esp_err_t uart_get_parity(uart_port_t uart_num, uart_parity_t* parity_mode); * @brief Set UART baud rate. * * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * * @param baud_rate UART baud-rate. * * @return @@ -208,7 +228,6 @@ esp_err_t uart_set_baudrate(uart_port_t uart_num, uint32_t baud_rate); * @brief Get UART bit-rate. * * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * * @param baudrate Pointer to accept value of UART baud rate * * @return @@ -222,10 +241,8 @@ esp_err_t uart_get_baudrate(uart_port_t uart_num, uint32_t* baudrate); * @brief Set UART line inverse mode * * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * - * @param Inverse_mask Choose the wires that need to be inversed. - * - * (inverse_mask should be chosen from UART_INVERSE_RXD/UART_INVERSE_TXD/UART_INVERSE_RTS/UART_INVERSE_CTS, combine with OR-OPERATION) + * @param inverse_mask Choose the wires that need to be inversed. + * Inverse_mask should be chosen from UART_INVERSE_RXD/UART_INVERSE_TXD/UART_INVERSE_RTS/UART_INVERSE_CTS, combine with OR operation. * * @return * - ESP_OK Success @@ -237,12 +254,9 @@ esp_err_t uart_set_line_inverse(uart_port_t uart_num, uint32_t inverse_mask); * @brief Set hardware flow control. * * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * * @param flow_ctrl Hardware flow control mode - * - * @param rx_thresh Threshold of Hardware RX flow control(0 ~ UART_FIFO_LEN) - * - * Only when UART_HW_FLOWCTRL_RTS is set , will the rx_thresh value be set. + * @param rx_thresh Threshold of Hardware RX flow control(0 ~ UART_FIFO_LEN). + * Only when UART_HW_FLOWCTRL_RTS is set, will the rx_thresh value be set. * * @return * - ESP_OK Success @@ -254,7 +268,6 @@ esp_err_t uart_set_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t flow * @brief Get hardware flow control mode * * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * * @param flow_ctrl Option for different flow control mode. * * @return @@ -267,10 +280,8 @@ esp_err_t uart_get_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t* flo * @brief Clear UART interrupt status * * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * * @param clr_mask Bit mask of the status that to be cleared. - * - * (enable_mask should be chosen from the fields of register UART_INT_CLR_REG) + * enable_mask should be chosen from the fields of register UART_INT_CLR_REG. * * @return * - ESP_OK Success @@ -282,10 +293,8 @@ esp_err_t uart_clear_intr_status(uart_port_t uart_num, uint32_t clr_mask); * @brief Set UART interrupt enable * * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * * @param enable_mask Bit mask of the enable bits. - * - * (enable_mask should be chosen from the fields of register UART_INT_ENA_REG) + * enable_mask should be chosen from the fields of register UART_INT_ENA_REG. * * @return * - ESP_OK Success @@ -297,10 +306,8 @@ esp_err_t uart_enable_intr_mask(uart_port_t uart_num, uint32_t enable_mask); * @brief Clear UART interrupt enable bits * * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * * @param disable_mask Bit mask of the disable bits. - * - * (disable_mask should be chosen from the fields of register UART_INT_ENA_REG) + * disable_mask should be chosen from the fields of register UART_INT_ENA_REG. * * @return * - ESP_OK Success @@ -346,9 +353,7 @@ esp_err_t uart_disable_tx_intr(uart_port_t uart_num); * @brief Enable UART TX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT) * * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * * @param enable 1: enable; 0: disable - * * @param thresh Threshold of TX interrupt, 0 ~ UART_FIFO_LEN * * @return @@ -358,19 +363,17 @@ esp_err_t uart_disable_tx_intr(uart_port_t uart_num); esp_err_t uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh); /** -* @brief register UART interrupt handler(ISR). -* @note - * UART ISR handler will be attached to the same CPU core that this function is running on. - * Users should know that which CPU is running and then pick a INUM that is not used by system. - * We can find the information of INUM and interrupt level in soc.h. + * @brief register UART interrupt handler(ISR). + * + * @note UART ISR handler will be attached to the same CPU core that this function is running on. + * Users should know that which CPU is running and then pick a INUM that is not used by system. + * We can find the information of INUM and interrupt level in soc.h. + * + * @attention The ISR handler function MUST be defined with attribution of "IRAM_ATTR" for now. * * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * * @param uart_intr_num UART interrupt number,check the info in soc.h, and please refer to core-isa.h for more details - * * @param fn Interrupt handler function. - * @attention - * The ISR handler function MUST be defined with attribution of "IRAM_ATTR" for now. * @param arg parameter for handler function * * @return @@ -382,18 +385,13 @@ esp_err_t uart_isr_register(uart_port_t uart_num, uint8_t uart_intr_num, void (* /** * @brief Set UART pin number * - * @note - * Internal signal can be output to multiple GPIO pads - * Only one GPIO pad can connect with input signal + * @note Internal signal can be output to multiple GPIO pads. + * Only one GPIO pad can connect with input signal. * * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * * @param tx_io_num UART TX pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin. - * * @param rx_io_num UART RX pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin. - * * @param rts_io_num UART RTS pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin. - * * @param cts_io_num UART CTS pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin. * * @return @@ -407,7 +405,6 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r * UART rx hardware flow control should not be set. * * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * * @param level 1: RTS output low(active); 0: RTS output high(block) * * @return @@ -420,7 +417,6 @@ esp_err_t uart_set_rts(uart_port_t uart_num, int level); * @brief UART set DTR level (before inverse) * * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * * @param level 1: DTR output low; 0: DTR output high * * @return @@ -433,7 +429,6 @@ esp_err_t uart_set_dtr(uart_port_t uart_num, int level); * @brief UART parameter configure * * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * * @param uart_config UART parameter settings * * @return @@ -446,7 +441,6 @@ esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_conf * @brief UART interrupt configure * * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * * @param intr_conf UART interrupt settings * * @return @@ -458,22 +452,16 @@ esp_err_t uart_intr_config(uart_port_t uart_num, const uart_intr_config_t *intr_ /** * @brief Install UART driver. * - * UART ISR handler will be attached to the same CPU core that this function is running on. - * Users should know that which CPU is running and then pick a INUM that is not used by system. - * We can find the information of INUM and interrupt level in soc.h. + * UART ISR handler will be attached to the same CPU core that this function is running on. + * Users should know that which CPU is running and then pick a INUM that is not used by system. + * We can find the information of INUM and interrupt level in soc.h. * * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * * @param rx_buffer_size UART RX ring buffer size - * * @param tx_buffer_size UART TX ring buffer size. - * - * If set to zero, driver will not use TX buffer, TX function will block task until all data have been sent out.. - * + * If set to zero, driver will not use TX buffer, TX function will block task until all data have been sent out.. * @param queue_size UART event queue size/depth. - * * @param uart_intr_num UART interrupt number,check the info in soc.h, and please refer to core-isa.h for more details - * * @param uart_queue UART event queue handle, if set NULL, driver will not use an event queue. * * @return @@ -497,7 +485,6 @@ esp_err_t uart_driver_delete(uart_port_t uart_num); * @brief Wait UART TX FIFO empty * * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * * @param ticks_to_wait Timeout, count in RTOS ticks * * @return @@ -508,15 +495,13 @@ esp_err_t uart_driver_delete(uart_port_t uart_num); esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait); /** - * @brief Send data to the UART port from a given buffer and length, - * This function will not wait for the space in TX FIFO, just fill the TX FIFO and return when the FIFO is full. - * @note - * This function should only be used when UART TX buffer is not enabled. + * @brief Send data to the UART port from a given buffer and length. + * + * This function will not wait for the space in TX FIFO, just fill the TX FIFO and return when the FIFO is full. + * @note This function should only be used when UART TX buffer is not enabled. * * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * * @param buffer data buffer address - * * @param len data length to send * * @return @@ -528,16 +513,14 @@ int uart_tx_chars(uart_port_t uart_num, const char* buffer, uint32_t len); /** * @brief Send data to the UART port from a given buffer and length, * - * If parameter tx_buffer_size is set to zero: - * This function will not return until all the data have been sent out, or at least pushed into TX FIFO. + * If parameter tx_buffer_size is set to zero: + * This function will not return until all the data have been sent out, or at least pushed into TX FIFO. * - * Otherwise, if tx_buffer_size > 0, this function will return after copying all the data to tx ringbuffer, - * then, UART ISR will move data from ring buffer to TX FIFO gradually. + * Otherwise, if tx_buffer_size > 0, this function will return after copying all the data to tx ringbuffer, + * then, UART ISR will move data from ring buffer to TX FIFO gradually. * * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * * @param src data buffer address - * * @param size data length to send * * @return @@ -549,20 +532,17 @@ int uart_write_bytes(uart_port_t uart_num, const char* src, size_t size); /** * @brief Send data to the UART port from a given buffer and length, * - * If parameter tx_buffer_size is set to zero: - * This function will not return until all the data and the break signal have been sent out. - * After all data send out, send a break signal. + * If parameter tx_buffer_size is set to zero: + * This function will not return until all the data and the break signal have been sent out. + * After all data send out, send a break signal. * - * Otherwise, if tx_buffer_size > 0, this function will return after copying all the data to tx ringbuffer, - * then, UART ISR will move data from ring buffer to TX FIFO gradually. - * After all data send out, send a break signal. + * Otherwise, if tx_buffer_size > 0, this function will return after copying all the data to tx ringbuffer, + * then, UART ISR will move data from ring buffer to TX FIFO gradually. + * After all data send out, send a break signal. * * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * * @param src data buffer address - * * @param size data length to send - * * @param brk_len break signal length (unit: time of one data bit at current_baudrate) * * @return @@ -576,11 +556,8 @@ int uart_write_bytes_with_break(uart_port_t uart_num, const char* src, size_t si * @brief UART read bytes from UART buffer * * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * * @param buf pointer to the buffer. - * * @param length data length - * * @param ticks_to_wait sTimeout, count in RTOS ticks * * @return diff --git a/components/esp32/include/esp_wifi.h b/components/esp32/include/esp_wifi.h index 88ea0d9a6..65a91929d 100644 --- a/components/esp32/include/esp_wifi.h +++ b/components/esp32/include/esp_wifi.h @@ -88,6 +88,9 @@ extern "C" { #define ESP_ERR_WIFI_PASSWORD (ESP_ERR_WIFI_BASE + 10) /*!< Passord is invalid */ #define ESP_ERR_WIFI_TIMEOUT (ESP_ERR_WIFI_BASE + 11) /*!< Timeout error */ +/** + * @brief WiFi stack configuration parameters passed to esp_wifi_init call. + */ typedef struct { system_event_handler_t event_handler; /**< WiFi event handler */ } wifi_init_config_t; @@ -108,12 +111,12 @@ typedef struct { * will post station connected event to this queue. If the queue is not initialized, WiFi * will not post any events * - * @param wifi_init_config_t *config : provide WiFi init configuration + * @param config provide WiFi init configuration * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NO_MEM : out of memory - * - others : refer to error code esp_err.h + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NO_MEM: out of memory + * - others: refer to error code esp_err.h */ esp_err_t esp_wifi_init(wifi_init_config_t *config); @@ -123,7 +126,7 @@ esp_err_t esp_wifi_init(wifi_init_config_t *config); * * @attention 1. This API should be called if you want to remove WiFi driver from the system * - * @return ESP_OK : succeed + * @return ESP_OK: succeed */ esp_err_t esp_wifi_deinit(void); @@ -133,25 +136,25 @@ esp_err_t esp_wifi_deinit(void); * Set the WiFi operating mode as station, soft-AP or station+soft-AP, * The default mode is soft-AP mode. * - * @param wifi_mode_t mode : WiFi operating modes: + * @param mode WiFi operating mode * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init - * - ESP_ERR_WIFI_ARG : invalid argument - * - others : refer to error code in esp_err.h + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init + * - ESP_ERR_WIFI_ARG: invalid argument + * - others: refer to error code in esp_err.h */ esp_err_t esp_wifi_set_mode(wifi_mode_t mode); /** * @brief Get current operating mode of WiFi * - * @param wifi_mode_t *mode : store current WiFi mode + * @param[out] mode store current WiFi mode * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init - * - ESP_ERR_WIFI_ARG : invalid argument + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init + * - ESP_ERR_WIFI_ARG: invalid argument */ esp_err_t esp_wifi_get_mode(wifi_mode_t *mode); @@ -161,29 +164,25 @@ esp_err_t esp_wifi_get_mode(wifi_mode_t *mode); * If mode is WIFI_MODE_AP, it create soft-AP control block and start soft-AP * If mode is WIFI_MODE_APSTA, it create soft-AP and station control block and start soft-AP and station * - * @param null - * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init - * - ESP_ERR_WIFI_ARG : invalid argument - * - ESP_ERR_WIFI_NO_MEM : out of memory - * - ESP_ERR_WIFI_CONN : WiFi internal error, station or soft-AP control block wrong - * - ESP_ERR_WIFI_FAIL : other WiFi internal errors + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init + * - ESP_ERR_WIFI_ARG: invalid argument + * - ESP_ERR_WIFI_NO_MEM: out of memory + * - ESP_ERR_WIFI_CONN: WiFi internal error, station or soft-AP control block wrong + * - ESP_ERR_WIFI_FAIL: other WiFi internal errors */ esp_err_t esp_wifi_start(void); /** * @brief Stop WiFi - If mode is WIFI_MODE_STA, it stop station and free station control block + * If mode is WIFI_MODE_STA, it stop station and free station control block * If mode is WIFI_MODE_AP, it stop soft-AP and free soft-AP control block * If mode is WIFI_MODE_APSTA, it stop station/soft-AP and free station/soft-AP control block * - * @param null - * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init */ esp_err_t esp_wifi_stop(void); @@ -193,52 +192,47 @@ esp_err_t esp_wifi_stop(void); * @attention 1. This API only impact WIFI_MODE_STA or WIFI_MODE_APSTA mode * @attention 2. If the ESP32 is connected to an AP, call esp_wifi_disconnect to disconnect. * - * @param null - * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init - * - ESP_ERR_WIFI_NOT_START : WiFi is not started by esp_wifi_start - * - ESP_ERR_WIFI_CONN : WiFi internal error, station or soft-AP control block wrong - * - ESP_ERR_WIFI_SSID : SSID of AP which station connects is invalid + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init + * - ESP_ERR_WIFI_NOT_START: WiFi is not started by esp_wifi_start + * - ESP_ERR_WIFI_CONN: WiFi internal error, station or soft-AP control block wrong + * - ESP_ERR_WIFI_SSID: SSID of AP which station connects is invalid */ esp_err_t esp_wifi_connect(void); /** * @brief Disconnect the ESP32 WiFi station from the AP. * - * @param null - * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init - * - ESP_ERR_WIFI_NOT_START : WiFi is not started by esp_wifi_start - * - ESP_ERR_WIFI_FAIL : other WiFi internal errors + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init + * - ESP_ERR_WIFI_NOT_START: WiFi is not started by esp_wifi_start + * - ESP_ERR_WIFI_FAIL: other WiFi internal errors */ esp_err_t esp_wifi_disconnect(void); /** * @brief Currently this API is just an stub API * - * @param null - * + * @return - * - ESP_OK : succeed - * - others : fail + * - ESP_OK: succeed + * - others: fail */ esp_err_t esp_wifi_clear_fast_connect(void); /** * @brief deauthenticate all stations or associated id equals to aid * - * @param uint16_t aid : when aid is 0, deauthenticate all stations, otherwise deauthenticate station whose associated id is aid + * @param aid when aid is 0, deauthenticate all stations, otherwise deauthenticate station whose associated id is aid * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init - * - ESP_ERR_WIFI_NOT_START : WiFi is not started by esp_wifi_start - * - ESP_ERR_WIFI_ARG : invalid argument - * - ESP_ERR_WIFI_MODE : WiFi mode is wrong + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init + * - ESP_ERR_WIFI_NOT_START: WiFi is not started by esp_wifi_start + * - ESP_ERR_WIFI_ARG: invalid argument + * - ESP_ERR_WIFI_MODE: WiFi mode is wrong */ esp_err_t esp_wifi_deauth_sta(uint16_t aid); @@ -249,88 +243,87 @@ esp_err_t esp_wifi_deauth_sta(uint16_t aid); * will be freed in esp_wifi_get_ap_list, so generally, call esp_wifi_get_ap_list to cause * the memory to be freed once the scan is done * - * @param struct scan_config *config : configuration of scanning - * @param bool block : if block is true, this API will block the caller until the scan is done, otherwise + * @param config configuration of scanning + * @param block if block is true, this API will block the caller until the scan is done, otherwise * it will return immediately * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init - * - ESP_ERR_WIFI_NOT_START : WiFi is not started by esp_wifi_start - * - ESP_ERR_WIFI_TIMEOUT : blocking scan is timeout - * - others : refer to error code in esp_err.h + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init + * - ESP_ERR_WIFI_NOT_START: WiFi is not started by esp_wifi_start + * - ESP_ERR_WIFI_TIMEOUT: blocking scan is timeout + * - others: refer to error code in esp_err.h */ -esp_err_t esp_wifi_scan_start(wifi_scan_config_t *conf, bool block); +esp_err_t esp_wifi_scan_start(wifi_scan_config_t *config, bool block); /** * @brief Stop the scan in process * - * @param null * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init - * - ESP_ERR_WIFI_NOT_START : WiFi is not started by esp_wifi_start + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init + * - ESP_ERR_WIFI_NOT_START: WiFi is not started by esp_wifi_start */ esp_err_t esp_wifi_scan_stop(void); /** * @brief Get number of APs found in last scan * - * @param uint16_t *number : store number of APIs found in last scan + * @param[out] number store number of APIs found in last scan * - * @attention This API can only be called when the scan is completed, otherwise it may get wrong value + * @attention This API can only be called when the scan is completed, otherwise it may get wrong value. * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init - * - ESP_ERR_WIFI_NOT_START : WiFi is not started by esp_wifi_start - * - ESP_ERR_WIFI_ARG : invalid argument + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init + * - ESP_ERR_WIFI_NOT_START: WiFi is not started by esp_wifi_start + * - ESP_ERR_WIFI_ARG: invalid argument */ esp_err_t esp_wifi_scan_get_ap_num(uint16_t *number); /** * @brief Get AP list found in last scan * - * @param uint16_t *number : as input param, it stores max AP number ap_records can hold, as output param, it store - the actual AP number this API returns - * @param wifi_ap_record_t *ap_records: wifi_ap_record_t array to hold the found APs + * @param[inout] number As input param, it stores max AP number ap_records can hold. + * As output param, it receives the actual AP number this API returns. + * @param ap_records wifi_ap_record_t array to hold the found APs * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init - * - ESP_ERR_WIFI_NOT_START : WiFi is not started by esp_wifi_start - * - ESP_ERR_WIFI_ARG : invalid argument - * - ESP_ERR_WIFI_NO_MEM : out of memory + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init + * - ESP_ERR_WIFI_NOT_START: WiFi is not started by esp_wifi_start + * - ESP_ERR_WIFI_ARG: invalid argument + * - ESP_ERR_WIFI_NO_MEM: out of memory */ esp_err_t esp_wifi_scan_get_ap_records(uint16_t *number, wifi_ap_record_t *ap_records); /** - * @brief Get information of AP associated with ESP32 station + * @brief Get information of AP which the ESP32 station is associated with * - * @param wifi_ap_record_t *ap_info: the wifi_ap_record_t to hold station assocated AP + * @param ap_info the wifi_ap_record_t to hold AP information * * @return - * - ESP_OK : succeed - * - others : fail + * - ESP_OK: succeed + * - others: fail */ esp_err_t esp_wifi_sta_get_ap_info(wifi_ap_record_t *ap_info); /** * @brief Set current power save type * - * @param wifi_ps_type_t type : power save type + * @param type power save type * - * @return ESP_ERR_WIFI_NOT_SUPPORT : not support yet + * @return ESP_ERR_WIFI_NOT_SUPPORT: not supported yet */ esp_err_t esp_wifi_set_ps(wifi_ps_type_t type); /** * @brief Get current power save type * - * @param wifi_ps_type_t *type : store current power save type + * @param[out] type: store current power save type * - * @return ESP_ERR_WIFI_NOT_SUPPORT : not support yet + * @return ESP_ERR_WIFI_NOT_SUPPORT: not supported yet */ esp_err_t esp_wifi_get_ps(wifi_ps_type_t *type); @@ -340,47 +333,47 @@ esp_err_t esp_wifi_get_ps(wifi_ps_type_t *type); * * @attention Currently we only support 802.11b or 802.11bg or 802.11bgn mode * - * @param wifi_interface_t ifx : interfaces - * @param uint8_t protocol : WiFi protocol bitmap + * @param ifx interfaces + * @param protocol_bitmap WiFi protocol bitmap * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init - * - ESP_ERR_WIFI_IF : invalid interface - * - others : refer to erro code in esp_err.h + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init + * - ESP_ERR_WIFI_IF: invalid interface + * - others: refer to error codes in esp_err.h */ esp_err_t esp_wifi_set_protocol(wifi_interface_t ifx, uint8_t protocol_bitmap); /** - * @brief Get the current protocol bitmap of specified ifx + * @brief Get the current protocol bitmap of the specified interface * - * @param wifi_interface_t ifx : interfaces - * @param uint8_t protocol : store current WiFi protocol bitmap of interface ifx + * @param ifx interface + * @param[out] protocol_bitmap store current WiFi protocol bitmap of interface ifx * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init - * - ESP_ERR_WIFI_IF : invalid interface - * - ESP_ERR_WIFI_ARG : invalid argument - * - others : refer to error code in esp_err.h + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init + * - ESP_ERR_WIFI_IF: invalid interface + * - ESP_ERR_WIFI_ARG: invalid argument + * - others: refer to error codes in esp_err.h */ esp_err_t esp_wifi_get_protocol(wifi_interface_t ifx, uint8_t *protocol_bitmap); /** * @brief Set the bandwidth of ESP32 specified interface * - * @attention 1. API return false if try to configure a interface that is not enable + * @attention 1. API return false if try to configure an interface that is not enabled * @attention 2. WIFI_BW_HT40 is supported only when the interface support 11N * - * @param wifi_interface_t ifx : interface to be configured - * @param wifi_bandwidth_t bw : bandwidth + * @param ifx interface to be configured + * @param bw bandwidth * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init - * - ESP_ERR_WIFI_IF : invalid interface - * - ESP_ERR_WIFI_ARG : invalid argument - * - others : refer to error code in esp_err.h + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init + * - ESP_ERR_WIFI_IF: invalid interface + * - ESP_ERR_WIFI_ARG: invalid argument + * - others: refer to error codes in esp_err.h */ esp_err_t esp_wifi_set_bandwidth(wifi_interface_t ifx, wifi_bandwidth_t bw); @@ -389,45 +382,45 @@ esp_err_t esp_wifi_set_bandwidth(wifi_interface_t ifx, wifi_bandwidth_t bw); * * @attention 1. API return false if try to get a interface that is not enable * - * @param wifi_interface_t ifx : interface to be configured - * @param wifi_bandwidth_t *bw : store bandwidth of interface ifx + * @param ifx interface to be configured + * @param[out] bw store bandwidth of interface ifx * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init - * - ESP_ERR_WIFI_IF : invalid interface - * - ESP_ERR_WIFI_ARG : invalid argument + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init + * - ESP_ERR_WIFI_IF: invalid interface + * - ESP_ERR_WIFI_ARG: invalid argument */ esp_err_t esp_wifi_get_bandwidth(wifi_interface_t ifx, wifi_bandwidth_t *bw); /** - * @brief Set primary/second channel of ESP32 + * @brief Set primary/secondary channel of ESP32 * * @attention 1. This is a special API for sniffer * - * @param uint8_t primary : for HT20, primary is the channel number, for HT40, primary is the primary channel - * @param wifi_second_chan_t second : for HT20, second is ignored, for HT40, second is the second channel + * @param primary for HT20, primary is the channel number, for HT40, primary is the primary channel + * @param second for HT20, second is ignored, for HT40, second is the second channel * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init - * - ESP_ERR_WIFI_IF : invalid interface - * - ESP_ERR_WIFI_ARG : invalid argument + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init + * - ESP_ERR_WIFI_IF: invalid interface + * - ESP_ERR_WIFI_ARG: invalid argument */ esp_err_t esp_wifi_set_channel(uint8_t primary, wifi_second_chan_t second); /** - * @brief Get the primary/second channel of ESP32 + * @brief Get the primary/secondary channel of ESP32 * * @attention 1. API return false if try to get a interface that is not enable * - * @param uint8_t *primary : store current primary channel - * @param wifi_second_chan_t *second : store current second channel + * @param primary store current primary channel + * @param[out] second store current second channel * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init - * - ESP_ERR_WIFI_ARG : invalid argument + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init + * - ESP_ERR_WIFI_ARG: invalid argument */ esp_err_t esp_wifi_get_channel(uint8_t *primary, wifi_second_chan_t *second); @@ -435,25 +428,25 @@ esp_err_t esp_wifi_get_channel(uint8_t *primary, wifi_second_chan_t *second); * @brief Set country code * The default value is WIFI_COUNTRY_CN * - * @param wifi_country_t country : country type + * @param country country type * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init - * - ESP_ERR_WIFI_ARG : invalid argument - * - others : refer to error code in esp_err.h + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init + * - ESP_ERR_WIFI_ARG: invalid argument + * - others: refer to error code in esp_err.h */ esp_err_t esp_wifi_set_country(wifi_country_t country); /** * @brief Get country code * - * @param wifi_country_t country : store current country + * @param country store current country * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init - * - ESP_ERR_WIFI_ARG : invalid argument + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init + * - ESP_ERR_WIFI_ARG: invalid argument */ esp_err_t esp_wifi_get_country(wifi_country_t *country); @@ -462,43 +455,44 @@ esp_err_t esp_wifi_get_country(wifi_country_t *country); * * @attention 1. This API can only be called when the interface is disabled * @attention 2. ESP32 soft-AP and station have different MAC addresses, do not set them to be the same. - * - The bit0 of the first byte of ESP32 MAC address can not be 1. For example, the MAC address + * @attention 3. The bit 0 of the first byte of ESP32 MAC address can not be 1. For example, the MAC address * can set to be "1a:XX:XX:XX:XX:XX", but can not be "15:XX:XX:XX:XX:XX". * - * @param wifi_interface_t ifx : interface - * @param uint8 mac[6]: the MAC address. + * @param ifx interface + * @param mac the MAC address * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init - * - ESP_ERR_WIFI_ARG : invalid argument - * - ESP_ERR_WIFI_IF : invalid interface - * - ESP_ERR_WIFI_MAC : invalid mac address - * - ESP_ERR_WIFI_MODE : WiFi mode is wrong - * - others : refer to error code in esp_err.h + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init + * - ESP_ERR_WIFI_ARG: invalid argument + * - ESP_ERR_WIFI_IF: invalid interface + * - ESP_ERR_WIFI_MAC: invalid mac address + * - ESP_ERR_WIFI_MODE: WiFi mode is wrong + * - others: refer to error codes in esp_err.h */ esp_err_t esp_wifi_set_mac(wifi_interface_t ifx, uint8_t mac[6]); /** * @brief Get mac of specified interface * - * @param uint8_t mac[6] : store mac of this interface ifx + * @param ifx interface + * @param[out] mac store mac of the interface ifx * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init - * - ESP_ERR_WIFI_ARG : invalid argument - * - ESP_ERR_WIFI_IF : invalid interface + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init + * - ESP_ERR_WIFI_ARG: invalid argument + * - ESP_ERR_WIFI_IF: invalid interface */ esp_err_t esp_wifi_get_mac(wifi_interface_t ifx, uint8_t mac[6]); /** * @brief The RX callback function in the promiscuous mode. * - * Each time a packet is received, the callback function will be called. + * Each time a packet is received, the callback function will be called. * - * @param void *buf : the data received - * @param uint16_t len : data length + * @param buf the data received + * @param len data length * * @return none */ @@ -507,36 +501,36 @@ typedef void (* wifi_promiscuous_cb_t)(void *buf, uint16_t len); /** * @brief Register the RX callback function in the promiscuous mode. * - * Each time a packet is received, the registered callback function will be called. + * Each time a packet is received, the registered callback function will be called. * - * @param wifi_promiscuous_cb_t cb : callback + * @param cb callback * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init */ esp_err_t esp_wifi_set_promiscuous_rx_cb(wifi_promiscuous_cb_t cb); /** * @brief Enable the promiscuous mode. * - * @param bool promiscuous : false - disable / true - enable + * @param en false - disable, true - enable * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init */ esp_err_t esp_wifi_set_promiscuous(bool en); /** * @brief Get the promiscuous mode. * - * @param bool *enable : store the current status of promiscuous mode + * @param[out] en store the current status of promiscuous mode * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init - * - ESP_ERR_WIFI_ARG : invalid argument + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init + * - ESP_ERR_WIFI_ARG: invalid argument */ esp_err_t esp_wifi_get_promiscuous(bool *en); @@ -548,32 +542,32 @@ esp_err_t esp_wifi_get_promiscuous(bool *en); * @attention 3. ESP32 is limited to only one channel, so when in the soft-AP+station mode, the soft-AP will adjust its channel automatically to be the same as * the channel of the ESP32 station. * - * @param wifi_interface_t ifx : interface - * @param wifi_config_t *conf : station or soft-AP configuration + * @param ifx interface + * @param conf station or soft-AP configuration * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init - * - ESP_ERR_WIFI_ARG : invalid argument - * - ESP_ERR_WIFI_IF : invalid interface - * - ESP_ERR_WIFI_MODE : invalid mode - * - ESP_ERR_WIFI_PASSWORD : invalid password - * - ESP_ERR_WIFI_NVS : WiFi internal NVS error - * - others : refer to the erro code in esp_err.h + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init + * - ESP_ERR_WIFI_ARG: invalid argument + * - ESP_ERR_WIFI_IF: invalid interface + * - ESP_ERR_WIFI_MODE: invalid mode + * - ESP_ERR_WIFI_PASSWORD: invalid password + * - ESP_ERR_WIFI_NVS: WiFi internal NVS error + * - others: refer to the erro code in esp_err.h */ esp_err_t esp_wifi_set_config(wifi_interface_t ifx, wifi_config_t *conf); /** * @brief Get configuration of specified interface * - * @param wifi_interface_t ifx : interface - * @param wifi_config_t *conf : station or soft-AP configuration + * @param ifx interface + * @param[out] conf station or soft-AP configuration * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init - * - ESP_ERR_WIFI_ARG : invalid argument - * - ESP_ERR_WIFI_IF : invalid interface + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init + * - ESP_ERR_WIFI_ARG: invalid argument + * - ESP_ERR_WIFI_IF: invalid interface */ esp_err_t esp_wifi_get_config(wifi_interface_t ifx, wifi_config_t *conf); @@ -582,14 +576,14 @@ esp_err_t esp_wifi_get_config(wifi_interface_t ifx, wifi_config_t *conf); * * @attention SSC only API * - * @param wifi_sta_list_t *sta: station list + * @param[out] sta station list * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init - * - ESP_ERR_WIFI_ARG : invalid argument - * - ESP_ERR_WIFI_MODE : WiFi mode is wrong - * - ESP_ERR_WIFI_CONN : WiFi internal error, the station/soft-AP control block is invalid + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init + * - ESP_ERR_WIFI_ARG: invalid argument + * - ESP_ERR_WIFI_MODE: WiFi mode is wrong + * - ESP_ERR_WIFI_CONN: WiFi internal error, the station/soft-AP control block is invalid */ esp_err_t esp_wifi_ap_get_sta_list(wifi_sta_list_t *sta); @@ -599,12 +593,12 @@ esp_err_t esp_wifi_ap_get_sta_list(wifi_sta_list_t *sta); * * @attention 1. The default value is WIFI_STORAGE_FLASH * - * @param wifi_storage_t storage : storage type + * @param storage : storage type * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init - * - ESP_ERR_WIFI_ARG : invalid argument + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init + * - ESP_ERR_WIFI_ARG: invalid argument */ esp_err_t esp_wifi_set_storage(wifi_storage_t storage); @@ -612,72 +606,63 @@ esp_err_t esp_wifi_set_storage(wifi_storage_t storage); * @brief Set auto connect * The default value is true * - * @param bool en : true - enable auto connect / false - disable auto connect + * @param en : true - enable auto connect / false - disable auto connect * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init - * - ESP_ERR_WIFI_MODE : WiFi internal error, the station/soft-AP control block is invalid - * - others : refer to error code in esp_err.h + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init + * - ESP_ERR_WIFI_MODE: WiFi internal error, the station/soft-AP control block is invalid + * - others: refer to error code in esp_err.h */ esp_err_t esp_wifi_set_auto_connect(bool en); /** * @brief Get the auto connect flag * - * @param bool *en : store current auto connect configuration + * @param[out] en store current auto connect configuration * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init - * - ESP_ERR_WIFI_ARG : invalid argument + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init + * - ESP_ERR_WIFI_ARG: invalid argument */ esp_err_t esp_wifi_get_auto_connect(bool *en); /** * @brief Set vendor specific element * - * @param bool enable : enable or not - * @param wifi_vendor_ie_type_t type : 0 - WIFI_VND_IE_TYPE_BEACON - * 1 - WIFI_VND_IE_TYPE_PROBE_REQ - * 2 - WIFI_VND_IE_TYPE_PROBE_RESP - * 3 - WIFI_VND_IE_TYPE_ASSOC_REQ - * 4 - WIFI_VND_IE_TYPE_ASSOC_RESP - * @param wifi_vendor_ie_id_t idx : 0 - WIFI_VND_IE_ID_0 - 1 - WIFI_VND_IE_ID_1 - * @param uint8_t *vnd_ie : pointer to a vendor specific element + * @param enable enable or not + * @param type information element type + * @param idx information element index + * @param vnd_ie pointer to a vendor specific element * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init - * - ESP_ERR_WIFI_ARG : invalid argument - * - ESP_ERR_WIFI_NO_MEM : out of memory + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init + * - ESP_ERR_WIFI_ARG: invalid argument + * - ESP_ERR_WIFI_NO_MEM: out of memory */ esp_err_t esp_wifi_set_vendor_ie(bool enable, wifi_vendor_ie_type_t type, wifi_vendor_ie_id_t idx, uint8_t *vnd_ie); /** * @brief Define function pointer for vendor specific element callback - * @param void *ctx : reserved - * @param wifi_vendor_ie_type_t type : 0 - WIFI_VND_IE_TYPE_BEACON - * 1 - WIFI_VND_IE_TYPE_PROBE_REQ - * 2 - WIFI_VND_IE_TYPE_PROBE_RESP - * 3 - WIFI_VND_IE_TYPE_ASSOC_REQ - * 4 - WIFI_VND_IE_TYPE_ASSOC_RESP - * @param const uint8_t sa[6] : source address - * @param const uint8_t *vnd_ie : pointer to a vendor specific element - * @param int rssi : received signal strength indication + * @param ctx reserved + * @param type information element type + * @param sa source address + * @param vnd_ie pointer to a vendor specific element + * @param rssi received signal strength indication */ typedef void (*esp_vendor_ie_cb_t) (void *ctx, wifi_vendor_ie_type_t type, const uint8_t sa[6], const uint8_t *vnd_ie, int rssi); /** * @brief Set vendor specific element callback * - * @param esp_vendor_ie_cb_t cb : callback function - * @param void *ctx : reserved + * @param cb callback function + * @param ctx reserved * * @return - * - ESP_OK : succeed - * - ESP_ERR_WIFI_NOT_INIT : WiFi is not initialized by eps_wifi_init + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init */ esp_err_t esp_wifi_set_vendor_ie_cb(esp_vendor_ie_cb_t cb, void *ctx); diff --git a/components/nvs_flash/include/nvs.h b/components/nvs_flash/include/nvs.h index 841895979..5f7a93a7b 100644 --- a/components/nvs_flash/include/nvs.h +++ b/components/nvs_flash/include/nvs.h @@ -77,8 +77,9 @@ typedef enum { */ esp_err_t nvs_open(const char* name, nvs_open_mode open_mode, nvs_handle *out_handle); +/**@{*/ /** - * @brief nvs_set_X - set value for given key + * @brief set value for given key * * This family of functions set value for the key, given its name. Note that * actual storage will not be updated until nvs_commit function is called. @@ -89,7 +90,6 @@ esp_err_t nvs_open(const char* name, nvs_open_mode open_mode, nvs_handle *out_ha * implementation, but is guaranteed to be at least * 16 characters. Shouldn't be empty. * @param[in] value The value to set. - * @param[in] length For nvs_set_blob: length of binary value to set, in bytes. * * @return * - ESP_OK if value was set successfully @@ -112,10 +112,39 @@ esp_err_t nvs_set_u32 (nvs_handle handle, const char* key, uint32_t value); esp_err_t nvs_set_i64 (nvs_handle handle, const char* key, int64_t value); esp_err_t nvs_set_u64 (nvs_handle handle, const char* key, uint64_t value); esp_err_t nvs_set_str (nvs_handle handle, const char* key, const char* value); -esp_err_t nvs_set_blob(nvs_handle handle, const char* key, const void* value, size_t length); +/**@}*/ /** - * @brief nvs_get_X - get value for given key + * @brief set variable length binary value for given key + * + * This family of functions set value for the key, given its name. Note that + * actual storage will not be updated until nvs_commit function is called. + * + * @param[in] handle Handle obtained from nvs_open function. + * Handles that were opened read only cannot be used. + * @param[in] key Key name. Maximal length is determined by the underlying + * implementation, but is guaranteed to be at least + * 16 characters. Shouldn't be empty. + * @param[in] value The value to set. + * @param[in] length length of binary value to set, in bytes. + * + * @return + * - ESP_OK if value was set successfully + * - ESP_ERR_NVS_INVALID_HANDLE if handle has been closed or is NULL + * - ESP_ERR_NVS_READ_ONLY if storage handle was opened as read only + * - ESP_ERR_NVS_INVALID_NAME if key name doesn't satisfy constraints + * - ESP_ERR_NVS_NOT_ENOUGH_SPACE if there is not enough space in the + * underlying storage to save the value + * - ESP_ERR_NVS_REMOVE_FAILED if the value wasn't updated because flash + * write operation has failed. The value was written however, and + * update will be finished after re-initialization of nvs, provided that + * flash operation doesn't fail again. + */ +esp_err_t nvs_set_blob(nvs_handle handle, const char* key, const void* value, size_t length); + +/**@{*/ +/** + * @brief get value for given key * * These functions retrieve value for the key, given its name. If key does not * exist, or the requested variable type doesn't match the type which was used @@ -125,7 +154,55 @@ esp_err_t nvs_set_blob(nvs_handle handle, const char* key, const void* value, si * * All functions expect out_value to be a pointer to an already allocated variable * of the given type. - * Additionally, nvs_get_str and nvs_get_blob support WinAPI-style length queries. + * + * \code{c} + * // Example of using nvs_get_i32: + * int32_t max_buffer_size = 4096; // default value + * esp_err_t err = nvs_get_i32(my_handle, "max_buffer_size", &max_buffer_size); + * assert(err == ESP_OK || err == ESP_ERR_NVS_NOT_FOUND); + * // if ESP_ERR_NVS_NOT_FOUND was returned, max_buffer_size will still + * // have its default value. + * + * \endcode + * + * @param[in] handle Handle obtained from nvs_open function. + * @param[in] key Key name. Maximal length is determined by the underlying + * implementation, but is guaranteed to be at least + * 16 characters. Shouldn't be empty. + * @param out_value Pointer to the output value. + * May be NULL for nvs_get_str and nvs_get_blob, in this + * case required length will be returned in length argument. + * + * @return + * - ESP_OK if the value was retrieved successfully + * - ESP_ERR_NVS_NOT_FOUND if the requested key doesn't exist + * - ESP_ERR_NVS_INVALID_HANDLE if handle has been closed or is NULL + * - ESP_ERR_NVS_INVALID_NAME if key name doesn't satisfy constraints + * - ESP_ERR_NVS_INVALID_LENGTH if length is not sufficient to store data + */ +esp_err_t nvs_get_i8 (nvs_handle handle, const char* key, int8_t* out_value); +esp_err_t nvs_get_u8 (nvs_handle handle, const char* key, uint8_t* out_value); +esp_err_t nvs_get_i16 (nvs_handle handle, const char* key, int16_t* out_value); +esp_err_t nvs_get_u16 (nvs_handle handle, const char* key, uint16_t* out_value); +esp_err_t nvs_get_i32 (nvs_handle handle, const char* key, int32_t* out_value); +esp_err_t nvs_get_u32 (nvs_handle handle, const char* key, uint32_t* out_value); +esp_err_t nvs_get_i64 (nvs_handle handle, const char* key, int64_t* out_value); +esp_err_t nvs_get_u64 (nvs_handle handle, const char* key, uint64_t* out_value); +/**@}*/ + +/** + * @brief get value for given key + * + * These functions retrieve value for the key, given its name. If key does not + * exist, or the requested variable type doesn't match the type which was used + * when setting a value, an error is returned. + * + * In case of any error, out_value is not modified. + * + * All functions expect out_value to be a pointer to an already allocated variable + * of the given type. + * + * nvs_get_str and nvs_get_blob functions support WinAPI-style length queries. * To get the size necessary to store the value, call nvs_get_str or nvs_get_blob * with zero out_value and non-zero pointer to length. Variable pointed to * by length argument will be set to the required length. For nvs_get_str, @@ -136,13 +213,6 @@ esp_err_t nvs_set_blob(nvs_handle handle, const char* key, const void* value, si * nvs_get/set_blob used for arbitrary data structures. * * \code{c} - * // Example of using nvs_get_i32: - * int32_t max_buffer_size = 4096; // default value - * esp_err_t err = nvs_get_i32(my_handle, "max_buffer_size", &max_buffer_size); - * assert(err == ESP_OK || err == ESP_ERR_NVS_NOT_FOUND); - * // if ESP_ERR_NVS_NOT_FOUND was returned, max_buffer_size will still - * // have its default value. - * * // Example (without error checking) of using nvs_get_str to get a string into dynamic array: * size_t required_size; * nvs_get_str(my_handle, "server_name", NULL, &required_size); @@ -163,8 +233,7 @@ esp_err_t nvs_set_blob(nvs_handle handle, const char* key, const void* value, si * @param out_value Pointer to the output value. * May be NULL for nvs_get_str and nvs_get_blob, in this * case required length will be returned in length argument. - * @param[inout] length For nvs_get_str and nvs_get_blob, non-zero pointer - * to the variable holding the length of out_value. + * @param[inout] length A non-zero pointer to the variable holding the length of out_value. * In case out_value a zero, will be set to the length * required to hold the value. In case out_value is not * zero, will be set to the actual length of the value @@ -177,16 +246,10 @@ esp_err_t nvs_set_blob(nvs_handle handle, const char* key, const void* value, si * - ESP_ERR_NVS_INVALID_NAME if key name doesn't satisfy constraints * - ESP_ERR_NVS_INVALID_LENGTH if length is not sufficient to store data */ -esp_err_t nvs_get_i8 (nvs_handle handle, const char* key, int8_t* out_value); -esp_err_t nvs_get_u8 (nvs_handle handle, const char* key, uint8_t* out_value); -esp_err_t nvs_get_i16 (nvs_handle handle, const char* key, int16_t* out_value); -esp_err_t nvs_get_u16 (nvs_handle handle, const char* key, uint16_t* out_value); -esp_err_t nvs_get_i32 (nvs_handle handle, const char* key, int32_t* out_value); -esp_err_t nvs_get_u32 (nvs_handle handle, const char* key, uint32_t* out_value); -esp_err_t nvs_get_i64 (nvs_handle handle, const char* key, int64_t* out_value); -esp_err_t nvs_get_u64 (nvs_handle handle, const char* key, uint64_t* out_value); +/**@{*/ esp_err_t nvs_get_str (nvs_handle handle, const char* key, char* out_value, size_t* length); esp_err_t nvs_get_blob(nvs_handle handle, const char* key, void* out_value, size_t* length); +/**@}*/ /** * @brief Erase key-value pair with given key name. diff --git a/components/spi_flash/include/esp_partition.h b/components/spi_flash/include/esp_partition.h index ae0185dcd..13b803e10 100644 --- a/components/spi_flash/include/esp_partition.h +++ b/components/spi_flash/include/esp_partition.h @@ -25,57 +25,78 @@ extern "C" { #endif +/** + * @file esp_partition.h + * @brief Partition APIs + */ + + +/** + * @brief Partition type + * @note Keep this enum in sync with PartitionDefinition class gen_esp32part.py + */ typedef enum { - ESP_PARTITION_TYPE_APP = 0x00, - ESP_PARTITION_TYPE_DATA = 0x01, - ESP_PARTITION_TYPE_FILESYSTEM = 0x02, + ESP_PARTITION_TYPE_APP = 0x00, //!< Application partition type + ESP_PARTITION_TYPE_DATA = 0x01, //!< Data partition type } esp_partition_type_t; +/** + * @brief Partition subtype + * @note Keep this enum in sync with PartitionDefinition class gen_esp32part.py + */ typedef enum { - ESP_PARTITION_SUBTYPE_APP_FACTORY = 0x00, - ESP_PARTITION_SUBTYPE_APP_OTA_MIN = 0x10, - ESP_PARTITION_SUBTYPE_APP_OTA_0 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 0, - ESP_PARTITION_SUBTYPE_APP_OTA_1 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 1, - ESP_PARTITION_SUBTYPE_APP_OTA_2 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 2, - ESP_PARTITION_SUBTYPE_APP_OTA_3 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 3, - ESP_PARTITION_SUBTYPE_APP_OTA_4 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 4, - ESP_PARTITION_SUBTYPE_APP_OTA_5 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 5, - ESP_PARTITION_SUBTYPE_APP_OTA_6 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 6, - ESP_PARTITION_SUBTYPE_APP_OTA_7 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 7, - ESP_PARTITION_SUBTYPE_APP_OTA_8 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 8, - ESP_PARTITION_SUBTYPE_APP_OTA_9 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 9, - ESP_PARTITION_SUBTYPE_APP_OTA_10 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 10, - ESP_PARTITION_SUBTYPE_APP_OTA_11 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 11, - ESP_PARTITION_SUBTYPE_APP_OTA_12 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 12, - ESP_PARTITION_SUBTYPE_APP_OTA_13 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 13, - ESP_PARTITION_SUBTYPE_APP_OTA_14 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 14, - ESP_PARTITION_SUBTYPE_APP_OTA_15 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 15, - ESP_PARTITION_SUBTYPE_APP_OTA_MAX = 15, - ESP_PARTITION_SUBTYPE_APP_TEST = 0x20, + ESP_PARTITION_SUBTYPE_APP_FACTORY = 0x00, //!< Factory application partition + ESP_PARTITION_SUBTYPE_APP_OTA_MIN = 0x10, //!< Base for OTA partition subtypes + ESP_PARTITION_SUBTYPE_APP_OTA_0 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 0, //!< OTA partition 0 + ESP_PARTITION_SUBTYPE_APP_OTA_1 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 1, //!< OTA partition 1 + ESP_PARTITION_SUBTYPE_APP_OTA_2 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 2, //!< OTA partition 2 + ESP_PARTITION_SUBTYPE_APP_OTA_3 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 3, //!< OTA partition 3 + ESP_PARTITION_SUBTYPE_APP_OTA_4 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 4, //!< OTA partition 4 + ESP_PARTITION_SUBTYPE_APP_OTA_5 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 5, //!< OTA partition 5 + ESP_PARTITION_SUBTYPE_APP_OTA_6 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 6, //!< OTA partition 6 + ESP_PARTITION_SUBTYPE_APP_OTA_7 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 7, //!< OTA partition 7 + ESP_PARTITION_SUBTYPE_APP_OTA_8 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 8, //!< OTA partition 8 + ESP_PARTITION_SUBTYPE_APP_OTA_9 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 9, //!< OTA partition 9 + ESP_PARTITION_SUBTYPE_APP_OTA_10 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 10,//!< OTA partition 10 + ESP_PARTITION_SUBTYPE_APP_OTA_11 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 11,//!< OTA partition 11 + ESP_PARTITION_SUBTYPE_APP_OTA_12 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 12,//!< OTA partition 12 + ESP_PARTITION_SUBTYPE_APP_OTA_13 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 13,//!< OTA partition 13 + ESP_PARTITION_SUBTYPE_APP_OTA_14 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 14,//!< OTA partition 14 + ESP_PARTITION_SUBTYPE_APP_OTA_15 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 15,//!< OTA partition 15 + ESP_PARTITION_SUBTYPE_APP_OTA_MAX = 15, //!< Max subtype of OTA partition + ESP_PARTITION_SUBTYPE_APP_TEST = 0x20, //!< Test application partition - ESP_PARTITION_SUBTYPE_DATA_OTA = 0x00, - ESP_PARTITION_SUBTYPE_DATA_RF = 0x01, - ESP_PARTITION_SUBTYPE_DATA_NVS = 0x02, + ESP_PARTITION_SUBTYPE_DATA_OTA = 0x00, //!< OTA selection partition + ESP_PARTITION_SUBTYPE_DATA_PHY = 0x01, //!< PHY init data partition + ESP_PARTITION_SUBTYPE_DATA_NVS = 0x02, //!< NVS partition - ESP_PARTITION_SUBTYPE_FILESYSTEM_ESPHTTPD = 0x00, - ESP_PARTITION_SUBTYPE_FILESYSTEM_FAT = 0x01, - ESP_PARTITION_SUBTYPE_FILESYSTEM_SPIFFS = 0x02, + ESP_PARTITION_SUBTYPE_DATA_ESPHTTPD = 0x80, //!< ESPHTTPD partition + ESP_PARTITION_SUBTYPE_DATA_FAT = 0x81, //!< FAT partition + ESP_PARTITION_SUBTYPE_DATA_SPIFFS = 0x82, //!< SPIFFS partition - ESP_PARTITION_SUBTYPE_ANY = 0xff, + ESP_PARTITION_SUBTYPE_ANY = 0xff, //!< Used to search for partitions with any subtype } esp_partition_subtype_t; +/** + * @brief Convenience macro to get esp_partition_subtype_t value for the i-th OTA partition + */ #define ESP_PARTITION_SUBTYPE_OTA(i) ((esp_partition_subtype_t)(ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ((i) & 0xf))) - +/** + * @brief Opaque partition iterator type + */ typedef struct esp_partition_iterator_opaque_* esp_partition_iterator_t; +/** + * @brief partition information structure + */ typedef struct { - esp_partition_type_t type; - esp_partition_subtype_t subtype; - uint32_t address; - uint32_t size; - char label[17]; - bool encrypted; + esp_partition_type_t type; /*!< partition type (app/data) */ + esp_partition_subtype_t subtype; /*!< partition subtype */ + uint32_t address; /*!< starting address of the partition in flash */ + uint32_t size; /*!< size of the partition, in bytes */ + char label[17]; /*!< partition label, zero-terminated ASCII string */ + bool encrypted; /*!< flag is set to true if partition is encrypted */ } esp_partition_t; /** diff --git a/components/spi_flash/include/esp_spi_flash.h b/components/spi_flash/include/esp_spi_flash.h index 840bbc497..5d124da6b 100644 --- a/components/spi_flash/include/esp_spi_flash.h +++ b/components/spi_flash/include/esp_spi_flash.h @@ -62,13 +62,13 @@ esp_err_t spi_flash_erase_sector(size_t sector); /** * @brief Erase a range of flash sectors * - * @param uint32_t start_address : Address where erase operation has to start. + * @param start_address Address where erase operation has to start. * Must be 4kB-aligned - * @param uint32_t size : Size of erased range, in bytes. Must be divisible by 4kB. + * @param size Size of erased range, in bytes. Must be divisible by 4kB. * * @return esp_err_t */ -esp_err_t spi_flash_erase_range(size_t start_addr, size_t size); +esp_err_t spi_flash_erase_range(size_t start_address, size_t size); /** diff --git a/components/vfs/include/esp_vfs.h b/components/vfs/include/esp_vfs.h index 2d9e52c5a..7dd273fb0 100644 --- a/components/vfs/include/esp_vfs.h +++ b/components/vfs/include/esp_vfs.h @@ -57,15 +57,15 @@ extern "C" { * flags member to ESP_VFS_FLAG_CONTEXT_PTR and provide the context pointer * to esp_vfs_register function. * If the implementation doesn't use this extra argument, populate the - * members without _p suffix and set flags memeber to ESP_VFS_FLAG_DEFAULT. + * members without _p suffix and set flags member to ESP_VFS_FLAG_DEFAULT. * * If the FS driver doesn't provide some of the functions, set corresponding * members to NULL. */ typedef struct { - int fd_offset; - int flags; + int fd_offset; /*!< file descriptor offset, determined by the FS driver */ + int flags; /*!< ESP_VFS_FLAG_CONTEXT_PTR or ESP_VFS_FLAG_DEFAULT */ union { size_t (*write_p)(void* p, int fd, const void * data, size_t size); size_t (*write)(int fd, const void * data, size_t size); @@ -135,7 +135,7 @@ esp_err_t esp_vfs_register(const char* base_path, const esp_vfs_t* vfs, void* ct * These functions are to be used in newlib syscall table. They will be called by * newlib when it needs to use any of the syscalls. */ - +/**@{*/ ssize_t esp_vfs_write(struct _reent *r, int fd, const void * data, size_t size); off_t esp_vfs_lseek(struct _reent *r, int fd, off_t size, int mode); ssize_t esp_vfs_read(struct _reent *r, int fd, void * dst, size_t size); @@ -146,7 +146,7 @@ int esp_vfs_stat(struct _reent *r, const char * path, struct stat * st); int esp_vfs_link(struct _reent *r, const char* n1, const char* n2); int esp_vfs_unlink(struct _reent *r, const char *path); int esp_vfs_rename(struct _reent *r, const char *src, const char *dst); - +/**@}*/ #ifdef __cplusplus diff --git a/docs/Doxyfile b/docs/Doxyfile index a46f014a5..0e4549a10 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -20,9 +20,8 @@ XML_OUTPUT = xml GENERATE_HTML = NO HAVE_DOT = NO GENERATE_LATEX = NO -GENERATE_MAN = NO +GENERATE_MAN = YES GENERATE_RTF = NO -QUIET = YES WARN_LOGFILE = "doxygen-warning-log.txt" From 4eeb2bc41e43c850d468ed9132c0202f0ddbf638 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 16 Nov 2016 10:35:47 +1100 Subject: [PATCH 26/48] build system: Fix embedding files which are themselves generated by the build system Used by secure boot, which generates the secure boot signing key inside build/. --- make/component_wrapper.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/component_wrapper.mk b/make/component_wrapper.mk index 55a135158..6f903f9fc 100644 --- a/make/component_wrapper.mk +++ b/make/component_wrapper.mk @@ -194,7 +194,7 @@ OBJCOPY_EMBED_ARGS := --input binary --output elf32-xtensa-le --binary-architect define GenerateEmbedTarget $(1).$(2).o: $(call resolvepath,$(1),$(COMPONENT_PATH)) | $$(dir $(1)) $(summary) EMBED $$@ - $$(if $$(filter-out $$(notdir $$(abspath $$<)),$$(abspath $$(notdir $$<))), cp $$< $$(notdir $$<) ) # copy input file to build dir, unless already in build dir + $(if $(filter-out $$(notdir $$(abspath $$<)),$$(abspath $$(notdir $$<))), cp $$< $$(notdir $$<) ) # copy input file to build dir, unless already in build dir $$(if $$(subst bin,,$(2)),echo -ne '\0' >> $$(notdir $$<) ) # trailing NUL byte on text output $(OBJCOPY) $(OBJCOPY_EMBED_ARGS) $$(notdir $$<) $$@ rm $$(notdir $$<) From 24b4c17ead152119736716347b29e9266462ab75 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 16 Nov 2016 11:12:48 +1100 Subject: [PATCH 27/48] build system: Refactor SubmoduleCheck to work project-wide Required at project level because some components use header files in other components' submodules, and one component with a submodule (esptool.py) doesn't have or need a component.mk. --- components/bt/component.mk | 3 +- components/esp32/component.mk | 4 +-- components/esptool_py/Makefile.projbuild | 4 ++- docs/build_system.rst | 8 +++++ make/common.mk | 25 ---------------- make/component_wrapper.mk | 5 ++-- make/project.mk | 37 +++++++++++++++++++++--- 7 files changed, 49 insertions(+), 37 deletions(-) diff --git a/components/bt/component.mk b/components/bt/component.mk index 91620ddc1..d6bde0c5b 100644 --- a/components/bt/component.mk +++ b/components/bt/component.mk @@ -15,5 +15,4 @@ COMPONENT_ADD_LDFLAGS := -lbt -L $(COMPONENT_PATH)/lib \ ALL_LIB_FILES := $(patsubst %,$(COMPONENT_PATH)/lib/lib%.a,$(LIBS)) $(COMPONENT_LIBRARY): $(ALL_LIB_FILES) -# automatically trigger a git submodule update if BT library is missing -$(eval $(call SubmoduleCheck,$(ALL_LIB_FILES),$(COMPONENT_PATH)/lib)) +COMPONENT_SUBMODULES += lib diff --git a/components/esp32/component.mk b/components/esp32/component.mk index 040c686e5..8059d157c 100644 --- a/components/esp32/component.mk +++ b/components/esp32/component.mk @@ -17,9 +17,7 @@ COMPONENT_ADD_LDFLAGS := -lesp32 \ ALL_LIB_FILES := $(patsubst %,$(COMPONENT_PATH)/lib/lib%.a,$(LIBS)) -# automatically trigger a git submodule update -# if any libraries are missing -$(eval $(call SubmoduleCheck,$(ALL_LIB_FILES),$(COMPONENT_PATH)/lib)) +COMPONENT_SUBMODULES += lib # this is a hack to make sure the app is re-linked if the binary # libraries change or are updated. If they change, the main esp32 diff --git a/components/esptool_py/Makefile.projbuild b/components/esptool_py/Makefile.projbuild index aa3bb2bfa..acbada724 100644 --- a/components/esptool_py/Makefile.projbuild +++ b/components/esptool_py/Makefile.projbuild @@ -54,4 +54,6 @@ app-flash: $(APP_BIN) $(ESPTOOLPY_SRC) @echo "Flashing app to serial port $(ESPPORT), offset $(CONFIG_APP_OFFSET)..." $(ESPTOOLPY_WRITE_FLASH) $(CONFIG_APP_OFFSET) $(APP_BIN) -$(eval $(call SubmoduleCheck,$(ESPTOOLPY_SRC),$(COMPONENT_PATH)/esptool)) +# Submodules normally added in component.mk, but can be added +# at the project level as long as qualified path +COMPONENT_SUBMODULES += $(COMPONENT_PATH)/esptool diff --git a/docs/build_system.rst b/docs/build_system.rst index 8168cb76e..aa14cdda5 100644 --- a/docs/build_system.rst +++ b/docs/build_system.rst @@ -186,6 +186,14 @@ The following variables can be set inside ``component.mk`` to control build sett generates an include file which you then want to include in another component. Most components do not need to set this variable. +The following variable only works for components that are part of esp-idf itself: + +- ``COMPONENT_SUBMODULES``: Optional list of git submodule paths + (relative to COMPONENT_PATH) used by the component. These will be + checked (and initialised if necessary) by the build process. This + variable is ignored if the component is outside the IDF_PATH + directory. + Optional Component-Specific Variables ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/make/common.mk b/make/common.mk index 6e4fa75ab..4d40f7abc 100644 --- a/make/common.mk +++ b/make/common.mk @@ -26,31 +26,6 @@ details := @true MAKEFLAGS += --silent endif -# Pseudo-target to check a git submodule has been properly initialised -# -# $(eval $(call SubmoduleCheck,FILENAMES,SUBMODULE_PATH)) to create a target that -# automatically runs 'git submodule update --init SUBMODULE_PATH' if any of -# the files in FILENAMES are missing, and fails if this is not possible. -# -# Will also print a WARNING if the submodule at SUBMODULE_PATH appears -# to require an update. -define SubmoduleCheck -$(1): - @echo "WARNING: Missing submodule $(2) for $$@..." - [ -d ${IDF_PATH}/.git ] || ( echo "ERROR: esp-idf must be cloned from git to work."; exit 1) - [ -x $(which git) ] || ( echo "ERROR: Need to run 'git submodule --init' in esp-idf root directory."; exit 1) - @echo "Attempting 'git submodule update --init' in esp-idf root directory..." - cd ${IDF_PATH} && git submodule update --init $(2) - -# Parse 'git submodule status' output for out-of-date submodule. -# Status output prefixes status line with '+' if the submodule commit doesn't match -ifneq ("$(shell cd ${IDF_PATH} && git submodule status $(2) | grep '^+')","") -$$(info WARNING: git submodule $2 may be out of date. Run 'git submodule update' to update.) -endif -endef - - - # General make utilities # convenience variable for printing an 80 asterisk wide separator line diff --git a/make/component_wrapper.mk b/make/component_wrapper.mk index 6f903f9fc..005c99671 100644 --- a/make/component_wrapper.mk +++ b/make/component_wrapper.mk @@ -103,8 +103,8 @@ endef # component_project_vars.mk target for the component. This is used to # take component.mk variables COMPONENT_ADD_INCLUDEDIRS, -# COMPONENT_ADD_LDFLAGS and COMPONENT_DEPENDS and inject those into -# the project make pass. +# COMPONENT_ADD_LDFLAGS, COMPONENT_DEPENDS and COMPONENT_SUBMODULES +# and inject those into the project make pass. # # The target here has no dependencies, as the parent target in # project.mk evaluates dependencies before calling down to here. See @@ -119,6 +119,7 @@ component_project_vars.mk:: @echo '# Automatically generated build file. Do not edit.' > $@ @echo 'COMPONENT_INCLUDES += $(call MakeVariablePath,$(addprefix $(COMPONENT_PATH)/,$(COMPONENT_ADD_INCLUDEDIRS)))' >> $@ @echo 'COMPONENT_LDFLAGS += $(call MakeVariablePath,$(COMPONENT_ADD_LDFLAGS))' >> $@ + @echo 'COMPONENT_SUBMODULES += $(call MakeVariablePath,$(addprefix $(COMPONENT_PATH)/,$(COMPONENT_SUBMODULES)))' >> $@ @echo '$(COMPONENT_NAME)-build: $(addsuffix -build,$(COMPONENT_DEPENDS))' >> $@ diff --git a/make/project.mk b/make/project.mk index a08199280..870db55f9 100644 --- a/make/project.mk +++ b/make/project.mk @@ -10,7 +10,7 @@ # where this file is located. # -.PHONY: build-components menuconfig defconfig all build clean all_binaries +.PHONY: build-components menuconfig defconfig all build clean all_binaries check-submodules all: all_binaries # see below for recipe of 'all' target # @@ -94,13 +94,16 @@ COMPONENT_PATHS += $(abspath $(SRCDIRS)) # A component is buildable if it has a component.mk makefile in it COMPONENT_PATHS_BUILDABLE := $(foreach cp,$(COMPONENT_PATHS),$(if $(wildcard $(cp)/component.mk),$(cp))) -# Initialise a project-wide list of include dirs (COMPONENT_INCLUDES), -# and LDFLAGS args (COMPONENT_LDFLAGS) supplied by each component. +# Initialise project-wide variables which can be added to by +# each component. # # These variables are built up via the component_project_vars.mk # generated makefiles (one per component). +# +# See docs/build-system.rst for more details. COMPONENT_INCLUDES := COMPONENT_LDFLAGS := +COMPONENT_SUBMODULES := # COMPONENT_PROJECT_VARS is the list of component_project_vars.mk generated makefiles # for each component. @@ -289,7 +292,7 @@ endef define GenerateComponentTargets .PHONY: $(2)-build $(2)-clean -$(2)-build: +$(2)-build: check-submodules $(call ComponentMake,$(1),$(2)) build $(2)-clean: @@ -332,4 +335,30 @@ app-clean: $(addsuffix -clean,$(notdir $(COMPONENT_PATHS_BUILDABLE))) config-clean: app-clean clean: config-clean +# phony target to check if any git submodule listed in COMPONENT_SUBMODULES are missing +# or out of date, and exit if so. Components can add paths to this variable. +# +# This only works for components inside IDF_PATH +check-submodules: +# Generate a target to check this submodule +# $(1) - submodule directory, relative to IDF_PATH +define GenerateSubmoduleCheckTarget +check-submodules: $(IDF_PATH)/$(1)/.git +$(IDF_PATH)/$(1)/.git: + @echo "WARNING: Missing submodule $(1)..." + [ -d ${IDF_PATH}/.git ] || ( echo "ERROR: esp-idf must be cloned from git to work."; exit 1) + [ -x $(which git) ] || ( echo "ERROR: Need to run 'git submodule init $(1)' in esp-idf root directory."; exit 1) + @echo "Attempting 'git submodule update --init $(1)' in esp-idf root directory..." + cd ${IDF_PATH} && git submodule update --init $(1) + +# Parse 'git submodule status' output for out-of-date submodule. +# Status output prefixes status line with '+' if the submodule commit doesn't match +ifneq ("$(shell cd ${IDF_PATH} && git submodule status $(1) | grep '^+')","") +$$(info WARNING: git submodule $(1) may be out of date. Run 'git submodule update' to update.) +endif +endef + +# filter/subst in expression ensures all submodule paths begin with $(IDF_PATH), and then strips that prefix +# so the argument is suitable for use with 'git submodule' commands +$(foreach submodule,$(subst $(IDF_PATH)/,,$(filter $(IDF_PATH)/%,$(COMPONENT_SUBMODULES))),$(eval $(call GenerateSubmoduleCheckTarget,$(submodule)))) From 84635a160e0b6765e031c562c6a38f0d078c69f7 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 16 Nov 2016 11:18:40 +1100 Subject: [PATCH 28/48] micro-ecc: Add submodule dependency Closes github #100 --- components/micro-ecc/component.mk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/micro-ecc/component.mk b/components/micro-ecc/component.mk index df73f7a3b..8c569df59 100644 --- a/components/micro-ecc/component.mk +++ b/components/micro-ecc/component.mk @@ -4,3 +4,5 @@ COMPONENT_SRCDIRS := micro-ecc COMPONENT_OBJS := micro-ecc/uECC.o COMPONENT_ADD_INCLUDEDIRS := micro-ecc + +COMPONENT_SUBMODULES := micro-ecc From 872a481cf1c526263c0bf90afc0ebf7c25aa6a47 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 16 Nov 2016 11:45:39 +1100 Subject: [PATCH 29/48] build system: When embedding binary files, fix re-generating on partial builds When embedding a generated file (ie secure boot public key data), the file was being re-generated each time. --- make/component_wrapper.mk | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/make/component_wrapper.mk b/make/component_wrapper.mk index 005c99671..2c073af76 100644 --- a/make/component_wrapper.mk +++ b/make/component_wrapper.mk @@ -189,18 +189,29 @@ OBJCOPY_EMBED_ARGS := --input binary --output elf32-xtensa-le --binary-architect # txt files are null-terminated before being embedded (otherwise # identical behaviour.) # -# Files are temporarily copied to the build directory before objcopy, -# because objcopy generates the symbol name from the full command line -# path to the input file. define GenerateEmbedTarget -$(1).$(2).o: $(call resolvepath,$(1),$(COMPONENT_PATH)) | $$(dir $(1)) + +# copy the input file into the build dir (using a subdirectory +# in case the file already exists elsewhere in the build dir) +embed_bin/$$(notdir $(1)): $(call resolvepath,$(1),$(COMPONENT_PATH)) | embed_bin + cp $$< $$@ + +embed_txt/$$(notdir $(1)): $(call resolvepath,$(1),$(COMPONENT_PATH)) | embed_txt + cp $$< $$@ + echo -ne '\0' >> $$@ # null-terminate text files + +# messing about with the embed_X subdirectory then using 'cd' for objcopy is because the +# full path passed to OBJCOPY makes it into the name of the symbols in the .o file +$(1).$(2).o: embed_$(2)/$$(notdir $(1)) | $$(dir $(1)) $(summary) EMBED $$@ - $(if $(filter-out $$(notdir $$(abspath $$<)),$$(abspath $$(notdir $$<))), cp $$< $$(notdir $$<) ) # copy input file to build dir, unless already in build dir - $$(if $$(subst bin,,$(2)),echo -ne '\0' >> $$(notdir $$<) ) # trailing NUL byte on text output - $(OBJCOPY) $(OBJCOPY_EMBED_ARGS) $$(notdir $$<) $$@ - rm $$(notdir $$<) + cd embed_$(2); $(OBJCOPY) $(OBJCOPY_EMBED_ARGS) $$(notdir $$<) ../$$@ + +CLEAN_FILES += embed_$(2)/$$(notdir $(1)) endef +embed_txt embed_bin: + mkdir -p $@ + # generate targets to embed binary & text files $(foreach binfile,$(COMPONENT_EMBED_FILES), $(eval $(call GenerateEmbedTarget,$(binfile),bin))) From 78d084942670c1703af3da58d0fa91f07fd19953 Mon Sep 17 00:00:00 2001 From: Benjamin Vernoux Date: Fri, 28 Oct 2016 22:25:14 +0200 Subject: [PATCH 30/48] Simplified "Installing OpenOCD" with git clone --recursive --- docs/openocd.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/openocd.rst b/docs/openocd.rst index 2dcb55f0c..642e3067e 100644 --- a/docs/openocd.rst +++ b/docs/openocd.rst @@ -40,10 +40,8 @@ Installing OpenOCD The sources for the ESP32-enabled variant of OpenOCD are available from `Espressifs Github `_. To download the source, use the following commands:: - git clone https://github.com/espressif/openocd-esp32.git + git clone --recursive https://github.com/espressif/openocd-esp32.git cd openocd-esp32 - git submodule init - git submodule update For compilation of OpenOCD, please refer to the README, README.OSX and README.Windows file in the openocd-esp32 directory. You can skip the ``make install`` step if you want. From ceea97495f5070e50ba3b36de3b9f1a0afcf5226 Mon Sep 17 00:00:00 2001 From: Liu Zhi Fu Date: Thu, 17 Nov 2016 10:22:20 +0800 Subject: [PATCH 31/48] lwip:refractor to the description about this menuconfig option --- components/lwip/Kconfig | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/components/lwip/Kconfig b/components/lwip/Kconfig index 7661fe6cb..bf7bff15b 100644 --- a/components/lwip/Kconfig +++ b/components/lwip/Kconfig @@ -4,16 +4,17 @@ config L2_TO_L3_COPY bool "Enable copy between Layer2 and Layer3 packets" default 0 help - If this feature is enabled, then all traffic from layer2(WIFI Driver) - to layer3(LWIP stack) will make a copy, the layer2 buffer will be - freed and the copy will be sent to layer3. Please be notified that the - total layer2 receiving buffer is fixed and ESP32 currently supports 25 - layer2 receiving buffer, when layer2 buffer runs out of memory, then the - incoming packets will be dropped in hardware. The layer3 buffer is - allocated from the heap, so the total layer3 receiving buffer depends - on the available heap size, when heap runs out of memory, no copy will - be sent to layer3 and packet will be dropped in layer2. Please make sure - you fully understand the impact of this feature before enabling it. + If this feature is enabled, all traffic from layer2(WIFI Driver) will be + copied to a new buffer before sending it to layer3(LWIP stack), freeing + the layer2 buffer. + Please be notified that the total layer2 receiving buffer is fixed and + ESP32 currently supports 25 layer2 receiving buffer, when layer2 buffer + runs out of memory, then the incoming packets will be dropped in hardware. + The layer3 buffer is allocated from the heap, so the total layer3 receiving + buffer depends on the available heap size, when heap runs out of memory, + no copy will be sent to layer3 and packet will be dropped in layer2. + Please make sure you fully understand the impact of this feature before + enabling it. config LWIP_MAX_SOCKETS int "Max number of open sockets" From 5e428f21b6e07825ce041acc9a4b84bdeddb1dc9 Mon Sep 17 00:00:00 2001 From: Liu Zhi Fu Date: Thu, 17 Nov 2016 10:53:00 +0800 Subject: [PATCH 32/48] lwip: default ESP_L2_TO_L3_COPY to 0 --- components/lwip/include/lwip/lwip/opt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/lwip/include/lwip/lwip/opt.h b/components/lwip/include/lwip/lwip/opt.h index 9a1d10afb..c42f3cd73 100755 --- a/components/lwip/include/lwip/lwip/opt.h +++ b/components/lwip/include/lwip/lwip/opt.h @@ -3012,7 +3012,7 @@ * ESP_L2_TO_L3_COPY: enable memcpy when receiving packet from L2 */ #ifndef ESP_L2_TO_L3_COPY -#define ESP_L2_TO_L3_COPY 1 +#define ESP_L2_TO_L3_COPY 0 #endif #ifndef ESP_THREAD_SAFE_DEBUG From f12be7ebd8c5b0006a94c1ddaa492555ffc73d78 Mon Sep 17 00:00:00 2001 From: Liu Zhi Fu Date: Thu, 17 Nov 2016 11:22:20 +0800 Subject: [PATCH 33/48] nvs_flash: adjust the nvs_flash start sector number Modify the nvs flash start sector from 6 to 9 --- components/nvs_flash/src/nvs_api.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/nvs_flash/src/nvs_api.cpp b/components/nvs_flash/src/nvs_api.cpp index c1a910260..f6c6c588a 100644 --- a/components/nvs_flash/src/nvs_api.cpp +++ b/components/nvs_flash/src/nvs_api.cpp @@ -63,7 +63,7 @@ extern "C" void nvs_dump() extern "C" esp_err_t nvs_flash_init(void) { - return nvs_flash_init_custom(6, 3); + return nvs_flash_init_custom(9, 3); } extern "C" esp_err_t nvs_flash_init_custom(uint32_t baseSector, uint32_t sectorCount) From 12dd886ee194004ce8f9e74c1b3329b3b40129be Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 16 Nov 2016 18:03:55 +1100 Subject: [PATCH 34/48] build system: Use correct objcopy arguments for object format Avoid ambiguous argument error on some platforms Ref internal discussion !198 squash! build system: Use correct objcopy --input-target argument not --input --- make/component_wrapper.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/component_wrapper.mk b/make/component_wrapper.mk index 2c073af76..3018c18b5 100644 --- a/make/component_wrapper.mk +++ b/make/component_wrapper.mk @@ -180,7 +180,7 @@ $(foreach srcdir,$(COMPONENT_SRCDIRS), $(eval $(call GenerateCompileTargets,$(sr ## Support for embedding binary files into the ELF as symbols -OBJCOPY_EMBED_ARGS := --input binary --output elf32-xtensa-le --binary-architecture xtensa --rename-section .data=.rodata.embedded +OBJCOPY_EMBED_ARGS := --input-target binary --output-target elf32-xtensa-le --binary-architecture xtensa --rename-section .data=.rodata.embedded # Generate pattern for embedding text or binary files into the app # $(1) is name of file (as relative path inside component) From 936b02216b49af02488d058e80c2b58dc771fd51 Mon Sep 17 00:00:00 2001 From: Liu Zhi Fu Date: Thu, 17 Nov 2016 11:44:39 +0800 Subject: [PATCH 35/48] docs/nvs_flash: update the nvs flash offset comment according review --- components/nvs_flash/include/nvs_flash.h | 2 +- docs/partition-tables.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/nvs_flash/include/nvs_flash.h b/components/nvs_flash/include/nvs_flash.h index 1cade0e95..d6e199025 100644 --- a/components/nvs_flash/include/nvs_flash.h +++ b/components/nvs_flash/include/nvs_flash.h @@ -21,7 +21,7 @@ extern "C" { /** Initialise NVS flash storage with default flash sector layout Temporarily, this region is hardcoded as a 12KB (0x3000 byte) - region starting at 24KB (0x6000 byte) offset in flash. + region starting at 36KB (0x9000 byte) offset in flash. @return ESP_OK if flash was successfully initialised. */ diff --git a/docs/partition-tables.rst b/docs/partition-tables.rst index 5f5911bd5..a1a46866e 100644 --- a/docs/partition-tables.rst +++ b/docs/partition-tables.rst @@ -23,7 +23,7 @@ Known Issues The below design document outlines the goals for the partition table system. At the moment, only some features are used: - data partition types "rf" & "wifi" are unused and can be entirely omitted to save space. -- NVS (non-volatile-storage) uses a hardcoded 12KB (0x3000 byte) region at offset 0x6000. +- NVS (non-volatile-storage) uses a hardcoded 12KB (0x3000 byte) region at offset 0x9000. Once a full user API is in place for partition access, these limitations will be resolved and you'll be able to use the partition mechanism fully for storing data in flash. From d19d7107d34541bf6edc9d9e80daeff394904cf4 Mon Sep 17 00:00:00 2001 From: Liu Zhi Fu Date: Thu, 17 Nov 2016 11:56:22 +0800 Subject: [PATCH 36/48] esp32: tw8706 softap join ap return wrong code In softap/null mode, esp_wifi_connect will return ESP_ERR_WIFI_MODE --- components/esp32/lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esp32/lib b/components/esp32/lib index 41da160a5..e188536a6 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit 41da160a5dbf9e13b4fb51f31acf372f50c28270 +Subproject commit e188536a6315cc3ce4f1006ac3a4450faea6abc6 From d116adf260358180807045ad047dc95f302a2f52 Mon Sep 17 00:00:00 2001 From: Jeroen Domburg Date: Thu, 17 Nov 2016 12:09:08 +0800 Subject: [PATCH 37/48] Add documentation --- components/esp32/include/esp_int_wdt.h | 3 -- components/esp32/include/esp_task_wdt.h | 9 ---- docs/Doxyfile | 4 +- docs/api/wdts.rst | 72 +++++++++++++++++++++++++ docs/index.rst | 5 +- 5 files changed, 78 insertions(+), 15 deletions(-) create mode 100644 docs/api/wdts.rst diff --git a/components/esp32/include/esp_int_wdt.h b/components/esp32/include/esp_int_wdt.h index 438740039..b32d0219f 100644 --- a/components/esp32/include/esp_int_wdt.h +++ b/components/esp32/include/esp_int_wdt.h @@ -41,9 +41,6 @@ This uses the TIMERG1 WDT. * @brief Initialize the interrupt watchdog. This is called in the init code if * the interrupt watchdog is enabled in menuconfig. * - * @param null - * - * @return null */ void esp_int_wdt_init(); diff --git a/components/esp32/include/esp_task_wdt.h b/components/esp32/include/esp_task_wdt.h index bbc499567..eb7737700 100644 --- a/components/esp32/include/esp_task_wdt.h +++ b/components/esp32/include/esp_task_wdt.h @@ -42,9 +42,6 @@ This uses the TIMERG0 WDT. * @brief Initialize the task watchdog. This is called in the init code, if the * task watchdog is enabled in menuconfig. * - * @param null - * - * @return null */ void esp_task_wdt_init(); @@ -52,9 +49,6 @@ void esp_task_wdt_init(); * @brief Feed the watchdog. After the first feeding session, the watchdog will expect the calling * task to keep feeding the watchdog until task_wdt_delete() is called. * - * @param null - * - * @return null */ void esp_task_wdt_feed(); @@ -63,9 +57,6 @@ void esp_task_wdt_feed(); /** * @brief Delete the watchdog for the current task. * - * @param null - * - * @return null */ void esp_task_wdt_delete(); diff --git a/docs/Doxyfile b/docs/Doxyfile index 6ff4c4586..d5970ee5e 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -1,6 +1,8 @@ PROJECT_NAME = "ESP32 Programming Guide" -INPUT = ../components/esp32/include/esp_wifi.h ../components/driver/include/driver ../components/bt/include ../components/nvs_flash/include ../components/log/include ../components/vfs/include +INPUT = ../components/esp32/include/esp_wifi.h ../components/driver/include/driver ../components/bt/include \ + ../components/nvs_flash/include ../components/log/include ../components/vfs/include \ + ../components/esp32/include/esp_int_wdt.h ../components/esp32/include/esp_task_wdt.h WARN_NO_PARAMDOC = YES diff --git a/docs/api/wdts.rst b/docs/api/wdts.rst new file mode 100644 index 000000000..1b476f2f7 --- /dev/null +++ b/docs/api/wdts.rst @@ -0,0 +1,72 @@ +Watchdogs +========= + +Overview +-------- + +Esp-idf has support for two types of watchdogs: a task watchdog as well as an interrupt watchdog. Both can be +enabled using ``make menuconfig`` and selecting the appropriate options. + +Interrupt watchdog +^^^^^^^^^^^^^^^^^^ + +The interrupt watchdog makes sure the FreeRTOS task switching interrupt isn't blocked for a long time. This +is bad because no other tasks, including potentially important ones like the WiFi task and the idle task, +can't get any CPU runtime. A blocked task switching interrupt can happen because a program runs into an +infinite loop with interrupts disabled or hangs in an interrupt. + +The default action of the interrupt watchdog is to invoke the panic handler. causing a register dump and an opportunity +for the programmer to find out, using either OpenOCD or gdbstub, what bit of code is stuck with interrupts +disabled. Depending on the configuration of the panic handler, it can also blindly reset the CPU, which may be +preferred in a production environment. + +The interrupt watchdog is built around the hardware watchdog in timer group 1. If this watchdog for some reason +cannot execute the NMI handler that invokes the panic handler (e.g. because IRAM is overwritten by garbage), +it will hard-reset the SOC. + +Task watchdog +^^^^^^^^^^^^^ + +Any tasks can elect to be watched by the task watchdog. If such a task does not feed the watchdog within the time +specified by the task watchdog timeout (which is configurable using ``make menuconfig``), the watchdog will +print out a warning with information about which processes are running on the ESP32 CPUs and which processes +failed to feed the watchdog. + +By default, the task watchdog watches the idle tasks. The usual cause of idle tasks not feeding the watchdog +is a higher-priority process looping without yielding to the lower-priority processes, and can be an indicator +of badly-written code that spinloops on a peripheral or a task that is stuck in an infinite loop. + +Other task can elect to be watched by the task watchdog by calling ``esp_task_wdt_feed()``. Calling this routine +for the first time will register the task to the task watchdog; calling it subsequent times will feed +the watchdog. If a task does not want to be watched anymore (e.g. because it is finished and will call +``vTaskDelete()`` on itself), it needs to call ``esp_task_wdt_delete()``. + +The task watchdog is built around the hardware watchdog in timer group 0. If this watchdog for some reason +cannot execute the interrupt handler that prints the task data (e.g. because IRAM is overwritten by garbage +or interrupts are disabled entirely) it will hard-reset the SOC. + +JTAG and watchdogs +^^^^^^^^^^^^^^^^^^ + +While debugging using OpenOCD, if the CPUs are halted the watchdogs will keep running, eventually resetting the +CPU. This makes it very hard to debug code; that is why the OpenOCD config will disable both watchdogs on startup. +This does mean that you will not get any warnings or panics from either the task or interrupt watchdog when the ESP32 +is connected to OpenOCD via JTAG. + +API Reference +------------- + +Header Files +^^^^^^^^^^^^ + + * `esp32/include/esp_int_wdt.h `_ + * `esp32/include/esp_task_wdt.h `_ + + +Functions +--------- + +.. doxygenfunction:: esp_int_wdt_init +.. doxygenfunction:: esp_task_wdt_init +.. doxygenfunction:: esp_task_wdt_feed +.. doxygenfunction:: esp_task_wdt_delete diff --git a/docs/index.rst b/docs/index.rst index 1ca6e28ee..c19fc52c9 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -42,9 +42,9 @@ Contents: 1.2. Application startup flow - TBA 1.3. Flash encryption and secure boot: how they work and APIs - TBA 1.4. Lower Power Coprocessor - TBA - 1.5. Watchdogs + 1.5. Watchdogs 1.6. ... - 2. Memeory - TBA + 2. Memory - TBA 2.1. Memory layout of the application (IRAM/IROM, limitations of each) - TBA 2.2. Flash layout and partitions - TBA 2.3. Flash access APIs - TBA @@ -92,6 +92,7 @@ Contents: Wi-Fi Bluetooth + Watchdogs api/gpio api/uart From 02f5bb9442e7dac64086b1573030b9ba9b814466 Mon Sep 17 00:00:00 2001 From: Jeroen Domburg Date: Thu, 17 Nov 2016 12:33:31 +0800 Subject: [PATCH 38/48] Add docs build artifacts to gitignore --- .gitignore | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.gitignore b/.gitignore index 5ec57a167..2870b4a80 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,8 @@ GPATH examples/*/sdkconfig examples/*/sdkconfig.old examples/*/build + +#Doc build artifacts +docs/_build/ +docs/doxygen-warning-log.txt +docs/xml/ From d73448f57f2c8ab44de4dad373cbc1a2e28fd9af Mon Sep 17 00:00:00 2001 From: Jeroen Domburg Date: Thu, 17 Nov 2016 18:05:47 +0800 Subject: [PATCH 39/48] Make sure task wdt also does the right thing when triggered when flash is disabled --- components/esp32/include/esp_attr.h | 4 ++++ components/esp32/task_wdt.c | 15 ++++++++------- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/components/esp32/include/esp_attr.h b/components/esp32/include/esp_attr.h index 78aa3bd19..7ef2920d9 100644 --- a/components/esp32/include/esp_attr.h +++ b/components/esp32/include/esp_attr.h @@ -26,6 +26,10 @@ // Forces data into DRAM instead of flash #define DRAM_ATTR __attribute__((section(".dram1"))) +// Forces a string into DRAM instrad of flash +// Use as ets_printf(DRAM_STR("Hello world!\n")); +#define DRAM_STR(str) (__extension__({static const DRAM_ATTR char __c[] = (str); (const char *)&__c;})) + // Forces code into RTC fast memory. See "docs/deep-sleep-stub.rst" #define RTC_IRAM_ATTR __attribute__((section(".rtc.text"))) diff --git a/components/esp32/task_wdt.c b/components/esp32/task_wdt.c index de5f9f54f..6f3959125 100644 --- a/components/esp32/task_wdt.c +++ b/components/esp32/task_wdt.c @@ -49,6 +49,7 @@ struct wdt_task_t { static wdt_task_t *wdt_task_list=NULL; static portMUX_TYPE taskwdt_spinlock = portMUX_INITIALIZER_UNLOCKED; + static void IRAM_ATTR task_wdt_isr(void *arg) { wdt_task_t *wdttask; const char *cpu; @@ -69,21 +70,21 @@ static void IRAM_ATTR task_wdt_isr(void *arg) { return; } //Watchdog got triggered because at least one task did not report in. - ets_printf("Task watchdog got triggered. The following tasks did not feed the watchdog in time:\n"); + ets_printf(DRAM_STR("Task watchdog got triggered. The following tasks did not feed the watchdog in time:\n")); for (wdttask=wdt_task_list; wdttask!=NULL; wdttask=wdttask->next) { if (!wdttask->fed_watchdog) { - cpu=xTaskGetAffinity(wdttask->task_handle)==0?"CPU 0":"CPU 1"; - if (xTaskGetAffinity(wdttask->task_handle)==tskNO_AFFINITY) cpu="CPU 0/1"; - ets_printf(" - %s (%s)\n", pcTaskGetTaskName(wdttask->task_handle), cpu); + cpu=xTaskGetAffinity(wdttask->task_handle)==0?DRAM_STR("CPU 0"):DRAM_STR("CPU 1"); + if (xTaskGetAffinity(wdttask->task_handle)==tskNO_AFFINITY) cpu=DRAM_STR("CPU 0/1"); + ets_printf(DRAM_STR(" - %s (%s)\n"), pcTaskGetTaskName(wdttask->task_handle), cpu); } } - ets_printf("Tasks currently running:\n"); + ets_printf(DRAM_STR("Tasks currently running:\n")); for (int x=0; x Date: Fri, 18 Nov 2016 10:07:34 +0800 Subject: [PATCH 40/48] components/openssl_demo: remove the apache license header and add cc license head --- .../09_openssl_client/main/openssl_client.c | 19 +++++++------------ .../09_openssl_client/main/openssl_client.h | 9 +++++++++ .../10_openssl_server/main/openssl_server.c | 19 +++++++------------ .../10_openssl_server/main/openssl_server.h | 9 +++++++++ 4 files changed, 32 insertions(+), 24 deletions(-) diff --git a/examples/09_openssl_client/main/openssl_client.c b/examples/09_openssl_client/main/openssl_client.c index c804b6c4f..c6b0e449a 100644 --- a/examples/09_openssl_client/main/openssl_client.c +++ b/examples/09_openssl_client/main/openssl_client.c @@ -1,16 +1,11 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at +/* OpenSSL client Example -// 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. + 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 "openssl_client.h" diff --git a/examples/09_openssl_client/main/openssl_client.h b/examples/09_openssl_client/main/openssl_client.h index 5bc69a0ac..f5ab887ad 100644 --- a/examples/09_openssl_client/main/openssl_client.h +++ b/examples/09_openssl_client/main/openssl_client.h @@ -1,3 +1,12 @@ +/* OpenSSL client 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. +*/ + #ifndef _OPENSSL_DEMO_H_ #define _OPENSSL_DEMO_H_ diff --git a/examples/10_openssl_server/main/openssl_server.c b/examples/10_openssl_server/main/openssl_server.c index 7f4b7d6b6..53b6050d5 100644 --- a/examples/10_openssl_server/main/openssl_server.c +++ b/examples/10_openssl_server/main/openssl_server.c @@ -1,16 +1,11 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at +/* OpenSSL server Example -// 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. + 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 "openssl_server.h" diff --git a/examples/10_openssl_server/main/openssl_server.h b/examples/10_openssl_server/main/openssl_server.h index e87f5e482..5f49de35f 100644 --- a/examples/10_openssl_server/main/openssl_server.h +++ b/examples/10_openssl_server/main/openssl_server.h @@ -1,3 +1,12 @@ +/* OpenSSL server 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. +*/ + #ifndef _OPENSSL_DEMO_H_ #define _OPENSSL_DEMO_H_ From 51021b06f8c7e49e937f8c295df95807bf505eb3 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 15 Nov 2016 18:23:29 +0800 Subject: [PATCH 41/48] nvs: initialize using layout from partition table --- components/nvs_flash/include/nvs_flash.h | 30 ++++++++++-------------- components/nvs_flash/src/nvs_api.cpp | 12 +++++++++- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/components/nvs_flash/include/nvs_flash.h b/components/nvs_flash/include/nvs_flash.h index d6e199025..eca7f99ed 100644 --- a/components/nvs_flash/include/nvs_flash.h +++ b/components/nvs_flash/include/nvs_flash.h @@ -18,25 +18,21 @@ extern "C" { #endif -/** Initialise NVS flash storage with default flash sector layout - - Temporarily, this region is hardcoded as a 12KB (0x3000 byte) - region starting at 36KB (0x9000 byte) offset in flash. - - @return ESP_OK if flash was successfully initialised. -*/ +/** + * @brief Initialize NVS flash storage with layout given in the partition table. + * + * @return ESP_OK if storage was successfully initialized. + */ esp_err_t nvs_flash_init(void); -/** Initialise NVS flash storage with custom flash sector layout - - @param baseSector Flash sector (units of 4096 bytes) offset to start NVS. - @param sectorCount Length (in flash sectors) of NVS region. - - @return ESP_OK if flash was successfully initialised. - - @note Use this parameter if you're not using the options in menuconfig for - configuring flash layout & partition table. -*/ +/** + * @brief Initialize NVS flash storage with custom flash sector layout + * @note Make sure specified sectors don't fall within ranges occupied + * by other partitions. + * @param baseSector Flash sector (units of 4096 bytes) offset to start NVS + * @param sectorCount Length (in flash sectors) of NVS region + * @return ESP_OK if flash was successfully initialized + */ esp_err_t nvs_flash_init_custom(uint32_t baseSector, uint32_t sectorCount); diff --git a/components/nvs_flash/src/nvs_api.cpp b/components/nvs_flash/src/nvs_api.cpp index f6c6c588a..b2cb5e7ad 100644 --- a/components/nvs_flash/src/nvs_api.cpp +++ b/components/nvs_flash/src/nvs_api.cpp @@ -16,6 +16,7 @@ #include "nvs_storage.hpp" #include "intrusive_list.h" #include "nvs_platform.hpp" +#include "esp_partition.h" #include "sdkconfig.h" #ifdef ESP_PLATFORM @@ -61,10 +62,19 @@ extern "C" void nvs_dump() s_nvs_storage.debugDump(); } +#ifdef ESP_PLATFORM extern "C" esp_err_t nvs_flash_init(void) { - return nvs_flash_init_custom(9, 3); + const esp_partition_t* partition = esp_partition_find_first( + ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, NULL); + if (partition == NULL) { + return ESP_ERR_NOT_FOUND; + } + + return nvs_flash_init_custom(partition->address / SPI_FLASH_SEC_SIZE, + partition->size / SPI_FLASH_SEC_SIZE); } +#endif extern "C" esp_err_t nvs_flash_init_custom(uint32_t baseSector, uint32_t sectorCount) { From 6e97936bace204d802cee8d34f6cbfed3a5dee0c Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 15 Nov 2016 18:24:56 +0800 Subject: [PATCH 42/48] nvs: allow nvs_flash_init to be called more than once MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also don’t assert in nvs_* functions if nvs_flash_init wasn’t called, and make nvs_flash_init_custom an internal API for unit tests. --- components/nvs_flash/include/nvs_flash.h | 10 ----- components/nvs_flash/src/nvs_api.cpp | 9 +++-- components/nvs_flash/src/nvs_platform.hpp | 21 +++++----- components/nvs_flash/src/nvs_storage.cpp | 5 +++ components/nvs_flash/src/nvs_storage.hpp | 2 + components/nvs_flash/src/nvs_test_api.h | 47 +++++++++++++++++++++++ components/nvs_flash/test/test_nvs.cpp | 2 +- 7 files changed, 73 insertions(+), 23 deletions(-) create mode 100644 components/nvs_flash/src/nvs_test_api.h diff --git a/components/nvs_flash/include/nvs_flash.h b/components/nvs_flash/include/nvs_flash.h index eca7f99ed..0162a8f8a 100644 --- a/components/nvs_flash/include/nvs_flash.h +++ b/components/nvs_flash/include/nvs_flash.h @@ -25,16 +25,6 @@ extern "C" { */ esp_err_t nvs_flash_init(void); -/** - * @brief Initialize NVS flash storage with custom flash sector layout - * @note Make sure specified sectors don't fall within ranges occupied - * by other partitions. - * @param baseSector Flash sector (units of 4096 bytes) offset to start NVS - * @param sectorCount Length (in flash sectors) of NVS region - * @return ESP_OK if flash was successfully initialized - */ -esp_err_t nvs_flash_init_custom(uint32_t baseSector, uint32_t sectorCount); - #ifdef __cplusplus } diff --git a/components/nvs_flash/src/nvs_api.cpp b/components/nvs_flash/src/nvs_api.cpp index b2cb5e7ad..751542ee1 100644 --- a/components/nvs_flash/src/nvs_api.cpp +++ b/components/nvs_flash/src/nvs_api.cpp @@ -65,6 +65,11 @@ extern "C" void nvs_dump() #ifdef ESP_PLATFORM extern "C" esp_err_t nvs_flash_init(void) { + Lock::init(); + Lock lock; + if (s_nvs_storage.isValid()) { + return ESP_OK; + } const esp_partition_t* partition = esp_partition_find_first( ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, NULL); if (partition == NULL) { @@ -78,9 +83,7 @@ extern "C" esp_err_t nvs_flash_init(void) extern "C" esp_err_t nvs_flash_init_custom(uint32_t baseSector, uint32_t sectorCount) { - Lock::init(); - Lock lock; - ESP_LOGD(TAG, "init start=%d count=%d", baseSector, sectorCount); + ESP_LOGD(TAG, "nvs_flash_init_custom start=%d count=%d", baseSector, sectorCount); s_nvs_handles.clear(); return s_nvs_storage.init(baseSector, sectorCount); } diff --git a/components/nvs_flash/src/nvs_platform.hpp b/components/nvs_flash/src/nvs_platform.hpp index 374dbca6c..0973c4875 100644 --- a/components/nvs_flash/src/nvs_platform.hpp +++ b/components/nvs_flash/src/nvs_platform.hpp @@ -16,9 +16,6 @@ #ifdef ESP_PLATFORM -#define NVS_DEBUGV(...) ets_printf(__VA_ARGS__) - -#include "rom/ets_sys.h" #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" @@ -30,19 +27,23 @@ class Lock public: Lock() { - assert(mSemaphore); - xSemaphoreTake(mSemaphore, portMAX_DELAY); + if (mSemaphore) { + xSemaphoreTake(mSemaphore, portMAX_DELAY); + } } ~Lock() { - assert(mSemaphore); - xSemaphoreGive(mSemaphore); + if (mSemaphore) { + xSemaphoreGive(mSemaphore); + } } static esp_err_t init() { - assert(mSemaphore == nullptr); + if (mSemaphore) { + return ESP_OK; + } mSemaphore = xSemaphoreCreateMutex(); if (!mSemaphore) { return ESP_ERR_NO_MEM; @@ -52,7 +53,9 @@ public: static void uninit() { - vSemaphoreDelete(mSemaphore); + if (mSemaphore) { + vSemaphoreDelete(mSemaphore); + } mSemaphore = nullptr; } diff --git a/components/nvs_flash/src/nvs_storage.cpp b/components/nvs_flash/src/nvs_storage.cpp index cacfbd402..f8da28fa2 100644 --- a/components/nvs_flash/src/nvs_storage.cpp +++ b/components/nvs_flash/src/nvs_storage.cpp @@ -69,6 +69,11 @@ esp_err_t Storage::init(uint32_t baseSector, uint32_t sectorCount) return ESP_OK; } +bool Storage::isValid() const +{ + return mState == StorageState::ACTIVE; +} + esp_err_t Storage::findItem(uint8_t nsIndex, ItemType datatype, const char* key, Page* &page, Item& item) { for (auto it = std::begin(mPageManager); it != std::end(mPageManager); ++it) { diff --git a/components/nvs_flash/src/nvs_storage.hpp b/components/nvs_flash/src/nvs_storage.hpp index f8cee9f2a..ecf2651ae 100644 --- a/components/nvs_flash/src/nvs_storage.hpp +++ b/components/nvs_flash/src/nvs_storage.hpp @@ -47,6 +47,8 @@ public: esp_err_t init(uint32_t baseSector, uint32_t sectorCount); + bool isValid() const; + esp_err_t createOrOpenNamespace(const char* nsName, bool canCreate, uint8_t& nsIndex); esp_err_t writeItem(uint8_t nsIndex, ItemType datatype, const char* key, const void* data, size_t dataSize); diff --git a/components/nvs_flash/src/nvs_test_api.h b/components/nvs_flash/src/nvs_test_api.h new file mode 100644 index 000000000..97940092d --- /dev/null +++ b/components/nvs_flash/src/nvs_test_api.h @@ -0,0 +1,47 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "nvs_flash.h" + +/** + * @brief Initialize NVS flash storage with custom flash sector layout + * + * @note This API is intended to be used in unit tests. + * + * @param baseSector Flash sector (units of 4096 bytes) offset to start NVS + * @param sectorCount Length (in flash sectors) of NVS region. + NVS partition must be at least 3 sectors long. + * @return ESP_OK if flash was successfully initialized + */ +esp_err_t nvs_flash_init_custom(uint32_t baseSector, uint32_t sectorCount); + + +/** + * @brief Dump contents of NVS storage to stdout + * + * This function may be used for debugging purposes to inspect the state + * of NVS pages. For each page, list of entries is also dumped. + */ +void nvs_dump(void); + + +#ifdef __cplusplus +} +#endif diff --git a/components/nvs_flash/test/test_nvs.cpp b/components/nvs_flash/test/test_nvs.cpp index 81bf7fd21..282d4de48 100644 --- a/components/nvs_flash/test/test_nvs.cpp +++ b/components/nvs_flash/test/test_nvs.cpp @@ -13,7 +13,7 @@ // limitations under the License. #include "catch.hpp" #include "nvs.hpp" -#include "nvs_flash.h" +#include "nvs_test_api.h" #include "spi_flash_emulation.h" #include #include From a0feea8daa21d301a19283304ef635008eeff75c Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 15 Nov 2016 18:35:10 +0800 Subject: [PATCH 43/48] partition_table: update layouts, remove unused subtypes, sync with header file --- components/partition_table/gen_esp32part.py | 10 +++++++--- components/partition_table/partitions_singleapp.csv | 4 ++-- components/partition_table/partitions_two_ota.csv | 6 +++--- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/components/partition_table/gen_esp32part.py b/components/partition_table/gen_esp32part.py index cb6a5f24a..5ead13adc 100755 --- a/components/partition_table/gen_esp32part.py +++ b/components/partition_table/gen_esp32part.py @@ -116,7 +116,8 @@ class PartitionDefinition(object): "app" : APP_TYPE, "data" : DATA_TYPE, } - + + # Keep this map in sync with esp_partition_subtype_t enum in esp_partition.h SUBTYPES = { APP_TYPE : { "factory" : 0x00, @@ -124,8 +125,11 @@ class PartitionDefinition(object): }, DATA_TYPE : { "ota" : 0x00, - "rf" : 0x01, - "wifi" : 0x02, + "phy" : 0x01, + "nvs" : 0x02, + "esphttpd" : 0x80, + "fat" : 0x81, + "spiffs" : 0x82, }, } diff --git a/components/partition_table/partitions_singleapp.csv b/components/partition_table/partitions_singleapp.csv index 940b8a76c..8517b1196 100644 --- a/components/partition_table/partitions_singleapp.csv +++ b/components/partition_table/partitions_singleapp.csv @@ -1,4 +1,4 @@ # Name, Type, SubType, Offset, Size +nvs, data, nvs, 0x9000, 0x6000 +phy_init, data, phy, 0xf000, 0x1000 factory, app, factory, 0x10000, 1M -rfdata, data, rf, , 256K -wifidata, data, wifi, , 256K diff --git a/components/partition_table/partitions_two_ota.csv b/components/partition_table/partitions_two_ota.csv index 8e064e14b..58c1127d8 100644 --- a/components/partition_table/partitions_two_ota.csv +++ b/components/partition_table/partitions_two_ota.csv @@ -1,7 +1,7 @@ # Name, Type, SubType, Offset, Size +nvs, data, nvs, 0x9000, 0x4000 +otadata, data, ota, 0xd000, 0x2000 +phy_init, data, phy, 0xf000, 0x1000 factory, 0, 0, 0x10000, 1M ota_0, 0, ota_0, , 1M ota_1, 0, ota_1, , 1M -rfdata, data, rf, , 256K -wifidata, data, wifi, , 256K -otadata, data, ota, , 256K From 4db29f74a0cf2ac950628bd4cf56d08451d333a6 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 15 Nov 2016 18:36:18 +0800 Subject: [PATCH 44/48] add PHY init support --- components/esp32/Kconfig | 54 +++++ components/esp32/Makefile.projbuild | 42 ++++ components/esp32/cpu_start.c | 15 ++ components/esp32/include/esp_phy_init.h | 170 +++++++++++++++ components/esp32/lib | 2 +- components/esp32/phy.h | 51 +++++ components/esp32/phy_init.c | 264 ++++++++++++++++++++++++ components/esp32/phy_init_data.h | 139 +++++++++++++ 8 files changed, 736 insertions(+), 1 deletion(-) create mode 100644 components/esp32/Makefile.projbuild create mode 100644 components/esp32/include/esp_phy_init.h create mode 100644 components/esp32/phy.h create mode 100644 components/esp32/phy_init.c create mode 100644 components/esp32/phy_init_data.h diff --git a/components/esp32/Kconfig b/components/esp32/Kconfig index 1f04cf4bb..6bf649911 100644 --- a/components/esp32/Kconfig +++ b/components/esp32/Kconfig @@ -364,4 +364,58 @@ config ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL depends on DOCUMENTATION_FOR_RTC_CNTL endchoice +config ESP32_STORE_PHY_CALIBRATION_DATA_IN_NVS + bool "Store PHY calibration data in NVS" + default y + help + Choose whether to use non-volatile storage library (NVS) + to store PHY calibration data obtained at run time. + If enabled, this will use approximately 2kB of NVS storage + for PHY calibration data. + If this option is not enabled, calibration data will not be stored, + unless application provides its own implementations of + esp_phy_store_cal_data and esp_phy_load_cal_data functions. + See esp_phy_init.h for details. + + If unsure, choose 'y'. + + +config ESP32_PHY_AUTO_INIT + bool "Initialize PHY in startup code" + default y + help + If enabled, PHY will be initialized in startup code, before + app_main function runs. + If this is undesired, disable this option and call esp_phy_init + from the application before enabling WiFi or BT. + + If this option is enabled along with ESP32_STORE_PHY_CALIBRATION_DATA_IN_NVS, + startup code will also initialize NVS prior to initializing PHY. + + If unsure, choose 'y'. + +config ESP32_PHY_INIT_DATA_IN_PARTITION + bool "Use a partition to store PHY init data" + default n + help + If enabled, PHY init data will be loaded from a partition. + When using a custom partition table, make sure that PHY data + partition is included (type: 'data', subtype: 'phy'). + With default partition tables, this is done automatically. + If PHY init data is stored in a partition, it has to be flashed there, + otherwise runtime error will occur. + + If this option is not enabled, PHY init data will be embedded + into the application binary. + + If unsure, choose 'n'. + +config ESP32_PHY_MAX_TX_POWER + int "Max TX power (dBm)" + range 0 20 + default 20 + help + Set maximum transmit power. Actual transmit power for high + data rates may be lower than this setting. + endmenu diff --git a/components/esp32/Makefile.projbuild b/components/esp32/Makefile.projbuild new file mode 100644 index 000000000..1b54f1844 --- /dev/null +++ b/components/esp32/Makefile.projbuild @@ -0,0 +1,42 @@ +ifdef CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION + +PHY_INIT_DATA_OBJ = $(BUILD_DIR_BASE)/phy_init_data.o +PHY_INIT_DATA_BIN = $(BUILD_DIR_BASE)/phy_init_data.bin + +PARTITION_TABLE_COMPONENT_PATH := $(COMPONENT_PATH)/../partition_table +ESP32_COMPONENT_PATH := $(COMPONENT_PATH) + +GEN_ESP32PART := $(PYTHON) $(PARTITION_TABLE_COMPONENT_PATH)/gen_esp32part.py -q + +# Path to partition CSV file is relative to project path for custom +# partition CSV files, but relative to component dir otherwise. +PARTITION_TABLE_ROOT := $(call dequote,$(if $(CONFIG_PARTITION_TABLE_CUSTOM),$(PROJECT_PATH),$(PARTITION_TABLE_COMPONENT_PATH))) +PARTITION_TABLE_CSV_PATH := $(call dequote,$(abspath $(PARTITION_TABLE_ROOT)/$(subst $(quote),,$(CONFIG_PARTITION_TABLE_FILENAME)))) +PARTITION_TABLE_BIN := $(BUILD_DIR_BASE)/$(notdir $(PARTITION_TABLE_CSV_PATH:.csv=.bin)) + +# Parse partition table and get offset of PHY init data partition +PHY_INIT_GET_ADDR_CMD := $(GEN_ESP32PART) $(PARTITION_TABLE_CSV_PATH) | $(GEN_ESP32PART) - | sed -n -e "s/[^,]*,data,phy,\\([^,]*\\),.*/\\1/p" +PHY_INIT_DATA_ADDR = $(shell $(PHY_INIT_GET_ADDR_CMD)) + +# Command to flash PHY init data partition +PHY_INIT_DATA_FLASH_CMD = $(ESPTOOLPY_SERIAL) write_flash $(PHY_INIT_DATA_ADDR) $(PHY_INIT_DATA_BIN) +ESPTOOL_ALL_FLASH_ARGS += $(PHY_INIT_DATA_ADDR) $(PHY_INIT_DATA_BIN) + +$(PHY_INIT_DATA_OBJ): $(ESP32_COMPONENT_PATH)/phy_init_data.h $(BUILD_DIR_BASE)/include/sdkconfig.h + $(summary) CC $(notdir $@) + printf "#include \"phy_init_data.h\"\n" | $(CC) -I $(BUILD_DIR_BASE)/include -I $(ESP32_COMPONENT_PATH) -I $(ESP32_COMPONENT_PATH)/include -c -o $@ -xc - + +$(PHY_INIT_DATA_BIN): $(PHY_INIT_DATA_OBJ) + $(summary) BIN $(notdir $@) + $(OBJCOPY) -O binary $< $@ + +phy_init_data: $(PHY_INIT_DATA_BIN) + +phy_init_data-flash: $(BUILD_DIR_BASE)/phy_init_data.bin + @echo "Flashing PHY init data..." + $(PHY_INIT_DATA_FLASH_CMD) + +phy_init_data-clean: + rm -f $(PHY_INIT_DATA_BIN) $(PHY_INIT_DATA_OBJ) + +endif # CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION diff --git a/components/esp32/cpu_start.c b/components/esp32/cpu_start.c index a96fdee95..df839069f 100644 --- a/components/esp32/cpu_start.c +++ b/components/esp32/cpu_start.c @@ -50,6 +50,7 @@ #include "esp_brownout.h" #include "esp_int_wdt.h" #include "esp_task_wdt.h" +#include "esp_phy_init.h" #include "trax.h" void start_cpu0(void) __attribute__((weak, alias("start_cpu0_default"))); @@ -187,6 +188,20 @@ void start_cpu0_default(void) esp_ipc_init(); spi_flash_init(); +#if CONFIG_ESP32_PHY_AUTO_INIT +#if CONFIG_ESP32_STORE_PHY_CALIBRATION_DATA_IN_NVS + nvs_flash_init(); +#endif + esp_phy_calibration_mode_t calibration_mode = PHY_RF_CAL_PARTIAL; + if (rtc_get_reset_reason(0) == DEEPSLEEP_RESET) { + calibration_mode = PHY_RF_CAL_NONE; + } + if (esp_phy_init(calibration_mode) != ESP_OK) { + ESP_LOGD(TAG, "phy init has failed"); + abort(); + } +#endif + xTaskCreatePinnedToCore(&main_task, "main", ESP_TASK_MAIN_STACK, NULL, ESP_TASK_MAIN_PRIO, NULL, 0); diff --git a/components/esp32/include/esp_phy_init.h b/components/esp32/include/esp_phy_init.h new file mode 100644 index 000000000..f911276df --- /dev/null +++ b/components/esp32/include/esp_phy_init.h @@ -0,0 +1,170 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + uint8_t param_ver_id; /*!< init_data structure version */ + uint8_t crystal_select; /*!< 0: 40MHz, 1: 26 MHz, 2: 24 MHz, 3: auto */ + uint8_t wifi_rx_gain_swp_step_1; /*!< do not change */ + uint8_t wifi_rx_gain_swp_step_2; /*!< do not change */ + uint8_t wifi_rx_gain_swp_step_3; /*!< do not change */ + uint8_t wifi_rx_gain_swp_step_4; /*!< do not change */ + uint8_t wifi_rx_gain_swp_step_5; /*!< do not change */ + uint8_t wifi_rx_gain_swp_step_6; /*!< do not change */ + uint8_t wifi_rx_gain_swp_step_7; /*!< do not change */ + uint8_t wifi_rx_gain_swp_step_8; /*!< do not change */ + uint8_t wifi_rx_gain_swp_step_9; /*!< do not change */ + uint8_t wifi_rx_gain_swp_step_10; /*!< do not change */ + uint8_t wifi_rx_gain_swp_step_11; /*!< do not change */ + uint8_t wifi_rx_gain_swp_step_12; /*!< do not change */ + uint8_t wifi_rx_gain_swp_step_13; /*!< do not change */ + uint8_t wifi_rx_gain_swp_step_14; /*!< do not change */ + uint8_t wifi_rx_gain_swp_step_15; /*!< do not change */ + uint8_t bt_rx_gain_swp_step_1; /*!< do not change */ + uint8_t bt_rx_gain_swp_step_2; /*!< do not change */ + uint8_t bt_rx_gain_swp_step_3; /*!< do not change */ + uint8_t bt_rx_gain_swp_step_4; /*!< do not change */ + uint8_t bt_rx_gain_swp_step_5; /*!< do not change */ + uint8_t bt_rx_gain_swp_step_6; /*!< do not change */ + uint8_t bt_rx_gain_swp_step_7; /*!< do not change */ + uint8_t bt_rx_gain_swp_step_8; /*!< do not change */ + uint8_t bt_rx_gain_swp_step_9; /*!< do not change */ + uint8_t bt_rx_gain_swp_step_10; /*!< do not change */ + uint8_t bt_rx_gain_swp_step_11; /*!< do not change */ + uint8_t bt_rx_gain_swp_step_12; /*!< do not change */ + uint8_t bt_rx_gain_swp_step_13; /*!< do not change */ + uint8_t bt_rx_gain_swp_step_14; /*!< do not change */ + uint8_t bt_rx_gain_swp_step_15; /*!< do not change */ + uint8_t gain_cmp_1; /*!< do not change */ + uint8_t gain_cmp_6; /*!< do not change */ + uint8_t gain_cmp_11; /*!< do not change */ + uint8_t gain_cmp_ext2_1; /*!< do not change */ + uint8_t gain_cmp_ext2_6; /*!< do not change */ + uint8_t gain_cmp_ext2_11; /*!< do not change */ + uint8_t gain_cmp_ext3_1; /*!< do not change */ + uint8_t gain_cmp_ext3_6; /*!< do not change */ + uint8_t gain_cmp_ext3_11; /*!< do not change */ + uint8_t gain_cmp_bt_ofs_1; /*!< do not change */ + uint8_t gain_cmp_bt_ofs_6; /*!< do not change */ + uint8_t gain_cmp_bt_ofs_11; /*!< do not change */ + uint8_t target_power_qdb_0; /*!< 78 means target power is 78/4=19.5dbm */ + uint8_t target_power_qdb_1; /*!< 76 means target power is 76/4=19dbm */ + uint8_t target_power_qdb_2; /*!< 74 means target power is 74/4=18.5dbm */ + uint8_t target_power_qdb_3; /*!< 68 means target power is 68/4=17dbm */ + uint8_t target_power_qdb_4; /*!< 64 means target power is 64/4=16dbm */ + uint8_t target_power_qdb_5; /*!< 52 means target power is 52/4=13dbm */ + uint8_t target_power_index_mcs0; /*!< target power index is 0, means target power is target_power_qdb_0 19.5dbm; (1m,2m,5.5m,11m,6m,9m) */ + uint8_t target_power_index_mcs1; /*!< target power index is 0, means target power is target_power_qdb_0 19.5dbm; (12m) */ + uint8_t target_power_index_mcs2; /*!< target power index is 1, means target power is target_power_qdb_1 19dbm; (18m) */ + uint8_t target_power_index_mcs3; /*!< target power index is 1, means target power is target_power_qdb_1 19dbm; (24m) */ + uint8_t target_power_index_mcs4; /*!< target power index is 2, means target power is target_power_qdb_2 18.5dbm; (36m) */ + uint8_t target_power_index_mcs5; /*!< target power index is 3, means target power is target_power_qdb_3 17dbm; (48m) */ + uint8_t target_power_index_mcs6; /*!< target power index is 4, means target power is target_power_qdb_4 16dbm; (54m) */ + uint8_t target_power_index_mcs7; /*!< target power index is 5, means target power is target_power_qdb_5 13dbm */ + uint8_t pwr_ind_11b_en; /*!< 0: 11b power is same as mcs0 and 6m, 1: 11b power different with OFDM */ + uint8_t pwr_ind_11b_0; /*!< 1m, 2m power index [0~5] */ + uint8_t pwr_ind_11b_1; /*!< 5.5m, 11m power index [0~5] */ + uint8_t chan_backoff_en; /*!< 0: channel backoff disable, 1:channel backoff enable */ + uint8_t chan1_power_backoff_qdb; /*!< 4 means backoff is 1db */ + uint8_t chan2_power_backoff_qdb; /*!< see chan1_power_backoff_qdb */ + uint8_t chan3_power_backoff_qdb; /*!< chan1_power_backoff_qdb */ + uint8_t chan4_power_backoff_qdb; /*!< chan1_power_backoff_qdb */ + uint8_t chan5_power_backoff_qdb; /*!< chan1_power_backoff_qdb */ + uint8_t chan6_power_backoff_qdb; /*!< chan1_power_backoff_qdb */ + uint8_t chan7_power_backoff_qdb; /*!< chan1_power_backoff_qdb */ + uint8_t chan8_power_backoff_qdb; /*!< chan1_power_backoff_qdb */ + uint8_t chan9_power_backoff_qdb; /*!< chan1_power_backoff_qdb */ + uint8_t chan10_power_backoff_qdb; /*!< chan1_power_backoff_qdb */ + uint8_t chan11_power_backoff_qdb; /*!< chan1_power_backoff_qdb */ + uint8_t chan12_power_backoff_qdb; /*!< chan1_power_backoff_qdb */ + uint8_t chan13_power_backoff_qdb; /*!< chan1_power_backoff_qdb */ + uint8_t chan14_power_backoff_qdb; /*!< chan1_power_backoff_qdb */ + uint8_t chan1_rate_backoff_index; /*!< if bit i is set, backoff data rate is target_power_qdb_i */ + uint8_t chan2_rate_backoff_index; /*!< see chan1_rate_backoff_index */ + uint8_t chan3_rate_backoff_index; /*!< see chan1_rate_backoff_index */ + uint8_t chan4_rate_backoff_index; /*!< see chan1_rate_backoff_index */ + uint8_t chan5_rate_backoff_index; /*!< see chan1_rate_backoff_index */ + uint8_t chan6_rate_backoff_index; /*!< see chan1_rate_backoff_index */ + uint8_t chan7_rate_backoff_index; /*!< see chan1_rate_backoff_index */ + uint8_t chan8_rate_backoff_index; /*!< see chan1_rate_backoff_index */ + uint8_t chan9_rate_backoff_index; /*!< see chan1_rate_backoff_index */ + uint8_t chan10_rate_backoff_index; /*!< see chan1_rate_backoff_index */ + uint8_t chan11_rate_backoff_index; /*!< see chan1_rate_backoff_index */ + uint8_t chan12_rate_backoff_index; /*!< see chan1_rate_backoff_index */ + uint8_t chan13_rate_backoff_index; /*!< see chan1_rate_backoff_index */ + uint8_t chan14_rate_backoff_index; /*!< see chan1_rate_backoff_index */ + uint8_t spur_freq_cfg_msb_1; /*!< first spur: */ + uint8_t spur_freq_cfg_1; /*!< spur_freq_cfg = (spur_freq_cfg_msb_1 <<8) | spur_freq_cfg_1 */ + uint8_t spur_freq_cfg_div_1; /*!< spur_freq=spur_freq_cfg/spur_freq_cfg_div_1 */ + uint8_t spur_freq_en_h_1; /*!< the seventh bit for total enable */ + uint8_t spur_freq_en_l_1; /*!< each bit for 1 channel, and use [spur_freq_en_h, spur_freq_en_l] to select the spur's channel priority */ + uint8_t spur_freq_cfg_msb_2; /*!< second spur: */ + uint8_t spur_freq_cfg_2; /*!< spur_freq_cfg = (spur_freq_cfg_msb_2 <<8) | spur_freq_cfg_2 */ + uint8_t spur_freq_cfg_div_2; /*!< spur_freq=spur_freq_cfg/spur_freq_cfg_div_2 */ + uint8_t spur_freq_en_h_2; /*!< the seventh bit for total enable */ + uint8_t spur_freq_en_l_2; /*!< each bit for 1 channel, and use [spur_freq_en_h, spur_freq_en_l] to select the spur's channel priority */ + uint8_t spur_freq_cfg_msb_3; /*!< third spur: */ + uint8_t spur_freq_cfg_3; /*!< spur_freq_cfg = (spur_freq_cfg_msb_3 <<8) | spur_freq_cfg_3 */ + uint8_t spur_freq_cfg_div_3; /*!< spur_freq=spur_freq_cfg/spur_freq_cfg_div_3 */ + uint8_t spur_freq_en_h_3; /*!< the seventh bit for total enable */ + uint8_t spur_freq_en_l_3; /*!< each bit for 1 channel, and use [spur_freq_en_h, spur_freq_en_l] to select the spur's channel priority, */ + uint8_t reserved[23]; /*!< reserved for future expansion */ +} esp_phy_init_data_t; + +typedef struct { + uint8_t opaque[1904]; /*!< opaque calibration data */ +} esp_phy_calibration_data_t; + +typedef enum { + PHY_RF_CAL_PARTIAL = 0x00000000, /*!< Do part of RF calibration. This should be used after power-on reset. */ + PHY_RF_CAL_NONE = 0x00000001, /*!< Don't do any RF calibration. This mode is only suggested to be used after deep sleep reset. */ + PHY_RF_CAL_FULL = 0x00000002 /*!< Do full RF calibration. Produces best results, but also consumes a lot of time and current. Suggested to be used once. */ +} esp_phy_calibration_mode_t; + +/** + * + * @param mode + * @return + */ +esp_err_t esp_phy_init(esp_phy_calibration_mode_t mode); + +#ifndef CONFIG_ESP32_STORE_PHY_CALIBRATION_DATA_IN_NVS + +/** + * + * @param cal_data + * @return + */ +esp_err_t esp_phy_store_cal_data(const esp_phy_calibration_data_t* cal_data); + +/** + * + * @param out_cal_data + * @return + */ +esp_err_t esp_phy_load_cal_data(esp_phy_calibration_data_t* out_cal_data); + +#endif // CONFIG_ESP32_STORE_PHY_CALIBRATION_DATA_IN_NVS + +#ifdef __cplusplus +} +#endif + diff --git a/components/esp32/lib b/components/esp32/lib index e188536a6..db867fe91 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit e188536a6315cc3ce4f1006ac3a4450faea6abc6 +Subproject commit db867fe9128cc1fc273d76af5a412f6743519149 diff --git a/components/esp32/phy.h b/components/esp32/phy.h new file mode 100644 index 000000000..ad6b9003e --- /dev/null +++ b/components/esp32/phy.h @@ -0,0 +1,51 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include "esp_phy_init.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file phy.h + * @brief Declarations for functions provided by libphy.a + */ + +/** + * @brief Initialize function pointer table in PHY library. + * @note This function should be called before register_chipv7_phy. + */ +void phy_get_romfunc_addr(void); + +/** + * @brief Initialize PHY module and do RF calibration + * @param[in] init_data Initialization parameters to be used by the PHY + * @param[inout] cal_data As input, calibration data previously obtained. As output, will contain new calibration data. + * @param[in] cal_mode RF calibration mode + * @return reserved for future use + */ +int register_chipv7_phy(const esp_phy_init_data_t* init_data, esp_phy_calibration_data_t *cal_data, esp_phy_calibration_mode_t cal_mode); + +/** + * @brief Get the format version of calibration data used by PHY library. + * @return Format version number + */ +uint32_t phy_get_rf_cal_version(); + +#ifdef __cplusplus +} +#endif + diff --git a/components/esp32/phy_init.c b/components/esp32/phy_init.c new file mode 100644 index 000000000..11d571f04 --- /dev/null +++ b/components/esp32/phy_init.c @@ -0,0 +1,264 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include + +#include "rom/ets_sys.h" +#include "soc/dport_reg.h" + +#include "esp_err.h" +#include "esp_phy_init.h" +#include "esp_system.h" +#include "phy.h" +#include "esp_log.h" +#include "sdkconfig.h" +#include "phy_init_data.h" + +static const char* TAG = "phy_init"; + +static const esp_phy_init_data_t* phy_get_init_data(); +static void phy_release_init_data(const esp_phy_init_data_t*); + +esp_err_t esp_phy_init(esp_phy_calibration_mode_t mode) +{ + ESP_LOGD(TAG, "esp_phy_init, mode=%d", mode); + esp_err_t err; + const esp_phy_init_data_t* init_data = phy_get_init_data(); + if (init_data == NULL) { + ESP_LOGE(TAG, "failed to obtain PHY init data"); + return ESP_FAIL; + } + esp_phy_calibration_data_t* cal_data = + (esp_phy_calibration_data_t*) calloc(sizeof(esp_phy_calibration_data_t), 1); + if (cal_data == NULL) { + ESP_LOGE(TAG, "failed to allocate memory for RF calibration data"); + return ESP_ERR_NO_MEM; + } + // Initialize PHY function pointer table + phy_get_romfunc_addr(); + // Enable WiFi peripheral clock + SET_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, 0x87cf); + // If full calibration is requested, don't need to load previous calibration data + if (mode != PHY_RF_CAL_FULL) { + err = esp_phy_load_cal_data(cal_data); + if (err != ESP_OK) { + ESP_LOGW(TAG, "failed to load RF calibration data, falling back to full calibration"); + mode = PHY_RF_CAL_FULL; + } + } + ESP_LOGV(TAG, "calling register_chipv7_phy, init_data=%p, cal_data=%p, mode=%d", init_data, cal_data, mode); + register_chipv7_phy(init_data, cal_data, mode); + if (mode != PHY_RF_CAL_NONE) { + err = esp_phy_store_cal_data(cal_data); + } else { + err = ESP_OK; + } + phy_release_init_data(init_data); + free(cal_data); // PHY maintains a copy of calibration data, so we can free this + return err; +} + +// PHY init data handling functions + +#if CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION +#define NO_DEFAULT_INIT_DATA +#include "esp_partition.h" + +static const esp_phy_init_data_t* phy_get_init_data() +{ + const esp_partition_t* partition = esp_partition_find_first( + ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_PHY, NULL); + if (partition == NULL) { + ESP_LOGE(TAG, "PHY data partition not found"); + return NULL; + } + ESP_LOGD(TAG, "loading PHY init data from partition at offset 0x%x", partition->address); + size_t init_data_store_length = sizeof(phy_init_magic_pre) + + sizeof(esp_phy_init_data_t) + sizeof(phy_init_magic_post); + uint8_t* init_data_store = (uint8_t*) malloc(init_data_store_length); + if (init_data_store == NULL) { + ESP_LOGE(TAG, "failed to allocate memory for PHY init data"); + return NULL; + } + esp_err_t err = esp_partition_read(partition, 0, init_data_store, init_data_store_length); + if (err != ESP_OK) { + ESP_LOGE(TAG, "failed to read PHY data partition (%d)", err); + return NULL; + } + if (memcmp(init_data_store, PHY_INIT_MAGIC, sizeof(phy_init_magic_pre)) != 0 || + memcmp(init_data_store + init_data_store_length - sizeof(phy_init_magic_post), + PHY_INIT_MAGIC, sizeof(phy_init_magic_post)) != 0) { + ESP_LOGE(TAG, "failed to validate PHY data partition"); + return NULL; + } + ESP_LOGE(TAG, "PHY data partition validated"); + return (const esp_phy_init_data_t*) (init_data_store + sizeof(phy_init_magic_pre)); +} + +static void phy_release_init_data(const esp_phy_init_data_t* init_data) +{ + free((uint8_t*) init_data - sizeof(phy_init_magic_pre)); +} + +#else // CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION + +// phy_init_data.h will declare static 'phy_init_data' variable initialized with default init data + +static const esp_phy_init_data_t* phy_get_init_data() +{ + ESP_LOGD(TAG, "loading PHY init data from application binary"); + return &phy_init_data; +} + +static void phy_release_init_data(const esp_phy_init_data_t* init_data) +{ + // no-op +} +#endif // CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION + + +// PHY calibration data handling functions + +#if CONFIG_ESP32_STORE_PHY_CALIBRATION_DATA_IN_NVS +#include "nvs.h" + +static const char* PHY_NAMESPACE = "phy"; +static const char* PHY_CAL_VERSION_KEY = "cal_version"; +static const char* PHY_CAL_MAC_KEY = "cal_mac"; +static const char* PHY_CAL_DATA_KEY = "cal_data"; + +static esp_err_t load_cal_data_from_nvs(nvs_handle handle, + esp_phy_calibration_data_t* out_cal_data); + +static esp_err_t store_cal_data_to_nvs(nvs_handle handle, + const esp_phy_calibration_data_t* cal_data); + +esp_err_t esp_phy_load_cal_data(esp_phy_calibration_data_t* out_cal_data) +{ + nvs_handle handle; + esp_err_t err = nvs_open(PHY_NAMESPACE, NVS_READONLY, &handle); + if (err != ESP_OK) { + ESP_LOGD(TAG, "%s: failed to open NVS namespace (%d)", __func__, err); + return err; + } + else { + err = load_cal_data_from_nvs(handle, out_cal_data); + nvs_close(handle); + return err; + } +} + +esp_err_t esp_phy_store_cal_data(const esp_phy_calibration_data_t* cal_data) +{ + nvs_handle handle; + esp_err_t err = nvs_open(PHY_NAMESPACE, NVS_READWRITE, &handle); + if (err != ESP_OK) { + ESP_LOGD(TAG, "%s: failed to open NVS namespace (%d)", __func__, err); + return err; + } + else { + err = store_cal_data_to_nvs(handle, cal_data); + nvs_close(handle); + return err; + } +} + +static esp_err_t load_cal_data_from_nvs(nvs_handle handle, esp_phy_calibration_data_t* out_cal_data) +{ + esp_err_t err; + uint32_t cal_data_version; + err = nvs_get_u32(handle, PHY_CAL_VERSION_KEY, &cal_data_version); + if (err != ESP_OK) { + ESP_LOGD(TAG, "%s: failed to get cal_version (%d)", __func__, err); + return err; + } + uint32_t cal_format_version = phy_get_rf_cal_version(); + if (cal_data_version != cal_format_version) { + ESP_LOGD(TAG, "%s: expected calibration data format %d, found %d", + __func__, cal_format_version, cal_data_version); + return ESP_FAIL; + } + uint8_t cal_data_mac[6]; + size_t length = sizeof(cal_data_mac); + err = nvs_get_blob(handle, PHY_CAL_MAC_KEY, cal_data_mac, &length); + if (err != ESP_OK) { + ESP_LOGD(TAG, "%s: failed to get cal_mac (%d)", __func__, err); + return err; + } + if (length != sizeof(cal_data_mac)) { + ESP_LOGD(TAG, "%s: invalid length of cal_mac (%d)", __func__, length); + return ESP_ERR_INVALID_SIZE; + } + uint8_t sta_mac[6]; + system_efuse_read_mac(sta_mac); + if (memcmp(sta_mac, cal_data_mac, sizeof(sta_mac)) != 0) { + ESP_LOGE(TAG, "%s: calibration data MAC check failed: expected " \ + MACSTR ", found " MACSTR, + __func__, MAC2STR(sta_mac), MAC2STR(cal_data_mac)); + return ESP_FAIL; + } + length = sizeof(*out_cal_data); + err = nvs_get_blob(handle, PHY_CAL_DATA_KEY, out_cal_data, &length); + if (err != ESP_OK) { + ESP_LOGE(TAG, "%s: failed to get cal_data(%d)", __func__, err); + return err; + } + if (length != sizeof(*out_cal_data)) { + ESP_LOGD(TAG, "%s: invalid length of cal_data (%d)", __func__, length); + return ESP_ERR_INVALID_SIZE; + } + return ESP_OK; +} + +static esp_err_t store_cal_data_to_nvs(nvs_handle handle, + const esp_phy_calibration_data_t* cal_data) +{ + esp_err_t err; + uint32_t cal_format_version = phy_get_rf_cal_version(); + err = nvs_set_u32(handle, PHY_CAL_VERSION_KEY, cal_format_version); + if (err != ESP_OK) { + return err; + } + uint8_t sta_mac[6]; + system_efuse_read_mac(sta_mac); + err = nvs_set_blob(handle, PHY_CAL_MAC_KEY, sta_mac, sizeof(sta_mac)); + if (err != ESP_OK) { + return err; + } + err = nvs_set_blob(handle, PHY_CAL_DATA_KEY, cal_data, sizeof(*cal_data)); + return err; +} + +#else // CONFIG_ESP32_STORE_PHY_CALIBRATION_DATA_IN_NVS + +// Default implementation: don't store or load calibration data. +// These functions are defined as weak and can be overridden in the application. + +esp_err_t esp_phy_store_cal_data(const esp_phy_calibration_data_t* cal_data) __attribute__((weak)) +{ + // pretend that calibration data is stored + return ESP_OK; +} + +esp_err_t esp_phy_load_cal_data(const esp_phy_calibration_data_t* cal_data) __attribute__((weak)) +{ + // nowhere to load data from + return ESP_ERR_NOT_SUPPORTED; +} + +#endif // CONFIG_ESP32_STORE_PHY_CALIBRATION_DATA_IN_NVS + diff --git a/components/esp32/phy_init_data.h b/components/esp32/phy_init_data.h new file mode 100644 index 000000000..206598f97 --- /dev/null +++ b/components/esp32/phy_init_data.h @@ -0,0 +1,139 @@ +// Copyright 2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include "esp_phy_init.h" +#include "sdkconfig.h" + +// constrain a value between 'low' and 'high', inclusive +#define LIMIT(val, low, high) ((val < low) ? low : (val > high) ? high : val) + +#define PHY_INIT_MAGIC "PHYINIT" + +static const char phy_init_magic_pre[] = PHY_INIT_MAGIC; + +/** + * @brief Structure containing default recommended PHY initialization parameters. + */ +static const esp_phy_init_data_t phy_init_data= { + .param_ver_id = 0, + .crystal_select = 3, + .wifi_rx_gain_swp_step_1 = 0x05, + .wifi_rx_gain_swp_step_2 = 0x04, + .wifi_rx_gain_swp_step_3 = 0x06, + .wifi_rx_gain_swp_step_4 = 0x05, + .wifi_rx_gain_swp_step_5 = 0x01, + .wifi_rx_gain_swp_step_6 = 0x06, + .wifi_rx_gain_swp_step_7 = 0x05, + .wifi_rx_gain_swp_step_8 = 0x04, + .wifi_rx_gain_swp_step_9 = 0x06, + .wifi_rx_gain_swp_step_10 = 0x04, + .wifi_rx_gain_swp_step_11 = 0x05, + .wifi_rx_gain_swp_step_12 = 0x00, + .wifi_rx_gain_swp_step_13 = 0x00, + .wifi_rx_gain_swp_step_14 = 0x00, + .wifi_rx_gain_swp_step_15 = 0x00, + .bt_rx_gain_swp_step_1 = 0x05, + .bt_rx_gain_swp_step_2 = 0x04, + .bt_rx_gain_swp_step_3 = 0x06, + .bt_rx_gain_swp_step_4 = 0x05, + .bt_rx_gain_swp_step_5 = 0x01, + .bt_rx_gain_swp_step_6 = 0x06, + .bt_rx_gain_swp_step_7 = 0x05, + .bt_rx_gain_swp_step_8 = 0x00, + .bt_rx_gain_swp_step_9 = 0x00, + .bt_rx_gain_swp_step_10 = 0x00, + .bt_rx_gain_swp_step_11 = 0x00, + .bt_rx_gain_swp_step_12 = 0x00, + .bt_rx_gain_swp_step_13 = 0x00, + .bt_rx_gain_swp_step_14 = 0x00, + .bt_rx_gain_swp_step_15 = 0x00, + .gain_cmp_1 = 0x0a, + .gain_cmp_6 = 0x0a, + .gain_cmp_11 = 0x0c, + .gain_cmp_ext2_1 = 0xf0, + .gain_cmp_ext2_6 = 0xf0, + .gain_cmp_ext2_11 = 0xf0, + .gain_cmp_ext3_1 = 0xe0, + .gain_cmp_ext3_6 = 0xe0, + .gain_cmp_ext3_11 = 0xe0, + .gain_cmp_bt_ofs_1 = 0x18, + .gain_cmp_bt_ofs_6 = 0x18, + .gain_cmp_bt_ofs_11 = 0x18, + .target_power_qdb_0 = LIMIT(CONFIG_ESP32_PHY_MAX_TX_POWER * 4, 0, 78), + .target_power_qdb_1 = LIMIT(CONFIG_ESP32_PHY_MAX_TX_POWER * 4, 0, 76), + .target_power_qdb_2 = LIMIT(CONFIG_ESP32_PHY_MAX_TX_POWER * 4, 0, 74), + .target_power_qdb_3 = LIMIT(CONFIG_ESP32_PHY_MAX_TX_POWER * 4, 0, 68), + .target_power_qdb_4 = LIMIT(CONFIG_ESP32_PHY_MAX_TX_POWER * 4, 0, 64), + .target_power_qdb_5 = LIMIT(CONFIG_ESP32_PHY_MAX_TX_POWER * 4, 0, 52), + .target_power_index_mcs0 = 0, + .target_power_index_mcs1 = 0, + .target_power_index_mcs2 = 1, + .target_power_index_mcs3 = 1, + .target_power_index_mcs4 = 2, + .target_power_index_mcs5 = 3, + .target_power_index_mcs6 = 4, + .target_power_index_mcs7 = 5, + .pwr_ind_11b_en = 0, + .pwr_ind_11b_0 = 0, + .pwr_ind_11b_1 = 0, + .chan_backoff_en = 0, + .chan1_power_backoff_qdb = 0, + .chan2_power_backoff_qdb = 0, + .chan3_power_backoff_qdb = 0, + .chan4_power_backoff_qdb = 0, + .chan5_power_backoff_qdb = 0, + .chan6_power_backoff_qdb = 0, + .chan7_power_backoff_qdb = 0, + .chan8_power_backoff_qdb = 0, + .chan9_power_backoff_qdb = 0, + .chan10_power_backoff_qdb = 0, + .chan11_power_backoff_qdb = 0, + .chan12_power_backoff_qdb = 0, + .chan13_power_backoff_qdb = 0, + .chan14_power_backoff_qdb = 0, + .chan1_rate_backoff_index = 0, + .chan2_rate_backoff_index = 0, + .chan3_rate_backoff_index = 0, + .chan4_rate_backoff_index = 0, + .chan5_rate_backoff_index = 0, + .chan6_rate_backoff_index = 0, + .chan7_rate_backoff_index = 0, + .chan8_rate_backoff_index = 0, + .chan9_rate_backoff_index = 0, + .chan10_rate_backoff_index = 0, + .chan11_rate_backoff_index = 0, + .chan12_rate_backoff_index = 0, + .chan13_rate_backoff_index = 0, + .chan14_rate_backoff_index = 0, + .spur_freq_cfg_msb_1 = 0, + .spur_freq_cfg_1 = 0, + .spur_freq_cfg_div_1 = 0, + .spur_freq_en_h_1 = 0, + .spur_freq_en_l_1 = 0, + .spur_freq_cfg_msb_2 = 0, + .spur_freq_cfg_2 = 0, + .spur_freq_cfg_div_2 = 0, + .spur_freq_en_h_2 = 0, + .spur_freq_en_l_2 = 0, + .spur_freq_cfg_msb_3 = 0, + .spur_freq_cfg_3 = 0, + .spur_freq_cfg_div_3 = 0, + .spur_freq_en_h_3 = 0, + .spur_freq_en_l_3 = 0, + .reserved = {0} +}; + +static const char phy_init_magic_post[] = PHY_INIT_MAGIC; + From 6d4ab76db2a9f24371864c9f4238ea635b598eed Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 16 Nov 2016 12:22:32 +1100 Subject: [PATCH 45/48] phy init data: Read PHY init data partition offset from menuconfig --- components/esp32/Makefile.projbuild | 30 +++----- components/partition_table/Kconfig.projbuild | 72 +++++++++++-------- .../partition_table/partitions_singleapp.csv | 1 + .../partition_table/partitions_two_ota.csv | 1 + 4 files changed, 55 insertions(+), 49 deletions(-) diff --git a/components/esp32/Makefile.projbuild b/components/esp32/Makefile.projbuild index 1b54f1844..01f8d03c5 100644 --- a/components/esp32/Makefile.projbuild +++ b/components/esp32/Makefile.projbuild @@ -3,34 +3,21 @@ ifdef CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION PHY_INIT_DATA_OBJ = $(BUILD_DIR_BASE)/phy_init_data.o PHY_INIT_DATA_BIN = $(BUILD_DIR_BASE)/phy_init_data.bin -PARTITION_TABLE_COMPONENT_PATH := $(COMPONENT_PATH)/../partition_table -ESP32_COMPONENT_PATH := $(COMPONENT_PATH) - -GEN_ESP32PART := $(PYTHON) $(PARTITION_TABLE_COMPONENT_PATH)/gen_esp32part.py -q - -# Path to partition CSV file is relative to project path for custom -# partition CSV files, but relative to component dir otherwise. -PARTITION_TABLE_ROOT := $(call dequote,$(if $(CONFIG_PARTITION_TABLE_CUSTOM),$(PROJECT_PATH),$(PARTITION_TABLE_COMPONENT_PATH))) -PARTITION_TABLE_CSV_PATH := $(call dequote,$(abspath $(PARTITION_TABLE_ROOT)/$(subst $(quote),,$(CONFIG_PARTITION_TABLE_FILENAME)))) -PARTITION_TABLE_BIN := $(BUILD_DIR_BASE)/$(notdir $(PARTITION_TABLE_CSV_PATH:.csv=.bin)) - -# Parse partition table and get offset of PHY init data partition -PHY_INIT_GET_ADDR_CMD := $(GEN_ESP32PART) $(PARTITION_TABLE_CSV_PATH) | $(GEN_ESP32PART) - | sed -n -e "s/[^,]*,data,phy,\\([^,]*\\),.*/\\1/p" -PHY_INIT_DATA_ADDR = $(shell $(PHY_INIT_GET_ADDR_CMD)) - # Command to flash PHY init data partition -PHY_INIT_DATA_FLASH_CMD = $(ESPTOOLPY_SERIAL) write_flash $(PHY_INIT_DATA_ADDR) $(PHY_INIT_DATA_BIN) -ESPTOOL_ALL_FLASH_ARGS += $(PHY_INIT_DATA_ADDR) $(PHY_INIT_DATA_BIN) +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) + +ESP32_COMPONENT_PATH := $(COMPONENT_PATH) $(PHY_INIT_DATA_OBJ): $(ESP32_COMPONENT_PATH)/phy_init_data.h $(BUILD_DIR_BASE)/include/sdkconfig.h $(summary) CC $(notdir $@) printf "#include \"phy_init_data.h\"\n" | $(CC) -I $(BUILD_DIR_BASE)/include -I $(ESP32_COMPONENT_PATH) -I $(ESP32_COMPONENT_PATH)/include -c -o $@ -xc - - + $(PHY_INIT_DATA_BIN): $(PHY_INIT_DATA_OBJ) $(summary) BIN $(notdir $@) - $(OBJCOPY) -O binary $< $@ + $(OBJCOPY) -O binary $< $@ -phy_init_data: $(PHY_INIT_DATA_BIN) +phy_init_data: $(PHY_INIT_DATA_BIN) phy_init_data-flash: $(BUILD_DIR_BASE)/phy_init_data.bin @echo "Flashing PHY init data..." @@ -39,4 +26,7 @@ phy_init_data-flash: $(BUILD_DIR_BASE)/phy_init_data.bin phy_init_data-clean: rm -f $(PHY_INIT_DATA_BIN) $(PHY_INIT_DATA_OBJ) +all: phy_init_data +flash: phy_init_data + endif # CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION diff --git a/components/partition_table/Kconfig.projbuild b/components/partition_table/Kconfig.projbuild index fa2685d7a..1f019a6e3 100644 --- a/components/partition_table/Kconfig.projbuild +++ b/components/partition_table/Kconfig.projbuild @@ -1,49 +1,63 @@ menu "Partition Table" choice - prompt "Partition Table" - default PARTITION_TABLE_SINGLE_APP - help - The partition table to flash to the ESP32. The partition table - determines where apps, data and other resources are expected to - be found. + prompt "Partition Table" + default PARTITION_TABLE_SINGLE_APP + help + The partition table to flash to the ESP32. The partition table + determines where apps, data and other resources are expected to + be found. - The predefined partition table CSV descriptions can be found - in the components/partition_table directory. Otherwise it's - possible to create a new custom partition CSV for your application. + The predefined partition table CSV descriptions can be found + in the components/partition_table directory. Otherwise it's + possible to create a new custom partition CSV for your application. config PARTITION_TABLE_SINGLE_APP - bool "Single factory app, no OTA" + bool "Single factory app, no OTA" config PARTITION_TABLE_TWO_OTA - bool "Factory app, two OTA definitions" + bool "Factory app, two OTA definitions" config PARTITION_TABLE_CUSTOM - bool "Custom partition table CSV" + bool "Custom partition table CSV" endchoice config PARTITION_TABLE_CUSTOM_FILENAME - string "Custom partition CSV file" if PARTITION_TABLE_CUSTOM - default partitions.csv - help - Name of the custom partition CSV filename. This path is evaluated - relative to the project root directory. + string "Custom partition CSV file" if PARTITION_TABLE_CUSTOM + default partitions.csv + help + Name of the custom partition CSV filename. This path is evaluated + relative to the project root directory. config PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET - hex "App offset in flash" if PARTITION_TABLE_CUSTOM - default 0x10000 - help - If using a custom partition table, specify the offset in the flash - where 'make flash' should write the built app. + hex "Factory app partition offset" if PARTITION_TABLE_CUSTOM + default 0x10000 + help + If using a custom partition table, specify the offset in the flash + where 'make flash' should write the built app. + +config PARTITION_TABLE_CUSTOM_PHY_DATA_OFFSET + hex "PHY data partition offset" if PARTITION_TABLE_CUSTOM + depends on ESP32_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 - default partitions_two_ota.csv if PARTITION_TABLE_TWO_OTA - default PARTITION_TABLE_CUSTOM_FILENAME if PARTITION_TABLE_CUSTOM + string + default partitions_singleapp.csv if PARTITION_TABLE_SINGLE_APP + default partitions_two_ota.csv if PARTITION_TABLE_TWO_OTA + default PARTITION_TABLE_CUSTOM_FILENAME if PARTITION_TABLE_CUSTOM config APP_OFFSET - hex - default PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET if PARTITION_TABLE_CUSTOM - default 0x10000 # this is the factory app offset used by the default tables + hex + default PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET if PARTITION_TABLE_CUSTOM + default 0x10000 # this is the factory app offset used by the default tables + +config PHY_DATA_OFFSET + 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 endmenu diff --git a/components/partition_table/partitions_singleapp.csv b/components/partition_table/partitions_singleapp.csv index 8517b1196..e1647008e 100644 --- a/components/partition_table/partitions_singleapp.csv +++ b/components/partition_table/partitions_singleapp.csv @@ -1,4 +1,5 @@ # Name, Type, SubType, Offset, Size +# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild nvs, data, nvs, 0x9000, 0x6000 phy_init, data, phy, 0xf000, 0x1000 factory, app, factory, 0x10000, 1M diff --git a/components/partition_table/partitions_two_ota.csv b/components/partition_table/partitions_two_ota.csv index 58c1127d8..afb43967a 100644 --- a/components/partition_table/partitions_two_ota.csv +++ b/components/partition_table/partitions_two_ota.csv @@ -1,4 +1,5 @@ # Name, Type, SubType, Offset, Size +# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild nvs, data, nvs, 0x9000, 0x4000 otadata, data, ota, 0xd000, 0x2000 phy_init, data, phy, 0xf000, 0x1000 From 541b1426546a4ee22089e78177ad13d380d3a3d6 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 18 Nov 2016 01:18:39 +0800 Subject: [PATCH 46/48] phy_init: reduce the amount of hardwired logic, add coexist init --- components/esp32/Kconfig | 19 +--- components/esp32/cpu_start.c | 45 +++++++--- components/esp32/include/esp_phy_init.h | 107 ++++++++++++++++++++--- components/esp32/include/soc/dport_reg.h | 1 + components/esp32/lib | 2 +- components/esp32/phy.h | 15 +++- components/esp32/phy_init.c | 104 +++++++--------------- components/nvs_flash/src/nvs_api.cpp | 14 +-- 8 files changed, 185 insertions(+), 122 deletions(-) diff --git a/components/esp32/Kconfig b/components/esp32/Kconfig index 6bf649911..206ea669e 100644 --- a/components/esp32/Kconfig +++ b/components/esp32/Kconfig @@ -364,21 +364,6 @@ config ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL depends on DOCUMENTATION_FOR_RTC_CNTL endchoice -config ESP32_STORE_PHY_CALIBRATION_DATA_IN_NVS - bool "Store PHY calibration data in NVS" - default y - help - Choose whether to use non-volatile storage library (NVS) - to store PHY calibration data obtained at run time. - If enabled, this will use approximately 2kB of NVS storage - for PHY calibration data. - If this option is not enabled, calibration data will not be stored, - unless application provides its own implementations of - esp_phy_store_cal_data and esp_phy_load_cal_data functions. - See esp_phy_init.h for details. - - If unsure, choose 'y'. - config ESP32_PHY_AUTO_INIT bool "Initialize PHY in startup code" @@ -389,8 +374,8 @@ config ESP32_PHY_AUTO_INIT If this is undesired, disable this option and call esp_phy_init from the application before enabling WiFi or BT. - If this option is enabled along with ESP32_STORE_PHY_CALIBRATION_DATA_IN_NVS, - startup code will also initialize NVS prior to initializing PHY. + If this option is enabled, startup code will also initialize + NVS prior to initializing PHY. If unsure, choose 'y'. diff --git a/components/esp32/cpu_start.c b/components/esp32/cpu_start.c index df839069f..1eb0a5355 100644 --- a/components/esp32/cpu_start.c +++ b/components/esp32/cpu_start.c @@ -63,6 +63,7 @@ static bool app_cpu_started = false; #endif //!CONFIG_FREERTOS_UNICORE static void do_global_ctors(void); +static void do_phy_init(); static void main_task(void* args); extern void app_main(void); @@ -189,17 +190,8 @@ void start_cpu0_default(void) spi_flash_init(); #if CONFIG_ESP32_PHY_AUTO_INIT -#if CONFIG_ESP32_STORE_PHY_CALIBRATION_DATA_IN_NVS nvs_flash_init(); -#endif - esp_phy_calibration_mode_t calibration_mode = PHY_RF_CAL_PARTIAL; - if (rtc_get_reset_reason(0) == DEEPSLEEP_RESET) { - calibration_mode = PHY_RF_CAL_NONE; - } - if (esp_phy_init(calibration_mode) != ESP_OK) { - ESP_LOGD(TAG, "phy init has failed"); - abort(); - } + do_phy_init(); #endif xTaskCreatePinnedToCore(&main_task, "main", @@ -239,3 +231,36 @@ static void main_task(void* args) vTaskDelete(NULL); } +static void do_phy_init() +{ + esp_phy_calibration_mode_t calibration_mode = PHY_RF_CAL_PARTIAL; + if (rtc_get_reset_reason(0) == DEEPSLEEP_RESET) { + calibration_mode = PHY_RF_CAL_NONE; + } + const esp_phy_init_data_t* init_data = esp_phy_get_init_data(); + if (init_data == NULL) { + ESP_LOGE(TAG, "failed to obtain PHY init data"); + abort(); + } + esp_phy_calibration_data_t* cal_data = + (esp_phy_calibration_data_t*) calloc(sizeof(esp_phy_calibration_data_t), 1); + if (cal_data == NULL) { + ESP_LOGE(TAG, "failed to allocate memory for RF calibration data"); + abort(); + } + esp_err_t err = esp_phy_load_cal_data_from_nvs(cal_data); + if (err != ESP_OK) { + ESP_LOGW(TAG, "failed to load RF calibration data, falling back to full calibration"); + calibration_mode = PHY_RF_CAL_FULL; + } + + esp_phy_init(init_data, calibration_mode, cal_data); + + if (calibration_mode != PHY_RF_CAL_NONE) { + err = esp_phy_store_cal_data_to_nvs(cal_data); + } else { + err = ESP_OK; + } + esp_phy_release_init_data(init_data); + free(cal_data); // PHY maintains a copy of calibration data, so we can free this +} diff --git a/components/esp32/include/esp_phy_init.h b/components/esp32/include/esp_phy_init.h index f911276df..7bc053610 100644 --- a/components/esp32/include/esp_phy_init.h +++ b/components/esp32/include/esp_phy_init.h @@ -20,6 +20,14 @@ extern "C" { #endif +/** + * @file PHY init parameters and API + */ + + +/** + * @brief Structure holding PHY init parameters + */ typedef struct { uint8_t param_ver_id; /*!< init_data structure version */ uint8_t crystal_select; /*!< 0: 40MHz, 1: 26 MHz, 2: 24 MHz, 3: auto */ @@ -129,8 +137,11 @@ typedef struct { uint8_t reserved[23]; /*!< reserved for future expansion */ } esp_phy_init_data_t; +/** + * @brief Opaque PHY calibration data + */ typedef struct { - uint8_t opaque[1904]; /*!< opaque calibration data */ + uint8_t opaque[1904]; /*!< calibration data */ } esp_phy_calibration_data_t; typedef enum { @@ -140,29 +151,97 @@ typedef enum { } esp_phy_calibration_mode_t; /** + * @brief Get PHY init data * - * @param mode - * @return + * If "Use a partition to store PHY init data" option is set in menuconfig, + * This function will load PHY init data from a partition. Otherwise, + * PHY init data will be compiled into the application itself, and this function + * will return a pointer to PHY init data located in read-only memory (DROM). + * + * If "Use a partition to store PHY init data" option is enabled, this function + * may return NULL if the data loaded from flash is not valid. + * + * @note Call esp_phy_release_init_data to release the pointer obtained using + * this function after the call to esp_wifi_init. + * + * @return pointer to PHY init data structure */ -esp_err_t esp_phy_init(esp_phy_calibration_mode_t mode); - -#ifndef CONFIG_ESP32_STORE_PHY_CALIBRATION_DATA_IN_NVS +const esp_phy_init_data_t* esp_phy_get_init_data(); /** - * - * @param cal_data - * @return + * @brief Release PHY init data + * @param data pointer to PHY init data structure obtained from + * esp_phy_get_init_data function */ -esp_err_t esp_phy_store_cal_data(const esp_phy_calibration_data_t* cal_data); +void esp_phy_release_init_data(const esp_phy_init_data_t* data); /** + * @brief Function called by esp_phy_init to load PHY calibration data * - * @param out_cal_data - * @return + * This is a convenience function which can be used to load PHY calibration + * data from NVS. Data can be stored to NVS using esp_phy_store_cal_data_to_nvs + * function. + * + * If calibration data is not present in the NVS, or + * data is not valid (was obtained for a chip with a different MAC address, + * or obtained for a different version of software), this function will + * return an error. + * + * If "Initialize PHY in startup code" option is set in menuconfig, this + * function will be used to load calibration data. To provide a different + * mechanism for loading calibration data, disable + * "Initialize PHY in startup code" option in menuconfig and call esp_phy_init + * function from the application. For an example usage of esp_phy_init and + * this function, see do_phy_init function in cpu_start.c + * + * @param out_cal_data pointer to calibration data structure to be filled with + * loaded data. + * @return ESP_OK on success */ -esp_err_t esp_phy_load_cal_data(esp_phy_calibration_data_t* out_cal_data); +esp_err_t esp_phy_load_cal_data_from_nvs(esp_phy_calibration_data_t* out_cal_data); + +/** + * @brief Function called by esp_phy_init to store PHY calibration data + * + * This is a convenience function which can be used to store PHY calibration + * data to the NVS. Calibration data is returned by esp_phy_init function. + * Data saved using this function to the NVS can later be loaded using + * esp_phy_store_cal_data_to_nvs function. + * + * If "Initialize PHY in startup code" option is set in menuconfig, this + * function will be used to store calibration data. To provide a different + * mechanism for storing calibration data, disable + * "Initialize PHY in startup code" option in menuconfig and call esp_phy_init + * function from the application. + * + * @param cal_data pointer to calibration data which has to be saved. + * @return ESP_OK on success + */ +esp_err_t esp_phy_store_cal_data_to_nvs(const esp_phy_calibration_data_t* cal_data); + +/** + * @brief Initialize PHY module + * + * PHY module should be initialized in order to use WiFi or BT. + * If "Initialize PHY in startup code" option is set in menuconfig, + * this function will be called automatically before app_main is called, + * using parameters obtained from esp_phy_get_init_data. + * + * Applications which don't need to enable PHY on every start up should + * disable this menuconfig option and call esp_phy_init before calling + * esp_wifi_init or bt_controller_init. See do_phy_init function in + * cpu_start.c for an example of using this function. + * + * @param init_data PHY parameters. Default set of parameters can + * be obtained by calling esp_phy_get_default_init_data + * function. + * @param mode Calibration mode (Full, partial, or no calibration) + * @param[inout] calibration_data + * @return ESP_OK on success. + */ +esp_err_t esp_phy_init(const esp_phy_init_data_t* init_data, + esp_phy_calibration_mode_t mode, esp_phy_calibration_data_t* calibration_data); -#endif // CONFIG_ESP32_STORE_PHY_CALIBRATION_DATA_IN_NVS #ifdef __cplusplus } diff --git a/components/esp32/include/soc/dport_reg.h b/components/esp32/include/soc/dport_reg.h index 0c43c0874..1be0fdee1 100644 --- a/components/esp32/include/soc/dport_reg.h +++ b/components/esp32/include/soc/dport_reg.h @@ -1028,6 +1028,7 @@ #define DPORT_WIFI_RST_EN_REG (DR_REG_DPORT_BASE + 0x0D0) /* DPORT_WIFI_RST : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ /*description: */ +#define DPORT_MAC_RST (BIT(2)) #define DPORT_WIFI_RST 0xFFFFFFFF #define DPORT_WIFI_RST_M ((DPORT_WIFI_RST_V)<<(DPORT_WIFI_RST_S)) #define DPORT_WIFI_RST_V 0xFFFFFFFF diff --git a/components/esp32/lib b/components/esp32/lib index db867fe91..a580f70a6 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit db867fe9128cc1fc273d76af5a412f6743519149 +Subproject commit a580f70a64872a7cc291b1f22455f6adbc2e35cf diff --git a/components/esp32/phy.h b/components/esp32/phy.h index ad6b9003e..81990f2e3 100644 --- a/components/esp32/phy.h +++ b/components/esp32/phy.h @@ -41,10 +41,23 @@ int register_chipv7_phy(const esp_phy_init_data_t* init_data, esp_phy_calibratio /** * @brief Get the format version of calibration data used by PHY library. - * @return Format version number + * @return Format version number, OR'ed with BIT(16) if PHY is in WIFI only mode. */ uint32_t phy_get_rf_cal_version(); +/** + * @brief Set RF/BB for only WIFI mode or coexist(WIFI & BT) mode + * @param[in] true is for only WIFI mode, false is for coexist mode. default is 0. + * @return NULL + */ +void phy_set_wifi_mode_only(bool wifi_only); + +/** + * @brief Set BT the highest priority in coexist mode. + * @return NULL + */ +void coex_bt_high_prio(void); + #ifdef __cplusplus } #endif diff --git a/components/esp32/phy_init.c b/components/esp32/phy_init.c index 11d571f04..32d8f64ed 100644 --- a/components/esp32/phy_init.c +++ b/components/esp32/phy_init.c @@ -25,60 +25,37 @@ #include "esp_system.h" #include "phy.h" #include "esp_log.h" +#include "nvs.h" #include "sdkconfig.h" #include "phy_init_data.h" static const char* TAG = "phy_init"; -static const esp_phy_init_data_t* phy_get_init_data(); -static void phy_release_init_data(const esp_phy_init_data_t*); -esp_err_t esp_phy_init(esp_phy_calibration_mode_t mode) +esp_err_t esp_phy_init(const esp_phy_init_data_t* init_data, + esp_phy_calibration_mode_t mode, esp_phy_calibration_data_t* calibration_data) { - ESP_LOGD(TAG, "esp_phy_init, mode=%d", mode); - esp_err_t err; - const esp_phy_init_data_t* init_data = phy_get_init_data(); - if (init_data == NULL) { - ESP_LOGE(TAG, "failed to obtain PHY init data"); - return ESP_FAIL; - } - esp_phy_calibration_data_t* cal_data = - (esp_phy_calibration_data_t*) calloc(sizeof(esp_phy_calibration_data_t), 1); - if (cal_data == NULL) { - ESP_LOGE(TAG, "failed to allocate memory for RF calibration data"); - return ESP_ERR_NO_MEM; - } - // Initialize PHY function pointer table + assert(init_data); + assert(calibration_data); + // Initialize PHY pointer table phy_get_romfunc_addr(); + REG_SET_BIT(DPORT_WIFI_RST_EN_REG, DPORT_MAC_RST); + REG_CLR_BIT(DPORT_WIFI_RST_EN_REG, DPORT_MAC_RST); // Enable WiFi peripheral clock SET_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, 0x87cf); - // If full calibration is requested, don't need to load previous calibration data - if (mode != PHY_RF_CAL_FULL) { - err = esp_phy_load_cal_data(cal_data); - if (err != ESP_OK) { - ESP_LOGW(TAG, "failed to load RF calibration data, falling back to full calibration"); - mode = PHY_RF_CAL_FULL; - } - } - ESP_LOGV(TAG, "calling register_chipv7_phy, init_data=%p, cal_data=%p, mode=%d", init_data, cal_data, mode); - register_chipv7_phy(init_data, cal_data, mode); - if (mode != PHY_RF_CAL_NONE) { - err = esp_phy_store_cal_data(cal_data); - } else { - err = ESP_OK; - } - phy_release_init_data(init_data); - free(cal_data); // PHY maintains a copy of calibration data, so we can free this - return err; + ESP_LOGV(TAG, "register_chipv7_phy, init_data=%p, cal_data=%p, mode=%d", + init_data, calibration_data, mode); + phy_set_wifi_mode_only(0); + register_chipv7_phy(init_data, calibration_data, mode); + coex_bt_high_prio(); + return ESP_OK; } // PHY init data handling functions - #if CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION -#define NO_DEFAULT_INIT_DATA #include "esp_partition.h" -static const esp_phy_init_data_t* phy_get_init_data() +const esp_phy_init_data_t* esp_phy_get_init_data() { const esp_partition_t* partition = esp_partition_find_first( ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_PHY, NULL); @@ -109,7 +86,7 @@ static const esp_phy_init_data_t* phy_get_init_data() return (const esp_phy_init_data_t*) (init_data_store + sizeof(phy_init_magic_pre)); } -static void phy_release_init_data(const esp_phy_init_data_t* init_data) +void esp_phy_release_init_data(const esp_phy_init_data_t* init_data) { free((uint8_t*) init_data - sizeof(phy_init_magic_pre)); } @@ -118,13 +95,13 @@ static void phy_release_init_data(const esp_phy_init_data_t* init_data) // phy_init_data.h will declare static 'phy_init_data' variable initialized with default init data -static const esp_phy_init_data_t* phy_get_init_data() +const esp_phy_init_data_t* esp_phy_get_init_data() { ESP_LOGD(TAG, "loading PHY init data from application binary"); return &phy_init_data; } -static void phy_release_init_data(const esp_phy_init_data_t* init_data) +void esp_phy_release_init_data(const esp_phy_init_data_t* init_data) { // no-op } @@ -132,22 +109,18 @@ static void phy_release_init_data(const esp_phy_init_data_t* init_data) // PHY calibration data handling functions - -#if CONFIG_ESP32_STORE_PHY_CALIBRATION_DATA_IN_NVS -#include "nvs.h" - static const char* PHY_NAMESPACE = "phy"; static const char* PHY_CAL_VERSION_KEY = "cal_version"; static const char* PHY_CAL_MAC_KEY = "cal_mac"; static const char* PHY_CAL_DATA_KEY = "cal_data"; -static esp_err_t load_cal_data_from_nvs(nvs_handle handle, +static esp_err_t load_cal_data_from_nvs_handle(nvs_handle handle, esp_phy_calibration_data_t* out_cal_data); -static esp_err_t store_cal_data_to_nvs(nvs_handle handle, +static esp_err_t store_cal_data_to_nvs_handle(nvs_handle handle, const esp_phy_calibration_data_t* cal_data); -esp_err_t esp_phy_load_cal_data(esp_phy_calibration_data_t* out_cal_data) +esp_err_t esp_phy_load_cal_data_from_nvs(esp_phy_calibration_data_t* out_cal_data) { nvs_handle handle; esp_err_t err = nvs_open(PHY_NAMESPACE, NVS_READONLY, &handle); @@ -156,13 +129,13 @@ esp_err_t esp_phy_load_cal_data(esp_phy_calibration_data_t* out_cal_data) return err; } else { - err = load_cal_data_from_nvs(handle, out_cal_data); + err = load_cal_data_from_nvs_handle(handle, out_cal_data); nvs_close(handle); return err; } } -esp_err_t esp_phy_store_cal_data(const esp_phy_calibration_data_t* cal_data) +esp_err_t esp_phy_store_cal_data_to_nvs(const esp_phy_calibration_data_t* cal_data) { nvs_handle handle; esp_err_t err = nvs_open(PHY_NAMESPACE, NVS_READWRITE, &handle); @@ -171,13 +144,14 @@ esp_err_t esp_phy_store_cal_data(const esp_phy_calibration_data_t* cal_data) return err; } else { - err = store_cal_data_to_nvs(handle, cal_data); + err = store_cal_data_to_nvs_handle(handle, cal_data); nvs_close(handle); return err; } } -static esp_err_t load_cal_data_from_nvs(nvs_handle handle, esp_phy_calibration_data_t* out_cal_data) +static esp_err_t load_cal_data_from_nvs_handle(nvs_handle handle, + esp_phy_calibration_data_t* out_cal_data) { esp_err_t err; uint32_t cal_data_version; @@ -186,7 +160,8 @@ static esp_err_t load_cal_data_from_nvs(nvs_handle handle, esp_phy_calibration_d ESP_LOGD(TAG, "%s: failed to get cal_version (%d)", __func__, err); return err; } - uint32_t cal_format_version = phy_get_rf_cal_version(); + uint32_t cal_format_version = phy_get_rf_cal_version() & (~BIT(16)); + ESP_LOGV(TAG, "phy_get_rf_cal_version: %d\n", cal_format_version); if (cal_data_version != cal_format_version) { ESP_LOGD(TAG, "%s: expected calibration data format %d, found %d", __func__, cal_format_version, cal_data_version); @@ -224,11 +199,12 @@ static esp_err_t load_cal_data_from_nvs(nvs_handle handle, esp_phy_calibration_d return ESP_OK; } -static esp_err_t store_cal_data_to_nvs(nvs_handle handle, +static esp_err_t store_cal_data_to_nvs_handle(nvs_handle handle, const esp_phy_calibration_data_t* cal_data) { esp_err_t err; - uint32_t cal_format_version = phy_get_rf_cal_version(); + uint32_t cal_format_version = phy_get_rf_cal_version() & (~BIT(16)); + ESP_LOGV(TAG, "phy_get_rf_cal_version: %d\n", cal_format_version); err = nvs_set_u32(handle, PHY_CAL_VERSION_KEY, cal_format_version); if (err != ESP_OK) { return err; @@ -243,22 +219,6 @@ static esp_err_t store_cal_data_to_nvs(nvs_handle handle, return err; } -#else // CONFIG_ESP32_STORE_PHY_CALIBRATION_DATA_IN_NVS - -// Default implementation: don't store or load calibration data. -// These functions are defined as weak and can be overridden in the application. - -esp_err_t esp_phy_store_cal_data(const esp_phy_calibration_data_t* cal_data) __attribute__((weak)) +void register_chipv7_phy_stub() { - // pretend that calibration data is stored - return ESP_OK; } - -esp_err_t esp_phy_load_cal_data(const esp_phy_calibration_data_t* cal_data) __attribute__((weak)) -{ - // nowhere to load data from - return ESP_ERR_NOT_SUPPORTED; -} - -#endif // CONFIG_ESP32_STORE_PHY_CALIBRATION_DATA_IN_NVS - diff --git a/components/nvs_flash/src/nvs_api.cpp b/components/nvs_flash/src/nvs_api.cpp index 751542ee1..7c9ec89a6 100644 --- a/components/nvs_flash/src/nvs_api.cpp +++ b/components/nvs_flash/src/nvs_api.cpp @@ -62,6 +62,13 @@ extern "C" void nvs_dump() s_nvs_storage.debugDump(); } +extern "C" esp_err_t nvs_flash_init_custom(uint32_t baseSector, uint32_t sectorCount) +{ + ESP_LOGD(TAG, "nvs_flash_init_custom start=%d count=%d", baseSector, sectorCount); + s_nvs_handles.clear(); + return s_nvs_storage.init(baseSector, sectorCount); +} + #ifdef ESP_PLATFORM extern "C" esp_err_t nvs_flash_init(void) { @@ -81,13 +88,6 @@ extern "C" esp_err_t nvs_flash_init(void) } #endif -extern "C" esp_err_t nvs_flash_init_custom(uint32_t baseSector, uint32_t sectorCount) -{ - ESP_LOGD(TAG, "nvs_flash_init_custom start=%d count=%d", baseSector, sectorCount); - s_nvs_handles.clear(); - return s_nvs_storage.init(baseSector, sectorCount); -} - static esp_err_t nvs_find_ns_handle(nvs_handle handle, HandleEntry& entry) { auto it = find_if(begin(s_nvs_handles), end(s_nvs_handles), [=](HandleEntry& e) -> bool { From 0b265dc2a71247eccf0574b3a60fcebb7f99ceee Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 18 Nov 2016 19:17:13 +0800 Subject: [PATCH 47/48] nvs, spi_flash: handle case when source data is in DROM --- components/nvs_flash/src/nvs_page.cpp | 25 +++++++++++++++++++- components/spi_flash/flash_ops.c | 6 +++++ components/spi_flash/include/esp_spi_flash.h | 2 ++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/components/nvs_flash/src/nvs_page.cpp b/components/nvs_flash/src/nvs_page.cpp index d2ca22535..80ccb1f6d 100644 --- a/components/nvs_flash/src/nvs_page.cpp +++ b/components/nvs_flash/src/nvs_page.cpp @@ -114,7 +114,30 @@ esp_err_t Page::writeEntryData(const uint8_t* data, size_t size) assert(mFirstUsedEntry != INVALID_ENTRY); const uint16_t count = size / ENTRY_SIZE; - auto rc = spi_flash_write(getEntryAddress(mNextFreeEntry), data, size); + const uint8_t* buf = data; + +#ifdef ESP_PLATFORM + /* On the ESP32, data can come from DROM, which is not accessible by spi_flash_write + * function. To work around this, we copy the data to heap if it came from DROM. + * Hopefully this won't happen very often in practice. For data from DRAM, we should + * still be able to write it to flash directly. + * TODO: figure out how to make this platform-specific check nicer (probably by introducing + * a platform-specific flash layer). + */ + if ((uint32_t) data < 0x3ff00000) { + buf = (uint8_t*) malloc(size); + if (!buf) { + return ESP_ERR_NO_MEM; + } + memcpy((void*)buf, data, size); + } +#endif //ESP_PLATFORM + auto rc = spi_flash_write(getEntryAddress(mNextFreeEntry), buf, size); +#ifdef ESP_PLATFORM + if (buf != data) { + free((void*)buf); + } +#endif //ESP_PLATFORM if (rc != ESP_OK) { mState = PageState::INVALID; return rc; diff --git a/components/spi_flash/flash_ops.c b/components/spi_flash/flash_ops.c index 134e1fe65..3358c550f 100644 --- a/components/spi_flash/flash_ops.c +++ b/components/spi_flash/flash_ops.c @@ -135,6 +135,12 @@ esp_err_t IRAM_ATTR spi_flash_write(size_t dest_addr, const void *src, size_t si if (size % 4 != 0) { return ESP_ERR_INVALID_SIZE; } + if ((uint32_t) src < 0x3ff00000) { + // if source address is in DROM, we won't be able to read it + // from within SPIWrite + // TODO: consider buffering source data using heap and writing it anyway? + return ESP_ERR_INVALID_ARG; + } // Out of bound writes are checked in ROM code, but we can give better // error code here if (dest_addr + size > g_rom_flashchip.chip_size) { diff --git a/components/spi_flash/include/esp_spi_flash.h b/components/spi_flash/include/esp_spi_flash.h index 5d124da6b..f940c0ad5 100644 --- a/components/spi_flash/include/esp_spi_flash.h +++ b/components/spi_flash/include/esp_spi_flash.h @@ -76,6 +76,8 @@ esp_err_t spi_flash_erase_range(size_t start_address, size_t size); * * @note Address in flash, dest, has to be 4-byte aligned. * This is a temporary limitation which will be removed. + * @note If source address is in DROM, this function will return + * ESP_ERR_INVALID_ARG. * * @param dest destination address in Flash * @param src pointer to the source buffer From 1f6585dd4ff67c9d3feef78691478c9e64967f88 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 18 Nov 2016 20:34:54 +0800 Subject: [PATCH 48/48] docs: update partition tables documentation --- docs/partition-tables.rst | 46 ++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/docs/partition-tables.rst b/docs/partition-tables.rst index a1a46866e..c9709029d 100644 --- a/docs/partition-tables.rst +++ b/docs/partition-tables.rst @@ -17,40 +17,30 @@ The simplest way to use the partition table is to `make menuconfig` and choose o In both cases the factory app is flashed at offset 0x10000. If you `make partition_table` then it will print a summary of the partition table. -Known Issues ------------- - -The below design document outlines the goals for the partition table system. At the moment, only some features are used: - -- data partition types "rf" & "wifi" are unused and can be entirely omitted to save space. -- NVS (non-volatile-storage) uses a hardcoded 12KB (0x3000 byte) region at offset 0x9000. - -Once a full user API is in place for partition access, these limitations will be resolved and you'll be able to use the partition mechanism fully for storing data in flash. - Built-in Partition Tables ------------------------- Here is the summary printed for the "Single factory app, no OTA" configuration:: # Espressif ESP32 Partition Table - # Name, Type, SubType, Offset, Size - factory, app, factory, 0x10000, 1M - rfdata, data, rf, 0x110000, 256K - wifidata,data, wifi, 0x150000, 256K + # Name, Type, SubType, Offset, Size + nvs, data, nvs, 0x9000, 0x6000 + phy_init, data, phy, 0xf000, 0x1000 + factory, app, factory, 0x10000, 1M * At a 0x10000 (64KB) offset in the flash is the app labelled "factory". The bootloader will run this app by default. -* There are also two data regions defined in the partition table for storing RF & Wifi calibration data. +* There are also two data regions defined in the partition table for storing NVS library partition and PHY init data. Here is the summary printed for the "Factory app, two OTA definitions" configuration:: # Espressif ESP32 Partition Table - # Name, Type, SubType, Offset, Size - factory, app, factory, 0x10000, 1M - ota_0, app, ota_0, 0x110000, 1M - ota_1, app, ota_1, 0x210000, 1M - rfdata, data, rf, 0x310000, 256K - wifidata,data, wifi, 0x350000, 256K - otadata, data, ota, 0x390000, 256K + # Name, Type, SubType, Offset, Size + nvs, data, nvs, 0x9000, 0x4000 + otadata, data, ota, 0xd000, 0x2000 + phy_init, data, phy, 0xf000, 0x1000 + factory, 0, 0, 0x10000, 1M + ota_0, 0, ota_0, , 1M + ota_1, 0, ota_1, , 1M * There are now three app partition definitions. * The type of all three are set as "app", but the subtype varies between the factory app at 0x10000 and the next two "OTA" apps. @@ -65,13 +55,13 @@ If you choose "Custom partition table CSV" in menuconfig then you can also enter The CSV format is the same format as printed in the summaries shown above. However, not all fields are required in the CSV. For example, here is the "input" CSV for the OTA partition table:: # Name, Type, SubType, Offset, Size + nvs, data, nvs, 0x9000, 0x4000 + otadata, data, ota, 0xd000, 0x2000 + phy_init, data, phy, 0xf000, 0x1000 factory, app, factory, 0x10000, 1M ota_0, app, ota_0, , 1M ota_1, app, ota_1, , 1M - rfdata, data, rf, , 256K - wifidata, data, wifi, , 256K - otadata, data, ota, , 256K - + * Whitespace between fields is ignored, and so is any line starting with # (comments). * Each non-comment line in the CSV file is a partition definition. * Only the offset for the first partition is supplied. The gen_esp32part.py tool fills in each remaining offset to start after the preceding partition. @@ -93,7 +83,7 @@ Subtype When type is "app", the subtype field can be specified as factory (0), ota_0 (0x10) ... ota_15 (0x1F) and test (0x20). Or it can be any number 0-255 (0x00-0xFF). The bootloader will execute the factory app unless there it sees a partition of type data/ota, in which case it reads this partition to determine which OTA image to boot -When type is "data", the subtype field can be specified as ota (0), rf (1), wifi (2). Or it can be a number 0x00-0xFF. The bootloader ignores all data subtypes except for ota. Other "data" subtypes are reserved for Espressif use. To create custom data partition subtypes then use a custom type value, and choose any subtype 0x00-0xFF. +When type is "data", the subtype field can be specified as ota (0), phy (1), nvs (2). Or it can be a number 0x00-0xFF. The bootloader ignores all data subtypes except for ota. Subtypes 0-0x7f are reserved for Espressif use. To create custom data partition subtypes use "data" type, and choose any unused subtype in 0x80-0xFF range. If you are porting a filesystem to the ESP-IDF, consider opening a PR to add the new subtype to esp_partition.h file. Offset & Size ~~~~~~~~~~~~~ @@ -104,6 +94,8 @@ App partitions have to be at offsets aligned to 0x10000 (64K). If you leave the Sizes and offsets can be specified as decimal numbers, hex numbers with the prefix 0x, or size multipliers M or K (1024 and 1024*1024 bytes). +NVS data partition has to be at least 0x3000 bytes long, and OTA data parition has to be 0x2000 bytes long. If you are using NVS in your application to store a lot of data, consider using a custom partition table with larger NVS partition. + Generating Binary Partition Table ---------------------------------