/* ----------------------------------------------------------------------------
 * Copyright (c) Huawei Technologies Co., Ltd. 2013-2020. All rights reserved.
 * Description: Runstop
 * Author: Huawei LiteOS Team
 * Create: 2013-01-01
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright notice, this list of
 * conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
 * of conditions and the following disclaimer in the documentation and/or other materials
 * provided with the distribution.
 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
 * to endorse or promote products derived from this software without specific prior written
 * permission.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * --------------------------------------------------------------------------- */

#include "los_runstop_pri.h"
#include "los_task_pri.h"
#include "los_event_pri.h"
#include "los_tick_pri.h"
#ifndef LOSCFG_PLATFORM_NO_UART
#include "uart.h"
#endif
#ifdef LOSCFG_KERNEL_CPUP
#include "los_cpup_pri.h"
#endif

#include "arch/cpu.h"

#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */

#define WAKEUP_FROM_SUSPEND 0x01
#define FLASH_IMG_SUCCESS   0x02

/* If core is ready for imaging */
LITE_OS_SEC_DATA_MINOR STATIC UINT32 g_sysDoneFlag[LOSCFG_KERNEL_CORE_NUM] = {
    [0 ... (LOSCFG_KERNEL_CORE_NUM - 1)] = OS_NO_STORE_SYSTEM
}; /*标记数组状态，用来表示系统是否加载完成*/

/* Start position of flash to write image */
LITE_OS_SEC_DATA_MINOR STATIC UINTPTR g_flashImgAddr;
/*flash图像地址和大小，用于存储flash相关信息。*/

/* Start position of heap memory after carry the image from flash to memory */
LITE_OS_SEC_DATA_MINOR STATIC const VOID *g_heapMemStart = NULL;
/*初始化图像地址*/

/* Size of heap memory in image */
LITE_OS_SEC_DATA_MINOR STATIC size_t g_heapMemSize = 0;
/*初始化定义图像大小*/

#ifdef LOSCFG_EXC_INTERACTION
/* Start position of exc interaction heap memory after carry the image from flash to memory */
LITE_OS_SEC_DATA_MINOR STATIC const VOID *g_excInteractionMemStart = NULL;
/*在存储器映像从闪存复制到内存之后异常交互堆的起始位置变量*/

/* Size of exc interaction heap memory in image */
LITE_OS_SEC_DATA_MINOR STATIC size_t g_excInteractionMemSize = 0;
/*异常交互堆内存在储存器映像中的大小*/
#endif
/* Size of wow image */
LITE_OS_SEC_DATA_MINOR STATIC size_t g_wowImgSize = 0;

LITE_OS_SEC_DATA_MINOR STATIC RUNSTOP_PARAM_S g_runstopParam;
LITE_OS_SEC_DATA_MINOR STATIC EVENT_CB_S g_suspendResumeEvent;
LITE_OS_SEC_DATA_MINOR STATIC EVENT_CB_S g_writeFlashEvent;

typedef struct {
    UINTPTR memStart;  /*内存起始地址*/
    UINTPTR flashStart;  /*闪存起始地址*/
    size_t memSize;  /*存储空间大小*/
} FlashWriteParam;

BOOL IsImageResume(VOID)
{
    return (g_resumeFromImg != LOS_COLD_RESET);
}
/*判断系统是否从存储器映像中恢复的，功能是当系统异常启动或者需要重启的时候就会从内存将其数据保存到闪存中
此函数就是判断系统是否是从存储器映像回复的，从而确定是否需要对系统状态进行恢复*/

