1 /*
2  * SPDX-FileCopyrightText: 2015-2022 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 "freertos/FreeRTOS.h"
10 #include "freertos/task.h"
11 #if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
12 #if CONFIG_IDF_TARGET_ESP32S2
13 #include "esp32s2/memprot.h"
14 #else
15 #include "esp_memprot.h"
16 #endif
17 #endif
18 
19 #define SHUTDOWN_HANDLERS_NO 5
20 
21 static shutdown_handler_t shutdown_handlers[SHUTDOWN_HANDLERS_NO];
22 
esp_register_shutdown_handler(shutdown_handler_t handler)23 esp_err_t esp_register_shutdown_handler(shutdown_handler_t handler)
24 {
25     for (int i = 0; i < SHUTDOWN_HANDLERS_NO; i++) {
26         if (shutdown_handlers[i] == handler) {
27             return ESP_ERR_INVALID_STATE;
28         } else if (shutdown_handlers[i] == NULL) {
29             shutdown_handlers[i] = handler;
30             return ESP_OK;
31         }
32     }
33     return ESP_ERR_NO_MEM;
34 }
35 
esp_unregister_shutdown_handler(shutdown_handler_t handler)36 esp_err_t esp_unregister_shutdown_handler(shutdown_handler_t handler)
37 {
38     for (int i = 0; i < SHUTDOWN_HANDLERS_NO; i++) {
39         if (shutdown_handlers[i] == handler) {
40             shutdown_handlers[i] = NULL;
41             return ESP_OK;
42         }
43     }
44     return ESP_ERR_INVALID_STATE;
45 }
46 
47 
esp_restart(void)48 void esp_restart(void)
49 {
50     for (int i = SHUTDOWN_HANDLERS_NO - 1; i >= 0; i--) {
51         if (shutdown_handlers[i]) {
52             shutdown_handlers[i]();
53         }
54     }
55 
56 #ifdef CONFIG_FREERTOS_SMP
57     //Note: Scheduler suspension behavior changed in FreeRTOS SMP
58     vTaskPreemptionDisable(NULL);
59 #else
60     // Disable scheduler on this core.
61     vTaskSuspendAll();
62 #endif // CONFIG_FREERTOS_SMP
63 
64     bool digital_reset_needed = false;
65 #if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
66 #if CONFIG_IDF_TARGET_ESP32S2
67     if (esp_memprot_is_intr_ena_any() || esp_memprot_is_locked_any()) {
68         digital_reset_needed = true;
69     }
70 #else
71     bool is_on = false;
72     if (esp_mprot_is_intr_ena_any(&is_on) != ESP_OK || is_on) {
73         digital_reset_needed = true;
74     } else if (esp_mprot_is_conf_locked_any(&is_on) != ESP_OK || is_on) {
75         digital_reset_needed = true;
76     }
77 #endif
78 #endif
79     if (digital_reset_needed) {
80         esp_restart_noos_dig();
81     }
82     esp_restart_noos();
83 }
84