1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
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 * Description: Reboot interface.
15 * Author:
16 * Create: 2018-10-15
17 */
18 #include "non_os.h"
19 #include "systick.h"
20 #include "hal_reboot.h"
21 #include "preserve.h"
22 #if defined(SUPPORT_IPC)
23 #include "ipc.h"
24 #elif defined(IPC_NEW)
25 #include "ipc.h"
26 #include "ipc_porting.h"
27 #endif
28 #if ((IS_MAIN_CORE == NO))
29 #include "watchdog.h"
30 #endif
31 #include "non_os_reboot.h"
32 #if defined(CONFIG_DFX_SUPPORT_DELAY_REBOOT) && (CONFIG_DFX_SUPPORT_DELAY_REBOOT == DFX_YES)
33 #include "dfx_feature_config.h"
34 #include "dfx_adapt_layer.h"
35 #endif
36
37 #define DELAY_MS_BEFORE_REBOOT 1000
38
39 #if defined(CONFIG_DFX_SUPPORT_DELAY_REBOOT) && (CONFIG_DFX_SUPPORT_DELAY_REBOOT == DFX_YES)
40 typedef struct {
41 uint32_t permit_sec; /* 允许重启时间 */
42 } delay_request_item_t; /* 延时请求的一个item */
43
44 typedef struct {
45 delay_request_item_t item[VETO_REBOOT_REASON_MAX];
46 uint32_t permit_reboot_sec;
47 } delay_request_t; /* 延时请求结构 */
48
49 static delay_request_t g_delay_request_info = {0};
50 #endif /* CONFIG_DFX_SUPPORT_DELAY_REBOOT */
51
52 static reboot_cause_t g_reboot_reset_reason = REBOOT_CAUSE_UNKNOWN;
53
54 /* Initialise the reboot subsystem */
reboot_init(void)55 void reboot_init(void)
56 {
57 if (non_os_is_driver_initialised(DRIVER_INIT_REBOOT) == true) {
58 return;
59 }
60
61 non_os_set_driver_initalised(DRIVER_INIT_REBOOT, true);
62 }
63
64 /* De-initialise the reboot subsystem */
reboot_deinit(void)65 void reboot_deinit(void)
66 {
67 non_os_set_driver_initalised(DRIVER_INIT_REBOOT, false);
68 }
69
70 #if CORE == MASTER_BY_ALL
reboot_chip(void)71 void reboot_chip(void)
72 {
73 hal_reboot_chip();
74 }
75 #endif
76
77 #if CORE == APPS
78 #if EXCEPTION_TEST_ENABLE == YES && defined(SUPPORT_IPC)
cores_exception_test(cores_t core,ipc_exception_test_command_e exception_test_command)79 static void cores_exception_test(cores_t core, ipc_exception_test_command_e exception_test_command)
80 {
81 ipc_status_t ipc_returned_value;
82 ipc_payload_exception_test test_command;
83 test_command.command = exception_test_command;
84
85 ipc_returned_value = ipc_spin_send_message_timeout(core,
86 IPC_ACTION_EXCEPTION_TEST,
87 (const ipc_payload *)&test_command,
88 sizeof(ipc_payload_exception_test),
89 IPC_PRIORITY_LOWEST,
90 false, IPC_SPIN_SEND_DEFAULT_TIMEOUT);
91 if (ipc_returned_value != IPC_STATUS_OK) {
92 UNUSED(ipc_returned_value);
93 }
94 }
95
app_exception_test(ipc_exception_test_command_e exception_test_command)96 static void app_exception_test(ipc_exception_test_command_e exception_test_command)
97 {
98 uint16_t* test_pointer = NULL;
99 volatile uint16_t i = true;
100 switch (exception_test_command) {
101 case EXCEPTION_TEST_COMMAND_APP_WTD_REBOOT:
102 while (i != 0) {}
103 break;
104 case EXCEPTION_TEST_COMMAND_APP_PANIC:
105 panic(PANIC_EXCEPTION_TEST, __LINE__);
106 break;
107 case EXCEPTION_TEST_COMMAND_APP_HARDFAULT:
108 // tscancode-suppress *
109 *test_pointer = 0;
110 break;
111 case EXCEPTION_TEST_COMMAND_APP_WDT_FRST:
112 non_os_enter_critical();
113 while (i != 0) {}
114 non_os_exit_critical();
115 break;
116 default:
117 break;
118 }
119 }
120 #endif
121
122 #if EXCEPTION_TEST_ENABLE == YES && defined(SUPPORT_IPC)
exception_test(ipc_exception_test_command_e exception_test_command)123 void exception_test(ipc_exception_test_command_e exception_test_command)
124 {
125 if (exception_test_command <= EXCEPTION_TEST_COMMAND_BT_STD_CHIP_WDT_FRST) {
126 cores_exception_test(CORES_BT_CORE, exception_test_command);
127 } else if (exception_test_command <= EXCEPTION_TEST_COMMAND_APP_WDT_FRST) {
128 app_exception_test(exception_test_command);
129 #if (CHIP_LIBRA == 1)
130 } else {
131 cores_exception_test(CORES_GNSS_CORE, exception_test_command);
132 #endif
133 }
134 }
135 #endif
136 #endif
137
138 /* Perform a software reboot of the entire system. */
reboot_system(reboot_cause_t cause)139 void reboot_system(reboot_cause_t cause)
140 {
141 UNUSED(cause);
142 #ifdef SUPPORT_IPC
143 ipc_payload_request_reboot request_reboot;
144 request_reboot.requested_reboot_reason = ((uint16_t)cause);
145 UNUSED(request_reboot);
146 #if (IS_MAIN_CORE == NO)
147 non_os_enter_critical();
148 (void)ipc_spin_send_message_timeout(CORES_APPS_CORE,
149 IPC_ACTION_SYS_REBOOT_REQ,
150 (const ipc_payload *)&request_reboot,
151 sizeof(ipc_payload_request_reboot),
152 IPC_PRIORITY_HIGHEST,
153 false, IPC_SPIN_SEND_MAX_TIMEOUT);
154 non_os_exit_critical();
155 while (true) {
156 uapi_watchdog_kick();
157 }
158 #endif
159 #elif (defined(IPC_NEW) && (IS_MAIN_CORE == NO))
160 req_reboot_msg msg = {0};
161 msg.req_reboot_reason = (uint16_t)cause;
162 msg.core = CORE;
163 ipc_msg_info_t head = {0};
164 head.dst_core = CORES_APPS_CORE;
165 head.priority = 1;
166 head.msg_id = IPC_MSG_SYS_REBOOT_REQ;
167 head.buf_addr = (uint8_t *)&msg;
168 head.buf_len = (size_t)sizeof(req_reboot_msg);
169 non_os_enter_critical();
170 (void)uapi_ipc_send_msg_sync(&head);
171 non_os_exit_critical();
172 #endif
173 #if MCU_ONLY
174 reboot_chip();
175 #endif
176 }
177
reboot_get_reset_reason(void)178 reboot_cause_t reboot_get_reset_reason(void)
179 {
180 return g_reboot_reset_reason;
181 }
182
183 #if CORE == MASTER_BY_ALL
reboot_get_security_reboot_reason(void)184 reboot_cause_t reboot_get_security_reboot_reason(void)
185 {
186 return (reboot_cause_t)hal_reboot_get_reset_reason();
187 }
188
189 #endif // CORE == BT
190
191 #if defined(CONFIG_DFX_SUPPORT_DELAY_REBOOT) && (CONFIG_DFX_SUPPORT_DELAY_REBOOT == DFX_YES)
192 /*
193 * @brief 延时重启,在一段时间内投票反对重启,仅影响uapi_reboot_system_check_veto接口。
194 * @param reason 延时原因
195 * @param sec 延时时间
196 * @retval 返回实际延时时间。如果系统未对最大延时时间进行配置返回传入时间。如果系统进行了限制则返回时间小于最大延时时间。
197 */
uapi_reboot_vote_against(veto_reboot_reason_t reason,uint32_t sec)198 uint32_t uapi_reboot_vote_against(veto_reboot_reason_t reason, uint32_t sec)
199 {
200 uint32_t permit_sec = 0;
201 if (reason >= VETO_REBOOT_REASON_MAX) {
202 return ERRCODE_FAIL;
203 }
204
205 uint32_t cur_sec = dfx_get_cur_second();
206 if (cur_sec == 0) {
207 return ERRCODE_FAIL;
208 }
209 permit_sec = cur_sec + sec;
210
211 uint32_t int_value = osal_irq_lock();
212
213 if (permit_sec > g_delay_request_info.item[reason].permit_sec) {
214 g_delay_request_info.item[reason].permit_sec = permit_sec;
215 }
216
217 osal_irq_restore(int_value);
218 return ERRCODE_SUCC;
219 }
220
221 /*
222 * @brief 去延时重启
223 * @param reason 延时原因
224 * @retval 返回实际延时时间。如果系统未对最大延时时间进行配置返回传入时间。如果系统进行了限制则返回时间小于最大延时时间。
225 */
uapi_reboot_unvote_against(veto_reboot_reason_t reason)226 void uapi_reboot_unvote_against(veto_reboot_reason_t reason)
227 {
228 if (reason >= VETO_REBOOT_REASON_MAX) {
229 return ;
230 }
231
232 uint32_t int_value = osal_irq_lock();
233 g_delay_request_info.item[reason].permit_sec = 0;
234
235 osal_irq_restore(int_value);
236 }
237
238 /*
239 * @brief 重启。受延时重启影响
240 * @param reason 重启原因
241 */
uapi_reboot_system_check_veto(reboot_cause_t reason)242 void uapi_reboot_system_check_veto(reboot_cause_t reason)
243 {
244 uint32_t cur_sec = dfx_get_cur_second();
245 if (cur_sec == ERRCODE_FAIL) {
246 return;
247 }
248 uint32_t permit_sec = 0;
249 uint32_t int_value = osal_irq_lock();
250
251 for (int i = 0; i < VETO_REBOOT_REASON_MAX; i++) {
252 if (g_delay_request_info.item[i].permit_sec > permit_sec) {
253 permit_sec = g_delay_request_info.item[i].permit_sec;
254 }
255 }
256
257 osal_irq_restore(int_value);
258
259 if (permit_sec > cur_sec) {
260 return;
261 } else {
262 reboot_system(reason);
263 }
264 }
265
266 #else
uapi_reboot_vote_against(veto_reboot_reason_t reason,uint32_t sec)267 uint32_t uapi_reboot_vote_against(veto_reboot_reason_t reason, uint32_t sec)
268 {
269 unused(reason);
270 unused(sec);
271 return 0;
272 }
uapi_reboot_unvote_against(veto_reboot_reason_t reason)273 void uapi_reboot_unvote_against(veto_reboot_reason_t reason)
274 {
275 unused(reason);
276 return;
277 }
278
uapi_reboot_system_check_veto(reboot_cause_t reason)279 void uapi_reboot_system_check_veto(reboot_cause_t reason)
280 {
281 reboot_system(reason);
282 }
283 #endif /* CONFIG_DFX_SUPPORT_DELAY_REBOOT */
284