• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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