LITE_OS_SEC_TEXT_MINOR STATIC VOID OsDoWriteWow2Flash(FLASH_WRITE_FUNC flashWriteFunc,
                                                      const FlashWriteParam *wowSection,
                                                      const FlashWriteParam *excHeapSection,
                                                      const FlashWriteParam *heapMemSection)
{
    if ((wowSection->memSize != 0) &&
        (flashWriteFunc((VOID *)wowSection->memStart, wowSection->flashStart, wowSection->memSize) != 0)) {
        PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__);
        return;
    }

    if ((excHeapSection->memSize != 0) &&
        (flashWriteFunc((VOID *)excHeapSection->memStart, excHeapSection->flashStart, excHeapSection->memSize)) != 0) {
        PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__);
        return;
    }

    if ((heapMemSection->memSize != 0) &&
        (flashWriteFunc((VOID *)heapMemSection->memStart, heapMemSection->flashStart, heapMemSection->memSize) != 0)) {
        PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__);
        return;
    }
}
/*首先检查内存中的大小是否为0
若不为0则将wowsection、excheapsection、heapmemsection中的静态数据和代码存储在系统启动的时候将其从闪存加入到内存中*/
LITE_OS_SEC_TEXT_MINOR VOID OsWriteWow2Flash(VOID) /*根据指定的内存区域，在闪存中写入相应的数据，完成写入操作*/
{
    FlashWriteParam wowSection;
    FlashWriteParam excHeapSection = {0};
    FlashWriteParam heapMemSection;     /*这是三种闪存内部独立的堆专用的内存区域对应的闪存写入参数*/
    size_t eraseAlignSize;   /*表示闪存擦除时的对齐大小*/
    size_t writeAlignSize;   /*闪存写入时的对齐大小*/
    FLASH_WRITE_FUNC flashWriteFunc = g_runstopParam.pfFlashWriteFunc;

    eraseAlignSize = g_runstopParam.uwFlashEraseAlignSize; /*用来指定擦除和写入时的对齐大小，通常设置为扇区大小的整数倍*/
    writeAlignSize = g_runstopParam.uwFlashWriteAlignSize; /*为了避免出现擦除或写入不规则数据的情况，
    需要将操作的地址向下或向上舍入到扇区大小的整数倍
    从而避免因为不规则的操作而导致数据的错误或损坏。*/
    writeAlignSize = (writeAlignSize >= eraseAlignSize) ? writeAlignSize : eraseAlignSize;
    if (flashWriteFunc == NULL) {
        PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__);
        return;
    }

    wowSection.memStart = (UINTPTR)&__ram_vectors_vma;/*初始化wowSection，为内存中起始地址*/
    wowSection.flashStart = g_flashImgAddr;  /*为闪存中起始地址*/
    wowSection.memSize = ((UINTPTR)&__wow_end) - ((UINTPTR)&__ram_vectors_vma);
    wowSection.memSize = (wowSection.memSize + writeAlignSize - 1) & ~(writeAlignSize - 1);
                /*计算了wowSection大小，通过与运算保证每次写入的数据都是整个扇区的倍数*/
#ifdef LOSCFG_EXC_INTERACTION
    excHeapSection.memStart = (UINTPTR)m_aucSysMem0;
    excHeapSection.flashStart = g_flashImgAddr + wowSection.memSize;
    excHeapSection.memSize = LOS_MemLastUsedGet(m_aucSysMem0) - (UINTPTR)m_aucSysMem0;
    excHeapSection.memSize = (excHeapSection.memSize + writeAlignSize - 1) & ~(writeAlignSize - 1);

    g_excInteractionMemStart = (VOID *)(((UINTPTR)&__ram_vectors_vma) + wowSection.memSize);
    g_excInteractionMemSize = excHeapSection.memSize;
#endif

    heapMemSection.memStart = (UINTPTR)m_aucSysMem1;
    heapMemSection.flashStart = g_flashImgAddr + wowSection.memSize + excHeapSection.memSize;
    heapMemSection.memSize = LOS_MemLastUsedGet(m_aucSysMem1) - (UINTPTR)m_aucSysMem1;
    heapMemSection.memSize = (heapMemSection.memSize + writeAlignSize - 1) & ~(writeAlignSize - 1);

    g_heapMemSize = heapMemSection.memSize;
    g_heapMemStart = (VOID *)(((UINTPTR)&__ram_vectors_vma) + wowSection.memSize + excHeapSection.memSize);
    g_wowImgSize = wowSection.memSize + heapMemSection.memSize + excHeapSection.memSize;

    OsDoWriteWow2Flash(flashWriteFunc, &wowSection, &excHeapSection, &heapMemSection);
    /*将变量传输给函数，由其实现相应的写入操作*/
}

