154568cb3Sopenharmony_ci/*
254568cb3Sopenharmony_ci * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved.
354568cb3Sopenharmony_ci *
454568cb3Sopenharmony_ci * UniProton is licensed under Mulan PSL v2.
554568cb3Sopenharmony_ci * You can use this software according to the terms and conditions of the Mulan PSL v2.
654568cb3Sopenharmony_ci * You may obtain a copy of Mulan PSL v2 at:
754568cb3Sopenharmony_ci *          http://license.coscl.org.cn/MulanPSL2
854568cb3Sopenharmony_ci * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
954568cb3Sopenharmony_ci * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
1054568cb3Sopenharmony_ci * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
1154568cb3Sopenharmony_ci * See the Mulan PSL v2 for more details.
1254568cb3Sopenharmony_ci * Create: 2009-12-22
1354568cb3Sopenharmony_ci * Description: 异常模块的C文件。
1454568cb3Sopenharmony_ci */
1554568cb3Sopenharmony_ci#include "prt_clk.h"
1654568cb3Sopenharmony_ci#include "prt_exc_internal.h"
1754568cb3Sopenharmony_ci#include "prt_sys_external.h"
1854568cb3Sopenharmony_ci#include "prt_task_external.h"
1954568cb3Sopenharmony_ci#include "prt_irq_external.h"
2054568cb3Sopenharmony_ci#include "prt_asm_cpu_external.h"
2154568cb3Sopenharmony_ci
2254568cb3Sopenharmony_ciOS_SEC_BSS bool g_excSaveFlag;
2354568cb3Sopenharmony_ciOS_SEC_BSS struct ExcRegInfo g_excInfo;
2454568cb3Sopenharmony_ci
2554568cb3Sopenharmony_ci// 异常时获取当前任务的信息
2654568cb3Sopenharmony_ciOS_SEC_BSS ExcTaskInfoFunc g_excTaskInfoGet;
2754568cb3Sopenharmony_ci
2854568cb3Sopenharmony_ciOS_SEC_L4_TEXT U32 OsExcConfigInit(void)
2954568cb3Sopenharmony_ci{
3054568cb3Sopenharmony_ci    return OS_OK;
3154568cb3Sopenharmony_ci}
3254568cb3Sopenharmony_ci
3354568cb3Sopenharmony_ci/*
3454568cb3Sopenharmony_ci * 描述:获取异常线程信息
3554568cb3Sopenharmony_ci */
3654568cb3Sopenharmony_cistatic OS_SEC_L4_TEXT void OsExcGetThreadInfo(struct ExcInfo *excInfo)
3754568cb3Sopenharmony_ci{
3854568cb3Sopenharmony_ci    struct TskInfo taskInfo;
3954568cb3Sopenharmony_ci    U32 threadId = INVALIDPID;
4054568cb3Sopenharmony_ci
4154568cb3Sopenharmony_ci    if (memset_s(&taskInfo, sizeof(struct TskInfo), 0, sizeof(struct TskInfo)) != EOK) {
4254568cb3Sopenharmony_ci        OS_GOTO_SYS_ERROR1();
4354568cb3Sopenharmony_ci    }
4454568cb3Sopenharmony_ci#if defined(OS_OPTION_TASK_INFO)
4554568cb3Sopenharmony_ci    /* 任务存在时 */
4654568cb3Sopenharmony_ci    if ((OsTskMaxNumGet() > 0) && ((UNI_FLAG & OS_FLG_BGD_ACTIVE) != 0)) {
4754568cb3Sopenharmony_ci        /* 记录当前任务ID号 */
4854568cb3Sopenharmony_ci        if (PRT_TaskSelf(&threadId) == OS_OK) {
4954568cb3Sopenharmony_ci            /* 获取当前任务信息 */
5054568cb3Sopenharmony_ci            OS_ERR_RECORD(PRT_TaskGetInfo(threadId, &taskInfo));
5154568cb3Sopenharmony_ci        }
5254568cb3Sopenharmony_ci    }
5354568cb3Sopenharmony_ci#endif
5454568cb3Sopenharmony_ci    /* 记录发生异常时的线程ID,发生在任务中,此项具有意义,其他线程中,此项无意义 */
5554568cb3Sopenharmony_ci    excInfo->threadId = INVALIDPID;
5654568cb3Sopenharmony_ci
5754568cb3Sopenharmony_ci    /* 设置异常前的线程类型 */
5854568cb3Sopenharmony_ci    if (g_intCount > CUR_NEST_COUNT) {
5954568cb3Sopenharmony_ci        excInfo->threadType = EXC_IN_HWI;
6054568cb3Sopenharmony_ci    } else if ((UNI_FLAG & OS_FLG_TICK_ACTIVE) != 0) {
6154568cb3Sopenharmony_ci        excInfo->threadType = EXC_IN_TICK;
6254568cb3Sopenharmony_ci    } else if ((UNI_FLAG & OS_FLG_SYS_ACTIVE) != 0) {
6354568cb3Sopenharmony_ci        excInfo->threadType = EXC_IN_SYS;
6454568cb3Sopenharmony_ci    } else if ((UNI_FLAG & OS_FLG_BGD_ACTIVE) != 0) {
6554568cb3Sopenharmony_ci        excInfo->threadType = EXC_IN_TASK;
6654568cb3Sopenharmony_ci        if (OsTskMaxNumGet() > 0) { /* 任务存在时 */
6754568cb3Sopenharmony_ci            excInfo->threadId = threadId;
6854568cb3Sopenharmony_ci        }
6954568cb3Sopenharmony_ci    } else {  // OS_FLG_BGD_ACTIVE没有置位,代表此时还在系统进程中,没有进入业务线程。
7054568cb3Sopenharmony_ci        excInfo->threadType = EXC_IN_SYS_BOOT;
7154568cb3Sopenharmony_ci    }
7254568cb3Sopenharmony_ci
7354568cb3Sopenharmony_ci    /* MSP主堆栈 */
7454568cb3Sopenharmony_ci    if ((excInfo->sp >= OsGetSysStackTop()) && (excInfo->sp <= OsGetSysStackBottom())) {
7554568cb3Sopenharmony_ci        excInfo->stackBottom = OsGetSysStackBottom();
7654568cb3Sopenharmony_ci    } else { /* PSP进程堆栈 */
7754568cb3Sopenharmony_ci        excInfo->stackBottom = TRUNCATE((taskInfo.topOfStack + taskInfo.stackSize), OS_TSK_STACK_ADDR_ALIGN);
7854568cb3Sopenharmony_ci    }
7954568cb3Sopenharmony_ci}
8054568cb3Sopenharmony_ci
8154568cb3Sopenharmony_ci/*
8254568cb3Sopenharmony_ci * 描述:记录异常信息
8354568cb3Sopenharmony_ci */
8454568cb3Sopenharmony_ciOS_SEC_L4_TEXT void OsExcSaveInfo(struct ExcRegInfo *regs)
8554568cb3Sopenharmony_ci{
8654568cb3Sopenharmony_ci    struct ExcInfo *excInfo = OS_EXC_INFO_ADDR;
8754568cb3Sopenharmony_ci    char *version = NULL;
8854568cb3Sopenharmony_ci    U64 count;
8954568cb3Sopenharmony_ci
9054568cb3Sopenharmony_ci    /* 记录os版本号 */
9154568cb3Sopenharmony_ci    version = PRT_SysGetOsVersion();
9254568cb3Sopenharmony_ci    if (version != NULL) {
9354568cb3Sopenharmony_ci        if (strncpy_s(excInfo->osVer, sizeof(excInfo->osVer),
9454568cb3Sopenharmony_ci                      version, sizeof(excInfo->osVer) - 1) != EOK) {
9554568cb3Sopenharmony_ci            OS_GOTO_SYS_ERROR1();
9654568cb3Sopenharmony_ci        }
9754568cb3Sopenharmony_ci    }
9854568cb3Sopenharmony_ci    excInfo->osVer[OS_SYS_OS_VER_LEN - 1] = '\0';
9954568cb3Sopenharmony_ci
10054568cb3Sopenharmony_ci    /* 记录异常类型 */
10154568cb3Sopenharmony_ci    excInfo->excCause = regs->excType;
10254568cb3Sopenharmony_ci    /* 记录CPU ID */
10354568cb3Sopenharmony_ci    excInfo->coreId = OsGetHwThreadId();
10454568cb3Sopenharmony_ci
10554568cb3Sopenharmony_ci    /* 设置字节序 */
10654568cb3Sopenharmony_ci    excInfo->byteOrder = OS_BYTE_ORDER;
10754568cb3Sopenharmony_ci
10854568cb3Sopenharmony_ci    /* 记录CPU类型 */
10954568cb3Sopenharmony_ci    excInfo->cpuType = OsGetCpuType();
11054568cb3Sopenharmony_ci
11154568cb3Sopenharmony_ci    /* 记录CPU TICK值 */
11254568cb3Sopenharmony_ci    count = PRT_ClkGetCycleCount64();
11354568cb3Sopenharmony_ci    excInfo->cpuTick = count;
11454568cb3Sopenharmony_ci
11554568cb3Sopenharmony_ci    /* 记录当前异常嵌套次数 */
11654568cb3Sopenharmony_ci    excInfo->nestCnt = CUR_NEST_COUNT;
11754568cb3Sopenharmony_ci
11854568cb3Sopenharmony_ci    /* 记录寄存器信息 */
11954568cb3Sopenharmony_ci    excInfo->regInfo = (*regs);
12054568cb3Sopenharmony_ci
12154568cb3Sopenharmony_ci    /* 记录异常前栈指针 */
12254568cb3Sopenharmony_ci    excInfo->sp = (regs->context)->sp;
12354568cb3Sopenharmony_ci
12454568cb3Sopenharmony_ci    /* 记录异常前栈底 */
12554568cb3Sopenharmony_ci    excInfo->stackBottom = INVALIDSTACKBOTTOM;
12654568cb3Sopenharmony_ci
12754568cb3Sopenharmony_ci    OsExcGetThreadInfo(excInfo);
12854568cb3Sopenharmony_ci}
12954568cb3Sopenharmony_ci
13054568cb3Sopenharmony_cistatic OS_SEC_L4_TEXT void OsExcRecordInfo(U32 excType, U32 faultAddr, struct ExcContext *excBufAddr)
13154568cb3Sopenharmony_ci{
13254568cb3Sopenharmony_ci    // 若为1时faultAddr有效
13354568cb3Sopenharmony_ci    U16 tmpFlag = (U16)OS_GET_32BIT_HIGH_16BIT(excType);
13454568cb3Sopenharmony_ci
13554568cb3Sopenharmony_ci    g_excInfo.excType = excType;
13654568cb3Sopenharmony_ci    /* 此掩码在CDA解析时需要判断 */
13754568cb3Sopenharmony_ci    if (((U32)tmpFlag & OS_EXC_FLAG_FAULTADDR_VALID) != 0) {
13854568cb3Sopenharmony_ci        g_excInfo.faultAddr = faultAddr;
13954568cb3Sopenharmony_ci    } else {
14054568cb3Sopenharmony_ci        g_excInfo.faultAddr = OS_EXC_IMPRECISE_ACCESS_ADDR;
14154568cb3Sopenharmony_ci    }
14254568cb3Sopenharmony_ci
14354568cb3Sopenharmony_ci    /* 异常上下文记录 */
14454568cb3Sopenharmony_ci    g_excInfo.context = excBufAddr;
14554568cb3Sopenharmony_ci}
14654568cb3Sopenharmony_ci
14754568cb3Sopenharmony_cistatic OS_SEC_L4_TEXT void OsReboot(void)
14854568cb3Sopenharmony_ci{
14954568cb3Sopenharmony_ci    while (1) {
15054568cb3Sopenharmony_ci        /* Wait for HWWDG to reboot board. */
15154568cb3Sopenharmony_ci    }
15254568cb3Sopenharmony_ci}
15354568cb3Sopenharmony_ci/*
15454568cb3Sopenharmony_ci * 描述:EXC模块的处理分发函数
15554568cb3Sopenharmony_ci */
15654568cb3Sopenharmony_ciOS_SEC_L4_TEXT void OsExcHandleEntryM4(U32 excType, U32 faultAddr, struct ExcContext *excBufAddr)
15754568cb3Sopenharmony_ci{
15854568cb3Sopenharmony_ci    CUR_NEST_COUNT++;
15954568cb3Sopenharmony_ci    g_intCount++;
16054568cb3Sopenharmony_ci    UNI_FLAG |= OS_FLG_HWI_ACTIVE;
16154568cb3Sopenharmony_ci
16254568cb3Sopenharmony_ci    OsExcRecordInfo(excType, faultAddr, excBufAddr);
16354568cb3Sopenharmony_ci
16454568cb3Sopenharmony_ci    if (OS_EXC_MAX_NEST_DEPTH < CUR_NEST_COUNT || g_excSaveFlag == TRUE) {
16554568cb3Sopenharmony_ci        OsReboot();
16654568cb3Sopenharmony_ci    }
16754568cb3Sopenharmony_ci
16854568cb3Sopenharmony_ci    if (memset_s(OS_EXC_INFO_ADDR, EXC_RECORD_SIZE, 0, EXC_RECORD_SIZE) != EOK) {
16954568cb3Sopenharmony_ci        OS_GOTO_SYS_ERROR1();
17054568cb3Sopenharmony_ci    }
17154568cb3Sopenharmony_ci
17254568cb3Sopenharmony_ci    /* 没有初始化完成分配异常信息记录空间 */
17354568cb3Sopenharmony_ci    OsExcSaveInfo(&g_excInfo);
17454568cb3Sopenharmony_ci    g_excSaveFlag = TRUE;
17554568cb3Sopenharmony_ci
17654568cb3Sopenharmony_ci    if (g_excModInfo.excepHook != NULL) {
17754568cb3Sopenharmony_ci        (void)g_excModInfo.excepHook(OS_EXC_INFO_ADDR);
17854568cb3Sopenharmony_ci    }
17954568cb3Sopenharmony_ci    OsReboot();
18054568cb3Sopenharmony_ci}
181