1 // Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <stdint.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <stdbool.h>
19
20 #include "esp_private/system_internal.h"
21 #include "driver/rtc_cntl.h"
22
23 #include "esp_rom_sys.h"
24
25 #include "soc/soc.h"
26 #include "soc/cpu.h"
27 #include "soc/rtc_periph.h"
28 #include "hal/cpu_hal.h"
29
30 #include "hal/brownout_hal.h"
31
32 #include "sdkconfig.h"
33
34 #if defined(CONFIG_ESP32_BROWNOUT_DET_LVL)
35 #define BROWNOUT_DET_LVL CONFIG_ESP32_BROWNOUT_DET_LVL
36 #elif defined(CONFIG_ESP32S2_BROWNOUT_DET_LVL)
37 #define BROWNOUT_DET_LVL CONFIG_ESP32S2_BROWNOUT_DET_LVL
38 #elif defined(CONFIG_ESP32S3_BROWNOUT_DET_LVL)
39 #define BROWNOUT_DET_LVL CONFIG_ESP32S3_BROWNOUT_DET_LVL
40 #elif defined(CONFIG_ESP32C3_BROWNOUT_DET_LVL)
41 #define BROWNOUT_DET_LVL CONFIG_ESP32C3_BROWNOUT_DET_LVL
42 #else
43 #define BROWNOUT_DET_LVL 0
44 #endif
45
46 #if SOC_BROWNOUT_RESET_SUPPORTED
47 #define BROWNOUT_RESET_EN true
48 #else
49 #define BROWNOUT_RESET_EN false
50 #endif // SOC_BROWNOUT_RESET_SUPPORTED
51
52 #ifndef SOC_BROWNOUT_RESET_SUPPORTED
rtc_brownout_isr_handler(void * arg)53 static void rtc_brownout_isr_handler(void *arg)
54 {
55 /* Normally RTC ISR clears the interrupt flag after the application-supplied
56 * handler returns. Since restart is called here, the flag needs to be
57 * cleared manually.
58 */
59 brownout_hal_intr_clear();
60 /* Stall the other CPU to make sure the code running there doesn't use UART
61 * at the same time as the following esp_rom_printf.
62 */
63 esp_cpu_stall(!cpu_hal_get_core_id());
64 esp_reset_reason_set_hint(ESP_RST_BROWNOUT);
65 esp_rom_printf("\r\nBrownout detector was triggered\r\n\r\n");
66 esp_restart_noos();
67 }
68 #endif // not SOC_BROWNOUT_RESET_SUPPORTED
69
esp_brownout_init(void)70 void esp_brownout_init(void)
71 {
72 brownout_hal_config_t cfg = {
73 .threshold = BROWNOUT_DET_LVL,
74 .enabled = true,
75 .reset_enabled = BROWNOUT_RESET_EN,
76 .flash_power_down = true,
77 .rf_power_down = true,
78 };
79
80 brownout_hal_config(&cfg);
81
82
83 #ifndef SOC_BROWNOUT_RESET_SUPPORTED
84 rtc_isr_register(rtc_brownout_isr_handler, NULL, RTC_CNTL_BROWN_OUT_INT_ENA_M);
85
86 brownout_hal_intr_enable(true);
87 #endif // not SOC_BROWNOUT_RESET_SUPPORTED
88 }
89
esp_brownout_disable(void)90 void esp_brownout_disable(void)
91 {
92 brownout_hal_config_t cfg = {
93 .enabled = false,
94 };
95
96 brownout_hal_config(&cfg);
97
98 #ifndef SOC_BROWNOUT_RESET_SUPPORTED
99 brownout_hal_intr_enable(false);
100
101 rtc_isr_deregister(rtc_brownout_isr_handler, NULL);
102 #endif // not SOC_BROWNOUT_RESET_SUPPORTED
103 }
104