LITE_OS_SEC_TEXT_MINOR VOID OsSystemSuspend(VOID) /*实现系统的挂起操作*/
{
    UINT32 cpuid; /*获取当前CPU的ID*/

    (VOID)LOS_IntLock(); 
    LOS_TaskLock();
    cpuid = ArchCurrCpuid();
    /*禁止中断并锁定任务调度器，确保在执行挂起操作期间不会被打断*/
    g_sysDoneFlag[cpuid] = OS_NO_STORE_SYSTEM; /*将当前CPU的系统挂起标志设置为不需要保存系统状态*/
    g_saveTsk[cpuid] = OsCurrTaskGet(); /*保存当前任务指针到savetask变量中*/

    OsSRSaveRegister(); /*保存当前CPU的寄存器状态，以便在恢复系统时能够正确恢复到挂起前的状态*/
    /* If 1 core, only to save registers */
    if (cpuid != 0) {   /*若此CPU部位0号内核*/
        if (g_otherCoreResume != 0) {   /*说明其他多核核心需要恢复运行*/
            HalIrqInitPercpu();
            OsTickStart();
            LOS_TaskUnlock();
            (VOID)LOS_IntUnLock();
            return;            
        }
        g_sysDoneFlag[cpuid - 1] = OS_STORE_SYSTEM; /*需要初始化中断并启动系统时钟，并最终解锁任务调度器并恢复中断*/
        while (1) {}
    }

    if (g_resumeFromImg) {  /*如果是 0 号 CPU，且系统需要从镜像中恢复（g_resumeFromImg 为真）*/
        OsWriteWow2Flash();
        LOS_TaskUnlock();
        (VOID)LOS_IntUnLock();
        (VOID)LOS_EventWrite(&g_suspendResumeEvent, FLASH_IMG_SUCCESS);
        /*调用 OsWriteWow2Flash 函数将数据写入闪存，并发送 FLASH_IMG_SUCCESS 事件信号，表示成功从镜像中恢复*/
    } else { /*不需要从镜像中恢复*/
        OsTickStart();
        LOS_TaskUnlock();
        (VOID)LOS_IntUnLock();

        if (g_runstopParam.pfIdleWakeupCallback != NULL) {
            g_runstopParam.pfIdleWakeupCallback();
        }
        (VOID)LOS_EventWrite(&g_suspendResumeEvent, WAKEUP_FROM_SUSPEND);
    }
    /*启动系统时钟，解锁任务调度器和中断，并根据是否设置了空闲唤醒回调函数来执行相应的操作，
    最后发送 WAKEUP_FROM_SUSPEND 事件信号，表示从挂起状态唤醒*/
}

LITE_OS_SEC_TEXT VOID OsWriteToFlashTask(VOID)
/*初始化了一个事件对象 g_writeFlashEvent
并且在循环中调用 LOS_EventRead 函数等待事件的发生，
并以 OR 模式和清除模式等待事件的标志位为 0x01。
一旦事件发生，它调用 OsSystemSuspend 函数将系统挂起。*/
{
    (VOID)LOS_EventInit(&g_writeFlashEvent);

    while (1) {
        (VOID)LOS_EventRead(&g_writeFlashEvent, 0x01, LOS_WAITMODE_OR | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER);
        OsSystemSuspend();
    }
}

