1 /*
2  * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "esp_system.h"
8 #include "esp_private/system_internal.h"
9 #include "esp_heap_caps.h"
10 #include "freertos/FreeRTOS.h"
11 #include "freertos/task.h"
12 #include "soc/cpu.h"
13 #include "soc/rtc.h"
14 #include "soc/rtc_cntl_reg.h"
15 #include "esp_private/panic_internal.h"
16 #include "esp_rom_uart.h"
17 #if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
18 #if CONFIG_IDF_TARGET_ESP32S2
19 #include "esp32s2/memprot.h"
20 #else
21 #include "esp_memprot.h"
22 #endif
23 #endif
24 
25 #define SHUTDOWN_HANDLERS_NO 5
26 
27 static shutdown_handler_t shutdown_handlers[SHUTDOWN_HANDLERS_NO];
28 
esp_restart_noos_dig(void)29 void IRAM_ATTR esp_restart_noos_dig(void)
30 {
31     // make sure all the panic handler output is sent from UART FIFO
32     if (CONFIG_ESP_CONSOLE_UART_NUM >= 0) {
33         esp_rom_uart_tx_wait_idle(CONFIG_ESP_CONSOLE_UART_NUM);
34     }
35 
36     // switch to XTAL (otherwise we will keep running from the PLL)
37     rtc_clk_cpu_freq_set_xtal();
38 
39 #if CONFIG_IDF_TARGET_ESP32
40     esp_cpu_unstall(PRO_CPU_NUM);
41 #endif
42     // reset the digital part
43     SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_SYS_RST);
44     while (true) {
45         ;
46     }
47 }
48 
esp_register_shutdown_handler(shutdown_handler_t handler)49 esp_err_t esp_register_shutdown_handler(shutdown_handler_t handler)
50 {
51     for (int i = 0; i < SHUTDOWN_HANDLERS_NO; i++) {
52         if (shutdown_handlers[i] == handler) {
53             return ESP_ERR_INVALID_STATE;
54         } else if (shutdown_handlers[i] == NULL) {
55             shutdown_handlers[i] = handler;
56             return ESP_OK;
57         }
58     }
59     return ESP_ERR_NO_MEM;
60 }
61 
esp_unregister_shutdown_handler(shutdown_handler_t handler)62 esp_err_t esp_unregister_shutdown_handler(shutdown_handler_t handler)
63 {
64     for (int i = 0; i < SHUTDOWN_HANDLERS_NO; i++) {
65         if (shutdown_handlers[i] == handler) {
66             shutdown_handlers[i] = NULL;
67             return ESP_OK;
68         }
69     }
70     return ESP_ERR_INVALID_STATE;
71 }
72 
73 
esp_restart(void)74 void IRAM_ATTR esp_restart(void)
75 {
76     for (int i = SHUTDOWN_HANDLERS_NO - 1; i >= 0; i--) {
77         if (shutdown_handlers[i]) {
78             shutdown_handlers[i]();
79         }
80     }
81 
82     // Disable scheduler on this core.
83     vTaskSuspendAll();
84 
85     bool digital_reset_needed = false;
86 #if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
87 #if CONFIG_IDF_TARGET_ESP32S2
88     if (esp_memprot_is_intr_ena_any() || esp_memprot_is_locked_any()) {
89         digital_reset_needed = true;
90     }
91 #else
92     bool is_on = false;
93     if (esp_mprot_is_intr_ena_any(&is_on) != ESP_OK || is_on) {
94         digital_reset_needed = true;
95     } else if (esp_mprot_is_conf_locked_any(&is_on) != ESP_OK || is_on) {
96         digital_reset_needed = true;
97     }
98 #endif
99 #endif
100     if (digital_reset_needed) {
101         esp_restart_noos_dig();
102     }
103     esp_restart_noos();
104 }
105 
esp_get_free_heap_size(void)106 uint32_t esp_get_free_heap_size( void )
107 {
108     return heap_caps_get_free_size( MALLOC_CAP_DEFAULT );
109 }
110 
esp_get_free_internal_heap_size(void)111 uint32_t esp_get_free_internal_heap_size( void )
112 {
113     return heap_caps_get_free_size( MALLOC_CAP_8BIT | MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL );
114 }
115 
esp_get_minimum_free_heap_size(void)116 uint32_t esp_get_minimum_free_heap_size( void )
117 {
118     return heap_caps_get_minimum_free_size( MALLOC_CAP_DEFAULT );
119 }
120 
esp_get_idf_version(void)121 const char *esp_get_idf_version(void)
122 {
123     return IDF_VER;
124 }
125 
esp_system_abort(const char * details)126 void __attribute__((noreturn)) esp_system_abort(const char *details)
127 {
128     panic_abort(details);
129 }
130