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