LITE_OS_SEC_TEXT VOID OsStoreSystemInfoBeforeSuspend(VOID)
/*根据当前 CPU 的 ID 判断是否需要挂起系统。
如果当前 CPU 不是 0 号 CPU，直接调用 OsSystemSuspend 函数挂起系统。
如果是 0 号 CPU，则调用 LOS_EventWrite 函数向事件对象 g_writeFlashEvent 发送一个事件，
唤醒 OsWriteToFlashTask 任务来执行挂起操作。*/
{
    UINT32 cpuid = ArchCurrCpuid();
    if (cpuid != 0) {
        OsSystemSuspend();
    } else {
        (VOID)LOS_EventWrite(&g_writeFlashEvent, 0x01);
    }
    return;
}

LITE_OS_SEC_TEXT_MINOR VOID OsSystemWakeup(VOID)
/*是系统从挂起状态唤醒后的处理函数。*/


{
    UINT32 cpuid;
    errno_t err;

    if (!g_resumeFromImg) {
        return;
    }
/*进行一些内存数据的复制操作，然后设置当前 CPU 的任务指针，*/
#ifdef LOSCFG_EXC_INTERACTION
    err = memmove_s(m_aucSysMem0, g_excInteractMemSize, g_excInteractionMemStart, g_excInteractionMemSize);
    if (err != EOK) {
        PRINT_RELEASE("%s, %d failed, errno = %d\n", __FUNCTION__, __LINE__, err);
        return;
    }
#endif
    err = memmove_s(m_aucSysMem1, OS_SYS_MEM_SIZE, g_heapMemStart, g_heapMemSize);
    if (err != EOK) {
        PRINT_RELEASE("%s, %d failed, errno = %d\n", __FUNCTION__, __LINE__, err);
        return;
    }
    dsb();
    /* Set the task of the current CPU */
    cpuid = ArchCurrCpuid();
    OsCurrTaskSet(g_saveTsk[cpuid]);

/*设置系统计数器频率。接着，它重置内存池的末尾节点，清零 BSS 区域的数据，重新初始化中断*/
    /* Set system counter freq */
    HalClockFreqWrite(OS_SYS_CLOCK);
    dsb();
#ifdef LOSCFG_EXC_INTERACTION
    if (LOS_MemPoolSizeGet(m_aucSysMem0) != g_excInteractionMemSize) {
        OsMemResetEndNode(m_aucSysMem0, (UINTPTR)m_aucSysMem0 + g_excInteractionMemSize);
    }
#endif
    if (LOS_MemPoolSizeGet(m_aucSysMem1) != g_heapMemSize) {
        OsMemResetEndNode(m_aucSysMem1, (UINTPTR)m_aucSysMem1 + g_heapMemSize);
    }

    (VOID)memset_s((VOID *)&__bss_start, (((UINTPTR)&__bss_end) - ((UINTPTR)&__bss_start)), 0,
        (((UINTPTR)&__bss_end) - ((UINTPTR)&__bss_start)));

    ArchIrqInit();

#ifndef LOSCFG_PLATFORM_NO_UART
    uart_early_init();
#endif

    g_resumeFromImg = LOS_COLD_RESET;
    g_otherCoreResume = 1;

#ifdef LOSCFG_KERNEL_CPUP
    OsSetCpuCycle(0);
#endif
/*并调用 OsSRRestoreRegister 函数恢复寄存器状态*/
#if (LOSCFG_KERNEL_SMP == YES)
    release_secondary_cores();
#endif
    OsSRRestoreRegister();
}

