From b600a908c4daaa5218b88688a659ef9dcd924743 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 7 Aug 2018 08:37:43 +0300 Subject: [PATCH 1/5] unit test: fix regex for detecting abort --- tools/unit-test-app/unit_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/unit-test-app/unit_test.py b/tools/unit-test-app/unit_test.py index c1e6f96d1..f0cd686b6 100755 --- a/tools/unit-test-app/unit_test.py +++ b/tools/unit-test-app/unit_test.py @@ -43,7 +43,7 @@ from IDF.IDFApp import UT UT_APP_BOOT_UP_DONE = "Press ENTER to see the list of tests." RESET_PATTERN = re.compile(r"(ets [\w]{3}\s+[\d]{1,2} [\d]{4} [\d]{2}:[\d]{2}:[\d]{2}[^()]*\([\w].*?\))") EXCEPTION_PATTERN = re.compile(r"(Guru Meditation Error: Core\s+\d panic'ed \([\w].*?\))") -ABORT_PATTERN = re.compile(r"(abort\(\) was called at PC 0x[a-eA-E\d]{8} on core \d)") +ABORT_PATTERN = re.compile(r"(abort\(\) was called at PC 0x[a-fA-F\d]{8} on core \d)") FINISH_PATTERN = re.compile(r"1 Tests (\d) Failures (\d) Ignored") END_LIST_STR = r'\r?\nEnter test for running' TEST_PATTERN = re.compile(r'\((\d+)\)\s+"([^"]+)" ([^\r]+)\r?\n(' + END_LIST_STR + r')?') From fd61c1440bd217ada56550e0918e10322148d21e Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 8 Aug 2018 15:55:33 +0300 Subject: [PATCH 2/5] tiny-test-fw: invoke expect callbacks in order of appearance Previously the callbacks were invoked in the same order as the list of patterns to be matched. --- tools/tiny-test-fw/DUT.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/tiny-test-fw/DUT.py b/tools/tiny-test-fw/DUT.py index 091a96154..97487525e 100644 --- a/tools/tiny-test-fw/DUT.py +++ b/tools/tiny-test-fw/DUT.py @@ -576,7 +576,10 @@ class BaseDUT(object): data = self.data_cache.get_data(time_remaining) if match_succeed: - # do callback and flush matched data cache + # sort matched items according to order of appearance in the input data, + # so that the callbacks are invoked in correct order + matched_expect_items = sorted(matched_expect_items, key=lambda it: it["index"]) + # invoke callbacks and flush matched data cache slice_index = -1 for expect_item in matched_expect_items: # trigger callback From 0aa384d40c690aeb4fa9a05493d5f7940dcc371c Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Sun, 29 Jul 2018 12:57:59 +0300 Subject: [PATCH 3/5] esp32: add API to get reset reason --- components/esp32/brownout.c | 3 +- components/esp32/esp_system_internal.h | 56 ++++++++++++ components/esp32/include/esp_system.h | 36 +++++--- components/esp32/include/rom/rtc.h | 1 + components/esp32/panic.c | 27 +++++- components/esp32/reset_reason.c | 116 +++++++++++++++++++++++++ components/esp32/system_api.c | 1 + components/esp32/task_wdt.c | 2 + 8 files changed, 229 insertions(+), 13 deletions(-) create mode 100644 components/esp32/esp_system_internal.h create mode 100644 components/esp32/reset_reason.c diff --git a/components/esp32/brownout.c b/components/esp32/brownout.c index 50d8ac044..1d7800614 100644 --- a/components/esp32/brownout.c +++ b/components/esp32/brownout.c @@ -21,7 +21,7 @@ #include "soc/cpu.h" #include "soc/rtc_cntl_reg.h" #include "rom/ets_sys.h" -#include "esp_system.h" +#include "esp_system_internal.h" #include "driver/rtc_cntl.h" #include "freertos/FreeRTOS.h" @@ -42,6 +42,7 @@ static void rtc_brownout_isr_handler() * at the same time as the following ets_printf. */ esp_cpu_stall(!xPortGetCoreID()); + esp_reset_reason_set_hint(ESP_RST_BROWNOUT); ets_printf("\r\nBrownout detector was triggered\r\n\r\n"); esp_restart_noos(); } diff --git a/components/esp32/esp_system_internal.h b/components/esp32/esp_system_internal.h new file mode 100644 index 000000000..5bda73fb7 --- /dev/null +++ b/components/esp32/esp_system_internal.h @@ -0,0 +1,56 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "esp_system.h" + +/** + * @brief Internal function to restart PRO and APP CPUs. + * + * @note This function should not be called from FreeRTOS applications. + * Use esp_restart instead. + * + * This is an internal function called by esp_restart. It is called directly + * by the panic handler and brownout detector interrupt. + */ +void esp_restart_noos() __attribute__ ((noreturn)); + +/** + * @brief Internal function to set reset reason hint + * + * The hint is used do distinguish different reset reasons when software reset + * is performed. + * + * The hint is stored in RTC store register, RTC_RESET_CAUSE_REG. + * + * @param hint Desired esp_reset_reason_t value for the real reset reason + */ +void esp_reset_reason_set_hint(esp_reset_reason_t hint); + +/** + * @brief Internal function to get the reset hint value + * @return - Reset hint value previously stored into RTC_RESET_CAUSE_REG using + * esp_reset_reason_set_hint function + * - ESP_RST_UNKNOWN if the value in RTC_RESET_CAUSE_REG is invalid + */ +esp_reset_reason_t esp_reset_reason_get_hint(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp32/include/esp_system.h b/components/esp32/include/esp_system.h index 0d57d84d8..01feea32d 100644 --- a/components/esp32/include/esp_system.h +++ b/components/esp32/include/esp_system.h @@ -35,6 +35,25 @@ typedef enum { #define FOUR_UNIVERSAL_MAC_ADDR 4 #define UNIVERSAL_MAC_ADDR_NUM CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS + +/** + * @brief Reset reasons + */ +typedef enum { + ESP_RST_UNKNOWN, //!< Reset reason can not be determined + ESP_RST_POWERON, //!< Reset due to power-on event + ESP_RST_EXT, //!< Reset by external pin (not applicable for ESP32) + ESP_RST_SW, //!< Software reset via esp_restart + ESP_RST_PANIC, //!< Software reset due to exception/panic + ESP_RST_INT_WDT, //!< Reset (software or hardware) due to interrupt watchdog + ESP_RST_TASK_WDT, //!< Reset due to task watchdog + ESP_RST_WDT, //!< Reset due to other watchdogs + ESP_RST_DEEPSLEEP, //!< Reset after exiting deep sleep mode + ESP_RST_BROWNOUT, //!< Brownout reset (software or hardware) + ESP_RST_SDIO, //!< Reset over SDIO +} esp_reset_reason_t; + +/** @cond */ /** * @attention application don't need to call this function anymore. It do nothing and will * be removed in future version. @@ -68,17 +87,6 @@ esp_err_t esp_register_shutdown_handler(shutdown_handler_t handle); */ void esp_restart(void) __attribute__ ((noreturn)); -/** - * @brief Internal function to restart PRO and APP CPUs. - * - * @note This function should not be called from FreeRTOS applications. - * Use esp_restart instead. - * - * This is an internal function called by esp_restart. It is called directly - * by the panic handler and brownout detector interrupt. - */ -void esp_restart_noos() __attribute__ ((noreturn)); - /** * @brief Restart system. * @@ -87,6 +95,12 @@ void esp_restart_noos() __attribute__ ((noreturn)); */ void system_restart(void) __attribute__ ((deprecated, noreturn)); +/** + * @brief Get reason of last reset + * @return See description of esp_reset_reason_t for explanation of each value. + */ +esp_reset_reason_t esp_reset_reason(void); + /** * @brief Get system time, unit: microsecond. * diff --git a/components/esp32/include/rom/rtc.h b/components/esp32/include/rom/rtc.h index 08d8ace09..9ebd1020b 100644 --- a/components/esp32/include/rom/rtc.h +++ b/components/esp32/include/rom/rtc.h @@ -68,6 +68,7 @@ extern "C" { #define RTC_XTAL_FREQ_REG RTC_CNTL_STORE4_REG #define RTC_APB_FREQ_REG RTC_CNTL_STORE5_REG #define RTC_ENTRY_ADDR_REG RTC_CNTL_STORE6_REG +#define RTC_RESET_CAUSE_REG RTC_CNTL_STORE6_REG #define RTC_MEMORY_CRC_REG RTC_CNTL_STORE7_REG diff --git a/components/esp32/panic.c b/components/esp32/panic.c index 5a000574b..e8640c025 100644 --- a/components/esp32/panic.c +++ b/components/esp32/panic.c @@ -40,7 +40,7 @@ #include "esp_spi_flash.h" #include "esp_cache_err_int.h" #include "esp_app_trace.h" -#include "esp_system.h" +#include "esp_system_internal.h" #include "sdkconfig.h" #if CONFIG_SYSVIEW_ENABLE #include "SEGGER_RTT.h" @@ -121,6 +121,20 @@ void __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, s abort(); } +/* These two weak stubs for esp_reset_reason_{get,set}_hint are used when + * the application does not call esp_reset_reason() function, and + * reset_reason.c is not linked into the output file. + */ +void __attribute__((weak)) esp_reset_reason_set_hint(esp_reset_reason_t hint) +{ +} + +esp_reset_reason_t __attribute__((weak)) esp_reset_reason_get_hint(void) +{ + return ESP_RST_UNKNOWN; +} + + static bool abort_called; static __attribute__((noreturn)) inline void invoke_abort() @@ -147,6 +161,12 @@ void abort() #if !CONFIG_ESP32_PANIC_SILENT_REBOOT ets_printf("abort() was called at PC 0x%08x on core %d\r\n", (intptr_t)__builtin_return_address(0) - 3, xPortGetCoreID()); #endif + /* Calling code might have set other reset reason hint (such as Task WDT), + * don't overwrite that. + */ + if (esp_reset_reason_get_hint() == ESP_RST_UNKNOWN) { + esp_reset_reason_set_hint(ESP_RST_PANIC); + } invoke_abort(); } @@ -234,6 +254,10 @@ void panicHandler(XtExcFrame *frame) } #endif //!CONFIG_FREERTOS_UNICORE + if (frame->exccause == PANIC_RSN_INTWDT_CPU0 || frame->exccause == PANIC_RSN_INTWDT_CPU1) { + esp_reset_reason_set_hint(ESP_RST_INT_WDT); + } + haltOtherCore(); esp_dport_access_int_abort(); panicPutStr("Guru Meditation Error: Core "); @@ -333,6 +357,7 @@ void xt_unhandled_exception(XtExcFrame *frame) return; } panicPutStr(". Exception was unhandled.\r\n"); + esp_reset_reason_set_hint(ESP_RST_PANIC); } commonErrorHandler(frame); } diff --git a/components/esp32/reset_reason.c b/components/esp32/reset_reason.c new file mode 100644 index 000000000..191271df0 --- /dev/null +++ b/components/esp32/reset_reason.c @@ -0,0 +1,116 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "esp_system.h" +#include "esp_system_internal.h" +#include "rom/rtc.h" +#include "soc/rtc_cntl_reg.h" + +static esp_reset_reason_t s_reset_reason; + +static esp_reset_reason_t get_reset_reason(RESET_REASON rtc_reset_reason, esp_reset_reason_t reset_reason_hint) +{ + switch (rtc_reset_reason) { + case POWERON_RESET: + return ESP_RST_POWERON; + + /* For ESP32, ESP_RST_EXT is never returned */ + + + case SW_CPU_RESET: + case SW_RESET: + case EXT_CPU_RESET: /* unused */ + if (reset_reason_hint == ESP_RST_PANIC || + reset_reason_hint == ESP_RST_BROWNOUT || + reset_reason_hint == ESP_RST_TASK_WDT || + reset_reason_hint == ESP_RST_INT_WDT) { + return reset_reason_hint; + } + return ESP_RST_SW; + + case DEEPSLEEP_RESET: + return ESP_RST_DEEPSLEEP; + + case TG0WDT_SYS_RESET: + return ESP_RST_TASK_WDT; + + case TG1WDT_SYS_RESET: + return ESP_RST_INT_WDT; + + case OWDT_RESET: + case RTCWDT_SYS_RESET: + case RTCWDT_RTC_RESET: + case RTCWDT_CPU_RESET: /* unused */ + case TGWDT_CPU_RESET: /* unused */ + return ESP_RST_WDT; + + case RTCWDT_BROWN_OUT_RESET: /* unused */ + return ESP_RST_BROWNOUT; + + case SDIO_RESET: + return ESP_RST_SDIO; + + case INTRUSION_RESET: /* unused */ + default: + return ESP_RST_UNKNOWN; + } +} + +static void __attribute__((constructor)) esp_reset_reason_init(void) +{ + s_reset_reason = get_reset_reason(rtc_get_reset_reason(PRO_CPU_NUM), + esp_reset_reason_get_hint()); + esp_reset_reason_set_hint(ESP_RST_UNKNOWN); +} + +esp_reset_reason_t esp_reset_reason(void) +{ + return s_reset_reason; +} + +/* Reset reason hint is stored in RTC_RESET_CAUSE_REG, a.k.a. RTC_CNTL_STORE6_REG, + * a.k.a. RTC_ENTRY_ADDR_REG. It is safe to use this register both for the + * deep sleep wake stub entry address and for reset reason hint, since wake stub + * is only used for deep sleep reset, and in this case the reason provided by + * rtc_get_reset_reason is unambiguous. + * + * Same layout is used as for RTC_APB_FREQ_REG (a.k.a. RTC_CNTL_STORE5_REG): + * the value is replicated in low and high half-words. In addition to that, + * MSB is set to 1, which doesn't happen when RTC_CNTL_STORE6_REG contains + * deep sleep wake stub address. + */ + +#define RST_REASON_BIT 0x80000000 +#define RST_REASON_MASK 0x7FFF +#define RST_REASON_SHIFT 16 + +/* in IRAM, can be called from panic handler */ +void IRAM_ATTR esp_reset_reason_set_hint(esp_reset_reason_t hint) +{ + assert((hint & (~RST_REASON_MASK)) == 0); + uint32_t val = hint | (hint << RST_REASON_SHIFT) | RST_REASON_BIT; + REG_WRITE(RTC_RESET_CAUSE_REG, val); +} + +/* in IRAM, can be called from panic handler */ +esp_reset_reason_t IRAM_ATTR esp_reset_reason_get_hint(void) +{ + uint32_t reset_reason_hint = REG_READ(RTC_RESET_CAUSE_REG); + uint32_t high = (reset_reason_hint >> RST_REASON_SHIFT) & RST_REASON_MASK; + uint32_t low = reset_reason_hint & RST_REASON_MASK; + if ((reset_reason_hint & RST_REASON_BIT) == 0 || high != low) { + return ESP_RST_UNKNOWN; + } + return (esp_reset_reason_t) low; +} diff --git a/components/esp32/system_api.c b/components/esp32/system_api.c index f56bf622e..ce111bd59 100644 --- a/components/esp32/system_api.c +++ b/components/esp32/system_api.c @@ -36,6 +36,7 @@ #include "freertos/task.h" #include "freertos/xtensa_api.h" #include "esp_heap_caps.h" +#include "esp_system_internal.h" static const char* TAG = "system_api"; diff --git a/components/esp32/task_wdt.c b/components/esp32/task_wdt.c index 0e0b87c65..fb10aac05 100644 --- a/components/esp32/task_wdt.c +++ b/components/esp32/task_wdt.c @@ -35,6 +35,7 @@ #include "driver/timer.h" #include "driver/periph_ctrl.h" #include "esp_task_wdt.h" +#include "esp_system_internal.h" //Assertion macro where, if 'cond' is false, will exit the critical section and return 'ret' #define ASSERT_EXIT_CRIT_RETURN(cond, ret) ({ \ @@ -155,6 +156,7 @@ static void task_wdt_isr(void *arg) if (twdt_config->panic){ //Trigger Panic if configured to do so ets_printf("Aborting.\n"); portEXIT_CRITICAL(&twdt_spinlock); + esp_reset_reason_set_hint(ESP_RST_TASK_WDT); abort(); } From 3ef650cd4630ff17017cede82e23784c25951e67 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Sun, 29 Jul 2018 14:17:09 +0300 Subject: [PATCH 4/5] esp32/test: add tests for reset reasons --- components/esp32/ld/esp32.common.ld | 1 + components/esp32/test/test_attr.c | 27 +++ components/esp32/test/test_exception.c | 9 - components/esp32/test/test_int_wdt.c | 20 -- components/esp32/test/test_noinit.c | 123 ------------- components/esp32/test/test_reset_reason.c | 211 ++++++++++++++++++++++ components/esp32/test/test_restart.c | 25 --- 7 files changed, 239 insertions(+), 177 deletions(-) create mode 100644 components/esp32/test/test_attr.c delete mode 100644 components/esp32/test/test_exception.c delete mode 100644 components/esp32/test/test_int_wdt.c delete mode 100644 components/esp32/test/test_noinit.c create mode 100644 components/esp32/test/test_reset_reason.c delete mode 100644 components/esp32/test/test_restart.c diff --git a/components/esp32/ld/esp32.common.ld b/components/esp32/ld/esp32.common.ld index 21470e6f4..a582b7597 100644 --- a/components/esp32/ld/esp32.common.ld +++ b/components/esp32/ld/esp32.common.ld @@ -32,6 +32,7 @@ SECTIONS _rtc_bss_start = ABSOLUTE(.); *rtc_wake_stub*.o(.bss .bss.*) *rtc_wake_stub*.o(COMMON) + *(.rtc.bss) _rtc_bss_end = ABSOLUTE(.); } > rtc_slow_seg diff --git a/components/esp32/test/test_attr.c b/components/esp32/test/test_attr.c new file mode 100644 index 000000000..d6560b3cc --- /dev/null +++ b/components/esp32/test/test_attr.c @@ -0,0 +1,27 @@ +#include "unity.h" +#include "esp_attr.h" +#include "esp_log.h" + +static __NOINIT_ATTR uint32_t s_noinit; +static RTC_NOINIT_ATTR uint32_t s_rtc_noinit; +static RTC_DATA_ATTR uint32_t s_rtc_data; + +extern int _rtc_noinit_start; +extern int _rtc_noinit_end; +extern int _rtc_data_start; +extern int _rtc_data_end; +extern int _noinit_start; +extern int _noinit_end; + +static bool data_in_segment(void *ptr, int *seg_start, int *seg_end) +{ + return ((intptr_t)ptr < (intptr_t)seg_end) && \ + ((intptr_t)ptr >= (intptr_t)seg_start); +} + +TEST_CASE("Attributes place variables into correct sections", "[ld]") +{ + TEST_ASSERT(data_in_segment(&s_noinit, &_noinit_start, &_noinit_end)); + TEST_ASSERT(data_in_segment(&s_rtc_noinit, &_rtc_noinit_start, &_rtc_noinit_end)); + TEST_ASSERT(data_in_segment(&s_rtc_data, &_rtc_data_start, &_rtc_data_end)); +} diff --git a/components/esp32/test/test_exception.c b/components/esp32/test/test_exception.c deleted file mode 100644 index 4e5d6dec2..000000000 --- a/components/esp32/test/test_exception.c +++ /dev/null @@ -1,9 +0,0 @@ -#include "unity.h" -#include "esp_system.h" -#include "string.h" - - -TEST_CASE("make exception", "[restart][reset=StoreProhibited,SW_CPU_RESET]") -{ - *(int *) NULL = 0; -} diff --git a/components/esp32/test/test_int_wdt.c b/components/esp32/test/test_int_wdt.c deleted file mode 100644 index 9bfde9cdc..000000000 --- a/components/esp32/test/test_int_wdt.c +++ /dev/null @@ -1,20 +0,0 @@ -/* - Tests for the interrupt watchdog -*/ - -#include -#include -#include "rom/ets_sys.h" -#include "unity.h" -#include "soc/dport_reg.h" -#include "soc/io_mux_reg.h" -#include "esp_intr_alloc.h" -#include "freertos/FreeRTOS.h" - - - -TEST_CASE("Int wdt test", "[esp32][reset=Interrupt wdt timeout on CPU0,SW_CPU_RESET]") -{ - portENTER_CRITICAL_NESTED(); - while(1); -} diff --git a/components/esp32/test/test_noinit.c b/components/esp32/test/test_noinit.c deleted file mode 100644 index bb1b42939..000000000 --- a/components/esp32/test/test_noinit.c +++ /dev/null @@ -1,123 +0,0 @@ -#include "unity.h" -#include "esp_system.h" -#include "rom/rtc.h" -#include "esp_log.h" - -// This is a test sequence to test behavior of .rtc_noinit and .noinit sections. -// The values placed into .rtc_noinit section go to RTC SLOW Memory segment and -// keep their value after reset and deep sleep. Use new added attribute macro -// RTC_NOINIT_ATTR for this behavior. The second macro - __NOINIT_ATTR places value -// into .noinit section which goes to SRAM and will not be initialized after reset. - -#define RTC_NOINIT_PATTERN 0xAAAAAAAA -#define _NOINIT_PATTERN 0x55555555 - -static __NOINIT_ATTR uint32_t noinit_data; -static RTC_NOINIT_ATTR uint32_t rtc_noinit_data; - -extern int _rtc_noinit_start; -extern int _rtc_noinit_end; -extern int _noinit_start; -extern int _noinit_end; - -// Pointers to the values -uint32_t *noinit_val_addr = (uint32_t*)&noinit_data; -uint32_t *rtc_noinit_val_addr = (uint32_t*)&rtc_noinit_data; - -static const char* tag = "noinit_UnitTestMain"; - -static esp_err_t check_data_seg(uint32_t *value_address, \ - uint32_t *seg_start, uint32_t *seg_end) -{ - esp_err_t result = ESP_FAIL; - if (((uint32_t)value_address <= (uint32_t)seg_end) && \ - ((uint32_t)value_address >= (uint32_t)seg_start)){ - result = ESP_OK; - } - return result; -} - -static void setup_attributes(void) -{ - rtc_noinit_data = RTC_NOINIT_PATTERN; - noinit_data = _NOINIT_PATTERN; -} - -static void init_attributes(void) -{ - setup_attributes(); - printf("noinit_data = 0x%X \n", (uint32_t)*noinit_val_addr); - printf("rtc_noinit_data = 0x%X \n", (uint32_t)*rtc_noinit_val_addr); - TEST_ASSERT(*noinit_val_addr == noinit_data); - TEST_ASSERT(*rtc_noinit_val_addr == rtc_noinit_data); -} - -static void reset_reason_power_on(void) -{ - printf("This test case checks behavior of noinit variables POWERON_RESET sequence. \n"); - RESET_REASON reason = rtc_get_reset_reason(0); - ESP_LOGI(tag, "POWERON_RESET reset values = (0x%X), (0x%X), reset reason=(%d)\n", \ - (uint32_t)*noinit_val_addr, (uint32_t)*rtc_noinit_val_addr, (uint16_t)reason); - TEST_ASSERT((reason == POWERON_RESET) || (reason == RTCWDT_RTC_RESET)); - - init_attributes(); - TEST_ASSERT(check_data_seg(noinit_val_addr, \ - (uint32_t*)&_noinit_start, \ - (uint32_t*)&_noinit_end) == ESP_OK); - TEST_ASSERT(check_data_seg(rtc_noinit_val_addr, \ - (uint32_t*)&_rtc_noinit_start, \ - (uint32_t*)&_rtc_noinit_end) == ESP_OK); - TEST_ASSERT(_NOINIT_PATTERN == *noinit_val_addr); - TEST_ASSERT(RTC_NOINIT_PATTERN == *rtc_noinit_val_addr); - - printf("Next test case will check SOFTWARE_RESET behavior. \n"); - esp_restart(); -} - -static void reset_reason_sw_reset(void) -{ - printf("This test case checks behavior of noinit variables after software reset sequence. \n"); - RESET_REASON reason = rtc_get_reset_reason(0); - ESP_LOGI(tag, "SW_CPU_RESET reset values = (0x%X), (0x%X), reset reason=(%d)\n", \ - (uint32_t)*noinit_val_addr, (uint32_t)*rtc_noinit_val_addr, (uint16_t)reason); - TEST_ASSERT(reason == SW_CPU_RESET); - TEST_ASSERT(check_data_seg(noinit_val_addr, \ - (uint32_t*)&_noinit_start, \ - (uint32_t*)&_noinit_end) == ESP_OK); - TEST_ASSERT(check_data_seg(rtc_noinit_val_addr, \ - (uint32_t*)&_rtc_noinit_start, \ - (uint32_t*)&_rtc_noinit_end) == ESP_OK); - // The ROM bootloader behavior may apply to this assert. - // TEST_ASSERT(0x55555555 == *noinit_val_addr); - TEST_ASSERT(RTC_NOINIT_PATTERN == *rtc_noinit_val_addr); - printf("Go to deep sleep to check DEEP_SLEEP_RESET behavior. \n"); - esp_sleep_enable_timer_wakeup(2000000); - esp_deep_sleep_start(); -} - -static void reset_reason_deep_sleep(void) -{ - printf("This test case checks behavior of noinit variables after deep sleep reset. \n"); - RESET_REASON reason = rtc_get_reset_reason(0); - ESP_LOGI(tag, "DEEP_SLEEP_RESET reset values = (0x%X), (0x%X), reset reason=(%d)\n", \ - (uint32_t)*noinit_val_addr, (uint32_t)*rtc_noinit_val_addr, (uint16_t)reason); - TEST_ASSERT(reason == DEEPSLEEP_RESET); - TEST_ASSERT(check_data_seg(noinit_val_addr, \ - (uint32_t*)&_noinit_start, \ - (uint32_t*)&_noinit_end) == ESP_OK); - TEST_ASSERT(check_data_seg(rtc_noinit_val_addr, \ - (uint32_t*)&_rtc_noinit_start, \ - (uint32_t*)&_rtc_noinit_end) == ESP_OK); - TEST_ASSERT(RTC_NOINIT_PATTERN == *rtc_noinit_val_addr); - printf("The noinit test cases are done.. \n"); -} - -// The lines below are required to suppress GCC warnings about casting of function pointers -// in unity macro expansion. These warnings may be treated as errors during automated test. -#pragma GCC diagnostic push // required for GCC -#pragma GCC diagnostic ignored "-Wdiscarded-qualifiers" -// The multiple stages test case to check values after certain reset reason -TEST_CASE_MULTIPLE_STAGES("NOINIT attributes behavior", - "[restart][reset=SW_CPU_RESET, DEEPSLEEP_RESET]", - reset_reason_power_on, reset_reason_sw_reset, reset_reason_deep_sleep); -#pragma GCC diagnostic pop // require GCC diff --git a/components/esp32/test/test_reset_reason.c b/components/esp32/test/test_reset_reason.c new file mode 100644 index 000000000..8a1d9a3b2 --- /dev/null +++ b/components/esp32/test/test_reset_reason.c @@ -0,0 +1,211 @@ +#include "unity.h" +#include "esp_system.h" +#include "esp_task_wdt.h" +#include "esp_attr.h" +#include "soc/rtc_cntl_reg.h" + +#define RTC_BSS_ATTR __attribute__((section(".rtc.bss"))) + +static __NOINIT_ATTR uint32_t s_noinit_val; +static RTC_NOINIT_ATTR uint32_t s_rtc_noinit_val; +static RTC_DATA_ATTR uint32_t s_rtc_data_val; +static RTC_BSS_ATTR uint32_t s_rtc_bss_val; + +#define CHECK_VALUE 0x89abcdef + +static void setup_values() +{ + s_noinit_val = CHECK_VALUE; + s_rtc_noinit_val = CHECK_VALUE; + s_rtc_data_val = CHECK_VALUE; + s_rtc_bss_val = CHECK_VALUE; +} + +/* This test needs special test runners: rev1 silicon, and SPI flash with + * fast start-up time. Otherwise reset reason will be RTCWDT_RESET. + */ +TEST_CASE("reset reason ESP_RST_POWERON", "[reset][ignore]") +{ + TEST_ASSERT_EQUAL(ESP_RST_POWERON, esp_reset_reason()); +} + +static void do_deep_sleep() +{ + setup_values(); + esp_sleep_enable_timer_wakeup(10000); + esp_deep_sleep_start(); +} + +static void check_reset_reason_deep_sleep() +{ + TEST_ASSERT_EQUAL(ESP_RST_DEEPSLEEP, esp_reset_reason()); + + TEST_ASSERT_EQUAL_HEX32(CHECK_VALUE, s_rtc_noinit_val); + TEST_ASSERT_EQUAL_HEX32(CHECK_VALUE, s_rtc_data_val); + TEST_ASSERT_EQUAL_HEX32(CHECK_VALUE, s_rtc_bss_val); +} + +TEST_CASE_MULTIPLE_STAGES("reset reason ESP_RST_DEEPSLEEP", "[reset_reason][reset=DEEPSLEEP_RESET]", + do_deep_sleep, + check_reset_reason_deep_sleep); + +static void do_exception() +{ + setup_values(); + *(int*) (0x40000001) = 0; +} + +static void do_abort() +{ + setup_values(); + abort(); +} + +static void check_reset_reason_panic() +{ + TEST_ASSERT_EQUAL(ESP_RST_PANIC, esp_reset_reason()); + + TEST_ASSERT_EQUAL_HEX32(CHECK_VALUE, s_noinit_val); + TEST_ASSERT_EQUAL_HEX32(CHECK_VALUE, s_rtc_noinit_val); + TEST_ASSERT_EQUAL_HEX32(0, s_rtc_data_val); + TEST_ASSERT_EQUAL_HEX32(0, s_rtc_bss_val); +} + +TEST_CASE_MULTIPLE_STAGES("reset reason ESP_RST_PANIC after exception", "[reset_reason][reset=LoadStoreError,SW_CPU_RESET]", + do_exception, + check_reset_reason_panic); + +TEST_CASE_MULTIPLE_STAGES("reset reason ESP_RST_PANIC after abort", "[reset_reason][reset=abort,SW_CPU_RESET]", + do_abort, + check_reset_reason_panic); + +static void do_restart() +{ + setup_values(); + esp_restart(); +} + +#if portNUM_PROCESSORS > 1 +static void do_restart_from_app_cpu() +{ + setup_values(); + xTaskCreatePinnedToCore((TaskFunction_t) &do_restart, "restart", 2048, NULL, 5, NULL, 1); + vTaskDelay(2); +} +#endif + +static void check_reset_reason_sw() +{ + TEST_ASSERT_EQUAL(ESP_RST_SW, esp_reset_reason()); + + TEST_ASSERT_EQUAL_HEX32(CHECK_VALUE, s_noinit_val); + TEST_ASSERT_EQUAL_HEX32(CHECK_VALUE, s_rtc_noinit_val); + TEST_ASSERT_EQUAL_HEX32(0, s_rtc_data_val); + TEST_ASSERT_EQUAL_HEX32(0, s_rtc_bss_val); +} + +TEST_CASE_MULTIPLE_STAGES("reset reason ESP_RST_SW after restart", "[reset_reason][reset=SW_CPU_RESET]", + do_restart, + check_reset_reason_sw); + +#if portNUM_PROCESSORS > 1 +TEST_CASE_MULTIPLE_STAGES("reset reason ESP_RST_SW after restart from APP CPU", "[reset_reason][reset=SW_CPU_RESET]", + do_restart_from_app_cpu, + check_reset_reason_sw); +#endif + + +static void do_int_wdt() +{ + portENTER_CRITICAL_NESTED(); + while(1); +} + +static void do_int_wdt_hw() +{ + XTOS_SET_INTLEVEL(XCHAL_NMILEVEL); + while(1); +} + +static void check_reset_reason_int_wdt() +{ + TEST_ASSERT_EQUAL(ESP_RST_INT_WDT, esp_reset_reason()); +} + +TEST_CASE_MULTIPLE_STAGES("reset reason ESP_RST_INT_WDT after interrupt watchdog (panic)", + "[reset_reason][reset=Interrupt wdt timeout on CPU0,SW_CPU_RESET]", + do_int_wdt, + check_reset_reason_int_wdt); + +TEST_CASE_MULTIPLE_STAGES("reset reason ESP_RST_INT_WDT after interrupt watchdog (hw)", + "[reset_reason][reset=TG1WDT_SYS_RESET]", + do_int_wdt_hw, + check_reset_reason_int_wdt); + +static void do_task_wdt() +{ + setup_values(); + esp_task_wdt_init(1, true); + esp_task_wdt_add(xTaskGetIdleTaskHandleForCPU(0)); + while(1); +} + +static void check_reset_reason_task_wdt() +{ + TEST_ASSERT_EQUAL(ESP_RST_TASK_WDT, esp_reset_reason()); + + TEST_ASSERT_EQUAL_HEX32(CHECK_VALUE, s_noinit_val); + TEST_ASSERT_EQUAL_HEX32(CHECK_VALUE, s_rtc_noinit_val); + TEST_ASSERT_EQUAL_HEX32(0, s_rtc_data_val); + TEST_ASSERT_EQUAL_HEX32(0, s_rtc_bss_val); +} + +TEST_CASE_MULTIPLE_STAGES("reset reason ESP_RST_TASK_WDT after task watchdog", + "[reset_reason][reset=abort,SW_CPU_RESET]", + do_task_wdt, + check_reset_reason_task_wdt); + +static void do_rtc_wdt() +{ + WRITE_PERI_REG(RTC_CNTL_WDTWPROTECT_REG, RTC_CNTL_WDT_WKEY_VALUE); + REG_SET_FIELD(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_SYS_RESET_LENGTH, 7); + REG_SET_FIELD(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_STG0, RTC_WDT_STG_SEL_RESET_SYSTEM); + WRITE_PERI_REG(RTC_CNTL_WDTCONFIG1_REG, 10000); + REG_SET_BIT(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_FLASHBOOT_MOD_EN); + while(1); +} + +static void check_reset_reason_any_wdt() +{ + TEST_ASSERT_EQUAL(ESP_RST_WDT, esp_reset_reason()); +} + +TEST_CASE_MULTIPLE_STAGES("reset reason ESP_RST_WDT after RTC watchdog", + "[reset_reason][reset=RTCWDT_RTC_RESET]", + do_rtc_wdt, + check_reset_reason_any_wdt); + + +static void do_brownout() +{ + setup_values(); + printf("Manual test: lower the supply voltage to cause brownout\n"); + vTaskSuspend(NULL); +} + +static void check_reset_reason_brownout() +{ + TEST_ASSERT_EQUAL(ESP_RST_BROWNOUT, esp_reset_reason()); + + TEST_ASSERT_EQUAL_HEX32(CHECK_VALUE, s_noinit_val); + TEST_ASSERT_EQUAL_HEX32(CHECK_VALUE, s_rtc_noinit_val); + TEST_ASSERT_EQUAL_HEX32(0, s_rtc_data_val); + TEST_ASSERT_EQUAL_HEX32(0, s_rtc_bss_val); +} + +TEST_CASE_MULTIPLE_STAGES("reset reason ESP_RST_BROWNOUT after brownout event", + "[reset_reason][ignore][reset=SW_CPU_RESET]", + do_brownout, + check_reset_reason_brownout); + +/* Not tested here: ESP_RST_SDIO */ diff --git a/components/esp32/test/test_restart.c b/components/esp32/test/test_restart.c deleted file mode 100644 index 6ad334da0..000000000 --- a/components/esp32/test/test_restart.c +++ /dev/null @@ -1,25 +0,0 @@ -#include "unity.h" -#include "esp_system.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" - - -TEST_CASE("restart from PRO CPU", "[restart][reset=SW_CPU_RESET]") -{ - esp_restart(); -} - -static void restart_task(void *arg) -{ - esp_restart(); -} - -#ifndef CONFIG_FREERTOS_UNICORE -TEST_CASE("restart from APP CPU", "[restart][reset=SW_CPU_RESET]") -{ - xTaskCreatePinnedToCore(&restart_task, "restart", 2048, NULL, 5, NULL, 1); - while (true) { - ; - } -} -#endif From 8403adf4e00aeea3461a0a14372f8b3a33161d84 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Mon, 30 Jul 2018 16:19:20 +0300 Subject: [PATCH 5/5] docs: add API reference section for esp_system.h --- components/esp32/include/esp_system.h | 36 ++++-- docs/Doxyfile | 4 +- .../api-reference/system/base_mac_address.rst | 82 ------------ docs/en/api-reference/system/index.rst | 2 +- docs/en/api-reference/system/system.rst | 118 ++++++++++++++++++ .../api-reference/system/base_mac_address.rst | 1 - docs/zh_CN/api-reference/system/system.rst | 1 + 7 files changed, 148 insertions(+), 96 deletions(-) delete mode 100644 docs/en/api-reference/system/base_mac_address.rst create mode 100644 docs/en/api-reference/system/system.rst delete mode 100644 docs/zh_CN/api-reference/system/base_mac_address.rst create mode 100644 docs/zh_CN/api-reference/system/system.rst diff --git a/components/esp32/include/esp_system.h b/components/esp32/include/esp_system.h index 01feea32d..b43dbebb8 100644 --- a/components/esp32/include/esp_system.h +++ b/components/esp32/include/esp_system.h @@ -31,10 +31,11 @@ typedef enum { ESP_MAC_ETH, } esp_mac_type_t; +/** @cond */ #define TWO_UNIVERSAL_MAC_ADDR 2 #define FOUR_UNIVERSAL_MAC_ADDR 4 #define UNIVERSAL_MAC_ADDR_NUM CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS - +/** @endcond */ /** * @brief Reset reasons @@ -55,7 +56,7 @@ typedef enum { /** @cond */ /** - * @attention application don't need to call this function anymore. It do nothing and will + * @attention Applications don't need to call this function anymore. It does nothing and will * be removed in future version. */ void system_init(void) __attribute__ ((deprecated)); @@ -67,13 +68,18 @@ void system_init(void) __attribute__ ((deprecated)); * This name will be removed in a future release. */ void system_restore(void) __attribute__ ((deprecated)); +/** @endcond */ +/** + * Shutdown handler type + */ typedef void (*shutdown_handler_t)(void); + /** * @brief Register shutdown handler * - * This function allows you to register a handler that gets invoked before a - * systematic shutdown of the chip. + * This function allows you to register a handler that gets invoked before + * the application is restarted using esp_restart function. */ esp_err_t esp_register_shutdown_handler(shutdown_handler_t handle); @@ -87,6 +93,7 @@ esp_err_t esp_register_shutdown_handler(shutdown_handler_t handle); */ void esp_restart(void) __attribute__ ((noreturn)); +/** @cond */ /** * @brief Restart system. * @@ -94,6 +101,7 @@ void esp_restart(void) __attribute__ ((noreturn)); * This name will be removed in a future release. */ void system_restart(void) __attribute__ ((deprecated, noreturn)); +/** @endcond */ /** * @brief Get reason of last reset @@ -101,6 +109,7 @@ void system_restart(void) __attribute__ ((deprecated, noreturn)); */ esp_reset_reason_t esp_reset_reason(void); +/** @cond */ /** * @brief Get system time, unit: microsecond. * @@ -108,6 +117,7 @@ esp_reset_reason_t esp_reset_reason(void); * This definition will be removed in a future release. */ uint32_t system_get_time(void) __attribute__ ((deprecated)); +/** @endcond */ /** * @brief Get the size of available heap. @@ -119,6 +129,7 @@ uint32_t system_get_time(void) __attribute__ ((deprecated)); */ uint32_t esp_get_free_heap_size(void); +/** @cond */ /** * @brief Get the size of available heap. * @@ -128,6 +139,7 @@ uint32_t esp_get_free_heap_size(void); * @return Available heap size, in bytes. */ uint32_t system_get_free_heap_size(void) __attribute__ ((deprecated)); +/** @endcond */ /** * @brief Get the minimum heap that has ever been available @@ -201,6 +213,7 @@ esp_err_t esp_efuse_mac_get_custom(uint8_t *mac); */ esp_err_t esp_efuse_mac_get_default(uint8_t *mac); +/** @cond */ /** * @brief Read hardware MAC address from efuse. * @@ -223,6 +236,7 @@ esp_err_t esp_efuse_read_mac(uint8_t *mac) __attribute__ ((deprecated)); * @return ESP_OK on success */ esp_err_t system_efuse_read_mac(uint8_t *mac) __attribute__ ((deprecated)); +/** @endcond */ /** * @brief Read base MAC address and set MAC address of the interface. @@ -254,6 +268,7 @@ esp_err_t esp_read_mac(uint8_t* mac, esp_mac_type_t type); */ esp_err_t esp_derive_local_mac(uint8_t* local_mac, const uint8_t* universal_mac); +/** @cond */ /** * Get SDK version * @@ -262,6 +277,7 @@ esp_err_t esp_derive_local_mac(uint8_t* local_mac, const uint8_t* universal_mac) * @return constant string "master" */ const char* system_get_sdk_version(void) __attribute__ ((deprecated)); +/** @endcond */ /** * Get IDF version @@ -278,13 +294,11 @@ typedef enum { CHIP_ESP32 = 1, //!< ESP32 } esp_chip_model_t; -/** - * Chip feature flags, used in esp_chip_info_t - */ -#define CHIP_FEATURE_EMB_FLASH BIT(0) -#define CHIP_FEATURE_WIFI_BGN BIT(1) -#define CHIP_FEATURE_BLE BIT(4) -#define CHIP_FEATURE_BT BIT(5) +/* Chip feature flags, used in esp_chip_info_t */ +#define CHIP_FEATURE_EMB_FLASH BIT(0) //!< Chip has embedded flash memory +#define CHIP_FEATURE_WIFI_BGN BIT(1) //!< Chip has 2.4GHz WiFi +#define CHIP_FEATURE_BLE BIT(4) //!< Chip has Bluetooth LE +#define CHIP_FEATURE_BT BIT(5) //!< Chip has Bluetooth Classic /** * @brief The structure represents information about the chip diff --git a/docs/Doxyfile b/docs/Doxyfile index d91b7cf23..2f50b6520 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -180,7 +180,9 @@ INPUT = \ ../../components/freertos/include/freertos/event_groups.h \ ../../components/freertos/include/freertos/ringbuf.h \ ### Helper functions for error codes - ../../components/esp32/include/esp_err.h + ../../components/esp32/include/esp_err.h \ + ### System APIs + ../../components/esp32/include/esp_system.h diff --git a/docs/en/api-reference/system/base_mac_address.rst b/docs/en/api-reference/system/base_mac_address.rst deleted file mode 100644 index abb4781d8..000000000 --- a/docs/en/api-reference/system/base_mac_address.rst +++ /dev/null @@ -1,82 +0,0 @@ -Base MAC address -================ - -Overview --------- - -Serveral MAC addresses (universally administered by IEEE) are uniquely assigned to the networking interfaces (WiFi/BT/Ethernet). -The final octet of each universally administered MAC address increases by one. Only the first one which is called base MAC address -of them is stored in EFUSE or external storage, the others are generated from it. Here, 'generate' means adding 0, 1, 2 and 3 -(respectively) to the final octet of the base MAC address. - -If the universally administered MAC addresses are not enough for all of the networking interfaces. Local administered MAC addresses -which are derived from universally administered MAC addresses are assigned to the reset of networking interfaces. - -A `definition of local vs universal MAC address can be found on Wikipedia `_. - -The number of universally administered MAC address can be configured using ``make menuconfig``. - -Base MAC address -^^^^^^^^^^^^^^^^ - -If using the default base MAC address factory programmed by Espressif in BLK0 of EFUSE, nothing needs to be done. - -If using a custom base MAC address stored in BLK3 of EFUSE, call API ``esp_efuse_mac_get_custom()`` to get the base MAC address -which is stored in BLK3 of EFUSE. If correct MAC address is returned, then call ``esp_base_mac_addr_set()`` to set the base MAC -address for system to generate the MAC addresses used by the networking interfaces(WiFi/BT/Ethernet). -There are 192 bits storage spaces for custom to store base MAC address in BLK3 of EFUSE. They are EFUSE_BLK3_RDATA0, -EFUSE_BLK3_RDATA1, EFUSE_BLK3_RDATA2, EFUSE_BLK3_RDATA3, EFUSE_BLK3_RDATA4 and EFUSE_BLK3_RDATA5, each of them is 32 bits -register. The format of the 192 bits storage spaces is: - -.. highlight:: none - -:: - - ------------------------------------------------------ - Field |Bits |Range |Description - ------------------------------------------------------ - version |8 |[191:184] |1: useful. 0: useless - ------------------------------------------------------ - reserve |112 |[183:72] |reserved - ------------------------------------------------------ - mac address |64 |[71:8] |base MAC address - ------------------------------------------------------ - mac crc |8 |[7:0] |crc of base MAC address - ------------------------------------------------------ - -If using base MAC address stored in external storage, firstly get the base MAC address stored in external storage, then call -API ``esp_base_mac_addr_set()`` to set the base MAC address for system to generate the MAC addresses used by the networking -interfaces(WiFi/BT/Ethernet). - -All of the steps must be done before initializing the networking interfaces(WiFi/BT/Ethernet). It is recommended to do it in -``app_main()`` which can be referenced in :example:`system/base_mac_address`. - -Number of universally administered MAC address -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -If the number of universal MAC addresses is two, only two interfaces (WiFi station and Bluetooth) receive a universally -administered MAC address. These are generated sequentially by adding 0 and 1 (respectively) to the base MAC address. -The remaining two interfaces (WiFi softap and Ethernet) receive local MAC addresses. These are derived from the universal -WiFi station and Bluetooth MAC addresses, respectively. - -If the number of universal MAC addresses is four, all four interfaces (WiFi station, WiFi softap, Bluetooth and Ethernet) -receive a universally administered MAC address. These are generated sequentially by adding 0, 1, 2 and 3 (respectively) -to the final octet of the base MAC address. - -When using the default (Espressif-assigned) base MAC address, either setting can be used. When using a custom universal MAC -address range, the correct setting will depend on the allocation of MAC addresses in this range (either 2 or 4 per device.) - -API Reference -------------- - -Header Files -^^^^^^^^^^^^ - - * :component_file:`esp32/include/esp_system.h` - - -Functions ---------- - -.. doxygenfunction:: esp_base_mac_addr_set -.. doxygenfunction:: esp_efuse_mac_get_custom diff --git a/docs/en/api-reference/system/index.rst b/docs/en/api-reference/system/index.rst index 2b94e6d55..76b7c8d62 100644 --- a/docs/en/api-reference/system/index.rst +++ b/docs/en/api-reference/system/index.rst @@ -16,11 +16,11 @@ System API Application Level Tracing Power Management Sleep Modes - Base MAC address Over The Air Updates (OTA) ESP HTTPS OTA ESP pthread Error Codes and Helper Functions + Miscellaneous System APIs Example code for this API section is provided in :example:`system` directory of ESP-IDF examples. diff --git a/docs/en/api-reference/system/system.rst b/docs/en/api-reference/system/system.rst new file mode 100644 index 000000000..2f0834a56 --- /dev/null +++ b/docs/en/api-reference/system/system.rst @@ -0,0 +1,118 @@ +Miscellaneous System APIs +========================= + +Software reset +-------------- + +To perform software reset of the chip, :cpp:func:`esp_restart` function is provided. When the function is called, execution of the program will stop, both CPUs will be reset, application will be loaded by the bootloader and started again. + +Additionally, :cpp:func:`esp_register_shutdown_handler` function is provided to register a routine which needs to be called prior to restart (when done by :cpp:func:`esp_restart`). This is similar to the functionality of ``atexit`` POSIX function. + +Reset reason +------------ + +ESP-IDF application can be started or restarted due to a variety of reasons. To get the last reset reason, call :cpp:func:`esp_reset_reason` function. See description of :cpp:type:`esp_reset_reason_t` for the list of possible reset reasons. + +Heap memory +----------- + +Two heap memory related functions are provided: + +* :cpp:func:`esp_get_free_heap_size` returns the current size of free heap memory +* :cpp:func:`esp_get_minimum_free_heap_size` returns the minimum size of free heap memory that was available during program execution. + +Note that ESP-IDF supports multiple heaps with different capabilities. Functions mentioned in this section return the size of heap memory which can be allocated using ``malloc`` family of functions. For further information about heap memory see :doc:`Heap Memory Allocation `. + +Random number generation +------------------------ + +ESP32 contains a hardware random number generator, values from it can be obtained using :cpp:func:`esp_random`. + +When Wi-Fi or Bluetooth are enabled, numbers returned by hardware random number generator (RNG) can be considered true random numbers. Without Wi-Fi or Bluetooth enabled, hardware RNG is a pseudo-random number generator. At startup, ESP-IDF bootloader seeds the hardware RNG with entropy, but care must be taken when reading random values between the start of ``app_main`` and initialization of Wi-Fi or Bluetooth drivers. + + +MAC Address +----------- + +These APIs allow querying and customizing MAC addresses used by Wi-Fi, Bluetooth, and Ethernet drivers. + +ESP32 has up to 4 network interfaces: Wi-Fi station, Wi-Fi AP, Ethernet, and Bluetooth. Each of these interfaces needs to have a MAC address assigned to it. In ESP-IDF these addresses are calculated from *Base MAC address*. Base MAC address can be initialized with factory-programmed value from EFUSE, or with a user-defined value. In addition to setting the base MAC address, applications can specify the way in which MAC addresses are allocated to devices. See `Number of universally administered MAC address`_ section for more details. + ++---------------+--------------------------------+----------------------------------+ +| Interface | MAC address | MAC address | +| | (4 universally administered) | (2 universally administered) | ++===============+================================+==================================+ +| Wi-Fi Station | base_mac | base_mac | ++---------------+--------------------------------+----------------------------------+ +| Wi-Fi SoftAP | base_mac, +1 to the last octet | base_mac, first octet randomized | ++---------------+--------------------------------+----------------------------------+ +| Bluetooth | base_mac, +2 to the last octet | base_mac, +1 to the last octet | ++---------------+--------------------------------+----------------------------------+ +| Ethernet | base_mac, +3 to the last octet | base_mac, +1 to the last octet, | +| | | first octet randomized | ++---------------+--------------------------------+----------------------------------+ + + +Base MAC address +^^^^^^^^^^^^^^^^ + +Wi-Fi, Bluetooth, and Ethernet drivers use :cpp:func:`esp_read_mac` function to get MAC address for a specific interface. + +By default, this function will use MAC address factory programmed in BLK0 of EFUSE as the base MAC address. MAC addresses of each interface will be calculated according to the table above. + +Applications which don't use MAC address factory programmed into BLK0 of EFUSE can modify base MAC address used by :cpp:func:`esp_read_mac` using a call to :cpp:func:`esp_base_mac_addr_set`. Custom value of MAC address can come from application defined storage, such as Flash, NVS, etc. Note that the call to :cpp:func:`esp_base_mac_addr_set` needs to happen before network protocol stacks are initialized, for example, early in ``app_main``. + +Custom MAC address in BLK3 of EFUSE +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To facilitate usage of custom MAC addresses, ESP-IDF provides :cpp:func:`esp_efuse_mac_get_custom` function, which loads MAC address from BLK3 of EFUSE. This function assumes that custom MAC address is stored in BLK3 of EFUSE (EFUSE_BLK3_RDATA0, EFUSE_BLK3_RDATA1, EFUSE_BLK3_RDATA2, EFUSE_BLK3_RDATA3, EFUSE_BLK3_RDATA4, EFUSE_BLK3_RDATA5 registers) in the following format: + ++-----------------+-----------+---------------+------------------------------+ +| Field | # of bits | Range of bits | Notes | ++=================+===========+===============+==============================+ +| Version | 8 | 191:184 | 0: invalid, others — valid | ++-----------------+-----------+---------------+------------------------------+ +| Reserved | 128 | 183:56 | | ++-----------------+-----------+---------------+------------------------------+ +| MAC address | 48 | 55:8 | | ++-----------------+-----------+---------------+------------------------------+ +| MAC address CRC | 8 | 7:0 | CRC-8-CCITT, polynomial 0x07 | ++-----------------+-----------+---------------+------------------------------+ + +Once MAC address has been obtained using :cpp:func:`esp_efuse_mac_get_custom`, call :cpp:func:`esp_base_mac_addr_set` to set this MAC address as base MAC address. + + +Number of universally administered MAC address +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Serveral MAC addresses (universally administered by IEEE) are uniquely assigned to the networking interfaces (Wi-Fi/BT/Ethernet). The final octet of each universally administered MAC address increases by one. Only the first one of them (which is called base MAC address) is stored in EFUSE or external storage, the others are generated from it. Here, 'generate' means adding 0, 1, 2 and 3 (respectively) to the final octet of the base MAC address. + +If the universally administered MAC addresses are not enough for all of the networking interfaces, locally administered MAC addresses which are derived from universally administered MAC addresses are assigned to the rest of networking interfaces. + +See `this article `_ for the definition of local and universally administered MAC addresses. + +The number of universally administered MAC address can be configured using :envvar:`CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS`. + +If the number of universal MAC addresses is two, only two interfaces (Wi-Fi Station and Bluetooth) receive a universally administered MAC address. These are generated sequentially by adding 0 and 1 (respectively) to the base MAC address. The remaining two interfaces (Wi-Fi SoftAP and Ethernet) receive local MAC addresses. These are derived from the universal Wi-Fi station and Bluetooth MAC addresses, respectively. + +If the number of universal MAC addresses is four, all four interfaces (Wi-Fi Station, Wi-Fi SoftAP, Bluetooth and Ethernet) receive a universally administered MAC address. These are generated sequentially by adding 0, 1, 2 and 3 (respectively) to the final octet of the base MAC address. + +When using the default (Espressif-assigned) base MAC address, either setting can be used. When using a custom universal MAC address range, the correct setting will depend on the allocation of MAC addresses in this range (either 2 or 4 per device.) + +Chip version +------------ + +:cpp:func:`esp_chip_info` function fills :cpp:class:`esp_chip_info_t` structure with information about the chip. This includes the chip revision, number of CPU cores, and a bit mask of features enabled in the chip. + +SDK version +----------- + +:cpp:func:`esp_get_idf_version` returns a string describing the IDF version which was used to compile the application. This is the same value as the one available through ``IDF_VER`` variable of the build system. The version string generally has the format of ``git describe`` output. + + +API Reference +------------- + +.. include:: /_build/inc/esp_system.inc + + diff --git a/docs/zh_CN/api-reference/system/base_mac_address.rst b/docs/zh_CN/api-reference/system/base_mac_address.rst deleted file mode 100644 index 05cfa83ba..000000000 --- a/docs/zh_CN/api-reference/system/base_mac_address.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../../../en/api-reference/system/base_mac_address.rst \ No newline at end of file diff --git a/docs/zh_CN/api-reference/system/system.rst b/docs/zh_CN/api-reference/system/system.rst new file mode 100644 index 000000000..fc07ecfe3 --- /dev/null +++ b/docs/zh_CN/api-reference/system/system.rst @@ -0,0 +1 @@ +.. include:: ../../../en/api-reference/system/system.rst