1 /*
2 * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved.
3 *
4 * UniProton is licensed under Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 * http://license.coscl.org.cn/MulanPSL2
8 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11 * See the Mulan PSL v2 for more details.
12 * Create: 2009-12-22
13 * Description: 异常模块的C文件。
14 */
15 #include "prt_clk.h"
16 #include "prt_exc_internal.h"
17 #include "prt_sys_external.h"
18 #include "prt_task_external.h"
19 #include "prt_irq_external.h"
20 #include "prt_asm_cpu_external.h"
21
22 OS_SEC_BSS bool g_excSaveFlag;
23 OS_SEC_BSS struct ExcRegInfo g_excInfo;
24
25 // 异常时获取当前任务的信息
26 OS_SEC_BSS ExcTaskInfoFunc g_excTaskInfoGet;
27
OsExcConfigInit(void)28 OS_SEC_L4_TEXT U32 OsExcConfigInit(void)
29 {
30 return OS_OK;
31 }
32
33 /*
34 * 描述:获取异常线程信息
35 */
OsExcGetThreadInfo(struct ExcInfo * excInfo)36 static OS_SEC_L4_TEXT void OsExcGetThreadInfo(struct ExcInfo *excInfo)
37 {
38 struct TskInfo taskInfo;
39 U32 threadId = INVALIDPID;
40
41 if (memset_s(&taskInfo, sizeof(struct TskInfo), 0, sizeof(struct TskInfo)) != EOK) {
42 OS_GOTO_SYS_ERROR1();
43 }
44 #if defined(OS_OPTION_TASK_INFO)
45 /* 任务存在时 */
46 if ((OsTskMaxNumGet() > 0) && ((UNI_FLAG & OS_FLG_BGD_ACTIVE) != 0)) {
47 /* 记录当前任务ID号 */
48 if (PRT_TaskSelf(&threadId) == OS_OK) {
49 /* 获取当前任务信息 */
50 OS_ERR_RECORD(PRT_TaskGetInfo(threadId, &taskInfo));
51 }
52 }
53 #endif
54 /* 记录发生异常时的线程ID,发生在任务中,此项具有意义,其他线程中,此项无意义 */
55 excInfo->threadId = INVALIDPID;
56
57 /* 设置异常前的线程类型 */
58 if (g_intCount > CUR_NEST_COUNT) {
59 excInfo->threadType = EXC_IN_HWI;
60 } else if ((UNI_FLAG & OS_FLG_TICK_ACTIVE) != 0) {
61 excInfo->threadType = EXC_IN_TICK;
62 } else if ((UNI_FLAG & OS_FLG_SYS_ACTIVE) != 0) {
63 excInfo->threadType = EXC_IN_SYS;
64 } else if ((UNI_FLAG & OS_FLG_BGD_ACTIVE) != 0) {
65 excInfo->threadType = EXC_IN_TASK;
66 if (OsTskMaxNumGet() > 0) { /* 任务存在时 */
67 excInfo->threadId = threadId;
68 }
69 } else { // OS_FLG_BGD_ACTIVE没有置位,代表此时还在系统进程中,没有进入业务线程。
70 excInfo->threadType = EXC_IN_SYS_BOOT;
71 }
72
73 /* MSP主堆栈 */
74 if ((excInfo->sp >= OsGetSysStackTop()) && (excInfo->sp <= OsGetSysStackBottom())) {
75 excInfo->stackBottom = OsGetSysStackBottom();
76 } else { /* PSP进程堆栈 */
77 excInfo->stackBottom = TRUNCATE((taskInfo.topOfStack + taskInfo.stackSize), OS_TSK_STACK_ADDR_ALIGN);
78 }
79 }
80
81 /*
82 * 描述:记录异常信息
83 */
OsExcSaveInfo(struct ExcRegInfo * regs)84 OS_SEC_L4_TEXT void OsExcSaveInfo(struct ExcRegInfo *regs)
85 {
86 struct ExcInfo *excInfo = OS_EXC_INFO_ADDR;
87 char *version = NULL;
88 U64 count;
89
90 /* 记录os版本号 */
91 version = PRT_SysGetOsVersion();
92 if (version != NULL) {
93 if (strncpy_s(excInfo->osVer, sizeof(excInfo->osVer),
94 version, sizeof(excInfo->osVer) - 1) != EOK) {
95 OS_GOTO_SYS_ERROR1();
96 }
97 }
98 excInfo->osVer[OS_SYS_OS_VER_LEN - 1] = '\0';
99
100 /* 记录异常类型 */
101 excInfo->excCause = regs->excType;
102 /* 记录CPU ID */
103 excInfo->coreId = OsGetHwThreadId();
104
105 /* 设置字节序 */
106 excInfo->byteOrder = OS_BYTE_ORDER;
107
108 /* 记录CPU类型 */
109 excInfo->cpuType = OsGetCpuType();
110
111 /* 记录CPU TICK值 */
112 count = PRT_ClkGetCycleCount64();
113 excInfo->cpuTick = count;
114
115 /* 记录当前异常嵌套次数 */
116 excInfo->nestCnt = CUR_NEST_COUNT;
117
118 /* 记录寄存器信息 */
119 excInfo->regInfo = (*regs);
120
121 /* 记录异常前栈指针 */
122 excInfo->sp = (regs->context)->sp;
123
124 /* 记录异常前栈底 */
125 excInfo->stackBottom = INVALIDSTACKBOTTOM;
126
127 OsExcGetThreadInfo(excInfo);
128 }
129
OsExcRecordInfo(U32 excType,U32 faultAddr,struct ExcContext * excBufAddr)130 static OS_SEC_L4_TEXT void OsExcRecordInfo(U32 excType, U32 faultAddr, struct ExcContext *excBufAddr)
131 {
132 // 若为1时faultAddr有效
133 U16 tmpFlag = (U16)OS_GET_32BIT_HIGH_16BIT(excType);
134
135 g_excInfo.excType = excType;
136 /* 此掩码在CDA解析时需要判断 */
137 if (((U32)tmpFlag & OS_EXC_FLAG_FAULTADDR_VALID) != 0) {
138 g_excInfo.faultAddr = faultAddr;
139 } else {
140 g_excInfo.faultAddr = OS_EXC_IMPRECISE_ACCESS_ADDR;
141 }
142
143 /* 异常上下文记录 */
144 g_excInfo.context = excBufAddr;
145 }
146
OsReboot(void)147 static OS_SEC_L4_TEXT void OsReboot(void)
148 {
149 while (1) {
150 /* Wait for HWWDG to reboot board. */
151 }
152 }
153 /*
154 * 描述:EXC模块的处理分发函数
155 */
OsExcHandleEntryM4(U32 excType,U32 faultAddr,struct ExcContext * excBufAddr)156 OS_SEC_L4_TEXT void OsExcHandleEntryM4(U32 excType, U32 faultAddr, struct ExcContext *excBufAddr)
157 {
158 CUR_NEST_COUNT++;
159 g_intCount++;
160 UNI_FLAG |= OS_FLG_HWI_ACTIVE;
161
162 OsExcRecordInfo(excType, faultAddr, excBufAddr);
163
164 if (OS_EXC_MAX_NEST_DEPTH < CUR_NEST_COUNT || g_excSaveFlag == TRUE) {
165 OsReboot();
166 }
167
168 if (memset_s(OS_EXC_INFO_ADDR, EXC_RECORD_SIZE, 0, EXC_RECORD_SIZE) != EOK) {
169 OS_GOTO_SYS_ERROR1();
170 }
171
172 /* 没有初始化完成分配异常信息记录空间 */
173 OsExcSaveInfo(&g_excInfo);
174 g_excSaveFlag = TRUE;
175
176 if (g_excModInfo.excepHook != NULL) {
177 (void)g_excModInfo.excepHook(OS_EXC_INFO_ADDR);
178 }
179 OsReboot();
180 }
181