LITE_OS_SEC_TEXT_MINOR UINT32 OsWaitImagingDone(UINTPTR wowFlashAddr, size_t *wowImgSize)
{
    UINT32 ret;

    g_flashImgAddr = wowFlashAddr; /*烧录的flash地址*/
    (VOID)LOS_EventInit(&g_suspendResumeEvent); /*指向用于存储烧录镜像大小的变量的指针*/

    // 这个标志将被存储到闪存中，当 CPU 重新启动时，它将影响唤醒流程。
    g_resumeFromImg = LOS_RUN_STOP_RESET;
    // 这个标志会影响之后的挂起过程，并且在 CPU 重新启动时根据 'g_resumeFromImg' 的值进行重置
    g_otherCoreResume = 0;
    g_sysDoneFlag[LOSCFG_KERNEL_CORE_NUM - 1] = OS_STORE_SYSTEM; /*表示系统状态需要被保存*/

    ret = LOS_EventRead(&g_suspendResumeEvent, 0xFF, LOS_WAITMODE_OR | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER);
    /*等待事件发生*/
    if (wowImgSize != NULL) {
        *wowImgSize = g_wowImgSize;
    }/*保证能够在烧录完成之后正确的保存和恢复状态*/

    return ret;
}

LITE_OS_SEC_TEXT_MINOR VOID OsCarryLeftScatter(VOID) /*将位于RAM的数据从指定位置复制到Flash存储器中*/
{
    size_t size;
    UINTPTR memAddr;
    size_t wowSize;/*等待复制数据的大小*/
    size_t readAlignSize;/*读取对齐大小*/
    size_t eraseAlignSize;/*擦除对齐大小*/
    size_t writeAlignSize;/*写入对齐大小*/
    /*读取所有参数的初始状态*/
    UINTPTR imageFlashAddr;
    FLASH_READ_FUNC flashReadFunc = g_runstopParam.pfFlashReadFunc;

    imageFlashAddr = g_runstopParam.uwImageFlashAddr;
    readAlignSize = g_runstopParam.uwFlashReadAlignSize;
    eraseAlignSize = g_runstopParam.uwFlashEraseAlignSize;
    writeAlignSize = g_runstopParam.uwFlashWriteAlignSize;
    writeAlignSize = (writeAlignSize >= eraseAlignSize) ? writeAlignSize : eraseAlignSize;
    /*计算wowsize的大小，根据对齐大小调整值*/
    wowSize = ((UINTPTR)&__wow_end) - ((UINTPTR)&__ram_vectors_vma);
    wowSize = (wowSize + writeAlignSize - 1) & ~(writeAlignSize - 1);
    imageFlashAddr += wowSize;
    /*检查memaddr是否超出了BSS段的起始地址*/
    memAddr = ((UINTPTR)&__ram_vectors_vma) + wowSize;
    if (memAddr >= ((UINTPTR)&__bss_start)) {
        return;
    }
    /*计算了要复制的数据大小，在磁盘中根据对齐大小调整size*/
    size = ((UINTPTR)&__int_stack_start) - memAddr;
    size = (size + readAlignSize - 1) & ~(readAlignSize - 1);
    /*将RAM中的数据从memaddr复制到flash存储器的imageflashaddr，进行缓存和同步操作*/
    if ((flashReadFunc != NULL) && (flashReadFunc((VOID *)memAddr, imageFlashAddr, size) != 0)) {
        PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__);
    }
    dsb();
    flush_icache();
    flush_dcache(memAddr, memAddr + size);
}

LITE_OS_SEC_TEXT_MINOR VOID OsRunstopParamInit(const RUNSTOP_PARAM_S *runstopParam)
/*初始化运行暂停功能所需的参数，保存在全局变量g_中，以便告诉计算机目前的系统转台
包含了运行暂停功能所需的各个回调函数和对齐大小等参数*/
{
    g_runstopParam.pfIdleWakeupCallback = runstopParam->pfIdleWakeupCallback;
    g_runstopParam.pfWakeupCallback = runstopParam->pfWakeupCallback;
    g_runstopParam.pfImageDoneCallback = runstopParam->pfImageDoneCallback;
    g_runstopParam.pfFlashReadFunc = runstopParam->pfFlashReadFunc;
    g_runstopParam.pfFlashWriteFunc = runstopParam->pfFlashWriteFunc;
    g_runstopParam.uwFlashReadAlignSize = runstopParam->uwFlashReadAlignSize;
    g_runstopParam.uwFlashEraseAlignSize = runstopParam->uwFlashEraseAlignSize;
    g_runstopParam.uwFlashWriteAlignSize = runstopParam->uwFlashWriteAlignSize;
    g_runstopParam.uwWowFlashAddr = runstopParam->uwWowFlashAddr;
    g_runstopParam.uwImageFlashAddr = runstopParam->uwImageFlashAddr;
}

LITE_OS_SEC_TEXT_MINOR VOID LOS_MakeImage(RUNSTOP_PARAM_S *runstopParam)
/*用于除法运行暂停功能的操作，并根据返回值进行相应处理*/
{
    UINT32 ret;
    size_t imgSize;
    /*检查是否需要暂停*/
    if (runstopParam == NULL) {
        return;
    }
    /*调用函数，将传入的runstopparam转换为全局变量*/
    OsRunstopParamInit(runstopParam);

    ret = OsWaitImagingDone(g_runstopParam.uwWowFlashAddr, &imgSize);
    /*用于等待图像转移完成，范围相应的状态码ret和图像大小imgsize*/
    if (ret == WAKEUP_FROM_SUSPEND) { /*从暂停状态唤醒，并查看系统是否需要空闲唤醒回调*/
        if (g_runstopParam.pfWakeupCallback != NULL) {
            g_runstopParam.pfWakeupCallback();
        }
        OsCarryLeftScatter(); /*将RAM中的数据复制到Flash存储器*/
        PRINT_INFO("Resume ok!\n");
    } else if (ret == FLASH_IMG_SUCCESS) { /*闪存图像成功*/
        if (g_runstopParam.pfImageDoneCallback != NULL) {
            g_runstopParam.pfImageDoneCallback();
        }

        PRINT_INFO("Flash ok! Image length 0x%x\n", imgSize);/*图像转移成功，并打印图像大小*/
    }
}

LITE_OS_SEC_TEXT_MINOR UINT32 OsWowWriteFlashTaskCreate(VOID)
{
    UINT32 ret;
    UINT32 writeFlashTaskId;
    TSK_INIT_PARAM_S taskInitParam;
    /*首先对任务初始化参数进行了清零操作*/
    (VOID)memset_s((VOID *)(&taskInitParam), sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S));
    /*设置了任务入口函数，并且制定了任务的堆栈大小，任务名和优先级*/
    taskInitParam.pfnTaskEntry = (TSK_ENTRY_FUNC)OsWriteToFlashTask;
    taskInitParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
    taskInitParam.pcName = "WowWriteFlashTask";
    taskInitParam.usTaskPrio = OS_TASK_PRIORITY_LOWEST - 1;
#ifdef LOSCFG_KERNEL_SMP
    taskInitParam.usCpuAffiMask = CPUID_TO_AFFI_MASK(0);
#endif
    /*创建任务，返回结果*/
    ret = LOS_TaskCreate(&writeFlashTaskId, &taskInitParam);
    return ret;
}

LITE_OS_SEC_TEXT_MINOR size_t OsWowImageSizeGet(VOID)
/*获取wow图像的大小，返回全局变量*/
{
    return g_wowImgSize;
}

LITE_OS_SEC_TEXT_MINOR UINT32 OsWowSysDoneFlagGet(VOID)
/*获取wow系统完成的标志*/
{
    UINT32 cpuid = ArchCurrCpuid();
    return g_sysDoneFlag[cpuid];
}

LITE_OS_SEC_TEXT_MINOR VOID OsWowOtherCoreResume(UINT32 cpuid)
/*唤醒其他的核心*/
{
    if (g_otherCoreResume == 1) { /*全局变量的值为1则表示需要唤醒其他核心*/
        OsCurrTaskSet(g_saveTsk[cpuid]);
        OsSRRestoreRegister();
    }
    return;
}

#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
