From 99c01f46b7339f93a2aff7dfe342eabc04abc235 Mon Sep 17 00:00:00 2001 From: cailun <2505225681@qq.com> Date: Fri, 3 Nov 2023 00:31:07 +0800 Subject: [PATCH 01/26] doc --- ...teOS阅读报告.docx => 蔡伦_LiteOS阅读泛读报告.docx} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename doc/{蔡伦_LiteOS阅读报告.docx => 蔡伦_LiteOS阅读泛读报告.docx} (100%) diff --git a/doc/蔡伦_LiteOS阅读报告.docx b/doc/蔡伦_LiteOS阅读泛读报告.docx similarity index 100% rename from doc/蔡伦_LiteOS阅读报告.docx rename to doc/蔡伦_LiteOS阅读泛读报告.docx From 6412ea5ff6cabc6ca3facde053c7ca031b65fc03 Mon Sep 17 00:00:00 2001 From: he <1429721469@qq.com> Date: Fri, 3 Nov 2023 00:43:59 +0800 Subject: [PATCH 02/26] hjc --- hjc/hjc.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 hjc/hjc.txt diff --git a/hjc/hjc.txt b/hjc/hjc.txt new file mode 100644 index 0000000..e69de29 From 3e0fcb461917fbbc2b6b4860a1404e7164596133 Mon Sep 17 00:00:00 2001 From: faj <1900949849@qq.com> Date: Fri, 3 Nov 2023 20:37:13 +0800 Subject: [PATCH 03/26] fuaojia_branch --- fuaojia_branch.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 fuaojia_branch.txt diff --git a/fuaojia_branch.txt b/fuaojia_branch.txt new file mode 100644 index 0000000..e69de29 From a5ed7a0caafd1f6e1e2a7a1caf1e3b1fd03eaf54 Mon Sep 17 00:00:00 2001 From: tree <1913915946@qq.com> Date: Mon, 27 Nov 2023 19:54:03 +0800 Subject: [PATCH 04/26] 11.27 --- src/kernel/base/los_bitmap.c | 12 ++++--- src/kernel/base/los_err.c | 8 +++-- src/kernel/base/los_event.c | 34 ++++++++++--------- src/kernel/base/los_exc.c | 51 ++++++++++++++++------------- src/kernel/base/los_hwi.c | 61 +++++++++++++++++++++++------------ src/kernel/base/los_lockdep.c | 25 +++++++------- src/kernel/base/los_misc.c | 42 ++++++++++++------------ src/kernel/base/los_mp.c | 20 ++++++------ src/kernel/base/los_mux.c | 25 +++++++------- src/kernel/base/los_percpu.c | 2 +- src/kernel/base/los_printf.c | 14 ++++---- 11 files changed, 170 insertions(+), 124 deletions(-) diff --git a/src/kernel/base/los_bitmap.c b/src/kernel/base/los_bitmap.c index 84a056a..8ac0390 100644 --- a/src/kernel/base/los_bitmap.c +++ b/src/kernel/base/los_bitmap.c @@ -26,6 +26,10 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ +/*这是一个位图(bitmap)的实现,用于对位图进行设置、清除和获取最高/最低位的操作。 +该位图使用一个32位无符号整数(UINT32)来表示,每一位都代表一个标记 +函数通过位运算来实现对位图的操作,其中包括左移、按位与、按位或、按位取反等操作。*/ + #include "los_bitmap.h" #include "los_toolchain.h" @@ -36,7 +40,7 @@ extern "C" { #endif /* __cplusplus */ #define OS_BITMAP_MASK 0x1FU - +//LOS_BitmapSet:将指定位置的位设置为1 VOID LOS_BitmapSet(UINT32 *bitmap, UINT16 pos) { if (bitmap == NULL) { @@ -45,7 +49,7 @@ VOID LOS_BitmapSet(UINT32 *bitmap, UINT16 pos) *bitmap |= 1U << (pos & OS_BITMAP_MASK); } - +//LOS_BitmapClr:将指定位置的位清除为0 VOID LOS_BitmapClr(UINT32 *bitmap, UINT16 pos) { if (bitmap == NULL) { @@ -54,7 +58,7 @@ VOID LOS_BitmapClr(UINT32 *bitmap, UINT16 pos) *bitmap &= ~(1U << (pos & OS_BITMAP_MASK)); } - +//LOS_HighBitGet:获取位图中最高位(值为1的位置)的索引 UINT16 LOS_HighBitGet(UINT32 bitmap) { if (bitmap == 0) { @@ -63,7 +67,7 @@ UINT16 LOS_HighBitGet(UINT32 bitmap) return (OS_BITMAP_MASK - CLZ(bitmap)); } - +//LOS_LowBitGet:获取位图中最低位(值为1的位置)的索引 UINT16 LOS_LowBitGet(UINT32 bitmap) { if (bitmap == 0) { diff --git a/src/kernel/base/los_err.c b/src/kernel/base/los_err.c index 970015d..abcc40a 100644 --- a/src/kernel/base/los_err.c +++ b/src/kernel/base/los_err.c @@ -25,7 +25,8 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +/*这段代码是关于错误处理的相关功能,包括注册错误处理函数和执行错误处理的函数。 +通过以下接口,用户可以自定义错误处理函数,并在发生错误时进行相应的处理操作。这样可以增强系统的健壮性和容错性,更好地应对各种错误情况。*/ #include "los_err.h" #ifdef __cplusplus @@ -35,8 +36,9 @@ extern "C" { #endif /* __cplusplus */ /* Hook function for error handling. */ +//g_usrErrFunc:全局变量,用于保存用户注册的错误处理函数 LITE_OS_SEC_BSS LOS_ERRORHANDLE_FUNC g_usrErrFunc; - +//LOS_ErrHandle:用于执行错误处理的函数,当系统出现错误时会调用该函数来处理错误信息 LITE_OS_SEC_TEXT_INIT UINT32 LOS_ErrHandle(CHAR *fileName, UINT32 lineNo, UINT32 errorNo, UINT32 paraLen, VOID *para) { @@ -46,7 +48,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_ErrHandle(CHAR *fileName, UINT32 lineNo, UINT32 return LOS_OK; } - +//LOS_RegErrHandle:用于注册错误处理函数的接口,用户可以通过该函数注册自定义的错误处理函数 LITE_OS_SEC_TEXT_INIT VOID LOS_RegErrHandle(LOS_ERRORHANDLE_FUNC func) { g_usrErrFunc = func; diff --git a/src/kernel/base/los_event.c b/src/kernel/base/los_event.c index b2fe8cb..3caadc8 100644 --- a/src/kernel/base/los_event.c +++ b/src/kernel/base/los_event.c @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +/*这段代码是关于事件管理的实现,包括事件的初始化、读取、写入、清除等操作。*/ #include "los_event_pri.h" #include "los_task_pri.h" #include "los_spinlock.h" @@ -38,7 +38,7 @@ extern "C" { #endif #endif /* __cplusplus */ - +//LOS_EventInit()函数用于初始化事件控制块(eventCB),并将事件ID、事件列表等属性设置为初始值 LITE_OS_SEC_TEXT_INIT UINT32 LOS_EventInit(PEVENT_CB_S eventCB) { UINT32 intSave; @@ -55,7 +55,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_EventInit(PEVENT_CB_S eventCB) LOS_IntRestore(intSave); return LOS_OK; } - +//OsEventParamCheck()函数用于检查参数的有效性,包括事件掩码(eventMask)、模式(mode)等 LITE_OS_SEC_TEXT STATIC UINT32 OsEventParamCheck(const VOID *ptr, UINT32 eventMask, UINT32 mode) { if (ptr == NULL) { @@ -75,16 +75,17 @@ LITE_OS_SEC_TEXT STATIC UINT32 OsEventParamCheck(const VOID *ptr, UINT32 eventMa !(mode & (LOS_WAITMODE_OR | LOS_WAITMODE_AND))) { return LOS_ERRNO_EVENT_FLAGS_INVALID; } + //指针非空,事件掩码非0,事件掩码不包含LOS_ERRTYPE_ERROR标志位,模式合法 return LOS_OK; } - +//OsEventPoll()函数用于轮询事件,根据指定的事件掩码和模式判断是否满足条件 LITE_OS_SEC_TEXT STATIC UINT32 OsEventPoll(UINT32 *eventId, UINT32 eventMask, UINT32 mode) { UINT32 ret = 0; LOS_ASSERT(ArchIntLocked()); LOS_ASSERT(LOS_SpinHeld(&g_taskSpin)); - + if (mode & LOS_WAITMODE_OR) { if ((*eventId & eventMask) != 0) { ret = *eventId & eventMask; @@ -101,7 +102,7 @@ LITE_OS_SEC_TEXT STATIC UINT32 OsEventPoll(UINT32 *eventId, UINT32 eventMask, UI return ret; } - +//OsEventReadCheck()函数用于检查事件读取操作的参数有效性,包括事件控制块(eventCB)、事件掩码(eventMask)、模式(mode)等 LITE_OS_SEC_TEXT STATIC UINT32 OsEventReadCheck(const PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode) { UINT32 ret; @@ -122,7 +123,7 @@ LITE_OS_SEC_TEXT STATIC UINT32 OsEventReadCheck(const PEVENT_CB_S eventCB, UINT3 } return LOS_OK; } - +//OsEventReadImp()函数是事件读取的实现,根据指定的事件掩码和模式进行轮询,并根据超时时间和是否只读取一次进行相应的操作 LITE_OS_SEC_TEXT STATIC UINT32 OsEventReadImp(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout, BOOL once, UINT32 *intSave) { @@ -165,7 +166,7 @@ LITE_OS_SEC_TEXT STATIC UINT32 OsEventReadImp(PEVENT_CB_S eventCB, UINT32 eventM } return ret; } - +//OsEventRead()函数是对外提供的事件读取接口,调用OsEventReadCheck()和OsEventReadImp()实现事件的读取操作 LITE_OS_SEC_TEXT STATIC UINT32 OsEventRead(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout, BOOL once) { @@ -184,7 +185,7 @@ LITE_OS_SEC_TEXT STATIC UINT32 OsEventRead(PEVENT_CB_S eventCB, UINT32 eventMask SCHEDULER_UNLOCK(intSave); return ret; } - +//OsEventWrite()函数用于向事件控制块中写入指定的事件 LITE_OS_SEC_TEXT STATIC UINT32 OsEventWrite(PEVENT_CB_S eventCB, UINT32 events, BOOL once) { LosTaskCB *resumedTask = NULL; @@ -230,7 +231,7 @@ LITE_OS_SEC_TEXT STATIC UINT32 OsEventWrite(PEVENT_CB_S eventCB, UINT32 events, } return LOS_OK; } - +//LOS_EventPoll()函数是对外提供的事件轮询接口,调用OsEventParamCheck()和OsEventPoll()实现事件的轮询操作 LITE_OS_SEC_TEXT UINT32 LOS_EventPoll(UINT32 *eventId, UINT32 eventMask, UINT32 mode) { UINT32 ret; @@ -246,17 +247,17 @@ LITE_OS_SEC_TEXT UINT32 LOS_EventPoll(UINT32 *eventId, UINT32 eventMask, UINT32 SCHEDULER_UNLOCK(intSave); return ret; } - +//LOS_EventRead()函数是对外提供的事件读取接口,调用OsEventRead()实现事件的读取操作 LITE_OS_SEC_TEXT UINT32 LOS_EventRead(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout) { return OsEventRead(eventCB, eventMask, mode, timeout, FALSE); } - +//LOS_EventWrite()函数是对外提供的事件写入接口,调用OsEventWrite()实现事件的写入操作 LITE_OS_SEC_TEXT UINT32 LOS_EventWrite(PEVENT_CB_S eventCB, UINT32 events) { return OsEventWrite(eventCB, events, FALSE); } - +//LOS_EventDestroy()函数用于销毁事件控制块,将事件ID设置为0 LITE_OS_SEC_TEXT_INIT UINT32 LOS_EventDestroy(PEVENT_CB_S eventCB) { UINT32 intSave; @@ -279,7 +280,7 @@ OUT: LOS_TRACE(EVENT_DELETE, (UINTPTR)eventCB, ret); return ret; } - +//LOS_EventClear()函数用于清除指定的事件 LITE_OS_SEC_TEXT_MINOR UINT32 LOS_EventClear(PEVENT_CB_S eventCB, UINT32 events) { UINT32 intSave; @@ -296,18 +297,19 @@ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_EventClear(PEVENT_CB_S eventCB, UINT32 events) return LOS_OK; } - +//OsEventWriteOnce()函数是事件写入的实现,与OsEventWrite()类似,但只写入一次 LITE_OS_SEC_TEXT_MINOR UINT32 OsEventWriteOnce(PEVENT_CB_S eventCB, UINT32 events) { return OsEventWrite(eventCB, events, TRUE); } #ifdef LOSCFG_COMPAT_POSIX +//OsEventReadOnce()函数是事件读取的实现,与OsEventRead()类似,但只读取一次 LITE_OS_SEC_TEXT_MINOR UINT32 OsEventReadOnce(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout) { return OsEventRead(eventCB, eventMask, mode, timeout, TRUE); } - +// /OsEventReadWithCond()函数用于根据条件读取事件,只有当条件满足时才进行事件读取操作 LITE_OS_SEC_TEXT UINT32 OsEventReadWithCond(const EventCond *cond, PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout) { diff --git a/src/kernel/base/los_exc.c b/src/kernel/base/los_exc.c index 71970f0..3ea59a0 100644 --- a/src/kernel/base/los_exc.c +++ b/src/kernel/base/los_exc.c @@ -25,7 +25,8 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +/*这是关于LiteOS中异常处理的代码,其中包括记录异常信息、异常信息保存和读取等功能。 +同时还包括了一些与异常相关的函数,如打印异常信息、任务回溯等*/ #include "los_exc.h" #include "los_printf_pri.h" #include "los_task_pri.h" @@ -48,7 +49,7 @@ extern "C" { #endif #endif /* __cplusplus */ - +//ExcInfoDumpFormat的结构体类型,包含了用于存储异常信息的缓冲区指针、偏移量、长度和存储地址等信息 #ifdef LOSCFG_SHELL_EXCINFO_DUMP typedef struct { CHAR *buf; /* pointer to the buffer for storing the exception information */ @@ -56,11 +57,13 @@ typedef struct { UINT32 len; /* the size of storing the exception information */ UINTPTR dumpAddr; /* the address of storing the exception information */ } ExcInfoDumpFormat; - +//全局变量g_excInfoPool,用于存储异常信息的缓冲区和相关的信息 STATIC ExcInfoDumpFormat g_excInfoPool = {0}; /* the hook of read-writing exception information */ STATIC __attribute__((section(".data"))) LogReadWriteFunc g_dumpHook = NULL; - +//LOS_ExcInfoRegHook:注册异常信息读写钩子函数,用于设置异常信息的存储地址、长度以及缓冲区等信息 +//"钩子函数"是指在特定事件发生时会被调用的函数 +//通过使用钩子函数,可以在异常发生时灵活地执行特定的操作,例如记录异常信息、进行特定的处理或通知其他模块进行相应的操作 VOID LOS_ExcInfoRegHook(UINTPTR startAddr, UINT32 len, CHAR *buf, LogReadWriteFunc hook) { if ((hook == NULL) || (buf == NULL)) { @@ -78,57 +81,57 @@ VOID LOS_ExcInfoRegHook(UINTPTR startAddr, UINT32 len, CHAR *buf, LogReadWriteFu g_excInfoPool.buf = buf; g_dumpHook = hook; } - +//OsSetExcInfoRW:设置异常信息读写钩子函数 VOID OsSetExcInfoRW(LogReadWriteFunc func) { g_dumpHook = func; } - +//OsGetExcInfoRW:获取异常信息读写钩子函数 LogReadWriteFunc OsGetExcInfoRW(VOID) { return g_dumpHook; } - +//OsSetExcInfoBuf:设置异常信息的缓冲区 VOID OsSetExcInfoBuf(CHAR *buf) { g_excInfoPool.buf = buf; } - +//OsGetExcInfoBuf:获取异常信息的缓冲区 CHAR *OsGetExcInfoBuf(VOID) { return g_excInfoPool.buf; } - +//OsSetExcInfoOffset:设置异常信息的偏移量 VOID OsSetExcInfoOffset(UINT32 Offset) { g_excInfoPool.offset = Offset; } - +//OsGetExcInfoOffset:获取异常信息的偏移量 UINT32 OsGetExcInfoOffset(VOID) { return g_excInfoPool.offset; } - +//OsSetExcInfoDumpAddr:设置异常信息的存储地址 VOID OsSetExcInfoDumpAddr(UINTPTR addr) { g_excInfoPool.dumpAddr = addr; } - +//OsGetExcInfoDumpAddr:获取异常信息的存储地址 UINTPTR OsGetExcInfoDumpAddr(VOID) { return g_excInfoPool.dumpAddr; } - +//OsSetExcInfoLen:设置异常信息的长度 VOID OsSetExcInfoLen(UINT32 len) { g_excInfoPool.len = len; } - +//OsGetExcInfoLen:获取异常信息的长度 UINT32 OsGetExcInfoLen(VOID) { return g_excInfoPool.len; } - +//WriteExcBufVa:将格式化的字符串写入异常信息缓冲区 VOID WriteExcBufVa(const CHAR *format, va_list arglist) { errno_t ret; @@ -143,7 +146,7 @@ VOID WriteExcBufVa(const CHAR *format, va_list arglist) g_excInfoPool.offset += ret; } } - +//WriteExcInfoToBuf:将格式化的字符串写入异常信息缓冲区 VOID WriteExcInfoToBuf(const CHAR *format, ...) { va_list arglist; @@ -152,7 +155,7 @@ VOID WriteExcInfoToBuf(const CHAR *format, ...) WriteExcBufVa(format, arglist); va_end(arglist); } - +//OsRecordExcInfoTime:记录异常信息的时间 VOID OsRecordExcInfoTime(VOID) { #define NOW_TIME_LENGTH 24 @@ -169,7 +172,7 @@ VOID OsRecordExcInfoTime(VOID) #undef NOW_TIME_LENGTH PrintExcInfo("%s \n", nowTime); } - +//OsShellCmdReadExcInfo:读取并打印异常信息的Shell命令 #ifdef LOSCFG_SHELL INT32 OsShellCmdReadExcInfo(INT32 argc, const CHAR **argv) { @@ -200,6 +203,9 @@ SHELLCMD_ENTRY(readExcInfo_shellcmd, CMD_TYPE_EX, "excInfo", 0, (CmdCallBackFunc #endif #ifdef LOSCFG_EXC_INTERACTION +//OsCheckExcInteractionTask:检查任务是否为异常交互任务 +//异常交互任务通常指的是用于处理异常情况的特殊任务或线程 +//当系统发生严重的错误或异常时,需要立即采取相应的措施来处理异常情况,这就需要使用异常交互任务来处理 UINT32 OsCheckExcInteractionTask(const TSK_INIT_PARAM_S *initParam) { if ((initParam->pfnTaskEntry == (TSK_ENTRY_FUNC)ShellTask) || @@ -209,7 +215,7 @@ UINT32 OsCheckExcInteractionTask(const TSK_INIT_PARAM_S *initParam) } return LOS_NOK; } - +//OsKeepExcInteractionTask:保留异常交互任务,删除其他任务 VOID OsKeepExcInteractionTask(VOID) { LosTaskCB *taskCB = NULL; @@ -243,7 +249,7 @@ VOID OsKeepExcInteractionTask(VOID) } #endif - +//LOS_Panic:打印异常信息并停止CPU执行 VOID LOS_Panic(const CHAR *fmt, ...) { va_list ap; @@ -252,7 +258,7 @@ VOID LOS_Panic(const CHAR *fmt, ...) va_end(ap); ArchHaltCpu(); } - +//LOS_BackTrace:打印当前任务的运行信息和回溯堆栈 VOID LOS_BackTrace(VOID) { #ifdef LOSCFG_BACKTRACE @@ -262,7 +268,7 @@ VOID LOS_BackTrace(VOID) ArchBackTrace(); #endif } - +//LOS_TaskBackTrace:打印指定任务的运行信息和回溯堆栈 VOID LOS_TaskBackTrace(UINT32 taskID) { #ifdef LOSCFG_BACKTRACE @@ -289,6 +295,7 @@ VOID LOS_TaskBackTrace(UINT32 taskID) #ifdef __GNUC__ /* stack protector */ +//__stack_chk_fail:用于栈保护机制,当发现栈被破坏时触发异常处理 VOID __stack_chk_fail(VOID) { /* __builtin_return_address is a builtin function, building in gcc */ diff --git a/src/kernel/base/los_hwi.c b/src/kernel/base/los_hwi.c index 0adc4f4..c620a44 100644 --- a/src/kernel/base/los_hwi.c +++ b/src/kernel/base/los_hwi.c @@ -25,7 +25,9 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +/* +关于LiteOS中硬件中断处理的部分,涉及了中断的注册、删除、触发、使能、禁止等操作 +*/ #include "los_hwi_pri.h" #include "los_hwi.h" #include "los_memory.h" @@ -61,7 +63,7 @@ const HwiControllerOps *g_hwiOps = NULL; typedef VOID (*HWI_PROC_FUNC0)(VOID); typedef VOID (*HWI_PROC_FUNC2)(INT32, VOID *); - +//OsIrqNestingActive:用于在处理中断期间激活中断嵌套计数器,避免在处理时钟中断时进行抢占 STATIC INLINE VOID OsIrqNestingActive(UINT32 hwiNum) { #ifdef LOSCFG_ARCH_INTERRUPT_PREEMPTION @@ -71,7 +73,7 @@ STATIC INLINE VOID OsIrqNestingActive(UINT32 hwiNum) } #endif } - +//OsIrqNestingInactive:用于在处理中断结束后禁用中断嵌套计数器 STATIC INLINE VOID OsIrqNestingInactive(UINT32 hwiNum) { #ifdef LOSCFG_ARCH_INTERRUPT_PREEMPTION @@ -80,17 +82,17 @@ STATIC INLINE VOID OsIrqNestingInactive(UINT32 hwiNum) } #endif } - +//OsIrqNestingCntGet:获取当前CPU的中断嵌套计数值 size_t OsIrqNestingCntGet(VOID) { return g_intCount[ArchCurrCpuid()]; } - +//OsIrqNestingCntSet:设置当前CPU的中断嵌套计数值 VOID OsIrqNestingCntSet(size_t val) { g_intCount[ArchCurrCpuid()] = val; } - +//InterruptHandle:处理中断的实际函数,根据中断号调用对应的中断处理函数 STATIC INLINE VOID InterruptHandle(HwiHandleInfo *hwiForm) { hwiForm->respCount++; @@ -114,7 +116,7 @@ STATIC INLINE VOID InterruptHandle(HwiHandleInfo *hwiForm) } #endif } - +//OsIntHandle:中断处理入口函数,负责处理中断前的一些准备工作,如调用中断处理前的钩子函数等 VOID OsIntHandle(UINT32 hwiNum, HwiHandleInfo *hwiForm) { size_t *intCnt = NULL; @@ -148,7 +150,7 @@ VOID OsIntHandle(UINT32 hwiNum, HwiHandleInfo *hwiForm) OsCpupIrqEnd(hwiNum); #endif } - +//OsIntEntry:中断向量入口函数,根据中断号调用对应的中断处理函数 VOID OsIntEntry(VOID) { if ((g_hwiOps != NULL) && (g_hwiOps->handleIrq != NULL)) { @@ -156,7 +158,7 @@ VOID OsIntEntry(VOID) } return; } - +//OsHwiCpIrqParam:根据传入的中断参数结构体分配内存,并将参数信息拷贝到新分配的内存中 STATIC HWI_ARG_T OsHwiCpIrqParam(const HWI_IRQ_PARAM_S *irqParam) { HWI_IRQ_PARAM_S *paramByAlloc = NULL; @@ -169,6 +171,7 @@ STATIC HWI_ARG_T OsHwiCpIrqParam(const HWI_IRQ_PARAM_S *irqParam) return (HWI_ARG_T)paramByAlloc; } #ifndef LOSCFG_SHARED_IRQ +//OsHwiDel:删除指定的中断处理函数 STATIC UINT32 OsHwiDel(HwiHandleInfo *hwiForm, const HWI_IRQ_PARAM_S *irqParam, UINT32 irqId) { UINT32 intSave; @@ -190,7 +193,7 @@ STATIC UINT32 OsHwiDel(HwiHandleInfo *hwiForm, const HWI_IRQ_PARAM_S *irqParam, HWI_UNLOCK(intSave); return LOS_OK; } - +//OsHwiCreate:创建中断处理函数,并将其添加到中断处理链表中 STATIC UINT32 OsHwiCreate(HwiHandleInfo *hwiForm, HWI_MODE_T hwiMode, HWI_PROC_FUNC hwiHandler, const HWI_IRQ_PARAM_S *irqParam) { @@ -218,6 +221,7 @@ STATIC UINT32 OsHwiCreate(HwiHandleInfo *hwiForm, HWI_MODE_T hwiMode, HWI_PROC_F return LOS_OK; } #else /* LOSCFG_SHARED_IRQ */ +//函数OsFreeHwiNode:用于释放中断处理函数节点,并在需要时禁止该中断 STATIC INLINE UINT32 OsFreeHwiNode(HwiHandleInfo *head, HwiHandleInfo *hwiForm, UINT32 irqId) { UINT32 ret = LOS_OK; @@ -240,7 +244,8 @@ STATIC INLINE UINT32 OsFreeHwiNode(HwiHandleInfo *head, HwiHandleInfo *hwiForm, return ret; } - +//OsHwiDel:用于删除硬件中断处理函数,它首先判断中断是否是共享中断 +//如果不是,则直接释放该中断的处理函数节点;如果是共享中断,则遍历链表找到对应的设备ID,然后释放该中断的处理函数节点 STATIC UINT32 OsHwiDel(HwiHandleInfo *head, const HWI_IRQ_PARAM_S *irqParam, UINT32 irqId) { HwiHandleInfo *hwiFormPrev = NULL; @@ -290,7 +295,8 @@ STATIC UINT32 OsHwiDel(HwiHandleInfo *head, const HWI_IRQ_PARAM_S *irqParam, UIN HWI_UNLOCK(intSave); return ret; } - +//OsHwiCreate:用于创建硬件中断处理函数,它首先判断中断是否是共享中断,并检查是否已经存在具有相同设备ID的中断处理函数节点,如果存在则返回错误 +//然后申请内存并初始化新的中断处理函数节点,将其添加到链表中 STATIC UINT32 OsHwiCreate(HwiHandleInfo *head, HWI_MODE_T hwiMode, HWI_PROC_FUNC hwiHandler, const HWI_IRQ_PARAM_S *irqParam) { @@ -359,7 +365,9 @@ size_t IntActive() LOS_IntRestore(intSave); return intCount; } - +//LOS_HwiCreate 函数:用于创建硬件中断处理函数 +//它会注册一个中断处理函数,并将其与指定的硬件中断号相关联 +//可以设置中断的优先级、硬件中断模式和处理函数 LITE_OS_SEC_TEXT UINT32 LOS_HwiCreate(HWI_HANDLE_T hwiNum, HWI_PRIOR_T hwiPrio, HWI_MODE_T hwiMode, @@ -396,7 +404,8 @@ LITE_OS_SEC_TEXT UINT32 LOS_HwiCreate(HWI_HANDLE_T hwiNum, } return ret; } - +//LOS_HwiDelete 函数:用于删除已经创建的硬件中断处理函数 +//通过指定硬件中断号,可以将之前注册的中断处理函数从系统中删除 LITE_OS_SEC_TEXT UINT32 LOS_HwiDelete(HWI_HANDLE_T hwiNum, HWI_IRQ_PARAM_S *irqParam) { UINT32 ret; @@ -417,7 +426,8 @@ LITE_OS_SEC_TEXT UINT32 LOS_HwiDelete(HWI_HANDLE_T hwiNum, HWI_IRQ_PARAM_S *irqP return ret; } - +//LOS_HwiTrigger 函数:用于手动触发指定的硬件中断 +//调用该函数后,会立即触发对应的硬件中断,使得系统执行相应的中断处理函数 LITE_OS_SEC_TEXT UINT32 LOS_HwiTrigger(HWI_HANDLE_T hwiNum) { if ((g_hwiOps == NULL) || (g_hwiOps->triggerIrq == NULL)) { @@ -427,7 +437,8 @@ LITE_OS_SEC_TEXT UINT32 LOS_HwiTrigger(HWI_HANDLE_T hwiNum) return g_hwiOps->triggerIrq(hwiNum); } - +//LOS_HwiEnable 函数:用于使能指定的硬件中断 +//调用该函数后,系统将允许对应的硬件中断产生,并执行相应的中断处理函数 LITE_OS_SEC_TEXT UINT32 LOS_HwiEnable(HWI_HANDLE_T hwiNum) { if ((g_hwiOps == NULL) || (g_hwiOps->enableIrq == NULL)) { @@ -437,7 +448,8 @@ LITE_OS_SEC_TEXT UINT32 LOS_HwiEnable(HWI_HANDLE_T hwiNum) return g_hwiOps->enableIrq(hwiNum); } - +//LOS_HwiDisable 函数:用于禁止指定的硬件中断 +//调用该函数后,系统将阻止对应的硬件中断产生,屏蔽其影响 LITE_OS_SEC_TEXT UINT32 LOS_HwiDisable(HWI_HANDLE_T hwiNum) { if ((g_hwiOps == NULL) || (g_hwiOps->disableIrq == NULL)) { @@ -447,7 +459,8 @@ LITE_OS_SEC_TEXT UINT32 LOS_HwiDisable(HWI_HANDLE_T hwiNum) return g_hwiOps->disableIrq(hwiNum); } - +//LOS_HwiClear 函数:用于清除指定的硬件中断 +//在某些平台上,硬件中断发生后可能需要手动清除中断标志位,以便正确处理后续的中断 LITE_OS_SEC_TEXT UINT32 LOS_HwiClear(HWI_HANDLE_T hwiNum) { if ((g_hwiOps == NULL) || (g_hwiOps->clearIrq == NULL)) { @@ -457,7 +470,8 @@ LITE_OS_SEC_TEXT UINT32 LOS_HwiClear(HWI_HANDLE_T hwiNum) return g_hwiOps->clearIrq(hwiNum); } - +//LOS_HwiSetPriority 函数:用于设置硬件中断的优先级 +//通过指定硬件中断号和优先级,可以调整硬件中断的触发顺序 LITE_OS_SEC_TEXT UINT32 LOS_HwiSetPriority(HWI_HANDLE_T hwiNum, HWI_PRIOR_T priority) { if ((g_hwiOps == NULL) || (g_hwiOps->setIrqPriority == NULL)) { @@ -468,6 +482,8 @@ LITE_OS_SEC_TEXT UINT32 LOS_HwiSetPriority(HWI_HANDLE_T hwiNum, HWI_PRIOR_T prio return g_hwiOps->setIrqPriority(hwiNum, priority); } #ifdef LOSCFG_KERNEL_SMP +//LOS_HwiSetAffinity函数:用于设置硬件中断的处理CPU亲和性 +//它首先检查硬件中断操作函数指针是否为空,然后调用具体的操作函数来设置中断的处理CPU亲和性 LITE_OS_SEC_TEXT UINT32 LOS_HwiSetAffinity(HWI_HANDLE_T hwiNum, UINT32 cpuMask) { if ((g_hwiOps == NULL) || (g_hwiOps->setIrqCpuAffinity == NULL)) { @@ -477,7 +493,8 @@ LITE_OS_SEC_TEXT UINT32 LOS_HwiSetAffinity(HWI_HANDLE_T hwiNum, UINT32 cpuMask) return g_hwiOps->setIrqCpuAffinity(hwiNum, cpuMask); } - +//LOS_HwiSendIpi函数:用于发送硬件中断处理请求给指定的CPU +//它首先检查硬件中断操作函数指针是否为空,然后调用具体的操作函数来发送中断处理请求 LITE_OS_SEC_TEXT UINT32 LOS_HwiSendIpi(HWI_HANDLE_T hwiNum, UINT32 cpuMask) { if ((g_hwiOps == NULL) || (g_hwiOps->sendIpi == NULL)) { @@ -490,6 +507,8 @@ LITE_OS_SEC_TEXT UINT32 LOS_HwiSendIpi(HWI_HANDLE_T hwiNum, UINT32 cpuMask) #endif #ifdef LOSCFG_KERNEL_LOWPOWER +//LOS_IntWakeupHookReg函数:用于注册中断唤醒回调函数 +//它将传入的回调函数赋值给全局变量g_intWakeupHook,以便在中断唤醒时调用该回调函数 LITE_OS_SEC_TEXT_MINOR VOID LOS_IntWakeupHookReg(WAKEUPFROMINTHOOK hook) { g_intWakeupHook = hook; @@ -497,6 +516,8 @@ LITE_OS_SEC_TEXT_MINOR VOID LOS_IntWakeupHookReg(WAKEUPFROMINTHOOK hook) #endif /* Initialization of the hardware interrupt */ +//OsHwiInit函数:用于初始化硬件中断 +//它会调用具体的平台相关函数来进行硬件中断的初始化操作 LITE_OS_SEC_TEXT_INIT VOID OsHwiInit(VOID) { ArchIrqInit(); diff --git a/src/kernel/base/los_lockdep.c b/src/kernel/base/los_lockdep.c index 7c65cf1..b4826f0 100644 --- a/src/kernel/base/los_lockdep.c +++ b/src/kernel/base/los_lockdep.c @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +/*这段代码是关于锁依赖检查的实现。包含了一些头文件和函数的定义,用于在多核系统中检测锁的使用情况*/ #include "los_base.h" #include "los_spinlock.h" #include "los_task_pri.h" @@ -47,6 +47,8 @@ extern "C" { STATIC Atomic g_lockdepAvailable = 1; /* atomic insurance for lockdep check */ +//OsLockDepRequire:该函数用于获取锁依赖检查的原子操作,确保在进行锁依赖检查时不会被中断 +//原子操作是指在计算机科学中,不会被中断的操作 STATIC INLINE VOID OsLockDepRequire(UINT32 *intSave) { *intSave = LOS_IntLock(); @@ -54,13 +56,13 @@ STATIC INLINE VOID OsLockDepRequire(UINT32 *intSave) /* busy waiting */ } } - +//OsLockDepRelease:释放锁依赖检查的原子操作,用于在完成锁依赖检查后恢复正常的中断状态 STATIC INLINE VOID OsLockDepRelease(UINT32 intSave) { LOS_AtomicSet(&g_lockdepAvailable, 1); LOS_IntRestore(intSave); } - +//OsLockDepGetCycles:获取当前 CPU 的周期计数器的值,用于记录锁请求和释放时的时间戳 STATIC INLINE UINT64 OsLockDepGetCycles(VOID) { UINT32 high, low; @@ -69,7 +71,7 @@ STATIC INLINE UINT64 OsLockDepGetCycles(VOID) /* combine cycleHi and cycleLo into 8 bytes cycles */ return (((UINT64)high << 32) + low); } - +//OsLockDepErrorStringGet:根据错误类型返回对应的错误字符串,用于打印错误信息 STATIC INLINE CHAR *OsLockDepErrorStringGet(enum LockDepErrType type) { CHAR *errorString = NULL; @@ -94,7 +96,7 @@ STATIC INLINE CHAR *OsLockDepErrorStringGet(enum LockDepErrType type) return errorString; } - +//OsLockDepPanic:当发生严重错误时触发系统的崩溃,通常在检测到死锁等无法修复的情况下调用 WEAK VOID OsLockDepPanic(enum LockDepErrType errType) { /* halt here */ @@ -103,7 +105,7 @@ WEAK VOID OsLockDepPanic(enum LockDepErrType errType) OsBackTrace(); while (1) {} } - +//OsLockDepDumpLock:输出锁依赖检查失败时的调试信息,包括任务名、任务 ID、CPU 号等,并最终触发崩溃 STATIC VOID OsLockDepDumpLock(const LosTaskCB *task, const SPIN_LOCK_S *lock, const VOID *requestAddr, enum LockDepErrType errType) { @@ -143,7 +145,7 @@ STATIC VOID OsLockDepDumpLock(const LosTaskCB *task, const SPIN_LOCK_S *lock, OsLockDepPanic(errType); } - +//OsLockDepCheckDependancy:检查当前任务与锁的所有者之间是否存在依赖关系,以避免死锁 STATIC BOOL OsLockDepCheckDependancy(const LosTaskCB *current, const LosTaskCB *lockOwner) { BOOL checkResult = TRUE; @@ -164,7 +166,7 @@ STATIC BOOL OsLockDepCheckDependancy(const LosTaskCB *current, const LosTaskCB * return checkResult; } - +//OsLockDepCheckIn:在请求锁时进行依赖检查,记录锁的请求地址和等待时间,如检查失败则触发崩溃 VOID OsLockDepCheckIn(const SPIN_LOCK_S *lock) { UINT32 intSave; @@ -217,7 +219,7 @@ OUT: OsLockDepRelease(intSave); } - +//OsLockDepRecord:记录成功获取锁的时间戳和持有者信息,并更新锁的所有者和 CPU 号等信息 VOID OsLockDepRecord(SPIN_LOCK_S *lock) { UINT32 intSave; @@ -250,7 +252,7 @@ VOID OsLockDepRecord(SPIN_LOCK_S *lock) OsLockDepRelease(intSave); } - +//OsLockDepCheckOut:在释放锁时进行依赖检查,记录持有时间并清除相关信息,如检查失败则触发崩溃 VOID OsLockDepCheckOut(SPIN_LOCK_S *lock) { UINT32 intSave; @@ -302,7 +304,8 @@ VOID OsLockDepCheckOut(SPIN_LOCK_S *lock) OUT: OsLockDepRelease(intSave); } - +//OsLockdepClearSpinlocks:清除当前任务持有的所有自旋锁,通常在系统处于异常状态下调用以确保解锁 +//自旋锁是一种用于多线程同步的机制。在使用自旋锁时,线程会反复检查锁是否被释放,如果锁已经被占用,线程就会一直循环等待,直到锁被释放为止 VOID OsLockdepClearSpinlocks(VOID) { LosTaskCB *task = OsCurrTaskGet(); diff --git a/src/kernel/base/los_misc.c b/src/kernel/base/los_misc.c index 3cbe7fc..6e495c5 100644 --- a/src/kernel/base/los_misc.c +++ b/src/kernel/base/los_misc.c @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +//操作系统的基础函数 #include "los_task_pri.h" #include "los_misc_pri.h" #include "los_memory_pri.h" @@ -48,23 +48,23 @@ extern "C" { #endif /* __cplusplus */ #ifdef LOSCFG_LIB_CONFIGURABLE -LITE_OS_SEC_BSS UINT32 g_osSysClock; -LITE_OS_SEC_BSS UINT32 g_semLimit; -LITE_OS_SEC_BSS UINT32 g_muxLimit; -LITE_OS_SEC_BSS UINT32 g_queueLimit; - -LITE_OS_SEC_BSS UINT32 g_swtmrLimit; -LITE_OS_SEC_BSS UINT32 g_taskLimit; -LITE_OS_SEC_BSS UINT32 g_minusOneTickPerSecond; -LITE_OS_SEC_BSS UINT32 g_taskMinStkSize; -LITE_OS_SEC_BSS UINT32 g_taskIdleStkSize; -LITE_OS_SEC_BSS UINT32 g_taskSwtmrStkSize; -LITE_OS_SEC_BSS UINT32 g_taskDfltStkSize; -LITE_OS_SEC_BSS UINT32 g_timeSliceTimeOut; - -LITE_OS_SEC_DATA BOOL g_nxEnabled = FALSE; -LITE_OS_SEC_BSS UINTPTR g_dlNxHeapBase; -LITE_OS_SEC_BSS UINT32 g_dlNxHeapSize; +LITE_OS_SEC_BSS UINT32 g_osSysClock; //操作系统的系统时钟频率 +LITE_OS_SEC_BSS UINT32 g_semLimit; //信号量的最大数量限制 +LITE_OS_SEC_BSS UINT32 g_muxLimit; //互斥锁的最大数量限制 +LITE_OS_SEC_BSS UINT32 g_queueLimit; //队列最大数量限制 + +LITE_OS_SEC_BSS UINT32 g_swtmrLimit; //软件定时器的最大数量限制 +LITE_OS_SEC_BSS UINT32 g_taskLimit; //任务的最大数量限制 +LITE_OS_SEC_BSS UINT32 g_minusOneTickPerSecond; //每秒减去的滴答数,用于时间戳计算 +LITE_OS_SEC_BSS UINT32 g_taskMinStkSize;//任务的最小堆栈大小 +LITE_OS_SEC_BSS UINT32 g_taskIdleStkSize; //空闲任务的堆栈大小 +LITE_OS_SEC_BSS UINT32 g_taskSwtmrStkSize; //软件定时器任务的堆栈大小 +LITE_OS_SEC_BSS UINT32 g_taskDfltStkSize; //默认任务的堆栈大小 +LITE_OS_SEC_BSS UINT32 g_timeSliceTimeOut; //时间片的超时时间 + +LITE_OS_SEC_DATA BOOL g_nxEnabled = FALSE; //是否启用了内存保护机制 +LITE_OS_SEC_BSS UINTPTR g_dlNxHeapBase; //动态加载库的内存堆起始地址 +LITE_OS_SEC_BSS UINT32 g_dlNxHeapSize; //动态加载库的内存堆大小 #endif #ifdef LOSCFG_KERNEL_TRACE @@ -77,11 +77,12 @@ LMS_INIT_HOOK g_lmsMemInitHook = NULL; LMS_FUNC_HOOK g_lmsMallocHook = NULL; LMS_FUNC_HOOK g_lmsFreeHook = NULL; #endif +//LOS_Align:用于将给定的地址按指定的边界对齐,返回对齐后的地址 LITE_OS_SEC_TEXT UINTPTR LOS_Align(UINTPTR addr, UINT32 boundary) { return (addr + boundary - 1) & ~((UINTPTR)(boundary - 1)); } - +//OsDumpMemByte:用于以字节为单位打印内存中的数据 LITE_OS_SEC_TEXT_MINOR VOID LOS_Msleep(UINT32 msecs) { UINT32 interval; @@ -97,7 +98,7 @@ LITE_OS_SEC_TEXT_MINOR VOID LOS_Msleep(UINT32 msecs) (VOID)LOS_TaskDelay(interval); } - +//OsDumpMemByte:用于以字节为单位打印内存中的数据 VOID OsDumpMemByte(size_t length, UINTPTR addr) { size_t dataLen; @@ -141,6 +142,7 @@ VOID OsDumpMemByte(size_t length, UINTPTR addr) } #if defined(LOSCFG_DEBUG_SEMAPHORE) || defined(LOSCFG_DEBUG_MUTEX) || defined(LOSCFG_DEBUG_QUEUE) +//OsArraySort:快速排序 VOID OsArraySort(UINT32 *sortArray, UINT32 start, UINT32 end, const SortParam *sortParam, OsCompareFunc compareFunc) { diff --git a/src/kernel/base/los_mp.c b/src/kernel/base/los_mp.c index d176a17..ba29cd8 100644 --- a/src/kernel/base/los_mp.c +++ b/src/kernel/base/los_mp.c @@ -25,7 +25,8 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +/*针对多处理器(SMP)系统的操作系统内核部分的实现 +主要包括了多处理器调度、任务管理和中断处理等功能*/ #include "los_mp_pri.h" #include "los_task_pri.h" #include "los_percpu_pri.h" @@ -45,7 +46,7 @@ LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_mpCallSpin); #define MP_CALL_LOCK(state) LOS_SpinLockSave(&g_mpCallSpin, &(state)) #define MP_CALL_UNLOCK(state) LOS_SpinUnlockRestore(&g_mpCallSpin, (state)) #endif - +//LOS_MpSchedule:多处理器调度函数,用于向指定的处理器发送调度中断 VOID LOS_MpSchedule(UINT32 target) { UINT32 ret; @@ -57,12 +58,12 @@ VOID LOS_MpSchedule(UINT32 target) } return; } - +//OsMpWakeHandler:多处理器唤醒处理函数,目前为空实现,无特定操作 VOID OsMpWakeHandler(VOID) { /* generic wakeup ipi, do nothing */ } - +//OsMpScheduleHandler:多处理器调度处理函数,设置调度标志以触发调度器在中断结束时执行调度 VOID OsMpScheduleHandler(VOID) { /* @@ -71,7 +72,7 @@ VOID OsMpScheduleHandler(VOID) */ OsPercpuGet()->schedFlag = INT_PEND_RESCH; } - +//OsMpHaltHandler:多处理器停机处理函数,将当前处理器标记为已停机状态,并进入死循环 VOID OsMpHaltHandler(VOID) { (VOID)LOS_IntLock(); @@ -79,7 +80,7 @@ VOID OsMpHaltHandler(VOID) while (1) {} } - +//OsMpCollectTasks:多处理器任务回收函数,用于递归检查所有可用任务,并删除标记为需要销毁的任务 VOID OsMpCollectTasks(VOID) { LosTaskCB *taskCB = NULL; @@ -109,6 +110,7 @@ VOID OsMpCollectTasks(VOID) } #ifdef LOSCFG_KERNEL_SMP_CALL +//OsMpFuncCall:多处理器函数调用函数,用于向指定的处理器发送函数调用请求 VOID OsMpFuncCall(UINT32 target, SMP_FUNC_CALL func, VOID *args) { UINT32 index; @@ -144,7 +146,7 @@ VOID OsMpFuncCall(UINT32 target, SMP_FUNC_CALL func, VOID *args) } return; } - +//OsMpFuncCallHandler:多处理器函数调用处理函数,从本处理器的函数调用队列中取出并执行函数调用请求 VOID OsMpFuncCallHandler(VOID) { UINT32 intSave; @@ -166,7 +168,7 @@ VOID OsMpFuncCallHandler(VOID) } MP_CALL_UNLOCK(intSave); } - +//OsMpFuncCallInit:多处理器函数调用初始化函数,用于初始化每个核心的函数调用队列 VOID OsMpFuncCallInit(VOID) { UINT32 index; @@ -176,7 +178,7 @@ VOID OsMpFuncCallInit(VOID) } } #endif /* LOSCFG_KERNEL_SMP_CALL */ - +//OsMpInit:多处理器初始化函数,包括创建周期性软件定时器和初始化函数调用队列等 UINT32 OsMpInit(VOID) { UINT16 swtmrId; diff --git a/src/kernel/base/los_mux.c b/src/kernel/base/los_mux.c index 25dbacc..31bb6df 100644 --- a/src/kernel/base/los_mux.c +++ b/src/kernel/base/los_mux.c @@ -25,7 +25,8 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +/*代码实现了一个简单的互斥锁(Mutex),用于保护共享资源的访问 +互斥锁的主要功能是确保在同一时间只有一个线程可以访问被保护的代码块或共享资源,从而避免并发访问引发的数据竞争和不一致性*/ #include "los_mux_pri.h" #include "los_mux_debug_pri.h" #include "los_bitmap.h" @@ -49,6 +50,7 @@ LITE_OS_SEC_DATA_INIT STATIC LOS_DL_LIST g_unusedMuxList; * Description : Initializes the mutex * Return : LOS_OK on success, or error code on failure */ +//OsMuxInit:Mutex初始化函数,用于初始化Mutex数据结构并设置初始状态 LITE_OS_SEC_TEXT UINT32 OsMuxInit(VOID) { LosMuxCB *muxNode = NULL; @@ -74,7 +76,7 @@ LITE_OS_SEC_TEXT UINT32 OsMuxInit(VOID) } return LOS_OK; } - +//LOS_MuxCreate:创建Mutex函数,用于创建一个新的Mutex对象,并返回其句柄 LITE_OS_SEC_TEXT UINT32 LOS_MuxCreate(UINT32 *muxHandle) { UINT32 intSave; @@ -113,7 +115,7 @@ LITE_OS_SEC_TEXT UINT32 LOS_MuxCreate(UINT32 *muxHandle) ERR_HANDLER: OS_RETURN_ERROR_P2(errLine, errNo); } - +//LOS_MuxDelete:删除Mutex函数,用于删除指定的Mutex对象及其相关资源 LITE_OS_SEC_TEXT UINT32 LOS_MuxDelete(UINT32 muxHandle) { UINT32 intSave; @@ -154,7 +156,7 @@ LITE_OS_SEC_TEXT UINT32 LOS_MuxDelete(UINT32 muxHandle) ERR_HANDLER: OS_RETURN_ERROR_P2(errLine, errNo); } - +//OsMuxParaCheck 函数主要用于验证互斥量操作的参数是否有效,包括互斥量是否被正确创建和传入的句柄是否有效,以及当前是否处于中断上下文 LITE_OS_SEC_TEXT STATIC UINT32 OsMuxParaCheck(const LosMuxCB *muxCB, UINT32 muxHandle) { if ((muxCB->muxStat == LOS_UNUSED) || (muxCB->muxId != muxHandle)) { @@ -168,7 +170,7 @@ LITE_OS_SEC_TEXT STATIC UINT32 OsMuxParaCheck(const LosMuxCB *muxCB, UINT32 muxH } return LOS_OK; } - +//OsMuxBitmapSet 函数用于在互斥量等待队列中设置任务的优先级位图,并根据需要调整任务的优先级,以确保任务在等待互斥量时能够正确反映其优先级关系 LITE_OS_SEC_TEXT STATIC VOID OsMuxBitmapSet(const LosTaskCB *runTask, const MuxBaseCB *muxPended) { if (muxPended->owner->priority > runTask->priority) { @@ -176,7 +178,7 @@ LITE_OS_SEC_TEXT STATIC VOID OsMuxBitmapSet(const LosTaskCB *runTask, const MuxB OsTaskPriModify(muxPended->owner, runTask->priority); } } - +//OsMuxBitmapRestore 函数用于恢复任务的优先级位图,并根据需要更新拥有者任务的优先级 LITE_OS_SEC_TEXT STATIC VOID OsMuxBitmapRestore(const LosTaskCB *runTask, LosTaskCB *owner) { UINT16 bitMapPri; @@ -244,7 +246,8 @@ LITE_OS_SEC_TEXT STATIC LOS_DL_LIST *OsMuxPendFindPos(const LosTaskCB *runTask, return node; } #endif - +//总体来说,OsMuxPostOp 函数用于处理 Mutex 的释放操作,包括唤醒等待任务、更新 Mutex 状态和持有者等 +//确保 Mutex 能够按照预期的方式被正确释放和传递给下一个任务 LITE_OS_SEC_TEXT UINT32 OsMuxPendOp(LosTaskCB *runTask, MuxBaseCB *muxPended, UINT32 timeout, UINT32 *intSave) { @@ -270,7 +273,7 @@ LITE_OS_SEC_TEXT UINT32 OsMuxPendOp(LosTaskCB *runTask, MuxBaseCB *muxPended, UI return ret; } - +//LOS_MuxPend:等待Mutex函数,用于尝试获取指定Mutex的访问权限。如果Mutex已被其他任务持有,则当前任务会被挂起,直到Mutex可用 LITE_OS_SEC_TEXT UINT32 LOS_MuxPend(UINT32 muxHandle, UINT32 timeout) { UINT32 ret; @@ -332,7 +335,7 @@ OUT_UNLOCK: } return ret; } - +//OsMuxPostOpSub:通过比较当前任务和 Mutex 等待队列中的任务的优先级,来调整当前任务的优先级位图,并将 Mutex 持有者的优先级提升 LITE_OS_SEC_TEXT STATIC VOID OsMuxPostOpSub(LosTaskCB *runTask, MuxBaseCB *muxPosted) { LosTaskCB *pendedTask = NULL; @@ -350,7 +353,7 @@ LITE_OS_SEC_TEXT STATIC VOID OsMuxPostOpSub(LosTaskCB *runTask, MuxBaseCB *muxPo LOS_BitmapClr(&runTask->priBitMap, bitMapPri); OsTaskPriModify(muxPosted->owner, bitMapPri); } - +// LITE_OS_SEC_TEXT UINT32 OsMuxPostOp(LosTaskCB *runTask, MuxBaseCB *muxPosted) { LosTaskCB *resumedTask = NULL; @@ -386,7 +389,7 @@ LITE_OS_SEC_TEXT UINT32 OsMuxPostOp(LosTaskCB *runTask, MuxBaseCB *muxPosted) return MUX_SCHEDULE; } - +//LOS_MuxPost:释放Mutex函数,用于释放当前任务对指定Mutex的访问权限,以便其他任务可以获取该Mutex LITE_OS_SEC_TEXT UINT32 LOS_MuxPost(UINT32 muxHandle) { UINT32 ret; diff --git a/src/kernel/base/los_percpu.c b/src/kernel/base/los_percpu.c index 7110c08..c7e0782 100644 --- a/src/kernel/base/los_percpu.c +++ b/src/kernel/base/los_percpu.c @@ -33,7 +33,7 @@ extern "C" { #endif /* __cplusplus */ #endif /* __cplusplus */ - +//定义全局变量数组,用于存储每个CPU核心的私有数据 Percpu g_percpu[LOSCFG_KERNEL_CORE_NUM]; #ifdef __cplusplus diff --git a/src/kernel/base/los_printf.c b/src/kernel/base/los_printf.c index 6457a4d..7974cb3 100644 --- a/src/kernel/base/los_printf.c +++ b/src/kernel/base/los_printf.c @@ -32,7 +32,7 @@ * It should not add OS inner invocation, which is not allowed to be accessed in user space. * But it's allowed to invoke syscall interface. *---------------------------------------------------------------------------- */ - +/*这段代码是一个输出控制模块,根据不同的输出类型将字符串输出到不同的设备上*/ #ifdef LOSCFG_LIB_LIBC #include "unistd.h" #endif @@ -62,13 +62,13 @@ typedef enum { CONSOLE_OUTPUT = 2, EXC_OUTPUT = 3 } OutputType; - +//ErrorMsg:用于输出错误信息,当字符串输出非法或者vsnprintf_s函数失败时调用 STATIC VOID ErrorMsg(VOID) { const CHAR *p = "Output illegal string! vsnprintf_s failed!\n"; UartPuts(p, (UINT32)strlen(p), UART_WITH_LOCK); } - +//UartOutput:实际将字符串输出到串口的函数,根据配置可能会进行一些额外的处理 STATIC VOID UartOutput(const CHAR *str, UINT32 len, BOOL isLock) { #ifdef LOSCFG_SHELL_DMESG @@ -82,7 +82,7 @@ STATIC VOID UartOutput(const CHAR *str, UINT32 len, BOOL isLock) UartPuts(str, len, isLock); #endif } - +//OutputControl:根据输出类型选择相应的输出设备,并调用对应的输出函数 STATIC VOID OutputControl(const CHAR *str, UINT32 len, OutputType type) { switch (type) { @@ -105,14 +105,14 @@ STATIC VOID OutputControl(const CHAR *str, UINT32 len, OutputType type) } return; } - +//OsVprintfFree:释放动态分配的缓冲区内存 STATIC VOID OsVprintfFree(CHAR *buf, UINT32 bufLen) { if (bufLen != SIZEBUF) { (VOID)LOS_MemFree(m_aucSysMem0, buf); } } - +//OsVprintf:核心函数,根据给定的格式化字符串和可变参数,进行字符串格式化并输出到相应的设备 STATIC VOID OsVprintf(const CHAR *fmt, va_list ap, OutputType type) { INT32 len; @@ -156,7 +156,7 @@ STATIC VOID OsVprintf(const CHAR *fmt, va_list ap, OutputType type) OutputControl(bBuf, len, type); OsVprintfFree(bBuf, bufLen); } - +//UartVprintf、ConsoleVprintf、UartPrintf、dprintf、LkDprintf、DmesgPrintf、ExcPrintf、PrintExcInfo:这些函数都是对OsVprintf的封装,提供了不同的输出接口,在不同的场景下调用OsVprintf来完成字符串的格式化和输出 VOID UartVprintf(const CHAR *fmt, va_list ap) { OsVprintf(fmt, ap, UART_OUTPUT); From d4596b7503d88e09b5535f3332c67d13c89fddde Mon Sep 17 00:00:00 2001 From: faj <1900949849@qq.com> Date: Mon, 27 Nov 2023 19:56:08 +0800 Subject: [PATCH 05/26] 1 --- src/kernel/include/arch_generic/atomic.h | 55 +++- src/kernel/include/console.h | 132 ++++----- src/kernel/include/los_atomic.h | 46 +-- src/kernel/include/los_base.h | 43 ++- src/kernel/include/los_bitmap.h | 21 +- src/kernel/include/los_builddef.h | 42 +-- src/kernel/include/los_config.h | 216 ++++++++------ src/kernel/include/los_cppsupport.h | 16 + src/kernel/include/los_cpup.h | 41 +++ src/kernel/include/los_err.h | 20 +- src/kernel/include/los_errno.h | 52 +++- src/kernel/include/los_event.h | 162 ++++++++++- src/kernel/include/los_exc.h | 75 ++++- src/kernel/include/los_hw.h | 3 +- src/kernel/include/los_hwi.h | 353 ++++++++++++++++++++++- 15 files changed, 1049 insertions(+), 228 deletions(-) diff --git a/src/kernel/include/arch_generic/atomic.h b/src/kernel/include/arch_generic/atomic.h index 2b68336..81dc858 100644 --- a/src/kernel/include/arch_generic/atomic.h +++ b/src/kernel/include/arch_generic/atomic.h @@ -31,6 +31,7 @@ * @ingroup kernel */ +//LiteOSϵͳУatomic.hͷļͨṩԭӲ֧֡ԭӲDzжϵIJȷڶ̻߳жԹԴаȫķʺ޸ġ #ifndef _ARCH_GENERIC_ATOMIC_H #define _ARCH_GENERIC_ATOMIC_H @@ -44,17 +45,26 @@ extern "C" { #endif /* __cplusplus */ #ifndef LOSCFG_KERNEL_SMP - +/*ArchAtomicRead ԭӶȡһֵ +һָԭӱָ v ǿתΪ volatile INT32 ͵ָ룬 +ظֵָָ*/ STATIC INLINE INT32 ArchAtomicRead(const Atomic *v) { return *(volatile INT32 *)v; } +/*ArchAtomicSet ԭһֵ +һָԭӱָ v ǿתΪ volatile INT32 ͵ָ룬 + setVal ֵָָı*/ STATIC INLINE VOID ArchAtomicSet(Atomic *v, INT32 setVal) { *(volatile INT32 *)v = setVal; } +/*ArchAtomicAdd ԭһֵ +ȱ浱ǰж״̬Ȼڹرжϵ£ addVal ӵָ v ָıϣ +Ӻֵ +󣬻ָ֮ǰж״̬*/ STATIC INLINE INT32 ArchAtomicAdd(Atomic *v, INT32 addVal) { UINT32 intSave; @@ -66,6 +76,9 @@ STATIC INLINE INT32 ArchAtomicAdd(Atomic *v, INT32 addVal) return *v; } +/*ArchAtomicSub ԭӼһֵ +ʵ ArchAtomicAdd ƣ +ֻǽ subVal ȥָ v ָı*/ STATIC INLINE INT32 ArchAtomicSub(Atomic *v, INT32 subVal) { UINT32 intSave; @@ -77,6 +90,10 @@ STATIC INLINE INT32 ArchAtomicSub(Atomic *v, INT32 subVal) return *v; } +/*ArchAtomicInc ԭһֵ +ȱ浱ǰж״̬ intSaveȻڹرжϵ£ +ָ addr ָı 1 +ָ֮ǰж״̬*/ STATIC INLINE VOID ArchAtomicInc(Atomic *addr) { UINT32 intSave; @@ -86,6 +103,7 @@ STATIC INLINE VOID ArchAtomicInc(Atomic *addr) LOS_IntRestore(intSave); } +//ArchAtomicIncRet ArchAtomicInc ƣӺıֵ STATIC INLINE INT32 ArchAtomicIncRet(Atomic *addr) { UINT32 intSave; @@ -96,6 +114,7 @@ STATIC INLINE INT32 ArchAtomicIncRet(Atomic *addr) return *addr; } +//ArchAtomicDec ԭӼһֵʵ ArchAtomicIncֻǽָ addr ָı 1 STATIC INLINE VOID ArchAtomicDec(Atomic *addr) { UINT32 intSave; @@ -105,6 +124,7 @@ STATIC INLINE VOID ArchAtomicDec(Atomic *addr) LOS_IntRestore(intSave); } +//ArchAtomicDecRet ArchAtomicDec ƣؼٺıֵ STATIC INLINE INT32 ArchAtomicDecRet(Atomic *addr) { UINT32 intSave; @@ -115,6 +135,10 @@ STATIC INLINE INT32 ArchAtomicDecRet(Atomic *addr) return *addr; } +/*ArchAtomic64Read ԭӶȡһ 64 λֵ +ȱ浱ǰж״̬ intSaveȻڹرжϵ£ +ȡָ v ָ 64 λֵ +ָ֮ǰж״̬ضȡֵ*/ STATIC INLINE INT64 ArchAtomic64Read(const Atomic64 *v) { UINT32 intSave; @@ -127,6 +151,10 @@ STATIC INLINE INT64 ArchAtomic64Read(const Atomic64 *v) return val; } +/*ArchAtomic64Set ԭһ 64 λֵΪ setVal +ȱ浱ǰж״̬ intSaveȻڹرжϵ£ +ָ v ָıΪ setVal +ָ֮ǰж״̬*/ STATIC INLINE VOID ArchAtomic64Set(Atomic64 *v, INT64 setVal) { UINT32 intSave; @@ -136,6 +164,10 @@ STATIC INLINE VOID ArchAtomic64Set(Atomic64 *v, INT64 setVal) LOS_IntRestore(intSave); } +/*ArchAtomic64Add ԭһ 64 λֵ +ȱ浱ǰж״̬ intSaveȻڹرжϵ£ +ָ v ָı addValȻӺֵ val +ָ֮ǰж״̬ val*/ STATIC INLINE INT64 ArchAtomic64Add(Atomic64 *v, INT64 addVal) { UINT32 intSave; @@ -149,6 +181,9 @@ STATIC INLINE INT64 ArchAtomic64Add(Atomic64 *v, INT64 addVal) return val; } +/*ArchAtomic64Sub ԭӼһ 64 λֵ +ʵ ArchAtomic64Add +ֻǽָ v ָıȥ subVal*/ STATIC INLINE INT64 ArchAtomic64Sub(Atomic64 *v, INT64 subVal) { UINT32 intSave; @@ -162,6 +197,8 @@ STATIC INLINE INT64 ArchAtomic64Sub(Atomic64 *v, INT64 subVal) return val; } +/*ArchAtomic64Inc ԭһ 64 λֵ +ʵ ArchAtomic64Addֻǽӵ̶ֵΪ 1*/ STATIC INLINE VOID ArchAtomic64Inc(Atomic64 *v) { UINT32 intSave; @@ -171,6 +208,7 @@ STATIC INLINE VOID ArchAtomic64Inc(Atomic64 *v) LOS_IntRestore(intSave); } +//ArchAtomic64IncRet ArchAtomic64Inc ƣӺıֵ STATIC INLINE INT64 ArchAtomic64IncRet(Atomic64 *v) { UINT32 intSave; @@ -184,6 +222,9 @@ STATIC INLINE INT64 ArchAtomic64IncRet(Atomic64 *v) return val; } +/*ArchAtomic64Dec ԭӼһ 64 λֵ +ȱ浱ǰж״̬ intSaveȻڹرжϵ£ָ v ָıȥ 1 +ָ֮ǰж״̬*/ STATIC INLINE VOID ArchAtomic64Dec(Atomic64 *v) { UINT32 intSave; @@ -193,6 +234,7 @@ STATIC INLINE VOID ArchAtomic64Dec(Atomic64 *v) LOS_IntRestore(intSave); } +//ArchAtomic64DecRet ArchAtomic64Dec ƣؼٺıֵ STATIC INLINE INT64 ArchAtomic64DecRet(Atomic64 *v) { UINT32 intSave; @@ -206,6 +248,10 @@ STATIC INLINE INT64 ArchAtomic64DecRet(Atomic64 *v) return val; } +/*ArchAtomicXchg32bits ԭӽһ 32 λֵ +ȱ浱ǰж״̬ intSaveȻڹرжϵ£ +ָ v ָıֵ prevValٽ v ֵΪ val +ָ֮ǰж״̬ԭȵֵ prevVal*/ STATIC INLINE INT32 ArchAtomicXchg32bits(Atomic *v, INT32 val) { UINT32 intSave; @@ -219,6 +265,7 @@ STATIC INLINE INT32 ArchAtomicXchg32bits(Atomic *v, INT32 val) return prevVal; } +//ArchAtomicXchg64bits ArchAtomicXchg32bitsԭӽһ 64 λֵ STATIC INLINE INT64 ArchAtomicXchg64bits(Atomic64 *v, INT64 val) { UINT32 intSave; @@ -232,6 +279,11 @@ STATIC INLINE INT64 ArchAtomicXchg64bits(Atomic64 *v, INT64 val) return prevVal; } +/*ArchAtomicCmpXchg32bits ԭӱȽϺͽһ 32 λֵ +ȱ浱ǰж״̬ intSaveȻڹرжϵ£ +ָ v ָıֵ prevValж prevVal Ƿ oldVal +ȣ򽫱 v ֵΪ valָ֮ǰж״̬ +Ƿִ˽IJֵ*/ STATIC INLINE BOOL ArchAtomicCmpXchg32bits(Atomic *v, INT32 val, INT32 oldVal) { UINT32 intSave; @@ -247,6 +299,7 @@ STATIC INLINE BOOL ArchAtomicCmpXchg32bits(Atomic *v, INT32 val, INT32 oldVal) return (prevVal != oldVal); } +//ArchAtomicCmpXchg64bits ArchAtomicCmpXchg32bitsԭӱȽϺͽһ 64 λֵ STATIC INLINE BOOL ArchAtomicCmpXchg64bits(Atomic64 *v, INT64 val, INT64 oldVal) { UINT32 intSave; diff --git a/src/kernel/include/console.h b/src/kernel/include/console.h index a0f102a..e57aba9 100644 --- a/src/kernel/include/console.h +++ b/src/kernel/include/console.h @@ -25,18 +25,18 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +//LiteOSϵͳУconsoleͷļͨڶ̨صĺݽṹ #ifndef _CONSOLE_H #define _CONSOLE_H - -#include "los_config.h" -#ifdef LOSCFG_FS_VFS -#include "termios.h" -#ifdef LOSCFG_NET_TELNET -#include "telnet_dev.h" -#endif -#include "virtual_serial.h" -#include "los_ringbuf.h" +//УʹȷͷļֻһΡŶ˿̨ĴС˿̨ʼӡͶȡȺ +#include "los_config.h"//ϵͳļڻȡϵͳһЩúԡ +#ifdef LOSCFG_FS_VFS//ʹָжǷ˺LOSCFG_FS_VFSѾ壬Ĵ飬 +#include "termios.h"// POSIX ն˿ƶͷļڶն˽пơ +#ifdef LOSCFG_NET_TELNET//ʹָжǷ˺,Ѿ壬Ĵ飬 +#include "telnet_dev.h"// Telnet 豸ͷļʵ Telnet ӡ +#endif//ָ +#include "virtual_serial.h"//⴮ڵͷļʵ⴮ڵĹܡ +#include "los_ringbuf.h"//˻λͷļʵֻĶд #endif #ifdef __cplusplus @@ -57,76 +57,76 @@ extern "C" { #define CONSOLE "/dev/console" #define CONSOLE_NAMELEN 16 - -#define CONSOLE_CMD_RD_BLOCK_SERIAL 0x104 -#define CONSOLE_CMD_RD_BLOCK_TELNET 101 -#define CONSOLE_RD_BLOCK 1 -#define CONSOLE_RD_NONBLOCK 0 -#define CONSOLE_SHELL_KEY_EVENT 0x112 -#define CONSOLE_SHELL_EXITED 0x400 -#define CONSOLE_CONTROL_RIGHTS_CAPTURE 201 -#define CONSOLE_CONTROL_RIGHTS_RELEASE 202 -#define CONSOLE_CONTROL_CAPTURE_LINE 203 -#define CONSOLE_CONTROL_CAPTURE_CHAR 204 -#define CONSOLE_FIFO_SIZE 1024 -#define CONSOLE_NUM 2 +//δ붨һЩͳǵĺ£ +#define CONSOLE_CMD_RD_BLOCK_SERIAL 0x104//ʾӴڶȡݵֵΪ0x104 +#define CONSOLE_CMD_RD_BLOCK_TELNET 101//ʾTelnetӶȡݵֵΪ101 +#define CONSOLE_RD_BLOCK 1//ʾģʽֵΪ1 +#define CONSOLE_RD_NONBLOCK 0//ʾģʽֵΪ0 +#define CONSOLE_SHELL_KEY_EVENT 0x112//ʾshell¼ֵΪ0x112 +#define CONSOLE_SHELL_EXITED 0x400//ʾshell˳ֵΪ0x400 +#define CONSOLE_CONTROL_RIGHTS_CAPTURE 201//ʾȨֵΪ201 +#define CONSOLE_CONTROL_RIGHTS_RELEASE 202//ʾȨͷţֵΪ202 +#define CONSOLE_CONTROL_CAPTURE_LINE 203//ʾֵΪ203 +#define CONSOLE_CONTROL_CAPTURE_CHAR 204//ʾַֵΪ204 +#define CONSOLE_FIFO_SIZE 1024//ʾ̨FIFOFirst In First OutСֵΪ1024 +#define CONSOLE_NUM 2//ʾֵ̨Ϊ2 typedef struct { - Ringbuf ringbuf; /* Ring buffer */ - EVENT_CB_S sendEvent; /* Inform telnet send task */ + Ringbuf ringbuf; /* Ring buffer *///ʾλһڻݵѭл߻ + EVENT_CB_S sendEvent; /* Inform telnet send task *///ʾtelnet¼Ļص } RingbufSendCB; typedef struct { - UINT32 consoleID; - UINT32 consoleType; - UINT32 consoleSem; - UINT32 shellEntryId; - UINT32 consoleMask; - struct inode *devInode; - CHAR *name; - INT32 fd; - UINT32 refCount; - BOOL isNonBlock; + UINT32 consoleID;//ʾ̨ID + UINT32 consoleType;//ʾ̨͡ + UINT32 consoleSem;//ʾͬĿ̨ź + UINT32 shellEntryId;//ʾshellID + UINT32 consoleMask;//ʾ̨롣 + struct inode *devInode;//ʾ豸ڵ㡣 + CHAR *name;//ʾ̨ơ + INT32 fd;//ʾļ + UINT32 refCount;//ʾü + BOOL isNonBlock;//ʾǷΪģʽ #ifdef LOSCFG_SHELL - VOID *shellHandle; + VOID *shellHandle;//ʾshellľ #endif - UINT32 sendTaskID; - RingbufSendCB *ringbufSendCB; - UINT8 fifo[CONSOLE_FIFO_SIZE]; - UINT32 fifoOut; - UINT32 fifoIn; - UINT32 currentLen; - struct termios consoleTermios; + UINT32 sendTaskID;//ʾID + RingbufSendCB *ringbufSendCB;//ʾλͻص + UINT8 fifo[CONSOLE_FIFO_SIZE];//ʾ̨FIFO + UINT32 fifoOut;//ʾFIFOλá + UINT32 fifoIn;//ʾFIFOλá + UINT32 currentLen;//ʾǰȡ + struct termios consoleTermios;//ʾ̨նԡ } CONSOLE_CB; -extern INT32 system_console_init(const CHAR *deviceName); -extern INT32 system_console_deinit(const CHAR *deviceName); -extern BOOL SetSerialNonBlock(const CONSOLE_CB *consoleCB); -extern BOOL SetSerialBlock(const CONSOLE_CB *consoleCB); -extern BOOL SetTelnetNonBlock(const CONSOLE_CB *consoleCB); -extern BOOL SetTelnetBlock(const CONSOLE_CB *consoleCB); -extern CONSOLE_CB *OsGetConsoleByID(INT32 consoleId); -extern CONSOLE_CB *OsGetConsoleByTaskID(UINT32 taskId); -extern UINT32 ConsoleTaskReg(INT32 consoleId, UINT32 taskId); -extern INT32 ConsoleUpdateFd(VOID); -extern BOOL ConsoleEnable(VOID); -extern BOOL is_nonblock(const CONSOLE_CB *consoleCB); -extern BOOL IsConsoleOccupied(const CONSOLE_CB *consoleCB); -extern INT32 FilepOpen(struct file *filep, const struct file_operations_vfs *fops); -extern INT32 FilepClose(struct file *filep, const struct file_operations_vfs *fops); -extern INT32 FilepRead(struct file *filep, const struct file_operations_vfs *fops, CHAR *buffer, size_t bufLen); -extern INT32 FilepWrite(struct file *filep, const struct file_operations_vfs *fops, const CHAR *buffer, size_t bufLen); -extern INT32 FilepPoll(struct file *filep, const struct file_operations_vfs *fops, poll_table *fds); -extern INT32 FilepIoctl(struct file *filep, const struct file_operations_vfs *fops, INT32 cmd, unsigned long arg); -extern INT32 GetFilepOps(const struct file *filep, struct file **privFilep, const struct file_operations_vfs **fops); +extern INT32 system_console_init(const CHAR *deviceName);//̨ʼڳʼ̨صԴ״̬ +extern INT32 system_console_deinit(const CHAR *deviceName);//̨ʼͷſ̨صԴ״̬ +extern BOOL SetSerialNonBlock(const CONSOLE_CB *consoleCB);//ôΪģʽ +extern BOOL SetSerialBlock(const CONSOLE_CB *consoleCB);//ôΪģʽ +extern BOOL SetTelnetNonBlock(const CONSOLE_CB *consoleCB);//TelnetΪģʽ +extern BOOL SetTelnetBlock(const CONSOLE_CB *consoleCB);//TelnetΪģʽ +extern CONSOLE_CB *OsGetConsoleByID(INT32 consoleId);//ݿ̨IDȡ̨Ŀƿ飨Control Block +extern CONSOLE_CB *OsGetConsoleByTaskID(UINT32 taskId);//IDȡĿ̨Ŀƿ顣 +extern UINT32 ConsoleTaskReg(INT32 consoleId, UINT32 taskId);//ָĿ̨й +extern INT32 ConsoleUpdateFd(VOID);//¿̨ļFile Descriptor +extern BOOL ConsoleEnable(VOID);//ʹ̨ܿܡ +extern BOOL is_nonblock(const CONSOLE_CB *consoleCB);//жϿ̨ǷΪģʽ +extern BOOL IsConsoleOccupied(const CONSOLE_CB *consoleCB);//жϿ̨ǷѾռá +extern INT32 FilepOpen(struct file *filep, const struct file_operations_vfs *fops);//ļ +extern INT32 FilepClose(struct file *filep, const struct file_operations_vfs *fops);//رļ +extern INT32 FilepRead(struct file *filep, const struct file_operations_vfs *fops, CHAR *buffer, size_t bufLen);//ļжȡݡ +extern INT32 FilepWrite(struct file *filep, const struct file_operations_vfs *fops, const CHAR *buffer, size_t bufLen);//ļдݡ +extern INT32 FilepPoll(struct file *filep, const struct file_operations_vfs *fops, poll_table *fds);//ļѯ +extern INT32 FilepIoctl(struct file *filep, const struct file_operations_vfs *fops, INT32 cmd, unsigned long arg);//ļIOƲ +extern INT32 GetFilepOps(const struct file *filep, struct file **privFilep, const struct file_operations_vfs **fops);//ȡļIJ #else -STATIC INLINE INT32 ConsoleUpdateFd(VOID) +STATIC INLINE INT32 ConsoleUpdateFd(VOID)//һһΪConsoleUpdateFdľ̬ΪINT3232λΪաݺʵΪreturn -1;úǸ¿̨ļFile Descriptor-1 { return -1; } -#endif +#endif//ʾ֮ǰָ#if -#ifdef __cplusplus +#ifdef __cplusplus//һָжǷΪC++뻷C++뻷򽫺Ĵextern "C"Ա֤CC++֮ĺùһ¡ #if __cplusplus } #endif /* __cplusplus */ diff --git a/src/kernel/include/los_atomic.h b/src/kernel/include/los_atomic.h index 05fff5f..eaf9204 100644 --- a/src/kernel/include/los_atomic.h +++ b/src/kernel/include/los_atomic.h @@ -30,12 +30,12 @@ * @defgroup los_atomic Atomic * @ingroup kernel */ - -#ifndef _LOS_ATOMIC_H -#define _LOS_ATOMIC_H +//los_atomic.h֧ԭӲͷļ +#ifndef _LOS_ATOMIC_H//ʾ _LOS_ATOMIC_H ûбִ´룬δ롣 +#define _LOS_ATOMIC_H//ǶһжͷļǷѾ #include "los_typedef.h" -#include "arch/atomic.h" +#include "arch/atomic.h"//ƽ̨صԭӲͷļʵڲͬӲƽ̨ #ifdef __cplusplus #if __cplusplus @@ -60,7 +60,7 @@ extern "C" { * @see LOS_Atomic64Read * @since Huawei LiteOS V200R003C00 */ -STATIC INLINE INT32 LOS_AtomicRead(const Atomic *v) +STATIC INLINE INT32 LOS_AtomicRead(const Atomic *v)//һAtomic͵ָvһ32λڶȡָڴλõԭӱֵ { return ArchAtomicRead(v); } @@ -84,7 +84,7 @@ STATIC INLINE INT32 LOS_AtomicRead(const Atomic *v) * @see LOS_Atomic64Set * @since Huawei LiteOS V200R003C00 */ -STATIC INLINE VOID LOS_AtomicSet(Atomic *v, INT32 setVal) +STATIC INLINE VOID LOS_AtomicSet(Atomic *v, INT32 setVal)//һAtomic͵ָvһ32λsetValûзֵΪVOID { ArchAtomicSet(v, setVal); } @@ -114,7 +114,7 @@ STATIC INLINE VOID LOS_AtomicSet(Atomic *v, INT32 setVal) */ STATIC INLINE INT32 LOS_AtomicAdd(Atomic *v, INT32 addVal) { - return ArchAtomicAdd(v, addVal); + return ArchAtomicAdd(v, addVal);//ڽָڴλõԭӱֵָ } /** @@ -142,7 +142,7 @@ STATIC INLINE INT32 LOS_AtomicAdd(Atomic *v, INT32 addVal) */ STATIC INLINE INT32 LOS_AtomicSub(Atomic *v, INT32 subVal) { - return ArchAtomicSub(v, subVal); + return ArchAtomicSub(v, subVal);//ڽָڴλõԭӱֵָ } /** @@ -168,7 +168,7 @@ STATIC INLINE INT32 LOS_AtomicSub(Atomic *v, INT32 subVal) */ STATIC INLINE VOID LOS_AtomicInc(Atomic *v) { - ArchAtomicInc(v); + ArchAtomicInc(v);//ڽָڴλõԭӱ1 } /** @@ -222,7 +222,7 @@ STATIC INLINE INT32 LOS_AtomicIncRet(Atomic *v) */ STATIC INLINE VOID LOS_AtomicDec(Atomic *v) { - ArchAtomicDec(v); + ArchAtomicDec(v);//úͨضϵṹṩԭӵݼʵ֡ͨʹͺ궨壬ڱʱδֱǶ뵽ôӶִЧʺͽʡõĿ } /** @@ -248,7 +248,7 @@ STATIC INLINE VOID LOS_AtomicDec(Atomic *v) */ STATIC INLINE INT32 LOS_AtomicDecRet(Atomic *v) { - return ArchAtomicDecRet(v); + return ArchAtomicDecRet(v);//úͨضϵṹṩԭӵݼصݼֵĺ } /** @@ -270,7 +270,7 @@ STATIC INLINE INT32 LOS_AtomicDecRet(Atomic *v) */ STATIC INLINE INT64 LOS_Atomic64Read(const Atomic64 *v) { - return ArchAtomic64Read(v); + return ArchAtomic64Read(v);//úͨضϵṹṩԭӶȡĺ } /** @@ -294,7 +294,7 @@ STATIC INLINE INT64 LOS_Atomic64Read(const Atomic64 *v) */ STATIC INLINE VOID LOS_Atomic64Set(Atomic64 *v, INT64 setVal) { - ArchAtomic64Set(v, setVal); + ArchAtomic64Set(v, setVal);//úӦɵײļܹṩģʵ 64 λԭӲ } /** @@ -322,7 +322,7 @@ STATIC INLINE VOID LOS_Atomic64Set(Atomic64 *v, INT64 setVal) */ STATIC INLINE INT64 LOS_Atomic64Add(Atomic64 *v, INT64 addVal) { - return ArchAtomic64Add(v, addVal); + return ArchAtomic64Add(v, addVal);//ԭӼӲúӦɵײļܹṩģʵ 64 λԭӲ } /** @@ -350,7 +350,7 @@ STATIC INLINE INT64 LOS_Atomic64Add(Atomic64 *v, INT64 addVal) */ STATIC INLINE INT64 LOS_Atomic64Sub(Atomic64 *v, INT64 subVal) { - return ArchAtomic64Sub(v, subVal); + return ArchAtomic64Sub(v, subVal);//ԭӼúӦɵײļܹṩģʵ 64 λԭӲ } /** @@ -376,7 +376,7 @@ STATIC INLINE INT64 LOS_Atomic64Sub(Atomic64 *v, INT64 subVal) */ STATIC INLINE VOID LOS_Atomic64Inc(Atomic64 *v) { - ArchAtomic64Inc(v); + ArchAtomic64Inc(v);//ԭӲúӦɵײļܹṩģʵ 64 λԭӲ } /** @@ -403,7 +403,7 @@ STATIC INLINE VOID LOS_Atomic64Inc(Atomic64 *v) */ STATIC INLINE INT64 LOS_Atomic64IncRet(Atomic64 *v) { - return ArchAtomic64IncRet(v); + return ArchAtomic64IncRet(v);//ԭӲӺֵúӦɵײļܹṩģʵ 64 λԭӲ } /** @@ -430,7 +430,7 @@ STATIC INLINE INT64 LOS_Atomic64IncRet(Atomic64 *v) */ STATIC INLINE VOID LOS_Atomic64Dec(Atomic64 *v) { - ArchAtomic64Dec(v); + ArchAtomic64Dec(v);//ԭӼٲúӦɵײļܹṩģʵ 64 λԭӲ } /** @@ -456,7 +456,7 @@ STATIC INLINE VOID LOS_Atomic64Dec(Atomic64 *v) */ STATIC INLINE INT64 LOS_Atomic64DecRet(Atomic64 *v) { - return ArchAtomic64DecRet(v); + return ArchAtomic64DecRet(v);//ԭӼٲؼٺֵúӦɵײļܹṩģʵ 64 λԭӲ } /** @@ -480,7 +480,7 @@ STATIC INLINE INT64 LOS_Atomic64DecRet(Atomic64 *v) */ STATIC INLINE INT32 LOS_AtomicXchg32bits(Atomic *v, INT32 val) { - return ArchAtomicXchg32bits(v, val); + return ArchAtomicXchg32bits(v, val);//ԭӽؽǰֵúӦɵײļܹṩģʵ 32 λԭӲ } /** @@ -504,7 +504,7 @@ STATIC INLINE INT32 LOS_AtomicXchg32bits(Atomic *v, INT32 val) */ STATIC INLINE INT64 LOS_AtomicXchg64bits(Atomic64 *v, INT64 val) { - return ArchAtomicXchg64bits(v, val); + return ArchAtomicXchg64bits(v, val);//ԭӽؽǰֵúӦɵײļܹṩģʵ 64 λԭӲ } /** @@ -531,7 +531,7 @@ STATIC INLINE INT64 LOS_AtomicXchg64bits(Atomic64 *v, INT64 val) */ STATIC INLINE BOOL LOS_AtomicCmpXchg32bits(Atomic *v, INT32 val, INT32 oldVal) { - return ArchAtomicCmpXchg32bits(v, val, oldVal); + return ArchAtomicCmpXchg32bits(v, val, oldVal);//ԭӱȽϺͽرȽϽúӦɵײļܹṩģʵ 32 λԭӲ } /** @@ -558,7 +558,7 @@ STATIC INLINE BOOL LOS_AtomicCmpXchg32bits(Atomic *v, INT32 val, INT32 oldVal) */ STATIC INLINE BOOL LOS_AtomicCmpXchg64bits(Atomic64 *v, INT64 val, INT64 oldVal) { - return ArchAtomicCmpXchg64bits(v, val, oldVal); + return ArchAtomicCmpXchg64bits(v, val, oldVal);//ԭӱȽϺͽرȽϽúӦɵײļܹṩģʵ 64 λԭӲ } #ifdef __cplusplus diff --git a/src/kernel/include/los_base.h b/src/kernel/include/los_base.h index a4544a5..bf1e570 100644 --- a/src/kernel/include/los_base.h +++ b/src/kernel/include/los_base.h @@ -75,19 +75,19 @@ extern "C" { * @since Huawei LiteOS V100R001C00 */ #define LOS_ASSERT_COND(expression) LOS_ASSERT(expression) - +//һ꺯һʽΪñʽΪݸһΪLOS_ASSERTĺ꺯ʱִжԡ /** * @ingroup los_base * Define the timeout interval as LOS_NO_WAIT. */ #define LOS_NO_WAIT 0 - +//һΪ0ʾһʱʱʾȴء /** * @ingroup los_base * Define the timeout interval as LOS_WAIT_FOREVER. */ #define LOS_WAIT_FOREVER 0xFFFFFFFF - +//һΪ0xFFFFFFFFʾһʱʱʾԶȴֱ߱жϡ /** * @ingroup los_base * @brief Align the value (addr) by some bytes (boundary). @@ -111,8 +111,8 @@ extern "C" { * @see LOS_Align | TRUNCATE * @since Huawei LiteOS V100R001C00 */ -#ifndef ALIGN -#define ALIGN(addr, boundary) LOS_Align(addr, boundary) +#ifndef ALIGN//жALIGNǷѾûбִнĴ롣 +#define ALIGN(addr, boundary) LOS_Align(addr, boundary)//ֱʾҪĵַͶ߽硣ںڲLOS_Alignеַaddrַ϶뵽ӽboundaryı #endif /** @@ -139,10 +139,16 @@ extern "C" { * @since Huawei LiteOS V100R001C00 */ #define TRUNCATE(addr, size) ((UINTPTR)(addr) & ~((size) - 1)) - +// addr sizeһضϺĵַԣú꽫ַ addr size ĴСж룬λλΪ㡣磬 addr 0x12345678size 4ضϺĵַ 0x12345670 /** * Read a UINT8 value from addr and stroed in value. */ +/*READ_UINT8(value, addr)READ_UINT16(value, addr) READ_UINT32(value, addr) +ֱڴӵַ addr жȡ 8 λ16 λ 32 λֵ +洢 value С⼸ʵַʽƣ +ָͨӶȡڴеֵʹ dsb() ͬ +ȷȡȷУdsb() һָ +ڽֹͬݲһµ*/ #define READ_UINT8(value, addr) ({ (value) = *((volatile UINT8 *)((UINTPTR)(addr))); dsb(); }) /** @@ -155,6 +161,9 @@ extern "C" { */ #define READ_UINT32(value, addr) ({ (value) = *((volatile UINT32 *)((UINTPTR)(addr))); dsb(); }) + +//жϱ뻷ǷΪ 64 λ 64 λ READ_UINT64 WRITE_UINT64 ꡣ꽫ԡ +//ڴӵַ addr жȡһ 64 λֵ洢 value Сʹ˺֮ǰƵIJָͨӶȡڴеֵʹ dsb() ͬ #ifdef __LP64__ /** * Read a UINT64 value from addr and stroed in value. @@ -162,6 +171,11 @@ extern "C" { #define READ_UINT64(value, addr) ({ (value) = *((volatile UINT64 *)((UINTPTR)(addr))); dsb(); }) #endif + +/*WRITE_UINT8(value, addr)WRITE_UINT16(value, addr) WRITE_UINT32(value, addr) +ֱڽ 8 λ16 λ 32 λֵ value д뵽ַ addr С +ЩҲʹ˺֮ǰƵIJʹ dsb() ͬ +ָͨдڴеֵ*/ /** * Write a UINT8 value to addr. */ @@ -177,6 +191,8 @@ extern "C" { */ #define WRITE_UINT32(value, addr) ({ dsb(); *((volatile UINT32 *)((UINTPTR)(addr))) = (value); }) + +// 64 λ£ WRITE_UINT64 ꣬ڽ 64 λֵ value д뵽ַ addr С #ifdef __LP64__ /** * Write a UINT64 addr to addr. @@ -187,11 +203,13 @@ extern "C" { /** * Get a UINT8 value from addr. */ +//ڴӵַ addr жȡһ 8 λ޷ֵضȡĽڶȡ֮ʹ dsb() ͬȷȡȷ #define GET_UINT8(addr) ({ UINT8 r = *((volatile UINT8 *)((UINTPTR)(addr))); dsb(); r; }) /** * Get a UINT16 value from addr. */ +//GET_UINT16(addr) GET_UINT32(addr) ֱڴӵַ addr жȡ 16 λ 32 λ޷ֵضȡĽͬأڶȡ֮Ҳͬ #define GET_UINT16(addr) ({ UINT16 r = *((volatile UINT16 *)((UINTPTR)(addr))); dsb(); r; }) /** @@ -199,6 +217,8 @@ extern "C" { */ #define GET_UINT32(addr) ({ UINT32 r = *((volatile UINT32 *)((UINTPTR)(addr))); dsb(); r; }) + +// 64 λ£ GET_UINT64(addr) ꣬ڴӵַ addr жȡһ 64 λ޷ֵضȡĽ #ifdef __LP64__ /** * Get a UINT64 value from addr. @@ -226,7 +246,7 @@ extern "C" { * @see LOS_ASSERT_COND * @since Huawei LiteOS V100R001C00 */ -#ifdef LOSCFG_DEBUG_VERSION +#ifdef LOSCFG_DEBUG_VERSION//ȣָͨ #ifdef LOSCFG_DEBUG_VERSION жǷڵ԰汾 LOSCFG_DEBUG_VERSION ꣬ʾڵ԰汾 #ifdef #endif ֮ݽЧ򣬴 #else #endif ֮ݽЧ #define LOS_ASSERT(judge) do { \ if ((UINTPTR)(judge) == 0) { \ (VOID)LOS_IntLock(); \ @@ -234,8 +254,12 @@ extern "C" { while (1) {} \ } \ } while (0) +//ڵ԰汾£궨ĴУLOS_ASSERT 걻Ϊһв judge ĺ꺯ǽжԼ飬 judge ʽĽΪ㣨٣ִϲ +// LOS_IntLock() úһڽֹжϵIJȷڶʧʱжϴ +//ʹ PRINT_ERR ӡһϢа˳ļкźͺ +//һѭ while (1)һֱͣѭС #else -#define LOS_ASSERT(judge) +#define LOS_ASSERT(judge)//ڷǵ԰汾£궨ĴУLOS_ASSERT 걻Ϊգκβ #endif /** @@ -261,7 +285,8 @@ extern "C" { * @since Huawei LiteOS V100R001C00 */ extern UINTPTR LOS_Align(UINTPTR addr, UINT32 boundary); - +//ԣĹǽ addr boundary ߽ж룬ضĵַ磬 addr 12boundary 8ôĵַ 16 +//extern ؼֱʾúطģֻǶĿڵǰļʹøúʱܹȷҪṩľʵ֡ /** * @ingroup los_base * @brief Sleep the current task. diff --git a/src/kernel/include/los_bitmap.h b/src/kernel/include/los_bitmap.h index 81bfb8f..b05e472 100644 --- a/src/kernel/include/los_bitmap.h +++ b/src/kernel/include/los_bitmap.h @@ -31,7 +31,7 @@ * @ingroup kernel */ -#ifndef _LOS_BITMAP_H +#ifndef _LOS_BITMAP_H//δһָ飬жǷ˺ _LOS_BITMAP_Hδúִ꣬ #ifndef #endif ֮Ĵ롣 #define _LOS_BITMAP_H #include "los_typedef.h" @@ -48,6 +48,7 @@ extern "C" { * * The effective bit index is from 0 to 31. */ +//궨ֵΪ 32ĺʹ 0 31 ʾλֵ 32 ʾЧλִֵʽڼбȽϳһڱʶijЩ״̬־ #define LOS_INVALID_BIT_INDEX 32 /** @@ -69,6 +70,9 @@ extern "C" { * @see LOS_BitmapClr * @since Huawei LiteOS V100R001C00 */ +/*bitmap һָ UINT32 ͵ָ룬ʾһλͼΪλ飩 +pos һ UINT16 ͵IJʾҪõλ +ڸλͼнָλλΪ 1ӦλõıλΪ 1*/ VOID LOS_BitmapSet(UINT32 *bitmap, UINT16 pos); /** @@ -90,6 +94,9 @@ VOID LOS_BitmapSet(UINT32 *bitmap, UINT16 pos); * @see LOS_BitmapSet. * @since Huawei LiteOS V100R001C00 */ +/*bitmap һָ UINT32 ͵ָ룬ʾһλͼΪλ飩 +pos һ UINT16 ͵IJʾҪλ +ڸλͼнָλλ㣬ӦλõıλΪ 0*/ VOID LOS_BitmapClr(UINT32 *bitmap, UINT16 pos); /** @@ -108,6 +115,12 @@ VOID LOS_BitmapClr(UINT32 *bitmap, UINT16 pos); * @see LOS_HighBitGet * @since Huawei LiteOS V100R001C00 */ +/*ڸλͼҵλҲֵСλ +ظλͼвκλıλ +򷵻 32 LOS_INVALID_BIT_INDEX ֵ +ʵֿܻ漰λ +ҵλšںΪ UINT16 + unsigned short ͣ˷ֵΪ 0 31 0 31 32*/ UINT16 LOS_LowBitGet(UINT32 bitmap); /** @@ -126,6 +139,12 @@ UINT16 LOS_LowBitGet(UINT32 bitmap); * @see LOS_LowBitGet * @since Huawei LiteOS V100R001C00 */ +/*ڸλͼҵλҲֵλ +ظλͼвκλıλ +򷵻 32 LOS_INVALID_BIT_INDEX ֵ +ʵֿܻ漰λҵλš +ںΪ UINT16 unsigned short ͣ +˷ֵΪ 0 31 0 31 32*/ UINT16 LOS_HighBitGet(UINT32 bitmap); #ifdef __cplusplus diff --git a/src/kernel/include/los_builddef.h b/src/kernel/include/los_builddef.h index 894fd80..192d90a 100644 --- a/src/kernel/include/los_builddef.h +++ b/src/kernel/include/los_builddef.h @@ -35,79 +35,79 @@ extern "C" { #endif /* __cplusplus */ #endif /* __cplusplus */ -#define OS_LITTLE_ENDIAN 0x1234 /* Little endian */ -#define OS_BIG_ENDIAN 0x4321 /* Big endian */ +#define OS_LITTLE_ENDIAN 0x1234 /* Little endian *///ʾСֵΪ 0x1234 +#define OS_BIG_ENDIAN 0x4321 /* Big endian *///ʾֵΪ 0x4321 #ifndef OS_BYTE_ORDER -#define OS_BYTE_ORDER OS_LITTLE_ENDIAN +#define OS_BYTE_ORDER OS_LITTLE_ENDIAN//δ OS_BYTE_ORDERΪ OS_LITTLE_ENDIAN #endif /* Define OS code data sections */ /* The indicator function is inline */ #ifndef LITE_OS_SEC_ALW_INLINE -#define LITE_OS_SEC_ALW_INLINE /* __attribute__((always_inline)) */ +#define LITE_OS_SEC_ALW_INLINE /* __attribute__((always_inline)) *///һ꣬ڽΪ #endif #ifndef LITE_OS_SEC_TEXT -#define LITE_OS_SEC_TEXT /* __attribute__((section(".text.sram"))) */ +#define LITE_OS_SEC_TEXT /* __attribute__((section(".text.sram"))) *///һ꣬ڽη .text.sram #endif #ifndef LITE_OS_SEC_TEXT_MINOR -#define LITE_OS_SEC_TEXT_MINOR /* __attribute__((section(".text.ddr"))) */ +#define LITE_OS_SEC_TEXT_MINOR /* __attribute__((section(".text.ddr"))) *///һ꣬ڽη .text.ddr #endif #ifndef LITE_OS_SEC_TEXT_INIT -#define LITE_OS_SEC_TEXT_INIT /* __attribute__((section(".text.init"))) */ +#define LITE_OS_SEC_TEXT_INIT /* __attribute__((section(".text.init"))) *///궨һΣڷóʼ룬λ .text.init С #endif #ifndef LITE_OS_SEC_DATA -#define LITE_OS_SEC_DATA /* __attribute__((section(".data.sram"))) */ +#define LITE_OS_SEC_DATA /* __attribute__((section(".data.sram"))) *///궨һݶΣڷݣλ .data.sram С #endif #ifndef LITE_OS_SEC_DATA_MINOR -#define LITE_OS_SEC_DATA_MINOR /* __attribute__((section(".data.ddr"))) */ +#define LITE_OS_SEC_DATA_MINOR /* __attribute__((section(".data.ddr"))) *///һҪݶΣڷôҪݣλ .data.ddr С #endif #ifndef LITE_OS_SEC_DATA_INIT -#define LITE_OS_SEC_DATA_INIT /* __attribute__((section(".data.init"))) */ +#define LITE_OS_SEC_DATA_INIT /* __attribute__((section(".data.init"))) *///궨һݶΣڷóʼݣλ .data.init С #endif #ifndef LITE_OS_SEC_DATA_VEC -#define LITE_OS_SEC_DATA_VEC __attribute__((section(".data.vector"))) +#define LITE_OS_SEC_DATA_VEC __attribute__((section(".data.vector")))//궨һݶΣڷݣλ .data.vector С #endif #ifndef LITE_OS_SEC_BSS -#define LITE_OS_SEC_BSS /* __attribute__((section(".bss.sram"))) */ +#define LITE_OS_SEC_BSS /* __attribute__((section(".bss.sram"))) *///궨һݶΣڷδʼݣBSSΣλ .bss.sram С #endif #ifndef LITE_OS_SEC_BSS_MINOR -#define LITE_OS_SEC_BSS_MINOR /* __attribute__((section(".bss.ddr"))) */ +#define LITE_OS_SEC_BSS_MINOR /* __attribute__((section(".bss.ddr"))) */// 궨һݶΣڷδʼĴҪݣBSSΣλ .bss.ddr С #endif #ifndef LITE_OS_SEC_BSS_INIT -#define LITE_OS_SEC_BSS_INIT /* __attribute__((section(".bss.init"))) */ +#define LITE_OS_SEC_BSS_INIT /* __attribute__((section(".bss.init"))) *///궨һݶΣڷδʼijʼݣBSSΣλ .bss.init С #endif #ifndef LITE_OS_SEC_ITCM -#define LITE_OS_SEC_ITCM /* __attribute__((section(".itcm "))) */ +#define LITE_OS_SEC_ITCM /* __attribute__((section(".itcm "))) */// 궨һΣڷô루ָֻݣ ITCM С ITCM ڴͬλ CPU ڲиٷʺ͵ӳٵơ #endif #ifndef LITE_OS_SEC_DTCM -#define LITE_OS_SEC_DTCM /* __attribute__((section(".dtcm"))) */ +#define LITE_OS_SEC_DTCM /* __attribute__((section(".dtcm"))) *///궨һݶΣڷݣλ DTCM С DTCM ڴͬλ CPU ڲиٷʺ͵ӳٵơ #endif -#define PACK1 +#define PACK1//궨һṹԱĶ뷽ʽṹijԱܵشһ𣬲ʹÿռ롣 #ifndef LITE_OS_ATTR_SEC -#define LITE_OS_ATTR_SEC(name) __attribute__((section(#name))) +#define LITE_OS_ATTR_SEC(name) __attribute__((section(#name)))//궨һڵĶΣͨ #name name תΪַõָƵĶС #endif #ifndef LITE_OS_ATTR_ALIGN -#define LITE_OS_ATTR_ALIGN(x) __attribute__((aligned(x))) +#define LITE_OS_ATTR_ALIGN(x) __attribute__((aligned(x)))//궨ݵĶ뷽ʽֽڶ룬x ʾֽ #endif #ifndef LITE_OS_ATTR_SEC_ALIGN -#define LITE_OS_ATTR_SEC_ALIGN(name, x) __attribute__((section(#name), aligned(x))) +#define LITE_OS_ATTR_SEC_ALIGN(name, x) __attribute__((section(#name), aligned(x)))//궨ijݵĶ뷽ʽݷõָƵĶУָĶ뷽ʽ롣 #endif #ifndef OS_EMBED_ASM -#define OS_EMBED_ASM __asm__ __volatile__ +#define OS_EMBED_ASM __asm__ __volatile__//궨Ƕָķʽ asm volatile ΪǶָǰ׺ʹñԽʶΪָ #endif #ifdef __cplusplus diff --git a/src/kernel/include/los_config.h b/src/kernel/include/los_config.h index 75b9ea0..bd14843 100644 --- a/src/kernel/include/los_config.h +++ b/src/kernel/include/los_config.h @@ -30,6 +30,22 @@ * @defgroup los_config System configuration items * @ingroup kernel */ +/*ԣlos_config.h ļͨݣ + +TaskãԶȼΧջСȲ㲻ͬӦó + +жϣInterruptãԶжϷ̵ȼΧԼжϴIJԵȡ + +ڴMemory ManagementãԶ嶯̬ڴ㷨ڴصĴСز + +ʱTimerãԶ嶨ʱȡʽȡ + +ȣTask Schedulingã㷨ʱƬתʱȡ + +ϵͳʱӣSystem ClockãԶϵͳʱӵƵʡʱʱԴȡ + +ͨ޸ los_config.h ļеĺ궨ȫֱԱԸӦԲϵͳжƺŻ +Ȼ󣬽޸ĺ los_config.h ļ LiteOS ںˣʵֶԲϵͳΪ͹ܵĶƻá*/ #ifndef _LOS_CONFIG_H #define _LOS_CONFIG_H @@ -45,53 +61,53 @@ extern "C" { #endif /* __cplusplus */ #endif /* __cplusplus */ -#ifdef LOSCFG_LIB_CONFIGURABLE -extern UINT32 g_osSysClock; -extern UINT32 g_tickPerSecond; -extern UINT32 g_taskLimit; -extern UINT32 g_taskMinStkSize; -extern UINT32 g_taskIdleStkSize; -extern UINT32 g_taskDfltStkSize; -extern UINT32 g_taskSwtmrStkSize; -extern UINT32 g_swtmrLimit; -extern UINT32 g_semLimit; -extern UINT32 g_muxLimit; -extern UINT32 g_queueLimit; -extern UINT32 g_timeSliceTimeOut; - -extern BOOL g_nxEnabled; -extern UINTPTR g_dlNxHeapBase; -extern UINT32 g_dlNxHeapSize; - -#define LOS_GET_NX_CFG() (g_nxEnabled) -#define LOS_SET_NX_CFG(value) (g_nxEnabled = (value)) -#define LOS_GET_DL_NX_HEAP_BASE() (g_dlNxHeapBase) -#define LOS_SET_DL_NX_HEAP_BASE(addr) (g_dlNxHeapBase = (addr)) -#define LOS_GET_DL_NX_HEAP_SIZE() (g_dlNxHeapSize) -#define LOS_SET_DL_NX_HEAP_SIZE(size) (g_dlNxHeapSize = (size)) - -#define OS_SYS_CLOCK g_osSysClock -#define KERNEL_TICK_PER_SECOND g_tickPerSecond -#define KERNEL_TSK_LIMIT g_taskLimit -#define KERNEL_TSK_MIN_STACK_SIZE g_taskMinStkSize -#define KERNEL_TSK_DEFAULT_STACK_SIZE g_taskDfltStkSize -#define KERNEL_TSK_IDLE_STACK_SIZE g_taskIdleStkSize -#define KERNEL_TSK_SWTMR_STACK_SIZE g_taskSwtmrStkSize -#define KERNEL_SWTMR_LIMIT g_swtmrLimit -#define KERNEL_SEM_LIMIT g_semLimit -#define KERNEL_MUX_LIMIT g_muxLimit -#define KERNEL_QUEUE_LIMIT g_queueLimit -#define KERNEL_TIMESLICE_TIMEOUT g_timeSliceTimeOut +#ifdef LOSCFG_LIB_CONFIGURABLE//жϺ궨 LOSCFG_LIB_CONFIGURABLE Ƿ񱻶塣ú걻壬ô±ᱻС +extern UINT32 g_osSysClock;//ϵͳʱƵ +extern UINT32 g_tickPerSecond;//ϵͳʱӵδ +extern UINT32 g_taskLimit;// +extern UINT32 g_taskMinStkSize;//СջС +extern UINT32 g_taskIdleStkSize;//ջС +extern UINT32 g_taskDfltStkSize;//ĬջС +extern UINT32 g_taskSwtmrStkSize;//ʱջС +extern UINT32 g_swtmrLimit;//ʱ +extern UINT32 g_semLimit;//ź +extern UINT32 g_muxLimit;//󻥳 +extern UINT32 g_queueLimit;// +extern UINT32 g_timeSliceTimeOut;//ʱƬתʱ + +extern BOOL g_nxEnabled;//Ƿڴ汣 +extern UINTPTR g_dlNxHeapBase;//ڴ汣Ƶʼַ +extern UINT32 g_dlNxHeapSize;//ڴ汣ƵĴС + +#define LOS_GET_NX_CFG() (g_nxEnabled)//ڻȡһΪg_nxEnabledıֵ +#define LOS_SET_NX_CFG(value) (g_nxEnabled = (value))//һΪg_nxEnabledıֵ +#define LOS_GET_DL_NX_HEAP_BASE() (g_dlNxHeapBase)//ڻȡһΪg_dlNxHeapBaseıֵ +#define LOS_SET_DL_NX_HEAP_BASE(addr) (g_dlNxHeapBase = (addr))//һΪg_dlNxHeapBaseıֵ +#define LOS_GET_DL_NX_HEAP_SIZE() (g_dlNxHeapSize)//ڻȡһΪg_dlNxHeapSizeıֵ +#define LOS_SET_DL_NX_HEAP_SIZE(size) (g_dlNxHeapSize = (size))//һΪg_dlNxHeapSizeıֵ + +#define OS_SYS_CLOCK g_osSysClock//ϵͳʱƵ +#define KERNEL_TICK_PER_SECOND g_tickPerSecond//ϵͳʱδ +#define KERNEL_TSK_LIMIT g_taskLimit// +#define KERNEL_TSK_MIN_STACK_SIZE g_taskMinStkSize//СջС +#define KERNEL_TSK_DEFAULT_STACK_SIZE g_taskDfltStkSize//ĬջС +#define KERNEL_TSK_IDLE_STACK_SIZE g_taskIdleStkSize//ĬջС +#define KERNEL_TSK_SWTMR_STACK_SIZE g_taskSwtmrStkSize//ʱջС +#define KERNEL_SWTMR_LIMIT g_swtmrLimit//ʱ +#define KERNEL_SEM_LIMIT g_semLimit//ź +#define KERNEL_MUX_LIMIT g_muxLimit//󻥳 +#define KERNEL_QUEUE_LIMIT g_queueLimit// +#define KERNEL_TIMESLICE_TIMEOUT g_timeSliceTimeOut//ʱƬתʱ #else /* LOSCFG_LIB_CONFIGURABLE */ #ifdef LOSCFG_KERNEL_NX -#define LOS_GET_NX_CFG() true -#define LOS_SET_NX_CFG(value) -#define LOS_GET_DL_NX_HEAP_BASE() LOS_DL_HEAP_BASE -#define LOS_SET_DL_NX_HEAP_BASE(addr) -#define LOS_GET_DL_NX_HEAP_SIZE() LOS_DL_HEAP_SIZE -#define LOS_SET_DL_NX_HEAP_SIZE(size) +#define LOS_GET_NX_CFG() true//ȡڴ汣Ƿֵ LOSCFG_KERNEL_NX 걻ʱ true򷵻 false +#define LOS_SET_NX_CFG(value)//ڴ汣Ƶֵú궨Ϊհףûʵʲ +#define LOS_GET_DL_NX_HEAP_BASE() LOS_DL_HEAP_BASE//ȡڴ汣Ƶʼַ LOSCFG_KERNEL_NX 걻ʱ LOS_DL_HEAP_BASE򷵻 NULL +#define LOS_SET_DL_NX_HEAP_BASE(addr)//ڴ汣Ƶʼַú궨Ϊհףûʵʲ +#define LOS_GET_DL_NX_HEAP_SIZE() LOS_DL_HEAP_SIZE//ȡڴ汣ƵĴС LOSCFG_KERNEL_NX 걻ʱ LOS_DL_HEAP_SIZE򷵻 0 +#define LOS_SET_DL_NX_HEAP_SIZE(size)//ڴ汣ƵĴСú궨Ϊհףûʵʲ #else /* LOSCFG_KERNEL_NX */ #define LOS_GET_NX_CFG() false #define LOS_SET_NX_CFG(value) @@ -101,7 +117,9 @@ extern UINT32 g_dlNxHeapSize; #define LOS_SET_DL_NX_HEAP_SIZE(size) #endif /* LOSCFG_KERNEL_NX */ -#define KERNEL_TICK_PER_SECOND LOSCFG_BASE_CORE_TICK_PER_SECOND +//δһϵк궨壬ڽһЩòӳ䵽Ӧĺ궨塣 +//Ŀǽòʹ޸òʱֻҪ޸Ӧĺ궨壬޸øòĴ롣ߴĿάԺͿֲԡ +#define KERNEL_TICK_PER_SECOND LOSCFG_BASE_CORE_TICK_PER_SECOND//KERNEL_TICK_PER_SECOND궨ΪLOSCFG_BASE_CORE_TICK_PER_SECONDζڴʹKERNEL_TICK_PER_SECONDʱʵʹò #define KERNEL_TSK_LIMIT LOSCFG_BASE_CORE_TSK_LIMIT #define KERNEL_TSK_MIN_STACK_SIZE LOSCFG_BASE_CORE_TSK_MIN_STACK_SIZE #define KERNEL_TSK_DEFAULT_STACK_SIZE LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE @@ -112,27 +130,27 @@ extern UINT32 g_dlNxHeapSize; #define KERNEL_MUX_LIMIT LOSCFG_BASE_IPC_MUX_LIMIT #define KERNEL_QUEUE_LIMIT LOSCFG_BASE_IPC_QUEUE_LIMIT #define KERNEL_TIMESLICE_TIMEOUT LOSCFG_BASE_CORE_TIMESLICE_TIMEOUT - +//#endif /* LOSCFG_LIB_CONFIGURABLE */ʾ궨ĽLOSCFG_LIB_CONFIGURABLEʱ궨岻ãΪ¶ġ #endif /* LOSCFG_LIB_CONFIGURABLE */ /** * system sections start and end address */ -extern CHAR __int_stack_start; -extern CHAR __int_stack_end; -extern CHAR __rodata_start; -extern CHAR __rodata_end; -extern CHAR __bss_start; -extern CHAR __bss_end; -extern CHAR __text_start; -extern CHAR __text_end; -extern CHAR __ram_data_start; -extern CHAR __ram_data_end; -extern CHAR __exc_heap_start; -extern CHAR __exc_heap_end; -extern CHAR __heap_start; -extern CHAR __init_array_start__; -extern CHAR __init_array_end__; +extern CHAR __int_stack_start;//ڲջʼַ +extern CHAR __int_stack_end;//ڲջĽַ +extern CHAR __rodata_start;//ֻݶεʼַ +extern CHAR __rodata_end;//ֻݶεĽַ +extern CHAR __bss_start;//δʼȫֱΣBSS Segmentʼַ +extern CHAR __bss_end;//δʼȫֱΣBSS SegmentĽַ +extern CHAR __text_start;//ִдΣText Segmentʼַ +extern CHAR __text_end;//ִдΣText SegmentĽַ +extern CHAR __ram_data_start;//RAM ݶεʼַ +extern CHAR __ram_data_end;//RAM ݶεĽַ +extern CHAR __exc_heap_start;//쳣ѣException Heapʼַ +extern CHAR __exc_heap_end;//쳣ѣException HeapĽַ +extern CHAR __heap_start;//ѣHeapʼַ +extern CHAR __init_array_start__;//ʼʼַ +extern CHAR __init_array_end__; //ʼĽַ /****************************** System clock module configuration ****************************/ /** @@ -140,24 +158,24 @@ extern CHAR __init_array_end__; * System clock (unit: HZ) */ #ifndef OS_SYS_CLOCK -#define OS_SYS_CLOCK (get_bus_clk()) +#define OS_SYS_CLOCK (get_bus_clk())//ϵͳʱƵʣĬֵΪget_bus_clk() #endif /** * @ingroup los_config * time timer clock (unit: HZ) */ #ifndef OS_TIME_TIMER_CLOCK -#define OS_TIME_TIMER_CLOCK OS_SYS_CLOCK +#define OS_TIME_TIMER_CLOCK OS_SYS_CLOCK//嶨ʱʱƵʣĬֵΪ OS_SYS_CLOCK #endif /** * limit addr range when search for 'func local(frame pointer)' or 'func name' */ #ifndef OS_SYS_FUNC_ADDR_START -#define OS_SYS_FUNC_ADDR_START ((UINTPTR)&__int_stack_start) +#define OS_SYS_FUNC_ADDR_START ((UINTPTR)&__int_stack_start)//庯ʼַĬֵΪ&__int_stack_start #endif #ifndef OS_SYS_FUNC_ADDR_END -#define OS_SYS_FUNC_ADDR_END g_sys_mem_addr_end +#define OS_SYS_FUNC_ADDR_END g_sys_mem_addr_end//庯ַֹĬֵΪg_sys_mem_addr_end #endif /** @@ -165,14 +183,14 @@ extern CHAR __init_array_end__; * Microseconds of adjtime in one second */ #ifndef LOSCFG_BASE_CORE_ADJ_PER_SECOND -#define LOSCFG_BASE_CORE_ADJ_PER_SECOND 500 +#define LOSCFG_BASE_CORE_ADJ_PER_SECOND 500//ÿӵ΢ʱ䡣ûжLOSCFG_BASE_CORE_ADJ_PER_SECOND䶨Ϊ500ζϵͳڽʱ΢ʱÿӿ΢500΢롣 #endif /** * @ingroup los_config * Sched clck interval */ -#define SCHED_CLOCK_INTETRVAL_TICKS 100 +#define SCHED_CLOCK_INTETRVAL_TICKS 100//ʾʱӵļ궨ֵΪ100ʾʱӵļΪ100ʱӽġ /****************************** Interrupt module configuration ****************************/ /** @@ -184,7 +202,7 @@ extern CHAR __init_array_end__; */ #ifdef LOSCFG_ARCH_INTERRUPT_PREEMPTION #ifndef MAX_BINARY_POINT_VALUE -#define MAX_BINARY_POINT_VALUE 4 +#define MAX_BINARY_POINT_VALUE 4//ʹǷѾMAX_BINARY_POINT_VALUEꡣûж壬䶨Ϊ4 #endif #endif @@ -197,6 +215,11 @@ extern CHAR __init_array_end__; * 0xFFFF: max number of all software timers */ #ifndef OS_SWTMR_MAX_TIMERID +/*ʾʱID +ĬֵΪ((0xFFFF / KERNEL_SWTMR_LIMIT) * KERNEL_SWTMR_LIMIT) +KERNEL_SWTMR_LIMITʾϵͳÿԴʱ +궨ǽõIDһʱΧڣ +ԸõIDԴ*/ #define OS_SWTMR_MAX_TIMERID ((0xFFFF / KERNEL_SWTMR_LIMIT) * KERNEL_SWTMR_LIMIT) #endif /** @@ -204,6 +227,11 @@ extern CHAR __init_array_end__; * Maximum size of a software timer queue. The default value of LOSCFG_BASE_CORE_SWTMR_LIMIT is 16. */ #ifndef OS_SWTMR_HANDLE_QUEUE_SIZE +/*ʾʱеС +ĬֵΪKERNEL_SWTMR_LIMIT +Ҳϵͳÿͬʱʱ +궨ܹʱ +ԱԴ˷Ѻ⡣*/ #define OS_SWTMR_HANDLE_QUEUE_SIZE KERNEL_SWTMR_LIMIT #endif #endif @@ -214,6 +242,10 @@ extern CHAR __init_array_end__; * Starting address of the system memory */ #ifndef OS_SYS_MEM_ADDR +/*__heap_startӽűжķţ +ʾڴصʼַ +ˣOS_SYS_MEM_ADDRֵڴصʼַָ룬 +ͨúϵͳڴء*/ #define OS_SYS_MEM_ADDR (&__heap_start) #endif @@ -223,9 +255,11 @@ extern CHAR __init_array_end__; * Starting address of dynload heap */ #if defined (LOSCFG_KERNEL_NX) && defined (LOSCFG_KERNEL_DYNLOAD) -#define LOS_DL_HEAP_SIZE (LOSCFG_KERNLE_DYN_HEAPSIZE * 0x100000) -#define LOS_DL_HEAP_BASE (SYS_MEM_END - LOS_DL_HEAP_SIZE) +//궼ˣô̬ģѵĴСΪ +#define LOS_DL_HEAP_SIZE (LOSCFG_KERNLE_DYN_HEAPSIZE * 0x100000)//(LOSCFG_KERNLE_DYN_HEAPSIZE * 0x100000) +#define LOS_DL_HEAP_BASE (SYS_MEM_END - LOS_DL_HEAP_SIZE)//SYS_MEM_END - LOS_DL_HEAP_SIZESYS_MEM_ENDʾϵͳڴصĽַ #else +//ûжLOSCFG_KERNEL_NXLOSCFG_KERNEL_DYNLOAD꣬򽫶̬ģѵĴСʼַΪ0 #define LOS_DL_HEAP_SIZE 0 #define LOS_DL_HEAP_BASE 0 #endif @@ -236,7 +270,7 @@ extern CHAR __init_array_end__; */ #ifndef OS_SYS_MEM_SIZE #define OS_SYS_MEM_SIZE ((g_sys_mem_addr_end) - \ - ((LOS_DL_HEAP_SIZE + ((UINTPTR)&__heap_start) + (64 - 1)) & ~(64 - 1))) + ((LOS_DL_HEAP_SIZE + ((UINTPTR)&__heap_start) + (64 - 1)) & ~(64 - 1)))//ڴصĴС #endif /****************************** fw Interface configuration **************************/ @@ -245,11 +279,12 @@ extern CHAR __init_array_end__; * The core number is one in non-SMP architecture. */ #ifdef LOSCFG_KERNEL_SMP +//LOSCFG_KERNEL_CORE_NUM Ϊ LOSCFG_KERNEL_SMP_CORE_NUM ֵLOSCFG_KERNEL_CORE_NUM Ϊ 1 #define LOSCFG_KERNEL_CORE_NUM LOSCFG_KERNEL_SMP_CORE_NUM #else #define LOSCFG_KERNEL_CORE_NUM 1 #endif - +//LOSCFG_KERNEL_CPU_MASK Ϊڱʾ CPU ıʽʹλ㣬ͨ 1 LOSCFG_KERNEL_CORE_NUM λȻȥ 1һ LOSCFG_KERNEL_CORE_NUM 1 Ķͨ CPU ׺ԣȷ߳̿Щ CPU ϡ #define LOSCFG_KERNEL_CPU_MASK ((1 << LOSCFG_KERNEL_CORE_NUM) - 1) /****************************** trace module configuration **************************/ @@ -259,6 +294,10 @@ extern CHAR __init_array_end__; */ #ifdef LOSCFG_KERNEL_TRACE #ifdef LOSCFG_RECORDER_MODE_OFFLINE +/*LOSCFG_KERNEL_TRACE £ôᱻ롣 +ͬʱ LOSCFG_RECORDER_MODE_OFFLINE + LOSTRACE_BUFFER_SIZE ᱻΪ LOSCFG_TRACE_BUFFER_SIZE ֵ +LOSTRACE_BUFFER_SIZE ᱻΪ 0*/ #define LOS_TRACE_BUFFER_SIZE LOSCFG_TRACE_BUFFER_SIZE #else #define LOS_TRACE_BUFFER_SIZE 0 @@ -277,39 +316,44 @@ extern CHAR __init_array_end__; /** * Version number */ -#define _T(x) x -#define HW_LITEOS_SYSNAME "Huawei LiteOS" -#define HW_LITEOS_SEP " " -#define _V(v) _T(HW_LITEOS_SYSNAME)_T(HW_LITEOS_SEP)_T(v) +//δһ궨壬ڶϵͳİ汾źϵͳơ +#define _T(x) x//궨彫IJ x ԭأں궨бʾַ +#define HW_LITEOS_SYSNAME "Huawei LiteOS"//궨Ϊַ "Huawei LiteOS"ʾϵͳơ +#define HW_LITEOS_SEP " "//궨Ϊַ " "ʾƺͰ汾֮ķָ +#define _V(v) _T(HW_LITEOS_SYSNAME)_T(HW_LITEOS_SEP)_T(v)//궨ͨϵͳƺͰ汾һİ汾ַ -#define HW_LITEOS_VERSION "V200R005C20B053" -#define HW_LITEOS_VER _V(HW_LITEOS_VERSION"-SMP") +#define HW_LITEOS_VERSION "V200R005C20B053"//궨Ϊַ "V200R005C20B053"ʾϵͳľ汾š +#define HW_LITEOS_VER _V(HW_LITEOS_VERSION"-SMP")//궨ʹ _V ꣬ϵͳƺͰ汾γ "Huawei LiteOS V200R005C20B053-SMP" 汾ַ /** * The Version number of Public */ -#define MAJ_V 5 -#define MIN_V 1 -#define REL_V 0 +#define MAJ_V 5//궨Ϊ 5ʾϵͳҪ汾š +#define MIN_V 1//궨Ϊ 1ʾϵͳĴҪ汾š +#define REL_V 0//궨Ϊ 0ʾϵͳķ汾š /** * The release candidate version number */ -#define EXTRA_V 0 +//Щ궨ͺڹϵͳİ汾ţṩһֽ汾תΪַʽĻơ +#define EXTRA_V 0//궨Ϊ 0ʾϵͳĶ汾Żѡ汾š -#define VERSION_NUM(a, b, c) (((a) << 16) | ((b) << 8) | (c)) -#define HW_LITEOS_OPEN_VERSION_NUM VERSION_NUM(MAJ_V, MIN_V, REL_V) +#define VERSION_NUM(a, b, c) (((a) << 16) | ((b) << 8) | (c))//궨彫汾 aΰ汾 b ͷ汾 c ϳһ޷ͨλʵ֡ +#define HW_LITEOS_OPEN_VERSION_NUM VERSION_NUM(MAJ_V, MIN_V, REL_V)// 궨ʹ VERSION_NUM ꣬汾šΰ汾źͷ汾һʾ汾ŵ޷ -#define STRINGIFY_1(x) #x -#define STRINGIFY(x) STRINGIFY_1(x) +#define STRINGIFY_1(x) #x//궨彫 x תΪַ +#define STRINGIFY(x) STRINGIFY_1(x)//궨 STRINGIFY_1 ꣬תΪַ -#define HW_LITEOS_OPEN_VERSION_STRING STRINGIFY(MAJ_V) "." STRINGIFY(MIN_V) "." STRINGIFY(REL_V) +#define HW_LITEOS_OPEN_VERSION_STRING STRINGIFY(MAJ_V) "." STRINGIFY(MIN_V) "." STRINGIFY(REL_V)//궨ʹ STRINGIFY ꣬汾šΰ汾źͷ汾תΪ "5.1.0" ַʽ #if (EXTRA_V != 0) +/* 0 HW_LITEOS_KERNEL_VERSION_STRING 궨Ϊкѡ汾ŵİ汾ַ +Ϊѡ汾ŵİ汾ַ*/ #define HW_LITEOS_KERNEL_VERSION_STRING HW_LITEOS_OPEN_VERSION_STRING "-rc" STRINGIFY(EXTRA_V) #else #define HW_LITEOS_KERNEL_VERSION_STRING HW_LITEOS_OPEN_VERSION_STRING #endif +// 0 HW_LITEOS_KERNEL_VERSION_STRING 궨Ϊкѡ汾ŵİ汾ַΪѡ汾ŵİ汾ַ extern VOID OsStart(VOID); extern UINT32 OsMain(VOID); extern VOID *OsGetMainTask(VOID); diff --git a/src/kernel/include/los_cppsupport.h b/src/kernel/include/los_cppsupport.h index cdf3fd4..c02d5e4 100644 --- a/src/kernel/include/los_cppsupport.h +++ b/src/kernel/include/los_cppsupport.h @@ -47,6 +47,8 @@ extern "C" { * If LOS_CppSystemInit() is called in the first stage of scatter load, * this flag should be passed as the third parameter. */ +/*ɢصĵһ׶ε LOS_CppSystemInit +˱־ӦΪݡ*/ #define BEFORE_SCATTER 0 /** @@ -54,6 +56,8 @@ extern "C" { * If LOS_CppSystemInit() is called in the second stage of scatter load, * this flag should be passed as the third parameter. */ +/*ɢصĵڶ׶ε LOS_CppSystemInit +˱־ӦΪݡ*/ #define AFTER_SCATTER 1 /** @@ -61,6 +65,8 @@ extern "C" { * If scatter load is disabled, this flag should be passed as the third * parameter when LOS_CppSystemInit() is called. */ +/*˷ɢأڵ LOS_CppSystemInit ʱ +Ӧ˱־Ϊݡ*/ #define NO_SCATTER 2 /** @@ -87,6 +93,16 @@ extern "C" { * * @since Huawei LiteOS V100R001C00 */ +//ʼϵͳC++лĺ +/*˵LOS_CppSystemInitҪ +ȫ־̬Ĺ캯C++У +ȫ־̬Ĺ캯Ҫڳʼǰá +LOS_CppSystemInitȫ־̬б +εǵĹ캯 +ִC++ʱijʼ +ȫ־̬Ĺ캯֮⣬ +ҪִC++ʱصijʼ +磬ԳʼC++쳣ơ̬ڴȡ*/ extern INT32 LOS_CppSystemInit(UINTPTR initArrayStart, UINTPTR initArrayEnd, INT32 flag); #ifdef __cplusplus diff --git a/src/kernel/include/los_cpup.h b/src/kernel/include/los_cpup.h index 3591a26..690cea4 100644 --- a/src/kernel/include/los_cpup.h +++ b/src/kernel/include/los_cpup.h @@ -53,6 +53,9 @@ extern "C" { * * Solution: Decrease the maximum number of tasks. */ +/* CPUģзڴ治Ĵ +ҾĴ LOS_ERRNO_OS_ERROR ģIDLOS_MOD_CPUPʹ루0x00ɵġ +ԱڳбʶʹضĴ*/ #define LOS_ERRNO_CPUP_NO_MEMORY LOS_ERRNO_OS_ERROR(LOS_MOD_CPUP, 0x00) /** @@ -63,6 +66,9 @@ extern "C" { * * Solution: Check whether the pointer to the input parameter is usable. */ +/* CPUģз˿ָ +ҾĴ LOS_ERRNO_OS_ERROR ģIDLOS_MOD_CPUPʹ루0x01ɵġ +ԱڳбʶʹضĴ*/ #define LOS_ERRNO_CPUP_TASK_PTR_NULL LOS_ERRNO_OS_ERROR(LOS_MOD_CPUP, 0x01) /** @@ -73,6 +79,9 @@ extern "C" { * * Solution: Check whether the CPU usage is initialized. */ +/* CPUģзδʼĴ +Ĵ LOS_ERRNO_OS_ERROR ģIDLOS_MOD_CPUPʹ루0x02ɵġ +ԱڳбʶʹضĴ*/ #define LOS_ERRNO_CPUP_NO_INIT LOS_ERRNO_OS_ERROR(LOS_MOD_CPUP, 0x02) /** @@ -83,6 +92,9 @@ extern "C" { * * Solution: Check whether the number of threads is applicable for the current operation. */ +/* CPUģзЧ +Ĵ LOS_ERRNO_OS_ERROR ģIDLOS_MOD_CPUPʹ루0x03ɵġ +ԱڳбʶʹضĴ*/ #define LOS_ERRNO_CPUP_MAXNUM_INVALID LOS_ERRNO_OS_ERROR(LOS_MOD_CPUP, 0x03) /** @@ -93,6 +105,9 @@ extern "C" { * * Solution: Check whether the target thread is created. */ +/* CPUģз߳δĴ +Ĵ LOS_ERRNO_OS_ERROR ģIDLOS_MOD_CPUPʹ루0x04ɵġ +ԱڳбʶʹضĴ*/ #define LOS_ERRNO_CPUP_THREAD_NO_CREATED LOS_ERRNO_OS_ERROR(LOS_MOD_CPUP, 0x04) /** @@ -103,12 +118,22 @@ extern "C" { * * Solution: Check whether the target task ID is applicable for the current operation. */ +/*CPUģзЧID +Ĵ LOS_ERRNO_OS_ERROR ģIDLOS_MOD_CPUPʹ루0x05ɵġ +ԱڳбʶʹضĴ*/ #define LOS_ERRNO_CPUP_TSK_ID_INVALID LOS_ERRNO_OS_ERROR(LOS_MOD_CPUP, 0x05) /** * @ingroup los_cpup * The structure of the CPU usage information of all tasks. */ +/*CPUϢ +ṹԱ +usStatusʾ״̬һ 16 λ޷ +uwUsageʾ CPU ʹʣһ 32 λ޷λΪ permillageǧ֮һ +ڲϵͳУCPU ḺϵͳиִС +CPUP_INFO_S ṹṩһַʽ +԰˽״̬ϵͳ CPU ʹϢ*/ typedef struct tagCpupInfo { UINT16 usStatus; /**< The task status. */ UINT32 uwUsage; /**< CPU usage of all tasks. It is a permillage. And the value range is [0,1000]. */ @@ -118,9 +143,13 @@ typedef struct tagCpupInfo { * @ingroup los_cpup * The time period which the CPU usage collects in. */ +//ڱʾ CPU ʹʵʱ䷶Χ enum { + //ʾʾ 10 ӵ CPU ʹʣֵΪ0 CPUP_LAST_TEN_SECONDS = 0, /**< Display CPU usage in the last ten seconds, the value is 0. */ + //ʾʾ 1 ӵ CPU ʹʣֵΪ1 CPUP_LAST_ONE_SECONDS = 1, /**< Display CPU usage in the last one second, the value is 1. */ + //ʾʾϵͳڵ CPU ʹʣֵΪ 0xffff CPUP_ALL_TIME = 0xffff /**< Display CPU usage from system startup to now, the value is 0xffff. */ }; @@ -149,6 +178,7 @@ enum { * @see LOS_HistoryTaskCpuUsage | LOS_AllCpuUsage * @since Huawei LiteOS V100R001C00 */ +//ȡʷϵͳCPUʹʡ mode ָȡ CPU ʹʵʱ䷶Χá extern UINT32 LOS_HistorySysCpuUsage(UINT32 mode); /** @@ -182,6 +212,9 @@ extern UINT32 LOS_HistorySysCpuUsage(UINT32 mode); * @see LOS_HistorySysCpuUsage * @since Huawei LiteOS V100R001C00 */ +/*ڻȡʷCPUʹʡ + taskId ʾIDʶ +mode ܱʾȡCPUʹʵģʽѡ*/ extern UINT32 LOS_HistoryTaskCpuUsage(UINT32 taskId, UINT32 mode); /** @@ -224,6 +257,10 @@ extern UINT32 LOS_HistoryTaskCpuUsage(UINT32 taskId, UINT32 mode); * * @since Huawei LiteOS V100R001C00 */ +/*ڻȡϵͳCPUʹϢ + maxNum ʾCPUcpupInfo ʾڴ洢CPUʹϢĽṹָ룬 +mode ܱʾȡCPUʹʵģʽѡ +flag ܱʾĿƱ־λ*/ extern UINT32 LOS_AllCpuUsage(UINT16 maxNum, CPUP_INFO_S *cpupInfo, UINT32 mode, UINT16 flag); /** @@ -244,6 +281,10 @@ extern UINT32 LOS_AllCpuUsage(UINT16 maxNum, CPUP_INFO_S *cpupInfo, UINT32 mode, * * @since Huawei LiteOS V100R001C00 */ +/*LOS_CpupReset ϵͳжϣ +ǵ CPU ʹͳϢ㡣 +һжִʱ +ϵͳͻ¿ʼ¼ǵ CPU ʹʡ*/ extern VOID LOS_CpupReset(VOID); #ifdef __cplusplus diff --git a/src/kernel/include/los_err.h b/src/kernel/include/los_err.h index ff84c03..ef1f1dc 100644 --- a/src/kernel/include/los_err.h +++ b/src/kernel/include/los_err.h @@ -62,11 +62,12 @@ extern "C" { * * @since Huawei LiteOS V100R001C00 */ -typedef VOID (*LOS_ERRORHANDLE_FUNC)(CHAR *fileName, - UINT32 lineNo, - UINT32 errorNo, - UINT32 paraLen, - VOID *para); +//LOS_ERRORHANDLE_FUNC һָָͣһú +typedef VOID (*LOS_ERRORHANDLE_FUNC)(CHAR *fileName,//ʾļ + UINT32 lineNo,//ʾкš + UINT32 errorNo,//ʾš + UINT32 paraLen,//ʾӲijȡ + VOID *para);//ʾӲָ롣 /** * @ingroup los_err @@ -88,6 +89,15 @@ typedef VOID (*LOS_ERRORHANDLE_FUNC)(CHAR *fileName, * * @since Huawei LiteOS V100R001C00 */ +/*Ǵ󡣵йзʱ +Եд¼Ϣ־Ȳ +IJڶλľϢ +ӶõؽдŲ顣 +CHAR *fileNameʾļ +UINT32 lineNoʾкš +UINT32 errorNoʾ͡ +UINT32 paraLenʾݵIJȡ +VOID *paraʾݵIJ*/ extern UINT32 LOS_ErrHandle(CHAR *fileName, UINT32 lineNo, UINT32 errorNo, UINT32 paraLen, VOID *para); diff --git a/src/kernel/include/los_errno.h b/src/kernel/include/los_errno.h index 9d05458..106b7ef 100644 --- a/src/kernel/include/los_errno.h +++ b/src/kernel/include/los_errno.h @@ -46,31 +46,31 @@ extern "C" { * @ingroup los_errno * OS error code flag. It is a 24-bit unsigned integer. Its value is 0x000000U. */ -#define LOS_ERRNO_OS_ID (0x00U << 16) +#define LOS_ERRNO_OS_ID (0x00U << 16)//궨Ϊ 0x00U << 16ʾϵͳصĴ롣 /** * @ingroup los_errno * Define the error level as informative. It is a 32-bit unsigned integer. Its value is 0x00000000U. */ -#define LOS_ERRTYPE_NORMAL (0x00U << 24) +#define LOS_ERRTYPE_NORMAL (0x00U << 24)//궨ʾ󼶱Ϊ "informative"Ϣ𣩣ֵΪ 0x00U << 24 /** * @ingroup los_errno * Define the error level as warning. It is a 32-bit unsigned integer. Its value is 0x01000000U. */ -#define LOS_ERRTYPE_WARN (0x01U << 24) +#define LOS_ERRTYPE_WARN (0x01U << 24)//궨ʾ󼶱Ϊ "warning"漶𣩣ֵΪ 0x01U << 24 /** * @ingroup los_errno * Define the error level as critical. It is a 32-bit unsigned integer. Its value is 0x02000000U. */ -#define LOS_ERRTYPE_ERROR (0x02U << 24) +#define LOS_ERRTYPE_ERROR (0x02U << 24)//궨ʾ󼶱Ϊ "critical"ؼ𣩣ֵΪ 0x02U << 24 /** * @ingroup los_errno * Define the error level as fatal. It is a 32-bit unsigned integer. Its value is 0x03000000U. */ -#define LOS_ERRTYPE_FATAL (0x03U << 24) +#define LOS_ERRTYPE_FATAL (0x03U << 24)//궨ʾ󼶱Ϊ "fatal"𣩣ֵΪ 0x03U << 24 /** * @ingroup los_errno @@ -82,6 +82,14 @@ extern "C" { *
  • 0-7 bits indicate the error code number. It is specified by ERRNO.
  • * */ +/*ɲϵͳ롣 +LOS_ERRTYPE_FATAL ʾ󼶱Ϊ "fatal"𣩣ֵΪ 0x03U << 24 +LOS_ERRNO_OS_ID ʾϵͳصĴ룬ֵΪ 0x00U << 16 +(UINT32)(MID) << 8 MID 8 λڱʾģʶ +(UINT32)(ERRNO) ʾĴ롣 +λLOS_ERRNO_OS_FATAL һϵͳ룬 +ʽΪ󼶱LOS_ERRTYPE_FATAL+ ԴLOS_ERRNO_OS_ID+ ģʶMID+ 루ERRNO +ͨĺ꣬Էɲͬ͵Ĵ룬ݴIJͬԽзʹ*/ #define LOS_ERRNO_OS_FATAL(MID, ERRNO) \ (LOS_ERRTYPE_FATAL | LOS_ERRNO_OS_ID | ((UINT32)(MID) << 8) | ((UINT32)(ERRNO))) @@ -95,6 +103,15 @@ extern "C" { *
  • 0-7 bits indicate the error code number. It is specified by ERRNO.
  • * */ +/*δ붨һ LOS_ERRNO_OS_ERRORɲϵͳش롣 +úʹ¼λ +LOS_ERRTYPE_ERROR ʾ󼶱Ϊ "critical"ؼ𣩣ֵΪ 0x02U << 24 +LOS_ERRNO_OS_ID ʾϵͳصĴ룬ֵΪ 0x00U << 16 +(UINT32)(MID) << 8 MID 8 λڱʾģʶ +(UINT32)(ERRNO) ʾĴ롣 +λLOS_ERRNO_OS_ERROR һϵͳش룬 +ʽΪ󼶱LOS_ERRTYPE_ERROR+ ԴLOS_ERRNO_OS_ID+ ģʶMID+ 루ERRNO +ͨĺ꣬Էɲͬ͵Ĵ룬ݴIJͬԽзʹ*/ #define LOS_ERRNO_OS_ERROR(MID, ERRNO) \ (LOS_ERRTYPE_ERROR | LOS_ERRNO_OS_ID | ((UINT32)(MID) << 8) | ((UINT32)(ERRNO))) @@ -108,6 +125,15 @@ extern "C" { *
  • 0-7 bits indicate the error code number. It is specified by ERRNO.
  • * */ +/*δ붨һ LOS_ERRNO_OS_WARNɲϵͳ롣 +úʹ¼λ +LOS_ERRTYPE_WARN ʾ󼶱Ϊ "warning"漶𣩣ֵΪ 0x01U << 24 +LOS_ERRNO_OS_ID ʾϵͳصĴ룬ֵΪ 0x00U << 16 +(UINT32)(MID) << 8 MID 8 λڱʾģʶ +(UINT32)(ERRNO) ʾĴ롣 +λLOS_ERRNO_OS_WARN һϵͳ룬 +ʽΪ󼶱LOS_ERRTYPE_WARN+ ԴLOS_ERRNO_OS_ID+ ģʶMID+ 루ERRNO +ͨĺ꣬Էɲͬ͵Ĵ룬ݴIJͬԽзʹڷ漶ĴʱԲȡӦĴʩԱDZķ*/ #define LOS_ERRNO_OS_WARN(MID, ERRNO) \ (LOS_ERRTYPE_WARN | LOS_ERRNO_OS_ID | ((UINT32)(MID) << 8) | ((UINT32)(ERRNO))) @@ -121,13 +147,29 @@ extern "C" { *
  • 0-7 bits indicate the error code number. It is specified by ERRNO.
  • * */ +/*δ붨һ LOS_ERRNO_OS_NORMALɲϵͳͨ롣 +úʹ¼λ +LOS_ERRTYPE_NORMAL ʾ󼶱Ϊ "normal"ͨ𣩣ֵΪ 0x00U << 24 +LOS_ERRNO_OS_ID ʾϵͳصĴ룬ֵΪ 0x00U << 16 +(UINT32)(MID) << 8 MID 8 λڱʾģʶ +(UINT32)(ERRNO) ʾĴ롣 +λLOS_ERRNO_OS_NORMAL һϵͳͨ룬 +ʽΪ󼶱LOS_ERRTYPE_NORMAL+ ԴLOS_ERRNO_OS_ID+ ģʶMID+ 루ERRNO +ͨĺ꣬Էɲͬ͵Ĵ룬ݴIJͬԽзʹڷͨĴʱԸҪӦĴ¼*/ #define LOS_ERRNO_OS_NORMAL(MID, ERRNO) \ (LOS_ERRTYPE_NORMAL | LOS_ERRNO_OS_ID | ((UINT32)(MID) << 8) | ((UINT32)(ERRNO))) /** * @ingroup los_errno * Define the ID of each module in kernel. The ID is used in error code. + * ںжÿģ ID ID ڴ롣 */ +/*δ붨һö LOS_MODULE_IDһϵеģʶӦֵ +ÿģ鶼һΨһıʶڴнʶáЩʶֵʮƱʾģ LOS_MOD_SYS ֵ 0x0LOS_MOD_MEM ֵ 0x1Դơ +öУһʶ LOS_MOD_BUTT һ־ʾöٵĽ +ͨʹöͣԷʹЩģʶʾʹݲͬģ顣 +磬ʹ LOS_MOD_SYS ʾϵͳģ飬ڴнصIJжϡ +֮öṩһּ򵥶ķʽʹøģıʶ*/ enum LOS_MOUDLE_ID { LOS_MOD_SYS = 0x0, /**< System ID. Its value is 0x0. */ LOS_MOD_MEM = 0x1, /**< Dynamic memory module ID. Its value is 0x1. */ diff --git a/src/kernel/include/los_event.h b/src/kernel/include/los_event.h index 7f1f653..47abca9 100644 --- a/src/kernel/include/los_event.h +++ b/src/kernel/include/los_event.h @@ -47,19 +47,19 @@ extern "C" { * @ingroup los_event * Event reading mode: The task waits for all its expected events to occur. */ -#define LOS_WAITMODE_AND 4U +#define LOS_WAITMODE_AND 4U//ģʽʾȴ¼Ҳ˵ֻее¼ʱŻִС /** * @ingroup los_event * Event reading mode: The task waits for any of its expected events to occur. */ -#define LOS_WAITMODE_OR 2U +#define LOS_WAITMODE_OR 2U//ģʽʾȴκһ¼Ҳ˵ֻҪκһ¼ͻִС /** * @ingroup los_event * Event reading mode: The event flag is immediately cleared after the event is read. */ -#define LOS_WAITMODE_CLR 1U +#define LOS_WAITMODE_CLR 1U//ģʽʾ¼ȡ¼־Ҳ˵һȡ¼¼־ͻᱻ /** * @ingroup los_event @@ -69,6 +69,14 @@ extern "C" { * Value: 0x02001c00. * * Solution: Set bits excluding bit 25 of the event mask to events. + * δ붨һ LOS_ERRNO_EVENT_SETBIT_INVALID + ʾ¼λЧ궨ʹ LOS_ERRNO_OS_ERROR ꣬ + úͨڶϵͳصĴ롣 + LOS_MOD_EVENT ʾģ¼ģ飬 + 0x00 Ǹô¼ģڲľš + ͨʹĺ궨壬Էڴúʹ룬 + ͬʱҲڶԴзͶλij¼λЧʱ + Է룬Ӷõ֪ʲôⲢӦĴ */ #define LOS_ERRNO_EVENT_SETBIT_INVALID LOS_ERRNO_OS_ERROR(LOS_MOD_EVENT, 0x00) @@ -81,6 +89,13 @@ extern "C" { * Solution: Increase the waiting time for event reading, or make another task write a * mask for the event. */ +/*δ붨һ LOS_ERRNO_EVENT_READ_TIMEOUTʾ¼ȡʱͬأú궨Ҳʹ LOS_ERRNO_OS_ERROR ꣬ʾôڲϵͳĴ룬¼ģڲľ 0x01 + +ijȴ¼ʱ趨˳ʱʱ䣬 +ڸʱûеȵ¼ôͻ᷵룬 +֪¼ȡʱ +Ķ԰ԱõжϺʹʱ +ӶϵͳȶԺͿɿԡ*/ #define LOS_ERRNO_EVENT_READ_TIMEOUT LOS_ERRNO_OS_ERROR(LOS_MOD_EVENT, 0x01) /** @@ -92,6 +107,13 @@ extern "C" { * * Solution: Pass in a valid EVENTMASK value. */ +/*δ붨һ LOS_ERRNO_EVENT_EVENTMASK_INVALIDʾ¼Ч +ͬأú궨Ҳʹ LOS_ERRNO_OS_ERROR ꣬ +ʾôڲϵͳĴ룬¼ģڲľ 0x02 +¼ڱʶȴ¼¼Ч +ʾָ¼벻Ϲ淶򲻿ʶ𡣵ʱ +Է룬֪¼ЧͨĶ壬 +ԱԸõؼʹ¼صĴ󣬴ӶϵͳĽ׳ԺͿάԡ*/ #define LOS_ERRNO_EVENT_EVENTMASK_INVALID LOS_ERRNO_OS_ERROR(LOS_MOD_EVENT, 0x02) /** @@ -102,6 +124,15 @@ extern "C" { * * Solution: Read the event in a task. */ +/*δ붨һ LOS_ERRNO_EVENT_READ_IN_INTERRUPTʾжн¼ȡ +ͬأú궨Ҳʹ LOS_ERRNO_OS_ERROR ꣬ +ʾôڲϵͳĴ룬¼ģڲľ 0x03 +ͨ£¼ȡӦнУжϴִС +Ϊжϴиȼܻȵľͳͻ +¼ȡжʱͻ᷵룬 +֪жн¼ȡDzֵ֧ġ +ͨĶ壬԰Աʱֲ޸жִ¼ȡ⣬ +ȷϵͳȷкͿɿԡ*/ #define LOS_ERRNO_EVENT_READ_IN_INTERRUPT LOS_ERRNO_OS_ERROR(LOS_MOD_EVENT, 0x03) /** @@ -115,6 +146,15 @@ extern "C" { * * Solution: Pass in a valid flag value. */ +/*δ붨һ LOS_ERRNO_EVENT_FLAGS_INVALIDʾ¼־Ч +ͬأú궨Ҳʹ LOS_ERRNO_OS_ERROR ꣬ +ʾôڲϵͳĴ룬¼ģڲľ 0x04 +¼־ڱʶض¼״̬ڽ¼ʱҪʹЧ¼־ +¼־ЧʱΪ˴ı־߱־Ԥڡ +ʱԷ룬֪¼־Ч +ͨĶ壬԰Աõؼʹ¼־صĴ +ӶϵͳȶԺͿάԡԱԸݴλ޸¼־Ч⣬ +ȷ¼׼ȷԺͿɿԡ*/ #define LOS_ERRNO_EVENT_FLAGS_INVALID LOS_ERRNO_OS_ERROR(LOS_MOD_EVENT, 0x04) /** @@ -125,6 +165,15 @@ extern "C" { * * Solution: Unlock the task and read the event. */ +/*δ붨һ LOS_ERRNO_EVENT_READ_IN_LOCKʾ״̬½¼ȡ +ͬأú궨Ҳʹ LOS_ERRNO_OS_ERROR ꣬ +ʾôڲϵͳĴ룬¼ģڲľ 0x05 +ͨ£¼ȡӦڷ״̬½У +Ϊ״̬½¼ȡܵԴ⡣ +״̬½¼ȡʱԷ룬 +֪¼ȡڲʵ״̬¡ +ͨĶ壬ԱԼʱֲ޸״ִ̬¼ȡ⣬ +ȷϵͳȷкͿɿԡϵͳIJԺͱDZڵ⡣*/ #define LOS_ERRNO_EVENT_READ_IN_LOCK LOS_ERRNO_OS_ERROR(LOS_MOD_EVENT, 0x05) /** @@ -135,6 +184,14 @@ extern "C" { * * Solution: Check whether the input parameter is null. */ +/*δ붨һ LOS_ERRNO_EVENT_PTR_NULLʾָΪָ롣 +ͬأú궨Ҳʹ LOS_ERRNO_OS_ERROR ꣬ +ʾôڲϵͳĴ룬¼ģڲľ 0x06 +ڽ¼ʱͨҪһЩ¼롢¼־¼ȡ +ݵָΪָ룬ܻᵼ·ʷǷڴ桢⡣ʱ +Է룬֪ߴָΪָ롣 +ͨĶ壬ԱԼʱֲ޸ָ⣬ +ȷϵͳȷкͿɿԡϵͳȶԺͿάԡ*/ #define LOS_ERRNO_EVENT_PTR_NULL LOS_ERRNO_OS_ERROR(LOS_MOD_EVENT, 0x06) /** @@ -147,6 +204,15 @@ extern "C" { * Solution: Read the event in a vailid task. * @deprecated This error code is obsolete since LiteOS 5.0.0. */ +/*δ붨һ LOS_ERRNO_EVENT_READ_IN_SYSTEM_TASK +ʾϵͳн¼ȡͬأú궨Ҳʹ LOS_ERRNO_OS_ERROR ꣬ +ʾôڲϵͳĴ룬¼ģڲľ 0x07 +һ˵ϵͳнϸߵȨ𣬲ڲϵͳڲĹؼ +ͨӦóˣϵͳн¼ȡܻ𲻿ԤڵΪ +ƻϵͳȶԺͿɿԡϵͳн¼ȡʱ +Է룬֪߲Ӧϵͳִ¼ȡ +ͨĶ壬԰Աϵͳִ¼ȡ +ӶȷϵͳкͰȫԡϵͳȶԺͿάԡ*/ #define LOS_ERRNO_EVENT_READ_IN_SYSTEM_TASK LOS_ERRNO_OS_ERROR(LOS_MOD_EVENT, 0x07) /** @@ -157,12 +223,29 @@ extern "C" { * * Solution: Check whether the event list is not empty. */ +/*δ붨һ LOS_ERRNO_EVENT_SHOULD_NOT_DESTORY +ʾͼٲӦñٵ¼ͬأú궨Ҳʹ LOS_ERRNO_OS_ERROR ꣬ +ʾôڲϵͳĴ룬¼ģڲľ 0x08 +¼УЩ¼ܲӦñ٣Ϊǿڱ߳ʹá +ͼЩ¼ܻᵼ´ΪԴй©⡣ʱԷ룬֪߲ӦЩ¼ +ͨĶ壬԰ԱٲӦñٵ¼ +ӶȷϵͳкͿɿԡϵͳȶԺͿάԡ*/ #define LOS_ERRNO_EVENT_SHOULD_NOT_DESTORY LOS_ERRNO_OS_ERROR(LOS_MOD_EVENT, 0x08) /** * @ingroup los_event * Event control structure */ +/*δ붨һΪ tagEvent Ľṹ壬аԱ +uwEventIDʾ¼룬¼ƿָʾѾ߼¼ +ͨڱʶ¼ͻԡ +stEventListһڵ㣬ڽ¼ƿӣֶ֧¼Ĺ +⣬ͨ typedef ؼֽ struct tagEvent ¶Ϊ EVENT_CB_S ͣ +ͬʱָ EVENT_CB_S ṹָ PEVENT_CB_S +ֽṹͨ¼ģ飬ڴ洢͹¼صϢ +¼ıʶ¼ƿϵ +ԱʹĽṹʵ¼Ĵɾȴʹȹܣ +Ӷõعϵͳе첽¼ϵͳIJ*/ typedef struct tagEvent { UINT32 uwEventID; /**< Event mask in the event control block, indicating the event that has been logically processed. */ @@ -187,6 +270,15 @@ typedef struct tagEvent { * @see LOS_EventClear * @since Huawei LiteOS V100R001C00 */ +/*UINT32 LOS_EventInit(PEVENT_CB_S eventCB) LiteOS ϵͳеһ +ڳʼ¼ƿ顣 + eventCB ָ¼ƿṹ EVENT_CB_S ָ룬 +ýṹڴ洢͹¼صϢ +ķֵ UINT32 һ޷ʾִеĽ롣 +ͨɹִУ򷵻 LOS_OK ʾɹ򷵻ضӦĴ롣 + LOS_EventInit ʹ¼֮ǰ¼ƿгʼ +ͨ˺ȷ¼ƿijʼ״̬ȷ +ҿ԰ȫʹ¼ƿ¼ĵȴʹȲ*/ extern UINT32 LOS_EventInit(PEVENT_CB_S eventCB); /** @@ -223,6 +315,25 @@ extern UINT32 LOS_EventInit(PEVENT_CB_S eventCB); * @see LOS_EventRead | LOS_EventWrite * @since Huawei LiteOS V100R001C00 */ +/*UINT32 LOS_EventPoll(UINT32 *eventId, UINT32 eventMask, UINT32 mode) LiteOS ϵͳеһѯ¼ + +˵: + +eventId һָ޷ָ룬ڴ洢ѯ¼ID +eventMask һ޷ʾϣѯ¼롣 +mode һ޷ʾѯģʽ¼ֵ֮һ +OS_EVENT_ORѯһ¼õ¼ +OS_EVENT_ANDѯ¼õ¼ +ķֵ UINT32 һ޷ +ʾִеĽ롣ͨɹִУ򷵻 LOS_OK ʾɹ +򷵻ضӦĴ롣 + LOS_EventPoll ѯָ¼ָģʽ¼ǷѾ +¼ +Ὣ¼IDд eventId ָĵַ LOS_OKû¼ +ѯģʽӦĴ루 LOS_ERRNO_EVENT_UNAVAILABLE +˺ͨ¼ʹãʵĵȴ¼Ļơ +ͨѯ¼Ըݲͬ¼״̬IJ +ʵ첽¼ȵĹܡ*/ extern UINT32 LOS_EventPoll(UINT32 *eventId, UINT32 eventMask, UINT32 mode); /** @@ -263,6 +374,24 @@ extern UINT32 LOS_EventPoll(UINT32 *eventId, UINT32 eventMask, UINT32 mode); * @see LOS_EventPoll | LOS_EventWrite * @since Huawei LiteOS V100R001C00 */ +/*UINT32 LOS_EventRead(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout) + LiteOS ϵͳеһڶȡ¼ +˵: +eventCB һָ¼ƿṹ EVENT_CB_S ָ룬ʾҪȡ¼ƿ顣 +eventMask һ޷ʾϣȡ¼롣 +mode һ޷ʾȡģʽ¼ֵ֮һ +OS_EVENT_ORȴһ¼õ¼ +OS_EVENT_ANDȴ¼õ¼ +timeout һ޷ʾʱʱ䣬λΪϵͳʱӽ +ָʱδȡسʱ롣 +ķֵ UINT32 һ޷ʾִеĽ롣 +ͨɹִУ򷵻 LOS_OK ʾɹʱ򷵻ضӦĴ롣 + LOS_EventRead Եȴָ¼ָģʽ¼ǷѾ +¼᷵ LOS_OKû¼ +ݶȡģʽȴ¼Ĵֱʱڵȴڼ䣬ܻᱻ +ֱ¼ȡ +˺ͨ¼ʹãʵĵȴ¼Ļơͨȡ¼ +Ըݲͬ¼״̬IJʵ첽¼ȵĹܡ*/ extern UINT32 LOS_EventRead(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout); /** @@ -311,6 +440,17 @@ extern UINT32 LOS_EventWrite(PEVENT_CB_S eventCB, UINT32 events); * @see LOS_EventPoll | LOS_EventRead | LOS_EventWrite * @since Huawei LiteOS V100R001C00 */ +/*UINT32 LOS_EventWrite(PEVENT_CB_S eventCB, UINT32 events) LiteOS ϵͳеһд¼ +˵: +eventCB һָ¼ƿṹ EVENT_CB_S ָ룬ʾҪд¼¼ƿ顣 +events һ޷ʾҪд¼롣 +ķֵ UINT32 һ޷ʾִеĽ롣 +ͨɹִУ򷵻 LOS_OK ʾɹ򷵻ضӦĴ롣 + LOS_EventWrite ָ¼ƿд¼ +¼ʾһ¼״̬ͨӦ¼λΪ 1 ʾ¼Ѿ +¼д󣬵ȴ¼ܻᱻѣ¼״̬IJ +˺ͨ¼ʹãʵ֮ͬͨš +ͨд¼ԴִУʵЭͬĹܡ*/ extern UINT32 LOS_EventClear(PEVENT_CB_S eventCB, UINT32 events); /** @@ -333,6 +473,22 @@ extern UINT32 LOS_EventClear(PEVENT_CB_S eventCB, UINT32 events); * @see LOS_EventPoll | LOS_EventRead | LOS_EventWrite * @since Huawei LiteOS V100R001C00 */ +/*UINT32 LOS_EventDestroy(PEVENT_CB_S eventCB) LiteOS ϵͳеһ¼ƿ顣 +˵: + +eventCB һָ¼ƿṹ EVENT_CB_S ָ룬ʾҪٵ¼ƿ顣 +ķֵ UINT32 һ޷ʾִеĽ롣 +ͨɹִУ򷵻 LOS_OK ʾɹ򷵻ضӦĴ롣 + + LOS_EventDestroy һ¼ƿ飬ͷŸ¼ƿռõԴ +һ¼ƿ鱻٣ʹø¼ƿ¼ + +ʵӦУҪij¼ƿʱ +ͨ LOS_EventDestroy ͷԴֹԴй©ϵͳԴ˷ѡ + +Ҫעǣ¼ƿ֮ǰ +Ҫȷûڵȴ¼ʹø¼ͬ +ܻᵼϵͳΪ쳣*/ extern UINT32 LOS_EventDestroy(PEVENT_CB_S eventCB); #ifdef __cplusplus diff --git a/src/kernel/include/los_exc.h b/src/kernel/include/los_exc.h index 07c38e9..56ec150 100644 --- a/src/kernel/include/los_exc.h +++ b/src/kernel/include/los_exc.h @@ -61,6 +61,23 @@ extern "C" { * los_exc.h: the header file that contains the API declaration. * @since Huawei LiteOS V100R001C00 */ +/*LOS_Panic(const CHAR *fmt, ...) LiteOS ϵͳеһڴϵͳ +˵: +fmt һʽַʾϢĸʽ +... ǿɱбݸʽַ fmt Ҫ󣬴ӦIJ +úûзֵ + + LOS_Panic ᵼϵͳ״̬ϵͳ޷ִȥ +ͨ£úڴش򲻿ɻָ쳣 +Էֹϵͳִпܵ¸Ĵ롣 + +úͨʽַһЩϢ +ӶṩڱԭλûϢ +ЩϢܶڵԺŲdzá + +ҪעǣLOS_Panic ӦýʹãڱҪʱʹá +ڸúϵͳᵼϵͳֹͣв޷ָ +Ӧñҵ߼еøúɲҪϵͳжϡ*/ VOID LOS_Panic(const CHAR *fmt, ...); /** @@ -79,8 +96,22 @@ VOID LOS_Panic(const CHAR *fmt, ...); * los_exc.h: the header file that contains the API declaration. * @since Huawei LiteOS V200R005C10 */ +/*VOID LOS_BackTrace(VOID) LiteOS ϵͳеĺڻȡǰ̵߳ĺջϢ +úûвҲûзֵ + LOS_BackTrace ȡǰ̵߳ĺջϢ +ÿĵõַԼӦĺЩϢڵԺŲdzã +԰Ա˽ִʱḷ́λڡ + +ͨ£LOS_BackTrace ڵĿģڳ쳣ʱ +ͨӡջϢԭ +ڶλ쳣dzа + +ҪעǣLOS_BackTrace ʵֿھӲƽ̨ͱ +ͬƽ̨ͱܻвͬʵַʽơ +ˣʹøúʱҪ˽صƽ̨ͱԣȷȡ׼ȷĺջϢ*/ extern VOID LOS_BackTrace(VOID); #define OsBackTrace LOS_BackTrace +//궨彫 OsBackTrace 滻Ϊ LOS_BackTraceζڴʹ OsBackTrace ʱʵǵ LOS_BackTrace /** * @ingroup los_exc @@ -99,9 +130,28 @@ extern VOID LOS_BackTrace(VOID); * los_exc.h: the header file that contains the API declaration. * @since Huawei LiteOS V100R001C00 */ +/*VOID LOS_TaskBackTrace(UINT32 taskID) LiteOS ϵͳеĺڻȡָĺջϢ +˵: +taskID һ޷ʾҪȡջϢĿID +úûзֵ + + LOS_TaskBackTrace ԻȡָĺջϢ +ÿĵõַԼӦĺЩϢڵԺŲdzã +԰Ա˽ִָʱḷ́λڡ + +ͨ£LOS_TaskBackTrace ڵĿģض쳣ʱ +ͨӡĺջϢԭ +ڶλ쳣dzа + +ҪעǣLOS_TaskBackTrace ʵֿھӲƽ̨ͱ +ͬƽ̨ͱܻвͬʵַʽơ +ˣʹøúʱҪ˽صƽ̨ͱԣȷȡ׼ȷĺջϢ + +⣬ҪȷָIDЧġڵID +ܵ»ȡȷĺջϢ*/ extern VOID LOS_TaskBackTrace(UINT32 taskID); #define OsTaskBackTrace LOS_TaskBackTrace - +//궨彫 OsTaskBackTrace 滻Ϊ LOS_TaskBackTraceζڴʹ OsTaskBackTrace ʱʵǵ LOS_TaskBackTrace #ifdef LOSCFG_SHELL_EXCINFO_DUMP /** * @ingroup los_exc @@ -122,7 +172,14 @@ extern VOID LOS_TaskBackTrace(UINT32 taskID); * * @since Huawei LiteOS V200R005C10 */ +/*һָ͵Ķ塣һΪ LogReadWriteFunc ĺָͣ +úָָһΪ VOID ĺ +Ϊ UINTPTR startAddrUINT32 spaceUINT32 rwFlag CHAR *buf +ֶ巽ʽضǩĺָͣԱڴʹá*/ typedef VOID (*LogReadWriteFunc)(UINTPTR startAddr, UINT32 space, UINT32 rwFlag, CHAR *buf); +/*һ궨壬 log_read_write_fn 滻Ϊ LogReadWriteFunc +עָһɵAPIʹͨ궨壬 +Խ log_read_write_fn 滻Ϊ LogReadWriteFuncԴﵽ򻯺ͳһĿġ*/ #define log_read_write_fn LogReadWriteFunc /* old API since V200R002C00, please avoid use of it */ /** @@ -146,6 +203,22 @@ typedef VOID (*LogReadWriteFunc)(UINTPTR startAddr, UINT32 space, UINT32 rwFlag, * * @since Huawei LiteOS V200R002C00 */ +/* LOS_ExcInfoRegHook LiteOS ϵͳеһ쳣ϢĴĻصӺ + +úĸ + +startAddr쳣ϢĴʼַ +space쳣ϢĴĴСֽΪλ +bufڴ洢쳣ϢĴݵĻ +hookصӺΪ LogReadWriteFuncָ͡ +˵쳣ʱLiteOS LOS_ExcInfoRegHook +쳣ϢĴʼַСͻΪݸ +Ȼ LOS_ExcInfoRegHook ڲ +ͨصӺ hook 쳣ϢĴݡ + +ܿԶ쳣쳣Ϣ¼ͨûصӺ +쳣ʱȡ쳣ϢĴݣ +Աнһķ¼*/ VOID LOS_ExcInfoRegHook(UINTPTR startAddr, UINT32 space, CHAR *buf, LogReadWriteFunc hook); #endif diff --git a/src/kernel/include/los_hw.h b/src/kernel/include/los_hw.h index db1cf00..2105a21 100644 --- a/src/kernel/include/los_hw.h +++ b/src/kernel/include/los_hw.h @@ -59,9 +59,10 @@ extern "C" { * los_hw.h: the header file that contains the API declaration. * @since Huawei LiteOS V200R003C00 */ +/*δ붨һ̬ LOS_CpuInfoúһַָָ롣*/ STATIC INLINE const CHAR *LOS_CpuInfo(VOID) { - return ArchCpuInfo(); + return ArchCpuInfo();//ݵǰӲƽ̨öӦĵײ㺯ԻȡCPUϢͺšƵʡȵȡʵͨӲƽ̨صģҿҪһЩײļĴȡضƽ̨صIJ } #ifdef __cplusplus diff --git a/src/kernel/include/los_hwi.h b/src/kernel/include/los_hwi.h index 95233f2..4603103 100644 --- a/src/kernel/include/los_hwi.h +++ b/src/kernel/include/los_hwi.h @@ -48,12 +48,16 @@ extern "C" { * @ingroup los_hwi * Count of interrupts. */ +/*дһΪg_intCount飬Ķ岢ڵǰԴļС +ؼ"extern"߱طģͨζԴļС +ӽ׶Σȥҵʵʵg_intCountĶ壬Ȼ뵱ǰĴӡ*/ extern size_t g_intCount[]; /** * An interrupt is active. */ -extern size_t IntActive(VOID); + +extern size_t IntActive(VOID);//IntActive(VOID)ڻȡǰжĺúûвΪ޷ͣsize_t /** * @ingroup los_hwi @@ -61,6 +65,16 @@ extern size_t IntActive(VOID); * * @see OS_INT_INACTIVE */ + + /*LiteOSϵͳУ#define OS_INT_ACTIVE IntActive() һԤָһꡣOS_INT_ACTIVE Ϊ IntActive() Ľ + + 궨һڴʹõı滻ơ£ + г OS_INT_ACTIVE ʱԤὫ滻Ϊ IntActive() ĵã + ʵϾǽΪһʹá + + ֺ궨ĿĿΪ˼򻯴дߴĿɶԡ + ͨ꣬ͨ򵥵ƣOS_INT_ACTIVEʾӵĺãIntActive() + ӶʹӼ⡣*/ #define OS_INT_ACTIVE IntActive() /** @@ -71,6 +85,21 @@ extern size_t IntActive(VOID); * * @see OS_INT_ACTIVE */ +/*LiteOSϵͳУ#define OS_INT_INACTIVE (!(OS_INT_ACTIVE)) һԤָ +һꡣOS_INT_INACTIVE Ϊ OS_INT_ACTIVE ȡĽ + +˵OS_INT_ACTIVE һ꣬ʾ IntActive() Ľ + OS_INT_INACTIVE һ꣬ʾ OS_INT_ACTIVE ȡĽ +£ʹ߼ ! OS_INT_ACTIVE Ľȡ + +궨ĿĿڱʾǰжǷڷǻ״̬ + OS_INT_ACTIVE Ϊ棨㣩ʾжϴڻ״̬ + OS_INT_INACTIVE Ϊ٣㣩ʾжϴڷǻ״̬ + +ַͨʽ꣬Էڴжж״̬ӦĴ +ʹ OS_INT_INACTIVE Ըֱ۵رʾжǷڷǻ״̬ +ߴĿɶԺͿάԡ +*/ #define OS_INT_INACTIVE (!(OS_INT_ACTIVE)) /** @@ -78,6 +107,18 @@ extern size_t IntActive(VOID); * Highest priority of a hardware interrupt.This is an external parameter. * The priority range is [OS_HWI_PRIO_HIGHEST, OS_HWI_PRIO_HIGHEST + LOSCFG_HWI_PRIO_LIMIT - 1]. */ +/*LiteOSϵͳУ#define OS_HWI_PRIO_HIGHEST 0 һԤָ +һꡣ OS_HWI_PRIO_HIGHEST Ϊ 0 + +LiteOSϵͳУжϣInterruptҲΪӲжϣHardware Interrupt +Ϊ HWIHWIвͬȼPriorityȼԽߣжӦʱԽ̡ +OS_HWI_PRIO_HIGHEST һʾжȼĺֵ꣬Ϊ 0 + +LiteOSϵͳУжϵȼֱʾģԽСʾȼԽߡ +ˣOS_HWI_PRIO_HIGHEST ʾжȼҲСжȼ +һЩض£Ҫʹжȼ +ʱʹ OS_HWI_PRIO_HIGHEST ʾжȼֵ 0 +Ӷؽдд*/ #define OS_HWI_PRIO_HIGHEST 0 /** @@ -85,12 +126,36 @@ extern size_t IntActive(VOID); * This represents the interrupt priority range, the larger number, the lower priority, the interrupt processor is * modified uniformly. */ +/*LiteOSϵͳУ +#define OS_HWI_PRIO_LOWEST (LOSCFG_HWI_PRIO_LIMIT - 1) һԤָ +һꡣ OS_HWI_PRIO_LOWEST Ϊ LOSCFG_HWI_PRIO_LIMIT ȥ 1 Ľ + +LiteOSϵͳУжϣInterruptҲΪӲжϣHardware Interrupt +Ϊ HWIHWIвͬȼPriorityȼԽߣжӦʱԽ̡OS_HWI_PRIO_LOWEST һʾжȼĺֵ꣬Ϊ LOSCFG_HWI_PRIO_LIMIT - 1 + +LOSCFG_HWI_PRIO_LIMIT һòڱʾϵͳֵ֧жȼ +ˣOS_HWI_PRIO_LOWEST ʾжȼҲжȼ +ֵжȼȥ 1 +һЩض£Ҫʹжȼ +ʱʹ OS_HWI_PRIO_LOWEST ʾжȼֵӶؽдд*/ #define OS_HWI_PRIO_LOWEST (LOSCFG_HWI_PRIO_LIMIT - 1) /** * @ingroup los_hwi * The lower priority number, the higher priority, so OS_HWI_PRIO_LOWEST big than OS_HWI_PRIO_HIGHEST. */ +/*úһ priʾҪжϵжȼֵ +Ķʹ߼ && ͱȽ >=<= +£ + +((pri) >= OS_HWI_PRIO_HIGHEST) ʾж pri ǷڵжȼOS_HWI_PRIO_HIGHEST pri ڵжȼΪ棨㣩Ϊ٣㣩 +((pri) <= OS_HWI_PRIO_LOWEST) ʾж pri ǷСڵжȼOS_HWI_PRIO_LOWEST pri СڵжȼΪ棨㣩Ϊ٣㣩 +궨彫ʹ߼ && + (((pri) >= OS_HWI_PRIO_HIGHEST) && ((pri) <= OS_HWI_PRIO_LOWEST)) +ֻе pri ͬʱڵжȼСڵжȼʱ +Ϊ棨㣩ʾжȼЧΪ٣㣩ʾжȼЧ +ڽжȼжϺʱ +ȷʹõжȼֵЧΧڣִжȼá*/ #define HWI_PRI_VALID(pri) (((pri) >= OS_HWI_PRIO_HIGHEST) && ((pri) <= OS_HWI_PRIO_LOWEST)) /** @@ -105,6 +170,23 @@ extern size_t IntActive(VOID); *
  • Please use macros starting with LOS, and macros starting with OS will not be supported.
  • * */ +/*Ԥָ롣 + +ЩڱʾڲϵͳӲжϣHWIģзĴ +ͨʹLiteOSṩĴġ +£ + +LOS_ERRNO_HWI_NUM_INVALID һʾЧжϺŵĴ롣 +ôֵ LOS_ERRNO_OS_ERROR ɣ +ģźʹֵ +УLOS_MOD_HWI ʾHWIģģţ0x00 ʾֵ +ˣLOS_ERRNO_HWI_NUM_INVALID ֵǸģźʹֵóġ +OS_ERRNO_HWI_NUM_INVALID LOS_ERRNO_HWI_NUM_INVALID ı +ͨ䶨ΪֵͬڴʹøʾЧжϺŵĴ롣 +Щڱ̹жϺʹHWIģصĴ +磬úʹжʱЧжϺţ +ͨ鷵صĴǷ LOS_ERRNO_HWI_NUM_INVALID OS_ERRNO_HWI_NUM_INVALID +жжϺǷЧӦĴ*/ #define LOS_ERRNO_HWI_NUM_INVALID LOS_ERRNO_OS_ERROR(LOS_MOD_HWI, 0x00) #define OS_ERRNO_HWI_NUM_INVALID LOS_ERRNO_HWI_NUM_INVALID @@ -120,6 +202,22 @@ extern size_t IntActive(VOID); *
  • Please use macros starting with LOS, and macros starting with OS will not be supported.
  • * */ +/*Ԥָ롣 + +ЩڱʾڲϵͳӲжϣHWIģзĴ +ͨʹLiteOSṩĴġ +£ + +LOS_ERRNO_HWI_PROC_FUNC_NULL һʾжϴΪյĴ롣ôֵ LOS_ERRNO_OS_ERROR ɣ +ģźʹֵ +УLOS_MOD_HWI ʾHWIģģţ0x01 ʾֵ +ˣLOS_ERRNO_HWI_PROC_FUNC_NULL ֵǸģźʹֵóġ +OS_ERRNO_HWI_PROC_FUNC_NULL LOS_ERRNO_HWI_PROC_FUNC_NULL ı +ͨ䶨ΪֵͬڴʹøʾжϴΪյĴ롣 +Щڱ̹жϺʹHWIģصĴ +磬úʹжʱжϴΪգ +ͨ鷵صĴǷ LOS_ERRNO_HWI_PROC_FUNC_NULL OS_ERRNO_HWI_PROC_FUNC_NULLжжϴǷȷã +ӦĴ*/ #define LOS_ERRNO_HWI_PROC_FUNC_NULL LOS_ERRNO_OS_ERROR(LOS_MOD_HWI, 0x01) #define OS_ERRNO_HWI_PROC_FUNC_NULL LOS_ERRNO_HWI_PROC_FUNC_NULL @@ -132,6 +230,18 @@ extern size_t IntActive(VOID); * Solution: This error code is not in use temporarily. * @deprecated This error code is obsolete since LiteOS 5.0.0. */ +/**/ +/*һ룬ʾӲжϣHWIصõ +£ + +OS_ERRNO_HWI_CB_UNAVAILABLE ʾӲжϣHWIصõĴ롣 + LOS_ERRNO_OS_ERROR ɣúģźʹֵ +LOS_MOD_HWI ʾHWIģģţ0x02 ʾֵ +ˣOS_ERRNO_HWI_CB_UNAVAILABLE ֵǸģźʹֵóġ +ڱ̹жϺʹHWIģصĴ +磬úעжϻصʱصã +ͨ鷵صĴǷ OS_ERRNO_HWI_CB_UNAVAILABLEжϻصĿԣ +ӶӦĴ*/ #define OS_ERRNO_HWI_CB_UNAVAILABLE LOS_ERRNO_OS_ERROR(LOS_MOD_HWI, 0x02) /** @@ -146,6 +256,21 @@ extern size_t IntActive(VOID); *
  • Please use macros starting with LOS, and macros starting with OS will not be supported.
  • * */ +/*Ԥָ롣 + +ЩڱʾڲϵͳӲжϣHWIģзĴͨʹLiteOSṩĴġ +£ + +LOS_ERRNO_HWI_NO_MEMORY һʾ޷ڴĴ롣 +ôֵ LOS_ERRNO_OS_ERROR ɣģźʹֵ +УLOS_MOD_HWI ʾHWIģģţ0x03 ʾֵ +ˣLOS_ERRNO_HWI_NO_MEMORY ֵǸģźʹֵóġ +OS_ERRNO_HWI_NO_MEMORY LOS_ERRNO_HWI_NO_MEMORY ıͨ䶨Ϊֵͬ +ڴʹøʾ޷ڴĴ롣 +Щڱ̹жϺʹHWIģصĴ +磬úעжϴʱ޷ڴ +ͨ鷵صĴǷ LOS_ERRNO_HWI_NO_MEMORY OS_ERRNO_HWI_NO_MEMORY +жڴǷɹӦĴ*/ #define LOS_ERRNO_HWI_NO_MEMORY LOS_ERRNO_OS_ERROR(LOS_MOD_HWI, 0x03) #define OS_ERRNO_HWI_NO_MEMORY LOS_ERRNO_HWI_NO_MEMORY @@ -162,6 +287,22 @@ extern size_t IntActive(VOID); *
  • Please use macros starting with LOS, and macros starting with OS will not be supported.
  • * */ +/*Ԥָڶ롣 + +ЩڱʾڲϵͳӲжϣHWIģзĴ +ͨʹLiteOSṩĴġ +£ + +LOS_ERRNO_HWI_ALREADY_CREATED һʾжѾĴ롣 +ôֵ LOS_ERRNO_OS_ERROR ɣģźʹֵ +LOS_MOD_HWI ʾHWIģģţ0x04 ʾֵ +ˣLOS_ERRNO_HWI_ALREADY_CREATED ֵǸģźʹֵóġ +OS_ERRNO_HWI_ALREADY_CREATED LOS_ERRNO_HWI_ALREADY_CREATED ı +ͨ䶨ΪֵͬڴʹøʾжѾĴ롣 +Щڱ̹жϺʹHWIģصĴ +磬ڴжʱжѾ +ͨ鷵صĴǷ LOS_ERRNO_HWI_ALREADY_CREATED OS_ERRNO_HWI_ALREADY_CREATED +жжǷѾڣӶӦĴ*/ #define LOS_ERRNO_HWI_ALREADY_CREATED LOS_ERRNO_OS_ERROR(LOS_MOD_HWI, 0x04) #define OS_ERRNO_HWI_ALREADY_CREATED LOS_ERRNO_HWI_ALREADY_CREATED @@ -177,6 +318,22 @@ extern size_t IntActive(VOID); *
  • Please use macros starting with LOS, and macros starting with OS will not be supported.
  • * */ +/*Ԥָڶ롣 + +ЩڱʾڲϵͳӲжϣHWIģзĴ +ͨʹLiteOSṩĴġ +£ + +LOS_ERRNO_HWI_PRIO_INVALID һʾжȼЧĴ롣 +ôֵ LOS_ERRNO_OS_ERROR ɣģźʹֵ +LOS_MOD_HWI ʾHWIģģţ0x05 ʾֵ +ˣLOS_ERRNO_HWI_PRIO_INVALID ֵǸģźʹֵóġ +OS_ERRNO_HWI_PRIO_INVALID LOS_ERRNO_HWI_PRIO_INVALID ı +ͨ䶨ΪֵͬڴʹøʾжȼЧĴ롣 +Щڱ̹жϺʹHWIģصĴ +磬жȼʱṩЧȼֵ +ͨ鷵صĴǷ LOS_ERRNO_HWI_PRIO_INVALID OS_ERRNO_HWI_PRIO_INVALIDжȼǷЧ +ӦĴ*/ #define LOS_ERRNO_HWI_PRIO_INVALID LOS_ERRNO_OS_ERROR(LOS_MOD_HWI, 0x05) #define OS_ERRNO_HWI_PRIO_INVALID LOS_ERRNO_HWI_PRIO_INVALID @@ -189,6 +346,18 @@ extern size_t IntActive(VOID); * Solution: This error code is not in use temporarily. * @deprecated This error code is obsolete since LiteOS 5.0.0. */ +/*һԤָڶ롣 + +ôڱʾڲϵͳӲжϣHWIģзĴ +˵жģʽЧĴ +ͨʹLiteOSṩĴ LOS_ERRNO_OS_ERROR ġ +úģźʹֵ +LOS_MOD_HWI ʾHWIģģţ0x06 ʾֵ +ˣOS_ERRNO_HWI_MODE_INVALID ֵǸģźʹֵóġ +ڱ̹жϺʹHWIģصĴ +磬жģʽʱṩЧģʽֵ +ͨ鷵صĴǷ OS_ERRNO_HWI_MODE_INVALID +жģʽǷЧӦĴ*/ #define OS_ERRNO_HWI_MODE_INVALID LOS_ERRNO_OS_ERROR(LOS_MOD_HWI, 0x06) /** @@ -200,6 +369,19 @@ extern size_t IntActive(VOID); * Solution: This error code is not in use temporarily. * @deprecated This error code is obsolete since LiteOS 5.0.0. */ +/*һԤָڶ롣 + +ôڱʾڲϵͳӲжϣHWIģзĴ +˵ǿжģʽѾĴ +ͨʹLiteOSṩĴ LOS_ERRNO_OS_ERROR ġ +úģźʹֵ +LOS_MOD_HWI ʾHWIģģţ0x07 ʾֵ +ˣOS_ERRNO_HWI_FASTMODE_ALREADY_CREATED ֵǸģźʹֵóġ + +ڱ̹жϺʹHWIģصĴ +磬ڴжģʽʱģʽѾ +ͨ鷵صĴǷ OS_ERRNO_HWI_FASTMODE_ALREADY_CREATED +жϿжģʽǷѾڣӶӦĴ*/ #define OS_ERRNO_HWI_FASTMODE_ALREADY_CREATED LOS_ERRNO_OS_ERROR(LOS_MOD_HWI, 0x07) /** @@ -214,6 +396,23 @@ extern size_t IntActive(VOID); *
  • Please use macros starting with LOS, and macros starting with OS will not be supported.
  • * */ +/*Ԥָڶ롣 + +ЩڱʾڲϵͳӲжϣHWIģзĴ󣬾˵ӲжϷĴ +ͨʹLiteOSṩĴġ +£ + +LOS_ERRNO_HWI_INTERR һʾӲжϷĴ롣 +ôֵ LOS_ERRNO_OS_ERROR ɣ +ģźʹֵ +LOS_MOD_HWI ʾHWIģģţ0x08 ʾֵ +ˣLOS_ERRNO_HWI_INTERR ֵǸģźʹֵóġ +OS_ERRNO_HWI_INTERR LOS_ERRNO_HWI_INTERR ı +ͨ䶨ΪֵͬڴʹøʾӲжϷĴ롣 +Щڱ̹жϺʹHWIģصĴ +磬жϴУӲжϷ +ͨ鷵صĴǷ LOS_ERRNO_HWI_INTERR OS_ERRNO_HWI_INTERR +жжǷ˴󣬽ӦĴ*/ #define LOS_ERRNO_HWI_INTERR LOS_ERRNO_OS_ERROR(LOS_MOD_HWI, 0x08) #define OS_ERRNO_HWI_INTERR LOS_ERRNO_HWI_INTERR @@ -230,6 +429,22 @@ extern size_t IntActive(VOID); *
  • Please use macros starting with LOS, and macros starting with OS will not be supported.
  • * */ +/*Ԥָڶ롣 + +ЩڱʾڲϵͳӲжϣHWIģзĴ󣬾˵ǹжϴĴ +ͨʹLiteOSṩĴġ +£ + +LOS_ERRNO_HWI_SHARED_ERROR һʾжϴĴ롣 +ôֵ LOS_ERRNO_OS_ERROR ɣģźʹֵ +LOS_MOD_HWI ʾHWIģģţ0x09 ʾֵ +ˣLOS_ERRNO_HWI_SHARED_ERROR ֵǸģźʹֵóġ +OS_ERRNO_HWI_SHARED_ERROR LOS_ERRNO_HWI_SHARED_ERROR ı +ͨ䶨ΪֵͬڴʹøʾжϴĴ롣 +Щڱ̹жϺʹHWIģصĴ +磬ùжʱ˴ +ͨ鷵صĴǷ LOS_ERRNO_HWI_SHARED_ERROR OS_ERRNO_HWI_SHARED_ERROR +жϹжǷóɹӦĴ*/ #define LOS_ERRNO_HWI_SHARED_ERROR LOS_ERRNO_OS_ERROR(LOS_MOD_HWI, 0x09) #define OS_ERRNO_HWI_SHARED_ERROR LOS_ERRNO_HWI_SHARED_ERROR @@ -242,6 +457,20 @@ extern size_t IntActive(VOID); * Solution: This error code is not in use temporarily. * @deprecated This error code is obsolete since LiteOS 5.0.0. */ +/*һԤָڶ롣 + +ڱʾڲϵͳӲжϣHWIģзĴ󣬾˵ӲжϲЧĴ +ͨʹLiteOSṩĴġ +£ + +OS_ERRNO_HWI_ARG_INVALID һʾӲжϲЧĴ롣 +ôֵ LOS_ERRNO_OS_ERROR ɣģźʹֵ +LOS_MOD_HWI ʾHWIģģţ0x0a ʾֵ +ˣOS_ERRNO_HWI_ARG_INVALID ֵǸģźʹֵóġ +ڱ̹жϺʹHWIģصĴ +磬עӲжϴʱݸIJЧ +ͨ鷵صĴǷ OS_ERRNO_HWI_ARG_INVALIDжϲǷЧ +ӦĴ*/ #define OS_ERRNO_HWI_ARG_INVALID LOS_ERRNO_OS_ERROR(LOS_MOD_HWI, 0x0a) /** @@ -257,6 +486,22 @@ extern size_t IntActive(VOID); *
  • Please use macros starting with LOS, and macros starting with OS will not be supported.
  • * */ +/*Ԥָڶ롣 + +ЩڱʾڲϵͳӲжϣHWIģзĴ󣬾˵ӲжϺδĴ +ͨʹLiteOSṩĴġ +£ + +LOS_ERRNO_HWI_HWINUM_UNCREATE һʾӲжϺδĴ롣 +ôֵ LOS_ERRNO_OS_ERROR ɣģźʹֵ +LOS_MOD_HWI ʾHWIģģţ0x0b ʾֵ +ˣLOS_ERRNO_HWI_HWINUM_UNCREATE ֵǸģźʹֵóġ +OS_ERRNO_HWI_HWINUM_UNCREATE LOS_ERRNO_HWI_HWINUM_UNCREATE ı +ͨ䶨ΪֵͬڴʹøʾӲжϺδĴ롣 +ڱ̹жϺʹHWIģصĴ +磬ijӲжʱָжϺδ +ͨ鷵صĴǷ LOS_ERRNO_HWI_HWINUM_UNCREATE OS_ERRNO_HWI_HWINUM_UNCREATE +жжϺǷЧӦĴ*/ #define LOS_ERRNO_HWI_HWINUM_UNCREATE LOS_ERRNO_OS_ERROR(LOS_MOD_HWI, 0x0b) #define OS_ERRNO_HWI_HWINUM_UNCREATE LOS_ERRNO_HWI_HWINUM_UNCREATE @@ -264,18 +509,21 @@ extern size_t IntActive(VOID); * @ingroup los_hwi * Define the type HWI_HANDLE_T for a hardware interrupt number, the type is an unsigned int. */ +//д붨һµ HWI_HANDLE_TΪ UINT32޷32λHWI_HANDLE_T ʾӲжϵľʶ typedef UINT32 HWI_HANDLE_T; /** * @ingroup los_hwi * Define the type HWI_PRIOR_T for a hardware interrupt priority, the type is an unsigned short. */ +//д붨һµ HWI_PRIOR_TΪ UINT16޷16λHWI_PRIOR_T ʾӲжϵȼ typedef UINT16 HWI_PRIOR_T; /** * @ingroup los_hwi * Define the type HWI_MODE_T for hardware interrupt mode configurations, the type is an unsigned short. */ +//д붨һµ HWI_MODE_TΪ UINT16޷16λHWI_MODE_T ʾӲжϵģʽá typedef UINT16 HWI_MODE_T; /** @@ -283,6 +531,9 @@ typedef UINT16 HWI_MODE_T; * Define the type HWI_ARG_T for the parameter used for the hardware interrupt creation function. * The function of this parameter varies among platforms. */ +/*д붨һµ HWI_ARG_TΪ UINTPTR +һ޷СָСͬ +HWI_ARG_T ʾӲжϴIJ庬ƽ̨졣*/ typedef UINTPTR HWI_ARG_T; /** @@ -303,6 +554,8 @@ typedef UINTPTR HWI_ARG_T; * @see LOS_HwiCreate * @since Huawei LiteOS V100R001C00 */ +/*д붨һָ HWI_PROC_FUNCָһûвͷֵĺ +HWI_PROC_FUNC ʾӲжϴ͡*/ typedef VOID (*HWI_PROC_FUNC)(VOID); /** @@ -311,12 +564,22 @@ typedef VOID (*HWI_PROC_FUNC)(VOID); * * The flag only used by the kernel as part of the IRQ handling routines. */ +/*궨һ IRQF_SHAREDֵΪ 0x8000U +IRQF_SHARED ڱʾһӲжϡ*/ #define IRQF_SHARED 0x8000U /** * @ingroup los_hwi * The hardware interrupt parameter for #LOS_HwiDelete and interrupt handler in #LOS_HwiCreate. */ +/*붨һΪ HWI_IRQ_PARAM_S Ľṹͣṹڰ³Ա +int swIrq: ʾжϺŵ +VOID *pDevId: ʾжϵ豸IDָ +const CHAR *pName: ʾжƵָ + +ṹ HWI_IRQ_PARAM_S LOS_HwiDelete LOS_HwiCreate еӲжϲ +ͨʹṹ壬 +ԴжϺš豸IDжƵϢԽӦIJ*/ typedef struct tagIrqParam { int swIrq; /**< The interrupt number */ VOID *pDevId; /**< The pointer to the device ID that launches the interrupt */ @@ -340,6 +603,27 @@ typedef struct tagIrqParam { * @see LOS_IntRestore * @since Huawei LiteOS V100R001C00 */ +/*δ붨һ̬ LOS_IntLock()£ + +STATIC INLINE + +STATIC ؼָʾúΪǰļļвɼ +INLINE ؼָ߱úĴ뵽ôɺá +UINT32 + +UINT32 ʾֵΪ޷32λ +LOS_IntLock(VOID) + +LOS_IntLock Ǻƣһ VOID ʾû +return ArchIntLock(); + +д ArchIntLock() ䷵ֵΪ LOS_IntLock() ķֵ +ArchIntLock() һӲصĺڽжϣ֮ǰж״̬ +ΪΪҺdz򵥣 +ԱڵôֱӲ ArchIntLock() Ĵ룬ִЧʡ +ܽ᣺LOS_IntLock() һ +õײ ArchIntLock() жϣ֮ǰж״̬ +ĿΪ˱ؼ򣬷ֹжϴϣȷݵһԺͿɿԡ*/ STATIC INLINE UINT32 LOS_IntLock(VOID) { return ArchIntLock(); @@ -361,6 +645,13 @@ STATIC INLINE UINT32 LOS_IntLock(VOID) * * @see LOS_IntLock */ +/*return ArchIntUnlock(); + +д ArchIntUnlock() ䷵ֵΪ LOS_IntUnLock() ķֵ +ArchIntUnlock() һӲصĺڻָ֮ǰõж״̬ +ܽ᣺LOS_IntUnLock() һ +õײ ArchIntUnlock() ָ֮ǰõж״̬ +ĿΪٽִϺ󣬻ָжϣж¼*/ STATIC INLINE UINT32 LOS_IntUnLock(VOID) { return ArchIntUnlock(); @@ -384,6 +675,14 @@ STATIC INLINE UINT32 LOS_IntUnLock(VOID) * @see LOS_IntLock * @since Huawei LiteOS V100R001C00 */ +/*ArchIntRestore(intSave); + +д ArchIntRestore() ֮ǰж״̬Ϊݸ +ArchIntRestore() һӲصĺڸݴж״ֵָ̬жϡ +ܽ᣺LOS_IntRestore() һ +õײ ArchIntRestore() ֮ǰж״ָ̬жϡ +ĿһαжϵĴִϺ󣬻ָж״̬ж¼ +ںûзֵԲ᷵κν*/ STATIC INLINE VOID LOS_IntRestore(UINT32 intSave) { ArchIntRestore(intSave); @@ -430,11 +729,11 @@ STATIC INLINE VOID LOS_IntRestore(UINT32 intSave) * @see LOS_HwiDelete * @since Huawei LiteOS V100R001C00 */ -extern UINT32 LOS_HwiCreate(HWI_HANDLE_T hwiNum, - HWI_PRIOR_T hwiPrio, - HWI_MODE_T hwiMode, - HWI_PROC_FUNC hwiHandler, - HWI_IRQ_PARAM_S *irqParam); +extern UINT32 LOS_HwiCreate(HWI_HANDLE_T hwiNum,//ʾжϺŻжıʶ + HWI_PRIOR_T hwiPrio,//ʾжϵȼ + HWI_MODE_T hwiMode,//ʾжϵģʽشƽȣ + HWI_PROC_FUNC hwiHandler,//ʾжϴָ롣 + HWI_IRQ_PARAM_S *irqParam);//ʾжϲĽṹָ롣 /** * @ingroup los_hwi @@ -470,6 +769,9 @@ extern UINT32 LOS_HwiCreate(HWI_HANDLE_T hwiNum, * @see LOS_HwiCreate * @since Huawei LiteOS V100R001C00 */ +//һ LiteOS ϵͳɾһжϴ +/*HWI_HANDLE_T hwiNum ǺĵһʾҪɾжϺŻжıʶ +HWI_IRQ_PARAM_S *irqParam ǺĵڶʾжϲĽṹָ롣*/ extern UINT32 LOS_HwiDelete(HWI_HANDLE_T hwiNum, HWI_IRQ_PARAM_S *irqParam); /** @@ -492,6 +794,8 @@ extern UINT32 LOS_HwiDelete(HWI_HANDLE_T hwiNum, HWI_IRQ_PARAM_S *irqParam); * * @since Huawei LiteOS V200R005C00 */ +//һ LiteOS ϵͳдһָжϡ +//HWI_HANDLE_T hwiNum ǺIJʾҪжϺŻжıʶ extern UINT32 LOS_HwiTrigger(HWI_HANDLE_T hwiNum); /** @@ -513,6 +817,10 @@ extern UINT32 LOS_HwiTrigger(HWI_HANDLE_T hwiNum); * * @since Huawei LiteOS V200R005C00 */ +//һ LiteOS ϵͳλһָжϡ +/*HWI_HANDLE_T hwiNum ǺIJʾҪжϺŻжıʶ +ǸָжϺţӦжϱ־λж״̬λ +ͨøúжϴ״̬Ա׼һжϴ*/ extern UINT32 LOS_HwiClear(HWI_HANDLE_T hwiNum); /** @@ -536,6 +844,10 @@ extern UINT32 LOS_HwiClear(HWI_HANDLE_T hwiNum); * @see LOS_HwiDisable * @since Huawei LiteOS V200R005C00 */ +//һ LiteOS ϵͳʹܣãһָжϡ +/*HWI_HANDLE_T hwiNum ǺIJʾҪʹܵжϺŻжıʶ +ǸָжϺţӦжʹλΪЧøжϡ +жϺ󣬵жϴʱϵͳתִжӦжϴ*/ extern UINT32 LOS_HwiEnable(HWI_HANDLE_T hwiNum); /** @@ -558,6 +870,10 @@ extern UINT32 LOS_HwiEnable(HWI_HANDLE_T hwiNum); * @see LOS_HwiEnable * @since Huawei LiteOS V200R005C00 */ +//һ LiteOS ϵͳнãرգһָжϡ +/*HWI_HANDLE_T hwiNum ǺIJʾҪõжϺŻжıʶ +ǸָжϺţӦжʹλΪЧøжϡ +жϺ󣬼ʹжϴϵͳҲתִжӦжϴ*/ extern UINT32 LOS_HwiDisable(HWI_HANDLE_T hwiNum); #ifdef LOSCFG_KERNEL_SMP @@ -582,6 +898,11 @@ extern UINT32 LOS_HwiDisable(HWI_HANDLE_T hwiNum); * * @since Huawei LiteOS V200R005C00 */ +//һ LiteOS ϵͳָĴж +/*HWI_HANDLE_T hwiNum ǺĵһʾҪ͵жϺŻжıʶ +UINT32 cpuMask ǺĵڶʾжϷ͵Ŀ괦룬ָжϷ͵Щϡ +ָĴж +ͨжϿĿ괦жźţӦжϴ*/ extern UINT32 LOS_HwiSendIpi(HWI_HANDLE_T hwiNum, UINT32 cpuMask); /** @@ -605,6 +926,12 @@ extern UINT32 LOS_HwiSendIpi(HWI_HANDLE_T hwiNum, UINT32 cpuMask); * * @since Huawei LiteOS V200R005C00 */ +//һ LiteOS ϵͳָжϵ׺ԣAffinity +/*HWI_HANDLE_T hwiNum ǺĵһʾҪ׺ԵжϺŻжıʶ +UINT32 cpuMask ǺĵڶʾҪõж׺룬ָжϿЩִС +ָжϵ׺ԣжضĴжϱʱ +ֻж׺صĴŻ᳢ִжϴ +Ӷ˲Ҫжϴݺʹ*/ extern UINT32 LOS_HwiSetAffinity(HWI_HANDLE_T hwiNum, UINT32 cpuMask); #endif /* LOSCFG_KERNEL_SMP */ @@ -632,6 +959,11 @@ extern UINT32 LOS_HwiSetAffinity(HWI_HANDLE_T hwiNum, UINT32 cpuMask); * @see None * @since Huawei LiteOS V200R005C00 */ +//һ LiteOS ϵͳָжϵȼPriority +/*HWI_HANDLE_T hwiNum ǺĵһʾҪȼжϺŻжıʶ +HWI_PRIOR_T priority ǺĵڶʾҪõжȼ +ָжϵȼȷжϵͳеִȼ +ϸȼжϽȻôԴж֮ǰõӦִС*/ extern UINT32 LOS_HwiSetPriority(HWI_HANDLE_T hwiNum, HWI_PRIOR_T priority); #ifdef LOSCFG_KERNEL_LOWPOWER @@ -652,6 +984,10 @@ extern UINT32 LOS_HwiSetPriority(HWI_HANDLE_T hwiNum, HWI_PRIOR_T priority); * @see None. * @since Huawei LiteOS V200R005C10 */ +//һָ͵Ķ塣 +/*ⲿֶ˺ָָĺIJбаһΪ hwiNum IJΪ HWI_HANDLE_T +ˣ˵typedef VOID (*WAKEUPFROMINTHOOK)(HWI_HANDLE_T hwiNum) һָ WAKEUPFROMINTHOOK +ָһֵĺҸúһ HWI_HANDLE_T ͵IJ hwiNum*/ typedef VOID (*WAKEUPFROMINTHOOK)(HWI_HANDLE_T hwiNum); /** @@ -671,6 +1007,11 @@ typedef VOID (*WAKEUPFROMINTHOOK)(HWI_HANDLE_T hwiNum); * @see None. * @since Huawei LiteOS V200R005C10 */ +//עжϻѹӺⲿ +/*WAKEUPFROMINTHOOK hook ǺIJһָжϻѹӺָ롣 +עжϻѹӺ +ָĺָ루ָжϻѴָ룩עᵽϵͳУ +Աضж¼ʱִӦĴ*/ extern VOID LOS_IntWakeupHookReg(WAKEUPFROMINTHOOK hook); #endif From 4e5ee91f58e1cdca3fd6e256e1490b2a3c8cabf5 Mon Sep 17 00:00:00 2001 From: tree <1913915946@qq.com> Date: Mon, 27 Nov 2023 20:05:17 +0800 Subject: [PATCH 06/26] test --- src/kernel/base/los_queue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kernel/base/los_queue.c b/src/kernel/base/los_queue.c index f6804c0..3b217ed 100644 --- a/src/kernel/base/los_queue.c +++ b/src/kernel/base/los_queue.c @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +//队列 #include "los_queue_pri.h" #include "los_queue_debug_pri.h" #include "los_task_pri.h" From 2178a790e5eacec1853b8102ca3e47cb7ba9e383 Mon Sep 17 00:00:00 2001 From: he <1429721469@qq.com> Date: Sun, 3 Dec 2023 23:28:01 +0800 Subject: [PATCH 07/26] =?UTF-8?q?=E4=BD=95=E4=BD=B3=E8=81=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../extended/.vscode/c_cpp_properties.json | 18 ++ src/kernel/extended/.vscode/launch.json | 24 ++ src/kernel/extended/.vscode/settings.json | 59 +++++ src/kernel/extended/lowpower/los_lowpower.c | 38 +-- .../lowpower/powermgr/los_lowpower_impl.c | 222 ++++++++++-------- .../lowpower/runstop/src/los_runstop.c | 141 +++++++---- .../extended/lowpower/tickless/los_tickless.c | 31 ++- src/kernel/extended/perf/los_perf.c | 101 ++++---- src/kernel/extended/perf/perf_output.c | 22 +- src/kernel/extended/perf/perf_output_pri.h | 14 +- src/kernel/extended/perf/perf_pmu.c | 13 +- src/kernel/extended/perf/perf_pmu_pri.h | 38 +-- src/kernel/extended/perf/pmu/perf_hw_pmu.c | 50 ++-- src/kernel/extended/perf/pmu/perf_sw_pmu.c | 20 +- src/kernel/extended/perf/pmu/perf_timed_pmu.c | 40 ++-- ...代码阅读(初稿)-何佳聪-.docx | Bin 0 -> 14017 bytes 16 files changed, 505 insertions(+), 326 deletions(-) create mode 100644 src/kernel/extended/.vscode/c_cpp_properties.json create mode 100644 src/kernel/extended/.vscode/launch.json create mode 100644 src/kernel/extended/.vscode/settings.json create mode 100644 src/kernel/extended/软件工程代码阅读(初稿)-何佳聪-.docx diff --git a/src/kernel/extended/.vscode/c_cpp_properties.json b/src/kernel/extended/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..b1880ec --- /dev/null +++ b/src/kernel/extended/.vscode/c_cpp_properties.json @@ -0,0 +1,18 @@ +{ + "configurations": [ + { + "name": "windows-gcc-x64", + "includePath": [ + "${workspaceFolder}/**" + ], + "compilerPath": "D:/mingw64/bin/gcc.exe", + "cStandard": "${default}", + "cppStandard": "${default}", + "intelliSenseMode": "windows-gcc-x64", + "compilerArgs": [ + "" + ] + } + ], + "version": 4 +} \ No newline at end of file diff --git a/src/kernel/extended/.vscode/launch.json b/src/kernel/extended/.vscode/launch.json new file mode 100644 index 0000000..f78275c --- /dev/null +++ b/src/kernel/extended/.vscode/launch.json @@ -0,0 +1,24 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "C/C++ Runner: Debug Session", + "type": "cppdbg", + "request": "launch", + "args": [], + "stopAtEntry": false, + "externalConsole": true, + "cwd": "h:/ruanjian/LiteOS-Reading/src/kernel/extended/perf/pmu", + "program": "h:/ruanjian/LiteOS-Reading/src/kernel/extended/perf/pmu/build/Debug/outDebug", + "MIMode": "gdb", + "miDebuggerPath": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + } + ] +} \ No newline at end of file diff --git a/src/kernel/extended/.vscode/settings.json b/src/kernel/extended/.vscode/settings.json new file mode 100644 index 0000000..3e5eb95 --- /dev/null +++ b/src/kernel/extended/.vscode/settings.json @@ -0,0 +1,59 @@ +{ + "C_Cpp_Runner.cCompilerPath": "gcc", + "C_Cpp_Runner.cppCompilerPath": "g++", + "C_Cpp_Runner.debuggerPath": "gdb", + "C_Cpp_Runner.cStandard": "", + "C_Cpp_Runner.cppStandard": "", + "C_Cpp_Runner.msvcBatchPath": "", + "C_Cpp_Runner.useMsvc": false, + "C_Cpp_Runner.warnings": [ + "-Wall", + "-Wextra", + "-Wpedantic", + "-Wshadow", + "-Wformat=2", + "-Wcast-align", + "-Wconversion", + "-Wsign-conversion", + "-Wnull-dereference" + ], + "C_Cpp_Runner.msvcWarnings": [ + "/W4", + "/permissive-", + "/w14242", + "/w14287", + "/w14296", + "/w14311", + "/w14826", + "/w44062", + "/w44242", + "/w14905", + "/w14906", + "/w14263", + "/w44265", + "/w14928" + ], + "C_Cpp_Runner.enableWarnings": true, + "C_Cpp_Runner.warningsAsError": false, + "C_Cpp_Runner.compilerArgs": [], + "C_Cpp_Runner.linkerArgs": [], + "C_Cpp_Runner.includePaths": [], + "C_Cpp_Runner.includeSearch": [ + "*", + "**/*" + ], + "C_Cpp_Runner.excludeSearch": [ + "**/build", + "**/build/**", + "**/.*", + "**/.*/**", + "**/.vscode", + "**/.vscode/**" + ], + "C_Cpp_Runner.useAddressSanitizer": false, + "C_Cpp_Runner.useUndefinedSanitizer": false, + "C_Cpp_Runner.useLeakSanitizer": false, + "C_Cpp_Runner.showCompilationTime": false, + "C_Cpp_Runner.useLinkTimeOptimization": false, + "C_Cpp_Runner.msvcSecureNoWarnings": false +} \ No newline at end of file diff --git a/src/kernel/extended/lowpower/los_lowpower.c b/src/kernel/extended/lowpower/los_lowpower.c index bd9dde0..2a19c3e 100644 --- a/src/kernel/extended/lowpower/los_lowpower.c +++ b/src/kernel/extended/lowpower/los_lowpower.c @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - + /*低功耗管理*/ #include "los_lowpower_pri.h" #ifdef LOSCFG_KERNEL_TICKLESS #include "los_tickless_pri.h" @@ -36,10 +36,10 @@ __attribute__((section(".data"))) STATIC const PowerMgrOps *g_pmOps = NULL; -VOID OsLowpowerInit(const PowerMgrOps *pmOps) +VOID OsLowpowerInit(const PowerMgrOps *pmOps) /*初始化低功耗管理*/ { if (pmOps == NULL) { -#ifdef LOSCFG_KERNEL_POWER_MGR +#ifdef LOSCFG_KERNEL_POWER_MGR/*是否配置了低功耗内核管理*/ PRINT_ERR("\r\n [PM] PowerMgrOps must be non-null.\n"); return; #endif @@ -48,34 +48,34 @@ VOID OsLowpowerInit(const PowerMgrOps *pmOps) return; } - if (g_pmOps != NULL) { + if (g_pmOps != NULL) { PRINT_ERR("\r\n [PM] Reassignment of PowerMgrOps is forbidden.\n"); return; } g_pmOps = pmOps; LOS_LowpowerHookReg(OsPowerMgrProcess); - + /*注册低功耗处理函数和终端唤醒处理函数*/ LOS_IntWakeupHookReg(OsPowerMgrWakeUpFromInterrupt); } -VOID OsPowerMgrProcess(VOID) +VOID OsPowerMgrProcess(VOID) /*执行低功耗管理的处理过程*/ { -#ifdef LOSCFG_KERNEL_POWER_MGR +#ifdef LOSCFG_KERNEL_POWER_MGR/*判断是否配置了内核低功耗管理*/ CALL_PMOPS_FUNC_VOID(process); #else - if (g_pmOps == NULL) { + if (g_pmOps == NULL) { #ifdef LOSCFG_KERNEL_TICKLESS OsTicklessOpen(); - wfi(); + wfi(); /*管理进程进入睡眠状态*/ #endif } else { - CALL_PMOPS_FUNC_VOID(process); + CALL_PMOPS_FUNC_VOID(process);/*执行低功耗管理*/ } #endif } -VOID OsPowerMgrWakeUpFromInterrupt(UINT32 intNum) +VOID OsPowerMgrWakeUpFromInterrupt(UINT32 intNum) /*从中断唤醒处理*/ { #ifdef LOSCFG_KERNEL_POWER_MGR CALL_PMOPS_FUNC_VOID(resumeFromInterrupt, intNum); @@ -90,44 +90,44 @@ VOID OsPowerMgrWakeUpFromInterrupt(UINT32 intNum) #endif } -VOID OsPowerMgrWakeupFromReset(VOID) +VOID OsPowerMgrWakeupFromReset(VOID) /*从复位唤醒处理*/ { CALL_PMOPS_FUNC_VOID(wakeupFromReset); } -VOID LOS_PowerMgrChangeFreq(LosFreqMode freq) +VOID LOS_PowerMgrChangeFreq(LosFreqMode freq)/*改变系统频率*/ { CALL_PMOPS_FUNC_VOID(changeFreq, freq); } -VOID LOS_PowerMgrDeepSleepVoteBegin(VOID) +VOID LOS_PowerMgrDeepSleepVoteBegin(VOID)/*开始深度睡眠设置*/ { CALL_PMOPS_FUNC_VOID(deepSleepVoteBegin); } -VOID LOS_PowerMgrDeepSleepVoteEnd(VOID) +VOID LOS_PowerMgrDeepSleepVoteEnd(VOID)/*结束深度睡眠状态*/ { CALL_PMOPS_FUNC_VOID(deepSleepVoteEnd); } -VOID LOS_PowerMgrSleepDelay(UINT32 tick) +VOID LOS_PowerMgrSleepDelay(UINT32 tick)/*延迟进入睡眠状态*/ { CALL_PMOPS_FUNC_VOID(deepSleepVoteDelay, tick); } -VOID LOS_PowerMgrRegisterExtVoter(UINT32 (*callback)(VOID)) +VOID LOS_PowerMgrRegisterExtVoter(UINT32 (*callback)(VOID))/*注册外部投票者*/ { CALL_PMOPS_FUNC_VOID(registerExternalVoter, callback); } -UINT32 LOS_PowerMgrGetSleepMode(VOID) +UINT32 LOS_PowerMgrGetSleepMode(VOID)/*获取睡眠模式*/ { UINT32 ret = 0; CALL_PMOPS_FUNC_RET(getSleepMode, ret); return ret; } -UINT32 LOS_PowerMgrGetDeepSleepVoteCount(VOID) +UINT32 LOS_PowerMgrGetDeepSleepVoteCount(VOID)/*获取深度睡眠的投票计数*/ { UINT32 ret = 0; CALL_PMOPS_FUNC_RET(getDeepSleepVoteCount, ret); diff --git a/src/kernel/extended/lowpower/powermgr/los_lowpower_impl.c b/src/kernel/extended/lowpower/powermgr/los_lowpower_impl.c index 0f8cc28..78f5f94 100644 --- a/src/kernel/extended/lowpower/powermgr/los_lowpower_impl.c +++ b/src/kernel/extended/lowpower/powermgr/los_lowpower_impl.c @@ -44,7 +44,7 @@ #endif #if defined(LOSCFG_KERNEL_RUNSTOP) || defined(LOSCFG_KERNEL_DEEPSLEEP) -/* Is system is up from the memory image, then this flag should be 1; else 0 */ +/* 如果系统是从内存映像中启动的,则该标志应为1;否则为0。*/ #ifdef LOSCFG_AARCH64 __attribute__((section(".data"))) INT64 g_resumeFromImg = LOS_COLD_RESET; __attribute__((section(".data"))) STATIC INT64 g_otherCoreResume = 0; @@ -55,8 +55,8 @@ __attribute__((section(".data"))) INT32 g_otherCoreResume = 0; #ifdef LOSCFG_AARCH64 /* - * 16: The number of aligned memory, - * 34: The number of task context registers(X0~X30, SP, DAIF, NZCV) + * 16: 对齐内存的数量, + * 34: 任务上下文寄存器的数量,指寄存器的集合(X0~X30, SP, DAIF, NZCV) */ LITE_OS_SEC_DATA_MINOR __attribute__((aligned(16))) UINT64 g_saveSRContext[34]; /* 3: The number of available universal registers(X0, X1, X2) temporarily saved */ @@ -161,24 +161,24 @@ STATIC PowerMgrRunOps g_pmRunOps = { .postConfig = OsPostConfigDefault, }; -STATIC VOID OsLightSleepDefault(VOID) +STATIC VOID OsLightSleepDefault(VOID)/*轻量级睡眠函数,执行wfi指令,让处理器进入睡眠状态*/ { TRACE_FUNC_CALL(); wfi(); } -STATIC VOID OsSetWakeUpTimerDefault(UINT32 sleepTick) +STATIC VOID OsSetWakeUpTimerDefault(UINT32 sleepTick)/*设置唤醒定时器,默认实现为空函数*/ { TRACE_FUNC_CALL(); } -STATIC UINT32 OsWithrawWakeUpTimerDefault(VOID) +STATIC UINT32 OsWithrawWakeUpTimerDefault(VOID)/*撤销唤醒定时器,默认实现返回0*/ { TRACE_FUNC_CALL(); return 0; } -STATIC UINT32 OsGetSleepTimeDefault(VOID) +STATIC UINT32 OsGetSleepTimeDefault(VOID)/*获取当前任务休眠时间*/ { #ifdef LOSCFG_KERNEL_TICKLESS return OsSleepTicksGet(); @@ -187,12 +187,12 @@ STATIC UINT32 OsGetSleepTimeDefault(VOID) #endif } -STATIC UINT32 OsSelectSleepModeDefault(UINT32 sleepTicks) +STATIC UINT32 OsSelectSleepModeDefault(UINT32 sleepTicks)/*选择合适的休眠模式*/ { if (sleepTicks < g_pmMgr.minSleepTicks) { return LOS_INTERMIT_NONE; } - + /*默认实现根据休眠时间和当前系统状态选择轻量级睡眠或者深度睡眠模式*/ if (g_pmMgr.deepSleepOps != NULL && sleepTicks >= g_pmMgr.minDeepSleepTicks && g_pmRunOps.getDeepSleepVoteCount() == 0) { return LOS_INTERMIT_DEEP_SLEEP; @@ -201,73 +201,73 @@ STATIC UINT32 OsSelectSleepModeDefault(UINT32 sleepTicks) return LOS_INTERMIT_LIGHT_SLEEP; } -STATIC VOID OsChangeFreqDefault(UINT8 freq) +STATIC VOID OsChangeFreqDefault(UINT8 freq)/*改变处理器频率*/ { (VOID)freq; TRACE_FUNC_CALL(); } -STATIC VOID OsEnterDeepSleepDefault(VOID) +STATIC VOID OsEnterDeepSleepDefault(VOID)// 进入深度睡眠模式函数 { TRACE_FUNC_CALL(); wfi(); } -STATIC UINT32 OsPreConfigDefault(VOID) +STATIC UINT32 OsPreConfigDefault(VOID)//电源管理模块预配置函数 { TRACE_FUNC_CALL(); return 1; } -STATIC VOID OsPostConfigDefault(VOID) +STATIC VOID OsPostConfigDefault(VOID)//电源管理模块后配置函数 { } #ifdef LOSCFG_KERNEL_DEEPSLEEP -STATIC BOOL OsCouldDeepSleepDefault(VOID) +STATIC BOOL OsCouldDeepSleepDefault(VOID)// 判断是否可以进入深度睡眠模式 { TRACE_FUNC_CALL(); return true; } -STATIC BOOL OsSuspendPreConfigDefault(VOID) +STATIC BOOL OsSuspendPreConfigDefault(VOID)// 休眠前的预配置函数 { TRACE_FUNC_CALL(); return true; } -STATIC VOID OsSuspendDeviceDefault(VOID) +STATIC VOID OsSuspendDeviceDefault(VOID)//休眠时设备挂起函数 { TRACE_FUNC_CALL(); } -STATIC VOID OsRollBackDefault(VOID) +STATIC VOID OsRollBackDefault(VOID)//唤醒后的回滚函数 { TRACE_FUNC_CALL(); } -STATIC VOID OsResumeDeviceDefault(VOID) +STATIC VOID OsResumeDeviceDefault(VOID)//唤醒后的设备恢复函数 { TRACE_FUNC_CALL(); } -STATIC VOID OsResumePostConfigDefault(VOID) +STATIC VOID OsResumePostConfigDefault(VOID)//唤醒后电源管理模块后配置函数 { TRACE_FUNC_CALL(); } -STATIC VOID OsSystemWakeupDefault(VOID) +STATIC VOID OsSystemWakeupDefault(VOID)//系统唤醒函数 { TRACE_FUNC_CALL(); } -STATIC VOID OsResumeCallBackDefault(VOID) +STATIC VOID OsResumeCallBackDefault(VOID)//唤醒后回调函数 { TRACE_FUNC_CALL(); } -STATIC VOID OsOtherCoreResumeDefault(VOID) +STATIC VOID OsOtherCoreResumeDefault(VOID)//其他核心唤醒函数 { TRACE_FUNC_CALL(); } @@ -275,18 +275,18 @@ STATIC VOID OsOtherCoreResumeDefault(VOID) STATIC VOID OsDeepSleepResume(VOID); STATIC PowerMgrDeepSleepOps g_deepSleepOps = { - .couldDeepSleep = OsCouldDeepSleepDefault, - .systemWakeup = OsSystemWakeupDefault, - .suspendPreConfig = OsSuspendPreConfigDefault, - .suspendDevice = OsSuspendDeviceDefault, - .rollback = OsRollBackDefault, - .resumeDevice = OsResumeDeviceDefault, - .resumePostConfig = OsResumePostConfigDefault, - .resumeCallBack = OsResumeCallBackDefault, - .otherCoreResume = OsOtherCoreResumeDefault + .couldDeepSleep = OsCouldDeepSleepDefault, //判断是否可以进入深度睡眠模式的函数指针 + .systemWakeup = OsSystemWakeupDefault,//唤醒函数的函数指针 + .suspendPreConfig = OsSuspendPreConfigDefault,//修面前的预配置函数的函数指针 + .suspendDevice = OsSuspendDeviceDefault,//设备挂起函数的函数指针 + .rollback = OsRollBackDefault,//唤醒后的回滚函数的函数指针 + .resumeDevice = OsResumeDeviceDefault,//设备回复函数的函数指针 + .resumePostConfig = OsResumePostConfigDefault,//唤醒后电源管理模块后配置函数的函数指针 + .resumeCallBack = OsResumeCallBackDefault,//唤醒后回调函数的函数指针 + .otherCoreResume = OsOtherCoreResumeDefault//其他核心唤醒函数的函数指针 }; -STATIC INLINE VOID OsTickResume(UINT32 sleepTicks) +STATIC INLINE VOID OsTickResume(UINT32 sleepTicks)//用于更新系统始终,根据休眠时间调整系统时钟 { UINT32 cpuid = ArchCurrCpuid(); if (sleepTicks > g_pmMgr.sleepTime[cpuid]) { @@ -297,7 +297,7 @@ STATIC INLINE VOID OsTickResume(UINT32 sleepTicks) OsSysTimeUpdate(sleepTicks); } -STATIC VOID OsDeepSleepResume(VOID) +STATIC VOID OsDeepSleepResume(VOID)//深度睡眠唤醒后的处理函数 { DEEPOPS_CALL_FUNC_VOID(resumeFromReset); LOS_AtomicSet(&g_pmMgr.resumeSleepCores, OS_MP_CPU_ALL); @@ -305,30 +305,32 @@ STATIC VOID OsDeepSleepResume(VOID) #ifdef LOSCFG_KERNEL_CPUP OsSetCpuCycle(0); #endif - +//恢复设置,恢复其他核心进程 #if (LOSCFG_KERNEL_SMP == YES) release_secondary_cores(); #endif OsSRRestoreRegister(); } -STATIC INLINE VOID OsEnterDeepSleepMainCore(VOID) +STATIC INLINE VOID OsEnterDeepSleepMainCore(VOID)//用于主核心进入深度睡眠 { + //挂起预配置 LOS_AtomicAdd(&g_pmMgr.deepSleepCores, 1); g_deepSleepOps.suspendPreConfig(); - + //是否可以进入神对睡眠判断 if (g_pmMgr.deepSleepCores == LOSCFG_KERNEL_CORE_NUM && g_deepSleepOps.couldDeepSleep()) { g_deepSleepOps.suspendDevice(); g_pmRunOps.setWakeUpTimer(g_pmMgr.sleepTime[0]); g_resumeFromImg = LOS_COLD_RESET; OsSRSaveRegister(); - + //进入深度睡眠,进行回滚操作,保存上下文 if (g_resumeFromImg == LOS_COLD_RESET) { g_resumeFromImg = LOS_DEEP_SLEEP_RESET; CALL_RUN_OPS_FUNC_NO_RETURN(contextSave); g_pmRunOps.enterDeepSleep(); g_deepSleepOps.rollback(); } + //设置唤醒定时器 g_deepSleepOps.resumeDevice(); UINT32 sleepTicks = g_pmRunOps.withdrawWakeUpTimer(); OsSysTimeUpdate(sleepTicks); @@ -342,42 +344,43 @@ STATIC INLINE VOID OsEnterDeepSleepMainCore(VOID) LOS_AtomicSub(&g_pmMgr.deepSleepCores, 1); } -STATIC INLINE VOID OsEnterSleepMode(VOID) +STATIC INLINE VOID OsEnterSleepMode(VOID)//进入睡眠模式,包括主核心和其他核心的不同处理 { #ifdef LOSCFG_KERNEL_SMP UINT32 currCpuid = ArchCurrCpuid(); - if (currCpuid == 0) { + if (currCpuid == 0) { //如果是0则进入主核心深度睡眠 #endif OsEnterDeepSleepMainCore(); -#ifdef LOSCFG_KERNEL_SMP +#ifdef LOSCFG_KERNEL_SMP //如果当前核心不是主核心,则直接返回,因为其他核心的睡眠处理逻辑不在此函数中处理 return; } UINT32 cpuMask = 1 << currCpuid; LOS_AtomicAdd(&g_pmMgr.deepSleepCores, 1); - OsSRSaveRegister(); + OsSRSaveRegister();//保存相关寄存器状态并判断是否需要唤醒当前核心。 if (g_pmMgr.resumeSleepCores & cpuMask) { INT32 val; - do { + do { //,将 g_pmMgr.resumeSleepCores 的值中当前核心的位清零,表示该核心已被唤醒。 val = LOS_AtomicRead(&g_pmMgr.resumeSleepCores); } while (LOS_AtomicCmpXchg32bits(&g_pmMgr.resumeSleepCores, val & (~cpuMask), val)); g_deepSleepOps.otherCoreResume(); UINT32 sleepTicks = g_pmRunOps.withdrawWakeUpTimer(); OsTickResume(sleepTicks); + //执行其他核心的恢复操作,并从唤醒定时器中获取休眠时间,然后调用 OsTickResume 函数更新系统时钟。 } else { - if (g_pmMgr.deepSleepCores == LOSCFG_KERNEL_CORE_NUM) { - LOS_MpSchedule(1 << 0); + if (g_pmMgr.deepSleepCores == LOSCFG_KERNEL_CORE_NUM) {//如果不需要唤醒,则判断是否所有核心都进入了深度睡眠 + LOS_MpSchedule(1 << 0);//调用函数选择一个核心唤醒系统 } #ifdef LOSCFG_KERNEL_TICKLESS - OsTicklessOpen(); + OsTicklessOpen();//开启节能模式 #endif g_pmRunOps.enterLightSleep(); } - LOS_AtomicSub(&g_pmMgr.deepSleepCores, 1); + LOS_AtomicSub(&g_pmMgr.deepSleepCores, 1);//将 g_pmMgr.deepSleepCores 的值减1,表示当前核心已经处理完睡眠状态 #endif // LOSCFG_KERNEL_SMP } -STATIC INLINE VOID OsSystemSuspend(LosIntermitMode *mode) +STATIC INLINE VOID OsSystemSuspend(LosIntermitMode *mode)//选择合适的低功耗模式(深度,轻度 { // If enterShutdownMode is not defined, will fall through to standby mode // If enterStandbyMode is not defined, will fall through to stop mode @@ -402,10 +405,10 @@ STATIC INLINE VOID OsSystemSuspend(LosIntermitMode *mode) } #endif -STATIC VOID OsLowpowerLightSleep(UINT32 mode, UINT32 cpuid, UINT32 sleepTicks) +STATIC VOID OsLowpowerLightSleep(UINT32 mode, UINT32 cpuid, UINT32 sleepTicks)//轻度睡眠中的模式调整 { if (g_pmRunOps.preConfig != NULL) { - sleepTicks = g_pmRunOps.getSleepTime(); + sleepTicks = g_pmRunOps.getSleepTime();//获取休眠时间 } if (sleepTicks > 1) { g_pmMgr.sleepMode[cpuid] = (mode & 0x0FF); @@ -414,18 +417,19 @@ STATIC VOID OsLowpowerLightSleep(UINT32 mode, UINT32 cpuid, UINT32 sleepTicks) OsTicklessOpen(); #endif if (mode == LOS_INTERMIT_LIGHT_SLEEP && g_pmRunOps.enterLightSleep != NULL) { - g_pmRunOps.enterLightSleep(); + g_pmRunOps.enterLightSleep();//进入轻度睡眠 } else { wfi(); } } else { - g_pmMgr.sleepMode[cpuid] = LOS_INTERMIT_NONE; + g_pmMgr.sleepMode[cpuid] = LOS_INTERMIT_NONE;//等待中断事件 g_pmMgr.sleepTime[cpuid] = 0; wfi(); } } STATIC VOID OsLowpowerDeepSleep(LosIntermitMode *mode, UINT32 cpuid, UINT32 sleepTicks) +//深度睡眠设置 { #ifdef LOSCFG_KERNEL_DEEPSLEEP if (g_pmRunOps.enterDeepSleep == NULL) { @@ -438,27 +442,31 @@ STATIC VOID OsLowpowerDeepSleep(LosIntermitMode *mode, UINT32 cpuid, UINT32 slee OsSystemSuspend(mode); } #else - *mode = LOS_INTERMIT_LIGHT_SLEEP; + *mode = LOS_INTERMIT_LIGHT_SLEEP;//若不支持深度睡眠则强制进入轻度睡眠 #endif } -STATIC VOID OsLowpowerProcess(VOID) +STATIC VOID OsLowpowerProcess(VOID)//处理系统进入低功耗模式的过程 { -#ifdef LOSCFG_KERNEL_RUNSTOP +#ifdef LOSCFG_KERNEL_RUNSTOP//检查系统是否需要在进入低功耗模式前保存系统消息 if (OsWowSysDoneFlagGet() == OS_STORE_SYSTEM) { OsStoreSystemInfoBeforeSuspend(); } #endif /* Change frequency is pended, need to change the freq here. */ - if ((g_pmRunOps.changeFreq != NULL)) { + if ((g_pmRunOps.changeFreq != NULL)) {//如果需要改变频率则调整切换 OsChangeFreq(); } - + //禁止中断,锁住任务调度,并获取当前CPUID和休眠时间 UINT32 intSave = LOS_IntLock(); LOS_TaskLock(); RUNOPS_CALL_FUNC_VOID(preConfig); UINT32 cpuid = ArchCurrCpuid(); UINT32 sleepTicks = g_pmRunOps.getSleepTime(); + /*如果休眠时间小于等于最小休眠时间(g_pmMgr.minSleepTicks) + 或者有任务请求不进入深度睡眠(LOS_PowerMgrGetDeepSleepVoteCount 返回值不为0), + 则将当前 CPU 设置为不进入任何中断模式,清零休眠时间, + 并调用 postConfig 函数。*/ if (sleepTicks <= g_pmMgr.minSleepTicks || LOS_PowerMgrGetDeepSleepVoteCount() != 0) { g_pmMgr.sleepMode[cpuid] = LOS_INTERMIT_NONE; g_pmMgr.sleepTime[cpuid] = 0; @@ -477,23 +485,23 @@ STATIC VOID OsLowpowerProcess(VOID) sleepTicks = g_pmMgr.maxSleepCount; } UINT32 mode = g_pmRunOps.selectSleepMode(sleepTicks); - if (mode >= LOS_INTERMIT_DEEP_SLEEP) { + if (mode >= LOS_INTERMIT_DEEP_SLEEP) {//如果支持深度睡眠 g_pmMgr.sleepTime[cpuid] = g_pmRunOps.withdrawWakeUpTimer(); OsLowpowerDeepSleep(&mode, cpuid, sleepTicks); } RUNOPS_CALL_FUNC_VOID(postConfig); - if (mode < LOS_INTERMIT_DEEP_SLEEP) { + if (mode < LOS_INTERMIT_DEEP_SLEEP) {//进入轻度睡眠 OsLowpowerLightSleep(mode, cpuid, sleepTicks); } } LOS_TaskUnlock(); - LOS_IntRestore(intSave); + LOS_IntRestore(intSave);//解锁任务调度并恢复中断 } -STATIC VOID OsLowpowerWakeupFromReset(VOID) +STATIC VOID OsLowpowerWakeupFromReset(VOID)//处理系统从重置状态唤醒的情况 { #ifdef LOSCFG_KERNEL_RUNSTOP if (g_resumeFromImg == LOS_RUN_STOP_RESET) { @@ -508,7 +516,7 @@ STATIC VOID OsLowpowerWakeupFromReset(VOID) #endif } -STATIC VOID OsLowpowerWakeupFromInterrupt(UINT32 intNum) +STATIC VOID OsLowpowerWakeupFromInterrupt(UINT32 intNum)//用于处理系统从重置状态唤醒的情况 { #ifdef LOSCFG_KERNEL_TICKLESS OsTicklessUpdate(intNum); @@ -517,26 +525,27 @@ STATIC VOID OsLowpowerWakeupFromInterrupt(UINT32 intNum) #endif } -STATIC VOID OsChangeFreq(VOID) +STATIC VOID OsChangeFreq(VOID)//处理改变系统频率的操作 { UINT32 freq; BOOL ret; - do { + do {//尝试获取频率切换的自旋锁(通过原子操作实现) + //如果成功获取锁,则说明没有其他线程正在频率切换过程中,可以继续执行 ret = LOS_AtomicCmpXchg32bits(&g_pmMgr.freeLock, LOCK_ON, LOCK_OFF); if (ret) { return; } - freq = (UINT32)g_pmMgr.freqPending; + freq = (UINT32)g_pmMgr.freqPending;//获取频率切换的目标频率,并进行频率切换 if (freq != (UINT32)g_pmMgr.freq) { - g_pmRunOps.changeFreq(freq); + g_pmRunOps.changeFreq(freq);//更新频率 LOS_AtomicSet(&g_pmMgr.freq, (INT32)freq); } - LOS_AtomicSet(&g_pmMgr.freeLock, LOCK_OFF); + LOS_AtomicSet(&g_pmMgr.freeLock, LOCK_OFF);//释放自旋锁 } while (FreqHigher(g_pmMgr.freqPending, freq)); } -STATIC VOID OsLowpowerChangeFreq(LosFreqMode freq) +STATIC VOID OsLowpowerChangeFreq(LosFreqMode freq)//改变系统频率 { TRACE_FUNC_CALL(); if (g_pmRunOps.changeFreq == NULL) { @@ -554,36 +563,36 @@ STATIC VOID OsLowpowerChangeFreq(LosFreqMode freq) // We get a high frequency request, then change it if (FreqHigher(g_pmMgr.freqPending, g_pmMgr.freq) && g_pmRunOps.changeFreq != NULL) { - OsChangeFreq(); + OsChangeFreq();//如果目标频率高于当前频率,并且 g_pmRunOps.changeFreq 不为空,则调用 OsChangeFreq 函数进行频率切换。 } } -STATIC VOID OsLowpowerDeepSleepVoteBegin(VOID) +STATIC VOID OsLowpowerDeepSleepVoteBegin(VOID)//开始深度睡眠投票 { TRACE_FUNC_CALL(); - LOS_AtomicInc(&g_pmMgr.sleepVoteCount); + LOS_AtomicInc(&g_pmMgr.sleepVoteCount);//用原子操作将 g_pmMgr.sleepVoteCount 加一,并断言 g_pmMgr.sleepVoteCount 大于零。 LOS_ASSERT(g_pmMgr.sleepVoteCount > 0); } -STATIC VOID OsLowpowerDeepSleepVoteEnd(VOID) +STATIC VOID OsLowpowerDeepSleepVoteEnd(VOID)//结束深度睡眠投票 { TRACE_FUNC_CALL(); - LOS_AtomicDec(&g_pmMgr.sleepVoteCount); + LOS_AtomicDec(&g_pmMgr.sleepVoteCount);//原子操作将 g_pmMgr.sleepVoteCount 减一,并断言 g_pmMgr.sleepVoteCount 大于等于零。 LOS_ASSERT(g_pmMgr.sleepVoteCount >= 0); } -STATIC VOID OsLowpowerDeepSleepVoteDelay(UINT32 delayTicks) +STATIC VOID OsLowpowerDeepSleepVoteDelay(UINT32 delayTicks)//延迟深度睡眠投票 { TRACE_FUNC_CALL(); } -STATIC VOID OsLowpowerRegisterExternalVoter(LowpowerExternalVoterHandle callback) +STATIC VOID OsLowpowerRegisterExternalVoter(LowpowerExternalVoterHandle callback)//注册外部投票者 { TRACE_FUNC_CALL(); g_pmMgr.exVoterHandle = callback; } -STATIC UINT32 OsLowpowerGetDeepSleepVoteCount(VOID) +STATIC UINT32 OsLowpowerGetDeepSleepVoteCount(VOID)//获取深度睡眠投票数 { if (g_pmMgr.exVoterHandle == NULL) { return (UINT32)g_pmMgr.sleepVoteCount; @@ -593,22 +602,26 @@ STATIC UINT32 OsLowpowerGetDeepSleepVoteCount(VOID) } STATIC PowerMgrOps g_pmOps = { - .process = OsLowpowerProcess, - .wakeupFromReset = OsLowpowerWakeupFromReset, - .resumeFromInterrupt = OsLowpowerWakeupFromInterrupt, - .changeFreq = OsLowpowerChangeFreq, - .deepSleepVoteBegin = OsLowpowerDeepSleepVoteBegin, - .deepSleepVoteEnd = OsLowpowerDeepSleepVoteEnd, - .deepSleepVoteDelay = OsLowpowerDeepSleepVoteDelay, - .registerExternalVoter = OsLowpowerRegisterExternalVoter, - .getDeepSleepVoteCount = OsLowpowerGetDeepSleepVoteCount, - .getSleepMode = NULL, - .setSleepMode = NULL, + .process = OsLowpowerProcess, //该函数指针用于处理低功耗过程,即在进入低功耗模式前需要执行的操作 + .wakeupFromReset = OsLowpowerWakeupFromReset,//该函数指针用于处理从复位状态唤醒时的操作 + .resumeFromInterrupt = OsLowpowerWakeupFromInterrupt,//该函数指针用于处理从中断状态恢复时的操作。 + .changeFreq = OsLowpowerChangeFreq,//该函数指针用于改变系统频率的操作,可以根据需要调整系统的工作频率 + .deepSleepVoteBegin = OsLowpowerDeepSleepVoteBegin,//该函数指针用于开始深度休眠投票,即在进入深度休眠模式前需要执行的操作 + .deepSleepVoteEnd = OsLowpowerDeepSleepVoteEnd,//该函数指针用于结束深度休眠投票,即在退出深度休眠模式后需要执行的操作 + .deepSleepVoteDelay = OsLowpowerDeepSleepVoteDelay,//该函数指针用于处理深度休眠投票延迟的操作,可以根据需要延迟深度休眠的投票 + .registerExternalVoter = OsLowpowerRegisterExternalVoter,//该函数指针用于注册外部投票者,即在系统中存在其他模块也需要参与低功耗投票时的操作 + .getDeepSleepVoteCount = OsLowpowerGetDeepSleepVoteCount,//该函数指针用于获取当前深度休眠投票的数量,可以用来监控系统中参与休眠投票的模块数量 + .getSleepMode = NULL,//该函数指针用于获取当前的睡眠模式,即获取系统当前是否处于睡眠状态 + .setSleepMode = NULL,//该函数指针用于设置睡眠模式,即将系统设置为指定的睡眠模式 + //以上提及的函数均为函数指针 }; #define FORCE_NULL_CALLBACK (void *)0x3f3f3f3f - -#define ASSIGN_MEMBER(lhs, rhs, member) \ +//以下定义是用于给结构体成员赋值,如果某个回调函数指针为特殊空值,则将相应的成员置为空,否则进行赋值 +#define ASSIGN_MEMBER(lhs, rhs, member) +//lhs 是左操作数,表示要赋值的结构体指针; +//rhs 是右操作数,表示要赋给成员的值; +//member 是要赋值的结构体成员 do { \ if ((rhs)->member == FORCE_NULL_CALLBACK) { \ (lhs)->member = NULL; \ @@ -631,16 +644,16 @@ VOID LOS_PowerMgrInit(const PowerMgrParameter *para) const PowerMgrRunOps *runOps = NULL; const PowerMgrDeepSleepOps *deepSleepOps = NULL; (void)deepSleepOps; - if (para != NULL) { + if (para != NULL) { //如果para为空,则运行操作和深度睡眠操作都为空指针 runOps = ¶->runOps; #ifdef LOSCFG_KERNEL_DEEPSLEEP deepSleepOps = ¶->deepSleepOps; #endif - g_pmMgr.minSleepTicks = para->config.minLightSleepTicks; - g_pmMgr.maxSleepCount = para->config.maxDeepSleepTicks; - g_pmMgr.minDeepSleepTicks = para->config.minDeepSleepTicks; + g_pmMgr.minSleepTicks = para->config.minLightSleepTicks;//记录了系统中需要从睡眠状态唤醒的 CPU 核心数 + g_pmMgr.maxSleepCount = para->config.maxDeepSleepTicks;//用于保护电源管理模块在多线程环境下的并发访问 + g_pmMgr.minDeepSleepTicks = para->config.minDeepSleepTicks;//记录自旋锁是否被释放 } - + //将传入的运行操作和深度睡眠操作分别赋值给全局变量 g_pmRunOps 和 g_deepSleepOps LOS_AtomicSet(&g_pmMgr.resumeSleepCores, 0); LOS_SpinInit(&g_pmMgr.lock); @@ -648,25 +661,25 @@ VOID LOS_PowerMgrInit(const PowerMgrParameter *para) // verify and assign input operators. if (runOps != NULL) { - ASSIGN_MEMBER(&g_pmRunOps, runOps, changeFreq); - ASSIGN_MEMBER(&g_pmRunOps, runOps, enterLightSleep); + ASSIGN_MEMBER(&g_pmRunOps, runOps, changeFreq);//改变CPU频率 + ASSIGN_MEMBER(&g_pmRunOps, runOps, enterLightSleep);//进入浅度睡眠 #ifdef LOSCFG_KERNEL_DEEPSLEEP - ASSIGN_MEMBER_NOT_NULL(&g_pmRunOps, runOps, enterDeepSleep); - ASSIGN_MEMBER_NOT_NULL(&g_pmRunOps, runOps, setWakeUpTimer); - ASSIGN_MEMBER_NOT_NULL(&g_pmRunOps, runOps, withdrawWakeUpTimer); + ASSIGN_MEMBER_NOT_NULL(&g_pmRunOps, runOps, enterDeepSleep);//进入深度睡眠 + ASSIGN_MEMBER_NOT_NULL(&g_pmRunOps, runOps, setWakeUpTimer);//设置唤醒定时器 + ASSIGN_MEMBER_NOT_NULL(&g_pmRunOps, runOps, withdrawWakeUpTimer);//撤销定时器 #else ASSIGN_MEMBER(&g_pmRunOps, runOps, enterDeepSleep); ASSIGN_MEMBER(&g_pmRunOps, runOps, setWakeUpTimer); ASSIGN_MEMBER(&g_pmRunOps, runOps, withdrawWakeUpTimer); #endif - ASSIGN_MEMBER_NOT_NULL(&g_pmRunOps, runOps, getSleepTime); - ASSIGN_MEMBER_NOT_NULL(&g_pmRunOps, runOps, selectSleepMode); - ASSIGN_MEMBER(&g_pmRunOps, runOps, preConfig); - ASSIGN_MEMBER(&g_pmRunOps, runOps, postConfig); + ASSIGN_MEMBER_NOT_NULL(&g_pmRunOps, runOps, getSleepTime);//货的睡眠时间 + ASSIGN_MEMBER_NOT_NULL(&g_pmRunOps, runOps, selectSleepMode);//选择不同的睡眠模式 + ASSIGN_MEMBER(&g_pmRunOps, runOps, preConfig);//预配置 + ASSIGN_MEMBER(&g_pmRunOps, runOps, postConfig);//后配置 } #ifdef LOSCFG_KERNEL_DEEPSLEEP - if (deepSleepOps != NULL) { + if (deepSleepOps != NULL) {//进入深度睡眠 ASSIGN_MEMBER(&g_deepSleepOps, deepSleepOps, couldDeepSleep); ASSIGN_MEMBER(&g_deepSleepOps, deepSleepOps, systemWakeup); ASSIGN_MEMBER(&g_deepSleepOps, deepSleepOps, suspendPreConfig); @@ -680,4 +693,7 @@ VOID LOS_PowerMgrInit(const PowerMgrParameter *para) #endif // Register PowerMgr to Low-Power Framework. LOS_LowpowerInit(&g_pmOps); + //将电源管理模块注册到低功耗框架中。 + //低功耗框架是一个用于管理处理器和设备进入低功耗模式的软件框架, + //它能够最大限度地降低系统能耗,提高系统的电池寿命 } diff --git a/src/kernel/extended/lowpower/runstop/src/los_runstop.c b/src/kernel/extended/lowpower/runstop/src/los_runstop.c index 0da74e3..f529d6a 100644 --- a/src/kernel/extended/lowpower/runstop/src/los_runstop.c +++ b/src/kernel/extended/lowpower/runstop/src/los_runstop.c @@ -51,22 +51,28 @@ extern "C" { /* 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; @@ -76,15 +82,17 @@ 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; + 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, @@ -109,29 +117,32 @@ LITE_OS_SEC_TEXT_MINOR STATIC VOID OsDoWriteWow2Flash(FLASH_WRITE_FUNC flashWrit return; } } - -LITE_OS_SEC_TEXT_MINOR VOID OsWriteWow2Flash(VOID) +/*首先检查内存中的大小是否为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; + FlashWriteParam heapMemSection; /*这是三种闪存内部独立的堆专用的内存区域对应的闪存写入参数*/ + size_t eraseAlignSize; /*表示闪存擦除时的对齐大小*/ + size_t writeAlignSize; /*闪存写入时的对齐大小*/ FLASH_WRITE_FUNC flashWriteFunc = g_runstopParam.pfFlashWriteFunc; - eraseAlignSize = g_runstopParam.uwFlashEraseAlignSize; - writeAlignSize = g_runstopParam.uwFlashWriteAlignSize; + 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.flashStart = g_flashImgAddr; + 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; @@ -152,39 +163,41 @@ LITE_OS_SEC_TEXT_MINOR VOID OsWriteWow2Flash(VOID) g_wowImgSize = wowSection.memSize + heapMemSection.memSize + excHeapSection.memSize; OsDoWriteWow2Flash(flashWriteFunc, &wowSection, &excHeapSection, &heapMemSection); + /*将变量传输给函数,由其实现相应的写入操作*/ } -LITE_OS_SEC_TEXT_MINOR VOID OsSystemSuspend(VOID) +LITE_OS_SEC_TEXT_MINOR VOID OsSystemSuspend(VOID) /*实现系统的挂起操作*/ { - UINT32 cpuid; + UINT32 cpuid; /*获取当前CPU的ID*/ - (VOID)LOS_IntLock(); + (VOID)LOS_IntLock(); LOS_TaskLock(); cpuid = ArchCurrCpuid(); + /*禁止中断并锁定任务调度器,确保在执行挂起操作期间不会被打断*/ + g_sysDoneFlag[cpuid] = OS_NO_STORE_SYSTEM; /*将当前CPU的系统挂起标志设置为不需要保存系统状态*/ + g_saveTsk[cpuid] = OsCurrTaskGet(); /*保存当前任务指针到savetask变量中*/ - g_sysDoneFlag[cpuid] = OS_NO_STORE_SYSTEM; - g_saveTsk[cpuid] = OsCurrTaskGet(); - - OsSRSaveRegister(); + OsSRSaveRegister(); /*保存当前CPU的寄存器状态,以便在恢复系统时能够正确恢复到挂起前的状态*/ /* If 1 core, only to save registers */ - if (cpuid != 0) { - if (g_otherCoreResume != 0) { + if (cpuid != 0) { /*若此CPU部位0号内核*/ + if (g_otherCoreResume != 0) { /*说明其他多核核心需要恢复运行*/ HalIrqInitPercpu(); OsTickStart(); LOS_TaskUnlock(); (VOID)LOS_IntUnLock(); - return; + return; } - g_sysDoneFlag[cpuid - 1] = OS_STORE_SYSTEM; + g_sysDoneFlag[cpuid - 1] = OS_STORE_SYSTEM; /*需要初始化中断并启动系统时钟,并最终解锁任务调度器并恢复中断*/ while (1) {} } - if (g_resumeFromImg) { + if (g_resumeFromImg) { /*如果是 0 号 CPU,且系统需要从镜像中恢复(g_resumeFromImg 为真)*/ OsWriteWow2Flash(); LOS_TaskUnlock(); (VOID)LOS_IntUnLock(); (VOID)LOS_EventWrite(&g_suspendResumeEvent, FLASH_IMG_SUCCESS); - } else { + /*调用 OsWriteWow2Flash 函数将数据写入闪存,并发送 FLASH_IMG_SUCCESS 事件信号,表示成功从镜像中恢复*/ + } else { /*不需要从镜像中恢复*/ OsTickStart(); LOS_TaskUnlock(); (VOID)LOS_IntUnLock(); @@ -194,9 +207,15 @@ LITE_OS_SEC_TEXT_MINOR VOID OsSystemSuspend(VOID) } (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); @@ -207,6 +226,10 @@ LITE_OS_SEC_TEXT VOID OsWriteToFlashTask(VOID) } 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) { @@ -218,6 +241,9 @@ LITE_OS_SEC_TEXT VOID OsStoreSystemInfoBeforeSuspend(VOID) } LITE_OS_SEC_TEXT_MINOR VOID OsSystemWakeup(VOID) +/*是系统从挂起状态唤醒后的处理函数。*/ + + { UINT32 cpuid; errno_t err; @@ -225,7 +251,7 @@ LITE_OS_SEC_TEXT_MINOR VOID OsSystemWakeup(VOID) if (!g_resumeFromImg) { return; } - +/*进行一些内存数据的复制操作,然后设置当前 CPU 的任务指针,*/ #ifdef LOSCFG_EXC_INTERACTION err = memmove_s(m_aucSysMem0, g_excInteractMemSize, g_excInteractionMemStart, g_excInteractionMemSize); if (err != EOK) { @@ -243,6 +269,7 @@ LITE_OS_SEC_TEXT_MINOR VOID OsSystemWakeup(VOID) cpuid = ArchCurrCpuid(); OsCurrTaskSet(g_saveTsk[cpuid]); +/*设置系统计数器频率。接着,它重置内存池的末尾节点,清零 BSS 区域的数据,重新初始化中断*/ /* Set system counter freq */ HalClockFreqWrite(OS_SYS_CLOCK); dsb(); @@ -270,7 +297,7 @@ LITE_OS_SEC_TEXT_MINOR VOID OsSystemWakeup(VOID) #ifdef LOSCFG_KERNEL_CPUP OsSetCpuCycle(0); #endif - +/*并调用 OsSRRestoreRegister 函数恢复寄存器状态*/ #if (LOSCFG_KERNEL_SMP == YES) release_secondary_cores(); #endif @@ -281,32 +308,33 @@ LITE_OS_SEC_TEXT_MINOR UINT32 OsWaitImagingDone(UINTPTR wowFlashAddr, size_t *wo { UINT32 ret; - g_flashImgAddr = wowFlashAddr; - (VOID)LOS_EventInit(&g_suspendResumeEvent); + g_flashImgAddr = wowFlashAddr; /*烧录的flash地址*/ + (VOID)LOS_EventInit(&g_suspendResumeEvent); /*指向用于存储烧录镜像大小的变量的指针*/ - // This flag will be stored into flash, and will affect the wakeup procedure when cpu is rebooting. + // 这个标志将被存储到闪存中,当 CPU 重新启动时,它将影响唤醒流程。 g_resumeFromImg = LOS_RUN_STOP_RESET; - // This flag affects the suspending procedure later, - // and will be reset depending on 'g_resumeFromImg' when cpu is rebooting. + // 这个标志会影响之后的挂起过程,并且在 CPU 重新启动时根据 'g_resumeFromImg' 的值进行重置 g_otherCoreResume = 0; - g_sysDoneFlag[LOSCFG_KERNEL_CORE_NUM - 1] = OS_STORE_SYSTEM; + 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) +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; + size_t wowSize;/*等待复制数据的大小*/ + size_t readAlignSize;/*读取对齐大小*/ + size_t eraseAlignSize;/*擦除对齐大小*/ + size_t writeAlignSize;/*写入对齐大小*/ + /*读取所有参数的初始状态*/ UINTPTR imageFlashAddr; FLASH_READ_FUNC flashReadFunc = g_runstopParam.pfFlashReadFunc; @@ -315,18 +343,19 @@ LITE_OS_SEC_TEXT_MINOR VOID OsCarryLeftScatter(VOID) 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__); } @@ -336,6 +365,8 @@ LITE_OS_SEC_TEXT_MINOR VOID OsCarryLeftScatter(VOID) } LITE_OS_SEC_TEXT_MINOR VOID OsRunstopParamInit(const RUNSTOP_PARAM_S *runstopParam) +/*初始化运行暂停功能所需的参数,保存在全局变量g_中,以便告诉计算机目前的系统转台 +包含了运行暂停功能所需的各个回调函数和对齐大小等参数*/ { g_runstopParam.pfIdleWakeupCallback = runstopParam->pfIdleWakeupCallback; g_runstopParam.pfWakeupCallback = runstopParam->pfWakeupCallback; @@ -350,28 +381,31 @@ LITE_OS_SEC_TEXT_MINOR VOID OsRunstopParamInit(const RUNSTOP_PARAM_S *runstopPar } 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); - if (ret == WAKEUP_FROM_SUSPEND) { + /*用于等待图像转移完成,范围相应的状态码ret和图像大小imgsize*/ + if (ret == WAKEUP_FROM_SUSPEND) { /*从暂停状态唤醒,并查看系统是否需要空闲唤醒回调*/ if (g_runstopParam.pfWakeupCallback != NULL) { g_runstopParam.pfWakeupCallback(); } - OsCarryLeftScatter(); + OsCarryLeftScatter(); /*将RAM中的数据复制到Flash存储器*/ PRINT_INFO("Resume ok!\n"); - } else if (ret == FLASH_IMG_SUCCESS) { + } else if (ret == FLASH_IMG_SUCCESS) { /*闪存图像成功*/ if (g_runstopParam.pfImageDoneCallback != NULL) { g_runstopParam.pfImageDoneCallback(); } - PRINT_INFO("Flash ok! Image length 0x%x\n", imgSize); + PRINT_INFO("Flash ok! Image length 0x%x\n", imgSize);/*图像转移成功,并打印图像大小*/ } } @@ -380,8 +414,9 @@ 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"; @@ -389,24 +424,28 @@ LITE_OS_SEC_TEXT_MINOR UINT32 OsWowWriteFlashTaskCreate(VOID) #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) { + if (g_otherCoreResume == 1) { /*全局变量的值为1则表示需要唤醒其他核心*/ OsCurrTaskSet(g_saveTsk[cpuid]); OsSRRestoreRegister(); } diff --git a/src/kernel/extended/lowpower/tickless/los_tickless.c b/src/kernel/extended/lowpower/tickless/los_tickless.c index fdeb5b8..d609b1e 100644 --- a/src/kernel/extended/lowpower/tickless/los_tickless.c +++ b/src/kernel/extended/lowpower/tickless/los_tickless.c @@ -46,42 +46,46 @@ STATIC volatile UINT32 g_sleepTicks[LOSCFG_KERNEL_CORE_NUM] = {0}; (((GET_SYS_CLOCK()) / (g_tickPerSecond)) - (cyclesCur)) : \ ((((GET_SYS_CLOCK()) / (g_tickPerSecond)) << 1) - (cyclesCur))) -LITE_OS_SEC_TEXT VOID LOS_TicklessEnable(VOID) +LITE_OS_SEC_TEXT VOID LOS_TicklessEnable(VOID) /*开启Tickless功能*/ { g_ticklessFlag = TRUE; + /*变量表示Tickless功能的开启状态,为TRUE表示已开启,为FALSE表示已关闭。*/ } -LITE_OS_SEC_TEXT VOID LOS_TicklessDisable(VOID) +LITE_OS_SEC_TEXT VOID LOS_TicklessDisable(VOID) /*开启Tickless功能*/ { g_ticklessFlag = FALSE; } -LITE_OS_SEC_TEXT BOOL OsTicklessFlagGet(VOID) +LITE_OS_SEC_TEXT BOOL OsTicklessFlagGet(VOID) /*用于获取Tickless标志的状态*/ { return g_ticklessFlag; } -LITE_OS_SEC_TEXT BOOL OsTickIrqFlagGet(VOID) +LITE_OS_SEC_TEXT BOOL OsTickIrqFlagGet(VOID) { return g_tickIrqFlag[ArchCurrCpuid()]; + /*数组表示每个核心的Tick中断标志的状态, + 为TRUE表示中断正在处理中,为FALSE表示中断未处理。*/ } -LITE_OS_SEC_TEXT VOID OsTickIrqFlagSet(BOOL tickIrqFlag) +LITE_OS_SEC_TEXT VOID OsTickIrqFlagSet(BOOL tickIrqFlag) /*用于设置当前核心的时钟中断标志*/ { g_tickIrqFlag[ArchCurrCpuid()] = tickIrqFlag; } -LITE_OS_SEC_TEXT UINT32 OsTicklessSleepTickGet(VOID) +LITE_OS_SEC_TEXT UINT32 OsTicklessSleepTickGet(VOID) /*用于获取当前系统的睡眠计时器的数值*/ { return g_sleepTicks[ArchCurrCpuid()]; } -LITE_OS_SEC_TEXT VOID OsTicklessSleepTickSet(UINT32 sleeptick) +LITE_OS_SEC_TEXT VOID OsTicklessSleepTickSet(UINT32 sleeptick) /*设置当前核心得到睡眠计时器的数值*/ { g_sleepTicks[ArchCurrCpuid()] = sleeptick; } -LITE_OS_SEC_TEXT UINT32 OsSleepTicksGet(VOID) +LITE_OS_SEC_TEXT UINT32 OsSleepTicksGet(VOID) /*函数用于获取当前需要休眠的ticks数,通过查询任务链表和软件定时器链表, + 找到最小的定时器到期时间,作为休眠时长。*/ { UINT32 tskSortLinkTicks, sleepTicks; @@ -104,7 +108,8 @@ LITE_OS_SEC_TEXT UINT32 OsSleepTicksGet(VOID) return sleepTicks; } -LITE_OS_SEC_TEXT VOID OsSysTimeUpdate(UINT32 sleepTicks) +LITE_OS_SEC_TEXT VOID OsSysTimeUpdate(UINT32 sleepTicks) /*用于更新系统时间, + 根据休眠时长更新全局计数器和任务链表、软件定时器链表的到期时间*/ { UINT32 intSave; @@ -127,7 +132,7 @@ LITE_OS_SEC_TEXT VOID OsSysTimeUpdate(UINT32 sleepTicks) LOS_IntRestore(intSave); } -VOID OsTicklessUpdate(UINT32 irqnum) +VOID OsTicklessUpdate(UINT32 irqnum) /*OsTicklessUpdate函数用于在发生中断时更新系统时间*/ { UINT32 cycles, ticks; UINT32 cyclesPertick; @@ -165,7 +170,8 @@ VOID OsTicklessUpdate(UINT32 irqnum) LOS_IntRestore(intSave); } -VOID OsTicklessStart(VOID) +VOID OsTicklessStart(VOID) /*Tickless模式的入口函数,根据休眠时长计算需要延迟的周期数, + 并设置定时器的重载值,启动Tickless模式。*/ { UINT32 intSave; /* @@ -202,7 +208,8 @@ VOID OsTicklessStart(VOID) return; } -VOID OsTicklessOpen(VOID) +VOID OsTicklessOpen(VOID) /*在Tick中断处理函数中开启Tickless模式。 + 当Tick中断处理函数检测到Tickless标志为1时,调用该函数启动Tickless模式。*/ { if (OsTickIrqFlagGet()) { OsTickIrqFlagSet(0); diff --git a/src/kernel/extended/perf/los_perf.c b/src/kernel/extended/perf/los_perf.c index ecb0c2e..e8b84f6 100644 --- a/src/kernel/extended/perf/los_perf.c +++ b/src/kernel/extended/perf/los_perf.c @@ -37,10 +37,11 @@ extern "C" { #endif /* __cplusplus */ #ifdef LOSCFG_KERNEL_PERF -STATIC Pmu *g_pmu = NULL; -STATIC PerfCB g_perfCb = {0}; +STATIC Pmu *g_pmu = NULL;//用于保存当前系统中所使用的硬件性能计数器 +STATIC PerfCB g_perfCb = {0};//保存了性能测量回调函数和一些测量结果数据 LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_perfSpin); +//定义了一个自旋锁 g_perfSpin,用于保护性能测量模块在多线程环境下的并发访问 #define PERF_LOCK(state) LOS_SpinLockSave(&g_perfSpin, &(state)) #define PERF_UNLOCK(state) LOS_SpinUnlockRestore(&g_perfSpin, (state)) @@ -55,8 +56,9 @@ STATIC INLINE UINT64 OsPerfGetCurrTime(VOID) #endif } -STATIC UINT32 OsPmuInit(VOID) +STATIC UINT32 OsPmuInit(VOID)//初始化性能计数器 { + //判断是否开启了计数器 #ifdef LOSCFG_PERF_HW_PMU if (OsHwPmuInit() != LOS_OK) { return LOS_ERRNO_PERF_HW_INIT_ERROR; @@ -77,13 +79,13 @@ STATIC UINT32 OsPmuInit(VOID) return LOS_OK; } -STATIC UINT32 OsPerfConfig(PerfEventConfig *eventsCfg) +STATIC UINT32 OsPerfConfig(PerfEventConfig *eventsCfg)//配置性能计数器 { UINT32 i; UINT32 ret; g_pmu = OsPerfPmuGet(eventsCfg->type); - if (g_pmu == NULL) { + if (g_pmu == NULL) {//根据配置的类型获取对应的性能计数器对象 PRINT_ERR("perf config type error %u!\n", eventsCfg->type); return LOS_ERRNO_PERF_INVALID_PMU; } @@ -92,6 +94,7 @@ STATIC UINT32 OsPerfConfig(PerfEventConfig *eventsCfg) (VOID)memset_s(&g_pmu->events, sizeof(PerfEvent), 0, sizeof(PerfEvent)); +//根据配置信息设置各性能事件的参数,调用性能计数器对象的配置函数进行配置 for (i = 0; i < eventNum; i++) { g_pmu->events.per[i].eventId = eventsCfg->events[i].eventId; g_pmu->events.per[i].period = eventsCfg->events[i].period; @@ -109,13 +112,13 @@ STATIC UINT32 OsPerfConfig(PerfEventConfig *eventsCfg) return LOS_OK; } -STATIC VOID OsPerfPrintCount(VOID) +STATIC VOID OsPerfPrintCount(VOID)//用于打印性能计数器的统计信息 { UINT32 index; UINT32 intSave; UINT32 cpuid = ArchCurrCpuid(); - PerfEvent *events = &g_pmu->events; + PerfEvent *events = &g_pmu->events;//获取性能计数器对象的性能时间数组和事件数量 UINT32 eventNum = events->nr; PERF_LOCK(intSave); @@ -123,7 +126,7 @@ STATIC VOID OsPerfPrintCount(VOID) Event *event = &(events->per[index]); /* filter out event counter with no event binded. */ - if (event->period == 0) { + if (event->period == 0) { //事件周期 continue; } PRINT_EMG("[%s] eventType: 0x%x [core %u]: %llu\n", g_pmu->getName(event), event->eventId, cpuid, @@ -132,7 +135,7 @@ STATIC VOID OsPerfPrintCount(VOID) PERF_UNLOCK(intSave); } -STATIC INLINE VOID OsPerfPrintTs(VOID) +STATIC INLINE VOID OsPerfPrintTs(VOID)//打印时间信息 { #ifdef LOSCFG_PERF_CALC_TIME_BY_TICK DOUBLE time = (g_perfCb.endTime - g_perfCb.startTime) * 1.0 / LOSCFG_BASE_CORE_TICK_PER_SECOND; @@ -142,7 +145,7 @@ STATIC INLINE VOID OsPerfPrintTs(VOID) PRINT_EMG("time used: %.6f(s)\r\n", time); } -STATIC VOID OsPerfStart(VOID) +STATIC VOID OsPerfStart(VOID)//启动及更新CPU和计数器状态 { UINT32 cpuid = ArchCurrCpuid(); @@ -152,7 +155,7 @@ STATIC VOID OsPerfStart(VOID) } if (g_perfCb.pmuStatusPerCpu[cpuid] != PERF_PMU_STARTED) { - UINT32 ret = g_pmu->start(); + UINT32 ret = g_pmu->start();//若计数器未启动则启动 if (ret != LOS_OK) { PRINT_ERR("perf start on core:%u failed, ret = 0x%x\n", cpuid, ret); return; @@ -164,7 +167,7 @@ STATIC VOID OsPerfStart(VOID) } } -STATIC VOID OsPerfStop(VOID) +STATIC VOID OsPerfStop(VOID)//停止性能计数器 { UINT32 cpuid = ArchCurrCpuid(); @@ -191,19 +194,21 @@ STATIC VOID OsPerfStop(VOID) } STATIC UINT32 OsPerfBackTrace(UINTPTR *callChain, UINT32 maxDepth, PerfRegs *regs) +//获取当前函数调用链的信息,并将结果存储在 callChain 数组中 { UINT32 i; - UINT32 count = ArchBackTraceGet(regs->fp, callChain, maxDepth); + UINT32 count = ArchBackTraceGet(regs->fp, callChain, maxDepth);//获取当前状态的帧指针值 PRINT_DEBUG("backtrace depth = %u, fp = 0x%x\n", count, regs->fp); for (i = 0; i < count; i++) { - PRINT_DEBUG("ip[%u]: 0x%x\n", i, callChain[i]); + PRINT_DEBUG("ip[%u]: 0x%x\n", i, callChain[i]);//打印调用链中每个函数的指令地址 } - return count; + return count;//返回用链的深度 } STATIC UINT32 OsPerfCollectData(Event *event, PerfSampleData *data, PerfRegs *regs) +//收集性能计数器的数据,并将其存储在 data 结构体中 { UINT32 size = 0; UINT32 depth; @@ -211,12 +216,12 @@ STATIC UINT32 OsPerfCollectData(Event *event, PerfSampleData *data, PerfRegs *re CHAR *p = (CHAR *)data; if (sampleType & PERF_RECORD_CPU) { - *(UINT32 *)(p + size) = ArchCurrCpuid(); + *(UINT32 *)(p + size) = ArchCurrCpuid();//函数获取当前CPU的ID,并存储在 data->cpuid 字段中 size += sizeof(data->cpuid); } if (sampleType & PERF_RECORD_TID) { - *(UINT32 *)(p + size) = LOS_CurTaskIDGet(); + *(UINT32 *)(p + size) = LOS_CurTaskIDGet();// 函数获取当前任务的ID,并存储在 data->taskId 字段中 size += sizeof(data->taskId); } @@ -231,7 +236,7 @@ STATIC UINT32 OsPerfCollectData(Event *event, PerfSampleData *data, PerfRegs *re } if (sampleType & PERF_RECORD_TIMESTAMP) { - *(UINT64 *)(p + size) = OsPerfGetCurrTime(); + *(UINT64 *)(p + size) = OsPerfGetCurrTime();//获取当前时间戳,并存储在 data->time 字段中 size += sizeof(data->time); } @@ -254,7 +259,7 @@ STATIC UINT32 OsPerfCollectData(Event *event, PerfSampleData *data, PerfRegs *re * return TRUE if user haven't specified any taskId(which is supposed * to instrument the whole system) */ -STATIC BOOL OsPerfTaskFilter(UINT32 taskId) +STATIC BOOL OsPerfTaskFilter(UINT32 taskId)//过滤任务ID,判断一个给定的任务ID是否需要进行性能优化 { UINT32 i; @@ -262,7 +267,7 @@ STATIC BOOL OsPerfTaskFilter(UINT32 taskId) return TRUE; } - for (i = 0; i < g_perfCb.taskIdsNr; i++) { + for (i = 0; i < g_perfCb.taskIdsNr; i++) { //储存允许过滤任务ID的列表 if (g_perfCb.taskIds[i] == taskId) { return TRUE; } @@ -270,7 +275,7 @@ STATIC BOOL OsPerfTaskFilter(UINT32 taskId) return FALSE; } -STATIC INLINE UINT32 OsPerfParamValid(VOID) +STATIC INLINE UINT32 OsPerfParamValid(VOID)//检查性能函数的有效性 { UINT32 index; UINT32 res = 0; @@ -287,7 +292,7 @@ STATIC INLINE UINT32 OsPerfParamValid(VOID) return res; } -STATIC UINT32 OsPerfHdrInit(UINT32 id) +STATIC UINT32 OsPerfHdrInit(UINT32 id)//初始化性能数据的头部信息 { PerfDataHdr head = { .magic = PERF_DATA_MAGIC_WORD, @@ -299,7 +304,7 @@ STATIC UINT32 OsPerfHdrInit(UINT32 id) return OsPerfOutPutWrite((CHAR *)&head, head.len); } -VOID OsPerfUpdateEventCount(Event *event, UINT32 value) +VOID OsPerfUpdateEventCount(Event *event, UINT32 value)//更新上传事件的技术 { if (event == NULL) { return; @@ -307,46 +312,46 @@ VOID OsPerfUpdateEventCount(Event *event, UINT32 value) event->count[ArchCurrCpuid()] += (value & 0xFFFFFFFF); /* event->count is UINT64 */ } -VOID OsPerfHandleOverFlow(Event *event, PerfRegs *regs) +VOID OsPerfHandleOverFlow(Event *event, PerfRegs *regs)//处理性能计数器溢出的情况 { PerfSampleData data; UINT32 len; (VOID)memset_s(&data, sizeof(PerfSampleData), 0, sizeof(PerfSampleData)); - if ((g_perfCb.needSample) && OsPerfTaskFilter(LOS_CurTaskIDGet())) { + if ((g_perfCb.needSample) && OsPerfTaskFilter(LOS_CurTaskIDGet())) {//判断是否优化 len = OsPerfCollectData(event, &data, regs); OsPerfOutPutWrite((CHAR *)&data, len); } } -UINT32 LOS_PerfInit(VOID *buf, UINT32 size) +UINT32 LOS_PerfInit(VOID *buf, UINT32 size)//初始化性能统计模块 { UINT32 ret; UINT32 intSave; - PERF_LOCK(intSave); + PERF_LOCK(intSave);//保存中断状态 if (g_perfCb.status != PERF_UNINIT) { ret = LOS_ERRNO_PERF_STATUS_INVALID; goto PERF_INIT_ERROR; } - ret = OsPmuInit(); + ret = OsPmuInit();//函数性能计数器初始化 if (ret != LOS_OK) { goto PERF_INIT_ERROR; } - ret = OsPerfOutPutInit(buf, size); + ret = OsPerfOutPutInit(buf, size);//性能输出缓冲区进行初始化 if (ret != LOS_OK) { ret = LOS_ERRNO_PERF_BUF_ERROR; goto PERF_INIT_ERROR; } g_perfCb.status = PERF_STOPED; PERF_INIT_ERROR: - PERF_UNLOCK(intSave); + PERF_UNLOCK(intSave);//解锁中断处理 return ret; } -UINT32 LOS_PerfConfig(PerfConfigAttr *attr) +UINT32 LOS_PerfConfig(PerfConfigAttr *attr)//配置性能统计模块的属性 { UINT32 ret; UINT32 intSave; @@ -355,20 +360,20 @@ UINT32 LOS_PerfConfig(PerfConfigAttr *attr) return LOS_ERRNO_PERF_CONFIG_NULL; } - PERF_LOCK(intSave); + PERF_LOCK(intSave);//保存中断状态 if (g_perfCb.status != PERF_STOPED) { ret = LOS_ERRNO_PERF_STATUS_INVALID; PRINT_ERR("perf config status error : 0x%x\n", g_perfCb.status); goto PERF_CONFIG_ERROR; } - g_pmu = NULL; + g_pmu = NULL;//将全局标量PMU计数器置零 g_perfCb.needSample = attr->needSample; g_perfCb.taskFilterEnable = attr->taskFilterEnable; g_perfCb.sampleType = attr->sampleType; - if (attr->taskFilterEnable) { + if (attr->taskFilterEnable) {//开启任务过滤功能 ret = memcpy_s(g_perfCb.taskIds, PERF_MAX_FILTER_TSKS * sizeof(UINT32), attr->taskIds, g_perfCb.taskIdsNr * sizeof(UINT32)); if (ret != EOK) { @@ -377,29 +382,29 @@ UINT32 LOS_PerfConfig(PerfConfigAttr *attr) } g_perfCb.taskIdsNr = MIN(attr->taskIdsNr, PERF_MAX_FILTER_TSKS); } - ret = OsPerfConfig(&attr->eventsCfg); + ret = OsPerfConfig(&attr->eventsCfg);//对事件配置进行处理 PERF_CONFIG_ERROR: PERF_UNLOCK(intSave); return ret; } -VOID LOS_PerfStart(UINT32 sectionId) +VOID LOS_PerfStart(UINT32 sectionId)//启动性能统计模块 { UINT32 intSave; UINT32 ret; PERF_LOCK(intSave); - if (g_perfCb.status != PERF_STOPED) { + if (g_perfCb.status != PERF_STOPED) {//判断统计模块是否打开 PRINT_ERR("perf start status error : 0x%x\n", g_perfCb.status); goto PERF_START_ERROR; } - if (!OsPerfParamValid()) { + if (!OsPerfParamValid()) {//检车行呢个统计模块的参数是否有效 PRINT_ERR("forgot call `LOS_Config(...)` before instrumenting?\n"); goto PERF_START_ERROR; } - if (g_perfCb.needSample) { + if (g_perfCb.needSample) {//判断是否需要抽样 ret = OsPerfHdrInit(sectionId); /* section header init */ if (ret != LOS_OK) { PRINT_ERR("perf hdr init error 0x%x\n", ret); @@ -407,7 +412,7 @@ VOID LOS_PerfStart(UINT32 sectionId) } } - SMP_CALL_PERF_FUNC(OsPerfStart); /* send to all cpu to start pmu */ + SMP_CALL_PERF_FUNC(OsPerfStart); /* 所有CPU开始PMU计数器,启动性能统计模块i奥 */ g_perfCb.status = PERF_STARTED; g_perfCb.startTime = OsPerfGetCurrTime(); PERF_START_ERROR: @@ -415,7 +420,7 @@ PERF_START_ERROR: return; } -VOID LOS_PerfStop(VOID) +VOID LOS_PerfStop(VOID)//停止性能统计模块的运行,进行一些清理操作 { UINT32 intSave; @@ -427,12 +432,12 @@ VOID LOS_PerfStop(VOID) SMP_CALL_PERF_FUNC(OsPerfStop); /* send to all cpu to stop pmu */ - OsPerfOutPutFlush(); + OsPerfOutPutFlush();//刷新输出操作 if (g_perfCb.needSample) { OsPerfOutPutInfo(); } - + //更新了两个全局变量的值,表示性能统计模块已经在状态上和时间上停止了 g_perfCb.status = PERF_STOPED; g_perfCb.endTime = OsPerfGetCurrTime(); @@ -442,21 +447,21 @@ PERF_STOP_ERROR: return; } -UINT32 LOS_PerfDataRead(CHAR *dest, UINT32 size) +UINT32 LOS_PerfDataRead(CHAR *dest, UINT32 size)//从性能统计门票快的输出缓冲区中读取数据到指定的内存 { return OsPerfOutPutRead(dest, size); } -VOID LOS_PerfNotifyHookReg(const PERF_BUF_NOTIFY_HOOK func) +VOID LOS_PerfNotifyHookReg(const PERF_BUF_NOTIFY_HOOK func)//注册型那个统计模块的通知hook函数 { UINT32 intSave; - + //保存中断状态,恢复中断状态 PERF_LOCK(intSave); OsPerfNotifyHookReg(func); PERF_UNLOCK(intSave); } -VOID LOS_PerfFlushHookReg(const PERF_BUF_FLUSH_HOOK func) +VOID LOS_PerfFlushHookReg(const PERF_BUF_FLUSH_HOOK func)//刷新hook { UINT32 intSave; @@ -465,7 +470,7 @@ VOID LOS_PerfFlushHookReg(const PERF_BUF_FLUSH_HOOK func) PERF_UNLOCK(intSave); } -VOID OsPerfSetIrqRegs(UINTPTR pc, UINTPTR fp) +VOID OsPerfSetIrqRegs(UINTPTR pc, UINTPTR fp)//设置中断相关的寄存器,用于中断时的性能统计 { LosTaskCB *runTask = (LosTaskCB *)ArchCurrTaskGet(); runTask->pc = pc; diff --git a/src/kernel/extended/perf/perf_output.c b/src/kernel/extended/perf/perf_output.c index 20bea3a..a83d806 100644 --- a/src/kernel/extended/perf/perf_output.c +++ b/src/kernel/extended/perf/perf_output.c @@ -39,11 +39,14 @@ STATIC PERF_BUF_FLUSH_HOOK g_perfBufFlushHook = NULL; STATIC PerfOutputCB g_perfOutputCb; STATIC VOID OsPerfDefaultNotify(VOID) +//默认的性能缓冲区通知回调函数,在性能缓冲区的水位线达到一定值时打印一条信息 { PRINT_INFO("perf buf waterline notify!\n"); } UINT32 OsPerfOutPutInit(VOID *buf, UINT32 size) +//初始化性能输出模块。如果传入的缓冲区指针为空,则使用LOS_MemAlloc函数动态分配内存。 +//然后初始化环形缓冲区,设置水位线,并注册默认的性能缓冲区通知回调函数 { UINT32 ret; BOOL releaseFlag = FALSE; @@ -69,21 +72,22 @@ RELEASE: return ret; } -VOID OsPerfOutPutFlush(VOID) +VOID OsPerfOutPutFlush(VOID)//刷新性能输出缓冲区 { if (g_perfBufFlushHook != NULL) { g_perfBufFlushHook(g_perfOutputCb.ringbuf.fifo, g_perfOutputCb.ringbuf.size); } } -UINT32 OsPerfOutPutRead(CHAR *dest, UINT32 size) +UINT32 OsPerfOutPutRead(CHAR *dest, UINT32 size)//从性能输出缓冲区中读取数据 { OsPerfOutPutFlush(); return LOS_RingbufRead(&g_perfOutputCb.ringbuf, dest, size); } -STATIC BOOL OsPerfOutPutBegin(UINT32 size) +STATIC BOOL OsPerfOutPutBegin(UINT32 size)//开始写入性能输出缓冲区 { + //检查是否有足够空间 if (g_perfOutputCb.ringbuf.remain < size) { PRINT_INFO("perf buf has no enough space for 0x%x\n", size); return FALSE; @@ -91,9 +95,9 @@ STATIC BOOL OsPerfOutPutBegin(UINT32 size) return TRUE; } -STATIC VOID OsPerfOutPutEnd(VOID) +STATIC VOID OsPerfOutPutEnd(VOID)//结束性能输出 { - OsPerfOutPutFlush(); + OsPerfOutPutFlush();//刷新缓冲区 if (LOS_RingbufUsedSize(&g_perfOutputCb.ringbuf) >= g_perfOutputCb.waterMark) { if (g_perfBufNotifyHook != NULL) { g_perfBufNotifyHook(); @@ -101,7 +105,7 @@ STATIC VOID OsPerfOutPutEnd(VOID) } } -UINT32 OsPerfOutPutWrite(CHAR *data, UINT32 size) +UINT32 OsPerfOutPutWrite(CHAR *data, UINT32 size)//将数据写入性能输入缓冲区 { if (!OsPerfOutPutBegin(size)) { return LOS_NOK; @@ -113,17 +117,17 @@ UINT32 OsPerfOutPutWrite(CHAR *data, UINT32 size) return LOS_OK; } -VOID OsPerfOutPutInfo(VOID) +VOID OsPerfOutPutInfo(VOID)//打印性能输出缓冲区的信息,包括地址和长度 { PRINT_EMG("dump section data, addr: %p length: %#x \r\n", g_perfOutputCb.ringbuf.fifo, g_perfOutputCb.ringbuf.size); } -VOID OsPerfNotifyHookReg(const PERF_BUF_NOTIFY_HOOK func) +VOID OsPerfNotifyHookReg(const PERF_BUF_NOTIFY_HOOK func)//注册性能缓冲区通知 { g_perfBufNotifyHook = func; } -VOID OsPerfFlushHookReg(const PERF_BUF_FLUSH_HOOK func) +VOID OsPerfFlushHookReg(const PERF_BUF_FLUSH_HOOK func)//注册性能缓冲区刷新的函数 { g_perfBufFlushHook = func; } diff --git a/src/kernel/extended/perf/perf_output_pri.h b/src/kernel/extended/perf/perf_output_pri.h index 382f2a9..603e64d 100644 --- a/src/kernel/extended/perf/perf_output_pri.h +++ b/src/kernel/extended/perf/perf_output_pri.h @@ -43,13 +43,13 @@ typedef struct { UINT32 waterMark; /* notify water mark */ } PerfOutputCB; -extern UINT32 OsPerfOutPutInit(VOID *buf, UINT32 size); -extern UINT32 OsPerfOutPutRead(CHAR *dest, UINT32 size); -extern UINT32 OsPerfOutPutWrite(CHAR *data, UINT32 size); -extern VOID OsPerfOutPutInfo(VOID); -extern VOID OsPerfOutPutFlush(VOID); -extern VOID OsPerfNotifyHookReg(const PERF_BUF_NOTIFY_HOOK func); -extern VOID OsPerfFlushHookReg(const PERF_BUF_FLUSH_HOOK func); +extern UINT32 OsPerfOutPutInit(VOID *buf, UINT32 size);//初始化性能输出模块 +extern UINT32 OsPerfOutPutRead(CHAR *dest, UINT32 size);//从性能输出缓冲区中读取数据,将数据拷贝到指定的目标缓冲区中 +extern UINT32 OsPerfOutPutWrite(CHAR *data, UINT32 size);//将数据写入性能输出缓冲区 +extern VOID OsPerfOutPutInfo(VOID);//输出性能统计信息 +extern VOID OsPerfOutPutFlush(VOID);//刷新性能输出缓冲区 +extern VOID OsPerfNotifyHookReg(const PERF_BUF_NOTIFY_HOOK func);//注册性能输出缓冲区通知 +extern VOID OsPerfFlushHookReg(const PERF_BUF_FLUSH_HOOK func);//注册性能输出缓冲区刷新 #ifdef __cplusplus #if __cplusplus diff --git a/src/kernel/extended/perf/perf_pmu.c b/src/kernel/extended/perf/perf_pmu.c index a2771ba..ff5cca6 100644 --- a/src/kernel/extended/perf/perf_pmu.c +++ b/src/kernel/extended/perf/perf_pmu.c @@ -36,11 +36,11 @@ extern "C" { STATIC Pmu *g_pmuMgr[PERF_EVENT_TYPE_MAX] = {NULL}; -UINT32 OsPerfPmuRegister(Pmu *pmu) +UINT32 OsPerfPmuRegister(Pmu *pmu)//注册性能计数器 { UINT32 type; - if ((pmu == NULL) || (pmu->type >= PERF_EVENT_TYPE_MAX)) { + if ((pmu == NULL) || (pmu->type >= PERF_EVENT_TYPE_MAX)) {//如果传入PMU为空指针或者type超出了有效范围 return LOS_NOK; } @@ -52,19 +52,20 @@ UINT32 OsPerfPmuRegister(Pmu *pmu) return LOS_NOK; } -Pmu *OsPerfPmuGet(UINT32 type) +Pmu *OsPerfPmuGet(UINT32 type)//获取指定类型的性能计数器 { if (type >= PERF_EVENT_TYPE_MAX) { return NULL; } - if (type == PERF_EVENT_TYPE_RAW) { /* process hardware raw events with hard pmu */ - type = PERF_EVENT_TYPE_HW; + if (type == PERF_EVENT_TYPE_RAW) { //如果是原始事件类型 + /* process hardware raw events with hard pmu */ + type = PERF_EVENT_TYPE_HW;//则将其转化为硬件事件类型 } return g_pmuMgr[type]; } -VOID OsPerfPmuRm(UINT32 type) +VOID OsPerfPmuRm(UINT32 type)//删除指定类型的性能计数器 { if (type >= PERF_EVENT_TYPE_MAX) { return; diff --git a/src/kernel/extended/perf/perf_pmu_pri.h b/src/kernel/extended/perf/perf_pmu_pri.h index 2507d34..4cbb5bd 100644 --- a/src/kernel/extended/perf/perf_pmu_pri.h +++ b/src/kernel/extended/perf/perf_pmu_pri.h @@ -53,7 +53,7 @@ typedef struct { VOID (*setPeriod)(Event *event); UINTPTR (*readCnt)(Event *event); UINT32 (*mapEvent)(UINT32 eventType, BOOL reverse); -} HwPmu; +} HwPmu;//硬件性能计数器结构体,包括硬件计数器、计数器是否能被分频、分频系数、启用、禁用、开始、停止、清除、设置周期、读取计数器值和事件映射等函数指针 typedef struct { Pmu pmu; @@ -69,35 +69,35 @@ typedef struct { }; #endif }; -} SwPmu; +} SwPmu;//软件性能计数器结构体,包括软件计数器、是否启用标志位、定时器配置时间 #define GET_HW_PMU(item) LOS_DL_LIST_ENTRY(item, HwPmu, pmu) -#define TIMER_PERIOD_LOWER_BOUND_US 100 +#define TIMER_PERIOD_LOWER_BOUND_US 100//定时器最小周期 -#define CCNT_FULL 0xFFFFFFFF -#define CCNT_PERIOD_LOWER_BOUND 0x00000000 -#define CCNT_PERIOD_UPPER_BOUND 0xFFFFFF00 -#define PERIOD_CALC(p) (CCNT_FULL - (p)) +#define CCNT_FULL 0xFFFFFFFF//计数器最大值 +#define CCNT_PERIOD_LOWER_BOUND 0x00000000//最小周期 +#define CCNT_PERIOD_UPPER_BOUND 0xFFFFFF00//最大周期 +#define PERIOD_CALC(p) (CCNT_FULL - (p))//计算给定周期对应的计数器值 #define VALID_PERIOD(p) ((PERIOD_CALC(p) > CCNT_PERIOD_LOWER_BOUND) \ - && (PERIOD_CALC(p) < CCNT_PERIOD_UPPER_BOUND)) + && (PERIOD_CALC(p) < CCNT_PERIOD_UPPER_BOUND))//判断给定周期是否合法 -#define PERF_HW_INVAILD_EVENT_TYPE 0xFFFFFFFF +#define PERF_HW_INVAILD_EVENT_TYPE 0xFFFFFFFF//无效的事件类型 #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) -extern UINT32 OsPerfPmuRegister(Pmu *pmu); -extern VOID OsPerfPmuRm(UINT32 type); -extern Pmu *OsPerfPmuGet(UINT32 type); +extern UINT32 OsPerfPmuRegister(Pmu *pmu);//注册硬件性能计数器 +extern VOID OsPerfPmuRm(UINT32 type);//删除硬件性能计数器 +extern Pmu *OsPerfPmuGet(UINT32 type);//获取指定类型的硬件性能计数器 -extern UINT32 OsHwPmuInit(VOID); -extern UINT32 OsSwPmuInit(VOID); -extern UINT32 OsTimedPmuInit(VOID); +extern UINT32 OsHwPmuInit(VOID);//初始化硬件性能计数器 +extern UINT32 OsSwPmuInit(VOID);//初始化软件性能计数器 +extern UINT32 OsTimedPmuInit(VOID);//初始化定时器性能计数器 -extern UINT32 OsGetPmuCounter0(VOID); -extern UINT32 OsGetPmuMaxCounter(VOID); -extern UINT32 OsGetPmuCycleCounter(VOID); -extern UINT32 OsPerfHwInit(HwPmu *hwPmu); +extern UINT32 OsGetPmuCounter0(VOID);//获取0核计数器值 +extern UINT32 OsGetPmuMaxCounter(VOID);//获取最大计数器数 +extern UINT32 OsGetPmuCycleCounter(VOID);//获取周期性计数器值 +extern UINT32 OsPerfHwInit(HwPmu *hwPmu);//初始化硬件性能计数器 #ifdef __cplusplus #if __cplusplus diff --git a/src/kernel/extended/perf/pmu/perf_hw_pmu.c b/src/kernel/extended/perf/pmu/perf_hw_pmu.c index ca0b797..f76869d 100644 --- a/src/kernel/extended/perf/pmu/perf_hw_pmu.c +++ b/src/kernel/extended/perf/pmu/perf_hw_pmu.c @@ -34,7 +34,7 @@ extern "C" { #endif /* __cplusplus */ #endif /* __cplusplus */ -STATIC Pmu *g_perfHw = NULL; +STATIC Pmu *g_perfHw = NULL;//指向性能计数器相关的数据结构或对象 STATIC CHAR *g_eventName[PERF_COUNT_HW_MAX] = { [PERF_COUNT_HW_CPU_CYCLES] = "cycles", @@ -53,39 +53,41 @@ STATIC CHAR *g_eventName[PERF_COUNT_HW_MAX] = { * 2.Find available counter for each event. * 3.Decide whether this hardware pmu need prescaler (once every 64 cycle counts). */ -STATIC UINT32 OsPerfHwConfig(VOID) +STATIC UINT32 OsPerfHwConfig(VOID)//性能计数器的配置函数,用于初始化和配置硬件性能计数器 { UINT32 i; HwPmu *armPmu = GET_HW_PMU(g_perfHw); - UINT32 maxCounter = OsGetPmuMaxCounter(); - UINT32 counter = OsGetPmuCounter0(); - UINT32 cycleCounter = OsGetPmuCycleCounter(); + UINT32 maxCounter = OsGetPmuMaxCounter();//获得最大计数器数量 + UINT32 counter = OsGetPmuCounter0();//获取0核计数器的值 + UINT32 cycleCounter = OsGetPmuCycleCounter();//周期计数器的值 UINT32 cycleCode = armPmu->mapEvent(PERF_COUNT_HW_CPU_CYCLES, PERF_EVENT_TO_CODE); if (cycleCode == PERF_HW_INVAILD_EVENT_TYPE) { return LOS_NOK; } - + //获取性能事件的列表的和数量并进行遍历 PerfEvent *events = &g_perfHw->events; UINT32 eventNum = events->nr; for (i = 0; i < eventNum; i++) { Event *event = &(events->per[i]); - if (!VALID_PERIOD(event->period)) { + if (!VALID_PERIOD(event->period)) {//检查事件周期是否合法 PRINT_ERR("Config period: 0x%x invalid, should be in (%#x, %#x)\n", event->period, PERIOD_CALC(CCNT_PERIOD_UPPER_BOUND), PERIOD_CALC(CCNT_PERIOD_LOWER_BOUND)); return LOS_NOK; } if (g_perfHw->type == PERF_EVENT_TYPE_HW) { /* do map */ + //映射编码 UINT32 eventId = armPmu->mapEvent(event->eventId, PERF_EVENT_TO_CODE); if (eventId == PERF_HW_INVAILD_EVENT_TYPE) { return LOS_NOK; } event->eventId = eventId; } - + //函数根据事件编码是否与周期计数器的事件编码相同,来确定该事件使用的计数器。 + //如果相同,则使用周期计数器;否则,使用普通计数器,并递增计数器的值。 if (event->eventId == cycleCode) { event->counter = cycleCounter; } else { @@ -93,11 +95,11 @@ STATIC UINT32 OsPerfHwConfig(VOID) counter++; } - if (counter >= maxCounter) { + if (counter >= maxCounter) {//检查计数器是否超过了最大计数器数量 PRINT_ERR("max events: %u excluding cycle event\n", maxCounter - 1); return LOS_NOK; } - + //打印结果,设置根据平台支持的分频 PRINT_DEBUG("Perf Config %u eventId = 0x%x, counter = 0x%x, period = 0x%x\n", i, event->eventId, event->counter, event->period); } @@ -106,21 +108,21 @@ STATIC UINT32 OsPerfHwConfig(VOID) return LOS_OK; } -STATIC UINT32 OsPerfHwStart(VOID) +STATIC UINT32 OsPerfHwStart(VOID)//用于启动硬件性能计数器 { UINT32 i; UINT32 cpuid = ArchCurrCpuid(); - HwPmu *armPmu = GET_HW_PMU(g_perfHw); + HwPmu *armPmu = GET_HW_PMU(g_perfHw);//获取硬件性能计数器的指针 PerfEvent *events = &g_perfHw->events; UINT32 eventNum = events->nr; - armPmu->clear(); + armPmu->clear();//清零计数器 for (i = 0; i < eventNum; i++) { Event *event = &(events->per[i]); - armPmu->setPeriod(event); - armPmu->enable(event); + armPmu->setPeriod(event);//设置事件的计数周期 + armPmu->enable(event);//启用事件的计数器 event->count[cpuid] = 0; } @@ -128,7 +130,7 @@ STATIC UINT32 OsPerfHwStart(VOID) return LOS_OK; } -STATIC UINT32 OsPerfHwStop(VOID) +STATIC UINT32 OsPerfHwStop(VOID)//停止硬件性能计数器 { UINT32 i; UINT32 cpuid = ArchCurrCpuid(); @@ -148,7 +150,9 @@ STATIC UINT32 OsPerfHwStop(VOID) /* multiplier of cycle counter */ UINT32 eventId = armPmu->mapEvent(event->eventId, PERF_CODE_TO_EVENT); if ((eventId == PERF_COUNT_HW_CPU_CYCLES) && (armPmu->cntDivided != 0)) { + //如果该事件的事件ID与周期计数器事件ID相同,并且硬件性能计数器的分频设置armPmu->cntDivided不为0 PRINT_DEBUG("perf stop is cycle\n"); + //此处将该事件的计数值左移6位,相当于乘以64 event->count[cpuid] = event->count[cpuid] << 6; /* CCNT counts every 64th cpu cycle */ } PRINT_DEBUG("perf stop eventCount[0x%x] : [%s] = %llu\n", event->eventId, g_eventName[eventId], @@ -157,11 +161,11 @@ STATIC UINT32 OsPerfHwStop(VOID) return LOS_OK; } -STATIC CHAR *OsPerfGetEventName(Event *event) +STATIC CHAR *OsPerfGetEventName(Event *event)//获取事件名称 { UINT32 eventId; - HwPmu *armPmu = GET_HW_PMU(g_perfHw); - eventId = armPmu->mapEvent(event->eventId, PERF_CODE_TO_EVENT); + HwPmu *armPmu = GET_HW_PMU(g_perfHw);//获取PMU上的事件信息 + eventId = armPmu->mapEvent(event->eventId, PERF_CODE_TO_EVENT);//将事件ID映射位对应计数器事件ID if (eventId < PERF_COUNT_HW_MAX) { return g_eventName[eventId]; } else { @@ -169,21 +173,21 @@ STATIC CHAR *OsPerfGetEventName(Event *event) } } -UINT32 OsPerfHwInit(HwPmu *hwPmu) +UINT32 OsPerfHwInit(HwPmu *hwPmu)//初始化性能计数器 { UINT32 ret; if (hwPmu == NULL) { return LOS_NOK; } - + //设置性能计数器的类型,配置函数,启动函数,停止函数,获取事件名称函数 hwPmu->pmu.type = PERF_EVENT_TYPE_HW; hwPmu->pmu.config = OsPerfHwConfig; hwPmu->pmu.start = OsPerfHwStart; hwPmu->pmu.stop = OsPerfHwStop; hwPmu->pmu.getName = OsPerfGetEventName; - + //将硬件性能计数器的事件数据结构清零 (VOID)memset_s(&hwPmu->pmu.events, sizeof(PerfEvent), 0, sizeof(PerfEvent)); - ret = OsPerfPmuRegister(&hwPmu->pmu); + ret = OsPerfPmuRegister(&hwPmu->pmu);//注册硬件性能计数器,将其存储在全局变量中 g_perfHw = OsPerfPmuGet(PERF_EVENT_TYPE_HW); return ret; diff --git a/src/kernel/extended/perf/pmu/perf_sw_pmu.c b/src/kernel/extended/perf/pmu/perf_sw_pmu.c index 5ea7e52..fe6f251 100644 --- a/src/kernel/extended/perf/pmu/perf_sw_pmu.c +++ b/src/kernel/extended/perf/pmu/perf_sw_pmu.c @@ -51,7 +51,7 @@ STATIC CHAR* g_eventName[PERF_COUNT_SW_MAX] = { [PERF_COUNT_SW_MUX_PEND] = "mux pend", }; -VOID OsPerfHook(UINT32 eventType) +VOID OsPerfHook(UINT32 eventType)//软件性能计数器的事件处理函数 { if (!g_perfSw.enable) { return; @@ -69,7 +69,7 @@ VOID OsPerfHook(UINT32 eventType) if (event->counter == eventType) { OsPerfUpdateEventCount(event, 1); if (event->count[ArchCurrCpuid()] % event->period == 0) { - OsPerfFetchCallerRegs(®s); + OsPerfFetchCallerRegs(®s);//获取寄存器信息 OsPerfHandleOverFlow(event, ®s); } return; @@ -77,7 +77,7 @@ VOID OsPerfHook(UINT32 eventType) } } -STATIC UINT32 OsPerfSwConfig(VOID) +STATIC UINT32 OsPerfSwConfig(VOID)//对软件性能计数器进行配置 { UINT32 i; PerfEvent *events = &g_perfSw.pmu.events; @@ -94,29 +94,29 @@ STATIC UINT32 OsPerfSwConfig(VOID) return LOS_OK; } -STATIC UINT32 OsPerfSwStart(VOID) +STATIC UINT32 OsPerfSwStart(VOID)//启动软件性能计数器 { UINT32 i; UINT32 cpuid = ArchCurrCpuid(); PerfEvent *events = &g_perfSw.pmu.events; UINT32 eventNum = events->nr; - for (i = 0; i < eventNum; i++) { + for (i = 0; i < eventNum; i++) {//遍历所有事件 Event *event = &(events->per[i]); - event->count[cpuid] = 0; + event->count[cpuid] = 0;//清零当前事件在CPU中的计数器 } - g_perfSw.enable = TRUE; + g_perfSw.enable = TRUE;//启动计数器 return LOS_OK; } -STATIC UINT32 OsPerfSwStop(VOID) +STATIC UINT32 OsPerfSwStop(VOID)//关闭软件性能计数器 { g_perfSw.enable = FALSE; return LOS_OK; } -STATIC CHAR *OsPerfGetEventName(Event *event) +STATIC CHAR *OsPerfGetEventName(Event *event)//获取事件的名称 { UINT32 eventId = event->eventId; if (eventId < PERF_COUNT_SW_MAX) { @@ -125,7 +125,7 @@ STATIC CHAR *OsPerfGetEventName(Event *event) return "unknown"; } -UINT32 OsSwPmuInit(VOID) +UINT32 OsSwPmuInit(VOID)//对PMU计数器进行初始化 { g_perfSw.pmu = (Pmu) { .type = PERF_EVENT_TYPE_SW, diff --git a/src/kernel/extended/perf/pmu/perf_timed_pmu.c b/src/kernel/extended/perf/pmu/perf_timed_pmu.c index 4659c08..6080f90 100644 --- a/src/kernel/extended/perf/pmu/perf_timed_pmu.c +++ b/src/kernel/extended/perf/pmu/perf_timed_pmu.c @@ -39,12 +39,12 @@ extern "C" { STATIC SwPmu g_perfTimed; -STATIC BOOL OsPerfTimedPeriodValid(UINT32 period) +STATIC BOOL OsPerfTimedPeriodValid(UINT32 period)//验证定时器中的时间周期是否合法 { return period >= TIMER_PERIOD_LOWER_BOUND_US; } -STATIC UINT32 OsPerfTimedStart(VOID) +STATIC UINT32 OsPerfTimedStart(VOID)//启动定时器事件 { UINT32 i; UINT32 cpuid = ArchCurrCpuid(); @@ -74,7 +74,7 @@ STATIC UINT32 OsPerfTimedStart(VOID) return LOS_OK; } -STATIC UINT32 OsPerfTimedConfig(VOID) +STATIC UINT32 OsPerfTimedConfig(VOID)//配置定时器,检验是否合法 { UINT32 i; PerfEvent *events = &g_perfTimed.pmu.events; @@ -101,7 +101,7 @@ STATIC UINT32 OsPerfTimedConfig(VOID) return LOS_NOK; } -STATIC UINT32 OsPerfTimedStop(VOID) +STATIC UINT32 OsPerfTimedStop(VOID)//关闭定时器设置 { UINT32 ret; if (ArchCurrCpuid() != 0) { /* only need stop on one core */ @@ -116,7 +116,7 @@ STATIC UINT32 OsPerfTimedStop(VOID) return LOS_OK; } -STATIC VOID OsPerfTimedHandle(VOID) +STATIC VOID OsPerfTimedHandle(VOID)//处理定时器事件 { UINT32 index; PerfRegs regs; @@ -125,7 +125,7 @@ STATIC VOID OsPerfTimedHandle(VOID) UINT32 eventNum = events->nr; (VOID)memset_s(®s, sizeof(PerfRegs), 0, sizeof(PerfRegs)); - OsPerfFetchIrqRegs(®s); + OsPerfFetchIrqRegs(®s);//获取当前寄存器状态 for (index = 0; index < eventNum; index++) { Event *event = &(events->per[index]); @@ -134,48 +134,50 @@ STATIC VOID OsPerfTimedHandle(VOID) } } -STATIC enum hrtimer_restart OsPerfHrtimer(struct hrtimer *hrtimer) +STATIC enum hrtimer_restart OsPerfHrtimer(struct hrtimer *hrtimer)//高精度定时器(hrtimer)的回调函数 { SMP_CALL_PERF_FUNC(OsPerfTimedHandle); /* send to all cpu to collect data */ + //将定时器事件的处理发送给所有CPU进行数据收集 return HRTIMER_RESTART; } -STATIC CHAR *OsPerfGetEventName(Event *event) +STATIC CHAR *OsPerfGetEventName(Event *event)//获取事件名称 { - if (event->eventId == PERF_COUNT_CPU_CLOCK) { + if (event->eventId == PERF_COUNT_CPU_CLOCK) {//读取事件ID是否与计数器中的事件记录相同 return "timed"; } else { return "unknown"; } } -UINT32 OsTimedPmuInit(VOID) +UINT32 OsTimedPmuInit(VOID)//初始化定时器 { UINT32 ret; - g_perfTimed.time = (union ktime) { + g_perfTimed.time = (union ktime) {//保存定时器信息 .tv.sec = 0, .tv.usec = HRTIMER_DEFAULT_PERIOD_US, }; - hrtimer_init(&g_perfTimed.hrtimer, 1, HRTIMER_MODE_REL); + hrtimer_init(&g_perfTimed.hrtimer, 1, HRTIMER_MODE_REL);//第一个参数代表定时器对象,第二个参数为时间源类型,代表的是相对时间,最后一个参数代表定时器模式,这里使用的是相对时间模式 - ret = hrtimer_create(&g_perfTimed.hrtimer, g_perfTimed.time, OsPerfHrtimer); + ret = hrtimer_create(&g_perfTimed.hrtimer, g_perfTimed.time, OsPerfHrtimer);//创建定时器 if (ret != LOS_OK) { return ret; } g_perfTimed.pmu = (Pmu) { - .type = PERF_EVENT_TYPE_TIMED, - .config = OsPerfTimedConfig, - .start = OsPerfTimedStart, - .stop = OsPerfTimedStop, - .getName = OsPerfGetEventName, + .type = PERF_EVENT_TYPE_TIMED,//此性能计数器是定时器类型 + .config = OsPerfTimedConfig,//性能计数器的事件配置 + .start = OsPerfTimedStart,//启动 + .stop = OsPerfTimedStop,//停止 + .getName = OsPerfGetEventName,//获取事件名称 }; (VOID)memset_s(&g_perfTimed.pmu.events, sizeof(PerfEvent), 0, sizeof(PerfEvent)); + //执行完之后清零事件结构体,并在下面进行状态码的注册读取 ret = OsPerfPmuRegister(&g_perfTimed.pmu); - return ret; + return ret;//返回值为初始化状态码 } #ifdef __cplusplus diff --git a/src/kernel/extended/软件工程代码阅读(初稿)-何佳聪-.docx b/src/kernel/extended/软件工程代码阅读(初稿)-何佳聪-.docx new file mode 100644 index 0000000000000000000000000000000000000000..4d112b6f661c0c5322db4731bd81bfcdb797786f GIT binary patch literal 14017 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 HZ?*pcv7}9Z literal 0 HcmV?d00001 From a8f162b24c7c2517448542d2ec01a8bec8559dca Mon Sep 17 00:00:00 2001 From: cailun <2505225681@qq.com> Date: Sun, 3 Dec 2023 23:42:32 +0800 Subject: [PATCH 08/26] src --- src/kernel/base/include/los_binarytree_pri.h | 59 +++++++++++-------- src/kernel/base/include/los_err_pri.h | 3 + src/kernel/base/include/los_event_pri.h | 7 ++- src/kernel/base/include/los_exc_pri.h | 14 ++++- src/kernel/base/include/los_hwi_pri.h | 21 ++++--- src/kernel/base/include/los_memory_pri.h | 14 ++++- src/kernel/base/include/los_memstat_pri.h | 21 ++++--- src/kernel/base/include/los_misc_pri.h | 7 ++- src/kernel/base/include/los_mp_pri.h | 10 +++- .../base/include/los_multipledlinkhead_pri.h | 15 +++-- src/kernel/base/los_bitmap.c | 2 +- src/kernel/include/los_typedef.h | 7 ++- 12 files changed, 123 insertions(+), 57 deletions(-) diff --git a/src/kernel/base/include/los_binarytree_pri.h b/src/kernel/base/include/los_binarytree_pri.h index 2de75ae..8f4a675 100644 --- a/src/kernel/base/include/los_binarytree_pri.h +++ b/src/kernel/base/include/los_binarytree_pri.h @@ -35,67 +35,76 @@ extern "C" { #endif /* __cplusplus */ #endif /* __cplusplus */ - +//定义二叉树节点的模型 typedef struct tagBinNode { - struct tagBinNode *left; - struct tagBinNode *right; - UINT32 nodeId; - CHAR keyValue[0]; + struct tagBinNode *left;//左子树节点 + struct tagBinNode *right;//右子树节点 + UINT32 nodeId;//节点的编号 + CHAR keyValue[0];//节点记录的值(柔性数组,动态分配内存) } BinNode; +//链接二叉树节点 typedef struct { - BinNode leaf; - UINTPTR linkReg1; + BinNode leaf;//一个二叉树 + UINTPTR linkReg1;//无符号数的指针,可连接三个节点 UINTPTR linkReg2; UINTPTR linkReg3; } LinkRegNode; #define LR_COUNT 4096 -extern LinkRegNode g_linkRegNode[LR_COUNT]; -extern UINT32 g_linkRegNodeIndex; -extern LinkRegNode *g_linkRegRoot; +extern LinkRegNode g_linkRegNode[LR_COUNT];//4096个链接二叉树节点 +extern UINT32 g_linkRegNodeIndex;//链接二叉树节点的索引 +extern LinkRegNode *g_linkRegRoot;//链接二叉树节点的指针 +//地址二叉树节点 typedef struct { - BinNode leaf; - UINTPTR addr; + BinNode leaf;//一个二叉树节点 + UINTPTR addr;//二叉树节点记录的地址 } AddrNode; #define ADDR_COUNT 40960 -extern AddrNode g_addrNode[ADDR_COUNT]; -extern UINT32 g_addrNodeIndex; -extern AddrNode *g_addrRoot; +extern AddrNode g_addrNode[ADDR_COUNT];//40960个地址二叉树节点 +extern UINT32 g_addrNodeIndex;//地址二叉树节点的索引 +extern AddrNode *g_addrRoot;//地址二叉树节点的指针 +//请求大小二叉树节点 typedef struct { - BinNode leaf; - UINT32 reqSize; + BinNode leaf;//一个二叉树 + UINT32 reqSize;//请求数据大小 } ReqSizeNode; #define REQ_SIZE_COUNT 4096 -extern ReqSizeNode g_reqSizeNode[REQ_SIZE_COUNT]; -extern UINT32 g_reqSizeNodeIndex; -extern ReqSizeNode *g_reqSizeRoot; +extern ReqSizeNode g_reqSizeNode[REQ_SIZE_COUNT];//4096个请求大小二叉树节点 +extern UINT32 g_reqSizeNodeIndex;//请求大小二叉树节点的索引 +extern ReqSizeNode *g_reqSizeRoot;//请求大小二叉树节点的指针 +//任务编号二叉树节点 typedef struct { BinNode leaf; UINT32 taskId; } TaskIDNode; -#define TASK_ID_COUNT 1024 +#define TASK_ID_COUNT 1024//1024个任务编号 +//将节点插入二叉树的函数 extern UINT32 OsBinTreeInsert(const VOID *node, UINT32 nodeLen, BinNode **leaf, BinNode *(*GetMyBinNode)(UINT32 *nodeId), INT32 (*CompareNode)(const VOID *node1, const VOID *node2)); - +//比较两个二叉树节点 extern INT32 OsCompareLRNode(const VOID *node1, const VOID *node2); +//通过二叉树节点的编号得到二叉树 extern BinNode *OsGetLRBinNode(UINT32 *nodeId); - +//比较两个地址二叉树节点 extern INT32 OsCompareAddrNode(const VOID *node1, const VOID *node2); +//通过地址二叉树节点的编号得到地址二叉树 extern BinNode *OsGetAddrBinNode(UINT32 *nodeId); - +//比较两个请求大小二叉树节点 extern INT32 OsCompareReqSizeNode(const VOID *node1, const VOID *node2); +//通过请求大小二叉树节点的编号得到请求大小二叉树 extern BinNode *OsGetReqSizeBinNode(UINT32 *nodeId); - +//比较两个任务编号二叉树节点 extern INT32 OsCompareTaskIDNode(const VOID *node1, const VOID *node2); +//通过任务编号二叉树节点的编号得到任务编号二叉树 extern BinNode *OsGetTaskIDBinNode(UINT32 *nodeId); #ifdef __cplusplus diff --git a/src/kernel/base/include/los_err_pri.h b/src/kernel/base/include/los_err_pri.h index 9b44583..0c1553e 100644 --- a/src/kernel/base/include/los_err_pri.h +++ b/src/kernel/base/include/los_err_pri.h @@ -40,6 +40,7 @@ extern "C" { #define OS_ERR_MAGIC_WORD 0xa1b2c3f8 /* used to call the error handling function by using an error code and return the same error code. */ +//通过调用处理异常的错误码返回错误码 #define OS_RETURN_ERROR(errNo) do { \ (VOID)LOS_ErrHandle("os_unspecific_file", OS_ERR_MAGIC_WORD, errNo, 0, NULL); \ return errNo; \ @@ -49,12 +50,14 @@ extern "C" { * Call the error handling function by using an error code and the line number of * the erroneous line, and return the same error code. */ +//通过调用异常发生行的位置返回错误码 #define OS_RETURN_ERROR_P2(errLine, errNo) do { \ (VOID)LOS_ErrHandle("os_unspecific_file", errLine, errNo, 0, NULL); \ return errNo; \ } while (0) /* Used to call the error handling function by using an error code. */ +//通过错误码进行调用处理异常的函数 #define OS_GOTO_ERR_HANDLER(errorNo) do { \ errNo = errorNo; \ errLine = OS_ERR_MAGIC_WORD; \ diff --git a/src/kernel/base/include/los_event_pri.h b/src/kernel/base/include/los_event_pri.h index 45c9beb..7c58bfb 100644 --- a/src/kernel/base/include/los_event_pri.h +++ b/src/kernel/base/include/los_event_pri.h @@ -38,10 +38,11 @@ extern "C" { #endif /* __cplusplus */ #ifdef LOSCFG_COMPAT_POSIX +//定义时间状态的结构体 typedef struct { - volatile INT32 *realValue; - INT32 value; - UINT32 clearEvent; + volatile INT32 *realValue;//指向的是一个共享资源的计数器 + INT32 value;//条件变量的值 + UINT32 clearEvent;//需要清除的事件标志 } EventCond; extern UINT32 OsEventReadWithCond(const EventCond *cond, PEVENT_CB_S eventCB, diff --git a/src/kernel/base/include/los_exc_pri.h b/src/kernel/base/include/los_exc_pri.h index 43d5a26..3bdde26 100644 --- a/src/kernel/base/include/los_exc_pri.h +++ b/src/kernel/base/include/los_exc_pri.h @@ -25,12 +25,13 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +//防止同一个头文件被多次包含 #ifndef _LOS_EXC_PRI_H #define _LOS_EXC_PRI_H #include "los_exc.h" + #ifdef __cplusplus #if __cplusplus extern "C" { @@ -38,17 +39,28 @@ extern "C" { #endif /* __cplusplus */ #ifdef LOSCFG_SHELL_EXCINFO_DUMP +//用于设置异常信息读写函数的指针。 extern VOID OsSetExcInfoRW(LogReadWriteFunc func); extern LogReadWriteFunc OsGetExcInfoRW(VOID); +//用于设置异常信息缓冲区的指针。 extern VOID OsSetExcInfoBuf(CHAR *buf); +//用于获取异常信息缓冲区的指针。 extern CHAR *OsGetExcInfoBuf(VOID); +//用于设置异常信息在缓冲区中的偏移量。 extern VOID OsSetExcInfoOffset(UINT32 offset); +//用于获取异常信息在缓冲区中的偏移量。 extern UINT32 OsGetExcInfoOffset(VOID); +//用于设置异常信息转储地址。 extern VOID OsSetExcInfoDumpAddr(UINTPTR addr); +//用于获取异常信息转储地址。 extern UINTPTR OsGetExcInfoDumpAddr(VOID); +//用于设置异常信息的长度。 extern VOID OsSetExcInfoLen(UINT32 len); +//用于获取异常信息的长度。 extern UINT32 OsGetExcInfoLen(VOID); +//用于记录异常信息的时间戳。 extern VOID OsRecordExcInfoTime(VOID); +//用于将格式化的字符串写入异常信息缓冲区。 extern VOID WriteExcBufVa(const CHAR *format, va_list arg); extern VOID WriteExcInfoToBuf(const CHAR *format, ...); #endif diff --git a/src/kernel/base/include/los_hwi_pri.h b/src/kernel/base/include/los_hwi_pri.h index 257a07b..4b0ed7a 100644 --- a/src/kernel/base/include/los_hwi_pri.h +++ b/src/kernel/base/include/los_hwi_pri.h @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +//定义了一些与硬件中断处理相关的数据结构和函数接口,用于操作和管理系统中的硬件中断。 #ifndef _LOS_HWI_PRI_H #define _LOS_HWI_PRI_H @@ -67,9 +67,11 @@ typedef struct { } HwiControllerOps; extern const HwiControllerOps *g_hwiOps; - +//用于初始化硬件中断 extern VOID OsHwiInit(VOID); +//用于获取当前中断嵌套的计数值,可以用于检查当前是否处于中断嵌套状态。 extern size_t OsIrqNestingCntGet(VOID); +//用于设置中断嵌套的计数值。 extern VOID OsIrqNestingCntSet(size_t val); /** @@ -77,8 +79,9 @@ extern VOID OsIrqNestingCntSet(size_t val); * by the kernel. The handleIrq hook function MUST be registered in the interrupt controller driver layer, otherwise it * will not respond. eg: Used for arm(cortex-a/r)/arm64. */ +//一个汇编入口函数,由汇编代码在dispatch.S中调用,用于统一处理外部中断的入口,由内核接管中断处理流程。 extern VOID OsIntEntry(VOID); - +//根据中断号获取中断处理信息的指针 STATIC INLINE HwiHandleInfo *OsGetHwiForm(UINT32 hwiNum) { if ((g_hwiOps == NULL) || (g_hwiOps->getHandleForm == NULL)) { @@ -86,7 +89,7 @@ STATIC INLINE HwiHandleInfo *OsGetHwiForm(UINT32 hwiNum) } return g_hwiOps->getHandleForm(hwiNum); } - +//用于获取指定中断的响应计数值 STATIC INLINE UINT32 OsGetHwiFormCnt(UINT32 hwiNum) { HwiHandleInfo *hwiForm = OsGetHwiForm(hwiNum); @@ -96,7 +99,7 @@ STATIC INLINE UINT32 OsGetHwiFormCnt(UINT32 hwiNum) } return hwiForm->respCount; } - +//用于获取当前正在处理的中断号。 STATIC INLINE UINT32 OsIntNumGet(VOID) { if ((g_hwiOps == NULL) || (g_hwiOps->getCurIrqNum == NULL)) { @@ -104,7 +107,7 @@ STATIC INLINE UINT32 OsIntNumGet(VOID) } return g_hwiOps->getCurIrqNum(); } - +//用于判断指定的中断号是否已经注册了相应的处理函数。 STATIC INLINE BOOL OsIntIsRegisted(UINT32 num) { HwiHandleInfo *hwiForm = OsGetHwiForm(num); @@ -118,7 +121,7 @@ STATIC INLINE BOOL OsIntIsRegisted(UINT32 num) return (hwiForm->hook != NULL); #endif } - +//用于获取指定中断的注册参数信息。 STATIC INLINE HWI_ARG_T OsIntGetPara(UINT32 num) { HwiHandleInfo *hwiForm = OsGetHwiForm(num); @@ -128,7 +131,7 @@ STATIC INLINE HWI_ARG_T OsIntGetPara(UINT32 num) } return hwiForm->registerInfo; } - +//用于获取中断版本信息。 STATIC INLINE CHAR *OsIntVersionGet(VOID) { if ((g_hwiOps == NULL) || (g_hwiOps->getIrqVersion == NULL)) { @@ -143,6 +146,7 @@ STATIC INLINE CHAR *OsIntVersionGet(VOID) * handleForm to this interface. * eg: Used for arm(cortex-m),xtensa,riscv. */ +//在中断控制器驱动层实现通用的中断处理入口,用于传递中断号和处理信息给相应的处理函数。 extern VOID OsIntHandle(UINT32 hwiNum, HwiHandleInfo *handleForm); /** @@ -151,6 +155,7 @@ extern VOID OsIntHandle(UINT32 hwiNum, HwiHandleInfo *handleForm); * HwiControllerOps need to be registered. If this function is not supported, you can call the LOS_Panic interface in * the implementation of the stub function to report an error in time. */ +//用于注册中断控制器相关的操作函数,需要在中断控制器初始化时被调用。 STATIC INLINE VOID OsHwiControllerReg(const HwiControllerOps *ops) { g_hwiOps = ops; diff --git a/src/kernel/base/include/los_memory_pri.h b/src/kernel/base/include/los_memory_pri.h index fe56414..7214baa 100644 --- a/src/kernel/base/include/los_memory_pri.h +++ b/src/kernel/base/include/los_memory_pri.h @@ -35,6 +35,8 @@ #include "los_spinlock.h" #include "los_misc_pri.h" +//关于内存管理的私有接口声明 + #ifdef __cplusplus #if __cplusplus extern "C" { @@ -60,6 +62,7 @@ typedef struct { struct LosSlabControlHeader slabCtrlHdr; #endif } LosMemPoolInfo; +//用于描述内存池的信息,包括内存池的起始地址、大小等信息。 #elif defined(LOSCFG_KERNEL_MEM_BESTFIT_LITTLE) @@ -90,6 +93,7 @@ extern SPIN_LOCK_S g_memSpin; #define MEM_LOCK(state) LOS_SpinLockSave(&g_memSpin, &(state)) #define MEM_UNLOCK(state) LOS_SpinUnlockRestore(&g_memSpin, (state)) +//用于系统内存的初始化。 extern UINTPTR g_sys_mem_addr_end; extern UINT32 OsMemSystemInit(UINTPTR memStart); @@ -104,11 +108,12 @@ extern UINT32 OsMemMulPoolInit(VOID *pool, UINT32 size); extern UINT32 OsMemMulPoolDeinit(const VOID *pool); extern VOID *OsMemMulPoolHeadGet(VOID); #else /* LOSCFG_MEM_MUL_POOL */ +//用于初始化多内存池,接受内存池的起始地址和大小作为参数。 STATIC INLINE UINT32 OsMemMulPoolInit(VOID *pool, UINT32 size) { return LOS_OK; } - +//用于反初始化多内存池,接受内存池的指针作为参数。 STATIC INLINE UINT32 OsMemMulPoolDeinit(const VOID *pool) { return LOS_OK; @@ -116,16 +121,21 @@ STATIC INLINE UINT32 OsMemMulPoolDeinit(const VOID *pool) #endif /* LOSCFG_MEM_MUL_POOL */ #ifdef LOSCFG_EXC_INTERACTION +//于初始化内存异常交互,接受内存起始地址作为参数。 extern UINT32 OsMemExcInteractionInit(UINTPTR memStart); #endif #ifdef LOSCFG_MEM_LEAKCHECK +//用于展示已使用的内存节点信息,接受内存池指针作为参数。 extern VOID OsMemUsedNodeShow(VOID *pool); #endif - +//用于重置内存池的结束节点,接受内存池指针和前一个地址作为参数。 extern VOID OsMemResetEndNode(VOID *pool, UINTPTR preAddr); +//用于打印内存信息,接受内存池指针作为参数。 extern VOID OsMemInfoPrint(const VOID *pool); +//用于执行内存检查的 shell 命令,接受命令参数作为输入。 extern UINT32 OsShellCmdMemCheck(INT32 argc, const CHAR *argv[]); +//用于执行多重内存完整性检查。 extern VOID OsMemIntegrityMultiCheck(VOID); #ifdef __cplusplus diff --git a/src/kernel/base/include/los_memstat_pri.h b/src/kernel/base/include/los_memstat_pri.h index 2b43079..40d8131 100644 --- a/src/kernel/base/include/los_memstat_pri.h +++ b/src/kernel/base/include/los_memstat_pri.h @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +//定义了一些用于内存统计的数据结构和函数接口,用于跟踪和管理任务使用的内存情况。 #ifndef _LOS_MEMSTAT_PRI_H #define _LOS_MEMSTAT_PRI_H @@ -43,19 +43,22 @@ extern "C" { #ifdef LOSCFG_MEM_TASK_STAT typedef struct { - UINT32 memUsed; - UINT32 memPeak; + UINT32 memUsed;//内存使用 + UINT32 memPeak;//内存峰值 } TaskMemUsedInfo; typedef struct { - UINT32 memTotalUsed; - UINT32 memTotalPeak; - TaskMemUsedInfo taskMemstats[TASK_NUM]; + UINT32 memTotalUsed;//内存使用量 + UINT32 memTotalPeak;//内存使用峰值 + TaskMemUsedInfo taskMemstats[TASK_NUM];//使用内存的任务列表 } Memstat; - +//用于增加任务的内存使用量和峰值。 extern VOID OsMemstatTaskUsedInc(Memstat *stat, UINT32 usedSize, UINT32 taskId); +//用于减少任务的内存使用量和峰值。 extern VOID OsMemstatTaskUsedDec(Memstat *stat, UINT32 usedSize, UINT32 taskId); +//用于清除任务的内存统计信息。 extern VOID OsMemstatTaskClear(Memstat *stat, UINT32 taskId); +//用于获取任务的内存使用率。 extern UINT32 OsMemstatTaskUsage(const Memstat *stat, UINT32 taskId); #endif @@ -63,9 +66,13 @@ extern VOID OsMemTaskClear(UINT32 taskId); extern UINT32 OsMemTaskUsage(UINT32 taskId); #ifdef LOSCFG_MEM_TASK_STAT +//增加任务的内存使用量和峰值。 #define OS_MEM_ADD_USED(stat, usedSize, taskId) OsMemstatTaskUsedInc(stat, usedSize, taskId) +//减少任务的内存使用量和峰值。 #define OS_MEM_REDUCE_USED(stat, usedSize, taskId) OsMemstatTaskUsedDec(stat, usedSize, taskId) +//清除任务的内存统计信息。 #define OS_MEM_CLEAR(taskId) OsMemTaskClear(taskId) +//获取任务的内存使用率。 #define OS_MEM_USAGE(taskId) OsMemTaskUsage(taskId) #else #define OS_MEM_ADD_USED(stat, usedSize, taskId) diff --git a/src/kernel/base/include/los_misc_pri.h b/src/kernel/base/include/los_misc_pri.h index b0a3403..041d8bd 100644 --- a/src/kernel/base/include/los_misc_pri.h +++ b/src/kernel/base/include/los_misc_pri.h @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +//定义了一些私有接口和数据结构,主要涉及与内存相关的功能和调试功能。 #ifndef _LOS_MISC_PRI_H #define _LOS_MISC_PRI_H @@ -36,7 +36,7 @@ extern "C" { #endif /* __cplusplus */ #endif /* __cplusplus */ - +//定义了一个用于将指定地址开始的连续内存字节进行转储的函数。可以用于调试和观察内存中的数据。 VOID OsDumpMemByte(size_t length, UINTPTR addr); #if defined(LOSCFG_DEBUG_SEMAPHORE) || defined(LOSCFG_DEBUG_MUTEX) || defined(LOSCFG_DEBUG_QUEUE) @@ -48,13 +48,16 @@ typedef struct { } SortParam; /* Compare the size of the last access time */ +//用于排序时比较控制块成员的大小。 typedef BOOL (*OsCompareFunc)(const SortParam *sortParam, UINT32 left, UINT32 right); /* Get the address of the comparison member variable */ +//用于获取控制块成员变量的地址。 #define SORT_ELEM_ADDR(sortParam, index) \ ((sortParam)->buf + ((index) * (sortParam)->ctrlBlockSize) + (sortParam)->sortElemOff) /* Sort this index array. */ +//用于对索引数组进行排序。 extern VOID OsArraySort(UINT32 *sortArray, UINT32 start, UINT32 end, const SortParam *sortParam, OsCompareFunc compareFunc); #endif diff --git a/src/kernel/base/include/los_mp_pri.h b/src/kernel/base/include/los_mp_pri.h index ad2d5de..0359e40 100644 --- a/src/kernel/base/include/los_mp_pri.h +++ b/src/kernel/base/include/los_mp_pri.h @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +//定义了一些私有接口、数据结构和宏,主要涉及多处理器(MP)相关的功能。 #ifndef _LOS_MP_PRI_H #define _LOS_MP_PRI_H @@ -56,10 +56,15 @@ typedef enum { typedef VOID (*SMP_FUNC_CALL)(VOID *args); #ifdef LOSCFG_KERNEL_SMP +//定义了一个用于在多处理器系统中切换调度目标的函数。 extern VOID LOS_MpSchedule(UINT32 target); +//定义了一个用于处理多处理器唤醒事件的函数。 extern VOID OsMpWakeHandler(VOID); +//定义了一个用于处理多处理器调度事件的函数。 extern VOID OsMpScheduleHandler(VOID); +//定义了一个用于处理多处理器停机事件的函数。 extern VOID OsMpHaltHandler(VOID); +//定义了一个用于初始化多处理器相关功能的函数。 extern UINT32 OsMpInit(VOID); #else STATIC INLINE VOID LOS_MpSchedule(UINT32 target) @@ -69,7 +74,7 @@ STATIC INLINE VOID LOS_MpSchedule(UINT32 target) #endif #ifdef LOSCFG_KERNEL_SMP_CALL - +//用于在目标 CPU 上调用函数 typedef struct { LOS_DL_LIST node; SMP_FUNC_CALL func; @@ -82,6 +87,7 @@ typedef struct { extern VOID OsMpFuncCall(UINT32 target, SMP_FUNC_CALL func, VOID *args); extern VOID OsMpFuncCallHandler(VOID); #else +//用于处理多处理器函数调用事件。 STATIC INLINE VOID OsMpFuncCall(UINT32 target, SMP_FUNC_CALL func, VOID *args) { (VOID)target; diff --git a/src/kernel/base/include/los_multipledlinkhead_pri.h b/src/kernel/base/include/los_multipledlinkhead_pri.h index 7befa0e..98461e2 100644 --- a/src/kernel/base/include/los_multipledlinkhead_pri.h +++ b/src/kernel/base/include/los_multipledlinkhead_pri.h @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +//定义了一个多重双向链表头的私有接口和数据结构。 #ifndef _LOS_MULTIPLE_DLINK_HEAD_PRI_H #define _LOS_MULTIPLE_DLINK_HEAD_PRI_H @@ -37,25 +37,30 @@ extern "C" { #endif /* __cplusplus */ #endif /* __cplusplus */ - +//表示最大的多重双向链表的大小的对数值。 #define OS_MAX_MULTI_DLNK_LOG2 29 +//表示最小的多重双向链表的大小的对数值。 #define OS_MIN_MULTI_DLNK_LOG2 4 +//表示多重双向链表的数量,通过最大和最小的对数值计算得到。 #define OS_MULTI_DLNK_NUM ((OS_MAX_MULTI_DLNK_LOG2 - OS_MIN_MULTI_DLNK_LOG2) + 1) +//表示多重双向链表头的大小。 #define OS_DLNK_HEAD_SIZE OS_MULTI_DLNK_HEAD_SIZE +//表示多重双向链表头结构体的大小。 #define OS_MULTI_DLNK_HEAD_SIZE sizeof(LosMultipleDlinkHead) - +//用于存储多重双向链表的头指针数组。 typedef struct { LOS_DL_LIST listHead[OS_MULTI_DLNK_NUM]; } LosMultipleDlinkHead; - +//根据给定的头地址和链表节点头指针,返回下一个多重链表的头指针。 STATIC INLINE LOS_DL_LIST *OsDLnkNextMultiHead(VOID *headAddr, LOS_DL_LIST *listNodeHead) { LosMultipleDlinkHead *head = (LosMultipleDlinkHead *)headAddr; return (&head->listHead[OS_MULTI_DLNK_NUM - 1] == listNodeHead) ? NULL : (listNodeHead + 1); } - +//对给定的头地址进行初始化,将多重双向链表的头指针数组中的所有指针置为 NULL。 extern VOID OsDLnkInitMultiHead(VOID *headAddr); +//根据给定的头地址和大小,返回对应的多重双向链表的头指针。 extern LOS_DL_LIST *OsDLnkMultiHead(VOID *headAddr, UINT32 size); #ifdef __cplusplus diff --git a/src/kernel/base/los_bitmap.c b/src/kernel/base/los_bitmap.c index 84a056a..d299fb6 100644 --- a/src/kernel/base/los_bitmap.c +++ b/src/kernel/base/los_bitmap.c @@ -35,7 +35,7 @@ extern "C" { #endif /* __cplusplus */ #endif /* __cplusplus */ -#define OS_BITMAP_MASK 0x1FU +#define OS_BITMAP_MASK 0x1FU//位图的掩码,与数据进行与操作得到低五位的信息 VOID LOS_BitmapSet(UINT32 *bitmap, UINT16 pos) { diff --git a/src/kernel/include/los_typedef.h b/src/kernel/include/los_typedef.h index aa5e5e1..dedd290 100644 --- a/src/kernel/include/los_typedef.h +++ b/src/kernel/include/los_typedef.h @@ -49,6 +49,7 @@ extern "C" { #define X_STRING(x) OS_STRING(x) /* type definitions */ +//定义数据类型 typedef unsigned char UINT8; typedef unsigned short UINT16; typedef unsigned int UINT32; @@ -59,7 +60,10 @@ typedef float FLOAT; typedef double DOUBLE; typedef char CHAR; + + #ifdef __LP64__ +//64位数据模型 typedef long unsigned int UINT64; typedef long signed int INT64; typedef unsigned long UINTPTR; @@ -71,6 +75,7 @@ typedef INT64 ssize_t; typedef UINT64 size_t; #endif #else +//32位数据模型 typedef unsigned long long UINT64; typedef signed long long INT64; typedef unsigned int UINTPTR; @@ -80,7 +85,7 @@ typedef INT32 ssize_t; typedef UINT32 size_t; #endif #endif - +//一些常数的定义 typedef UINTPTR AARCHPTR; typedef size_t BOOL; From cc2b0861fede0dffb70842cadac3f5f6926426ba Mon Sep 17 00:00:00 2001 From: tree <1913915946@qq.com> Date: Sun, 3 Dec 2023 23:46:09 +0800 Subject: [PATCH 09/26] 2 --- src/kernel/base/los_queue.c | 39 +++++++++++++++++++-------------- src/kernel/base/los_ringbuf.c | 19 ++++++++-------- src/kernel/base/los_sem.c | 23 ++++++++++--------- src/kernel/base/los_sortlink.c | 32 +++++++++++++-------------- src/kernel/base/los_stackinfo.c | 10 ++++----- src/kernel/base/los_swtmr.c | 25 +++++++++++++-------- src/kernel/base/los_tick.c | 23 +++++++++---------- 7 files changed, 95 insertions(+), 76 deletions(-) diff --git a/src/kernel/base/los_queue.c b/src/kernel/base/los_queue.c index 3b217ed..3a7e9a6 100644 --- a/src/kernel/base/los_queue.c +++ b/src/kernel/base/los_queue.c @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ -//队列 +//实现了一个基于轻量级操作系统的队列管理模块,提供了队列的创建、读写、删除以及信息获取等功能 #include "los_queue_pri.h" #include "los_queue_debug_pri.h" #include "los_task_pri.h" @@ -53,6 +53,7 @@ LITE_OS_SEC_BSS STATIC LOS_DL_LIST g_freeQueueList; * Description : queue initial * Return : LOS_OK on success or error code on failure */ +//初始化队列,返回成功或失败错误码 LITE_OS_SEC_TEXT_INIT UINT32 OsQueueInit(VOID) { LosQueueCB *queueNode = NULL; @@ -78,7 +79,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsQueueInit(VOID) } return LOS_OK; } - +//OsQueueCreateParameterCheck函数用于检查创建队列时传入的参数是否合法 STATIC INLINE UINT32 OsQueueCreateParameterCheck(UINT16 len, const UINT32 *queueId, UINT16 maxMsgSize) { if (queueId == NULL) { @@ -94,7 +95,7 @@ STATIC INLINE UINT32 OsQueueCreateParameterCheck(UINT16 len, const UINT32 *queue } return LOS_OK; } - +//OsQueueCreateInternal函数用于创建队列,包括在队列控制块中记录队列长度、消息大小等信息 LITE_OS_SEC_TEXT_INIT STATIC UINT32 OsQueueCreateInternal(UINT16 len, UINT32 *queueId, UINT16 msgSize, UINT8 *queue, UINT8 queueMemType) { @@ -165,7 +166,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_QueueCreateStatic(const CHAR *queueName, return OsQueueCreateInternal(len, queueId, msgSize, queueMem, OS_QUEUE_ALLOC_STATIC); } #endif - +//创建队列 LITE_OS_SEC_TEXT_INIT UINT32 LOS_QueueCreate(const CHAR *queueName, UINT16 len, UINT32 *queueId, UINT32 flags, UINT16 maxMsgSize) { @@ -198,7 +199,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_QueueCreate(const CHAR *queueName, UINT16 len, return LOS_OK; } - +//OsQueueReadParameterCheck和OsQueueWriteParameterCheck分别用于检查读和写操作的参数合法性 LITE_OS_SEC_TEXT STATIC UINT32 OsQueueReadParameterCheck(UINT32 queueId, const VOID *bufferAddr, const UINT32 *bufferSize, UINT32 timeout) { @@ -248,7 +249,7 @@ LITE_OS_SEC_TEXT STATIC UINT32 OsQueueWriteParameterCheck(UINT32 queueId, const } return LOS_OK; } - +//实现了队列的读取和写入操作,并对可能出现的错误进行了处理 STATIC UINT32 OsQueueBufferOperate(LosQueueCB *queueCB, UINT32 operateType, VOID *bufferAddr, UINT32 *bufferSize) { UINT8 *queueNode = NULL; @@ -296,7 +297,7 @@ STATIC UINT32 OsQueueBufferOperate(LosQueueCB *queueCB, UINT32 operateType, VOID } return LOS_OK; } - +//用于处理队列操作函数 OsQueueBufferOperate 返回的错误码,使得在发生错误时能够打印相应的错误信息 STATIC VOID OsQueueBufferOperateErrProcess(UINT32 errorCode) { switch (errorCode) { @@ -336,7 +337,7 @@ STATIC UINT32 OsQueueOperateParamCheck(const LosQueueCB *queueCB, UINT32 queueId } return LOS_OK; } - +//OsQueueOperate:实现了对队列的操作,包括参数检查、任务挂起与唤醒以及错误处理等功能 STATIC UINT32 OsQueueOperate(UINT32 queueId, UINT32 operateType, VOID *bufferAddr, UINT32 *bufferSize, UINT32 timeout) { LosQueueCB *queueCB = (LosQueueCB *)GET_QUEUE_HANDLE(queueId); @@ -400,7 +401,7 @@ QUEUE_END: OsQueueBufferOperateErrProcess(errorCode); return ret; } - +//LOS_QueueReadCopy:从队列中读取数据,通过参数检查后调用OsQueueOperate函数进行实际的读取操作 LITE_OS_SEC_TEXT UINT32 LOS_QueueReadCopy(UINT32 queueId, VOID *bufferAddr, UINT32 *bufferSize, @@ -417,7 +418,7 @@ LITE_OS_SEC_TEXT UINT32 LOS_QueueReadCopy(UINT32 queueId, operateType = OS_QUEUE_OPERATE_TYPE(OS_QUEUE_READ, OS_QUEUE_HEAD); return OsQueueOperate(queueId, operateType, bufferAddr, bufferSize, timeout); } - +//LOS_QueueWriteHeadCopy:向队列的头部写入数据,通过参数检查后调用OsQueueOperate函数进行实际的写入操作 LITE_OS_SEC_TEXT UINT32 LOS_QueueWriteHeadCopy(UINT32 queueId, VOID *bufferAddr, UINT32 bufferSize, @@ -434,7 +435,7 @@ LITE_OS_SEC_TEXT UINT32 LOS_QueueWriteHeadCopy(UINT32 queueId, operateType = OS_QUEUE_OPERATE_TYPE(OS_QUEUE_WRITE, OS_QUEUE_HEAD); return OsQueueOperate(queueId, operateType, bufferAddr, &bufferSize, timeout); } - +//LOS_QueueWriteCopy:向队列的尾部写入数据,通过参数检查后调用OsQueueOperate函数进行实际的写入操作 LITE_OS_SEC_TEXT UINT32 LOS_QueueWriteCopy(UINT32 queueId, VOID *bufferAddr, UINT32 bufferSize, @@ -451,12 +452,12 @@ LITE_OS_SEC_TEXT UINT32 LOS_QueueWriteCopy(UINT32 queueId, operateType = OS_QUEUE_OPERATE_TYPE(OS_QUEUE_WRITE, OS_QUEUE_TAIL); return OsQueueOperate(queueId, operateType, bufferAddr, &bufferSize, timeout); } - +//LOS_QueueRead:从队列中读取数据的简化接口,直接调用LOS_QueueReadCopy函数 LITE_OS_SEC_TEXT UINT32 LOS_QueueRead(UINT32 queueId, VOID *bufferAddr, UINT32 bufferSize, UINT32 timeout) { return LOS_QueueReadCopy(queueId, bufferAddr, &bufferSize, timeout); } - +//LOS_QueueWrite:向队列中写入数据的简化接口,先进行参数检查,然后调用LOS_QueueWriteCopy函数 LITE_OS_SEC_TEXT UINT32 LOS_QueueWrite(UINT32 queueId, VOID *bufferAddr, UINT32 bufferSize, UINT32 timeout) { if (bufferAddr == NULL) { @@ -465,7 +466,7 @@ LITE_OS_SEC_TEXT UINT32 LOS_QueueWrite(UINT32 queueId, VOID *bufferAddr, UINT32 bufferSize = sizeof(CHAR *); return LOS_QueueWriteCopy(queueId, &bufferAddr, bufferSize, timeout); } - +//LOS_QueueWriteHead:向队列头部写入数据的简化接口,先进行参数检查,然后调用LOS_QueueWriteHeadCopy函数 LITE_OS_SEC_TEXT UINT32 LOS_QueueWriteHead(UINT32 queueId, VOID *bufferAddr, UINT32 bufferSize, @@ -477,7 +478,8 @@ LITE_OS_SEC_TEXT UINT32 LOS_QueueWriteHead(UINT32 queueId, bufferSize = sizeof(CHAR *); return LOS_QueueWriteHeadCopy(queueId, &bufferAddr, bufferSize, timeout); } - +//LOS_QueueDelete:删除队列的函数 +//首先检查队列是否存在,如果存在则检查是否有任务正在使用队列或者队列中还有未释放的内存块,如果满足条件则释放队列所占用的资源 LITE_OS_SEC_TEXT_INIT UINT32 LOS_QueueDelete(UINT32 queueId) { LosQueueCB *queueCB = NULL; @@ -537,7 +539,7 @@ QUEUE_END: SCHEDULER_UNLOCK(intSave); return ret; } - +//LOS_QueueInfoGet:获取指定队列的相关信息,包括队列ID、队列长度、队列大小、队列头尾指针、等待读取和写入的任务数等 LITE_OS_SEC_TEXT_MINOR UINT32 LOS_QueueInfoGet(UINT32 queueId, QUEUE_INFO_S *queueInfo) { UINT32 intSave; @@ -595,6 +597,9 @@ QUEUE_END: * : timeout --- Expiry time. The value range is [0,LOS_WAIT_FOREVER] * Return : pointer if success otherwise NULL */ +//OsQueueMailAlloc函数用来从邮件池中分配一个邮件内存块 +//如果没有可用的内存块,则根据超时时间挂起当前任务,并将其加入到等待内存块的任务链表中 +//当有内存块可用时,会将任务从任务链表中移除,并返回分配的内存块指针 LITE_OS_SEC_TEXT VOID *OsQueueMailAlloc(UINT32 queueId, VOID *mailPool, UINT32 timeout) { VOID *mem = NULL; @@ -663,6 +668,8 @@ END: * : mailMem --- The mail memory block address * Return : LOS_OK on success or error code on failure */ +//OsQueueMailFree函数用来释放指定的邮件内存块,并将其加入到邮件池的空闲链表中 +//如果有任务在等待内存块,则会从任务链表中唤醒一个任务,并将其从任务链表中移除 LITE_OS_SEC_TEXT UINT32 OsQueueMailFree(UINT32 queueId, VOID *mailPool, VOID *mailMem) { VOID *mem = NULL; diff --git a/src/kernel/base/los_ringbuf.c b/src/kernel/base/los_ringbuf.c index c33ea3f..524cea8 100644 --- a/src/kernel/base/los_ringbuf.c +++ b/src/kernel/base/los_ringbuf.c @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +/*实现环形缓冲区。环形缓冲区是一种循环使用固定大小存储空间的数据结构,常用于解决生产者-消费者问题*/ #include "los_ringbuf.h" #ifdef __cplusplus @@ -33,7 +33,7 @@ extern "C" { #endif /* __cplusplus */ #endif /* __cplusplus */ - +//LOS_RingbufUsedSize:获取环形缓冲区已使用的大小 UINT32 LOS_RingbufUsedSize(Ringbuf *ringbuf) { UINT32 size; @@ -56,6 +56,7 @@ UINT32 LOS_RingbufUsedSize(Ringbuf *ringbuf) * | * endIdx */ +//OsRingbufWriteLinear:线性写入数据到环形缓冲区 STATIC UINT32 OsRingbufWriteLinear(Ringbuf *ringbuf, const CHAR *buf, UINT32 size) { UINT32 cpSize; @@ -77,7 +78,7 @@ STATIC UINT32 OsRingbufWriteLinear(Ringbuf *ringbuf, const CHAR *buf, UINT32 siz return cpSize; } - +//OsRingbufWriteLoop:循环写入数据到环形缓冲区 STATIC UINT32 OsRingbufWriteLoop(Ringbuf *ringbuf, const CHAR *buf, UINT32 size) { UINT32 right, cpSize; @@ -105,7 +106,7 @@ STATIC UINT32 OsRingbufWriteLoop(Ringbuf *ringbuf, const CHAR *buf, UINT32 size) return cpSize; } - +//LOS_RingbufWrite:向环形缓冲区写入数据 UINT32 LOS_RingbufWrite(Ringbuf *ringbuf, const CHAR *buf, UINT32 size) { UINT32 cpSize = 0; @@ -130,7 +131,7 @@ EXIT: LOS_SpinUnlockRestore(&ringbuf->lock, intSave); return cpSize; } - +//OsRingbufReadLinear:线性读取环形缓冲区中的数据 STATIC UINT32 OsRingbufReadLinear(Ringbuf *ringbuf, CHAR *buf, UINT32 size) { UINT32 cpSize, remain; @@ -153,7 +154,7 @@ STATIC UINT32 OsRingbufReadLinear(Ringbuf *ringbuf, CHAR *buf, UINT32 size) return cpSize; } - +//OsRingbufReadLoop:循环读取环形缓冲区中的数据 STATIC UINT32 OsRingbufReadLoop(Ringbuf *ringbuf, CHAR *buf, UINT32 size) { UINT32 right, cpSize; @@ -179,7 +180,7 @@ STATIC UINT32 OsRingbufReadLoop(Ringbuf *ringbuf, CHAR *buf, UINT32 size) return cpSize; } - +//LOS_RingbufRead:从环形缓冲区读取数据 UINT32 LOS_RingbufRead(Ringbuf *ringbuf, CHAR *buf, UINT32 size) { UINT32 cpSize; @@ -205,7 +206,7 @@ EXIT: LOS_SpinUnlockRestore(&ringbuf->lock, intSave); return cpSize; } - +//LOS_RingbufInit:初始化环形缓冲区 UINT32 LOS_RingbufInit(Ringbuf *ringbuf, CHAR *fifo, UINT32 size) { if ((ringbuf == NULL) || (fifo == NULL) || @@ -221,7 +222,7 @@ UINT32 LOS_RingbufInit(Ringbuf *ringbuf, CHAR *fifo, UINT32 size) ringbuf->status = RBUF_INITED; return LOS_OK; } - +//LOS_RingbufReset:重置环形缓冲区 VOID LOS_RingbufReset(Ringbuf *ringbuf) { UINT32 intSave; diff --git a/src/kernel/base/los_sem.c b/src/kernel/base/los_sem.c index 8703827..867babf 100644 --- a/src/kernel/base/los_sem.c +++ b/src/kernel/base/los_sem.c @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +/*实现信号量的操作系统内核代码,主要包括信号量的创建、删除、等待(Pend)和释放(Post)等操作*/ #include "los_sem_pri.h" #include "los_sem_debug_pri.h" #include "los_err_pri.h" @@ -49,7 +49,7 @@ STATIC_INLINE VOID OsSemNodeRecycle(LosSemCB *semNode) semNode->semStat = LOS_UNUSED; LOS_ListTailInsert(&g_unusedSemList, &semNode->semList); } - +//OsSemInit()函数:用于初始化信号量管理模块,包括申请创建信号量所需要的内存空间、将信号量结构体加入到未使用链表中等 LITE_OS_SEC_TEXT_INIT UINT32 OsSemInit(VOID) { LosSemCB *semNode = NULL; @@ -74,7 +74,8 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsSemInit(VOID) } return LOS_OK; } - +//OsSemCreate函数:用于创建一个信号量,并将其加入到已使用信号量列表中 +//参数count表示信号量的初始值,type表示信号量的类型(计数信号量或二进制信号量),semHandle用于返回创建的信号量的句柄 LITE_OS_SEC_TEXT_INIT STATIC UINT32 OsSemCreate(UINT16 count, UINT8 type, UINT32 *semHandle) { UINT32 intSave; @@ -109,7 +110,7 @@ LITE_OS_SEC_TEXT_INIT STATIC UINT32 OsSemCreate(UINT16 count, UINT8 type, UINT32 LOS_TRACE(SEM_CREATE, semCreated->semId, type, count); return LOS_OK; } - +//LOS_SemCreate:对外部提供的接口函数,用于创建一个计数信号量 LITE_OS_SEC_TEXT_INIT UINT32 LOS_SemCreate(UINT16 count, UINT32 *semHandle) { if (count > LOS_SEM_COUNT_MAX) { @@ -117,7 +118,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_SemCreate(UINT16 count, UINT32 *semHandle) } return OsSemCreate(count, OS_SEM_COUNTING, semHandle); } - +//LOS_BinarySemCreate:对外部提供的接口函数,用于创建一个二进制信号量 LITE_OS_SEC_TEXT_INIT UINT32 LOS_BinarySemCreate(UINT16 count, UINT32 *semHandle) { if (count > OS_SEM_BINARY_COUNT_MAX) { @@ -125,7 +126,8 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_BinarySemCreate(UINT16 count, UINT32 *semHandle } return OsSemCreate(count, OS_SEM_BINARY, semHandle); } - +//OsSemStateVerify:用于验证信号量的状态是否有效 +//参数semId表示要验证的信号量的ID,semNode是指向信号量控制块的指针 STATIC_INLINE UINT32 OsSemStateVerify(UINT32 semId, const LosSemCB *semNode) { #ifndef LOSCFG_RESOURCE_ID_NOT_USE_HIGH_BITS @@ -137,7 +139,8 @@ STATIC_INLINE UINT32 OsSemStateVerify(UINT32 semId, const LosSemCB *semNode) } return LOS_OK; } - +//OsSemGetCBWithCheck:用于根据信号量句柄获取信号量的控制块 +//参数semHandle表示信号量的句柄,semCB是一个指向指针的指针,用于返回获取到的信号量控制块 STATIC UINT32 OsSemGetCBWithCheck(UINT32 semHandle, LosSemCB **semCB) { if (GET_SEM_INDEX(semHandle) >= (UINT32)KERNEL_SEM_LIMIT) { @@ -147,7 +150,7 @@ STATIC UINT32 OsSemGetCBWithCheck(UINT32 semHandle, LosSemCB **semCB) *semCB = GET_SEM(semHandle); return LOS_OK; } - +//LOS_SemDelete:用于删除指定句柄的信号量,如果有任务正在等待该信号量,则删除失败 LITE_OS_SEC_TEXT_INIT UINT32 LOS_SemDelete(UINT32 semHandle) { UINT32 intSave; @@ -184,7 +187,7 @@ OUT: LOS_TRACE(SEM_DELETE, semHandle, ret); return ret; } - +//LOS_SemPend:用于等待(Pend)一个信号量,如果信号量不可用,则阻塞当前任务直到信号量可用或超时。timeout表示超时时间 LITE_OS_SEC_TEXT UINT32 LOS_SemPend(UINT32 semHandle, UINT32 timeout) { UINT32 intSave; @@ -252,7 +255,7 @@ OUT: SCHEDULER_UNLOCK(intSave); return ret; } - +//LOS_SemPost:用于释放(Post)一个信号量,使其变为可用状态,并唤醒等待该信号量的任务中的第一个任务 LITE_OS_SEC_TEXT UINT32 LOS_SemPost(UINT32 semHandle) { UINT32 intSave; diff --git a/src/kernel/base/los_sortlink.c b/src/kernel/base/los_sortlink.c index e39fdbc..e934398 100644 --- a/src/kernel/base/los_sortlink.c +++ b/src/kernel/base/los_sortlink.c @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +/*嵌入式操作系统中与任务调度相关的排序链表管理代码。包括了对排序链表的初始化、向排序链表中添加节点、从排序链表中删除节点、获取下一个超时时间等操作*/ #include "los_sortlink_pri.h" #include "los_memory.h" #include "los_exc.h" @@ -39,7 +39,7 @@ extern "C" { #define OS_INVALID_VALUE 0xFFFFFFFF #ifdef LOSCFG_BASE_CORE_USE_MULTI_LIST - +//OsSortLinkInit:初始化排序链表,为排序链表的头节点分配内存,并进行初始化 LITE_OS_SEC_TEXT_INIT UINT32 OsSortLinkInit(SortLinkAttribute *sortLinkHeader) { UINT32 size; @@ -60,7 +60,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsSortLinkInit(SortLinkAttribute *sortLinkHeader) } return LOS_OK; } - +//OsAdd2SortLink:将一个节点添加到排序链表中,根据节点的超时时间计算节点在排序链表中的位置,然后插入到相应位置 LITE_OS_SEC_TEXT VOID OsAdd2SortLink(const SortLinkAttribute *sortLinkHeader, SortLinkList *sortList) { SortLinkList *listSorted = NULL; @@ -106,7 +106,7 @@ LITE_OS_SEC_TEXT VOID OsAdd2SortLink(const SortLinkAttribute *sortLinkHeader, So LOS_ListTailInsert(&listSorted->sortLinkNode, &sortList->sortLinkNode); } } - +//OsCheckSortLink:检查排序链表是否合法,排除循环引用和无效节点 LITE_OS_SEC_TEXT STATIC VOID OsCheckSortLink(const LOS_DL_LIST *listHead, const LOS_DL_LIST *listNode) { LOS_DL_LIST *tmp = listNode->pstPrev; @@ -122,7 +122,7 @@ LITE_OS_SEC_TEXT STATIC VOID OsCheckSortLink(const LOS_DL_LIST *listHead, const /* delete invalid sortlink node */ OsBackTrace(); } - +//OsDeleteSortLink:从排序链表中删除一个节点,然后更新相邻节点的超时时间 LITE_OS_SEC_TEXT VOID OsDeleteSortLink(const SortLinkAttribute *sortLinkHeader, SortLinkList *sortList) { LOS_DL_LIST *listObject = NULL; @@ -141,7 +141,7 @@ LITE_OS_SEC_TEXT VOID OsDeleteSortLink(const SortLinkAttribute *sortLinkHeader, } LOS_ListDelete(&sortList->sortLinkNode); } - +//OsCalcExpierTime:根据当前的排序链表游标和节点的位置计算超时时间 LITE_OS_SEC_TEXT STATIC INLINE UINT32 OsCalcExpierTime(UINT32 rollNum, UINT32 sortIndex, UINT16 curSortIndex) { UINT32 expireTime; @@ -154,7 +154,7 @@ LITE_OS_SEC_TEXT STATIC INLINE UINT32 OsCalcExpierTime(UINT32 rollNum, UINT32 so expireTime = ((rollNum - 1) << OS_TSK_SORTLINK_LOGLEN) + sortIndex; return expireTime; } - +//OsSortLinkGetNextExpireTime:获取排序链表中下一个超时时间最小的节点的超时时间 LITE_OS_SEC_TEXT UINT32 OsSortLinkGetNextExpireTime(const SortLinkAttribute *sortLinkHeader) { UINT16 cursor; @@ -184,7 +184,7 @@ LITE_OS_SEC_TEXT UINT32 OsSortLinkGetNextExpireTime(const SortLinkAttribute *sor return expireTime; } - +//OsSortLinkUpdateExpireTime:更新排序链表中所有节点的超时时间,并更新游标 LITE_OS_SEC_TEXT VOID OsSortLinkUpdateExpireTime(UINT32 sleepTicks, SortLinkAttribute *sortLinkHeader) { SortLinkList *sortList = NULL; @@ -215,7 +215,7 @@ LITE_OS_SEC_TEXT VOID OsSortLinkUpdateExpireTime(UINT32 sleepTicks, SortLinkAttr } sortLinkHeader->cursor = (sortLinkHeader->cursor + sleepTicks - 1) % OS_TSK_SORTLINK_LEN; } - +//OsSortLinkGetTargetExpireTime:获取目标节点的超时时间 LITE_OS_SEC_TEXT_MINOR UINT32 OsSortLinkGetTargetExpireTime(const SortLinkAttribute *sortLinkHeader, const SortLinkList *targetSortList) { @@ -235,7 +235,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 OsSortLinkGetTargetExpireTime(const SortLinkAttrib } #else /* LOSCFG_BASE_CORE_USE_SINGLE_LIST */ - +//OsSortLinkInit:初始化排序链表头部 LITE_OS_SEC_TEXT_INIT UINT32 OsSortLinkInit(SortLinkAttribute *sortLinkHeader) { UINT32 size; @@ -252,7 +252,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsSortLinkInit(SortLinkAttribute *sortLinkHeader) LOS_ListInit(listObject); return LOS_OK; } - +//OsAdd2SortLink:向排序链表中添加元素 LITE_OS_SEC_TEXT VOID OsAdd2SortLink(const SortLinkAttribute *sortLinkHeader, SortLinkList *sortList) { SortLinkList *listSorted = NULL; @@ -286,7 +286,7 @@ LITE_OS_SEC_TEXT VOID OsAdd2SortLink(const SortLinkAttribute *sortLinkHeader, So LOS_ListTailInsert(&listSorted->sortLinkNode, &sortList->sortLinkNode); } } - +//OsCheckSortLink:检查排序链表的有效性,用于内部调用 LITE_OS_SEC_TEXT STATIC VOID OsCheckSortLink(const LOS_DL_LIST *listHead, const LOS_DL_LIST *listNode) { LOS_DL_LIST *tmp = listNode->pstPrev; @@ -302,7 +302,7 @@ LITE_OS_SEC_TEXT STATIC VOID OsCheckSortLink(const LOS_DL_LIST *listHead, const /* delete invalid sortlink node */ OsBackTrace(); } - +//OsDeleteSortLink:从排序链表中删除指定元素 LITE_OS_SEC_TEXT VOID OsDeleteSortLink(const SortLinkAttribute *sortLinkHeader, SortLinkList *sortList) { LOS_DL_LIST *listObject = NULL; @@ -319,7 +319,7 @@ LITE_OS_SEC_TEXT VOID OsDeleteSortLink(const SortLinkAttribute *sortLinkHeader, } LOS_ListDelete(&sortList->sortLinkNode); } - +//OsSortLinkGetNextExpireTime:获取排序链表中下一个到期的时间 LITE_OS_SEC_TEXT UINT32 OsSortLinkGetNextExpireTime(const SortLinkAttribute *sortLinkHeader) { UINT32 expireTime = OS_INVALID_VALUE; @@ -333,7 +333,7 @@ LITE_OS_SEC_TEXT UINT32 OsSortLinkGetNextExpireTime(const SortLinkAttribute *sor } return expireTime; } - +//OsSortLinkUpdateExpireTime:更新排序链表中到期时间 LITE_OS_SEC_TEXT VOID OsSortLinkUpdateExpireTime(UINT32 sleepTicks, SortLinkAttribute *sortLinkHeader) { SortLinkList *sortList = NULL; @@ -349,7 +349,7 @@ LITE_OS_SEC_TEXT VOID OsSortLinkUpdateExpireTime(UINT32 sleepTicks, SortLinkAttr ROLLNUM_SUB(sortList->idxRollNum, sleepTicks - 1); } } - +//OsSortLinkGetTargetExpireTime:获取指定排序链表元素的到期时间 LITE_OS_SEC_TEXT_MINOR UINT32 OsSortLinkGetTargetExpireTime(const SortLinkAttribute *sortLinkHeader, const SortLinkList *targetSortList) { diff --git a/src/kernel/base/los_stackinfo.c b/src/kernel/base/los_stackinfo.c index 9f90a6c..feb3da6 100644 --- a/src/kernel/base/los_stackinfo.c +++ b/src/kernel/base/los_stackinfo.c @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +//栈 #include "securec.h" #include "los_stackinfo_pri.h" #ifdef LOSCFG_SHELL @@ -35,7 +35,7 @@ const StackInfo *g_stackInfo = NULL; UINT32 g_stackNum; - +//OsStackWaterLineGet:获取栈的使用情况 UINT32 OsStackWaterLineGet(const UINTPTR *stackBottom, const UINTPTR *stackTop, UINT32 *peakUsed) { UINT32 size; @@ -53,20 +53,20 @@ UINT32 OsStackWaterLineGet(const UINTPTR *stackBottom, const UINTPTR *stackTop, return LOS_NOK; } } - +//OsExcStackInfoReg:注册异常栈信息 VOID OsExcStackInfoReg(const StackInfo *stackInfo, UINT32 stackNum) { g_stackInfo = stackInfo; g_stackNum = stackNum; } - +//OsStackInit:初始化任务栈 VOID OsStackInit(VOID *stacktop, UINT32 stacksize) { /* initialize the task stack, write magic num to stack top */ (VOID)memset_s(stacktop, stacksize, (INT32)OS_STACK_INIT, stacksize); *((UINTPTR *)stacktop) = OS_STACK_MAGIC_WORD; } - +//OsGetStackInfo:获取栈信息 VOID OsGetStackInfo(const StackInfo **stackInfo, UINT32 *stackNum) { *stackInfo = g_stackInfo; diff --git a/src/kernel/base/los_swtmr.c b/src/kernel/base/los_swtmr.c index 052e6ff..393f3d7 100644 --- a/src/kernel/base/los_swtmr.c +++ b/src/kernel/base/los_swtmr.c @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +/*软件定时器的实现,涉及软件定时器的创建、启动、停止、删除等操作*/ #include "los_swtmr_pri.h" #include "los_sortlink_pri.h" #include "los_queue_pri.h" @@ -52,6 +52,7 @@ LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_swtmrSpin); * Description: Start Software Timer * Input : swtmr --- Need to start software timer */ +//OsSwtmrStart:启动软件定时器 LITE_OS_SEC_TEXT VOID OsSwtmrStart(LosSwtmrCB *swtmr) { if ((swtmr->overrun == 0) && ((swtmr->mode == LOS_SWTMR_MODE_ONCE) || @@ -75,13 +76,14 @@ LITE_OS_SEC_TEXT VOID OsSwtmrStart(LosSwtmrCB *swtmr) * Description: Delete Software Timer * Input : swtmr --- Need to delete software timer, When using, Ensure that it can't be NULL. */ +//OsSwtmrDelete:删除软件定时器 STATIC INLINE VOID OsSwtmrDelete(LosSwtmrCB *swtmr) { /* insert to free list */ LOS_ListTailInsert(&g_swtmrFreeList, &swtmr->sortList.sortLinkNode); swtmr->state = OS_SWTMR_STATUS_UNUSED; } - +//OsSwtmrUpdate:更新软件定时器 STATIC INLINE VOID OsSwtmrUpdate(LosSwtmrCB *swtmr) { if (swtmr->mode == LOS_SWTMR_MODE_ONCE) { @@ -101,6 +103,7 @@ STATIC INLINE VOID OsSwtmrUpdate(LosSwtmrCB *swtmr) } #ifndef LOSCFG_BASE_CORE_SWTMR_IN_ISR +//OsSwtmrTask:软件定时器任务处理函数,用于处理定时器超时事件 LITE_OS_SEC_TEXT VOID OsSwtmrTask(VOID) { UINT32 ret, swtmrHandlerQueue; @@ -136,7 +139,7 @@ BOOL IsSwtmrTask(UINT32 taskId) return FALSE; } #endif - +//OsSwtmrTaskCreate:创建软件定时器任务 LITE_OS_SEC_TEXT_INIT UINT32 OsSwtmrTaskCreate(VOID) { UINT32 ret, swtmrTaskId; @@ -161,7 +164,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsSwtmrTaskCreate(VOID) return ret; } #endif - +//OsSwtmrInit:软件定时器初始化 LITE_OS_SEC_TEXT_INIT UINT32 OsSwtmrInit(VOID) { UINT32 size; @@ -209,6 +212,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsSwtmrInit(VOID) * Description: Tick interrupt interface module of software timer * Return : LOS_OK on success or error code on failure */ +//OsSwtmrScan:扫描软件定时器 LITE_OS_SEC_TEXT VOID OsSwtmrScan(VOID) { SortLinkList *sortList = NULL; @@ -277,6 +281,7 @@ LITE_OS_SEC_TEXT VOID OsSwtmrScan(VOID) * Description: Get next timeout * Return : Count of the Timer list */ +//OsSwtmrGetNextTimeout:获取下一个超时时间 LITE_OS_SEC_TEXT UINT32 OsSwtmrGetNextTimeout(VOID) { return OsSortLinkGetNextExpireTime(&OsPercpuGet()->swtmrSortLink); @@ -286,6 +291,7 @@ LITE_OS_SEC_TEXT UINT32 OsSwtmrGetNextTimeout(VOID) * Description: Stop of Software Timer interface * Input : swtmr --- the software timer control handler */ +//OsSwtmrStop:停止软件定时器 LITE_OS_SEC_TEXT STATIC VOID OsSwtmrStop(LosSwtmrCB *swtmr) { SortLinkAttribute *sortLinkHeader = NULL; @@ -309,6 +315,7 @@ LITE_OS_SEC_TEXT STATIC VOID OsSwtmrStop(LosSwtmrCB *swtmr) * Description: Get next software timer expiretime * Input : swtmr --- the software timer control handler */ +//获取指定软件定时器的剩余时间 LITE_OS_SEC_TEXT STATIC UINT32 OsSwtmrTimeGet(const LosSwtmrCB *swtmr) { SortLinkAttribute *sortLinkHeader = NULL; @@ -325,7 +332,7 @@ LITE_OS_SEC_TEXT STATIC UINT32 OsSwtmrTimeGet(const LosSwtmrCB *swtmr) return OsSortLinkGetTargetExpireTime(sortLinkHeader, &swtmr->sortList); } - +//创建一个软件定时器 LITE_OS_SEC_TEXT_INIT UINT32 LOS_SwtmrCreate(UINT32 interval, UINT8 mode, SWTMR_PROC_FUNC handler, @@ -377,7 +384,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_SwtmrCreate(UINT32 interval, return LOS_OK; } - +//启动一个软件定时器 LITE_OS_SEC_TEXT UINT32 LOS_SwtmrStart(UINT16 swtmrId) { LosSwtmrCB *swtmr = NULL; @@ -421,7 +428,7 @@ LITE_OS_SEC_TEXT UINT32 LOS_SwtmrStart(UINT16 swtmrId) LOS_TRACE(SWTMR_START, swtmr->timerId, swtmr->mode, swtmr->overrun, swtmr->interval, swtmr->expiry); return ret; } - +//停止一个软件定时器 LITE_OS_SEC_TEXT UINT32 LOS_SwtmrStop(UINT16 swtmrId) { LosSwtmrCB *swtmr = NULL; @@ -461,7 +468,7 @@ LITE_OS_SEC_TEXT UINT32 LOS_SwtmrStop(UINT16 swtmrId) LOS_TRACE(SWTMR_STOP, swtmr->timerId); return ret; } - +//获取一个软件定时器的剩余时间 LITE_OS_SEC_TEXT UINT32 LOS_SwtmrTimeGet(UINT16 swtmrId, UINT32 *tick) { LosSwtmrCB *swtmr = NULL; @@ -502,7 +509,7 @@ LITE_OS_SEC_TEXT UINT32 LOS_SwtmrTimeGet(UINT16 swtmrId, UINT32 *tick) SWTMR_UNLOCK(intSave); return ret; } - +//删除一个软件定时器 LITE_OS_SEC_TEXT UINT32 LOS_SwtmrDelete(UINT16 swtmrId) { LosSwtmrCB *swtmr = NULL; diff --git a/src/kernel/base/los_tick.c b/src/kernel/base/los_tick.c index c1d2db8..09c598b 100644 --- a/src/kernel/base/los_tick.c +++ b/src/kernel/base/los_tick.c @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +/*时钟模块:主要包括系统时钟的初始化、时钟中断处理函数、获取系统tick数等功能*/ #include "los_tick_pri.h" #include "los_swtmr_pri.h" #include "los_task_pri.h" @@ -52,6 +52,7 @@ STATIC WAKEUPFROMINTHOOK g_tickWakeupHook = NULL; /* * Description : Tick interruption handler */ +//OsTickHandler函数:时钟中断处理函数,用于处理时钟中断事件。 LITE_OS_SEC_TEXT VOID OsTickHandler(VOID) { UINT32 intSave; @@ -76,7 +77,7 @@ LITE_OS_SEC_TEXT VOID OsTickHandler(VOID) OsSwtmrScan(); #endif } - +//OsTickInit:初始化系统时钟 LITE_OS_SEC_TEXT_INIT UINT32 OsTickInit(UINT32 systemClock, UINT32 tickPerSecond) { if ((systemClock == 0) || @@ -88,12 +89,12 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsTickInit(UINT32 systemClock, UINT32 tickPerSecond return LOS_OK; } - +//启动系统时钟 LITE_OS_SEC_TEXT_INIT VOID OsTickStart(VOID) { HalClockStart(); } - +//LOS_TickCountGet函数:获取系统tick数 LITE_OS_SEC_TEXT_MINOR UINT64 LOS_TickCountGet(VOID) { UINT32 intSave; @@ -109,12 +110,12 @@ LITE_OS_SEC_TEXT_MINOR UINT64 LOS_TickCountGet(VOID) return tick; } - +//LOS_CyclePerTickGet函数:获取每个tick所对应的CPU周期数 LITE_OS_SEC_TEXT_MINOR UINT32 LOS_CyclePerTickGet(VOID) { return g_sysClock / KERNEL_TICK_PER_SECOND; } - +//LOS_GetCpuCycle函数:获取CPU周期数 LITE_OS_SEC_TEXT_MINOR VOID LOS_GetCpuCycle(UINT32 *highCnt, UINT32 *lowCnt) { UINT64 cycle; @@ -129,7 +130,7 @@ LITE_OS_SEC_TEXT_MINOR VOID LOS_GetCpuCycle(UINT32 *highCnt, UINT32 *lowCnt) /* get the low 32 bits */ *lowCnt = (UINT32)(cycle & 0xFFFFFFFFULL); } - +//LOS_CurrNanosec函数:获取当前的纳秒数 LITE_OS_SEC_TEXT_MINOR UINT64 LOS_CurrNanosec(VOID) { UINT64 nanos; @@ -137,7 +138,7 @@ LITE_OS_SEC_TEXT_MINOR UINT64 LOS_CurrNanosec(VOID) nanos = HalClockGetCycles() * (OS_SYS_NS_PER_SECOND / OS_SYS_NS_PER_MS) / (g_sysClock / OS_SYS_NS_PER_MS); return nanos; } - +//LOS_MS2Tick函数:将毫秒转换为tick数 LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MS2Tick(UINT32 millisec) { UINT64 delaySec; @@ -149,17 +150,17 @@ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MS2Tick(UINT32 millisec) delaySec = (UINT64)millisec * KERNEL_TICK_PER_SECOND; return (UINT32)((delaySec + OS_SYS_MS_PER_SECOND - 1) / OS_SYS_MS_PER_SECOND); } - +//LOS_Tick2MS函数:将tick数转换为毫秒数 LITE_OS_SEC_TEXT_MINOR UINT32 LOS_Tick2MS(UINT32 tick) { return (UINT32)(((UINT64)tick * OS_SYS_MS_PER_SECOND) / KERNEL_TICK_PER_SECOND); } - +//LOS_Udelay函数:微秒级延迟函数 LITE_OS_SEC_TEXT_MINOR VOID LOS_Udelay(UINT32 usecs) { HalDelayUs(usecs); } - +//LOS_Mdelay函数:毫秒级延迟函数 LITE_OS_SEC_TEXT_MINOR VOID LOS_Mdelay(UINT32 msecs) { UINT32 delayUs = (UINT32_MAX / OS_SYS_US_PER_MS) * OS_SYS_US_PER_MS; From 28d27255cd018076218505a95d4bd17aac5fa254 Mon Sep 17 00:00:00 2001 From: cailun <2505225681@qq.com> Date: Sun, 3 Dec 2023 23:59:27 +0800 Subject: [PATCH 10/26] src --- src/kernel/base/include/los_binarytree_pri.h | 2 +- src/kernel/base/include/los_err_pri.h | 2 +- src/kernel/base/include/los_event_pri.h | 2 +- src/kernel/base/include/los_exc_pri.h | 1 + src/kernel/base/include/los_memory_pri.h | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/kernel/base/include/los_binarytree_pri.h b/src/kernel/base/include/los_binarytree_pri.h index 8f4a675..7c10fdc 100644 --- a/src/kernel/base/include/los_binarytree_pri.h +++ b/src/kernel/base/include/los_binarytree_pri.h @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +//定义了与二叉树相关的结构体和函数,用于实现对数据的快速查找和插入。 #ifndef _LOS_BINARYTREE_PRI_H #define _LOS_BINARYTREE_PRI_H diff --git a/src/kernel/base/include/los_err_pri.h b/src/kernel/base/include/los_err_pri.h index 0c1553e..0755153 100644 --- a/src/kernel/base/include/los_err_pri.h +++ b/src/kernel/base/include/los_err_pri.h @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +//用于定义一些错误处理相关的宏和函数。 #ifndef _LOS_ERR_PRI_H #define _LOS_ERR_PRI_H diff --git a/src/kernel/base/include/los_event_pri.h b/src/kernel/base/include/los_event_pri.h index 7c58bfb..3ed390d 100644 --- a/src/kernel/base/include/los_event_pri.h +++ b/src/kernel/base/include/los_event_pri.h @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +//定义了一些与事件操作相关的私有函数和结构体。 #ifndef _LOS_EVENT_PRI_H #define _LOS_EVENT_PRI_H diff --git a/src/kernel/base/include/los_exc_pri.h b/src/kernel/base/include/los_exc_pri.h index 3bdde26..93d154f 100644 --- a/src/kernel/base/include/los_exc_pri.h +++ b/src/kernel/base/include/los_exc_pri.h @@ -25,6 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ +//定义了一些与异常处理相关的私有函数和宏 //防止同一个头文件被多次包含 #ifndef _LOS_EXC_PRI_H #define _LOS_EXC_PRI_H diff --git a/src/kernel/base/include/los_memory_pri.h b/src/kernel/base/include/los_memory_pri.h index 7214baa..642d88e 100644 --- a/src/kernel/base/include/los_memory_pri.h +++ b/src/kernel/base/include/los_memory_pri.h @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +//定义内存管理的私有接口和数据结构。 #ifndef _LOS_MEMORY_PRI_H #define _LOS_MEMORY_PRI_H From 3c2848c185895a745e3306abad672be530f4050f Mon Sep 17 00:00:00 2001 From: cailun <2505225681@qq.com> Date: Sun, 3 Dec 2023 23:59:52 +0800 Subject: [PATCH 11/26] doc --- doc/蔡伦_LiteOS阅读泛读报告.docx | Bin 0 -> 14958 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/蔡伦_LiteOS阅读泛读报告.docx b/doc/蔡伦_LiteOS阅读泛读报告.docx index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..589a7b5393bfd7ba1b3f7cd7e7625a1221bdebbc 100644 GIT binary patch literal 14958 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 S-%{4#0A25gY|`i7TK^B3O$d$v literal 0 HcmV?d00001 From aa43a7ec88db2f47c27eb2aa3d7e30285cd294bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=87=E8=B1=AA?= <2548632733@qq.com> Date: Mon, 4 Dec 2023 00:24:26 +0800 Subject: [PATCH 12/26] Code reading --- 文豪/cppsupport/los_cppsupport.c | 74 +++ 文豪/cpup/cpup_shellcmd.c | 134 ++++ 文豪/cpup/los_cpup.c | 593 ++++++++++++++++++ 文豪/los_cppsupport_pri.h | 53 ++ 文豪/los_cpup_pri.h | 74 +++ 文豪/los_trace_pri.h | 150 +++++ 文豪/trace/los_trace.c | 424 +++++++++++++ .../pipeline/serial/trace_pipeline_serial.c | 98 +++ .../pipeline/serial/trace_pipeline_serial.h | 50 ++ 文豪/trace/pipeline/trace_pipeline.c | 156 +++++ 文豪/trace/pipeline/trace_pipeline.h | 104 +++ 文豪/trace/pipeline/trace_tlv.c | 121 ++++ 文豪/trace/pipeline/trace_tlv.h | 95 +++ 文豪/trace/trace_offline.c | 264 ++++++++ 文豪/trace/trace_online.c | 117 ++++ 15 files changed, 2507 insertions(+) create mode 100644 文豪/cppsupport/los_cppsupport.c create mode 100644 文豪/cpup/cpup_shellcmd.c create mode 100644 文豪/cpup/los_cpup.c create mode 100644 文豪/los_cppsupport_pri.h create mode 100644 文豪/los_cpup_pri.h create mode 100644 文豪/los_trace_pri.h create mode 100644 文豪/trace/los_trace.c create mode 100644 文豪/trace/pipeline/serial/trace_pipeline_serial.c create mode 100644 文豪/trace/pipeline/serial/trace_pipeline_serial.h create mode 100644 文豪/trace/pipeline/trace_pipeline.c create mode 100644 文豪/trace/pipeline/trace_pipeline.h create mode 100644 文豪/trace/pipeline/trace_tlv.c create mode 100644 文豪/trace/pipeline/trace_tlv.h create mode 100644 文豪/trace/trace_offline.c create mode 100644 文豪/trace/trace_online.c diff --git a/文豪/cppsupport/los_cppsupport.c b/文豪/cppsupport/los_cppsupport.c new file mode 100644 index 0000000..e6239ab --- /dev/null +++ b/文豪/cppsupport/los_cppsupport.c @@ -0,0 +1,74 @@ +/* ---------------------------------------------------------------------------- + * Copyright (c) Huawei Technologies Co., Ltd. 2013-2019. All rights reserved. + * Description: LiteOS Cpp Support Implementation + * 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_cppsupport_pri.h" +#include "los_printf.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +typedef VOID (*InitFunc)(VOID); + +/*------------------------------------------- +*`LITE_OS_SEC_TEXT_MINOR``UINTPTR`ȡ +*`LOS_CppSystemInit`Уһʼ飬 +*εЩʼݴ`flag` +*ضλִгʼ +*--------------------------------------------*/ +LITE_OS_SEC_TEXT_MINOR INT32 LOS_CppSystemInit(UINTPTR initArrayStart, UINTPTR initArrayEnd, INT32 flag) +{ + UINTPTR fastEnd = (UINTPTR)&__fast_end; + UINTPTR *start = (UINTPTR *)initArrayStart; + InitFunc initFunc = NULL; + +#ifdef LOSCFG_AARCH64 + __register_frame(__EH_FRAME_BEGIN__); +#endif + + for (; start != (UINTPTR *)initArrayEnd; ++start) { + if ((flag == BEFORE_SCATTER) && ((UINTPTR)*start > fastEnd)) { + continue; + } else if ((flag == AFTER_SCATTER) && ((UINTPTR)*start <= fastEnd)) { + continue; + } + + initFunc = (InitFunc)(*start); + initFunc(); + } + + return 0; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ diff --git a/文豪/cpup/cpup_shellcmd.c b/文豪/cpup/cpup_shellcmd.c new file mode 100644 index 0000000..8e4160b --- /dev/null +++ b/文豪/cpup/cpup_shellcmd.c @@ -0,0 +1,134 @@ +/* ---------------------------------------------------------------------------- + * Copyright (c) Huawei Technologies Co., Ltd. 2013-2020. All rights reserved. + * Description: ShellCmd Cpup + * 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_config.h" +#ifdef LOSCFG_SHELL +#include "stdio.h" +#include "stdlib.h" +#include "los_cpup_pri.h" +#include "los_task_pri.h" +#include "shcmd.h" +#include "shell.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +VOID OsCmdCpupOperateOneParam(UINT32 mode) //ݲmodeȡϵͳCPUʹʵʷ// +{ + UINT32 ret; + + if (mode == CPUP_LAST_TEN_SECONDS) { //ȥ10s// + PRINTK("\nSysCpuUsage in 10s: "); + } else if (mode == CPUP_LAST_ONE_SECONDS) { //ȥ1s// + PRINTK("\nSysCpuUsage in 1s: "); + } else { //ʷƽCPUʹ// + PRINTK("\nSysCpuUsage in all time: "); + } + ret = LOS_HistorySysCpuUsage(mode); //ȡCPUʹʵֵ// + PRINTK("%u.%u", ret / LOS_CPUP_PRECISION_MULT, ret % LOS_CPUP_PRECISION_MULT); +} + +VOID OsCmdCpupOperateTwoParam(UINT32 mode, UINT32 taskId) //ݲmodeȡtaskIdָ// +{ //CPUʹʵʷ// + UINT32 ret; + + if (mode == CPUP_LAST_TEN_SECONDS) { //ȥ10s// + PRINTK("\nTaskId %u CpuUsage in 10s: ", taskId); + } else if (mode == CPUP_LAST_ONE_SECONDS) { //ȥ1s// + PRINTK("\nTaskId %u CpuUsage in 1s: ", taskId); + } else { //ʷƽCPUʹ// + PRINTK("\nTaskId %u CpuUsage in all time: ", taskId); + } + ret = LOS_HistoryTaskCpuUsage(taskId, mode); //ȡCPUʹʵֵ// + PRINTK("%u.%u", ret / LOS_CPUP_PRECISION_MULT, ret % LOS_CPUP_PRECISION_MULT); +} + +LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdCpup(INT32 argc, const CHAR **argv) //IJȡϵͳָCPUʹ// +{ + size_t mode, taskId; + CHAR *bufMode = NULL; + CHAR *bufId = NULL; + LosTaskCB *taskCB = NULL; + UINT32 ret; + + if (argc <= 0) { //ûвȡϵͳȥ10CPUʹʲӡ// + ret = LOS_HistorySysCpuUsage(CPUP_LAST_TEN_SECONDS); + PRINTK("\nSysCpuUsage in 10s: %u.%u", ret / LOS_CPUP_PRECISION_MULT, ret % LOS_CPUP_PRECISION_MULT); + return 0; + } + + mode = strtoul(argv[0], &bufMode, 0); //һתΪ޷modeʾCPUʹʵĻȡģʽ// +/*------------------------------------------------------------------*/ + //жmodeǷЧ// + if ((bufMode == NULL) || (*bufMode != 0)) { + PRINTK("\nThe input mode is invalid. Please try again.\n"); + return 0; + } + + if (mode > CPUP_ALL_TIME) { + mode = CPUP_ALL_TIME; + } +/*------------------------------------------------------------------*/ +//ֻһOsCmdCpupOperateOneParamȡϵͳCPUʹ// + if (argc == 1) { + OsCmdCpupOperateOneParam((UINT32)mode); + return 0; + } +/*------------------------------------------------------------------*/ +//жtaskIdǷЧ// + taskId = strtoul(argv[1], &bufId, 0); + if ((taskId >= g_taskMaxNum) || (*bufId != 0)) { + PRINTK("\nThe input taskId is invalid. Please try again.\n"); + return 0; + } + taskCB = OS_TCB_FROM_TID(taskId); + if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) { + PRINTK("\nThe task is unused. Please try again.\n"); + return 0; + } +/*-----------------------------------------------------------------*/ +//ڶΪIDȻOsCmdCpupOperateTwoParamȡָCPUʹ// + if (argc == 2) { + OsCmdCpupOperateTwoParam((UINT32)mode, (UINT32)taskId); + return 0; + } + + PRINTK("cpup [MODE] \ncpup [MODE] [TASKID] \n"); + return 0; +} +//ͨShellնcpupӦIJȡCPUʹʵʷ// +SHELLCMD_ENTRY(cpup_shellcmd, CMD_TYPE_EX, "cpup", XARGS, (CmdCallBackFunc)OsShellCmdCpup); +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ +#endif /* LOSCFG_SHELL */ diff --git a/文豪/cpup/los_cpup.c b/文豪/cpup/los_cpup.c new file mode 100644 index 0000000..688ff34 --- /dev/null +++ b/文豪/cpup/los_cpup.c @@ -0,0 +1,593 @@ +/* ---------------------------------------------------------------------------- + * Copyright (c) Huawei Technologies Co., Ltd. 2013-2020. All rights reserved. + * Description : LiteOS Cpu Usage Calculation Module Implementation + * 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_cpup_pri.h" +#include "los_task_pri.h" +#include "los_base.h" +#include "los_swtmr.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#ifdef LOSCFG_KERNEL_CPUP + +LITE_OS_SEC_BSS STATIC UINT16 g_cpupSwtmrId; //ڼ¼CPUʹͳƶʱID// +LITE_OS_SEC_BSS STATIC UINT16 g_cpupInitFlg = 0; //ڱCPUʹģǷѾʼ// +LITE_OS_SEC_BSS OsCpupCB *g_cpup = NULL; //ڱCPUʹصϢ// +LITE_OS_SEC_BSS STATIC UINT16 g_cpupMaxNum; //ʾCPUʹͳϢ// +LITE_OS_SEC_BSS STATIC UINT16 g_cpupTaskMaxNum; //ʾCPUʹͳϢ// +LITE_OS_SEC_BSS STATIC UINT16 g_hisPos = 0; /* current Sampling point of historyTime */ +LITE_OS_SEC_DATA_INIT STATIC UINT32 runningTasks[LOSCFG_KERNEL_CORE_NUM] = { + [0 ... (LOSCFG_KERNEL_CORE_NUM - 1)] = (UINT32)-1 +}; //ڼ¼ÿеID// +LITE_OS_SEC_BSS STATIC UINT64 cpuHistoryTime[OS_CPUP_HISTORY_RECORD_NUM + 1]; + //ڱCPUʷʱ¼// +LITE_OS_SEC_BSS STATIC UINT64 g_startCycles = 0; //ڼ¼лǰʱ// +#ifdef LOSCFG_CPUP_INCLUDE_IRQ //жǷжصĹ// +//// +LITE_OS_SEC_BSS UINT64 g_timeInIrqPerTskSwitch[LOSCFG_KERNEL_CORE_NUM]; //ڼ¼ÿлڼ䷢жϵʱ// +LITE_OS_SEC_BSS STATIC UINT64 g_intTimeStart[LOSCFG_KERNEL_CORE_NUM]; //ڼ¼ÿжϿʼʱ// +#endif + +#define HIGH_BITS 32 + +#define CPUP_PRE_POS(pos) (((pos) == 0) ? (OS_CPUP_HISTORY_RECORD_NUM - 1) : ((pos) - 1)) +#define CPUP_POST_POS(pos) (((pos) == (OS_CPUP_HISTORY_RECORD_NUM - 1)) ? 0 : ((pos) + 1)) + +LITE_OS_SEC_TEXT_INIT OsCpupCB *OsCpupCBGet(UINT32 index) +{ + return &g_cpup[index]; +} + +/*ڸʷʱʷʱ䣬ԱCPUʹ*/ +LITE_OS_SEC_TEXT_INIT VOID OsCpupGuard(VOID) +{ + UINT16 prevPos = g_hisPos; + UINT16 loop; + UINT16 runTaskId; + UINT64 curCycle; + UINT32 intSave; + + if (g_cpupInitFlg == 0) { //ʾCPUʹģδʼֱӷ// + return; + } + //ѳʼֹжϣȡǰʱ// + intSave = LOS_IntLock(); + curCycle = OsCpupGetCycle(); + + g_hisPos = CPUP_POST_POS(g_hisPos); //ʷʱλ// + cpuHistoryTime[prevPos] = curCycle; //¼βʱ// + +/*ÿCPUĵʷʱ*/ + for (loop = 0; loop < g_cpupMaxNum; loop++) { + g_cpup[loop].historyTime[prevPos] = g_cpup[loop].allTime; + } + + for (loop = 0; loop < LOSCFG_KERNEL_CORE_NUM; loop++) { + runTaskId = runningTasks[loop]; //ȡڵǰϵID// + /* reacquire the cycle to prevent flip */ + curCycle = OsCpupGetCycle(); + /*ӿʼǰʱõʱʷʱϵʷʱ*/ + g_cpup[runTaskId].historyTime[prevPos] += curCycle - g_cpup[runTaskId].startTime; +#ifdef LOSCFG_CPUP_INCLUDE_IRQ //жжϹǷ񱻰// + /*Ӹʷʱмȥлڼ䷢жõʱ*/ + g_cpup[runTaskId].historyTime[prevPos] -= g_timeInIrqPerTskSwitch[loop]; +#endif + } + + LOS_IntRestore(intSave); //ָж״̬// +} + +/*һʱԱ㶨ڸʷʱʷʱ䣬ӶʵCPUʹʵͳ*/ +LITE_OS_SEC_TEXT_INIT VOID OsCpupGuardCreator(VOID) +{ + /*溯IJֱΪ*/ + //趨ʱÿӵĻʱӵδ// + //ģʽΪģʽ// + //ص// + //ʱIDg_cpupSwtmrId// + //һΪ0ʾЯ// + (VOID)LOS_SwtmrCreate(LOSCFG_BASE_CORE_TICK_PER_SECOND, LOS_SWTMR_MODE_PERIOD, + (SWTMR_PROC_FUNC)OsCpupGuard, &g_cpupSwtmrId, 0); + + (VOID)LOS_SwtmrStart(g_cpupSwtmrId); //ʱ// +} + +/*ʼCPUʹͳģ飬аһȼ +ںΪOsCpupGuardCreator +ڴԵOsCpupGuard()ʱ*/ +LITE_OS_SEC_TEXT_INIT VOID OsCpupGuardInit(VOID) +{ + TSK_INIT_PARAM_S taskInitParam; + UINT32 tempId; + //ʼtaskInitParam// + (VOID)memset_s((void *)(&taskInitParam), sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S)); + taskInitParam.pfnTaskEntry = (TSK_ENTRY_FUNC)OsCpupGuardCreator; //ָںΪOsCpupGuardCreatorʱĺ// + taskInitParam.uwStackSize = LOS_TASK_MIN_STACK_SIZE; //ָջĴСΪСջС// + taskInitParam.pcName = "CpupGuardCreator"; //ָΪ"CpupGuardCreator"// + taskInitParam.usTaskPrio = OS_TASK_PRIORITY_HIGHEST; //ָȼΪȼ// + taskInitParam.uwResved = LOS_TASK_STATUS_DETACHED; //ָ״̬ΪLOS_TASK_STATUS_DETACHED// +#ifdef LOSCFG_KERNEL_SMP //жϲϵͳǷֶ֧// + taskInitParam.usCpuAffiMask = CPUID_TO_AFFI_MASK(ArchCurrCpuid()); //CPU׺// +#endif + /*ʼõIJtaskInitParamIDtempId*/ + (VOID)LOS_TaskCreate(&tempId, &taskInitParam); +} + +/* + * Description: initialization of CPUP + * Return : LOS_OK or Error Information + */ +LITE_OS_SEC_TEXT_INIT UINT32 OsCpupInit(VOID) +{ + UINT32 size; + + g_cpupTaskMaxNum = g_taskMaxNum; + g_cpupMaxNum = g_cpupTaskMaxNum; +/*˰жϵCPUʹͳƣLOSCFG_CPUP_INCLUDE_IRQ +g_cpupMaxNumLOSCFG_PLATFORM_HWI_LIMIT*/ +#ifdef LOSCFG_CPUP_INCLUDE_IRQ + g_cpupMaxNum += LOSCFG_PLATFORM_HWI_LIMIT; +#endif + + /* every task has only one record, and it won't operated at the same time */ + size = g_cpupMaxNum * sizeof(OsCpupCB); //ҪڴռС// + g_cpup = (OsCpupCB *)LOS_MemAlloc(m_aucSysMem0, size); //ڴ棬ڴ洢OsCpupCBṹ// + if (g_cpup == NULL) { //ڴʧ// + return LOS_ERRNO_CPUP_NO_MEMORY; + } + + OsCpupGuardInit(); //ʼCPUʹͳģ// + + (VOID)memset_s(g_cpup, size, 0, size); //ڴռ// + g_cpupInitFlg = 1; //ʾCPUʹͳģѾʼ// + + return LOS_OK; //ʼɹ// +} + +LITE_OS_SEC_TEXT_INIT VOID LOS_CpupReset(VOID) //CPUʹͳģ// +{ + UINT32 cpupIndex; + UINT32 maxNum = g_cpupMaxNum; + UINT64 curCycle; + UINT16 loop; + UINT32 intSave; + + /*ȫֱg_cpupǷΪNULLǣֱӷأִκβ*/ + if (g_cpup == NULL) { + return; + } + + g_cpupInitFlg = 0; //ʾCPUʹͳģδʼ// + intSave = LOS_IntLock(); //жϣֹùзж// + (VOID)LOS_SwtmrStop(g_cpupSwtmrId); //ֹͣCPUʹͳƶʱ// + curCycle = OsCpupGetCycle(); //ȡǰCPU// + + /*cpuHistoryTimeеԪضΪcurCycleʷʱ¼*/ + for (loop = 0; loop < (OS_CPUP_HISTORY_RECORD_NUM + 1); loop++) { + cpuHistoryTime[loop] = curCycle; + } + + /*ÿCPUʹͳƽṹ壬 + ʼʱʱ䶼ΪcurCycle + ͬʱÿṹеʷʱ¼*/ + for (cpupIndex = 0; cpupIndex < maxNum; cpupIndex++) { + g_cpup[cpupIndex].startTime = curCycle; + g_cpup[cpupIndex].allTime = curCycle; + for (loop = 0; loop < (OS_CPUP_HISTORY_RECORD_NUM + 1); loop++) { + g_cpup[cpupIndex].historyTime[loop] = curCycle; + } + } + +/*˰жϵCPUʹͳƣ +g_timeInIrqPerTskSwitchеԪضΪ0 +ڼ¼лڼжʱ*/ +#ifdef LOSCFG_CPUP_INCLUDE_IRQ + for (loop = 0; loop < LOSCFG_KERNEL_CORE_NUM; loop++) { + g_timeInIrqPerTskSwitch[loop] = 0; + } +#endif + + (VOID)LOS_SwtmrStart(g_cpupSwtmrId); //CPUʹͳƶʱ// + LOS_IntRestore(intSave); //ָж״̬// + g_cpupInitFlg = 1; //ʾCPUʹͳģѾ³ʼ// + + return; +} + +/*CPUʼֵԱ¼ʱʱ +ܹȷCPUIJֵӶõʱ*/ +LITE_OS_SEC_TEXT_MINOR VOID OsCpupSetCycle(UINT64 startCycles) +{ + g_startCycles = startCycles; + return; +} + +/* + * Description: get current cycles count + * Return : current cycles count + */ +LITE_OS_SEC_TEXT_MINOR UINT64 OsCpupGetCycle(VOID) +{ + UINT32 high; + UINT32 low; + UINT64 cycles; + + LOS_GetCpuCycle(&high, &low); + cycles = ((UINT64)high << HIGH_BITS) + low; //λ͵λļֵϲһ64λֵ// + if (g_startCycles == 0) { + g_startCycles = cycles; + } + + /* + * The cycles should keep growing, if the checking failed, + * it mean LOS_GetCpuCycle has the problem which should be fixed. + */ + LOS_ASSERT(cycles >= g_startCycles); + + return (cycles - g_startCycles); +} + +/* + * Description: start task to get cycles count in current task beginning + */ +LITE_OS_SEC_TEXT_MINOR VOID OsTaskCycleStart(VOID) //ʼʱȡCPUڼ// +{ + UINT32 taskId; + LosTaskCB *runTask = NULL; + + if (g_cpupInitFlg == 0) { //Ϊ0ʾδCPUڼijʼֱӷ// + return; + } + + runTask = OsCurrTaskGet(); //ȡǰе// + taskId = runTask->taskId; //ȡǰID// + + g_cpup[taskId].id = taskId; + g_cpup[taskId].startTime = OsCpupGetCycle(); + + return; +} + +/* + * Description: quit task and get cycle count + */ +LITE_OS_SEC_TEXT_MINOR VOID OsTaskCycleEnd(VOID) +{ + UINT32 taskId; + UINT64 cpuCycle; + LosTaskCB *runTask = NULL; + + if (g_cpupInitFlg == 0) { + return; + } + + runTask = OsCurrTaskGet(); + taskId = runTask->taskId; + + if (g_cpup[taskId].startTime == 0) { //жǷѾ¼Ŀʼʱ䣬// + return; //Ϊ0ʾδ¼ʼʱ䣬ֱӷ// + } + + cpuCycle = OsCpupGetCycle(); + g_cpup[taskId].allTime += cpuCycle - g_cpup[taskId].startTime; //ȡӿʼCPU// + +#ifdef LOSCFG_CPUP_INCLUDE_IRQ //˰жϴʱͳƣҪʱ// + UINT32 cpuId = ArchCurrCpuid(); + g_cpup[taskId].allTime -= g_timeInIrqPerTskSwitch[cpuId]; //ȥǰCPUжϴռõʱ + g_timeInIrqPerTskSwitch[cpuId] = 0; +#endif + g_cpup[taskId].startTime = 0; //ʾʱͳƽ// + + return; +} + +/* + * Description: start task to get cycles count in current task ending + */ +LITE_OS_SEC_TEXT_MINOR VOID OsTaskCycleEndStart(const LosTaskCB *newTask) +{ + UINT64 cpuCycle; + LosTaskCB *runTask = NULL; + OsCpupCB *cpup = NULL; + UINT32 cpuId = ArchCurrCpuid(); + + if ((g_cpupInitFlg == 0) || (newTask == NULL)) { + return; + } + + runTask = OsCurrTaskGet(); + cpuCycle = OsCpupGetCycle(); + + cpup = &g_cpup[runTask->taskId]; + if (cpup->startTime != 0) { + cpup->allTime += cpuCycle - cpup->startTime; //ʾ֮ǰѾʼCPUڼҪʱи// +#ifdef LOSCFG_CPUP_INCLUDE_IRQ //Ƿãʱ// + cpup->allTime -= g_timeInIrqPerTskSwitch[cpuId]; + g_timeInIrqPerTskSwitch[cpuId] = 0; +#endif + } + + cpup = &g_cpup[newTask->taskId]; + /*ID͵ǰCPUڼֵ棬ʾCPUڼʼ*/ + cpup->id = newTask->taskId; + cpup->startTime = cpuCycle; + runningTasks[cpuId] = newTask->taskId; //µǰCPUеID// + + return; +} + +/*ڻȡCPUڼеλ*/ +LITE_OS_SEC_TEXT_MINOR STATIC VOID OsCpupGetPos(UINT32 mode, UINT16 *curPosPointer, UINT16 *prePosPointer) +{ + UINT16 curPos; + UINT16 tmpPos; + UINT16 prePos; + + tmpPos = g_hisPos; //ȡǰλ// + curPos = CPUP_PRE_POS(tmpPos); //ȡǰһλ// + + /* + * The current position has nothing to do with the CPUP modes, + * however, the previous position differs. + */ + switch (mode) { + /*ʾҪȡһڵCPUڼݣ + ʱǰһλΪǰλõǰһλ*/ + case CPUP_LAST_ONE_SECONDS: + prePos = CPUP_PRE_POS(curPos); + break; + /*ʾҪȡʮڵCPUڼݣ + ʱǰһλΪǰλ*/ + case CPUP_LAST_TEN_SECONDS: + prePos = tmpPos; + break; + /*ʾҪȡʱڵCPUڼݣ + ʱǰһλΪһλ*/ + case CPUP_ALL_TIME: + /* fall-through */ + default: + prePos = OS_CPUP_HISTORY_RECORD_NUM; + break; + } + + *curPosPointer = curPos; //浱ǰλ// + *prePosPointer = prePos; //ǰһλ// + + return; +} + +/*ڼCPUʹͳƲĺϷ*/ +LITE_OS_SEC_TEXT_MINOR STATIC INLINE UINT32 OsCpuUsageParaCheck(UINT32 taskId) +{ + if (g_cpupInitFlg == 0) { + return LOS_ERRNO_CPUP_NO_INIT; + } + + if (OS_TSK_GET_INDEX(taskId) >= g_taskMaxNum) { //IDֵ// + return LOS_ERRNO_CPUP_TSK_ID_INVALID; //ʾIDЧش// + } + + /* weather the task is created */ + if (g_cpup[taskId].id != taskId) { + return LOS_ERRNO_CPUP_THREAD_NO_CREATED; //ʾδش// + } + + if ((g_cpup[taskId].status & OS_TASK_STATUS_UNUSED) || (g_cpup[taskId].status == 0)) { + return LOS_ERRNO_CPUP_THREAD_NO_CREATED; //ʾδش// + } + + return LOS_OK; //ʾͨ// +} + +LITE_OS_SEC_TEXT_MINOR UINT32 LOS_HistorySysCpuUsage(UINT32 mode) //ڻȡʷϵͳCPUʹ// +{ + UINT64 cpuCycleAll; + UINT64 idleCycleAll = 0; + UINT32 cpup = 0; + UINT16 pos; + UINT16 prePos; + UINT32 intSave; + UINT32 idleTaskId; +#ifdef LOSCFG_KERNEL_SMP + UINT32 cpuId = 0; +#endif + + if (g_cpupInitFlg == 0) { + return LOS_ERRNO_CPUP_NO_INIT; + } + + /* get end time of current task */ + intSave = LOS_IntLock(); //ж״̬// + OsTaskCycleEnd(); //ȡǰĽʱ// + + OsCpupGetPos(mode, &pos, &prePos); //ȡʷCPUʹݵλϢ// + cpuCycleAll = cpuHistoryTime[pos] - cpuHistoryTime[prePos]; //CPU// + +#ifdef LOSCFG_KERNEL_SMP //жǷΪSMPϵͳ// + /* For SMP system, each idle task needs to be accounted */ + while (cpuId < LOSCFG_KERNEL_CORE_NUM) { + idleTaskId = g_percpu[cpuId].idleTaskId; + //ۼӸĵĿidleCycleAll// + idleCycleAll += g_cpup[idleTaskId].historyTime[pos] - g_cpup[idleTaskId].historyTime[prePos]; + cpuId++; + } + cpuCycleAll *= LOSCFG_KERNEL_CORE_NUM; +#else + idleTaskId = OsGetIdleTaskId(); //ֱӻȡ// + idleCycleAll = g_cpup[idleTaskId].historyTime[pos] - g_cpup[idleTaskId].historyTime[prePos]; +#endif + + if (cpuCycleAll) { + cpup = (LOS_CPUP_PRECISION - (UINT32)((LOS_CPUP_PRECISION * idleCycleAll) / cpuCycleAll)); + } //óCPUʹ// + + OsTaskCycleStart(); //¿ʼʱͳ// + LOS_IntRestore(intSave); //ָж״̬// + + return cpup; +} + +LITE_OS_SEC_TEXT_MINOR UINT32 LOS_HistoryTaskCpuUsage(UINT32 taskId, UINT32 mode) +{ + UINT64 cpuCycleAll; + UINT64 cpuCycleCurTask; + UINT16 pos; + UINT16 prePos; + UINT32 intSave; + UINT32 cpup = 0; + UINT32 ret; + + if (g_cpupInitFlg == 0) { + return LOS_ERRNO_CPUP_NO_INIT; + } + + //ԴIDв飬LOS_OK򷵻ӦĴ// + ret = OsCpuUsageParaCheck(taskId); + if (ret != LOS_OK) { + return ret; + } + OsCpupCB *taskCpup = &g_cpup[taskId]; + + intSave = LOS_IntLock(); + OsTaskCycleEnd(); + + OsCpupGetPos(mode, &pos, &prePos); //ȡʷCPUʹݵλϢ// + cpuCycleAll = cpuHistoryTime[pos] - cpuHistoryTime[prePos]; //CPU// + cpuCycleCurTask = taskCpup->historyTime[pos] - taskCpup->historyTime[prePos]; //㵱ǰCPU// + if (cpuCycleAll) { + cpup = (UINT32)((LOS_CPUP_PRECISION * cpuCycleCurTask) / cpuCycleAll); + } //óCPUʹ// + + OsTaskCycleStart(); + LOS_IntRestore(intSave); + + return cpup; +} + +//ڻȡʷCPUʹ// +LITE_OS_SEC_TEXT_MINOR UINT32 LOS_AllCpuUsage(UINT16 maxNum, CPUP_INFO_S *cpupInfo, UINT32 mode, UINT16 flag) +{ + UINT16 loop; + UINT16 pos; + UINT16 prePos; + UINT32 intSave; + UINT64 cpuCycleAll; + UINT64 cpuCycleCurTask; + UINT16 numTmpMax = maxNum; + UINT16 numTmpMin = 0; + UINT16 numMax = g_cpupTaskMaxNum; + + if (g_cpupInitFlg == 0) { + return LOS_ERRNO_CPUP_NO_INIT; + } + + if (cpupInfo == NULL) { //鴫ָcpupInfoǷΪգΪգش// + return LOS_ERRNO_CPUP_TASK_PTR_NULL; + } + + if (maxNum == 0) { //鴫maxNumǷ00ش// + return LOS_ERRNO_CPUP_MAXNUM_INVALID; + } + +#ifdef LOSCFG_CPUP_INCLUDE_IRQ //걻// + if (flag == 0) { + numTmpMax += g_cpupTaskMaxNum; + numTmpMin += g_cpupTaskMaxNum; + numMax = g_cpupMaxNum; + } +#endif + + if (numTmpMax > numMax) { + numTmpMax = numMax; + } + + intSave = LOS_IntLock(); + OsTaskCycleEnd(); + + OsCpupGetPos(mode, &pos, &prePos); //ȡʷCPUʹݵλϢ// + cpuCycleAll = cpuHistoryTime[pos] - cpuHistoryTime[prePos]; //CPU// + + /*ͨѭCPUʹݣ㵱ǰCPU*/ + for (loop = numTmpMin; loop < numTmpMax; loop++) { + if ((g_cpup[loop].status & OS_TASK_STATUS_UNUSED) || (g_cpup[loop].status == 0)) { + continue; + } + + cpuCycleCurTask = g_cpup[loop].historyTime[pos] - g_cpup[loop].historyTime[prePos]; + cpupInfo[loop - numTmpMin].usStatus = g_cpup[loop].status; + + if (cpuCycleAll) { + cpupInfo[loop - numTmpMin].uwUsage = (UINT32)((LOS_CPUP_PRECISION * cpuCycleCurTask) / cpuCycleAll); + } + } + + OsTaskCycleStart(); + LOS_IntRestore(intSave); + + return LOS_OK; +} + +#ifdef LOSCFG_CPUP_INCLUDE_IRQ +/*жϿʼʱ¼ǰʱԱںжϴʱͳƺͷ*/ +LITE_OS_SEC_TEXT_MINOR VOID OsCpupIrqStart(VOID) +{ + g_intTimeStart[ArchCurrCpuid()] = OsCpupGetCycle(); + return; +} + +/*жϽʱͳƲ +¼жϺšжڼлʱԼۼжڼʱ*/ +LITE_OS_SEC_TEXT_MINOR VOID OsCpupIrqEnd(UINT32 intNum) +{ + UINT64 intTimeEnd = OsCpupGetCycle(); //ȡǰʱ// + UINT32 cpuId = ArchCurrCpuid(); //ȡǰCPUID// + + if (g_cpupInitFlg == 0) { + return; + } + + g_cpup[g_taskMaxNum + intNum].id = intNum; + g_cpup[g_taskMaxNum + intNum].status = OS_TASK_STATUS_RUNNING; //ж״̬Ϊ// + g_timeInIrqPerTskSwitch[cpuId] += (intTimeEnd - g_intTimeStart[cpuId]); //жڼлĵʱ// + g_cpup[g_taskMaxNum + intNum].allTime += (intTimeEnd - g_intTimeStart[cpuId]); + + return; +} +#endif + +#endif /* LOSCFG_KERNEL_CPUP */ +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + diff --git a/文豪/los_cppsupport_pri.h b/文豪/los_cppsupport_pri.h new file mode 100644 index 0000000..5e3fcb9 --- /dev/null +++ b/文豪/los_cppsupport_pri.h @@ -0,0 +1,53 @@ +/* ---------------------------------------------------------------------------- + * Copyright (c) Huawei Technologies Co., Ltd. 2013-2019. All rights reserved. + * Description: Cpp Support HeadFile + * 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. + * --------------------------------------------------------------------------- */ + +#ifndef _LOS_CPPSUPPORT_PRI_H +#define _LOS_CPPSUPPORT_PRI_H //ֹΰͬһͷļ// + +#include "los_cppsupport.h" + +#ifdef __cplusplus //ݱǷΪC++// +#if __cplusplus //ʹáextern 'C'// +extern "C" { //´ݽ// +#endif /* __cplusplus */ //ȷ// +#endif /* __cplusplus */ + +extern CHAR __fast_end; //һ_fast_endCHARͱ// + +#ifdef LOSCFG_AARCH64 //// +extern UINT8 __EH_FRAME_BEGIN__[]; //һUINT8͵// +VOID __register_frame(VOID *begin); +#endif + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ //رextern'C'// +#endif /* __cplusplus */ + +#endif /* _LOS_CPPSUPPORT_PRI_H */ diff --git a/文豪/los_cpup_pri.h b/文豪/los_cpup_pri.h new file mode 100644 index 0000000..f8da73e --- /dev/null +++ b/文豪/los_cpup_pri.h @@ -0,0 +1,74 @@ +/* ---------------------------------------------------------------------------- + * Copyright (c) Huawei Technologies Co., Ltd. 2013-2020. All rights reserved. + * Description: Cpup HeadFile + * 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. + * --------------------------------------------------------------------------- */ + +#ifndef _LOS_CPUP_PRI_H +#define _LOS_CPUP_PRI_H //ֹΰͬһͷļ// + +#include "los_cpup.h" //ܰһЩCPUʹ// +#include "los_task_pri.h" //ͳصĹͶ// + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#define OS_CPUP_HISTORY_RECORD_NUM 11 //ʷ¼Ϊ11// +#define LOS_CPUP_PRECISION 1000 //CPUʹʵľΪ1000// +#define LOS_CPUP_PRECISION_MULT (LOS_CPUP_PRECISION / 100) //ڼCPUʹ// + +typedef struct { + UINT32 id; /* Task ID */ + UINT16 status; /* Task status */ + UINT64 allTime; /* Total running time */ + UINT64 startTime; /* Time before a task is invoked */ + UINT64 historyTime[OS_CPUP_HISTORY_RECORD_NUM + 1]; /* Historical running time, the last one saves zero */ +} OsCpupCB; + +extern OsCpupCB *OsCpupCBGet(UINT32 index); //ȡ `OsCpupCB` ṹָ// +extern UINT32 OsCpupInit(VOID); //CPUʹͳģijʼ// +extern VOID OsCpupSetCycle(UINT64 startCycles); //CPUڼ// +extern UINT64 OsCpupGetCycle(VOID); //ȡCPUڼ// +extern VOID OsTaskCycleStart(VOID); //ڵʼ// +extern VOID OsTaskCycleEnd(VOID); //ڵĽ// +extern VOID OsTaskCycleEndStart(const LosTaskCB *newTask); //ڣʼµ// +#ifdef LOSCFG_CPUP_INCLUDE_IRQ +VOID OsCpupIrqStart(VOID); //ǰһ£ڴ// +VOID OsCpupIrqEnd(UINT32); //жϵCPUʹͳƺ// +#endif + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif /* _LOS_CPUP_PRI_H */ + +/*δ붨һЩCPUʹͳƵݽṹͺ +ڲϵͳʵֶжϵCPUʽмغͳơ*/ \ No newline at end of file diff --git a/文豪/los_trace_pri.h b/文豪/los_trace_pri.h new file mode 100644 index 0000000..762fd9f --- /dev/null +++ b/文豪/los_trace_pri.h @@ -0,0 +1,150 @@ +/* ---------------------------------------------------------------------------- + * Copyright (c) Huawei Technologies Co., Ltd. 2019-2020. All rights reserved. + * Description: LiteOS Trace Module Private HeadFile + * Author: Huawei LiteOS Team + * Create: 2019-08-30 + * 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. + * --------------------------------------------------------------------------- */ + +#ifndef _LOS_TRACE_PRI_H +#define _LOS_TRACE_PRI_H + +#include "los_trace.h" +#include "los_task_pri.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#ifdef LOSCFG_TRACE_CONTROL_AGENT +#define TRACE_CMD_END_CHAR 0xD +#endif + +#define TRACE_ERROR PRINT_ERR +#define TRACE_MODE_OFFLINE 0 +#define TRACE_MODE_ONLINE 1 + +/* just task and hwi were traced */ +#define TRACE_DEFAULT_MASK (TRACE_HWI_FLAG | TRACE_TASK_FLAG) +#define TRACE_CTL_MAGIC_NUM 0xDEADBEEF +#define TRACE_BIGLITTLE_WORD 0x12345678 +#define TRACE_VERSION(MODE) (0xFFFFFFFF & (MODE)) +#define TRACE_MASK_COMBINE(c1, c2, c3, c4) (((c1) << 24) | ((c2) << 16) | ((c3) << 8) | (c4)) + +#define TRACE_GET_MODE_FLAG(type) ((type) & 0xFFFFFFF0) + +extern SPIN_LOCK_S g_traceSpin; +#define TRACE_LOCK(state) LOS_SpinLockSave(&g_traceSpin, &(state)) +#define TRACE_UNLOCK(state) LOS_SpinUnlockRestore(&g_traceSpin, (state)) + +typedef VOID (*TRACE_DUMP_HOOK)(BOOL toClient); +extern TRACE_DUMP_HOOK g_traceDumpHook; + +enum TraceCmd { + TRACE_CMD_START = 1, + TRACE_CMD_STOP, + TRACE_CMD_SET_EVENT_MASK, + TRACE_CMD_RECODE_DUMP, + TRACE_CMD_MAX_CODE, +}; + +/** + * @ingroup los_trace + * struct to store the trace cmd from traceClient. + */ +typedef struct { + UINT8 cmd; + UINT8 param1; + UINT8 param2; + UINT8 param3; + UINT8 param4; + UINT8 param5; + UINT8 end; +} TraceClientCmd; + +/** + * @ingroup los_trace + * struct to store the event infomation + */ +typedef struct { + UINT32 cmd; /* trace start or stop cmd */ + UINT32 param; /* magic numb stand for notify msg */ +} TraceNotifyFrame; + +/** + * @ingroup los_trace + * struct to store the trace config information. + */ +typedef struct { + struct WriteCtrl { + UINT16 curIndex; /* The current record index */ + UINT16 maxRecordCount; /* The max num of track items */ + UINT16 curObjIndex; /* The current obj index */ + UINT16 maxObjCount; /* The max num of obj index */ + ObjData *objBuf; /* Pointer to obj info data */ + TraceEventFrame *frameBuf; /* Pointer to the track items */ + } ctrl; + OfflineHead *head; +} TraceOfflineHeaderInfo; + +extern UINT32 OsTraceGetMaskTid(UINT32 taskId); +extern VOID OsTraceSetObj(ObjData *obj, const LosTaskCB *tcb); +extern VOID OsTraceWriteOrSendEvent(const TraceEventFrame *frame); +extern UINT32 OsTraceBufInit(VOID *buf, UINT32 size); +extern VOID OsTraceObjAdd(UINT32 eventType, UINT32 taskId); +extern BOOL OsTraceIsEnable(VOID); +extern OfflineHead *OsTraceRecordGet(VOID); + +#ifdef LOSCFG_RECORDER_MODE_ONLINE +extern VOID OsTraceSendHead(VOID); +extern VOID OsTraceSendObjTable(VOID); +extern VOID OsTraceSendNotify(UINT32 type, UINT32 value); + +#define OsTraceNotifyStart() do { \ + OsTraceSendNotify(SYS_START, TRACE_CTL_MAGIC_NUM); \ + OsTraceSendHead(); \ + OsTraceSendObjTable(); \ + } while (0) + +#define OsTraceNotifyStop() do { \ + OsTraceSendNotify(SYS_STOP, TRACE_CTL_MAGIC_NUM); \ + } while (0) + +#define OsTraceReset() +#define OsTraceRecordDump(toClient) +#else +extern VOID OsTraceReset(VOID); +extern VOID OsTraceRecordDump(BOOL toClient); +#define OsTraceNotifyStart() +#define OsTraceNotifyStop() +#endif + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif /* _LOS_TRACE_PRI_H */ diff --git a/文豪/trace/los_trace.c b/文豪/trace/los_trace.c new file mode 100644 index 0000000..1f19ec2 --- /dev/null +++ b/文豪/trace/los_trace.c @@ -0,0 +1,424 @@ +/* ---------------------------------------------------------------------------- + * Copyright (c) Huawei Technologies Co., Ltd. 2019-2020. All rights reserved. + * Description: LiteOS Trace Implementation + * Author: Huawei LiteOS Team + * Create: 2019-08-31 + * 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 "uart.h" +#include "los_trace_pri.h" +#include "trace_pipeline.h" + +#ifdef LOSCFG_KERNEL_SMP +#include "los_mp_pri.h" +#endif + +#ifdef LOSCFG_SHELL +#include "shcmd.h" +#include "shell.h" +#endif + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#ifdef LOSCFG_KERNEL_TRACE +LITE_OS_SEC_BSS STATIC UINT32 g_traceEventCount; //׷¼// +LITE_OS_SEC_BSS STATIC volatile enum TraceState g_traceState = TRACE_UNINIT; //׷״̬// +LITE_OS_SEC_DATA_INIT STATIC volatile BOOL g_enableTrace = FALSE; //Ƿ׷ٹ// +LITE_OS_SEC_BSS STATIC UINT32 g_traceMask = TRACE_DEFAULT_MASK; //׷룬ڹ׷¼// + +#ifdef LOSCFG_TRACE_CONTROL_AGENT +LITE_OS_SEC_BSS STATIC UINT32 g_traceTaskId; //׷ID// +#endif + +#define EVENT_MASK 0xFFFFFFF0 +#define MIN(x, y) ((x) < (y) ? (x) : (y)) + +LITE_OS_SEC_BSS STATIC TRACE_HWI_FILTER_HOOK g_traceHwiFliterHook = NULL; + +LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_traceSpin); + +STATIC_INLINE BOOL OsTraceHwiFilter(UINT32 hwiNum) //жǷҪijӲж// +{ + BOOL ret = ((hwiNum == NUM_HAL_INTERRUPT_UART) || (hwiNum == OS_TICK_INT_NUM)); +#ifdef LOSCFG_KERNEL_SMP + ret |= (hwiNum == LOS_MP_IPI_SCHEDULE); +#endif + if (g_traceHwiFliterHook != NULL) { + ret |= g_traceHwiFliterHook(hwiNum); + } + return ret; +} + +//׷¼֡Ϣ// +STATIC VOID OsTraceSetFrame(TraceEventFrame *frame, UINT32 eventType, UINTPTR identity, const UINTPTR *params, + UINT16 paramCount) +{ + INT32 i; + UINT32 intSave; + + (VOID)memset_s(frame, sizeof(TraceEventFrame), 0, sizeof(TraceEventFrame)); + + if (paramCount > LOSCFG_TRACE_FRAME_MAX_PARAMS) { + paramCount = LOSCFG_TRACE_FRAME_MAX_PARAMS; + } + + TRACE_LOCK(intSave); + frame->curTask = OsTraceGetMaskTid(OsCurrTaskGet()->taskId); + frame->identity = identity; + frame->curTime = HalClockGetCycles(); + frame->eventType = eventType; + +#ifdef LOSCFG_TRACE_FRAME_CORE_MSG + frame->core.cpuId = ArchCurrCpuid(); //CPUID// + frame->core.hwiActive = OS_INT_ACTIVE ? TRUE : FALSE; //Ӳжϻ״̬// + frame->core.taskLockCnt = MIN(OsPercpuGet()->taskLockCnt, 0xF); /* taskLockCnt is 4 bits, max vaule = 0xF */ //// + frame->core.paramCount = paramCount; //Ŀ// +#endif + +#ifdef LOSCFG_TRACE_FRAME_EVENT_COUNT + frame->eventCount = g_traceEventCount; //׷¼ļ// + g_traceEventCount++; +#endif + TRACE_UNLOCK(intSave); + + for (i = 0; i < paramCount; i++) { + frame->params[i] = params[i]; + } +} + +VOID OsTraceSetObj(ObjData *obj, const LosTaskCB *tcb) //ö׷Ϣ// +{ + errno_t ret; + (VOID)memset_s(obj, sizeof(ObjData), 0, sizeof(ObjData)); + + obj->id = OsTraceGetMaskTid(tcb->taskId); //ȡID// + obj->prio = tcb->priority; //ȡȼ// + + ret = strncpy_s(obj->name, LOSCFG_TRACE_OBJ_MAX_NAME_SIZE, tcb->taskName, LOSCFG_TRACE_OBJ_MAX_NAME_SIZE - 1); + if (ret != EOK) { + TRACE_ERROR("Task name copy failed!\n"); + } +} + +//׷¼// +VOID OsTraceHook(UINT32 eventType, UINTPTR identity, const UINTPTR *params, UINT16 paramCount) +{ + if ((eventType == TASK_CREATE) || (eventType == TASK_PRIOSET)) { + OsTraceObjAdd(eventType, identity); /* handle important obj info, these can not be filtered */ + } + + if ((g_enableTrace == TRUE) && (eventType & g_traceMask)) { + UINTPTR id = identity; + if (TRACE_GET_MODE_FLAG(eventType) == TRACE_HWI_FLAG) { + if (OsTraceHwiFilter(identity)) { + return; + } + } else if (TRACE_GET_MODE_FLAG(eventType) == TRACE_TASK_FLAG) { + id = OsTraceGetMaskTid(identity); + } else if (eventType == MEM_INFO_REQ) { + LOS_MEM_POOL_STATUS status; + LOS_MemInfoGet((VOID *)identity, &status); + LOS_TRACE(MEM_INFO, identity, status.uwTotalUsedSize, status.uwTotalFreeSize); + return; + } + + TraceEventFrame frame; + OsTraceSetFrame(&frame, eventType, id, params, paramCount); + + OsTraceWriteOrSendEvent(&frame); //׷¼Ϣдͳȥ// + } +} + +BOOL OsTraceIsEnable(VOID) //ж׷Ƿ״̬// +{ + return g_enableTrace == TRUE; +} + +STATIC VOID OsTraceHookInstall(VOID) //װ׷ٹ// +{ + g_traceEventHook = OsTraceHook; +#ifdef LOSCFG_RECORDER_MODE_OFFLINE + g_traceDumpHook = OsTraceRecordDump; //߼¼ģʽ׷ת// +#endif +} + +#ifdef LOSCFG_TRACE_CONTROL_AGENT +STATIC BOOL OsTraceCmdIsValid(const TraceClientCmd *msg) //жϴTraceClientCmdṹǷЧ// +{ + return ((msg->end == TRACE_CMD_END_CHAR) && (msg->cmd < TRACE_CMD_MAX_CODE)); +} + +STATIC VOID OsTraceCmdHandle(const TraceClientCmd *msg) //TraceClientCmdṹ// +{ + if (!OsTraceCmdIsValid(msg)) { + return; + } + + switch (msg->cmd) { + case TRACE_CMD_START: //׷// + LOS_TraceStart(); + break; + case TRACE_CMD_STOP: //ֹͣ׷// + LOS_TraceStop(); + break; + case TRACE_CMD_SET_EVENT_MASK: //¼// + /* 4 params(UINT8) composition the mask(UINT32) */ + LOS_TraceEventMaskSet(TRACE_MASK_COMBINE(msg->param1, msg->param2, msg->param3, msg->param4)); + break; + case TRACE_CMD_RECODE_DUMP: //׷ټ¼ת// + LOS_TraceRecordDump(TRUE); + break; + default: + break; + } +} + +VOID TraceAgent(VOID) //ϵȴ׷ݵĵյ׷// +{ + UINT32 ret; + TraceClientCmd msg; + + while (1) { + (VOID)memset_s(&msg, sizeof(TraceClientCmd), 0, sizeof(TraceClientCmd)); + ret = OsTraceDataWait(); + if (ret == LOS_OK) { + OsTraceDataRecv((UINT8 *)&msg, sizeof(TraceClientCmd), 0); + OsTraceCmdHandle(&msg); + } + } +} + +STATIC UINT32 OsCreateTraceAgentTask(VOID) //һ׷ٴִ׷߼// +{ + UINT32 ret; + 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)TraceAgent; + taskInitParam.usTaskPrio = LOSCFG_TRACE_TASK_PRIORITY; + taskInitParam.pcName = "TraceAgent"; + taskInitParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; +#ifdef LOSCFG_KERNEL_SMP + taskInitParam.usCpuAffiMask = CPUID_TO_AFFI_MASK(ArchCurrCpuid()); +#endif + ret = LOS_TaskCreate(&g_traceTaskId, &taskInitParam); + return ret; +} +#endif + +UINT32 LOS_TraceInit(VOID *buf, UINT32 size) //ʼ׷ٹ// +{ + UINT32 intSave; + UINT32 ret; + + TRACE_LOCK(intSave); + if (g_traceState != TRACE_UNINIT) { + TRACE_ERROR("trace has been initialized already, the current state is :%d\n", g_traceState); + ret = LOS_ERRNO_TRACE_ERROR_STATUS; + goto LOS_ERREND; + } + +#ifdef LOSCFG_TRACE_CLIENT_INTERACT //жǷҪʼ׷ٹܵ// + ret = OsTracePipelineInit(); + if (ret != LOS_OK) { + goto LOS_ERREND; + } +#endif + +#ifdef LOSCFG_TRACE_CONTROL_AGENT //жǷҪ׷ٴ// + ret = OsCreateTraceAgentTask(); + if (ret != LOS_OK) { + TRACE_ERROR("trace init create agentTask error :0x%x\n", ret); + goto LOS_ERREND; + } +#endif + + ret = OsTraceBufInit(buf, size); //ʼ׷ٻ// + if (ret != LOS_OK) { + goto LOS_RELEASE; + } + + OsTraceHookInstall(); //װ׷ٹ// + + g_traceEventCount = 0; + + /*жǷҪȴ׷ٿͻ׷*/ +#ifdef LOSCFG_RECORDER_MODE_ONLINE /* Wait trace client to start trace */ + g_enableTrace = FALSE; + g_traceState = TRACE_INITED; +#else + g_enableTrace = TRUE; + g_traceState = TRACE_STARTED; +#endif + TRACE_UNLOCK(intSave); + return LOS_OK; +LOS_RELEASE: +#ifdef LOSCFG_TRACE_CONTROL_AGENT //жǷҪɾ׷ٴ// + LOS_TaskDelete(g_traceTaskId); +#endif +LOS_ERREND: + TRACE_UNLOCK(intSave); + return ret; +} + +UINT32 LOS_TraceStart(VOID) //׷ٹ// +{ + UINT32 intSave; + UINT32 ret = LOS_OK; + + TRACE_LOCK(intSave); + if (g_traceState == TRACE_STARTED) { + goto START_END; + } + + if (g_traceState == TRACE_UNINIT) { + TRACE_ERROR("trace not inited, be sure LOS_TraceInit excute success\n"); + ret = LOS_ERRNO_TRACE_ERROR_STATUS; + goto START_END; + } + + OsTraceNotifyStart(); //֪ͨ׷ٹܿʼ// + + g_enableTrace = TRUE; + g_traceState = TRACE_STARTED; + + TRACE_UNLOCK(intSave); + LOS_TRACE(MEM_INFO_REQ, m_aucSysMem0); //׷Ϣ// + return ret; +START_END: + TRACE_UNLOCK(intSave); + return ret; +} + +VOID LOS_TraceStop(VOID) //ֹͣ׷ٹ// +{ + UINT32 intSave; + + TRACE_LOCK(intSave); + if (g_traceState != TRACE_STARTED) { + goto STOP_END; + } + + g_enableTrace = FALSE; + g_traceState = TRACE_STOPED; + OsTraceNotifyStop(); //֪ͨ׷ٹֹͣ// +STOP_END: + TRACE_UNLOCK(intSave); +} + +VOID LOS_TraceEventMaskSet(UINT32 mask) //׷¼// +{ + g_traceMask = mask & EVENT_MASK; +} + +VOID LOS_TraceRecordDump(BOOL toClient) //ת׷ټ¼// +{ + if (g_traceState != TRACE_STOPED) { + TRACE_ERROR("trace dump must after trace stopped , the current state is : %d\n", g_traceState); + return; + } + OsTraceRecordDump(toClient); +} + +OfflineHead *LOS_TraceRecordGet(VOID) //ȡ׷ټ¼// +{ + return OsTraceRecordGet(); +} + +VOID LOS_TraceReset(VOID) //׷ٹ// +{ + if (g_traceState == TRACE_UNINIT) { + TRACE_ERROR("trace not inited, be sure LOS_TraceInit excute success\n"); + return; + } + + OsTraceReset(); +} + +VOID LOS_TraceHwiFilterHookReg(TRACE_HWI_FILTER_HOOK hook) //עжϹ˹// +{ + UINT32 intSave; + + TRACE_LOCK(intSave); + g_traceHwiFliterHook = hook; + TRACE_UNLOCK(intSave); +} + +#ifdef LOSCFG_SHELL +LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdTraceSetMask(INT32 argc, const CHAR **argv) //׷¼// +{ + size_t mask; + CHAR *endPtr = NULL; + + if (argc >= 2) { /* 2:Just as number of parameters */ + PRINTK("\nUsage: trace_mask or trace_mask ID\n"); + return OS_ERROR; + } + + if (argc == 0) { + mask = TRACE_DEFAULT_MASK; + } else { + mask = strtoul(argv[0], &endPtr, 0); + } + LOS_TraceEventMaskSet((UINT32)mask); + return LOS_OK; +} + +LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdTraceDump(INT32 argc, const CHAR **argv) //׷ټ¼ת// +{ + BOOL toClient; + CHAR *endPtr = NULL; + + if (argc >= 2) { /* 2:Just as number of parameters */ + PRINTK("\nUsage: trace_dump or trace_dump [1/0]\n"); + return OS_ERROR; + } + + if (argc == 0) { + toClient = FALSE; + } else { + toClient = strtoul(argv[0], &endPtr, 0) != 0 ? TRUE : FALSE; + } + LOS_TraceRecordDump(toClient); + return LOS_OK; +} + +/*кע*/ +SHELLCMD_ENTRY(tracestart_shellcmd, CMD_TYPE_EX, "trace_start", 0, (CmdCallBackFunc)LOS_TraceStart); //׷ٹܵ// +SHELLCMD_ENTRY(tracestop_shellcmd, CMD_TYPE_EX, "trace_stop", 0, (CmdCallBackFunc)LOS_TraceStop); //׷ٹֹܵͣ// +SHELLCMD_ENTRY(tracesetmask_shellcmd, CMD_TYPE_EX, "trace_mask", 1, (CmdCallBackFunc)OsShellCmdTraceSetMask); //׷¼// +SHELLCMD_ENTRY(tracereset_shellcmd, CMD_TYPE_EX, "trace_reset", 0, (CmdCallBackFunc)LOS_TraceReset); //׷ټ¼// +SHELLCMD_ENTRY(tracedump_shellcmd, CMD_TYPE_EX, "trace_dump", 1, (CmdCallBackFunc)OsShellCmdTraceDump); //ת׷ټ¼// +#endif + +#endif /* LOSCFG_KERNEL_TRACE */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ diff --git a/文豪/trace/pipeline/serial/trace_pipeline_serial.c b/文豪/trace/pipeline/serial/trace_pipeline_serial.c new file mode 100644 index 0000000..e61300b --- /dev/null +++ b/文豪/trace/pipeline/serial/trace_pipeline_serial.c @@ -0,0 +1,98 @@ +/* ---------------------------------------------------------------------------- + * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved. + * Description: LiteOS Trace Pipeline of Serial Implementation + * Author: Huawei LiteOS Team + * Create: 2020-03-31 + * 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 "trace_pipeline_serial.h" +#include "trace_pipeline.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#ifdef LOSCFG_TRACE_CONTROL_AGENT +UINT32 SerialPipelineInit(VOID) //ڳʼйܵ// +{ + return uart_hwiCreate(); +} + +UINT32 SerialDataReceive(UINT8 *data, UINT32 size, UINT32 timeout) //ڴӴйܵ// +{ + return uart_read(data, size, timeout); +} + +UINT32 SerialWait(VOID) //ڵȴйܵ׼// +{ + return uart_wait_adapt(); +} + +#else//4ų2930 + +UINT32 SerialPipelineInit(VOID) //ʾʼɹ// +{ + return LOS_OK; +} + +UINT32 SerialDataReceive(UINT8 *data, UINT32 size, UINT32 timeout) //ʾյ// +{ + return LOS_OK; +} + +UINT32 SerialWait(VOID) //ʾѾ׼// +{ + return LOS_OK; +} +#endif + +VOID SerialDataSend(UINT16 len, UINT8 *data) //йܵ// +{ + UINT32 i; + + for (i = 0; i < len; i++) { + UART_PUTC(data[i]); + } +} + +STATIC const TracePipelineOps g_serialOps = { + .init = SerialPipelineInit, + .dataSend = SerialDataSend, + .dataRecv = SerialDataReceive, + .wait = SerialWait, +}; + +UINT32 OsTracePipelineInit(VOID) //ڳʼ׷ٹܵע֮صIJӿ// +{ + OsTracePipelineReg(&g_serialOps); + return g_serialOps.init(); +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ diff --git a/文豪/trace/pipeline/serial/trace_pipeline_serial.h b/文豪/trace/pipeline/serial/trace_pipeline_serial.h new file mode 100644 index 0000000..a3cf977 --- /dev/null +++ b/文豪/trace/pipeline/serial/trace_pipeline_serial.h @@ -0,0 +1,50 @@ +/* ---------------------------------------------------------------------------- + * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved. + * Description: LiteOS Trace Pipeline of Serial Implementation HeadFile + * Author: Huawei LiteOS Team + * Create: 2020-03-16 + * 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. + * --------------------------------------------------------------------------- */ + +#ifndef _TRACE_PIPELINE_SERIAL_H +#define _TRACE_PIPELINE_SERIAL_H + +#include "los_typedef.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +extern INT32 uart_putc(CHAR c); //򴮿ڷһַ// + +#define UART_PUTC(c) uart_putc((c)) //uart_putc// + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif /* _TRACE_PIPELINE_SERIAL_H */ diff --git a/文豪/trace/pipeline/trace_pipeline.c b/文豪/trace/pipeline/trace_pipeline.c new file mode 100644 index 0000000..33e5f63 --- /dev/null +++ b/文豪/trace/pipeline/trace_pipeline.c @@ -0,0 +1,156 @@ +/* ---------------------------------------------------------------------------- + * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved. + * Description: LiteOS Trace Pipeline Implementation + * Author: Huawei LiteOS Team + * Create: 2020-03-31 + * 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 "trace_pipeline.h" +#include "trace_tlv.h" +#include "los_trace_pri.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +//ֹ// +LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_pipeSpin); //ʼһ// +#define PIPE_LOCK(state) LOS_SpinLockSave(&g_pipeSpin, &(state)) //// +#define PIPE_UNLOCK(state) LOS_SpinUnlockRestore(&g_pipeSpin, (state)) //// + +STATIC TlvTable g_traceTlvTblNotify[] = { //ṹijԱͺʹС// + { CMD, LOS_OFF_SET_OF(TraceNotifyFrame, cmd), sizeof(UINT32) }, + { PARAMS, LOS_OFF_SET_OF(TraceNotifyFrame, param), sizeof(UINT32) }, + { TRACE_TLV_TYPE_NULL, 0, 0 }, +}; + +STATIC TlvTable g_traceTlvTblHead[] = { //ṹijԱͺʹС// + { ENDIAN, LOS_OFF_SET_OF(TraceBaseHeaderInfo, bigLittleEndian), sizeof(UINT32) }, + { VERSION, LOS_OFF_SET_OF(TraceBaseHeaderInfo, version), sizeof(UINT32) }, + { CLOCK_FREQ, LOS_OFF_SET_OF(TraceBaseHeaderInfo, clockFreq), sizeof(UINT32) }, + { TRACE_TLV_TYPE_NULL, 0, 0 }, +}; + +STATIC TlvTable g_traceTlvTblObj[] = { //ṹijԱ͡ƫλúʹС// + { ADDR, LOS_OFF_SET_OF(ObjData, id), sizeof(UINT32) }, + { PRIO, LOS_OFF_SET_OF(ObjData, prio), sizeof(UINT32) }, + { NAME, LOS_OFF_SET_OF(ObjData, name), sizeof(CHAR) * LOSCFG_TRACE_OBJ_MAX_NAME_SIZE }, + { TRACE_TLV_TYPE_NULL, 0, 0 }, +}; + +STATIC TlvTable g_traceTlvTblEvent[] = { //ṹijԱͺʹС// +#ifdef LOSCFG_TRACE_FRAME_CORE_MSG + { CORE, LOS_OFF_SET_OF(TraceEventFrame, core), sizeof(UINT32) }, +#endif + { EVENT_CODE, LOS_OFF_SET_OF(TraceEventFrame, eventType), sizeof(UINT32) }, + { CUR_TIME, LOS_OFF_SET_OF(TraceEventFrame, curTime), sizeof(UINT64) }, + +#ifdef LOSCFG_TRACE_FRAME_EVENT_COUNT + { EVENT_COUNT, LOS_OFF_SET_OF(TraceEventFrame, eventCount), sizeof(UINT32) }, +#endif + { CUR_TASK, LOS_OFF_SET_OF(TraceEventFrame, curTask), sizeof(UINT32) }, + { IDENTITY, LOS_OFF_SET_OF(TraceEventFrame, identity), sizeof(UINTPTR) }, + { EVENT_PARAMS, LOS_OFF_SET_OF(TraceEventFrame, params), sizeof(UINTPTR) * LOSCFG_TRACE_FRAME_MAX_PARAMS }, + { TRACE_TLV_TYPE_NULL, 0, 0 }, +}; + +STATIC TlvTable *g_traceTlvTbl[] = { + g_traceTlvTblNotify, + g_traceTlvTblHead, + g_traceTlvTblObj, + g_traceTlvTblEvent +}; + +STATIC UINT32 DefaultPipelineInit(VOID) +{ + return LOS_OK; +} + +STATIC VOID DefaultDataSend(UINT16 len, UINT8 *data) +{ //lendataΪ"δʹ"// + (VOID)len; //// + (VOID)data; +} + +STATIC UINT32 DefaultDataReceive(UINT8 *data, UINT32 size, UINT32 timeout) +{ + (VOID)data; //datasizetimeoutΪ"δʹ"// + (VOID)size; + (VOID)timeout; + return LOS_OK; +} + +STATIC UINT32 DefaultWait(VOID) +{ + return LOS_OK; +} + +STATIC TracePipelineOps g_defaultOps = { + .init = DefaultPipelineInit, + .dataSend = DefaultDataSend, + .dataRecv = DefaultDataReceive, + .wait = DefaultWait, +}; + +STATIC const TracePipelineOps *g_tracePipelineOps = &g_defaultOps; + +VOID OsTracePipelineReg(const TracePipelineOps *ops) +{ + g_tracePipelineOps = ops; //עһTracePipelineOpsṹָ// +} + +VOID OsTraceDataSend(UINT8 type, UINT16 len, UINT8 *data) //ڷ׷// +{ + UINT32 intSave; + UINT8 outBuf[LOSCFG_TRACE_TLV_BUF_SIZE] = {0}; + + if ((type > TRACE_MSG_MAX) || (len > LOSCFG_TRACE_TLV_BUF_SIZE)) { //ĺϷԼ// + return; + } + + //ݽб// + len = OsTraceDataEncode(type, g_traceTlvTbl[type], data, &outBuf[0], sizeof(outBuf)); + + PIPE_LOCK(intSave); //ȡֹ̲ܵ߳// + g_tracePipelineOps->dataSend(len, &outBuf[0]); //ͱ// + PIPE_UNLOCK(intSave); //ͷŹܵ// +} + +UINT32 OsTraceDataRecv(UINT8 *data, UINT32 size, UINT32 timeout) //ڽ׷// +{ + return g_tracePipelineOps->dataRecv(data, size, timeout); +} + +UINT32 OsTraceDataWait(VOID) //ڵȴ׷// +{ + return g_tracePipelineOps->wait(); +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ diff --git a/文豪/trace/pipeline/trace_pipeline.h b/文豪/trace/pipeline/trace_pipeline.h new file mode 100644 index 0000000..49e292b --- /dev/null +++ b/文豪/trace/pipeline/trace_pipeline.h @@ -0,0 +1,104 @@ +/* ---------------------------------------------------------------------------- + * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved. + * Description: LiteOS Trace Pipeline Implementation HeadFile + * Author: Huawei LiteOS Team + * Create: 2020-03-16 + * 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. + * --------------------------------------------------------------------------- */ + +#ifndef _TRACE_PIPELINE_H +#define _TRACE_PIPELINE_H + +#include "los_typedef.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/*ʵ׷ˮߵĹ*/ +typedef struct { + UINT32 (*init)(VOID); //ڳʼ// + VOID (*dataSend)(UINT16 len, UINT8 *data); //ڷ// + UINT32 (*dataRecv)(UINT8 *data, UINT32 size, UINT32 timeout); //ڽ// + UINT32 (*wait)(VOID); //ڵȴ// +} TracePipelineOps; + +/* used as tlv's tag */ +enum TraceMsgType { //ڱʾ׷Ϣ// + //// + NOTIFY, //֪ͨ// + HEAD, //ͷ// + OBJ, //// + EVENT, //¼// + + TRACE_MSG_MAX, //ֵ// +}; + +enum TraceNotifySubType { //ڱʾ֪ͨϢ// + CMD = 0x1, + PARAMS, +}; + +enum TraceHeadSubType { //ڱʾ׷ͷϢ// + ENDIAN = 0x1, //ֽ// + VERSION, //汾// + OBJ_SIZE, //С// + OBJ_COUNT, //// + CUR_INDEX, //ǰ// + MAX_RECODE, + CUR_OBJ_INDEX, + CLOCK_FREQ, +}; + +enum TraceObjSubType { //ڱʾ׷ٶ// + ADDR = 0x1, //ַ// + PRIO, //ȼ/ + NAME, //// +}; + +enum TraceEvtSubType { //ڱʾ׷¼// + CORE = 0x1, //ı// + EVENT_CODE, //¼// + CUR_TIME, //ǰʱ// + EVENT_COUNT, //¼// + CUR_TASK, //ǰ// + IDENTITY, //Ϣ// + EVENT_PARAMS, //¼// +}; + +extern VOID OsTracePipelineReg(const TracePipelineOps *ops); //ע׷ٹܵ// +extern UINT32 OsTracePipelineInit(VOID); //ڳʼ׷ٹܵ// + +extern VOID OsTraceDataSend(UINT8 type, UINT16 len, UINT8 *data); //ڷ׷// +extern UINT32 OsTraceDataRecv(UINT8 *data, UINT32 size, UINT32 timeout); //ڽ׷// +extern UINT32 OsTraceDataWait(VOID); //ڵȴ׷// + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif /* _TRACE_PIPELINE_H */ diff --git a/文豪/trace/pipeline/trace_tlv.c b/文豪/trace/pipeline/trace_tlv.c new file mode 100644 index 0000000..4545766 --- /dev/null +++ b/文豪/trace/pipeline/trace_tlv.c @@ -0,0 +1,121 @@ +/* ---------------------------------------------------------------------------- + * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved. + * Description: LiteOS Trace Tlv Implementation + * Author: Huawei LiteOS Team + * Create: 2020-03-31 + * 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 "trace_tlv.h" +#include "securec.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#define CRC_WIDTH 8 //CRCλ// +#define CRC_POLY 0x1021 //CRCʽ// +#define CRC_TOPBIT 0x8000 //CRCеλ// + +STATIC UINT16 CalcCrc16(const UINT8 *buf, UINT32 len) //ڼ16λCRCУֵ// +{ + UINT32 i; + UINT16 crc = 0; + + for (; len > 0; len--) { + crc = crc ^ (*buf++ << CRC_WIDTH); + for (i = 0; i < CRC_WIDTH; i++) { + if (crc & CRC_TOPBIT) { + crc = (crc << 1) ^ CRC_POLY; + } else { + crc <<= 1; + } + } + } + return crc; +} + +STATIC UINT32 OsWriteTlv(UINT8 *tlvBuf, UINT8 type, UINT8 len, UINT8 *value) //TLVдTLV// +{ + TraceMsgTlvBody *body = (TraceMsgTlvBody *)tlvBuf; + + if (len == 0) { + return 0; + } + + body->type = type; + body->len = len; + /* Do not check return value for performance, if copy failed, only this package will be discarded */ + (VOID)memcpy_s(body->value, len, value, len); + return len + sizeof(body->type) + sizeof(body->len); //ʵдֽ// +} + +/*TLVеĶ壬ԴݱTLVʽдTLV*/ +STATIC UINT32 OsTlvEncode(const TlvTable *table, UINT8 *srcBuf, UINT8 *tlvBuf, INT32 tlvBufLen) +{ + UINT32 len = 0; + const TlvTable *tlvTableItem = table; + + while (tlvTableItem->tag != TRACE_TLV_TYPE_NULL) { + if ((len + tlvTableItem->elemSize + sizeof(UINT8) + sizeof(UINT8)) > tlvBufLen) { + break; + } + len += OsWriteTlv(tlvBuf + len, tlvTableItem->tag, tlvTableItem->elemSize, srcBuf + tlvTableItem->elemOffset); + tlvTableItem++; + } + return len; +} + +/*ԴݰTLVĶ룬дĿ껺*/ +UINT32 OsTraceDataEncode(UINT8 type, const TlvTable *table, UINT8 *src, UINT8 *dest, INT32 destLen) +{ + UINT16 crc; + INT32 len; + INT32 tlvBufLen; + UINT8 *tlvBuf = NULL; + + TraceMsgTlvHead *head = (TraceMsgTlvHead *)dest; + tlvBufLen = destLen - sizeof(TraceMsgTlvHead); + + if ((tlvBufLen <= 0) || (table == NULL)) { + return 0; + } + + tlvBuf = dest + sizeof(TraceMsgTlvHead); + len = OsTlvEncode(table, src, tlvBuf, tlvBufLen); + crc = CalcCrc16(tlvBuf, len); + + head->magicNum = TRACE_TLV_MSG_HEAD; + head->msgType = type; + head->len = len; + head->crc = crc; + return len + sizeof(TraceMsgTlvHead); +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ diff --git a/文豪/trace/pipeline/trace_tlv.h b/文豪/trace/pipeline/trace_tlv.h new file mode 100644 index 0000000..1871012 --- /dev/null +++ b/文豪/trace/pipeline/trace_tlv.h @@ -0,0 +1,95 @@ +/* ---------------------------------------------------------------------------- + * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved. + * Description: LiteOS Trace Tlv Implementation HeadFile + * Author: Huawei LiteOS Team + * Create: 2020-03-16 + * 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. + * --------------------------------------------------------------------------- */ + +#ifndef _TRACE_TLV_H +#define _TRACE_TLV_H + +#include "los_typedef.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#define TRACE_TLV_MSG_HEAD 0xFF +#define TRACE_TLV_TYPE_NULL 0xFF + +typedef struct { + UINT8 magicNum; //ħ// + UINT8 msgType; //Ϣ// + UINT16 len; //Ϣ// + UINT16 crc; //CRCУ// +} TraceMsgTlvHead; //TLVϢͷ// + +typedef struct { + UINT8 type; //Ϣ/// + UINT8 len; //Ϣ// + UINT8 value[]; //// +} TraceMsgTlvBody; //TLVϢϢ// + +typedef struct { + UINT8 tag; //ǩ// + UINT8 elemOffset; //Ԫƫ// + UINT8 elemSize; //ԪشС// +} TlvTable; //TLV// + +/** + * @ingroup los_trace + * @brief Encode trace raw data. + * + * @par Description: + * This API is used to encode trace raw data to tlv data. + * @attention + *
        + *
      • Encade trace data
      • + *
      + * + * @param type [IN] Type #UINT8. The type stands for different struct of src data. + * @param src [IN] Type #UINT8 *. The raw trace data. + * @param table [IN] Type #const TlvTable *. The tlv table descript elemOffset and elemSize. + * @param dest [OUT] Type #UINT8 *. The tlv data. + * @param destLen [IN] Type #UINT8 *. The tlv buf max len. + + * @retval #0 convert failed. + * @retval #UINT32 convert success bytes. + * + * @par Dependency: + *
      • trace_tlv.h: the header file that contains the API declaration.
      + * @see LOS_TraceDataEncode + * @since Huawei LiteOS V200R005C00 + */ +extern UINT32 OsTraceDataEncode(UINT8 type, const TlvTable *table, UINT8 *src, UINT8 *dest, INT32 destLen); +/*TLVϢԭʼ׷ݽб룬ӦTLV*/ +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif /* _TRACE_TLV_H */ \ No newline at end of file diff --git a/文豪/trace/trace_offline.c b/文豪/trace/trace_offline.c new file mode 100644 index 0000000..f23a43f --- /dev/null +++ b/文豪/trace/trace_offline.c @@ -0,0 +1,264 @@ +/* ---------------------------------------------------------------------------- + * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved. + * Description: LiteOS Trace Offline Mode Implementation + * Author: Huawei LiteOS Team + * Create: 2020-03-31 + * 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_trace_pri.h" +#include "trace_pipeline.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#ifdef LOSCFG_RECORDER_MODE_OFFLINE +#define BITS_NUM_FOR_TASK_ID 16 //ָIDλ// + +LITE_OS_SEC_BSS STATIC TraceOfflineHeaderInfo g_traceRecoder; //¼߸ټ¼Ϣ// +LITE_OS_SEC_BSS STATIC UINT32 g_tidMask[LOSCFG_BASE_CORE_TSK_LIMIT] = {0}; //ڴ洢ID// + +UINT32 OsTraceGetMaskTid(UINT32 tid) //ڻȡID// +{ + return tid | ((tid < LOSCFG_BASE_CORE_TSK_LIMIT) ? g_tidMask[tid] << BITS_NUM_FOR_TASK_ID : 0); /* tid < 65535 */ +} + +UINT32 OsTraceBufInit(VOID *buf, UINT32 size) //ڳʼ߸ٻ// +{ + UINT32 headSize; + + headSize = sizeof(OfflineHead) + sizeof(ObjData) * LOSCFG_TRACE_OBJ_MAX_NUM; //ڴ洢߸ټ¼ͷϢ// + if (size <= headSize) { + TRACE_ERROR("trace buf size not enough than 0x%x\n", headSize); + return LOS_ERRNO_TRACE_BUF_TOO_SMALL; + } + + if (buf == NULL) { + buf = LOS_MemAlloc(m_aucSysMem1, size); + if (buf == NULL) { + return LOS_ERRNO_TRACE_NO_MEMORY; + } + } + + (VOID)memset_s(buf, size, 0, size); + g_traceRecoder.head = (OfflineHead *)buf; + g_traceRecoder.head->baseInfo.bigLittleEndian = TRACE_BIGLITTLE_WORD; + g_traceRecoder.head->baseInfo.version = TRACE_VERSION(TRACE_MODE_OFFLINE); + g_traceRecoder.head->baseInfo.clockFreq = GET_SYS_CLOCK(); + g_traceRecoder.head->objSize = sizeof(ObjData); + g_traceRecoder.head->frameSize = sizeof(TraceEventFrame); + g_traceRecoder.head->objOffset = sizeof(OfflineHead); + g_traceRecoder.head->frameOffset = headSize; + g_traceRecoder.head->totalLen = size; + + g_traceRecoder.ctrl.curIndex = 0; + g_traceRecoder.ctrl.curObjIndex = 0; + g_traceRecoder.ctrl.maxObjCount = LOSCFG_TRACE_OBJ_MAX_NUM; + g_traceRecoder.ctrl.maxRecordCount = (size - headSize) / sizeof(TraceEventFrame); + g_traceRecoder.ctrl.objBuf = (ObjData *)((UINTPTR)buf + g_traceRecoder.head->objOffset); + g_traceRecoder.ctrl.frameBuf = (TraceEventFrame *)((UINTPTR)buf + g_traceRecoder.head->frameOffset); + + return LOS_OK; +} + +VOID OsTraceObjAdd(UINT32 eventType, UINT32 taskId) //߸ٻӶ// +{ + UINT32 intSave; + UINT32 index; + ObjData *obj = NULL; + + TRACE_LOCK(intSave); + /* add obj begin */ + index = g_traceRecoder.ctrl.curObjIndex; + if (index >= LOSCFG_TRACE_OBJ_MAX_NUM) { /* do nothing when config LOSCFG_TRACE_OBJ_MAX_NUM = 0 */ + TRACE_UNLOCK(intSave); + return; + } + obj = &g_traceRecoder.ctrl.objBuf[index]; + + if (taskId < LOSCFG_BASE_CORE_TSK_LIMIT) { + g_tidMask[taskId]++; + } + + OsTraceSetObj(obj, OS_TCB_FROM_TID(taskId)); + + g_traceRecoder.ctrl.curObjIndex++; + if (g_traceRecoder.ctrl.curObjIndex >= g_traceRecoder.ctrl.maxObjCount) { + g_traceRecoder.ctrl.curObjIndex = 0; /* turn around */ + } + /* add obj end */ + TRACE_UNLOCK(intSave); +} + +VOID OsTraceWriteOrSendEvent(const TraceEventFrame *frame) //߸ٻд¼֡// +{ + UINT16 index; + UINT32 intSave; + + TRACE_LOCK(intSave); + index = g_traceRecoder.ctrl.curIndex; + (VOID)memcpy_s(&g_traceRecoder.ctrl.frameBuf[index], sizeof(TraceEventFrame), frame, sizeof(TraceEventFrame)); + + g_traceRecoder.ctrl.curIndex++; + if (g_traceRecoder.ctrl.curIndex >= g_traceRecoder.ctrl.maxRecordCount) { + g_traceRecoder.ctrl.curIndex = 0; + } + TRACE_UNLOCK(intSave); +} + +VOID OsTraceReset(VOID) //߸ٻ// +{ + UINT32 intSave; + UINT32 bufLen; + + TRACE_LOCK(intSave); + bufLen = sizeof(TraceEventFrame) * g_traceRecoder.ctrl.maxRecordCount; + (VOID)memset_s(g_traceRecoder.ctrl.frameBuf, bufLen, 0, bufLen); + g_traceRecoder.ctrl.curIndex = 0; + TRACE_UNLOCK(intSave); +} + +STATIC VOID OsTraceInfoObj(VOID) //ڴӡ߸ٶϢ// +{ + UINT32 i; + ObjData *obj = &g_traceRecoder.ctrl.objBuf[0]; + + if (g_traceRecoder.ctrl.maxObjCount > 0) { + PRINTK("CurObjIndex = %u\n", g_traceRecoder.ctrl.curObjIndex); + PRINTK("Index TaskID TaskPrio TaskName \n"); + for (i = 0; i < g_traceRecoder.ctrl.maxObjCount; i++, obj++) { + PRINTK("%-7u 0x%-6x %-10u %s\n", i, obj->id, obj->prio, obj->name); + } + PRINTK("\n"); + } +} + +STATIC VOID OsTraceInfoEventTitle(VOID) //ڴӡ߸¼// +{ + PRINTK("CurEvtIndex = %u\n", g_traceRecoder.ctrl.curIndex); + + PRINTK("Index Time(cycles) EventType CurTask Identity "); +#ifdef LOSCFG_TRACE_FRAME_CORE_MSG + PRINTK("cpuId hwiActive taskLockCnt "); +#endif +#ifdef LOSCFG_TRACE_FRAME_EVENT_COUNT + PRINTK("eventCount "); +#endif + if (LOSCFG_TRACE_FRAME_MAX_PARAMS > 0) { + PRINTK("params "); + } + PRINTK("\n"); +} + +STATIC VOID OsTraceInfoEventData(VOID) //ڴӡ߸¼// +{ + UINT32 i, j; + TraceEventFrame *frame = &g_traceRecoder.ctrl.frameBuf[0]; + + for (i = 0; i < g_traceRecoder.ctrl.maxRecordCount; i++, frame++) { + PRINTK("%-7u 0x%-15llx 0x%-12x 0x%-7x 0x%-11x ", i, frame->curTime, frame->eventType, + frame->curTask, frame->identity); +#ifdef LOSCFG_TRACE_FRAME_CORE_MSG + UINT32 taskLockCnt = frame->core.taskLockCnt; +#ifdef LOSCFG_KERNEL_SMP + /* + * For smp systems, TRACE_LOCK will requst taskLock, and this counter + * will increase by 1 in that case. + */ + taskLockCnt -= 1; +#endif + PRINTK("%-11u %-11u %-11u", frame->core.cpuId, frame->core.hwiActive, taskLockCnt); +#endif +#ifdef LOSCFG_TRACE_FRAME_EVENT_COUNT + PRINTK("%-11u", frame->eventCount); +#endif + for (j = 0; j < LOSCFG_TRACE_FRAME_MAX_PARAMS; j++) { + PRINTK("0x%-11x", frame->params[j]); + } + PRINTK("\n"); + } +} + +STATIC VOID OsTraceInfoDisplay(VOID) //ʾ߸Ϣ// +{ + OfflineHead *head = g_traceRecoder.head; + + PRINTK("*******TraceInfo begin*******\n"); + PRINTK("clockFreq = %u\n", head->baseInfo.clockFreq); + + OsTraceInfoObj(); + + OsTraceInfoEventTitle(); + OsTraceInfoEventData(); + + PRINTK("*******TraceInfo end*******\n"); +} + +#ifdef LOSCFG_TRACE_CLIENT_INTERACT +STATIC VOID OsTraceSendInfo(VOID) //ڷ߸Ϣ// +{ + UINT32 i; + ObjData *obj = NULL; + TraceEventFrame *frame = NULL; + + OsTraceDataSend(HEAD, sizeof(OfflineHead), (UINT8 *)g_traceRecoder.head); + + obj = &g_traceRecoder.ctrl.objBuf[0]; + for (i = 0; i < g_traceRecoder.ctrl.maxObjCount; i++) { + OsTraceDataSend(OBJ, sizeof(ObjData), (UINT8 *)(obj + i)); + } + + frame = &g_traceRecoder.ctrl.frameBuf[0]; + for (i = 0; i < g_traceRecoder.ctrl.maxRecordCount; i++) { + OsTraceDataSend(EVENT, sizeof(TraceEventFrame), (UINT8 *)(frame + i)); + } +} +#endif + +VOID OsTraceRecordDump(BOOL toClient) //߸Ϣ// +{ + if (!toClient) { //ָʾǷ߸Ϣ// + OsTraceInfoDisplay(); + return; + } + +#ifdef LOSCFG_TRACE_CLIENT_INTERACT + OsTraceSendInfo(); +#endif +} + +OfflineHead *OsTraceRecordGet(VOID) //ڻȡ߸ټ¼ͷϢ// +{ + return g_traceRecoder.head; +} + +#endif /* LOSCFG_RECORDER_MODE_OFFLINE */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ diff --git a/文豪/trace/trace_online.c b/文豪/trace/trace_online.c new file mode 100644 index 0000000..6faba44 --- /dev/null +++ b/文豪/trace/trace_online.c @@ -0,0 +1,117 @@ +/* ---------------------------------------------------------------------------- + * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved. + * Description: LiteOS Trace Online Mode Implementation + * Author: Huawei LiteOS Team + * Create: 2020-03-31 + * 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_trace_pri.h" +#include "trace_pipeline.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#ifdef LOSCFG_RECORDER_MODE_ONLINE +UINT32 OsTraceGetMaskTid(UINT32 taskId) //ڻȡID// +{ + return taskId; +} + +UINT32 OsTraceBufInit(VOID *buf, UINT32 size) //ʼٻ// +{ + (VOID)buf; + (VOID)size; + return LOS_OK; +} + +VOID OsTraceSendHead(VOID) //͸ݵͷϢ// +{ + TraceBaseHeaderInfo head = { + .bigLittleEndian = TRACE_BIGLITTLE_WORD, + .version = TRACE_VERSION(TRACE_MODE_ONLINE), + .clockFreq = GET_SYS_CLOCK(), + }; + + OsTraceDataSend(HEAD, sizeof(TraceBaseHeaderInfo), (UINT8 *)&head); +} + +VOID OsTraceSendNotify(UINT32 type, UINT32 value) //֪ͨ͵ĸ// +{ + TraceNotifyFrame frame = { + .cmd = type, + .param = value, + }; + + OsTraceDataSend(NOTIFY, sizeof(TraceNotifyFrame), (UINT8 *)&frame); +} + +STATIC VOID OsTraceSendObj(const LosTaskCB *tcb) //ͶΪobjĸ// +{ + ObjData obj; + + OsTraceSetObj(&obj, tcb); + OsTraceDataSend(OBJ, sizeof(ObjData), (UINT8 *)&obj); +} + +VOID OsTraceSendObjTable(VOID) //Ͷ͵ĸ// +{ + UINT32 loop; + LosTaskCB *tcb = NULL; + + for (loop = 0; loop < g_taskMaxNum; ++loop) { + tcb = g_taskCBArray + loop; + if (tcb->taskStatus & OS_TASK_STATUS_UNUSED) { + continue; + } + OsTraceSendObj(tcb); + } +} + +VOID OsTraceObjAdd(UINT32 eventType, UINT32 taskId) //ټ¼Ӷ// +{ + if (OsTraceIsEnable()) { + OsTraceSendObj(OS_TCB_FROM_TID(taskId)); + } +} + +VOID OsTraceWriteOrSendEvent(const TraceEventFrame *frame) //¼// +{ + OsTraceDataSend(EVENT, sizeof(TraceEventFrame), (UINT8 *)frame); +} + +OfflineHead *OsTraceRecordGet(VOID) //ȡ߸ټ¼ͷ// +{ + return NULL; //ʾû߸ټ¼// +} + +#endif /* LOSCFG_RECORDER_MODE_ONLINE */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ From 2bdb3fa4bd8a2d663d08bec84f4a1c88df64f80a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=87=E8=B1=AA?= <2548632733@qq.com> Date: Mon, 4 Dec 2023 19:10:33 +0800 Subject: [PATCH 13/26] zhangxinyuan --- kkk.zip | Bin 0 -> 53432 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 kkk.zip diff --git a/kkk.zip b/kkk.zip new file mode 100644 index 0000000000000000000000000000000000000000..b5323c3119761ad9240d6743110933dd3af1dad0 GIT binary patch literal 53432 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

      @ZQcpVKYH!H)3v})qheLTNSptb-U$6D* zSQ#4`37DPK0tyC=t3nlZ&tIe&MGZhW%)9453VH;y_JVP3Au4)Rq@eVmVI9Q>^1fwm zylXe23$Sc`J!-adKOYZs=ehH*^l$1B1L;B3;#|WI=@#+CMM2Mv9C6nl2E{m(^B)OgsNhHXEm)PS}m?uFrmI4cSM2x&Ua=ScU z*W%#^bNsEz4rIa>tg#hIWR>WpF5HdLQd;>`XD*r(c;t$td)b&on4Dj=DPi!k;zD?rs zC+l%iR|%KsD}uKmbdX#Dizr@{C#_8sB&B_w@F8M`B$QW3k&ssgH`WHbajJGulpl!U zBe=d31Ln(!b�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�Xqvz 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 z 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 literal 0 HcmV?d00001 From 3e1c0beb7b72618478e67f78b2132acedc27bf3e Mon Sep 17 00:00:00 2001 From: tree <1913915946@qq.com> Date: Mon, 4 Dec 2023 20:05:08 +0800 Subject: [PATCH 14/26] =?UTF-8?q?=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/用例_oujiashu.docx | Bin 0 -> 14253 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 doc/用例_oujiashu.docx diff --git a/doc/用例_oujiashu.docx b/doc/用例_oujiashu.docx new file mode 100644 index 0000000000000000000000000000000000000000..80b0ece3233084e8e246b655c5949b1cb04eb7eb GIT binary patch literal 14253 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 literal 0 HcmV?d00001 From f6fcaaeb3788d64cbf0b39ef6ee3a8d11ac1b7e0 Mon Sep 17 00:00:00 2001 From: cailun <2505225681@qq.com> Date: Sun, 24 Dec 2023 20:59:27 +0800 Subject: [PATCH 15/26] src/kernel/base/los_bitmap.c --- src/kernel/base/los_bitmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kernel/base/los_bitmap.c b/src/kernel/base/los_bitmap.c index d299fb6..84a056a 100644 --- a/src/kernel/base/los_bitmap.c +++ b/src/kernel/base/los_bitmap.c @@ -35,7 +35,7 @@ extern "C" { #endif /* __cplusplus */ #endif /* __cplusplus */ -#define OS_BITMAP_MASK 0x1FU//位图的掩码,与数据进行与操作得到低五位的信息 +#define OS_BITMAP_MASK 0x1FU VOID LOS_BitmapSet(UINT32 *bitmap, UINT16 pos) { From 99c4c8235c1b2384b08f3b652ffc6f7afde31b30 Mon Sep 17 00:00:00 2001 From: cailun <2505225681@qq.com> Date: Tue, 26 Dec 2023 20:41:32 +0800 Subject: [PATCH 16/26] src --- src/kernel/base/include/los_membox_pri.h | 2 +- .../base/include/los_multipledlinkhead_pri.h | 2 +- src/kernel/base/include/los_mux_debug_pri.h | 14 ++++++++--- src/kernel/base/include/los_mux_pri.h | 19 +++++++++++---- src/kernel/base/include/los_percpu_pri.h | 23 +++++++++---------- src/kernel/base/include/los_printf_pri.h | 9 +++++--- src/kernel/base/include/los_priqueue_pri.h | 10 +++++++- src/kernel/base/include/los_queue_debug_pri.h | 10 +++++++- src/kernel/base/include/los_queue_pri.h | 11 ++++++--- src/kernel/base/include/los_sched_debug_pri.h | 16 ++++++------- src/kernel/base/include/los_sched_pri.h | 16 +++++++++---- src/kernel/base/include/los_sem_debug_pri.h | 7 +++++- src/kernel/base/include/los_sem_pri.h | 15 ++++++++---- src/kernel/base/include/los_slab_pri.h | 18 +++++++-------- src/kernel/base/include/los_sortlink_pri.h | 10 +++++--- src/kernel/base/include/los_stackinfo_pri.h | 19 +++++++++------ src/kernel/base/include/los_swtmr_pri.h | 17 ++++++++++---- src/kernel/base/include/los_task_pri.h | 3 ++- src/kernel/base/include/los_tick_pri.h | 13 ++++++++++- 19 files changed, 159 insertions(+), 75 deletions(-) diff --git a/src/kernel/base/include/los_membox_pri.h b/src/kernel/base/include/los_membox_pri.h index 6b64895..c7def84 100644 --- a/src/kernel/base/include/los_membox_pri.h +++ b/src/kernel/base/include/los_membox_pri.h @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +//这个头文件的作用是定义了与内存池相关的私有函数和数据结构。 #ifndef _LOS_MEMBOX_PRI_H #define _LOS_MEMBOX_PRI_H diff --git a/src/kernel/base/include/los_multipledlinkhead_pri.h b/src/kernel/base/include/los_multipledlinkhead_pri.h index 98461e2..f8c3880 100644 --- a/src/kernel/base/include/los_multipledlinkhead_pri.h +++ b/src/kernel/base/include/los_multipledlinkhead_pri.h @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ -//定义了一个多重双向链表头的私有接口和数据结构。 +//这个头文件定义了一个多重双向链表头的私有接口和数据结构。 #ifndef _LOS_MULTIPLE_DLINK_HEAD_PRI_H #define _LOS_MULTIPLE_DLINK_HEAD_PRI_H diff --git a/src/kernel/base/include/los_mux_debug_pri.h b/src/kernel/base/include/los_mux_debug_pri.h index 30e49dd..6aabee6 100644 --- a/src/kernel/base/include/los_mux_debug_pri.h +++ b/src/kernel/base/include/los_mux_debug_pri.h @@ -26,6 +26,9 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ +/*这个头文件定义了一些用于互斥锁(mutex)调试的接口和函数,包括死锁检测、互斥锁状态跟踪、互斥锁泄漏检查等。 + 这些接口和函数主要用于开发人员在调试过程中分析互斥锁的使用情况,帮助找出潜在的问题并解决它们。*/ + #ifndef _LOS_MUX_DEBUG_PRI_H #define _LOS_MUX_DEBUG_PRI_H @@ -35,7 +38,7 @@ extern "C" { #endif /* __cplusplus */ #endif /* __cplusplus */ - +//初始化死锁检测机制 /* Deadlock detection initialization interface */ extern UINT32 OsMuxDlockCheckInit(VOID); STATIC INLINE UINT32 OsMuxDlockCheckInitHook(VOID) @@ -46,7 +49,7 @@ STATIC INLINE UINT32 OsMuxDlockCheckInitHook(VOID) return LOS_OK; #endif } - +//向死锁检测机制中添加任务持有的互斥锁信息 /* Add holding mutex lock node information */ extern VOID OsMuxDlockNodeInsert(UINT32 taskId, VOID *muxCB); STATIC INLINE VOID OsMuxDlockNodeInsertHook(UINT32 taskId, VOID *muxCB) @@ -55,6 +58,7 @@ STATIC INLINE VOID OsMuxDlockNodeInsertHook(UINT32 taskId, VOID *muxCB) OsMuxDlockNodeInsert(taskId, muxCB); #endif } +//从死锁检测机制中删除任务持有的互斥锁信息 /* Delete holding mutex lock node information */ extern VOID OsMuxDlockNodeDelete(UINT32 taskId, const VOID *muxCB); STATIC INLINE VOID OsMuxDlockNodeDeleteHook(UINT32 taskId, const VOID *muxCB) @@ -63,6 +67,7 @@ STATIC INLINE VOID OsMuxDlockNodeDeleteHook(UINT32 taskId, const VOID *muxCB) OsMuxDlockNodeDelete(taskId, muxCB); #endif } +//更新任务最后执行的时间 /* Update the last time the task was executed */ extern VOID OsTaskTimeUpdate(UINT32 taskId, UINT64 tickCount); STATIC INLINE VOID OsTaskTimeUpdateHook(UINT32 taskId, UINT64 tickCount) @@ -71,7 +76,7 @@ STATIC INLINE VOID OsTaskTimeUpdateHook(UINT32 taskId, UINT64 tickCount) OsTaskTimeUpdate(taskId, tickCount); #endif } - +//初始化互斥锁状态跟踪机制 /* mutex debug initialization interface */ extern UINT32 OsMuxDbgInit(VOID); STATIC INLINE UINT32 OsMuxDbgInitHook(VOID) @@ -82,6 +87,7 @@ STATIC INLINE UINT32 OsMuxDbgInitHook(VOID) return LOS_OK; #endif } +//更新互斥锁最后执行的时间 /* Update the last time the mutex was executed */ extern VOID OsMuxDbgTimeUpdate(UINT32 muxId); STATIC INLINE VOID OsMuxDbgTimeUpdateHook(UINT32 muxId) @@ -90,6 +96,7 @@ STATIC INLINE VOID OsMuxDbgTimeUpdateHook(UINT32 muxId) OsMuxDbgTimeUpdate(muxId); #endif } +//在创建或删除互斥锁时更新互斥锁的状态跟踪信息 /* Update the MUX_DEBUG_CB of the mutex when created or deleted */ extern VOID OsMuxDbgUpdate(UINT32 muxID, TSK_ENTRY_FUNC creator); STATIC INLINE VOID OsMuxDbgUpdateHook(UINT32 muxId, TSK_ENTRY_FUNC creator) @@ -98,6 +105,7 @@ STATIC INLINE VOID OsMuxDbgUpdateHook(UINT32 muxId, TSK_ENTRY_FUNC creator) OsMuxDbgUpdate(muxId, creator); #endif } +//检查互斥锁是否泄漏 /* check the leak of mutex */ extern VOID OsMutexCheck(VOID); STATIC INLINE VOID OsMutexCheckHook(VOID) diff --git a/src/kernel/base/include/los_mux_pri.h b/src/kernel/base/include/los_mux_pri.h index c2ffb83..0361b35 100644 --- a/src/kernel/base/include/los_mux_pri.h +++ b/src/kernel/base/include/los_mux_pri.h @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +//一个关于互斥锁的内部实现的头文件 #ifndef _LOS_MUX_PRI_H #define _LOS_MUX_PRI_H @@ -45,12 +45,13 @@ extern "C" { * Mutex base object must be the same as the first three member names of LosMuxCB, * so that pthread_mutex_t can share the kernel mutex mechanism. */ +//这是互斥锁的基本控制块,包含了互斥锁的一些基本信息 typedef struct { - LOS_DL_LIST muxList; /* Mutex linked list */ - LosTaskCB *owner; /* The current thread that is locking a mutex */ - UINT16 muxCount; /* Times of locking a mutex */ + LOS_DL_LIST muxList;//连接列表 /* Mutex linked list */ + LosTaskCB *owner; //互斥锁的拥有者 /* The current thread that is locking a mutex */ + UINT16 muxCount; //被锁定的次数 /* Times of locking a mutex */ } MuxBaseCB; - +//这是互斥锁的控制块,包含了更多的互斥锁信息 typedef struct { LOS_DL_LIST muxList; /* Mutex linked list */ LosTaskCB *owner; /* The current thread that is locking a mutex */ @@ -60,21 +61,29 @@ typedef struct { } LosMuxCB; /* Mutex global array address, which can be obtained by using a handle ID. */ +//全局变量:这是一个互斥锁的全局数组地址,可以通过互斥锁的 ID 来获取对应的互斥锁对象。 extern LosMuxCB *g_allMux; /* COUNT | INDEX split bit */ #define MUX_SPLIT_BIT 16 /* Set the mutex id */ +//设置互斥锁的 ID #define SET_MUX_ID(count, muxId) (((count) << MUX_SPLIT_BIT) | (muxId)) +//根据互斥锁的 ID 获取索引 #define GET_MUX_INDEX(muxId) ((muxId) & ((1U << MUX_SPLIT_BIT) - 1)) +//根据互斥锁的 ID 获取计数值 #define GET_MUX_COUNT(muxId) ((muxId) >> MUX_SPLIT_BIT) /* Obtain the pointer to a mutex object of the mutex that has a specified handle. */ +//根据互斥锁的 ID 获取对应的互斥锁对象指针 #define GET_MUX(muxId) (((LosMuxCB *)g_allMux) + GET_MUX_INDEX(muxId)) +//初始化互斥锁 extern UINT32 OsMuxInit(VOID); +//执行互斥锁的等待操作 extern UINT32 OsMuxPendOp(LosTaskCB *runTask, MuxBaseCB *muxPended, UINT32 timeout, UINT32 *intSave); +//执行互斥锁的释放操作 extern UINT32 OsMuxPostOp(LosTaskCB *runTask, MuxBaseCB *muxPosted); #ifdef __cplusplus #if __cplusplus diff --git a/src/kernel/base/include/los_percpu_pri.h b/src/kernel/base/include/los_percpu_pri.h index bc8f0fa..340ed0f 100644 --- a/src/kernel/base/include/los_percpu_pri.h +++ b/src/kernel/base/include/los_percpu_pri.h @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +//这个头文件定义了关于每个CPU的私有数据结构,这个结构体存储了与每个 CPU 相关的一些信息。 #ifndef _LOS_PERCPU_PRI_H #define _LOS_PERCPU_PRI_H @@ -47,35 +47,34 @@ typedef enum { CPU_EXC /* cpu in the exc */ } ExcFlag; #endif - +//排序链表的属性结构体,用于表示任务链表和软件定时器链表 typedef struct { SortLinkAttribute taskSortLink; /* task sort link */ #ifdef LOSCFG_BASE_CORE_SWTMR SortLinkAttribute swtmrSortLink; /* swtmr sort link */ #endif - UINT32 idleTaskId; /* idle task id */ - UINT32 taskLockCnt; /* task lock flag */ - UINT32 swtmrHandlerQueue; /* software timer timeout queue id */ - UINT32 swtmrTaskId; /* software timer task id */ - - UINT32 schedFlag; /* pending scheduler flag */ + UINT32 idleTaskId;//空闲任务的任务 ID /* idle task id */ + UINT32 taskLockCnt;//任务锁计数,用于标记任务是否被锁定 /* task lock flag */ + UINT32 swtmrHandlerQueue;//软件定时器的超时队列 ID /* software timer timeout queue id */ + UINT32 swtmrTaskId;//软件定时器任务的 ID /* software timer task id */ + UINT32 schedFlag;//调度标志,用于表示是否需要进行调度 /* pending scheduler flag */ #ifdef LOSCFG_KERNEL_SMP - UINT32 excFlag; /* cpu halt or exc flag */ + UINT32 excFlag;//CPU 异常标志,用于表示 CPU 的运行状态,包括运行、休眠和异常状态 /* cpu halt or exc flag */ #ifdef LOSCFG_KERNEL_SMP_CALL - LOS_DL_LIST funcLink; /* mp function call link */ + LOS_DL_LIST funcLink;//多处理器函数调用链表,用于多处理器间的函数调用 /* mp function call link */ #endif #endif } Percpu; /* the kernel per-cpu structure */ extern Percpu g_percpu[LOSCFG_KERNEL_CORE_NUM]; - +//用于获取当前CPU STATIC INLINE Percpu *OsPercpuGet(VOID) { return &g_percpu[ArchCurrCpuid()]; } - +//用于获取指定CPU的Percpu结构体指针 STATIC INLINE Percpu *OsPercpuGetByID(UINT32 cpuid) { return &g_percpu[cpuid]; diff --git a/src/kernel/base/include/los_printf_pri.h b/src/kernel/base/include/los_printf_pri.h index b150765..0dd3b03 100644 --- a/src/kernel/base/include/los_printf_pri.h +++ b/src/kernel/base/include/los_printf_pri.h @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +//关于打印函数的私有头文件 #ifndef _LOS_PRINTF_PRI_H #define _LOS_PRINTF_PRI_H @@ -36,13 +36,16 @@ extern "C" { #endif /* __cplusplus */ #endif /* __cplusplus */ - +//在控制台上打印格式化字符串 extern VOID ConsoleVprintf(const CHAR *fmt, va_list ap); +//在串口上打印格式化字符串 extern VOID UartVprintf(const CHAR *fmt, va_list ap); +//打印异常信息 extern VOID PrintExcInfo(const CHAR *fmt, ...); - +//打印内核调试信息 extern VOID LkDprintf(const CHAR *fmt, va_list ap); #ifdef LOSCFG_SHELL_DMESG +//打印系统日志信息 extern VOID DmesgPrintf(const CHAR *fmt, va_list ap); #endif diff --git a/src/kernel/base/include/los_priqueue_pri.h b/src/kernel/base/include/los_priqueue_pri.h index 79cd22d..eecc647 100644 --- a/src/kernel/base/include/los_priqueue_pri.h +++ b/src/kernel/base/include/los_priqueue_pri.h @@ -25,7 +25,8 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +/*这个头文件定义了优先级队列的相关操作函数, +包括初始化优先级队列、插入项目到优先级队列、从优先级队列中删除项目、获取具有最高优先级的项目等*/ #ifndef _LOS_PRIQUEUE_PRI_H #define _LOS_PRIQUEUE_PRI_H @@ -57,6 +58,7 @@ extern "C" { * @see none. * @since Huawei LiteOS V100R001C00 */ +//初始化优先级队列 extern UINT32 OsPriQueueInit(VOID); /** @@ -79,6 +81,7 @@ extern UINT32 OsPriQueueInit(VOID); * @see OsPriQueueDequeue. * @since Huawei LiteOS V100R001C00 */ +//根据项目的优先级将项目插入到优先级队列中 extern VOID OsPriQueueEnqueue(LOS_DL_LIST *priqueueItem, UINT32 priority); /** @@ -99,6 +102,7 @@ extern VOID OsPriQueueEnqueue(LOS_DL_LIST *priqueueItem, UINT32 priority); * @see OsPriQueueEnqueue. * @since Huawei LiteOS V100R001C00 */ +//从优先级队列中删除一个项目 extern VOID OsPriQueueDequeue(LOS_DL_LIST *priqueueItem); /** @@ -120,6 +124,7 @@ extern VOID OsPriQueueDequeue(LOS_DL_LIST *priqueueItem); * @see none. * @since Huawei LiteOS V100R001C00 */ +//获取优先级队列中具有最高优先级的项目 extern LOS_DL_LIST *OsPriQueueTop(VOID); /** @@ -140,6 +145,7 @@ extern LOS_DL_LIST *OsPriQueueTop(VOID); * @see none. * @since Huawei LiteOS V100R001C00 */ +//获取具有指定优先级的项目数量 extern UINT32 OsPriQueueSize(UINT32 priority); /** @@ -159,6 +165,7 @@ extern UINT32 OsPriQueueSize(UINT32 priority); * @see none. * @since Huawei LiteOS V100R001C00 */ +//获取优先级队列中项目的总数 extern UINT32 OsPriQueueTotalSize(VOID); /** @@ -181,6 +188,7 @@ extern UINT32 OsPriQueueTotalSize(VOID); * @see OsPriQueueDequeue. * @since Huawei LiteOS V100R001C00 */ +//根据项目的优先级将项目插入到优先级队列的头部 extern VOID OsPriQueueEnqueueHead(LOS_DL_LIST *priqueueItem, UINT32 priority); #ifdef __cplusplus diff --git a/src/kernel/base/include/los_queue_debug_pri.h b/src/kernel/base/include/los_queue_debug_pri.h index 4186e09..806239a 100644 --- a/src/kernel/base/include/los_queue_debug_pri.h +++ b/src/kernel/base/include/los_queue_debug_pri.h @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +//这个头文件提供了针对队列调试的相关函数声明 #ifndef _LOS_QUEUE_DEBUG_PRI_H #define _LOS_QUEUE_DEBUG_PRI_H @@ -40,7 +40,9 @@ extern "C" { #endif /* __cplusplus */ /* queue debug initialization interface */ +//队列调试初始化接口 extern UINT32 OsQueueDbgInit(VOID); +//队列调试初始化的钩子函数,根据配置是否开启队列调试功能来调用OsQueueDbgInit STATIC INLINE UINT32 OsQueueDbgInitHook(VOID) { #ifdef LOSCFG_DEBUG_QUEUE @@ -50,7 +52,9 @@ STATIC INLINE UINT32 OsQueueDbgInitHook(VOID) #endif } /* Update the last time the queue was executed */ +//更新队列上次执行的时间 extern VOID OsQueueDbgTimeUpdate(UINT32 queueId); +//更新队列执行时间的钩子函数 STATIC INLINE VOID OsQueueDbgTimeUpdateHook(UINT32 queueId) { #ifdef LOSCFG_DEBUG_QUEUE @@ -58,7 +62,9 @@ STATIC INLINE VOID OsQueueDbgTimeUpdateHook(UINT32 queueId) #endif } /* Update the task entry of the queue debug info when created or deleted */ +//当队列被创建或删除时,更新队列调试信息中的任务入口信息 extern VOID OsQueueDbgUpdate(UINT32 queueId, TSK_ENTRY_FUNC entry); +//新队列调试信息的钩子函数 STATIC INLINE VOID OsQueueDbgUpdateHook(UINT32 queueId, TSK_ENTRY_FUNC entry) { #ifdef LOSCFG_DEBUG_QUEUE @@ -66,7 +72,9 @@ STATIC INLINE VOID OsQueueDbgUpdateHook(UINT32 queueId, TSK_ENTRY_FUNC entry) #endif } /* check the leak of queue */ +//检查队列内存泄漏 extern VOID OsQueueCheck(VOID); +//检查队列内存泄漏的钩子函数 STATIC INLINE VOID OsQueueCheckHook(VOID) { #ifdef LOSCFG_DEBUG_QUEUE diff --git a/src/kernel/base/include/los_queue_pri.h b/src/kernel/base/include/los_queue_pri.h index 8f1674a..5a5b13a 100644 --- a/src/kernel/base/include/los_queue_pri.h +++ b/src/kernel/base/include/los_queue_pri.h @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +//这个头文件定义了私有队列相关的一些结构体、宏和函数声明 #ifndef _LOS_QUEUE_PRI_H #define _LOS_QUEUE_PRI_H @@ -42,12 +42,12 @@ typedef enum { OS_QUEUE_WRITE = 1, OS_QUEUE_N_RW = 2 } QueueReadWrite; - +//枚举类型,分别表示队列的读写操作和队列头尾操作 typedef enum { OS_QUEUE_HEAD = 0, OS_QUEUE_TAIL = 1 } QueueHeadTail; - +//用于生成或获取队列操作类型和读写类型 #define OS_QUEUE_OPERATE_TYPE(ReadOrWrite, HeadOrTail) (((UINT32)(HeadOrTail) << 1) | (ReadOrWrite)) #define OS_QUEUE_READ_WRITE_GET(type) ((type) & 0x01U) #define OS_QUEUE_READ_HEAD (OS_QUEUE_READ | (OS_QUEUE_HEAD << 1)) @@ -73,6 +73,7 @@ typedef enum { #define GET_QUEUE_LIST(ptr) LOS_DL_LIST_ENTRY(ptr, LosQueueCB, readWriteList[OS_QUEUE_WRITE]) /* Queue information block structure */ +//队列信息块结构体,包含了队列的各种属性和状态信息 typedef struct { UINT8 *queueHandle; /* Pointer to a queue handle */ UINT8 queueState; /* state */ @@ -88,12 +89,16 @@ typedef struct { } LosQueueCB; /* Queue information control block */ +//全局变量,指向所有队列信息块的起始地址 extern LosQueueCB *g_allQueue; /* alloc a stationary memory for a mail according to queueId */ +//用于在指定的内存池中为邮件分配内存 extern VOID *OsQueueMailAlloc(UINT32 queueId, VOID *mailPool, UINT32 timeout); /* free a stationary memory for a mail according to queueId. */ +//释放邮件占用的内存 extern UINT32 OsQueueMailFree(UINT32 queueId, VOID *mailPool, VOID *mailMem); +//列初始化函数,用于初始化队列池 extern UINT32 OsQueueInit(VOID); #ifdef __cplusplus diff --git a/src/kernel/base/include/los_sched_debug_pri.h b/src/kernel/base/include/los_sched_debug_pri.h index 7e28ae5..2188c24 100644 --- a/src/kernel/base/include/los_sched_debug_pri.h +++ b/src/kernel/base/include/los_sched_debug_pri.h @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +//这个头文件定义了调度器相关的一些结构体和函数声明 #ifndef __LOS_SCHED_DEBUG_PRI_H #define __LOS_SCHED_DEBUG_PRI_H @@ -34,19 +34,19 @@ extern "C" { #endif /* __cplusplus */ #endif /* __cplusplus */ - +//表示单个CPU的运行时间和上下文切换次数 typedef struct { UINT64 runtime; UINT32 contexSwitch; } SchedPercpu; - +//表示整个系统的调度统计信息 typedef struct { - UINT64 startRuntime; - UINT64 allRuntime; - UINT32 allContextSwitch; - SchedPercpu schedPercpu[LOSCFG_KERNEL_CORE_NUM]; + UINT64 startRuntime;//开始运行的时间 + UINT64 allRuntime;//所有CPU的总共运行时间 + UINT32 allContextSwitch;//上下文切换次数 + SchedPercpu schedPercpu[LOSCFG_KERNEL_CORE_NUM];//每个CPU的具体情况 } SchedStat; - +//用于统计中断处理的时间和次数 extern VOID OsHwiStatistics(size_t intNum); #ifdef __cplusplus diff --git a/src/kernel/base/include/los_sched_pri.h b/src/kernel/base/include/los_sched_pri.h index e5ae61d..5ea0138 100644 --- a/src/kernel/base/include/los_sched_pri.h +++ b/src/kernel/base/include/los_sched_pri.h @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +//这个头文件定义了调度器相关的一些结构体和函数声明 #ifndef _LOS_SCHED_PRI_H #define _LOS_SCHED_PRI_H @@ -37,21 +37,22 @@ extern "C" { #endif /* __cplusplus */ #endif /* __cplusplus */ - +//表示任务调度标志位,每个位代表一个核心,用于防止在OSStartToRun之前进行内核调度 extern UINT32 g_taskScheduled; /* * Schedule flag, one bit represents one core. * This flag is used to prevent kernel scheduling before OSStartToRun. */ +//设置对应核心的调度标志位 #define OS_SCHEDULER_SET(cpuid) do { \ g_taskScheduled |= (1U << (cpuid)); \ } while (0); - +//清除对应核心的调度标志位 #define OS_SCHEDULER_CLR(cpuid) do { \ g_taskScheduled &= ~(1U << (cpuid)); \ } while (0); - +//判断当前核心的调度标志位是否激活 #define OS_SCHEDULER_ACTIVE (g_taskScheduled & (1U << ArchCurrCpuid())) typedef enum { @@ -60,6 +61,7 @@ typedef enum { } SchedFlag; /* Check if preemptable with counter flag */ +//用于判断当前任务是否可以被抢占 STATIC INLINE BOOL OsPreemptable(VOID) { /* @@ -76,7 +78,7 @@ STATIC INLINE BOOL OsPreemptable(VOID) LOS_IntRestore(intSave); return preemptable; } - +//用于判断当前任务是否可以在调度过程中被抢占 STATIC INLINE BOOL OsPreemptableInSched(VOID) { BOOL preemptable = FALSE; @@ -104,6 +106,7 @@ STATIC INLINE BOOL OsPreemptableInSched(VOID) * Current task needs to already be in the right state or the right * queues it needs to be in. */ +//选择下一个任务并切换到它 extern VOID OsSchedResched(VOID); /* @@ -111,12 +114,14 @@ extern VOID OsSchedResched(VOID); * try to do the schedule. However, the schedule won't be definitely * taken place while there're no other higher priority tasks or locked. */ +//将当前任务放回就绪队列,并尝试进行调度 extern VOID OsSchedPreempt(VOID); /* * Just like OsSchedPreempt, except this function will do the OS_INT_ACTIVE * check, in case the schedule taken place in the middle of an interrupt. */ +//触发调度,如果在中断中则设置调度标志位 STATIC INLINE VOID LOS_Schedule(VOID) { if (OS_INT_ACTIVE) { @@ -138,6 +143,7 @@ STATIC INLINE VOID LOS_Schedule(VOID) * This API is used to check time slices. If the number of Ticks equals to the time for task switch, * tasks are switched. Otherwise, the Tick counting continues. */ +//检查时间片,如果满足任务切换的条件则进行切换 extern VOID OsTimesliceCheck(VOID); #endif diff --git a/src/kernel/base/include/los_sem_debug_pri.h b/src/kernel/base/include/los_sem_debug_pri.h index 2b43684..8b8a7e1 100644 --- a/src/kernel/base/include/los_sem_debug_pri.h +++ b/src/kernel/base/include/los_sem_debug_pri.h @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +//这个头文件定义了一些用于调试信号量的接口和函数声明 #ifndef _LOS_SEM_DEBUG_PRI_H #define _LOS_SEM_DEBUG_PRI_H @@ -39,7 +39,9 @@ extern "C" { #endif /* __cplusplus */ /* semaphore debug initialization interface */ +//信号量调试初始化接口 extern UINT32 OsSemDbgInit(VOID); +//更新信号量最后一次执行的时间 STATIC INLINE UINT32 OsSemDbgInitHook(VOID) { #ifdef LOSCFG_DEBUG_SEMAPHORE @@ -49,6 +51,7 @@ STATIC INLINE UINT32 OsSemDbgInitHook(VOID) #endif } /* Update the last time the semaphore was executed */ +//更新信号量最后一次执行的时间 extern VOID OsSemDbgTimeUpdate(UINT32 semId); STATIC INLINE VOID OsSemDbgTimeUpdateHook(UINT32 semId) { @@ -58,6 +61,7 @@ STATIC INLINE VOID OsSemDbgTimeUpdateHook(UINT32 semId) return; } /* Update the SEM_DEBUG_CB of the semaphore when created or deleted */ +//在创建或删除信号量时更新SEM_DEBUG_CB的信息 extern VOID OsSemDbgUpdate(UINT32 semID, TSK_ENTRY_FUNC creator, UINT16 count); STATIC INLINE VOID OsSemDbgUpdateHook(UINT32 semId, TSK_ENTRY_FUNC creator, UINT16 count) { @@ -67,6 +71,7 @@ STATIC INLINE VOID OsSemDbgUpdateHook(UINT32 semId, TSK_ENTRY_FUNC creator, UINT return; } /* get the full data of SEM_DFX_CB */ +//取SEM_DFX_CB的完整数据 extern UINT32 OsSemInfoGetFullData(VOID); STATIC INLINE VOID OsSemInfoGetFullDataHook(VOID) { diff --git a/src/kernel/base/include/los_sem_pri.h b/src/kernel/base/include/los_sem_pri.h index de3a5bb..ba40aec 100644 --- a/src/kernel/base/include/los_sem_pri.h +++ b/src/kernel/base/include/los_sem_pri.h @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +//这个头文件定义了一些关于信号量的数据结构和函数声明,用于信号量的控制和管理。 #ifndef _LOS_SEM_PRI_H #define _LOS_SEM_PRI_H @@ -38,24 +38,28 @@ extern "C" { #endif /* __cplusplus */ /* Semaphore control structure. */ +//信号量控制块的数据结构 typedef struct { - UINT8 semStat; /* Semaphore state, enum LosSemState */ - UINT8 semType; /* Semaphore Type, enum LosSemType */ - UINT16 semCount; /* number of available semaphores */ - UINT32 semId; /* Semaphore control structure ID, COUNT(UINT16)|INDEX(UINT16) */ + UINT8 semStat;//信号量的状态 /* Semaphore state, enum LosSemState */ + UINT8 semType;//信号量的类型 /* Semaphore Type, enum LosSemType */ + UINT16 semCount;//信号量可用数量 /* number of available semaphores */ + UINT32 semId;//信号量ID /* Semaphore control structure ID, COUNT(UINT16)|INDEX(UINT16) */ LOS_DL_LIST semList; /* List of tasks that are waiting on a semaphore */ } LosSemCB; /* Semaphore type */ +//信号量类型的枚举值:包括计数信号量和二进制信号量 enum { OS_SEM_COUNTING, /* The semaphore is a counting semaphore which max count is LOS_SEM_COUNT_MAX */ OS_SEM_BINARY, /* The semaphore is a binary semaphore which max count is OS_SEM_BINARY_COUNT_MAX */ }; /* Max count of binary semaphores */ +//二进制信号量的最大计数值 #define OS_SEM_BINARY_COUNT_MAX 1 /* Semaphore information control block */ +//信号量信息控制块的全局指针 extern LosSemCB *g_allSem; #define GET_SEM_LIST(ptr) LOS_DL_LIST_ENTRY(ptr, LosSemCB, semList) @@ -75,6 +79,7 @@ extern LosSemCB *g_allSem; /* This API is used to create a semaphore control structure according to the initial number of available semaphores * specified by count and return the ID of this semaphore control structure. */ +用于根据初始可用信号量的数量创建信号量控制结构的函数 extern UINT32 OsSemInit(VOID); #ifdef __cplusplus diff --git a/src/kernel/base/include/los_slab_pri.h b/src/kernel/base/include/los_slab_pri.h index 24c8b94..e7c37e7 100644 --- a/src/kernel/base/include/los_slab_pri.h +++ b/src/kernel/base/include/los_slab_pri.h @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +//这个头文件是操作系统中关于 Slab 内存分配的底层实现和接口声明 /** * @defgroup los_slab Slab * @ingroup kernel @@ -53,7 +53,7 @@ extern "C" { /* max slab block size */ #define SLAB_MEM_MAX_SIZE (SLAB_MEM_CALSS_STEP_SIZE << (SLAB_MEM_COUNT - 1)) - +//描述 Slab 内存分配器状态的结构体 typedef struct tagLosSlabStatus { UINT32 totalSize; UINT32 usedSize; @@ -61,13 +61,13 @@ typedef struct tagLosSlabStatus { UINT32 allocCount; UINT32 freeCount; } LosSlabStatus; - +//Slab 块的节点结构体 typedef struct tagOsSlabBlockNode { UINT16 magic; UINT8 blkSz; UINT8 recordId; } OsSlabBlockNode; - +//原子位图结构体,用于表示 Slab 内存分配器中的位图 struct AtomicBitset { UINT32 numBits; UINT32 words[0]; @@ -144,25 +144,25 @@ extern UINT32 OsSlabGetMaxFreeBlkSize(const VOID *pool); extern VOID *OsSlabCtrlHdrGet(const VOID *pool); #else /* !LOSCFG_KERNEL_MEM_SLAB_EXTENTION */ - +//初始化 Slab 内存池 STATIC INLINE VOID OsSlabMemInit(VOID *pool, UINT32 size) { } - +//销毁 Slab 内存池 STATIC INLINE VOID OsSlabMemDeinit(VOID *pool) { } - +//从 Slab 内存池中分配内存 STATIC INLINE VOID *OsSlabMemAlloc(VOID *pool, UINT32 size) { return NULL; } - +//释放 Slab 内存池中的内存 STATIC INLINE BOOL OsSlabMemFree(VOID *pool, VOID *ptr) { return FALSE; } - +//检查指针是否属于 Slab 内存池 STATIC INLINE UINT32 OsSlabMemCheck(const VOID *pool, const VOID *ptr) { return (UINT32)-1; diff --git a/src/kernel/base/include/los_sortlink_pri.h b/src/kernel/base/include/los_sortlink_pri.h index 6faeaeb..1f2b66a 100644 --- a/src/kernel/base/include/los_sortlink_pri.h +++ b/src/kernel/base/include/los_sortlink_pri.h @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +//一个用于操作排序链表(SortLink)的私有头文件。 #ifndef _LOS_SORTLINK_PRI_H #define _LOS_SORTLINK_PRI_H @@ -118,13 +118,17 @@ typedef struct { UINT16 cursor; UINT16 reserved; } SortLinkAttribute; - +//初始化排序链表 extern UINT32 OsSortLinkInit(SortLinkAttribute *sortLinkHeader); +//一个节点添加到排序链表中 extern VOID OsAdd2SortLink(const SortLinkAttribute *sortLinkHeader, SortLinkList *sortList); +//从排序链表中删除一个节点 extern VOID OsDeleteSortLink(const SortLinkAttribute *sortLinkHeader, SortLinkList *sortList); +//获取下一个到期时间 extern UINT32 OsSortLinkGetNextExpireTime(const SortLinkAttribute *sortLinkHeader); +//获取目标节点的到期时间 extern UINT32 OsSortLinkGetTargetExpireTime(const SortLinkAttribute *sortLinkHeader, - const SortLinkList *targetSortList); +//更新到期时间 const SortLinkList *targetSortList); extern VOID OsSortLinkUpdateExpireTime(UINT32 sleepTicks, SortLinkAttribute *sortLinkHeader); #ifdef __cplusplus diff --git a/src/kernel/base/include/los_stackinfo_pri.h b/src/kernel/base/include/los_stackinfo_pri.h index 4d9c9ae..0642106 100644 --- a/src/kernel/base/include/los_stackinfo_pri.h +++ b/src/kernel/base/include/los_stackinfo_pri.h @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +//一个用于处理堆栈信息的私有头文件 #ifndef _LOS_STACK_INFO_PRI_H #define _LOS_STACK_INFO_PRI_H @@ -37,20 +37,25 @@ extern "C" { #endif /* __cplusplus */ #endif /* __cplusplus */ - +//堆栈信息结构体 typedef struct { - VOID *stackTop; - UINT32 stackSize; - CHAR *stackName; + VOID *stackTop;//堆栈的顶部 + UINT32 stackSize;//堆栈的大小 + CHAR *stackName;//堆栈的名称 } StackInfo; - +//表示无效的水位线值 #define OS_INVALID_WATERLINE 0xFFFFFFFF +//于检查堆栈顶部的魔术字是否有效的宏定义 #define OS_STACK_MAGIC_CHECK(topstack) (*(UINTPTR *)(topstack) == OS_STACK_MAGIC_WORD) /* 1:magic valid 0:unvalid */ - +//用于异常时获取堆栈信息的函数 extern VOID OsExcStackInfo(VOID); +//用于注册异常时获取的堆栈信息的函数 extern VOID OsExcStackInfoReg(const StackInfo *stackInfo, UINT32 stackNum); +//用于初始化堆栈的函数 extern VOID OsStackInit(VOID *stacktop, UINT32 stacksize); +//用于获取堆栈的水位线和使用峰值的函数 extern UINT32 OsStackWaterLineGet(const UINTPTR *stackBottom, const UINTPTR *stackTop, UINT32 *peakUsed); +//用于获取堆栈信息的函数 extern VOID OsGetStackInfo(const StackInfo **stackInfo, UINT32 *stackNum); #ifdef __cplusplus diff --git a/src/kernel/base/include/los_swtmr_pri.h b/src/kernel/base/include/los_swtmr_pri.h index 39f64a3..791e096 100644 --- a/src/kernel/base/include/los_swtmr_pri.h +++ b/src/kernel/base/include/los_swtmr_pri.h @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +//一个用于实现软件定时器的私有头文件。 #ifndef _LOS_SWTMR_PRI_H #define _LOS_SWTMR_PRI_H @@ -40,7 +40,7 @@ extern "C" { #endif /* __cplusplus */ #ifdef LOSCFG_BASE_CORE_SWTMR - +//软件定时器的状态枚举,包括未使用、已创建和计时中 enum SwtmrState { OS_SWTMR_STATUS_UNUSED, /* The software timer is not used. */ OS_SWTMR_STATUS_CREATED, /* The software timer is created. */ @@ -48,12 +48,13 @@ enum SwtmrState { }; /* Structure of the callback function that handles software timer timeout */ +//处理软件定时器超时回调的回调函数结构体 typedef struct { SWTMR_PROC_FUNC handler; /* Callback function that handles software timer timeout */ UINTPTR arg; /* Parameter passed in when the callback function that handles software timer timeout is called */ } SwtmrHandlerItem; - +//软件定时器控制块结构体 typedef struct { SortLinkList sortList; UINT8 state; /* Software timer state */ @@ -71,22 +72,28 @@ typedef struct { } LosSwtmrCB; /* Type of the pointer to the structure of the callback function that handles software timer timeout */ +//指向处理软件定时器超时回调的回调函数结构体的指针类型 typedef SwtmrHandlerItem *SwtmrHandlerItemPtr; - +//软件定时器控制块数组 extern LosSwtmrCB *g_swtmrCBArray; /* The software timer count list */ +//软件定时器排序链表 extern SortLinkAttribute g_swtmrSortLink; - #define OS_SWT_FROM_SWTID(swtmrId) ((LosSwtmrCB *)g_swtmrCBArray + ((swtmrId) % KERNEL_SWTMR_LIMIT)) /* This API is used to scan a software timer when a Tick interrupt occurs and determine whether * the software timer expires. */ +//在Tick中断发生时扫描软件定时器,判断是否到达超时时间 extern VOID OsSwtmrScan(VOID); +//初始化软件定时器 extern UINT32 OsSwtmrInit(VOID); +//软件定时器任务,用于处理软件定时器的超时事件 extern VOID OsSwtmrTask(VOID); +//软件定时器自旋锁 extern SPIN_LOCK_S g_swtmrSpin; #ifdef LOSCFG_EXC_INTERACTION +//判断当前任务是否为软件定时器任务 extern BOOL IsSwtmrTask(UINT32 taskId); #endif #endif /* LOSCFG_BASE_CORE_SWTMR */ diff --git a/src/kernel/base/include/los_task_pri.h b/src/kernel/base/include/los_task_pri.h index 4dab9bb..e755763 100644 --- a/src/kernel/base/include/los_task_pri.h +++ b/src/kernel/base/include/los_task_pri.h @@ -25,7 +25,8 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +/*这是关于LiteOS中任务调度相关的头文件,其中定义了任务控制块的数据结构和一些任务管理的接口函数。 +在这个头文件中,定义了任务的状态、优先级、标志位等信息,并提供了一些操作这些信息的宏和函数。*/ #ifndef _LOS_TASK_PRI_H #define _LOS_TASK_PRI_H diff --git a/src/kernel/base/include/los_tick_pri.h b/src/kernel/base/include/los_tick_pri.h index 5e67cef..5019d05 100644 --- a/src/kernel/base/include/los_tick_pri.h +++ b/src/kernel/base/include/los_tick_pri.h @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +//这个头文件是关于系统时钟中断tick的定义和操作。 #ifndef _LOS_TICK_PRI_H #define _LOS_TICK_PRI_H @@ -40,30 +40,41 @@ extern "C" { #endif /* __cplusplus */ /* spinlock for tick */ +//用于保护tick相关操作的自旋锁 extern SPIN_LOCK_S g_tickSpin; +//获取tick自旋锁并保存状态 #define TICK_LOCK(state) LOS_SpinLockSave(&g_tickSpin, &(state)) +//释放tick自旋锁并恢复状态 #define TICK_UNLOCK(state) LOS_SpinUnlockRestore(&g_tickSpin, (state)) /* Count of Ticks */ +//全局变量,保存系统tick的计数值 extern volatile UINT64 g_tickCount[]; /* Cycle to nanosecond scale */ +//循环周期到纳秒的转换比例 extern DOUBLE g_cycle2NsScale; /* This API is called when the system tick timeout and triggers the interrupt. */ +//系统tick中断处理函数,当系统tick超时触发中断时调用 extern VOID OsTickHandler(VOID); +//初始化系统tick相关配置 extern UINT32 OsTickInit(UINT32 systemClock, UINT32 tickPerSecond); +//启动系统tick中断 extern VOID OsTickStart(VOID); /* Convert from the cycle count to nanosecond. */ +//将循环周期转换为纳秒 #define CYCLE_TO_NS(cycles) ((cycles) * g_cycle2NsScale) /** * Current system timer register is 32 bit, therefore TIMER_MAXLOAD define just in order to avoid ambiguity. */ +//定时器最大加载值,用于避免歧义 #define TIMER_MAXLOAD 0xffffffff #ifdef LOSCFG_KERNEL_TICKLESS +//tick中断标志,在LOSCFG_KERNEL_TICKLESS选项开启时使用 #define LOS_TICK_INT_FLAG 0x80000000 #endif From a0bc24b6c18179795b7f005fd71d3f305f4015b0 Mon Sep 17 00:00:00 2001 From: cailun <2505225681@qq.com> Date: Tue, 26 Dec 2023 20:41:59 +0800 Subject: [PATCH 17/26] doc --- doc/蔡伦_LiteOS阅读泛读报告.docx | Bin 14958 -> 17703 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/蔡伦_LiteOS阅读泛读报告.docx b/doc/蔡伦_LiteOS阅读泛读报告.docx index 589a7b5393bfd7ba1b3f7cd7e7625a1221bdebbc..0a783a053357a4ec994b9e271fdba1e3ebf06a04 100644 GIT binary patch delta 8704 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 Fe*hX^qzC{2 delta 5956 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 vMi?9d`tP0mNB Date: Thu, 28 Dec 2023 00:09:42 +0800 Subject: [PATCH 18/26] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E4=BA=86task.c?= =?UTF-8?q?=E7=9A=84=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/用例_oujiashu.docx | Bin 14253 -> 0 bytes src/kernel/base/los_task.c | 62 ++++++++++++++++++++++--------------- 2 files changed, 37 insertions(+), 25 deletions(-) delete mode 100644 doc/用例_oujiashu.docx diff --git a/doc/用例_oujiashu.docx b/doc/用例_oujiashu.docx deleted file mode 100644 index 80b0ece3233084e8e246b655c5949b1cb04eb7eb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14253 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 diff --git a/src/kernel/base/los_task.c b/src/kernel/base/los_task.c index c771be6..31de5b0 100644 --- a/src/kernel/base/los_task.c +++ b/src/kernel/base/los_task.c @@ -25,7 +25,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +/*关于LiteOS中任务管理模块的部分实现,包括任务控制块的初始化、任务创建、任务删除等功能*/ #include "los_task_pri.h" #include "los_priqueue_pri.h" #include "los_sem_pri.h" @@ -282,7 +282,7 @@ LITE_OS_SEC_TEXT VOID OsTaskScan(VOID) LOS_Schedule(); } } - +//OsTaskInit用于初始化任务管理模块,包括任务控制块数组、空闲任务列表、任务回收列表等数据结构的初始化 LITE_OS_SEC_TEXT_INIT UINT32 OsTaskInit(VOID) { UINT32 index; @@ -335,7 +335,7 @@ UINT32 OsGetIdleTaskId(VOID) Percpu *perCpu = OsPercpuGet(); return perCpu->idleTaskId; } - +//创建空闲任务(Idle Task) LITE_OS_SEC_TEXT_INIT UINT32 OsIdleTaskCreate(VOID) { UINT32 ret; @@ -363,6 +363,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsIdleTaskCreate(VOID) * Description : get id of current running task. * Return : task id */ +//读取任务ID LITE_OS_SEC_TEXT UINT32 LOS_CurTaskIDGet(VOID) { LosTaskCB *runTask = OsCurrTaskGet(); @@ -372,7 +373,7 @@ LITE_OS_SEC_TEXT UINT32 LOS_CurTaskIDGet(VOID) } return runTask->taskId; } - +//获取当前正在运行的任务的任务名称 LITE_OS_SEC_TEXT CHAR *OsCurTaskNameGet(VOID) { LosTaskCB *runTask = OsCurrTaskGet(); @@ -428,12 +429,12 @@ LITE_OS_SEC_TEXT_MINOR VOID LOS_LowpowerHookReg(LOWPOWERIDLEHOOK hook) g_lowPowerHook = hook; } #endif - +//注册空闲任务钩子函数,即在系统空闲时执行的函数 LITE_OS_SEC_TEXT_MINOR VOID LOS_IdleHandlerHookReg(IDLEHANDLERHOOK hook) { g_idleHandlerHook = hook; } - +//检查任务是否分离(detached) STATIC BOOL OsTaskDeleteCheckDetached(const LosTaskCB *taskCB) { #if LOSCFG_COMPAT_POSIX @@ -442,7 +443,7 @@ STATIC BOOL OsTaskDeleteCheckDetached(const LosTaskCB *taskCB) return TRUE; #endif } - +//删除已分离的任务 STATIC VOID OsTaskDeleteDetached(const LosTaskCB *taskCB) { UINT32 intSave; @@ -451,7 +452,7 @@ STATIC VOID OsTaskDeleteDetached(const LosTaskCB *taskCB) LOS_IntRestore(intSave); (VOID)LOS_TaskDelete(taskCB->taskId); } - +//删除已加入的任务 STATIC VOID OsTaskDeleteJoined(LosTaskCB *taskCB, VOID *ret) { #ifdef LOSCFG_COMPAT_POSIX @@ -481,6 +482,8 @@ STATIC VOID OsTaskDeleteJoined(LosTaskCB *taskCB, VOID *ret) * Description : All task entry * Input : taskId --- The ID of the task to be run */ +//执行任务的实际代码,并根据任务的属性判断是否需要删除任务 +//如果任务是分离的,则直接删除任务;如果任务是加入的,则将任务加入的其他任务唤醒,并重新调度任务 LITE_OS_SEC_TEXT_INIT VOID OsTaskEntry(UINT32 taskId) { LosTaskCB *taskCB = NULL; @@ -511,7 +514,7 @@ LITE_OS_SEC_TEXT_INIT VOID OsTaskEntry(UINT32 taskId) OsTaskDeleteJoined(taskCB, ret); } } - +//对任务初始化参数进行检查,确保任务参数的合法性 STATIC UINT32 OsTaskInitParamCheck(const TSK_INIT_PARAM_S *initParam) { if (initParam == NULL) { @@ -566,7 +569,7 @@ STATIC UINT32 OsTaskCreateParamCheckStatic(const UINT32 *taskId, return LOS_OK; } #endif - +//对任务创建参数进行检查,确保参数的合法性。如果参数不合法,则返回相应的错误码;否则返回成功 LITE_OS_SEC_TEXT_INIT STATIC UINT32 OsTaskCreateParamCheck(const UINT32 *taskId, TSK_INIT_PARAM_S *initParam, VOID **pool) { @@ -776,6 +779,7 @@ LITE_OS_SEC_TEXT_INIT STATIC BOOL OsTaskDelAction(LosTaskCB *taskCB, BOOL useUsr * 3. Do the deletion in hard-irq * then LOS_TaskDelete will directly return with 'ret' value. */ +//OsTaskDeleteCheckOnRun函数用来检查是否需要在任务运行时进行删除操作 LITE_OS_SEC_TEXT_INIT STATIC BOOL OsTaskDeleteCheckOnRun(LosTaskCB *taskCB, UINT32 *ret) { /* init default out return value */ @@ -813,7 +817,7 @@ LITE_OS_SEC_TEXT_INIT STATIC BOOL OsTaskDeleteCheckOnRun(LosTaskCB *taskCB, UINT return TRUE; } - +//OsTaskCBInit函数用于初始化任务控制块,设置任务的各种属性和状态 LITE_OS_SEC_TEXT_INIT STATIC VOID OsTaskCBInit(LosTaskCB *taskCB, const TSK_INIT_PARAM_S *initParam, VOID *stackPtr, const VOID *topStack, BOOL useUsrStack) { @@ -869,7 +873,7 @@ LITE_OS_SEC_TEXT_INIT STATIC VOID OsTaskCBInit(LosTaskCB *taskCB, const TSK_INIT (VOID)memset_s(&taskCB->schedStat, sizeof(SchedStat), 0, sizeof(SchedStat)); #endif } - +//OsTaskGetFreeTaskCB函数用于获取一个空闲的任务控制块 STATIC UINT32 OsTaskGetFreeTaskCB(LosTaskCB **taskCB) { if (LOS_ListEmpty(&g_losFreeTask)) { @@ -883,7 +887,7 @@ STATIC UINT32 OsTaskGetFreeTaskCB(LosTaskCB **taskCB) LOS_ListDelete(LOS_DL_LIST_FIRST(&g_losFreeTask)); return LOS_OK; } - +//OsTaskCreateOnly函数用于创建一个新的任务,其中会对参数进行合法性检查 STATIC UINT32 OsTaskCreateOnly(UINT32 *taskId, TSK_INIT_PARAM_S *initParam, VOID *topStack, BOOL useUsrStack) { UINT32 intSave, errRet; @@ -947,7 +951,7 @@ LOS_ERREND: SCHEDULER_UNLOCK(intSave); return errRet; } - +//OsTaskResume函数用于恢复一个被挂起的任务 STATIC VOID OsTaskResume(const UINT32 *taskId) { UINT32 intSave; @@ -998,7 +1002,8 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreateOnly(UINT32 *taskId, TSK_INIT_PARAM_S { return OsTaskCreateOnly(taskId, initParam, NULL, FALSE); } - +//LOS_TaskCreate该函数用于创建一个新的任务,包括任务的名称、优先级、栈大小等参数的设置 +//在创建任务时,需要进行一些参数的合法性检查,例如是否超出最大任务数量、是否有足够的堆栈空间等 LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreate(UINT32 *taskId, TSK_INIT_PARAM_S *initParam) { UINT32 ret; @@ -1012,7 +1017,8 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreate(UINT32 *taskId, TSK_INIT_PARAM_S *in return LOS_OK; } - +//LOS_TaskDelete用于删除一个已经存在的任务 +//在删除任务时,需要对任务的状态进行判断。如果任务正在运行,则将其标记为删除状态并放入回收列表;否则直接释放任务占用的资源 LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskDelete(UINT32 taskId) { LosTaskCB *taskCB = NULL; @@ -1072,7 +1078,7 @@ LOS_RETURN: SCHEDULER_UNLOCK(intSave); return errRet; } - +//LOS_TaskResume函数用于恢复一个挂起的任务 LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskResume(UINT32 taskId) { UINT32 intSave; @@ -1136,6 +1142,7 @@ LOS_ERREND: * 3. Do the suspension in hard-irq * then LOS_TaskSuspend will directly return with 'ret' value. */ +//OsTaskSuspendCheckOnRun:检查当前任务是否需要挂起的函数,根据条件判断是否需要进行任务挂起操作 LITE_OS_SEC_TEXT_INIT STATIC BOOL OsTaskSuspendCheckOnRun(LosTaskCB *taskCB, UINT32 *ret) { /* init default out return value */ @@ -1164,7 +1171,8 @@ LITE_OS_SEC_TEXT_INIT STATIC BOOL OsTaskSuspendCheckOnRun(LosTaskCB *taskCB, UIN return TRUE; } - +//LOS_TaskSuspend:挂起指定任务的函数 +//如果任务已经处于挂起状态或者正在运行,并且不满足挂起条件,则直接返回错误码;否则执行挂起操作 LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskSuspend(UINT32 taskId) { UINT32 intSave; @@ -1218,7 +1226,7 @@ LOS_RETURN: SCHEDULER_UNLOCK(intSave); return errRet; } - +//LOS_TaskDelay该函数用于让任务进入延时状态,在指定的时间后重新被调度执行 LITE_OS_SEC_TEXT UINT32 LOS_TaskDelay(UINT32 tick) { UINT32 intSave; @@ -1250,7 +1258,7 @@ LITE_OS_SEC_TEXT UINT32 LOS_TaskDelay(UINT32 tick) return LOS_OK; } - +//LOS_TaskDelay:将任务进入延时状态,在指定的时间后重新被调度执行,如果当前在中断中或者不可抢占,则返回相应的错误码 LITE_OS_SEC_TEXT_MINOR UINT16 LOS_TaskPriGet(UINT32 taskId) { UINT32 intSave; @@ -1273,7 +1281,7 @@ LITE_OS_SEC_TEXT_MINOR UINT16 LOS_TaskPriGet(UINT32 taskId) SCHEDULER_UNLOCK(intSave); return priority; } - +//LOS_TaskPriGet:获取指定任务的优先级 LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskPriSet(UINT32 taskId, UINT16 taskPrio) { BOOL isReady = FALSE; @@ -1325,7 +1333,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskPriSet(UINT32 taskId, UINT16 taskPrio) } return LOS_OK; } - +//LOS_TaskPriSet:设置指定任务的优先级,根据任务当前状态选择不同的处理方式 LITE_OS_SEC_TEXT_MINOR UINT32 LOS_CurTaskPriSet(UINT16 taskPrio) { return LOS_TaskPriSet(OsCurrTaskGet()->taskId, taskPrio); @@ -1337,6 +1345,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_CurTaskPriSet(UINT16 taskPrio) * taskStatus --- task status * timeOut --- Expiry time * Return : LOS_OK on success or LOS_NOK on failure + * OsTaskWait和OsTaskWake:任务等待和唤醒的辅助函数 */ VOID OsTaskWait(LOS_DL_LIST *list, UINT16 taskStatus, UINT32 timeout) { @@ -1373,7 +1382,7 @@ VOID OsTaskWake(LosTaskCB *resumedTask, UINT16 taskStatus) OsPriQueueEnqueue(&resumedTask->pendList, resumedTask->priority); } } - +//LOS_TaskYield用于使当前任务主动放弃 CPU 控制权,让出 CPU 给其他高优先级任务执行 LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskYield(VOID) { UINT32 tskCount; @@ -1412,6 +1421,8 @@ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskYield(VOID) return LOS_OK; } +//LOS_TaskLock和LOS_TaskUnlock:任务锁定和解锁函数,用于保护临界区 + LITE_OS_SEC_TEXT_MINOR VOID LOS_TaskLock(VOID) { UINT32 intSave; @@ -1446,7 +1457,7 @@ LITE_OS_SEC_TEXT_MINOR VOID LOS_TaskUnlock(VOID) LOS_IntRestore(intSave); } - +//LOS_TaskInfoGet:获取指定任务的信息,包括任务名、栈大小、堆栈使用情况等 LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskInfoGet(UINT32 taskId, TSK_INFO_S *taskInfo) { UINT32 intSave; @@ -1503,7 +1514,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskInfoGet(UINT32 taskId, TSK_INFO_S *taskInf return LOS_OK; } - +//LOS_TaskCpuAffiSet和LOS_TaskCpuAffiGet:设置和获取任务的 CPU 亲和性,仅在支持多核的情况下有效 LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskCpuAffiSet(UINT32 taskId, UINT16 cpuAffiMask) { #ifdef LOSCFG_KERNEL_SMP @@ -1580,6 +1591,7 @@ LITE_OS_SEC_TEXT_MINOR UINT16 LOS_TaskCpuAffiGet(UINT32 taskId) /* * Description : Process pending signals tagged by others cores + *OsTaskProcSignal:处理挂起、删除任务等信号 */ LITE_OS_SEC_TEXT_MINOR UINT32 OsTaskProcSignal(VOID) { From 643f50b04673c107d1f11b406b1ef9b457b73765 Mon Sep 17 00:00:00 2001 From: tree <1913915946@qq.com> Date: Thu, 28 Dec 2023 08:53:41 +0800 Subject: [PATCH 19/26] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=9B=9B=E4=B8=AA?= =?UTF-8?q?=E7=94=A8=E4=BE=8B=E6=8F=8F=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 7 +++++++ doc/用例描述_oujiashu.docx | Bin 0 -> 19774 bytes 2 files changed, 7 insertions(+) create mode 100644 .vscode/settings.json create mode 100644 doc/用例描述_oujiashu.docx diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..e834bc5 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "files.associations": { + "los_queue_pri.h": "c", + "los_trace.h": "c", + "los_task_pri.h": "c" + } +} \ No newline at end of file diff --git a/doc/用例描述_oujiashu.docx b/doc/用例描述_oujiashu.docx new file mode 100644 index 0000000000000000000000000000000000000000..367e6a99f73b6737e5b641e40da5dcf74d217751 GIT binary patch literal 19774 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 t-3$yzTo@QIs(p0rsO2uQ_7Zm_?a)# Date: Fri, 29 Dec 2023 23:50:18 +0800 Subject: [PATCH 20/26] fuaojia/ --- src/kernel/base/mem/bestfit_little/los_heap.c | 170 ++++++++++++++++-- .../base/mem/bestfit_little/los_memory.c | 152 +++++++++++++++- .../mem/bestfit_little/los_memory_internal.h | 25 ++- .../base/mem/common/memstat/los_memstat.c | 54 ++++++ .../base/mem/common/multipool/los_multipool.c | 54 ++++++ 5 files changed, 424 insertions(+), 31 deletions(-) diff --git a/src/kernel/base/mem/bestfit_little/los_heap.c b/src/kernel/base/mem/bestfit_little/los_heap.c index 8bfa91c..3313db0 100644 --- a/src/kernel/base/mem/bestfit_little/los_heap.c +++ b/src/kernel/base/mem/bestfit_little/los_heap.c @@ -43,9 +43,9 @@ extern "C" { #endif /* __cplusplus */ #endif /* __cplusplus */ -#define HEAP_CAST(t, exp) ((t)(exp)) -#define HEAP_ALIGN sizeof(UINTPTR) -#define MALLOC_MAXSIZE (0xFFFFFFFF - HEAP_ALIGN + 1) +#define HEAP_CAST(t, exp) ((t)(exp))//궨һתĿݷʽt ʾĿͣexp ҪתıʽջὫ exp תΪ t +#define HEAP_ALIGN sizeof(UINTPTR)//궨嶨 HEAP_ALIGNֵ sizeof(UINTPTR)sizeof ڷĴСֽΪλ HEAP_ALIGN ֵȡ UINTPTR ͵ĴС +#define MALLOC_MAXSIZE (0xFFFFFFFF - HEAP_ALIGN + 1)//궨 MALLOC_MAXSIZEֵ 0xFFFFFFFF - HEAP_ALIGN + 10xFFFFFFFF ʾһ32λ޷ֵHEAP_ALIGN Ѿ涨ˡ궨ƺʾڷڴʱܵߴ硣 /* * Description : look up the next memory node according to one memory node in the memory block list. @@ -53,13 +53,25 @@ extern "C" { * struct LosHeapNode *node --- Size of memory in bytes to allocate * Return : Pointer to next memory node */ + /*ǻȡһѽڵָ롣ʵֹ£ +ǰڵѾһڵ㣨 node ڶѹβڵ㣩򷵻 NULL +򣬼һڵָ롣ݽṹ LosHeapNode Ķ֪ÿڵ㶼һ data ָһ size ֶΡΪ˵õһڵָ룬Ҫǰڵ data ָϵǰڵ size ֶΡ +һַҪת struct LosHeapNode* ͵ָ롣ͨȽַתΪ UINTPTR ͣǿתΪ struct LosHeapNode* ʵһ㡣 +һڵָ롣*/ struct LosHeapNode* OsHeapPrvGetNext(struct LosHeapManager *heapMan, struct LosHeapNode *node) { return (heapMan->tail == node) ? NULL : (struct LosHeapNode *)(UINTPTR)(node->data + node->size); } #ifdef LOSCFG_MEM_TASK_STAT - +/*úheapMan ʾѹָ룬size ʾѵijʼСúdzʼѵͳϢ + heapMan->stat ṹ㣬 + heapMan->stat.memTotalUsed heapMan->stat.memTotalPeakʾڴʹͷֵ +ʵֹ£ +ȵ memset_s heapMan->stat 㣬ȷֶεֵΪ 0 +ţ heapMan->stat.memTotalUsed ֵΪ sizeof(struct LosHeapNode) + sizeof(struct LosHeapManager)ѹṹͶѽڵṹĴС֮ͣǶʹõ + heapMan->stat.memTotalPeak ijʼֵҲΪ heapMan->stat.memTotalUsedʾڶʹùе߷ֵ +δǰ LOSCFG_MEM_TASK_STAT 궨Ѿ壬úᱻ롣*/ VOID OsHeapStatInit(struct LosHeapManager *heapMan, UINT32 size) { (VOID)memset_s(&heapMan->stat, sizeof(Memstat), 0, sizeof(Memstat)); @@ -67,7 +79,16 @@ VOID OsHeapStatInit(struct LosHeapManager *heapMan, UINT32 size) heapMan->stat.memTotalUsed = sizeof(struct LosHeapNode) + sizeof(struct LosHeapManager); heapMan->stat.memTotalPeak = heapMan->stat.memTotalUsed; } - +/*úѵͳϢӱʹõڴ顣ʵֹ£ +ȶ taskId blockSizetaskId ڼ¼ǰ IDblockSize ʾҪӵڴĴС +ѽڵṹͽڵ洢ݴС +Ȼͨжȷ taskId ֵǰΪҴڷж״̬OS_INT_INACTIVE + taskId Ϊǰ IDͨ LOS_CurTaskIDGet ȡ򣬽 taskId Ϊ TASK_NUM - 1 +ʾڴһ +ڵ taskId ֶΪ taskIdԱ¼ڴ +󣬵 OS_MEM_ADD_USED ¶ѵͳϢúὫ blockSize taskId ݸѹ stat ṹ壬 +Ա¼ʹڴ͸ڴʹ +úĿڶѵͳϢм¼ÿڴʹԱڴͼء*/ VOID OsHeapStatAddUsed(struct LosHeapManager *heapMan, struct LosHeapNode *node) { UINT32 taskId; @@ -87,7 +108,13 @@ VOID OsHeapStatAddUsed(struct LosHeapManager *heapMan, struct LosHeapNode *node) node->taskId = taskId; OS_MEM_ADD_USED(&heapMan->stat, blockSize, taskId); } - +/*úǴӶѵͳϢмٱʹõڴ顣ʵֹ£ +ȶ taskId blockSizetaskId ڼ¼ǰڵ IDֵڴʱã +blockSize ʾҪٵڴĴСѽڵṹͽڵ洢ݴС + OS_MEM_REDUCE_USED ¶ѵͳϢúὫ blockSize taskId ݸѹ stat ṹ壬 +Ա¼ʹڴ͸ڴʹ +úĿڶѵͳϢм¼ÿڴʹԱڴͼء OsHeapStatAddUsed ෴ +úǽڴʹ״̬תΪδʹ״̬*/ VOID OsHeapStatDecUsed(struct LosHeapManager *heapMan, struct LosHeapNode *node) { UINT32 taskId = node->taskId; @@ -97,17 +124,25 @@ VOID OsHeapStatDecUsed(struct LosHeapManager *heapMan, struct LosHeapNode *node) } #else /* LOSCFG_MEM_TASK_STAT */ - +//ڳʼѹڴͳϢheapMan ʾѹָ룬size ʾѵܴСѡʵУúûκξʵֱֲӷء VOID OsHeapStatInit(struct LosHeapManager *heapMan, UINT32 size) { } - +//ѵͳϢӱʹõڴ顣heapMan ʾѹָ룬node ʾҪӵͳϢеĶѽڵָ롣ѡʵУúûκξʵֲʲôҲ VOID OsHeapStatAddUsed(struct LosHeapManager *heapMan, struct LosHeapNode *node) { } - +//ڴӶѵͳϢмٱʹõڴ顣heapMan ʾѹָ룬node ʾҪͳϢмʹõĶѽڵָ롣ѡʵУúûκξʵֲʲôҲ VOID OsHeapStatDecUsed(struct LosHeapManager *heapMan, struct LosHeapNode *node) { } #endif /* LOSCFG_MEM_TASK_STAT */ #ifdef LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK - +/*δʵһԼĺ OsHeapIntegrityCheckڼڴԣ +ȷѹеڴûбƻԽ硣𲽽δĹܣ +ȣͨ (struct LosHeapNode *)(heap + 1) ķʽȡһѽڵĵַ heap ָѹṹָ롣 +Ȼ󣬼ѵʼַͽַ heapStart ʾѵʼַheapEnd ʾѵĽַ +ѭеÿڵ㡣ѭڲȼ鵱ǰڵĵַǷλڶѵķΧڣڵַСڶѵʼַڶѵĽַ +˵ѽڵѾƻԽ磬ʱ LOS_NOK ʾʧܡ +ǰڵĵַںϷΧڣͨ OsHeapPrvGetNext ȡһڵĵַһֵļ顣 +нڵ㶼ͨϷԼ󣬺 LOS_OK ʾѵԼͨ +֮δʵ˶ԶڴԵļ飬˶ڴ汻ƻԽ磬ȷ˶ѹеڴȷԡ*/ UINT32 OsHeapIntegrityCheck(struct LosHeapManager *heap) { struct LosHeapNode *node = (struct LosHeapNode *)(heap + 1); @@ -127,7 +162,7 @@ UINT32 OsHeapIntegrityCheck(struct LosHeapManager *heap) } #else /* LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK */ - +//δʵһΪ OsHeapIntegrityCheck ĺһָ LosHeapManager ṹָΪֱӷ LOS_OK UINT32 OsHeapIntegrityCheck(struct LosHeapManager *heap) { return LOS_OK; @@ -136,12 +171,16 @@ UINT32 OsHeapIntegrityCheck(struct LosHeapManager *heap) #endif /* LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK */ #ifdef LOSCFG_KERNEL_MEM_SLAB_EXTENTION - +/*һָڴصָ pool һʾҪڴСIJ size +ںڲ OsHeapAlloc ڴίиڴд +սڴصڴֱӷظߡ*/ VOID *OsMemAlloc(VOID *pool, UINT32 size) { return OsHeapAlloc(pool, size); } - +/*һָڴصָ pool һָͷڴָ ptr +ںڲ OsHeapFree ڴͷŲίиڴд +ڴͷŲǷɹɹ򷵻 LOS_OK ʾͷųɹ򷵻 LOS_NOK ʾͷʧܡ*/ UINT32 OsMemFree(VOID *pool, const VOID *ptr) { if (OsHeapFree(pool, ptr) == TRUE) { @@ -160,6 +199,19 @@ UINT32 OsMemFree(VOID *pool, const VOID *ptr) * UITN32 size --- size of the heap memory pool * Return : 1:success 0:error */ +/*δʵһΪ OsHeapInit ĺڳʼڴ𲽽δĹܣ +ȣһָڴصָ pool ͱʾڴشСIJ size +ţ뽫 pool ָǿתΪ struct LosHeapManager ͵ָ heapManԱԶѹṹԱIJ +Ȼ󣬴ִһϵе飺 + heapMan ǷΪ NULLڴصĴСǷСڵڶѹṹͶѽڵṹĿռС֮͡ +κһ FALSE +ͨIJ +ʹ memset_s ڴصݳʼΪ 0 +öѹṹе size ԱΪ size - sizeof(struct LosHeapManager) + head tail ָָڴеʼλãʼѽڵԣ usedprev size + OsHeapStatInit ԶڴͳϢijʼ +󣬺 TRUE ʾڴʼɹ +֮δʵ˶Զڴijʼڴص㡢ùṹĸԱֵԼͳϢijʼǶڴ׶ҪִеĹؼȷڴͷܹС*/ BOOL OsHeapInit(VOID *pool, UINT32 size) { struct LosHeapNode *node = NULL; @@ -192,6 +244,33 @@ BOOL OsHeapInit(VOID *pool, UINT32 size) * UINT32 size --- size of the heap memory pool * Return : NULL:error, other value:the address of the memory we alloced */ +/*δʵһΪ OsHeapAlloc ĺڶڴзָСڴ顣𲽽δĹܣ + +ȣһָڴصָ pool ͱʾҪڴСIJ size + +ţ붨һЩֲ nodenextbestptr alignSizeڼ¼ѽڵʱݡ + +heapMan ǽ pool ָǿתΪ struct LosHeapManager ͵ָ룬ԱԶѹṹԱIJ + +Ȼ󣬴ִһϵе飺 + + heapMan ǷΪ NULLҪڴСǷ񳬹ĴС MALLOC_MAXSIZEκһ NULL +ͨIJ + + OsHeapIntegrityCheck ԶڴԼ顣ʧܣֵ LOS_OK NULL +Ȼ󣬴Ӷڴβʼѽڵ㣬ѰҺʵĿнڵڴ顣£ + +жϵǰڵǷδʹãnode->used == 0ҴС㹻ĶĴСnode->size >= alignSize +ǣ best ָ룬ѡҵĵһʵĽڵ㡣 +ҵĽڵСĶĴСȣbest->size == alignSizeת SIZE_MATCH ǩ +ѭнڵ󣬺ҵѽڵвͬĴ + +ҵ˺ʵĽڵ㣨best != NULLIJ +ҵĽڵСĴСȫƥ䣨ת SIZE_MATCH ǩֱִк +򣬺ҵĽڵϷָһСΪ alignSize ڴ飬ؽڵ͹ֵ +󣬺طڴʼַ ptr + +֮δʵڶڴзָСڴĹܡѽڵ㣬ѰĿнڵ㣬ҪڴָҪʧִܻ󣬺 NULL*/ VOID *OsHeapAlloc(VOID *pool, UINT32 size) { struct LosHeapNode *node = NULL; @@ -222,11 +301,18 @@ VOID *OsHeapAlloc(VOID *pool, UINT32 size) } /* alloc failed */ + /*һж䣬ҵѽڵΪգû㹻СĿнڵ㣩ִлеĴ顣*/ if (best == NULL) { - PRINT_ERR("there's not enough mem to alloc 0x%x Bytes!\n", alignSize); - goto OUT; + PRINT_ERR("there's not enough mem to alloc 0x%x Bytes!\n", alignSize);//û㹻ڴСڴʱӡϢʾû޷ָСڴ档 + goto OUT;//תǩ OUT ִͨͷԴIJ } - + /*һж䣬жǷ㹻Ŀռ佫ҵĽڵָΪ֣ĴСұһ㹻ĿնһڵԪݡ*/ + /*node = (struct LosHeapNode*)(UINTPTR)(best->data + alignSize);µĽڵĵַýڵλԭڵĿпռ֮ڴʣڴ顣 +node->used = 0;½ڵΪδʹá +node->size = best->size - alignSize - sizeof(struct LosHeapNode);½ڵĴСΪԭڵСȥѷڴСͽڵԪݴСʣռ䡣 +node->prev = best;½ڵǰڵΪԭڵ㡣 +жϺͲڸ¶ѹеĽڵϵȷѵԡ +best->size = alignSize;ԭڵĴСΪѷСʾԭڵ˷ڴ顣*/ if ((best->size - alignSize) > sizeof(struct LosHeapNode)) { /* hole divide into 2 */ node = (struct LosHeapNode*)(UINTPTR)(best->data + alignSize); @@ -246,7 +332,11 @@ VOID *OsHeapAlloc(VOID *pool, UINT32 size) best->size = alignSize; } +/*δʵֶ̬ڴĴ롣˵ SIZE_MATCH ܴһڴԣڽڴʱѡܹƥСĿڴз䡣 + +Уе best ܱʾ˷СġƥĿڴ顣뽫 best align Ϊ 0used Ϊ 1ʾڴѱʹáȻ󣬴ָͨ ptr ˸ڴʼַ󣬴 OsHeapStatAddUsed ͳڴĺڴʹϢ¼ڴͳС +ֵעǣпܴһЩδϢ˾庬ҪĺشƶϺ⡣*/ SIZE_MATCH: best->align = 0; best->used = 1; @@ -264,6 +354,15 @@ OUT: * UINT32 boundary --- boundary the heap needs align * Return : NULL:error, other value:the address of the memory we alloced */ +/*δһڷָСָ߽磨alignment boundaryڴĺúΪ OsHeapAllocAlign + +ȽһЩ飬ȷIJ pool Ϊաsize 0boundary ڵ sizeof(VOID*)VOID* ĴСָС boundary Ƕġκһ㣬򷵻 NULLʾڴʧܡ + +ţҪڴĴС useSizeʹ OsHeapAlloc ڴ pool з useSize Сڴ飬丳ֵָ ptr + +ڴɹͨ OS_MEM_ALIGN 꽫 ptr ָ뵽ָı߽ boundaryַָԭʼַָͬ˵ԭʼָѾ룬ֱת OUT ǩ ptr ָ뼴ɡ˵ԭʼָδ룬ҪԭʼָͶָһĿ϶gap gap ĴСϢ洢ڶָǰ sizeof(UINTPTR) ֽڵλá󣬴뷵ضָ alignedPtr + +ҪעǣпܴһЩδĺ궨Ͷ壬庬ҪĺشƶϺ⡣*/ VOID* OsHeapAllocAlign(VOID *pool, UINT32 size, UINT32 boundary) { UINT32 useSize; @@ -297,7 +396,15 @@ VOID* OsHeapAllocAlign(VOID *pool, UINT32 size, UINT32 boundary) OUT: return ptr; } +/*δһͷڴĺΪ OsHeapDoFreeúһ LosHeapManager ṹָ heapManڴعһ LosHeapNode ṹָ curNodeҪͷŵڴӦڴؽڵ㡣 + +Ƚ curNode ֵ node used Ϊ 0ʾýڵΪδʹ״̬ + +ţʹ while ѭǰǰĿнڵ㡣˵ǰڵ node ǰһڵδʹã node Ϊǰһڵ㡣һĿǽ node չܴĿ +Ȼ󣬴ʹ while ѭҺĿнڵ㡣˵ʹ OsHeapPrvGetNext ȡ node һڵ next next δʹã node next ϲΪһµĽڵ㣬 node size ԡϲĽڵеһڵ㣨Ҳ heapMan->tail ָýڵ㣩 heapMan->tail Ϊϲ½ڵ㡣 next ڻѾʹãѭ + +Ҫעǣʹ LosHeapManager LosHeapNode ṹ壬ԺͷĺҪĺشƶϺ⡣*/ STATIC VOID OsHeapDoFree(struct LosHeapManager *heapMan, struct LosHeapNode *curNode) { struct LosHeapNode *node = curNode; @@ -330,6 +437,15 @@ STATIC VOID OsHeapDoFree(struct LosHeapManager *heapMan, struct LosHeapNode *cur * VOID* ptr --- the pointer of heap memory we want to free * Return : 1:success 0:error */ +/*δͷָڴĺ OsHeapFreeúһ VOID ָ poolڴأһ const VOID ָ ptrҪͷŵڴʼַ + +һЩͽṹָ룬 node һ LosHeapNode ṹָ룬ڱʾҪͷŵڴӦڴؽڵ㡣gapSize һ UINT32 ͱڼ¼ڴǰĿ϶Сret һ BOOL ͱڱʾڴǷɹͷš + +ţͨ ptr ָǰƶ sizeof(UINTPTR) ֽڣҵڴַ丳ֵ ptr Ȼ󣬴ж ptr ָڴַǷڴصķΧڣڷΧڣ򷵻 FALSE + +ʹ ((struct LosHeapNode *)ptr) - 1 ڴӦڴؽڵĵַ丳ֵ node Ȼ󣬴ýڵǷѾʹãԼǷеһڵ㡣鲻ͨ ret Ϊ FALSEת OUT ǩ + +󣬴 OsHeapStatDecUsed ڴع used ֶμһȻ OsHeapDoFree node Ӧڴͷţڴعеزշ ret ʾǷɹ*/ BOOL OsHeapFree(VOID *pool, const VOID *ptr) { struct LosHeapNode *node = NULL; @@ -378,6 +494,19 @@ OUT: * Output : status --- heap statistics * Return : LOS_OK on success or error code on failure */ +/*δڻȡָڴصͳϢĺ OsHeapStatisticsGetúһ VOID ָ poolڴأһ LosHeapStatus ṹָ statusڱڴصͳϢ + +һЩ heapUsedmaxFreeNodeSizefreeNodeNumusedNodeNum Լṹָ node ramHeap heapUsed ʾڴСmaxFreeNodeSize ʾڴСfreeNodeNum ʾнڵusedNodeNum ʾýڵ + +Ȼ󣬴鴫ڴָǷΪգΪգ򷵻 LOS_NOKţ鴫Ľṹָ status ǷΪգΪգ򷵻 LOS_NOK + +֮󣬴ʹ sizeof(struct LosHeapManager) ڴعͷռõĿռСӵ heapUsed С + +ʹָ node ڴصĽڵÿڵдýڵѱʹãСͽڵͷСӣۼӵ heapUsed У usedNodeNum һýڵδʹã maxFreeNodeSize freeNodeNum ֵ + +󣬴 heapUsed Ƿ񳬹ڴܴС򷵻 LOS_NOK򣬽ͳϢ浽ṹָ status У LOS_OK + +Ҫעǣϵͳ LOSCFG_MEM_TASK_STAT 궨壬뻹 usageWaterLine ֶεֵ*/ UINT32 OsHeapStatisticsGet(VOID *pool, LosHeapStatus *status) { UINT32 heapUsed = 0; @@ -435,6 +564,15 @@ UINT32 OsHeapStatisticsGet(VOID *pool, LosHeapStatus *status) * Input : pool --- Pointer to the manager, to distinguish heap * Return : max free block size */ +/*δڻȡָڴÿСĺ OsHeapGetMaxFreeBlkSizeúһһ VOID ָ poolڴء + +һЩ sizetempṹָ node ramHeap size ʾÿСtemp һʱڱ浱ǰڵĴС + +Ȼ󣬴鴫ڴָǷΪգΪգ򷵻 LOS_NOK + +֮󣬴ʹָ node ڴصĽڵÿڵдýڵδʹãС浽 temp С temp ֵ size size ֵΪ temp + +󣬺 size ֵڴÿĴС*/ UINT32 OsHeapGetMaxFreeBlkSize(VOID *pool) { UINT32 size = 0; diff --git a/src/kernel/base/mem/bestfit_little/los_memory.c b/src/kernel/base/mem/bestfit_little/los_memory.c index cf9269d..53d9bd0 100644 --- a/src/kernel/base/mem/bestfit_little/los_memory.c +++ b/src/kernel/base/mem/bestfit_little/los_memory.c @@ -41,18 +41,40 @@ extern "C" { #endif /* __cplusplus */ #endif /* __cplusplus */ -#define POOL_ADDR_ALIGNSIZE 64 +#define POOL_ADDR_ALIGNSIZE 64//һ꣬ʾڴصַĴСֵΪ64 -LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_memSpin); +LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_memSpin);//һηָĶΣsectionΪ.bss.initñڳǰᱻʼΪ0 +//һ꣬ڳʼg_memSpin -UINT8 *m_aucSysMem0 = (UINT8 *)NULL; -UINT8 *m_aucSysMem1 = (UINT8 *)NULL; -__attribute__((section(".data.init"))) UINTPTR g_sys_mem_addr_end; +UINT8 *m_aucSysMem0 = (UINT8 *)NULL;//һָUINT8͵ָʼֵΪNULL +UINT8 *m_aucSysMem1 = (UINT8 *)NULL;//һָUINT8͵ָʼֵΪNULL +__attribute__((section(".data.init"))) UINTPTR g_sys_mem_addr_end;//һUINTPTR͵ıλ.data.initΣڼ¼ϵͳڴַĩβλá -#ifdef LOSCFG_EXC_INTERACTION -__attribute__((section(".data.init"))) UINTPTR g_excInteractMemSize = 0; + +#ifdef LOSCFG_EXC_INTERACTION//ʾ˺LOSCFG_EXC_INTERACTION´顣 +__attribute__((section(".data.init"))) UINTPTR g_excInteractMemSize = 0;//һUINTPTR͵ıλ.data.initΣڼ¼쳣ڴĴСʼֵΪ0 #endif + +/*δһLOS_MemInit()ʵ֣ڳʼڴء + +LITE_OS_SEC_TEXT_INIT һηָĶΣsectionΪ.text.initʾúڳǰᱻʼ + + + +pool һָڴصָ룬ڴ洢ڴ顣 +size ڴصĴС +ڲ߼ + +ȣԴIJм顣poolΪָsizeСڵsizeof(struct LosHeapManager)һڲṹĴСֱӷشLOS_NOK +poolsizeǷOS_MEM_ALIGN_SIZEڴСж롣ûж룬ӡϢsizeΪĴС +Ȼ󣬺ȡ浱ǰж״̬Էֹڳʼзжϡ +ţOsMemMulPoolInit()ʼڴعʼʧܣתOUTǩ +ڴعʼɹOsHeapInit()ʼѹѹʼʧܣͷŶڴأȻתOUTǩ +󣬺OsSlabMemInit()ʼ Slab ڴֵΪɹ״̬LOS_OK +OUTǩ֮ǰж״̬ӡڴϢĸ־ +գسʼLOS_NOKʾʧܣLOS_OKʾɹ +δҪʵڴصijʼ߼ڴعѹ Slab ڴijʼ*/ LITE_OS_SEC_TEXT_INIT UINT32 LOS_MemInit(VOID *pool, UINT32 size) { UINT32 ret = LOS_NOK; @@ -103,6 +125,21 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsMemExcInteractionInit(UINTPTR memStart) * Description : Initialize Dynamic Memory pool * Return : LOS_OK on success or error code on failure */ + +/*δһ飬˺LOSCFG_EXC_INTERACTIONʱŻᱻ롣 + +LITE_OS_SEC_TEXT_INIT һηָĶΣsectionΪ.text.initʾúڳǰᱻʼ + + + +memStart һ޷ָ룬ʾڴʼַ +ڲ߼ + +ȣȫֱm_aucSysMem0ָmemStartϵͳڴʼַΪmemStart +Ȼ󣬺ȫֱg_excInteractMemSizeΪ궨EXC_INTERACT_MEM_SIZEֵʾ쳣ڴĴС +LOS_MemInit()m_aucSysMem0g_excInteractMemSizeΪڴʼؽڱretС +󣬺ӡһϢ쳣ڴĵַʹСʼretΪֵء +δҪڳʼ쳣ڴ棬ͨLOS_MemInit()ʼϵͳڴ棬ӡʼϢĿǸǷLOSCFG_EXC_INTERACTIONƴıִС*/ LITE_OS_SEC_TEXT_INIT UINT32 OsMemSystemInit(UINTPTR memStart) { UINT32 ret; @@ -121,6 +158,18 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsMemSystemInit(UINTPTR memStart) * Description : print heap information * Input : pool --- Pointer to the manager, to distinguish heap */ +/*δڴӡڴأpoolϢĺһpoolָΪ + + + +pool һָڴصָ룬ڻȡڴصϢ +ڲ߼ + +ȣpoolָתΪLosHeapManagerṹ͵ָ룬ֵheapMan +Ȼ󣬺һLosHeapStatus͵ıstatusڱѹ״̬Ϣ +ţOsHeapStatisticsGet()ȡѹ״̬Ϣ䱣statusСشLOS_NOKֱӷء +󣬺ӡһڴϢ־ϢڴصַڴشСʹڴСڴСнڵСѷڵͿнڵ +δҪڻȡڴص״̬Ϣӡ̨־ļУԺŲڴй©⡣*/ VOID OsMemInfoPrint(const VOID *pool) { struct LosHeapManager *heapMan = (struct LosHeapManager *)pool; @@ -136,6 +185,20 @@ VOID OsMemInfoPrint(const VOID *pool) status.usedNodeNum, status.freeNodeNum); } +/*δڴĺԴָڴзһָСڴ档 + + + +pool һָڴصָ룬ڴӸڴзڴ档 +size ҪڴС +ڲ߼ + +ȣһָptrڱ䵽ڴַ +Ȼ󣬺鴫IJpoolΪջsizeΪ0ֱӷؿָ롣 +ţסжϣOsSlabMemAlloc()ԴڴصSLABлȡһָСڴ档ɹ򽫷صڴַptrС +SLABзڴʧܣOsHeapAlloc()ӶڴзһָСڴ棬صڴַptrС +󣬺жϣ¼ڴ׷־ط䵽ڴַ +δҪڴڴзڴ棬ȳԴSLABлȡڴ棬ʧӶڴлȡڻȡڴʱ¼ڴ׷־ԺڴŻ*/ LITE_OS_SEC_TEXT VOID *LOS_MemAlloc(VOID *pool, UINT32 size) { VOID *ptr = NULL; @@ -158,6 +221,19 @@ LITE_OS_SEC_TEXT VOID *LOS_MemAlloc(VOID *pool, UINT32 size) return ptr; } +/*δڰָ߽ڴĺԴָڴзһָСָ߽ڴ档 + + + +pool һָڴصָ룬ڴӸڴзڴ档 +size ҪڴС +boundary Ҫı߽СصڴַǸñ߽ +ڲ߼ + +ȣһָptrڱ䵽ڴַ +Ȼ󣬺סжϣOsHeapAllocAlign()Ӷڴаָ߽һָСڴ档ɹ򽫷صڴַptrС +󣬺жϣ¼ڴ׷־ط䵽ڴַ +δҪڴڴаָ߽ڴ棬ֻڶڴϲڷڴʱ¼ڴ׷־ԺڴŻ*/ LITE_OS_SEC_TEXT VOID *LOS_MemAllocAlign(VOID *pool, UINT32 size, UINT32 boundary) { VOID *ptr = NULL; @@ -171,6 +247,14 @@ LITE_OS_SEC_TEXT VOID *LOS_MemAllocAlign(VOID *pool, UINT32 size, UINT32 boundar return ptr; } + +/*δ·ڴСĺҪ¼裺 + +жҪ·СָptrǷΪգΪգ˵Ҫһµڴ棬ֱӵLOS_MemAlloc()ڴзһָСڴ沢ء +Ҫ·СָptrΪСΪ0򽫸ָӦڴͷŵ +Ҫ·СָptrΪС0ҪӶڴзһµڴ棬ԭڴеݿڴСڿ֮ǰҪжԭڴַǷϷ巽ͨOsSlabMemCheck()ָǷڴеijڴ飬ǣԭڴеݣ򣬸ԭڴָǰ洢һֵʾʵڴĴСͶ״̬ҵڴ飬ٽڴ濽 +ԭڴͷŵط䵽ڴַ +δʵ·ڴСĹܣԶѾڴչСʵֹУҪǵԭڴѾ洢ݣڴ濽*/ VOID *LOS_MemRealloc(VOID *pool, VOID *ptr, UINT32 size) { VOID *retPtr = NULL; @@ -228,6 +312,15 @@ VOID *LOS_MemRealloc(VOID *pool, VOID *ptr, UINT32 size) return retPtr; } +/*δͷڴĺҪ¼裺 + +жڴָpoolҪͷŵڴָmemǷΪգһΪգ򷵻شLOS_NOKʾͷʧܡ +ȡ浱ǰж״̬Աָ +OsSlabMemFree()Դڴͷָڴ顣ɹͷţ򽫷ֵΪTRUEִһ +OsSlabMemFree()ʧܣ˵ڴ鲻ڴطģҪOsHeapFree()ԴӶڴͷָڴ顣ͬɹͷţ򽫷ֵΪTRUE򷵻ֵΪFALSE +ָ֮ǰж״̬ +յķֵΪTRUE򷵻سɹLOS_OK򷵻ʧLOS_NOK +δʵڴͷŹܡȳԴڴͷڴ棬ʧܣٳԴӶڴͷڴ档ַͨʽȷܹͷŴڴػзڴ顣*/ LITE_OS_SEC_TEXT UINT32 LOS_MemFree(VOID *pool, VOID *mem) { BOOL ret = FALSE; @@ -250,6 +343,17 @@ LITE_OS_SEC_TEXT UINT32 LOS_MemFree(VOID *pool, VOID *mem) return (ret == TRUE ? LOS_OK : LOS_NOK); } +/*δڻȡڴ״̬ϢĺҪ¼裺 + +жڴָpool״̬ϢָstatusǷΪգһΪգ򷵻شLOS_NOKʾȡʧܡ +һLosHeapStatusṹ͵ıheapStatusڱڴ״̬Ϣ +һerrһж״̬intSave +ȡ浱ǰж״̬Աָ +OsHeapStatisticsGet()ȡָڴصĶڴ״̬ϢheapStatusСش벻LOS_OKʾȡʧܣͷشLOS_NOK +ȡĶڴ״̬ϢֵstatusʹôСܿдСнڵСʹýڵͿнڵ +ڴͳƣ򻹻ὫʹõķֵֵstatusuwUsageWaterLineֶΡ +ͷسɹLOS_OK +δǻȡָڴص״̬ϢʹõڴСеڴСнڵĴСȡͨЩ״̬Ϣ˽ڴصʹӦŻ͹*/ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemInfoGet(VOID *pool, LOS_MEM_POOL_STATUS *status) { LosHeapStatus heapStatus; @@ -282,6 +386,15 @@ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemInfoGet(VOID *pool, LOS_MEM_POOL_STATUS *st return LOS_OK; } +/*δڻȡָڴʹڴСĺҪ¼裺 + +жڴָpoolǷΪգΪգ򷵻شOS_NULL_INTʾȡʧܡ +һLosHeapStatusṹ͵ıheapStatusڱڴ״̬Ϣ +һerrһж״̬intSave +ȡ浱ǰж״̬Աָ +OsHeapStatisticsGet()ȡָڴصĶڴ״̬ϢheapStatusСش벻LOS_OKʾȡʧܣͷشOS_NULL_INT +ͷضڴʹôС +δǻȡָڴʹõڴСͨú˽ڴصʹԱӦĹŻ*/ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemTotalUsedGet(VOID *pool) { LosHeapStatus heapStatus; @@ -303,6 +416,13 @@ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemTotalUsedGet(VOID *pool) return heapStatus.totalUsedSize; } +/*δڻȡָڴصĴСĺҪ¼裺 + +жڴָpoolǷΪգΪգ򷵻شOS_NULL_INTʾȡʧܡ +һLosHeapManagerṹ͵ָheapManagerڱڴصĹϢ +ڴָתΪLosHeapManager͵ָ룬heapManagerС +ڴصĴСheapManager->size +δǻȡָڴصĴСͨú˽ڴصĴСԱӦĹŻ*/ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemPoolSizeGet(const VOID *pool) { struct LosHeapManager *heapManager = NULL; @@ -315,6 +435,14 @@ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemPoolSizeGet(const VOID *pool) return heapManager->size; } +/*δڶָڴؽԼĺҪ¼裺 + +жڴָpoolǷΪգΪգ򷵻شOS_NULL_INTʾʧܡ +һж״̬intSaveһ޷ͱretڱ +ȡ浱ǰж״̬Աָ +OsHeapIntegrityCheck()ָڴؽԼ飬retСصĽΪ0ʾʧܡ +ͷؼ +δǶָڴؽԼ飬ȷڴеûбƻͨúԼʱڴе⣬ȡӦĴʩ޸*/ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemIntegrityCheck(VOID *pool) { UINT32 intSave; @@ -331,6 +459,16 @@ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemIntegrityCheck(VOID *pool) return ret; } +/*δڶԶڴؽԼĺҪ¼裺 + +ȵLOS_MemIntegrityCheck()ϵͳڴm_aucSysMem1Լ飬жϷֵǷΪLOS_OK +ͨڿ̨һϢʾɹҪʱϢд쳣Ϣ +ϵͳڴؼδͨ򲻽κδ +궨LOSCFG_EXC_INTERACTION壬ִĴ룬ֱӽ +LOS_MemIntegrityCheck()쳣ڴm_aucSysMem0Լ飬жϷֵǷΪLOS_OK +ͨڿ̨һϢʾɹҪʱϢд쳣Ϣ +쳣ڴؼδͨ򲻽κδ +δǶԶڴؽԼ飬ȷڴеûбƻͨúԼʱڴе⣬ȡӦĴʩ޸*/ VOID OsMemIntegrityMultiCheck(VOID) { if (LOS_MemIntegrityCheck(m_aucSysMem1) == LOS_OK) { diff --git a/src/kernel/base/mem/bestfit_little/los_memory_internal.h b/src/kernel/base/mem/bestfit_little/los_memory_internal.h index 2aeb022..52e29ff 100644 --- a/src/kernel/base/mem/bestfit_little/los_memory_internal.h +++ b/src/kernel/base/mem/bestfit_little/los_memory_internal.h @@ -42,13 +42,18 @@ extern "C" { #endif /* __cplusplus */ #endif /* __cplusplus */ - +//ڽָĴС sz ж룬ضĴСʹ HEAP_ALIGN 궨ָֽͨ sz HEAP_ALIGN - 1Ȼλȡ㣨&ʵ϶롣 #define ALIGNE(sz) (((sz) + HEAP_ALIGN - 1) & (~(HEAP_ALIGN - 1))) +//ڽָ value align ֽڶ룬ضֵ value תΪ UINT32 ͣ align - 1 λȡ㣬 value 뵽 align ı #define OS_MEM_ALIGN(value, align) (((UINT32)(UINTPTR)(value) + (UINT32)((align) - 1)) & \ (~(UINT32)((align) - 1))) +//ڱʾ־ĺ궨壬ֵΪ 0x80000000 #define OS_MEM_ALIGN_FLAG 0x80000000 +//ö־ĺ궨壬 align λ OS_MEM_ALIGN_FLAG ϡ #define OS_MEM_SET_ALIGN_FLAG(align) ((align) = ((align) | OS_MEM_ALIGN_FLAG)) +//ڻȡ־ĺ궨壬 align OS_MEM_ALIGN_FLAG аλ㣬õ־ #define OS_MEM_GET_ALIGN_FLAG(align) ((align) & OS_MEM_ALIGN_FLAG) +//ڻȡ϶Сĺ궨壬 align ~OS_MEM_ALIGN_FLAG аλ㣬õȥ־ֵ #define OS_MEM_GET_ALIGN_GAPSIZE(align) ((align) & (~OS_MEM_ALIGN_FLAG)) typedef struct tagLosHeapStatus { @@ -60,8 +65,12 @@ typedef struct tagLosHeapStatus { #ifdef LOSCFG_MEM_TASK_STAT UINT32 usageWaterLine; #endif -} LosHeapStatus; +} LosHeapStatus;//ṹ壺ڴѵ״̬ϢܹʹõĴСܹеĴСнڵĴСýڵͿнڵֶΡ +/*ṹ壺ڴеÿڵ㣬ǰһڵָ롢 IDڵС +ǷѾʹáǷҪֶΡʹλʡռ䣬 +ʹһΪ 0 data[0] ռλ +㶯̬ڴ档*/ struct LosHeapNode { struct LosHeapNode *prev; #ifdef LOSCFG_MEM_TASK_STAT @@ -73,12 +82,12 @@ struct LosHeapNode { UINT8 data[0]; }; -extern BOOL OsHeapInit(VOID *pool, UINT32 size); -extern VOID* OsHeapAlloc(VOID *pool, UINT32 size); -extern VOID* OsHeapAllocAlign(VOID *pool, UINT32 size, UINT32 boundary); -extern BOOL OsHeapFree(VOID *pool, const VOID* ptr); -extern UINT32 OsHeapStatisticsGet(VOID *pool, LosHeapStatus *status); -extern UINT32 OsHeapIntegrityCheck(struct LosHeapManager *heap); +extern BOOL OsHeapInit(VOID *pool, UINT32 size);//ڳʼڴأһڴռתΪһڴѣǷʼɹ +extern VOID* OsHeapAlloc(VOID *pool, UINT32 size);//ڴϷһָСڴ棬ط䵽ڴַ +extern VOID* OsHeapAllocAlign(VOID *pool, UINT32 size, UINT32 boundary);//ڴϷһָСҰո߽ڴ棬ط䵽ڴַ +extern BOOL OsHeapFree(VOID *pool, const VOID* ptr);//ͷڴеָڴַӦĽڵ㣬Ƿͷųɹ +extern UINT32 OsHeapStatisticsGet(VOID *pool, LosHeapStatus *status);//ڻȡڴѵ״̬Ϣ䱣ڴ LosHeapStatus ṹУػȡϢֽ +extern UINT32 OsHeapIntegrityCheck(struct LosHeapManager *heap);//ڼڴѵԣǷڴй©ڴص⡣ #ifdef __cplusplus #if __cplusplus diff --git a/src/kernel/base/mem/common/memstat/los_memstat.c b/src/kernel/base/mem/common/memstat/los_memstat.c index 7517b88..b0dc92c 100644 --- a/src/kernel/base/mem/common/memstat/los_memstat.c +++ b/src/kernel/base/mem/common/memstat/los_memstat.c @@ -39,6 +39,15 @@ extern "C" { #define MIN_TASK_ID(x, y) ((x) > (y) ? (y) : (x)) #define MAX_MEM_USE(x, y) ((x) > (y) ? (x) : (y)) +/*δһOsMemstatTaskUsedIncʵ֣ڸڴͳϢ + +ȻȡIDСֵȷԽ硣ȻͨstatȡڴͳtaskMemstats + +뽫usedSizeۼӵӦmemUsedֶϣʾʹõڴusedSizeֽڡȻʹMAX_MEM_USE¸ڴֵǰmemUsedֵmemPeakбȽϣȡϴֵΪµmemPeakֵ + +󣬴뽫usedSizeۼӵڴͳϢstatmemTotalUsedֶϣʾϵͳʹõڴusedSizeֽڡͬأʹMAX_MEM_USEڴķֵ + +δִйУʵʹõڴСڴͳϢ*/ LITE_OS_SEC_TEXT_MINOR VOID OsMemstatTaskUsedInc(Memstat *stat, UINT32 usedSize, UINT32 taskId) { UINT32 record = MIN_TASK_ID(taskId, TASK_NUM - 1); @@ -51,6 +60,13 @@ LITE_OS_SEC_TEXT_MINOR VOID OsMemstatTaskUsedInc(Memstat *stat, UINT32 usedSize, stat->memTotalPeak = MAX_MEM_USE(stat->memTotalPeak, stat->memTotalUsed); } +/*δһOsMemstatTaskUsedDecʵ֣ڸڴͳϢ + +ȻȡIDСֵȷԽ硣ȻͨstatȡڴͳtaskMemstats + +жϵǰʹõڴǷСҪͷŵڴusedSizeǣӡһϢֱӷء򣬽usedSizeӶӦmemUsedֶϼȥʾʹõڴusedSizeֽڡȻusedSizeڴͳϢstatmemTotalUsedֶϼȥʾϵͳʹõڴusedSizeֽڡ + +δִйУʵͷŵڴСڴͳϢǰʹõڴСҪͷŵڴС˵ڴͷŴ󣬴ӡһϢԱԡ*/ LITE_OS_SEC_TEXT_MINOR VOID OsMemstatTaskUsedDec(Memstat *stat, UINT32 usedSize, UINT32 taskId) { UINT32 record = MIN_TASK_ID(taskId, TASK_NUM - 1); @@ -66,6 +82,15 @@ LITE_OS_SEC_TEXT_MINOR VOID OsMemstatTaskUsedDec(Memstat *stat, UINT32 usedSize, stat->memTotalUsed -= usedSize; } +/*δһOsMemstatTaskClearʵ֣ڴͳϢ + +ȻȡIDСֵȷԽ硣ȻͨstatȡڴͳtaskMemstats + +жϵǰʹõڴǷΪ0Ϊ0ӡһϢ˵ɾʱδͷŵڴ档 + +Ȼ󣬽ӦmemUsedֶκmemPeakֶζΪ0ʾڴʹúڴֵ¼ + +δɾʱڴͳϢڱҪʱӡϢѿעڴͷŵԡ*/ LITE_OS_SEC_TEXT_MINOR VOID OsMemstatTaskClear(Memstat *stat, UINT32 taskId) { UINT32 record = MIN_TASK_ID(taskId, TASK_NUM - 1); @@ -80,6 +105,13 @@ LITE_OS_SEC_TEXT_MINOR VOID OsMemstatTaskClear(Memstat *stat, UINT32 taskId) taskMemstats[record].memPeak = 0; } +/*δһOsMemstatTaskUsageʵ֣ڻȡָڴʹ + +ȻȡIDСֵȷԽ硣ȻͨstatȡڴͳtaskMemstats + +뷵ָmemUsedֶΣǰʹõڴ + +δǻȡָڴʹڼغ͵ڴ*/ LITE_OS_SEC_TEXT_MINOR UINT32 OsMemstatTaskUsage(const Memstat *stat, UINT32 taskId) { UINT32 record = MIN_TASK_ID(taskId, TASK_NUM - 1); @@ -88,6 +120,17 @@ LITE_OS_SEC_TEXT_MINOR UINT32 OsMemstatTaskUsage(const Memstat *stat, UINT32 tas return taskMemstats[record].memUsed; } +/*δһOsMemTaskUsageʵ֣ڻȡָϵͳڴеڴʹ֮͡ + +ȣ붨ָpoolstatڴ洢ڴϢڴͳϢ + +ȻͨжǷ˶ڴֱ֧֣ڴغͶڴص + +δڴֱ֧֣ӻȡϵͳڴصڴͳϢstat󣬵OsMemstatTaskUsageȡָڸڴеڴʹؽ + +˶ڴ֧֣Ҫڴأÿڴָڴʹۼշܺ͡ + +δǻȡָϵͳڴеڴʹ֮ͣڼغ͵ϵͳڴ*/ UINT32 OsMemTaskUsage(UINT32 taskId) { LosMemPoolInfo *pool = NULL; @@ -110,6 +153,17 @@ UINT32 OsMemTaskUsage(UINT32 taskId) #endif } +/*δһOsMemTaskClearʵָ֣ϵͳڴеڴͳϢ + +ȣ붨ָpoolstatڴ洢ڴϢڴͳϢ + +ȻͨжǷ˶ڴֱ֧֣ڴغͶڴص + +δڴֱ֧֣ӻȡϵͳڴصڴͳϢstat󣬵OsMemstatTaskClearָڸڴеڴͳϢ + +˶ڴ֧֣ҪڴأλȡÿڴصڴͳϢOsMemstatTaskClearָÿڴеڴͳϢ + +δָϵͳڴеڴͳϢɾʱͷصڴͳƼ¼ȷڴͳϢ׼ȷԡ*/ VOID OsMemTaskClear(UINT32 taskId) { LosMemPoolInfo *pool = NULL; diff --git a/src/kernel/base/mem/common/multipool/los_multipool.c b/src/kernel/base/mem/common/multipool/los_multipool.c index c4c8e33..d50caa8 100644 --- a/src/kernel/base/mem/common/multipool/los_multipool.c +++ b/src/kernel/base/mem/common/multipool/los_multipool.c @@ -30,6 +30,17 @@ STATIC VOID *g_poolHead = NULL; +/*δһOsMemMulPoolInitʵ֣ڳʼڴء + +ȣ붨˼nextPoolcurPoolpoolEndУnextPoolcurPoolڱڴpoolEndڼڴصĽַ + +ȻͨѭڴµڴǷеڴسͻֳͻϢش롣 + +ţڴ״̬µڴز뵽ĩβΪͷڵ㡣 + +µڴصһڴָΪNULLسɹ״̬롣 + +δdzʼڴأµڴز뵽ڴУȷڴ֮ûгͻڴصʹÿṩڴϵͳԲͬ͵ڴзͷš*/ UINT32 OsMemMulPoolInit(VOID *pool, UINT32 size) { VOID *nextPool = g_poolHead; @@ -58,6 +69,21 @@ UINT32 OsMemMulPoolInit(VOID *pool, UINT32 size) return LOS_OK; } +/*δһOsMemMulPoolDeinitʵ֣ڷʼڴء + +ȣ붨˼retnextPoolcurPoolУretڱ溯ִнnextPoolcurPoolڱڴ + +Ȼͨһdo-whileѭĽṹִоķʼ + +ѭУȼ鴫ڴָǷΪգΪֱ˳ѭ + +ţжϴڴǷΪͷڵ㡣ͷڵ㣬ͷָָһڴأسɹ״̬롣 + +ͷڵ㣬ڴѰ봫ڴָȵĽڵ㡣һҵӦĽڵ㣬ǰһڵnextָָһڵ㣬سɹ״̬롣 + +ѭ󣬷ִн + +δǷʼڴأڴƳָڴأͷصԴʼԸҪ̬ӻɾڴأӦϵͳڴı仯*/ UINT32 OsMemMulPoolDeinit(const VOID *pool) { UINT32 ret = LOS_NOK; @@ -90,12 +116,29 @@ UINT32 OsMemMulPoolDeinit(const VOID *pool) return ret; } +/*δǺOsMemMulPoolHeadGetʵ֣ڻȡڴͷڵָ롣 +ܼ򵥣ֱӷȫֱg_poolHeadñ˶ڴͷڵָ롣 + +ԷػȡڴͷڵַԱڴؽбѯ޸ĵȡ*/ VOID *OsMemMulPoolHeadGet(VOID) { return g_poolHead; } +/*δǺLOS_MemDeInitʵ֣ͷָڴصԴзʼ + +ȣ붨˼retintSaveУretڱ溯ִнintSaveڱж״̬ + +ͨMEM_LOCKж״̬ȷִзʼڼ䲻ᱻжϴϡ + +Ȼ󣬵OsMemMulPoolDeinitָڴؽзʼؽ浽retС + +ͨMEM_UNLOCKָ֮ǰж״̬ + +գִн + +δͷָڴصԴִзʼͷڴ֮ǰʹMEM_LOCKж״̬ͷڴڼ䱻жϴϣȻͨOsMemMulPoolDeinitִзʼʹMEM_UNLOCKָ֮ǰж״̬ȷͷڴصĹУ̬ᷢԴͻ⡣*/ LITE_OS_SEC_TEXT_INIT UINT32 LOS_MemDeInit(VOID *pool) { UINT32 ret; @@ -108,6 +151,17 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_MemDeInit(VOID *pool) return ret; } +/*δǺLOS_MemPoolListʵ֣ڴӡڴÿڴصϢ + +ȣ붨nextPoolindexУnextPoolڱһڴصָ룬indexڼ¼ڴص + +ȻͨһwhileѭڴÿڴصOsMemInfoPrintϢnextPoolindex + +ѭУǰڴصıţȻOsMemInfoPrintڴصϢ + +󣬷ڴص + +δǴӡڴÿڴصϢڿԱеԺ͹ͨڴԻȡÿڴصĵַʹOsMemInfoPrintڴصϢ̨ϡͬʱͳڴصԱڴؽиϸĹ*/ LITE_OS_SEC_TEXT_INIT UINT32 LOS_MemPoolList(VOID) { VOID *nextPool = g_poolHead; From 0771df2fb35a5731773ee0767b6a95b49a203aa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=87=E8=B1=AA?= <2548632733@qq.com> Date: Sat, 30 Dec 2023 16:01:48 +0800 Subject: [PATCH 21/26] new code-reading --- debug/los_mux_deadlock.c | 257 +++++++++++++++++++++++++++++ debug/los_mux_debug.c | 189 +++++++++++++++++++++ debug/los_queue_debug.c | 206 +++++++++++++++++++++++ debug/los_sched_debug.c | 347 +++++++++++++++++++++++++++++++++++++++ debug/los_sem_debug.c | 299 +++++++++++++++++++++++++++++++++ kkk.zip | Bin 53432 -> 0 bytes 6 files changed, 1298 insertions(+) create mode 100644 debug/los_mux_deadlock.c create mode 100644 debug/los_mux_debug.c create mode 100644 debug/los_queue_debug.c create mode 100644 debug/los_sched_debug.c create mode 100644 debug/los_sem_debug.c delete mode 100644 kkk.zip diff --git a/debug/los_mux_deadlock.c b/debug/los_mux_deadlock.c new file mode 100644 index 0000000..6862541 --- /dev/null +++ b/debug/los_mux_deadlock.c @@ -0,0 +1,257 @@ +/* ---------------------------------------------------------------------------- + * Copyright (c) Huawei Technologies Co., Ltd. 2013-2019. All rights reserved. + * Description: Mutex Deadlock Check + * 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_mux_debug_pri.h" +#include "los_typedef.h" +#include "los_task.h" +#include "arch/exception.h" +#ifdef LOSCFG_SHELL +#include "shcmd.h" +#endif /* LOSCFG_SHELL */ + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */nbb + +typedef struct { + LOS_DL_LIST muxListHead; /* Task-held mutexs list */ //ڹеĻб// + UINT64 lastAccessTime; /* The last operation time */ //¼һβʱ// +} MuxDLinkCB; + +/*еĻб͸*/ +typedef struct { + LOS_DL_LIST muxList; /* Insert mutex into the owner task CB */ //ڽ뵽Ŀƿ// + VOID *muxCB; /* The Mutex CB pointer */ //ָ򻥳ƿָ// +} MuxDLinkNode; + +STATIC MuxDLinkCB *g_muxDeadlockCBArray = NULL; + +/* + * Mutex deadlock detection time threshold, will print out task information + * that has not been scheduled within this time. + * The unit is tick. + */ +#define OS_MUX_DEADLOCK_CHECK_THRESHOLD 60000 //μ黥֮СʱλΪ// + +UINT32 OsMuxDlockCheckInit(VOID) //ڷڴ沢ʼƿб// +{ + UINT32 index; + UINT32 size = (LOSCFG_BASE_CORE_TSK_LIMIT + 1) * sizeof(MuxDLinkCB); + + /* system resident memory, don't free */ + g_muxDeadlockCBArray = (MuxDLinkCB *)LOS_MemAlloc(m_aucSysMem1, size); + if (g_muxDeadlockCBArray == NULL) { + PRINT_ERR("%s: malloc failed!\n", __FUNCTION__); + return LOS_NOK; + } + + for (index = 0; index < LOSCFG_BASE_CORE_TSK_LIMIT + 1; index++) { + g_muxDeadlockCBArray[index].lastAccessTime = 0; + LOS_ListInit(&g_muxDeadlockCBArray[index].muxListHead); + } + return LOS_OK; +} + +VOID OsMuxDlockNodeInsert(UINT32 taskId, VOID *muxCB) //ָĻвһڵ// +{ + MuxDLinkNode *muxDLNode = NULL; + + if ((taskId > LOSCFG_BASE_CORE_TSK_LIMIT) || (muxCB == NULL)) { + return; + } + + muxDLNode = (MuxDLinkNode *)LOS_MemAlloc(m_aucSysMem1, sizeof(MuxDLinkNode)); + if (muxDLNode == NULL) { + return; + } + (VOID)memset_s(muxDLNode, sizeof(MuxDLinkNode), 0, sizeof(MuxDLinkNode)); + muxDLNode->muxCB = muxCB; + + LOS_ListTailInsert(&g_muxDeadlockCBArray[taskId].muxListHead, &muxDLNode->muxList); +} + +VOID OsMuxDlockNodeDelete(UINT32 taskId, const VOID *muxCB) //ڴָĻɾָĻڵ// +{ + MuxDLinkCB *muxDLCB = NULL; + LOS_DL_LIST *list = NULL; + MuxDLinkNode *muxDLNode = NULL; + + if ((taskId > LOSCFG_BASE_CORE_TSK_LIMIT) || (muxCB == NULL)) { + return; + } + + muxDLCB = &g_muxDeadlockCBArray[taskId]; + LOS_DL_LIST_FOR_EACH(list, &muxDLCB->muxListHead) { + muxDLNode = LOS_DL_LIST_ENTRY(list, MuxDLinkNode, muxList); + if (muxDLNode->muxCB == muxCB) { + LOS_ListDelete(&muxDLNode->muxList); + (VOID)LOS_MemFree(m_aucSysMem1, muxDLNode); + return; + } + } +} + +VOID OsTaskTimeUpdate(UINT32 taskId, UINT64 tickCount) //ڸʱ// +{ + if (taskId > LOSCFG_BASE_CORE_TSK_LIMIT) { + return; + } + + g_muxDeadlockCBArray[taskId].lastAccessTime = tickCount; +} + +STATIC VOID OsDeadlockBackTrace(const LosTaskCB *taskCB) //ڴӡĺջϢ// +{ + TaskContext *context = NULL; + + PRINTK("*******backtrace begin*******\n"); + context = (TaskContext *)taskCB->stackPointer; + ArchBackTraceWithSp(context); + PRINTK("********backtrace end********\n"); + return; +} + +STATIC VOID OsMutexPendTaskList(LOS_DL_LIST *list) //ڴӡȴбϢ// +{ + LOS_DL_LIST *listTmp = NULL; + LosTaskCB *pendedTask = NULL; + CHAR *name = NULL; + UINT32 index = 0; + UINT32 id, intSave; + + SCHEDULER_LOCK(intSave); + if (LOS_ListEmpty(list) == TRUE) { + SCHEDULER_UNLOCK(intSave); + PRINTK("Pended Task: null\n"); + return; + } + + LOS_DL_LIST_FOR_EACH(listTmp, list) { + pendedTask = OS_TCB_FROM_PENDLIST(listTmp); + name = pendedTask->taskName; + id = pendedTask->taskId; + SCHEDULER_UNLOCK(intSave); + if (index == 0) { + PRINTK("Pended task: %u. name:%-15s, id:0x%-5x\n", index, name, id); + } else { + PRINTK(" %u. name:%-15s, id:0x%-5x\n", index, name, id); + } + index++; + SCHEDULER_LOCK(intSave); + } + SCHEDULER_UNLOCK(intSave); +} + +STATIC VOID OsTaskHoldMutexList(MuxDLinkCB *muxDLCB) //ڴӡеĻϢ// +{ + UINT32 index = 0; + MuxDLinkNode *muxDLNode = NULL; + CHAR *ownerName = NULL; + LosMuxCB *muxCB = NULL; + LOS_DL_LIST *list = NULL; + LOS_DL_LIST *listTmp = NULL; + UINT32 count, intSave; + + SCHEDULER_LOCK(intSave); + if (LOS_ListEmpty(&muxDLCB->muxListHead) == TRUE) { + SCHEDULER_UNLOCK(intSave); + PRINTK("null\n"); + } else { + LOS_DL_LIST_FOR_EACH(list, &muxDLCB->muxListHead) { + muxDLNode = LOS_DL_LIST_ENTRY(list, MuxDLinkNode, muxList); + muxCB = (LosMuxCB *)muxDLNode->muxCB; + count = muxCB->muxCount; + ownerName = muxCB->owner->taskName; + SCHEDULER_UNLOCK(intSave); + PRINTK("\n", index); + PRINTK("Ptr handle:%p\n", muxCB); + PRINTK("Owner:%s\n", ownerName); + PRINTK("Count:%u\n", count); + + listTmp = &muxCB->muxList; + OsMutexPendTaskList(listTmp); + + index++; + SCHEDULER_LOCK(intSave); + } + SCHEDULER_UNLOCK(intSave); + } +} + +VOID OsMutexDlockCheck(VOID) //ڼ⻥Ϣ// +{ + UINT32 loop, intSave; + UINT32 taskId; + CHAR *name = NULL; + LosTaskCB *taskCB = NULL; + MuxDLinkCB *muxDLCB = NULL; + + SCHEDULER_LOCK(intSave); + for (loop = 0; loop < g_taskMaxNum; loop++) { + taskCB = (LosTaskCB *)g_taskCBArray + loop; + if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) { + continue; + } + + muxDLCB = &g_muxDeadlockCBArray[taskCB->taskId]; + if ((LOS_TickCountGet() - muxDLCB->lastAccessTime) > OS_MUX_DEADLOCK_CHECK_THRESHOLD) { + name = taskCB->taskName; + taskId = taskCB->taskId; + SCHEDULER_UNLOCK(intSave); + PRINTK("Task_name:%s, ID:0x%x, holds the Mutexs below:\n", name, taskId); + OsTaskHoldMutexList(muxDLCB); + OsDeadlockBackTrace(taskCB); + PRINTK("\n"); + SCHEDULER_LOCK(intSave); + } + } + SCHEDULER_UNLOCK(intSave); +} + +#ifdef LOSCFG_SHELL //ִл鲢Ϣ// +UINT32 OsShellCmdMuxDeadlockCheck(UINT32 argc, const CHAR **argv) +{ + if (argc > 0) { + PRINTK("\nUsage: dlock\n"); + return OS_ERROR; + } + PRINTK("Start mutexs deadlock check: \n"); + OsMutexDlockCheck(); + PRINTK("-----------End-----------\n"); + return LOS_OK; +} +SHELLCMD_ENTRY(deadlock_shellcmd, CMD_TYPE_EX, "dlock", 0, (CmdCallBackFunc)OsShellCmdMuxDeadlockCheck); +#endif /* LOSCFG_SHELL */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ diff --git a/debug/los_mux_debug.c b/debug/los_mux_debug.c new file mode 100644 index 0000000..5008bc5 --- /dev/null +++ b/debug/los_mux_debug.c @@ -0,0 +1,189 @@ +/* ---------------------------------------------------------------------------- + * Copyright (c) Huawei Technologies Co., Ltd. 2013-2019. All rights reserved. + * Description: Mutex Debug + * 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_mux_debug_pri.h" +#include "los_typedef.h" +#include "los_task.h" +#include "los_misc_pri.h" +#include "arch/exception.h" +#ifdef LOSCFG_SHELL +#include "shcmd.h" +#endif /* LOSCFG_SHELL */ + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +#ifdef LOSCFG_DEBUG_MUTEX //ڱʾĵϢ// +typedef struct { + TSK_ENTRY_FUNC creator; /* The task entry who created this mutex */ + UINT64 lastAccessTime; /* The last access time */ +} MuxDebugCB; +STATIC MuxDebugCB *g_muxDebugArray = NULL; + +//ڱȽϢʱ// +STATIC BOOL MuxCompareValue(const SortParam *sortParam, UINT32 left, UINT32 right) +{ + return (*((UINT64 *)(VOID *)SORT_ELEM_ADDR(sortParam, left)) > + *((UINT64 *)(VOID *)SORT_ELEM_ADDR(sortParam, right))); +} + +UINT32 OsMuxDbgInit(VOID) //ڳʼϢ// +{ + UINT32 size = LOSCFG_BASE_IPC_MUX_LIMIT * sizeof(MuxDebugCB); + /* system resident memory, don't free */ + g_muxDebugArray = (MuxDebugCB *)LOS_MemAlloc(m_aucSysMem1, size); + if (g_muxDebugArray == NULL) { + PRINT_ERR("%s: malloc failed!\n", __FUNCTION__); + return LOS_NOK; + } + (VOID)memset_s(g_muxDebugArray, size, 0, size); + return LOS_OK; +} + +VOID OsMuxDbgTimeUpdate(UINT32 muxId) //ڸָʱ// +{ + MuxDebugCB *muxDebug = &g_muxDebugArray[GET_MUX_INDEX(muxId)]; + muxDebug->lastAccessTime = LOS_TickCountGet(); +} + +VOID OsMuxDbgUpdate(UINT32 muxId, TSK_ENTRY_FUNC creator) //ڸָĴߺʱ// +{ + MuxDebugCB *muxDebug = &g_muxDebugArray[GET_MUX_INDEX(muxId)]; + muxDebug->creator = creator; + muxDebug->lastAccessTime = LOS_TickCountGet(); +} + +//ڶԻ򣬲ܴڵĻй©// +STATIC VOID SortMuxIndexArray(UINT32 *indexArray, UINT32 count) +{ + LosMuxCB muxNode = {{0, 0}, 0, 0, 0, 0}; + MuxDebugCB muxDebugNode = {0}; + UINT32 index, intSave; + SortParam muxSortParam; + muxSortParam.buf = (CHAR *)g_muxDebugArray; + muxSortParam.ctrlBlockSize = sizeof(MuxDebugCB); + muxSortParam.ctrlBlockCnt = LOSCFG_BASE_IPC_MUX_LIMIT; + muxSortParam.sortElemOff = LOS_OFF_SET_OF(MuxDebugCB, lastAccessTime); + + if (count > 0) { + SCHEDULER_LOCK(intSave); + OsArraySort(indexArray, 0, count - 1, &muxSortParam, MuxCompareValue); + SCHEDULER_UNLOCK(intSave); + for (index = 0; index < count; index++) { + SCHEDULER_LOCK(intSave); + (VOID)memcpy_s(&muxNode, sizeof(LosMuxCB), + GET_MUX(indexArray[index]), sizeof(LosMuxCB)); + (VOID)memcpy_s(&muxDebugNode, sizeof(MuxDebugCB), + &g_muxDebugArray[indexArray[index]], sizeof(MuxDebugCB)); + SCHEDULER_UNLOCK(intSave); + /* + * muxStat may be altered after the g_taskSpin is unlocked in OsMutexCheck. + * We should recheck the muxStat before the print. + */ + if ((muxNode.muxStat != LOS_USED) || + ((muxNode.muxStat == LOS_USED) && ((muxDebugNode.creator == NULL) || (muxNode.owner == NULL)))) { + continue; + } + PRINTK("Mutex ID <0x%x> may leak, TaskID of owner:0x%x, TaskEntry of owner: %p," + "TaskEntry of creator: %p,Latest operation time: 0x%llx\n", + muxNode.muxId, muxNode.owner->taskId, muxNode.owner->taskEntry, muxDebugNode.creator, + muxDebugNode.lastAccessTime); + } + } + (VOID)LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, indexArray); +} + +VOID OsMutexCheck(VOID) //ڼ黥״̬ԿܴڵĻй©д// +{ + LosMuxCB muxNode = {{0, 0}, 0, 0, 0, 0}; + MuxDebugCB muxDebugNode = {0}; + UINT32 index, intSave; + UINT32 count = 0; + + /* + * This return value does not need to be judged immediately, + * and the following code logic has already distinguished the return value from null and non-empty, + * and there is no case of accessing the null pointer. + */ + UINT32 *indexArray = (UINT32 *)LOS_MemAlloc((VOID *)OS_SYS_MEM_ADDR, LOSCFG_BASE_IPC_MUX_LIMIT * sizeof(UINT32)); + + for (index = 0; index < LOSCFG_BASE_IPC_MUX_LIMIT; index++) { + SCHEDULER_LOCK(intSave); + (VOID)memcpy_s(&muxNode, sizeof(LosMuxCB), GET_MUX(index), sizeof(LosMuxCB)); + (VOID)memcpy_s(&muxDebugNode, sizeof(MuxDebugCB), &g_muxDebugArray[index], sizeof(MuxDebugCB)); + SCHEDULER_UNLOCK(intSave); + + if ((muxNode.muxStat != LOS_USED) || + ((muxNode.muxStat == LOS_USED) && (muxDebugNode.creator == NULL))) { + continue; + } else if ((muxNode.muxStat == LOS_USED) && (muxNode.owner == NULL)) { + PRINTK("Mutex ID <0x%x> may leak, Owner is null, TaskEntry of creator: %p," + "Latest operation time: 0x%llx\n", + muxNode.muxId, muxDebugNode.creator, muxDebugNode.lastAccessTime); + } else { + if (indexArray != NULL) { + *(indexArray + count) = index; + count++; + } else { + PRINTK("Mutex ID <0x%x> may leak, TaskID of owner:0x%x, TaskEntry of owner: %p," + "TaskEntry of creator: %p,Latest operation time: 0x%llx\n", + muxNode.muxId, muxNode.owner->taskId, muxNode.owner->taskEntry, muxDebugNode.creator, + muxDebugNode.lastAccessTime); + } + } + } + + if (indexArray != NULL) { + SortMuxIndexArray(indexArray, count); + } +} + +#ifdef LOSCFG_SHELL +//ڻȡϢ// +LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdMuxInfoGet(UINT32 argc, const CHAR **argv) +{ + if (argc > 0) { + PRINTK("\nUsage: mutex\n"); + return OS_ERROR; + } + PRINTK("used mutexs information: \n"); + OsMutexCheck(); + return LOS_OK; +} +SHELLCMD_ENTRY(mutex_shellcmd, CMD_TYPE_EX, "mutex", 0, (CmdCallBackFunc)OsShellCmdMuxInfoGet); +#endif /* LOSCFG_SHELL */ +#endif /* LOSCFG_DEBUG_MUTEX */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ diff --git a/debug/los_queue_debug.c b/debug/los_queue_debug.c new file mode 100644 index 0000000..43ba6ad --- /dev/null +++ b/debug/los_queue_debug.c @@ -0,0 +1,206 @@ +/* ---------------------------------------------------------------------------- + * Copyright (c) Huawei Technologies Co., Ltd. 2013-2019. All rights reserved. + * Description: Queue Debug + * 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_queue_debug_pri.h" +#include "los_misc_pri.h" +#ifdef LOSCFG_SHELL +#include "shcmd.h" +#endif /* LOSCFG_SHELL */ + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +#ifdef LOSCFG_DEBUG_QUEUE //ڱеĵϢ// +typedef struct { + TSK_ENTRY_FUNC creator; /* The task entry who created this queue */ + UINT64 lastAccessTime; /* The last access time */ +} QueueDebugCB; +STATIC QueueDebugCB *g_queueDebugArray = NULL; + +//ڱȽ϶еԪֵ// +STATIC BOOL QueueCompareValue(const SortParam *sortParam, UINT32 left, UINT32 right) +{ + return (*((UINT64 *)(VOID *)SORT_ELEM_ADDR(sortParam, left)) > + *((UINT64 *)(VOID *)SORT_ELEM_ADDR(sortParam, right))); +} + +UINT32 OsQueueDbgInit(VOID) //ڳʼеĵϢ// +{ + UINT32 size = LOSCFG_BASE_IPC_QUEUE_LIMIT * sizeof(QueueDebugCB); + + /* system resident memory, don't free */ + g_queueDebugArray = (QueueDebugCB *)LOS_MemAlloc(m_aucSysMem1, size); + if (g_queueDebugArray == NULL) { + PRINT_ERR("%s: malloc failed!\n", __FUNCTION__); + return LOS_NOK; + } + (VOID)memset_s(g_queueDebugArray, size, 0, size); + return LOS_OK; +} + +VOID OsQueueDbgTimeUpdate(UINT32 queueId) //ڸ¶еʱ// +{ + QueueDebugCB *queueDebug = &g_queueDebugArray[GET_QUEUE_INDEX(queueId)]; + queueDebug->lastAccessTime = LOS_TickCountGet(); + return; +} + +VOID OsQueueDbgUpdate(UINT32 queueId, TSK_ENTRY_FUNC entry) //ڸ¶еĵϢ// +{ + QueueDebugCB *queueDebug = &g_queueDebugArray[GET_QUEUE_INDEX(queueId)]; + queueDebug->creator = entry; + queueDebug->lastAccessTime = LOS_TickCountGet(); + return; +} + +STATIC INLINE VOID OsQueueInfoOutPut(const LosQueueCB *node) //еϢ// +{ + PRINTK("Queue ID <0x%x> may leak, queue len is 0x%x, " + "readable cnt:0x%x, writeable cnt:0x%x, ", + node->queueId, + node->queueLen, + node->readWriteableCnt[OS_QUEUE_READ], + node->readWriteableCnt[OS_QUEUE_WRITE]); +} + +STATIC INLINE VOID OsQueueOpsOutput(const QueueDebugCB *node) //вϢ// +{ + PRINTK("TaskEntry of creator:0x%p, Latest operation time: 0x%llx\n", + node->creator, node->lastAccessTime); +} + +STATIC VOID SortQueueIndexArray(UINT32 *indexArray, UINT32 count) //ڶԶӦĶϢ// +{ + LosQueueCB queueNode = {0}; + QueueDebugCB queueDebugNode = {0}; + UINT32 index, intSave; + SortParam queueSortParam; + queueSortParam.buf = (CHAR *)g_queueDebugArray; + queueSortParam.ctrlBlockSize = sizeof(QueueDebugCB); + queueSortParam.ctrlBlockCnt = LOSCFG_BASE_IPC_QUEUE_LIMIT; + queueSortParam.sortElemOff = LOS_OFF_SET_OF(QueueDebugCB, lastAccessTime); + + if (count > 0) { + SCHEDULER_LOCK(intSave); + OsArraySort(indexArray, 0, count - 1, &queueSortParam, QueueCompareValue); + SCHEDULER_UNLOCK(intSave); + for (index = 0; index < count; index++) { + SCHEDULER_LOCK(intSave); + (VOID)memcpy_s(&queueNode, sizeof(LosQueueCB), + GET_QUEUE_HANDLE(indexArray[index]), sizeof(LosQueueCB)); + (VOID)memcpy_s(&queueDebugNode, sizeof(QueueDebugCB), + &g_queueDebugArray[indexArray[index]], sizeof(QueueDebugCB)); + SCHEDULER_UNLOCK(intSave); + if (queueNode.queueState == LOS_UNUSED) { + continue; + } + OsQueueInfoOutPut(&queueNode); + OsQueueOpsOutput(&queueDebugNode); + } + } + (VOID)LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, indexArray); +} + +VOID OsQueueCheck(VOID) //ڼе״̬ӦϢ// +{ + LosQueueCB queueNode = {0}; + QueueDebugCB queueDebugNode = {0}; + UINT32 index, intSave; + UINT32 count = 0; + + /* + * This return value does not need to be judged immediately, + * and the following code logic has already distinguished the return value from null and non-empty, + * and there is no case of accessing the null pointer. + */ + UINT32 *indexArray = (UINT32 *)LOS_MemAlloc((VOID *)OS_SYS_MEM_ADDR, LOSCFG_BASE_IPC_QUEUE_LIMIT * sizeof(UINT32)); + + for (index = 0; index < LOSCFG_BASE_IPC_QUEUE_LIMIT; index++) { + SCHEDULER_LOCK(intSave); + (VOID)memcpy_s(&queueNode, sizeof(LosQueueCB), + GET_QUEUE_HANDLE(index), sizeof(LosQueueCB)); + (VOID)memcpy_s(&queueDebugNode, sizeof(QueueDebugCB), + &g_queueDebugArray[index], sizeof(QueueDebugCB)); + SCHEDULER_UNLOCK(intSave); + if ((queueNode.queueState == LOS_UNUSED) || + ((queueNode.queueState == LOS_USED) && (queueDebugNode.creator == NULL))) { + continue; + } + if ((queueNode.queueState == LOS_USED) && + (queueNode.queueLen == queueNode.readWriteableCnt[OS_QUEUE_WRITE]) && + LOS_ListEmpty(&queueNode.readWriteList[OS_QUEUE_READ]) && + LOS_ListEmpty(&queueNode.readWriteList[OS_QUEUE_WRITE]) && + LOS_ListEmpty(&queueNode.memList)) { + PRINTK("Queue ID <0x%x> may leak, No task uses it, " + "QueueLen is 0x%x, ", + queueNode.queueId, + queueNode.queueLen); + OsQueueOpsOutput(&queueDebugNode); + } else { + if (indexArray != NULL) { + *(indexArray + count) = index; + count++; + } else { + OsQueueInfoOutPut(&queueNode); + OsQueueOpsOutput(&queueDebugNode); + } + } + } + + if (indexArray != NULL) { + SortQueueIndexArray(indexArray, count); + } + + return; +} + +#ifdef LOSCFG_SHELL +//û "queue" ʱʹöеϢ// +LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdQueueInfoGet(UINT32 argc, const CHAR **argv) +{ + if (argc > 0) { + PRINTK("\nUsage: queue\n"); + return OS_ERROR; + } + PRINTK("used queues information: \n"); + OsQueueCheck(); + return LOS_OK; +} + +SHELLCMD_ENTRY(queue_shellcmd, CMD_TYPE_EX, "queue", 0, (CmdCallBackFunc)OsShellCmdQueueInfoGet); +#endif /* LOSCFG_SHELL */ +#endif /* LOSCFG_DEBUG_QUEUE */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ diff --git a/debug/los_sched_debug.c b/debug/los_sched_debug.c new file mode 100644 index 0000000..ec4a78b --- /dev/null +++ b/debug/los_sched_debug.c @@ -0,0 +1,347 @@ +/* ---------------------------------------------------------------------------- + * Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved. + * Description: Schedule Statistics + * Author: Huawei LiteOS Team + * Create: 2018-11-16 + * 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_task_pri.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#ifdef LOSCFG_DEBUG_SCHED_STATISTICS +#define HIGHTASKPRI 16 +#define NS_PER_MS 1000000 +#define DECIMAL_TO_PERCENTAGE 100 + +typedef struct { + UINT64 idleRuntime; //ʱ// + UINT64 idleStarttime; //ʱ// + UINT64 highTaskRuntime; //ȼʱ// + UINT64 highTaskStarttime; //ȼʱ// + UINT64 sumPriority; //ȼ֮// + UINT32 prioritySwitch; //л// + UINT32 highTaskSwitch; //ȼл// + UINT32 contexSwitch; //л// + UINT32 hwiNum; //Ӳжϴ// +#ifdef LOSCFG_KERNEL_SMP + UINT32 ipiIrqNum; //жϴڶ¶壩// +#endif +} StatPercpu; + +STATIC BOOL g_statisticsStartFlag = FALSE; +STATIC UINT64 g_statisticsStartTime; +STATIC StatPercpu g_statPercpu[LOSCFG_KERNEL_CORE_NUM]; + +//ÿ CPU Ͻеͳ// +STATIC VOID OsSchedStatisticsPerCpu(const LosTaskCB *runTask, const LosTaskCB *newTask) +{ + UINT32 cpuId; + UINT32 idleTaskId; + UINT64 now, runtime; + + if (g_statisticsStartFlag != TRUE) { + return; + } + + cpuId = ArchCurrCpuid(); + idleTaskId = OsGetIdleTaskId(); + now = LOS_CurrNanosec(); + + g_statPercpu[cpuId].contexSwitch++; + + if ((runTask->taskId != idleTaskId) && (newTask->taskId == idleTaskId)) { + g_statPercpu[cpuId].idleStarttime = now; + } + + if ((runTask->taskId == idleTaskId) && (newTask->taskId != idleTaskId)) { + runtime = now - g_statPercpu[cpuId].idleStarttime; + g_statPercpu[cpuId].idleRuntime += runtime; + g_statPercpu[cpuId].idleStarttime = 0; + } + + if ((runTask->priority >= HIGHTASKPRI) && (newTask->priority < HIGHTASKPRI)) { + g_statPercpu[cpuId].highTaskStarttime = now; + } + + if ((runTask->priority < HIGHTASKPRI) && (newTask->priority >= HIGHTASKPRI)) { + runtime = now - g_statPercpu[cpuId].highTaskStarttime; + g_statPercpu[cpuId].highTaskRuntime += runtime; + g_statPercpu[cpuId].highTaskStarttime = 0; + } + + if (newTask->priority < HIGHTASKPRI) { + g_statPercpu[cpuId].highTaskSwitch++; + } + + if (newTask->taskId != idleTaskId) { + g_statPercpu[cpuId].sumPriority += newTask->priority; + g_statPercpu[cpuId].prioritySwitch++; + } + + return; +} + +//ڸµͳϢ// +LITE_OS_SEC_TEXT_MINOR VOID OsSchedStatistics(LosTaskCB *runTask, LosTaskCB *newTask) +{ + UINT64 runtime; + UINT32 cpuId = ArchCurrCpuid(); + UINT64 now = LOS_CurrNanosec(); + + SchedStat *schedRun = &runTask->schedStat; + SchedStat *schedNew = &newTask->schedStat; + SchedPercpu *cpuRun = &schedRun->schedPercpu[cpuId]; + SchedPercpu *cpuNew = &schedNew->schedPercpu[cpuId]; + + /* calculate one chance of running time */ + runtime = now - schedRun->startRuntime; + + /* add running timer to running task statistics */ + cpuRun->runtime += runtime; + schedRun->allRuntime += runtime; + + /* add context switch counters and schedule start time */ + cpuNew->contexSwitch++; + schedNew->allContextSwitch++; + schedNew->startRuntime = now; + OsSchedStatisticsPerCpu(runTask, newTask); +} + +LITE_OS_SEC_TEXT_MINOR VOID OsHwiStatistics(size_t intNum) //ڸӲжϵͳϢ// +{ + UINT32 cpuId = ArchCurrCpuid(); + + if ((g_statisticsStartFlag != TRUE) || (intNum == OS_TICK_INT_NUM)) { + return; + } + + g_statPercpu[cpuId].hwiNum++; +#ifdef LOSCFG_KERNEL_SMP + /* 16: 0~15 is ipi interrupts */ + if (intNum < 16) { + g_statPercpu[cpuId].ipiIrqNum++; + } +#endif + return; +} + +LITE_OS_SEC_TEXT_MINOR VOID OsShellCmdDumpSched(VOID) //ڴӡĵͳϢ// +{ + LosTaskCB *taskCB = NULL; + UINT32 loop; + UINT32 cpuId; +#ifdef LOSCFG_KERNEL_SMP + UINT32 affinity; +#endif + + PRINTK("\n"); + PRINTK("Task TID Total Time Total CST " + "CPU Time CST\n"); + PRINTK("---- --- ------------------ ---------- -" + "--- ------------------ ----------\n"); + + for (loop = 0; loop < g_taskMaxNum; loop++) { + taskCB = (((LosTaskCB *)g_taskCBArray) + loop); + if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) { + continue; + } +#ifdef LOSCFG_KERNEL_SMP + affinity = (UINT32)taskCB->cpuAffiMask; +#endif + PRINTK("%-30s0x%-6x%+16lf ms %10u\n", taskCB->taskName, taskCB->taskId, + (DOUBLE)(taskCB->schedStat.allRuntime) / NS_PER_MS, + taskCB->schedStat.allContextSwitch); + + for (cpuId = 0; cpuId < LOSCFG_KERNEL_CORE_NUM; cpuId++) { +#ifdef LOSCFG_KERNEL_SMP + if (!((1U << cpuId) & affinity)) { + continue; + } +#endif + PRINTK(" " + "CPU%u %+16lf ms %12u\n", cpuId, + (DOUBLE)(taskCB->schedStat.schedPercpu[cpuId].runtime) / NS_PER_MS, + taskCB->schedStat.schedPercpu[cpuId].contexSwitch); + } + } + + PRINTK("\n"); +} + +LITE_OS_SEC_TEXT_MINOR VOID OsStatisticsShow(UINT64 statisticsPastTime) //ʾϵͳͳϢ// +{ + UINT32 cpuId; + PRINTK("\n"); + PRINTK("Passed Time: %+16lf ms\n", ((DOUBLE)statisticsPastTime / NS_PER_MS)); + PRINTK("--------------------------------\n"); + PRINTK("CPU Idle(%%) ContexSwitch HwiNum " + "Avg Pri HiTask(%%) HiTask SwiNum HiTask P(ms)" +#ifdef LOSCFG_KERNEL_SMP + " MP Hwi\n"); +#else + "\n"); +#endif + PRINTK("---- --------- ----------- -------- --------- " + "---------- ------------ ----------" +#ifdef LOSCFG_KERNEL_SMP + " ------\n"); +#else + "\n"); +#endif + + for (cpuId = 0; cpuId < LOSCFG_KERNEL_CORE_NUM; cpuId++) { +#ifdef LOSCFG_KERNEL_SMP + PRINTK("CPU%u %+10lf%14u%14u %+11lf %+11lf%14u %+11lf %11u\n", cpuId, +#else + PRINTK("CPU%u %+10lf%14u%14u %+11lf %+11lf%14u %+11lf\n", cpuId, +#endif + ((DOUBLE)(g_statPercpu[cpuId].idleRuntime) / statisticsPastTime) * DECIMAL_TO_PERCENTAGE, + g_statPercpu[cpuId].contexSwitch, + g_statPercpu[cpuId].hwiNum, + (g_statPercpu[cpuId].prioritySwitch == 0) ? OS_TASK_PRIORITY_LOWEST : + ((DOUBLE)(g_statPercpu[cpuId].sumPriority) / (g_statPercpu[cpuId].prioritySwitch)), + ((DOUBLE)(g_statPercpu[cpuId].highTaskRuntime) / statisticsPastTime) * DECIMAL_TO_PERCENTAGE, + g_statPercpu[cpuId].highTaskSwitch, + (g_statPercpu[cpuId].highTaskSwitch == 0) ? 0 : + ((DOUBLE)(g_statPercpu[cpuId].highTaskRuntime) / (g_statPercpu[cpuId].highTaskSwitch)) / NS_PER_MS +#ifdef LOSCFG_KERNEL_SMP + , g_statPercpu[cpuId].ipiIrqNum); +#else + ); +#endif + } + + PRINTK("\n"); +} + +LITE_OS_SEC_TEXT_MINOR VOID OsShellStatisticsStart(VOID) //ڶϵͳͳƹ// +{ + LosTaskCB *taskCB = NULL; + UINT32 loop; + UINT32 cpuId = 0; + UINT32 intSave; + + SCHEDULER_LOCK(intSave); + + if (g_statisticsStartFlag) { + SCHEDULER_UNLOCK(intSave); + PRINT_WARN("mp static has started\n"); + return; + } + + g_statisticsStartTime = LOS_CurrNanosec(); + + for (loop = 0; loop < g_taskMaxNum; loop++) { + taskCB = (((LosTaskCB *)g_taskCBArray) + loop); + if (taskCB->taskStatus & OS_TASK_STATUS_RUNNING) { +#ifdef LOSCFG_KERNEL_SMP + cpuId = taskCB->currCpu; +#endif + if ((UINT32)(OS_TASK_INVALID_CPUID) == cpuId) { + continue; + } + if (!strcmp(taskCB->taskName, "IdleCore000")) { + g_statPercpu[cpuId].idleStarttime = g_statisticsStartTime; + } + if (taskCB->priority < HIGHTASKPRI) { + g_statPercpu[cpuId].highTaskStarttime = g_statisticsStartTime; + g_statPercpu[cpuId].highTaskSwitch++; + } + if (strcmp(taskCB->taskName, "IdleCore000")) { + g_statPercpu[cpuId].sumPriority += taskCB->priority; + g_statPercpu[cpuId].prioritySwitch++; + } + } + } + g_statisticsStartFlag = TRUE; + SCHEDULER_UNLOCK(intSave); + + PRINTK("mp static start\n"); + + return; +} + +//ڶϵͳֹͣͳƹܣͳݵĴչʾ// +LITE_OS_SEC_TEXT_MINOR VOID OsShellStatisticsStop(VOID) +{ + LosTaskCB *taskCB = NULL; + UINT32 loop; + UINT32 cpuId = 0; + UINT64 statisticsStopTime; + UINT64 statisticsPastTime; + UINT64 runtime; + UINT32 intSave; + + SCHEDULER_LOCK(intSave); + + if (g_statisticsStartFlag != TRUE) { + SCHEDULER_UNLOCK(intSave); + PRINT_WARN("Please set mp static start\n"); + return; + } + + g_statisticsStartFlag = FALSE; + statisticsStopTime = LOS_CurrNanosec(); + statisticsPastTime = statisticsStopTime - g_statisticsStartTime; + + for (loop = 0; loop < g_taskMaxNum; loop++) { + taskCB = (((LosTaskCB *)g_taskCBArray) + loop); + if (taskCB->taskStatus & OS_TASK_STATUS_RUNNING) { +#ifdef LOSCFG_KERNEL_SMP + cpuId = taskCB->currCpu; +#endif + if (cpuId == (UINT32)(OS_TASK_INVALID_CPUID)) { + continue; + } + if (!strcmp(taskCB->taskName, "IdleCore000")) { + runtime = statisticsStopTime - g_statPercpu[cpuId].idleStarttime; + g_statPercpu[cpuId].idleRuntime += runtime; + g_statPercpu[cpuId].idleStarttime = 0; + } + if (taskCB->priority < HIGHTASKPRI) { + runtime = statisticsStopTime - g_statPercpu[cpuId].highTaskStarttime; + g_statPercpu[cpuId].highTaskRuntime += runtime; + g_statPercpu[cpuId].highTaskStarttime = 0; + } + } + } + SCHEDULER_UNLOCK(intSave); + OsStatisticsShow(statisticsPastTime); + + (VOID)memset_s(g_statPercpu, sizeof(g_statPercpu), 0, sizeof(g_statPercpu)); + g_statisticsStartTime = 0; + return; +} +#endif + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ diff --git a/debug/los_sem_debug.c b/debug/los_sem_debug.c new file mode 100644 index 0000000..8f1774b --- /dev/null +++ b/debug/los_sem_debug.c @@ -0,0 +1,299 @@ +/* ---------------------------------------------------------------------------- + * Copyright (c) Huawei Technologies Co., Ltd. 2013-2019. All rights reserved. + * Description: Sem Debug + * 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_sem_debug_pri.h" +#include "stdlib.h" +#include "los_typedef.h" +#include "los_task_pri.h" +#include "los_misc_pri.h" +#ifdef LOSCFG_SHELL +#include "shcmd.h" +#endif /* LOSCFG_SHELL */ + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +#ifdef LOSCFG_DEBUG_SEMAPHORE +#define OS_ALL_SEM_MASK 0xffffffff + +STATIC VOID OsSemPendedTaskNamePrint(LosSemCB *semNode) //ڴӡȴijźб// +{ + LosTaskCB *tskCB = NULL; + CHAR *nameArr[LOSCFG_BASE_CORE_TSK_LIMIT] = {0}; + UINT32 i, intSave; + UINT32 num = 0; + + SCHEDULER_LOCK(intSave); + if ((semNode->semStat == LOS_UNUSED) || (LOS_ListEmpty(&semNode->semList))) { + SCHEDULER_UNLOCK(intSave); + return; + } + + LOS_DL_LIST_FOR_EACH_ENTRY(tskCB, &semNode->semList, LosTaskCB, pendList) { + nameArr[num++] = tskCB->taskName; + if (num == LOSCFG_BASE_CORE_TSK_LIMIT) { + break; + } + } + SCHEDULER_UNLOCK(intSave); + + PRINTK("Pended task list : "); + for (i = 0; i < num; i++) { + if (i == 0) { + PRINTK("%s\n", nameArr[i]); + } else { + PRINTK(", %s", nameArr[i]); + } + } + PRINTK("\n"); +} + +typedef struct { //ڼ¼źĵϢ// + UINT16 origSemCount; /* Number of original available semaphores */ + UINT64 lastAccessTime; /* The last operation time */ + TSK_ENTRY_FUNC creator; /* The task entry who created this sem */ +} SemDebugCB; +STATIC SemDebugCB *g_semDebugArray = NULL; //ڴ洢źĵϢ// + +//ڱȽԪصֵ// +STATIC BOOL SemCompareValue(const SortParam *sortParam, UINT32 left, UINT32 right) +{ + return (*((UINT64 *)(VOID *)SORT_ELEM_ADDR(sortParam, left)) > + *((UINT64 *)(VOID *)SORT_ELEM_ADDR(sortParam, right))); +} + +UINT32 OsSemDbgInit(VOID) //ڳʼźĵϢ// +{ + UINT32 size = LOSCFG_BASE_IPC_SEM_LIMIT * sizeof(SemDebugCB); + /* system resident memory, don't free */ + g_semDebugArray = (SemDebugCB *)LOS_MemAlloc(m_aucSysMem1, size); + if (g_semDebugArray == NULL) { + PRINT_ERR("%s: malloc failed!\n", __FUNCTION__); + return LOS_NOK; + } + (VOID)memset_s(g_semDebugArray, size, 0, size); + return LOS_OK; +} + +VOID OsSemDbgTimeUpdate(UINT32 semId) //ڸָźһηʱ// +{ + SemDebugCB *semDebug = &g_semDebugArray[GET_SEM_INDEX(semId)]; + semDebug->lastAccessTime = LOS_TickCountGet(); + return; +} + +VOID OsSemDbgUpdate(UINT32 semId, TSK_ENTRY_FUNC creator, UINT16 count) //ڸָźĵϢ// +{ + SemDebugCB *semDebug = &g_semDebugArray[GET_SEM_INDEX(semId)]; + semDebug->creator = creator; + semDebug->lastAccessTime = LOS_TickCountGet(); + semDebug->origSemCount = count; + return; +} + +/*ڰźʱԵǰʹõź*/ +/*ӡÿźĵϢ͵ȴź*/ +STATIC VOID OsSemSort(UINT32 *semIndexArray, UINT32 usedCount) +{ + UINT32 i, intSave; + LosSemCB *semCB = NULL; + LosSemCB semNode = {0}; + SemDebugCB semDebug = {0}; + SortParam semSortParam; + semSortParam.buf = (CHAR *)g_semDebugArray; + semSortParam.ctrlBlockSize = sizeof(SemDebugCB); + semSortParam.ctrlBlockCnt = LOSCFG_BASE_IPC_SEM_LIMIT; + semSortParam.sortElemOff = LOS_OFF_SET_OF(SemDebugCB, lastAccessTime); + + /* It will Print out ALL the Used Semaphore List. */ + PRINTK("Used Semaphore List: \n"); + PRINTK("\r\n SemID Count OriginalCount Creater(TaskEntry) LastAccessTime\n"); + PRINTK(" ------ ------ ------------- ------------------ -------------- \n"); + + SCHEDULER_LOCK(intSave); + OsArraySort(semIndexArray, 0, usedCount - 1, &semSortParam, SemCompareValue); + SCHEDULER_UNLOCK(intSave); + for (i = 0; i < usedCount; i++) { + semCB = GET_SEM(semIndexArray[i]); + SCHEDULER_LOCK(intSave); + (VOID)memcpy_s(&semNode, sizeof(LosSemCB), semCB, sizeof(LosSemCB)); + (VOID)memcpy_s(&semDebug, sizeof(SemDebugCB), &g_semDebugArray[semIndexArray[i]], sizeof(SemDebugCB)); + SCHEDULER_UNLOCK(intSave); + if ((semNode.semStat != LOS_USED) || (semDebug.creator == NULL)) { + continue; + } + PRINTK(" 0x%-07x0x%-07u0x%-14u%-22p0x%llx\n", semNode.semId, semDebug.origSemCount, + semNode.semCount, semDebug.creator, semDebug.lastAccessTime); + if (!LOS_ListEmpty(&semNode.semList)) { + OsSemPendedTaskNamePrint(semCB); + } + } +} +/*ڻȡǰʹõźϢźʱź*/ +UINT32 OsSemInfoGetFullData(VOID) +{ + UINT32 usedSemCnt = 0; + LosSemCB *semNode = NULL; + SemDebugCB *semDebug = NULL; + UINT32 i; + UINT32 *semIndexArray = NULL; + UINT32 count, intSave; + + SCHEDULER_LOCK(intSave); + /* Get the used semaphore count. */ + for (i = 0; i < LOSCFG_BASE_IPC_SEM_LIMIT; i++) { + semNode = GET_SEM(i); + semDebug = &g_semDebugArray[i]; + if ((semNode->semStat == LOS_USED) && (semDebug->creator != NULL)) { + usedSemCnt++; + } + } + SCHEDULER_UNLOCK(intSave); + + if (usedSemCnt > 0) { + semIndexArray = (UINT32 *)LOS_MemAlloc((VOID *)OS_SYS_MEM_ADDR, usedSemCnt * sizeof(UINT32)); + if (semIndexArray == NULL) { + PRINTK("LOS_MemAlloc failed in %s \n", __func__); + return LOS_NOK; + } + + /* Fill the semIndexArray with the real index. */ + count = 0; + + SCHEDULER_LOCK(intSave); + for (i = 0; i < LOSCFG_BASE_IPC_SEM_LIMIT; i++) { + semNode = GET_SEM(i); + semDebug = &g_semDebugArray[i]; + if ((semNode->semStat != LOS_USED) || (semDebug->creator == NULL)) { + continue; + } + *(semIndexArray + count) = i; + count++; + /* if the count is touched usedSemCnt break. */ + if (count >= usedSemCnt) { + break; + } + } + SCHEDULER_UNLOCK(intSave); + OsSemSort(semIndexArray, count); + + /* free the index array. */ + (VOID)LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, semIndexArray); + } + return LOS_OK; +} + +#ifdef LOSCFG_SHELL +STATIC UINT32 OsSemInfoOutput(size_t semId) //źϢ// +{ + UINT32 loop, semCnt, intSave; + LosSemCB *semCB = NULL; + LosSemCB semNode = {0}; + + if (semId == OS_ALL_SEM_MASK) { + for (loop = 0, semCnt = 0; loop < LOSCFG_BASE_IPC_SEM_LIMIT; loop++) { + semCB = GET_SEM(loop); + SCHEDULER_LOCK(intSave); + if (semCB->semStat == LOS_USED) { + (VOID)memcpy_s(&semNode, sizeof(LosSemCB), semCB, sizeof(LosSemCB)); + SCHEDULER_UNLOCK(intSave); + semCnt++; + PRINTK("\r\n SemID Count\n ---------- -----\n"); + PRINTK(" 0x%08x %u\n", semNode.semId, semNode.semCount); + continue; + } + SCHEDULER_UNLOCK(intSave); + } + PRINTK(" SemUsingNum : %u\n\n", semCnt); + return LOS_OK; + } else { + semCB = GET_SEM(semId); + SCHEDULER_LOCK(intSave); + (VOID)memcpy_s(&semNode, sizeof(LosSemCB), semCB, sizeof(LosSemCB)); + SCHEDULER_UNLOCK(intSave); + if ((semNode.semId != semId) || (semNode.semStat != LOS_USED)) { + PRINTK("\nThe semaphore is not in use!\n"); + return LOS_OK; + } + + PRINTK("\r\n SemID Count\n ---------- -----\n"); + PRINTK(" 0x%08x 0x%u\n", semNode.semId, semNode.semCount); + + if (LOS_ListEmpty(&semNode.semList)) { + PRINTK("No task is pended on this semaphore!\n"); + return LOS_OK; + } else { + OsSemPendedTaskNamePrint(semCB); + } + } + return LOS_OK; +} + +//ڻȡźϢ// +LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdSemInfoGet(UINT32 argc, const CHAR **argv) +{ + size_t semId; + CHAR *endPtr = NULL; + UINT32 ret; + + if (argc > 1) { + PRINTK("\nUsage: sem [fulldata|ID]\n"); + return OS_ERROR; + } + + if (argc == 0) { + semId = OS_ALL_SEM_MASK; + } else { + if (strcmp(argv[0], "fulldata") == 0) { + ret = OsSemInfoGetFullData(); + return ret; + } + + semId = strtoul(argv[0], &endPtr, 0); + if ((*endPtr != 0) || (GET_SEM_INDEX(semId) >= LOSCFG_BASE_IPC_SEM_LIMIT)) { + PRINTK("\nsem ID can't access %s.\n", argv[0]); + return OS_ERROR; + } + } + + ret = OsSemInfoOutput(semId); + return ret; +} + +SHELLCMD_ENTRY(sem_shellcmd, CMD_TYPE_EX, "sem", 1, (CmdCallBackFunc)OsShellCmdSemInfoGet); +#endif /* LOSCFG_SHELL */ +#endif /* LOSCFG_DEBUG_SEMAPHORE */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ diff --git a/kkk.zip b/kkk.zip deleted file mode 100644 index b5323c3119761ad9240d6743110933dd3af1dad0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53432 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

      @ZQcpVKYH!H)3v})qheLTNSptb-U$6D* zSQ#4`37DPK0tyC=t3nlZ&tIe&MGZhW%)9453VH;y_JVP3Au4)Rq@eVmVI9Q>^1fwm zylXe23$Sc`J!-adKOYZs=ehH*^l$1B1L;B3;#|WI=@#+CMM2Mv9C6nl2E{m(^B)OgsNhHXEm)PS}m?uFrmI4cSM2x&Ua=ScU z*W%#^bNsEz4rIa>tg#hIWR>WpF5HdLQd;>`XD*r(c;t$td)b&on4Dj=DPi!k;zD?rs zC+l%iR|%KsD}uKmbdX#Dizr@{C#_8sB&B_w@F8M`B$QW3k&ssgH`WHbajJGulpl!U zBe=d31Ln(!b�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�Xqvz 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 z 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 From 68d83fc343ee762138bfa5ac25809859dd92af90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=87=E8=B1=AA?= <2548632733@qq.com> Date: Sun, 31 Dec 2023 21:58:32 +0800 Subject: [PATCH 22/26] wenhao --- 文豪-用例描述.docx | Bin 0 -> 14105 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 文豪-用例描述.docx diff --git a/文豪-用例描述.docx b/文豪-用例描述.docx new file mode 100644 index 0000000000000000000000000000000000000000..a5be5e412a48256759719611f03b383b2d93be84 GIT binary patch literal 14105 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 literal 0 HcmV?d00001 From cb434628b6ca5df174e75bf7b566978bcc92821a Mon Sep 17 00:00:00 2001 From: tree <1913915946@qq.com> Date: Sun, 31 Dec 2023 22:07:03 +0800 Subject: [PATCH 23/26] =?UTF-8?q?=E7=94=A8=E4=BE=8B=E5=9B=BE=E5=92=8C?= =?UTF-8?q?=E7=94=A8=E4=BE=8B=E6=8F=8F=E8=BF=B0=E6=B1=87=E6=80=BB=EF=BC=8C?= =?UTF-8?q?=E6=8A=A5=E5=91=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 3 ++- doc/开源代码的泛读报告-LiteOS.docx | Bin 0 -> 181888 bytes 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 doc/开源代码的泛读报告-LiteOS.docx diff --git a/.vscode/settings.json b/.vscode/settings.json index e834bc5..de2a377 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,6 +2,7 @@ "files.associations": { "los_queue_pri.h": "c", "los_trace.h": "c", - "los_task_pri.h": "c" + "los_task_pri.h": "c", + "los_mux_debug_pri.h": "c" } } \ No newline at end of file diff --git a/doc/开源代码的泛读报告-LiteOS.docx b/doc/开源代码的泛读报告-LiteOS.docx new file mode 100644 index 0000000000000000000000000000000000000000..5a3b73c1a1c313bed337259b8d72f9d8bc34e4ad GIT binary patch literal 181888 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 N5ZWLfC-*f~dbxK=xFw^3?=SzY!ib{m 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

      DIR!vOK`{i}0(ew{FcYR!4 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

      YX9vDt^CB(~oU8kFJGZ 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 z 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 p{mbS53IAua`#Ze8{Wti}M);WmGE8A`aG0 Date: Sun, 31 Dec 2023 22:07:45 +0800 Subject: [PATCH 24/26] =?UTF-8?q?=E7=94=A8=E4=BE=8B=E5=9B=BE.pdf?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/用例图.pdf | Bin 0 -> 61841 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 doc/用例图.pdf diff --git a/doc/用例图.pdf b/doc/用例图.pdf new file mode 100644 index 0000000000000000000000000000000000000000..3030218601710da7ea95c8ffac8d15bdf9074637 GIT binary patch literal 61841 zcmc$G1z1$u`Zp=vDLFJq&d?$t-67pNbmt(AASK-m(jqM>-JwWHNK1#LqzHoFFdpyK z^FN+@&-0vfzhMuv_FnP6>s@cGwfAo?231LEb|42o7CJ*M^n-;C1aJWyjIFWI@7&?k z@NhKalmJ7(whk7Ys$dH<7XS#Ft;VScwzpvRv}6HrszaPzO&}W1W@c&*4iJC<4=i8B z6=G{;4=pZm-JBYy64=>B&feSs+U9lA%oG5vW+o!SsbmHLn?eZyfIR%Ll3G?~Zf4G^ z&SvIj&Sv%|&?bO90@pbrB3S5V_NFk_u9^6WM;LFM5)Q8R5CD)%aw+*0&D1+LuUsQbu)-Q zCv==SHO$;0oN{*1ffWDtBk}D=?pjRHu`sm)i#xdMLrHK!M-s>(0007cc{q4Mh5)E= z?IBPxxd6V6u#B^Vt0R;uOhsTPoa&q!&R}~N$7^w#cyLOnb4r>$v@$VMlM#out^qc7 zffo6uFW*G&0^s^_bgmozK04A?wot)xO4~xEFKK4tU~0yxXl8E#v4nP809MNd;%o-C z!$Nn@*frFRHtciqWorNGNNs_+S^NnZfD}XV`UxIN6bk^Sj@mR#4?oKI4f@XNWMOMX z@v!r7%W6#8f#Y)p;~VO(o<-&5#pUJiA7)+Ie_DNA*yeM^sV($r+M>xqd)V!f&zD!b zbMFO7)DEpC;}%|KeiGbunYujNI>`HaHnA7d7yU(K|LW@OZDE^ltlPqs(&Bstwdl;} zd54FG+oEo2ub9;2kB5lZ^Ym#_gPPsHY%VZdZnXKd&ayxMC>=zoUpnQmrtNS+=muQ% z8E#5g5h*mp)*Iz-OM4QFt{*DygML`j-Fk7E_MD&i*f@8i=YH!sn3l!+yyE`l$KAc< zudNrWpW6({d}h;p32z5%U#PjUzw=RO+9v9}n708OiaeuxLinlnR_>03(BlztpvD1AXPFoG0i|2SH)4FXB>Vt?P|wGBi2LkaBmt z7T}!?b8e~5yu6*AEKBi;eJE>1r0O{j;%K-TeI#K;Le10cxjDd%2D(0UEoJohP+2eP zC%9qBPXrZ2*tn_RS?glsiMt!n-AY4eW|^%9<$r>289(&N65VK#SJl!QDt%Nmk2m+8 zHMt5s1km`7qw}jCUM>F87i`thWd)j5jXC478KIAi2!7s~LWR5G_fHHBA&lACqXaRv zJLz>*I8GrnM$z9G91^I<{;C;>qR)+U_>BVUX`um+fxV@Rv zylqY2(Qz(QRB;1y`OR_Ve!4tjT1#AjF5gI#cul%#7w*0EZCV=kGFHI6x$Dhz!_|#Z zROH0){3H?OK;)GSrfI{^(nWTJEI}#tN})oZ-_C3*I~Nih+HD!^dit&c)&Puw(ks#d z1WoG5aad9L-SisS*)vGNK|Y%ByjH}44yzABcb3a((W)@zDG*bpaH;fyORagt-#$L# z>g7yCt?e1z2fSq&7tVQlqq`MP6j zjoipGF$Jx8h_v%PO%mlL7o)AuVXrZIOO}WcUCVa4SU6L6xwuWrZxEG(Jiyks^TYLPv(oY>Bf@G+x*( zri*(v!5Yc(V)1FDkhG*`Ex{WM<|0Eo`M|ZE8Jy8mc-9kV{(=Z=Q zejn;;MVgyda*#^w?;9?gh-I0hXjl!I@pBCGE2}D3H02STOYTKi)Qa-~+;r6a^dV%{+-8&9v~f0;q_>->#4L%AhB~-4^8$m_)&pO*X(xuU}^lZbA0(GVgfP!^4Q5CjU|D77JL)SIZXo#Hv5>sW6<=(ql& zkd*^h(Sx7}y~6PkyjVQw+?l87z(r2op$`$sa27KPKX&{HL&SVit_{)XDl)C1I|PcFoDq`~crG$<1TXd7G+~VSov^{<@Y*ILfMuaHPM-;?`OQOH zYakK#ww%EDW5n*Nlm_Rq^5;}Im?Asknt2-#9`e!gH!(^CFMVY{m%0o3IZzPYws{3U zoB8Nm9kT40VH21eWusj3%K9B-^agYCYr}r~=S9WxTV1uC*>TVD$LWtH)t&M+Ku&bJ zn|x-<)XO{g+$1OPRhr#EpO^$&@eY+*<#VQ0A>LvsWb)kug0D#Z6e6|L{Y2!wRq8B^ z%eAz&r9lnEj|W=v(6+XM8-RhPh1@8?46hi;7cp{jeMk$7iy2R65Yo|m;0J{7bSQ~x zxysc<<@zZZRjI2l2s*C4-efS#ZeX>tw=?vOiZ6QcEPE(+d|P0BYyibB?e2tkBA+Cn zh@0S~n*Xx~-pDN%3jCPu%~Bc!kFC;fG;9xp+GmPaFN=`ZB}mqsR5$K^Mp8ikWQIR5 zdZW`CeXE+VS`{mgCzG`Hke0fv4A=kOV>u6rsA6gLoav%_`m|}IU}G*1${pOcn)d1F zhE$b2k-~NQK7Y$4)t4(VUD@xta2Evv0U!)dL6(F*p2Gsh8zfw0iErt*JtJQGDbAfE zDOJy)0aIVz%+W+~ZEq$j_@bO7Sd>VIbDvWWpV&!E&eR7WF?)gzj{~&n#tu->knLkR zYID}YQrWzi3|q8i5i2J~rKG%JOeK$WXkCRHe|MywJ;WlC7Ez2K5fUZd1~xWKEmg<} z_KbhJGzzpy^X9p0{@GSMAXq7&)yePaTZ9n-`jCP~z>yvvA2`?t-W2DBlMxPU7hGgx;&>E9BT&|vQ;*yQ%(Zwb0v&YOaIh#}h z5IhTXGGc^%gz3gZy<5cZYQopb(IcrjFmGq8g2-AOF;Q}(p1#>dLSVRQyS%j>I3m9Y zSbqj4ajmy_p0@cir^RfjtT%S1+^ndHzxc87dTi4z?wRb?ab88Ce#h#AX9+=!k6zyD z&V7>?xr0f)_?@M3k|%Ji+A!xg)rxiFC&cH+1k=emi{j6L8nNXzke@CEV&k z%A2l;3D0CnW@luO1kz(`rbW!cdA0@!>=EU)ifYlS0mbj;I6PNo7D4D=Qw*tQKwq>uFhFG-1BbilJDIP z6#_I!g0F%T{ppP3g0$!sPr#aDOl_z5T%KMK?imX)*|ps6-QP9z9yyda6GvI#_hZWbYb#P|O1KJ3CU~^XCPMXOyB^q|4MWB^C zn_~9nM{TO~L^!PJ}jV*K?`!jk3M77udTLecLt3=1>bIMrjj}B7!Wlu zF!aUeFuMF)W%y-yjp<~0R@BJg%Ieda1C{9c7lp$wlr}gawK7@Y$*9RI`XJ^Am(SH% z>Ko5`fTv@wMqdt`=Q|_iC)95-Xj$i|72KF=ltWM;*yccxl~C8~>)RB3&5H_}poqs` zuc6oJg|{r?+lJ2_X{wC?9Y=v&b*N6(Xe^R^rB>v_scwB{f;^iK9pd5mN}MBZz88Xj zyu7x?^kKP4`~H1THzyKwI;z!!;vy~)!^Bzblz7)xL-09E5T1-_4wtS4eSG&?_luXI zcZVXd(%ngULNhuTHIiKJ>g}<)2x^qCSSrtJa`kIkCN&@EvW!NsI!AvPlCXb`#(TJD z-%BO!FWZGwPRK{lCIA zd(W2cn%*FCULtetHy9a8DX)VMoippZj1HC^v@tfPj7ee(MWOW!B$w9O!BS9vjh~j>^>*v-Eh^2J z1|o^;tuanJR?TMA+}e*C_sA{Zy}m26#X2Z1Y{e4V01UQ7hy}|X#gGJ;%kcz;rkPQy zQa1UcAmG*Ap$D2ASj0&}Gbpkmncp<#etvE)e0G{KS}KJ0Fn=gipM&ULy#&j}-abgg z_tCZ3YQnm}ydPaT#r1@n2=U+rL2zy1H|SoQkVbfS*z@B0|QV;bEtxS{|@{tH1ZOL2c@*9@e$*}Aw`;7)U0tkK67_evuzRM`rVi^>)SgY8bD zhNbh&4As0f3aK8NC|hdPm%VuPJ_xdi=$uUUc-(3m=kj=BL9*>?n>fK*zj7*VJW6|j z)j#&CK(Wr*eSIb|`l^4S->8G7sCfdBS&qj=F zAbdz_ZFl%&^4jtvq=S=^;ngtt)qrNgo_y^FtvGotmi&3S(A}o_f?^2F#84rZ;Zu`}&N&$*VQgZN~SQ|j7 z{F#G@{h2RpbC{qC=Fu`K#yK#_jzg_5t1PJNMu@)1$kIKt%x8XOvEy}iRrto!$>+0N z>)94(vKy{_S3{-eV}yf>t;8nuER^JyChLlI`yhID}7f;Q?Vu8guH`d+nyqfI;aw1Xh}4{s4Q!UYcO#|sFza+SDap1sq|J89OnMt&%I zVd-Vzu$aO}g-GmFMY)m=QVVZ~vS(kn7N~oQB($1v+>0am0qFO}Voz#mTy%*F2ce*N$~}rG zRhx@GHo5fR@;%yw@>k6<^QZO04YNizfMNio%~~9y0ryl=vFAh8tr*YDmTp}N$4gNYs95*``;lHf{^ z#W0opaDQwdvu87@XOjlK@07TvYh=cMYLk~ioJKGN(Zxx7PGFy|>u2v8*xwQNjXqsW9;w8sY^o#kbS}JSxX)8uUt)KY=Xor@OXLZj z@JoRt6~eTD8^NSbT7$O%>>ia|D;|9IrbLV#J*h=cYBN}wTdUEHiE)(@h zx6q8M#^R#(aCLhK4ZJPoDqhSZgZEeFbEPlODJsrG6@~*IJxmnBksdDy3gi= zYi7|}?QH2k_`eGcY8}SgHE(gUV0+{jF<0CH=5l;vEc8~QmpxjTjdaKTgXvH+!UGq`&7!1M>HoAI(L+(v`fa@0BcI+c;Z~kw(7HzvoOmjlx!ia}W2W)`{J0pL;Ai zG19R#Z7E1TD?yblP}I(}b5rXvwU;LLm=h6@U}^o;?F!#Fp1?jK(qN%k5ymkws-mRc z_Zxea7v|@PP)}Ti(NJ?6Jz@JxU& zEsJg?Y`^9>WsjLd!t=o$Cz45F`O_BeOZX~h)@g^(fd{kF$v5q5#*|5WZb$JSt$$hz z3}_NJwtIN7$wmax7{?XdE#YpAz`|%)u{3` zuXvlgt@2PR-h=YVm$Y~O#*^&Yjd~^{&Df@>`kR%dh@){EuGu=9>rtf*OGnJQIUbaj z-h8=i+hOZ3%bkRwhNQF7@8-OOX^skt4Re(wOx_k2P&;wkIlcUF-Zv{+p7LUT-?B%= zRQv#W2+r&4m!d~h{kseL{>TpZm1{1_whcbFD61{Cix)ar%UDUgeNMEH(C}8Agir3B z;fHzq_X~vnyJ3bB4(DlpSbJ06EGsRKlGQan4?RW=9Xp7SQ2ZpQU9bCSj&h6|!1}V7 z%e-T6Ga!ODv?TTB+K9|^%vh7E?O_!0`#uCn9Gc-*s0c3=;#=z3{aLw;DwL#`xSk=N zDsyV5fH1o?=m+fOWpD{}gSk49{hfqQ*~Rl$HaA?~oNTQ}VYvs9AK+gmqjlJcl!cN? zMQPOckN0cK_6D!B1MzD0jLkE%A0!W9OTHs-Ww&|fhF@kHq*|p}`a~?j+;Hp;PFqRk zr@29D6aK72Nqf5B8Yk2P{`@9r0l2Hpvu_URzs7U4wk z?Rw`MsT1N#&k_Fw1Fe@bnwP_~F6C6|!5epotPUHb z6iu;^K0IZBAd)yZL{c#7@Om?}7jP$VVK};;(?|8=-MDM8RK9kT2jc~eqBwhrnARa% zdx6VvzFE&6!MI7nt?LZNTdA%}N4AAjnL?*4+f(XEANY*@3fa^Tng_qkv#Uc6QdNdq zKMLOdH13fs@@VTR)%${mT17golV@lhq=&~!nl$VJRM?&H^ga^pABeO-zKgWpeV4id zPV{@0j^3xZ3p-^B7>LAssyD_xUa%bQ<9g_|KfPabLP-%$d0`>KW?hGAXQNKdO>$)s z@0Td%b7~5>wZNak-hRXXr2Rz=+Q(NXXARSVH^FnM)uhH8;~Kus8GQ|xa7D2e~=19?bdm3fy9*sF~EW#Zr`61()pV5%%am> z9En7ysdD?&yr>Q-f^>4HiD%Y!sq+1OcQk!d-}@AM(>=yT$5EWkyo9Q65Dw_c0WBC) zBvidp_8;t20*nx%dl%I^oDv@};duA?VrOJI-R>f&Cl*Gfdo8t#;BSDusgoh4=jA?d zkkgv$#c#XHBA~Q`_PIAQ;dI2=1S!cy;Zb}2eS@x-Rk+xu@EZ+zB2ANL*{tFZmi!zX z6l=;%km9I-BU*hq#Q=5{AD^#pu;OgrsG!&_vM77GC-kX|kn}uFk6b|)Z*?D(F;o~~ z>X3}Irp@O!moX|2q|@@|uA^l}ePYG>MK_;P+lj>e69b7Cvr|zPHL9@w5T#B@j^7eQw zQ6n3%NI0l@!=gmpj7Ty{&(Qk*cJt%ksu@aJ8A2-jVa^a3TF~6z0;lue> zUdxh71`GIPwA3bTVTU{O;`7SZ2EmnDL%baKd*?1}+h)oODk^pNq;!XZsD`82=7RKr zM7+D360*QFxA#r=iplXO(`nr~vbro8=%m zM}yAS%W1vN>Rx+b`1xLj_=saOi?EN9)R?t$fDT(6wt$V?0P~oXR&LL&ZsS_53)^F> zUgSz9tgD7_(Q*zEv+aFT`v}BLBf5?~pCtR<#QoQgt{N2Mw)G=?T3(Nn_8nQTB_f`a z-F~-~fZN|riSQGP$0NP3IVhtXR5~|} z{(xJDTnq3iyOucwu zDB14Hp;p&DJ|c#0_^68oUi@>QFpF$RQ@~4+(gNrn2H#!U&)z zer}^hq7``lIcXRt@+teqdAFc@)10+vgo9qhg>}wCoUyv6iw!@qjPFrrTZdsdU1uR` zpZdLOp=v4AfL?UqWqP3YBWRW`U_4XT6xeO>+>=wkTQP+;;c(hRFfe{Y)2adphl-Wr^h@t1}T5TTRfLP7zaMck^=@fF@z35(*4l7rdwULMsgv zaPJ1|FMz@6xQ)$rE3_& z_e#>P_9hT32m5P^0B%l62RpEp{WbCc2*nym*|4zIx7|wU9zaeyBY6jv|w*;G7*;_zyD-sU24$kV1 zU=y={qg1|U|5jMS!NC~@Bm#1A@bdu#c!AJ?g~EAYXZ!*n4v-*pY@yZywIqEQpb7Tx z2R#J9fIA}4&%d!tFpSQ3?qK$Ijo;x^cQuAwqpdWcxG30FWw4zY6w|{g4t6nvl@OPZ zl#-HSm4;$$Y@pyO83%}^l?l7JgM-aCdx7?gQ`^d3%-+QcW41#n7RIlDk4EWyqI9xf=9>$fxz1ccT%g;-ugu3$)}pV6pZIT z;S&nyv2X!!gE-}&kTNS1F?$PJGXNK-n2X6Z080?a4;_ndX?CC>7ZiEsC~IbAVF>~7 zb3sczw1BY(;DIu#1a|*+0_BBQrZKXcbr)aTvM@+BOJq zO#tc`pk@kf`+CTrl7fPc%%ISzZ_uotI{$xsaOWDy`Jg<&M(QUX{^fF^ei5cuhJYWm>PO%D zqssii$#)f#kdwS7dp(GtZ}=@(Z=jbo9AxAqmB5ai-+ASf)P@QPDpF{sx`zu?me(jg z01)O~VKV!-1^|FCZ_5d-!SfqF?g##UbhIkYre@Ai^<@4|28tt8GqbRQMkWttF(|~( z>>60;>gZ@|W_PU^KcU26RQ`|s{F@CJSKk%!hu;6W?g{V;{-Aq2z#nw)I_qD$#|xFk zzjcp`O8`dh7rLit2J<#hc>sUYL#RSt%lbDx6o6_W4-~Zr6)@DhTsxEN%gf*gF; z>z6;BOTyItcc#F7?Vi80_mk57152vwr44i$#SIGr0B%@(0&v4Z{m-TVEBJ?8{gb8u z?6aA$F z{3lHTwnF^g)xW_Mc)10xZ!Pc$f}nSp0N>9*JRDp+|Irj+6O*4ONU+7@clQ2iQ{ed) z2fi)&0N>u?0(^UA>t|Dd75qc4{&=YVCR6xZedVt_>F;I@Fe&_nuKudozh?Bmbbx;> z-#;h%OX>fxgK|g*u7=KAYV0`@rs(-E^zsmice!!&gKPUSCWz7tGdGmW$|3*^~ zSyuWmW|G-j#_uHx&8q;7V@NKrl_Xn$HSi$cy`zciY zvD5mSEa7i;mH(|J{OBqFi?05v*}r7-Fq!`a`TjZ4UrPUXMh|;;`8(CW&k_W9p%30b z-!0+4djbPf``?)Y-!CVP|9~k#P50Uc_`a>0`M%AT`2Jwk3@i9uX#a(N{BkhaUvpYd!s?1N>uG^XEi=DgEDf^>1D^|7%9X&jG#T_Gw4 zKPUQ22l!8#0&MS!?_K@-q5?lZkVEiat7d*KZVti!_*j7tHZl2m)y)4(Pxud*0{^!- z0EHF6Y~b5;i66$*&!zw?_+4oKv#0>$>n~9Kb6@$Z+~2uM{vTcCf6>)nHT&0${+AB$ zA2o#^9o*k%3Opb_DCX#URN&?n;1KwarT|m>-$ez1A6Ly9RuEe=X6O@nF;|GCgERBh zS2zbaFq{n>z=jF-oZi^l%mi{>K*7wz?HV$3otA*^&T@_Kl7w#H!Yp|k#0BC8ULPPX zZV-@_OMr=s>$PVBrgfq5%lNrg}eB|IyKY z6XexbR|961aIGsi4!DOU);mS@p`8ucHj>bzw!UywI_HTvj5fIHC#!>*jgQ82L-tC z^8Y3f9szD>>Q}q>0D1XgkihRCME8tAT_p!{DN-X5B(-~AyBrm8%-lpCKGZ6{rJ1jJ zFEqaQo+#m%^@^?C%R2t5$(WC>+weq12;D*YIPIaL?f%q$-TsIc*dNI~v(=V7cID!2 zoA;D8nqE~c%ulCUJoQ-cc%OQZmV(Sitk}nv6v6u1xCbc&E%gZTo)4AxH1N6cP!m4F zVLnfBVGPW{?+8SHOV}MqY}wy2nk_mMYM~h2o{kpgRm4XX7FB0~y~2h>UU#VkNfs#oZ3Ffyh#6Qjk1B zX0~z`;-G^ktmn;Dy%}lgN2n)5BaN>P`RKBj(Iy>Zr+lCdH~k6Zu(%6lJ!e0X5xDV#emgF>D) zadov^QQ_P2j$`+R+Ipe|!ns_F;qi!0($A$AC_`UGm$)}~F=c{ko))N#d zvxk=?2GXDGpgJkF9G!8^SupRew1(~#Nn;eaaSdS}Sd2mZM=4ZNF$~30ec>U6=qr+e zmADOxO=V8XTR8!g?G@z)UY?(Jw4$Mmu_ zY8JxR)o|X&Pn>+T6E;Ds6}92ut$fQOqhZ__qV0jCEJ(P)QcKFBwJwVENU#3J>etd! z_oJrcgNQ+vq4IvI%<_-Gq2RBaD4GMvG}zVH%QIJYwQtXkUvE4zYFXf8cp`u)q<9*= z(0KB(PWx-i=}~Va{@siML-Pe>Ne5JFo~3rv9cgFlP?u;-)I@wj2kk=$+Vu0=>RU;5 z*#(IFY!M{Fjv)*xO^O~&&LK=aXblG*PC`#+&{7*p%{b}v6JHw4tcj+O&{v0jjj{|$ z09muyN$~{9XNy1ENK$!v;?wzhDMrNdgYU;TgZv6Hm}4#qRA#dw0b;|9B!Z?<=nBf+ zx;*@vN?(T;ALMJE4Jv8(C42B2b2O>(8yD!C@;_dBlisPhImjNJ@RfT-dW0rR06)Xo z*ClVgirOtttI^AiZZk$Ct1X-to}0rf&Ww%N=fy5qW6*@Ipr_kze-*OGJyu;*rTC#1 zKWirHJ#YEgY;R>OK^`Mx2B|RcZFfp&YE9l`B*B|9qIdE(iM2VkGc&LBOv-vzh@>(gl(Yf}*SxjUZN3!?yT@amLNvh|jyX7i^!uhhUZSsr-0%$|_RB2-y!3S+4&NV2 z%cByAR0uwP94otiB|l1G8nU-wxAJM^(wXUld6@+AiM@r8u!h?xPI2uGIfwfhF*_YVJp(_XTSgDg#u!Dp?mxBKyT~tLSf;&P)r;*6w}88jhDR8XR#m{V1}0q z2*uGsk$zAVE-&<1F)tL`#0vv0a6_;1KyMInUqAeVJw@h&p7B7@c054n{O#Wez;Dph z?*aHvqAUo+!~NTac~GLzkHGb`;JXmrGj_Z^4Aiw-&jj7%?47IUYy)ut9jF{)kC9Mo zm|4&%Z48UEA1EmJ0RZVp8rGT#xkPrg7+SMxKJ%19VNDE`Cm~zbl=fiPlD@g3$cdzJGC8 z6cbKDf7L6Bz`$)<8#=F`)D>Zq;feg92CPe@%9PB7^QbP^_%f)^k)P>hLgK zC5M|J*@NhupgG!_C+ShdAXnMfS2xXE6h`2Dv37G-Nd4~1Acj%#w6h2B5cMW!!;kjO zVI1MmVN^4ct@W?+`2yulY`~cevR~Xjo*#Vv_Qy}nXudwUcpt74ErxJ2Bfxk>kc8_r zMmef5`}yaqIBZ9j)l|^C7`dalqZ@uB2|5=;4+$1Xb_78*0;$3{j;!m7QWLIz9f2;p4^nO+;OV{5&4D!5 z3y8;DdSR@rBlpRbFYwZzYi5Z;QS|*w7aj2lO?#!X5OKm$%Sczu(Dg3f0VMY7zTBIvq#LDV@-) zHpRjs{X}c4-OxvW)_$hbXE79}6F%2K6%y0&4|MR6`(cRB;t^xn`>UF zfPbb*W9leVkiu0O!j6huj&WFJXU`=G+F9Sv zdpP}>-Crl1R`VPm??tz!8kF*~bJDTq3371W`~*kg>K1v1Xj?^DeZO23?EqO6)hrk% zd8ZUrLG$E{Hir0ZY8=B_&?%urkB;ks4v|0p<6DnMKgqq2kw<^qOxfkDftBd^iD=Dv zKD2l@nzpSEE2D%~xUbKX%`CsrtJK2VGZACzOrX|1=|v3R)tG|Qv*q*fPJumY2+G>k z3oB(o8;e_}Pb#aC)S8w^Ndn94{ZhxlT%-@!&i!mSn>yo!28LNg?Kz)2%HI%J4_r_% zJgU&Sx5u_eo}4}xXF;tk_Q7ltBSnYAG^w-RZ!a=btfQUvh3C6Fn}M@MUq6w8BQ#Q^ zr1hDV+c1;a!>bvS*sEvWBu(evrYH@telcW?^KLqy%s?GuB2BNP<=Hz%&BZVx)iND$ zt#;`PIhl{K;OA5~>t>=cXY*<9KuC)vLds5ay7>HZrV?UDX3Xp8>*{oO%IxZTHR1Tn ztER}cr?<%A${k)zZIjz-!uypV5PNC1*ELftuB{PY96HY)teu52<(zlN6JHRh%ozDD zUoxfS^<^(@0>dvif#mI~$Da6Kfac+t^BKGzv;~JxNDJaLxYz( z1?P^E+nqN4;iZ8?4tiy&P~-depcwk_3`D zDFs1yJ9Am1X__ zH9vE9j8dpBS@1l2t~F->2p4W2w8|>$MtGbc=n1zspRheOYPdetTr_YGbRKn&M;odq}Ory@eao&-MRYt z@JWV&!-UIeIC97pZAZsC26h6I0I`?TlmPW0Cp&sNSAs%#r_rY`V0d;ki-wJmpdRfc z9Aj^Fs%D!6R$+`QLH?A!6-rElpllVzJ9!^fyZN=Ot@6?^`M>Fn`=;_^0<$seVBe+*{QP8mXf0OaE&nE)Up6KnG*r56 zF_})7o5eGDP|TCm?FPcZB%sP5L~mqpbMh@k4e7i{>#>g|-8svQSZn{Q4_PApo7&7G z&{G0CNw+-Sw<7kq^J4mwIn!?~Ml{;3;O21+L!L$qt*IWfNtQp|w9**N2%N^qc_?^1 znZrTf*@QqTjWR-06L0J!+U%B_ZmhE#cxdi1_KE;5){T5de8Ckiwt|8`PiC=Yq#8{W zi*+FH{1G6+n=}ZvF`xyA>4@B zCOh;&5q(^&ifsJk(LLJwkr%4jgc4yiL?BG|`))^@3d(dOYoH+dul1<>FPe6pn8evsg);Q z(I><`hU680tZR4Z&uJ5X+T}aCNfLpC?XJ0sdqsAtl{4BkHAH9R-(GYcUvryU>yAq6 zh;bqn7=HXg3LbspJ0?hVcg$9Vh#Gd06!n{8w52_~?6a-@5>{4>X8QmVR3;6&fWQ_^ z)BF6AzR_c3(%>%kGfi)b1+r=4REmZtbIcX~y`t)D=)nSo3_~F-_;4}9RpR^z@g9gx zS!+64-F|s`PJvEd&B(fedw3p9{Lbmkru-yxapgsQ>a-5;q7ThtBk|n2sjYeq&+NSM zPiLZ@F5$k!O3^uBZi=QOFK}|Fj%&okWC!K}xpjO` z9~XK-?qk5BQ$;z%tJKIeV1RPJXn_1+H4+X)OjNf>fgL&Y!1vScL;KnHuT)JpA9`me zs|ul#Di)BIehl|}JU$413@^suLxOph(Dy}9lJxb1L!hsRiCE?1j&>B)M4Dh*rAo&) zs2csG8u*0Xg10gP*aHSw^FHj%Se!0@cE8$51A@W_%BcoTfF;GC>WPrIhouw+D!$d4JbEZ^ySlZ5IFAk1Z-1oVxQskN?>fa@de z7PltYnAb0^Kqjl)iFz%mD}xz&tBdH76B(nZ8ww28cW1cx zRIqNA5T+`v&i3#+-g4dK%3E$q)MGFcOCpDGys;d7=`qLLIlj~w)_)J{A&eF2a; zm4vrXoDCt!glIQfi4*$iGd%<&&Itog4-2WE4D3EJaCSjj2z9tj^V&>zjytPzc)Gfd z@QCegbVK;(iC00b$HSZ>1_d4+hvX#MVEv3aQ+)@F>CXlIX0Ibaf=nK%Eur@d4Yr#( zKOdOV+$&SFla=RTVqjn_p78B6&6?rV^)Al0lM|4$lX9$zqQX*XJE6UmTUpQhD%)RYZB8c;r)5I7?mC3)eKiy))Um*xoPE7Ii1C(*82- z*{q9sqV#*RF9elsE_u||(Jr@5Wz^qh`kqh{dn?@W<-;n37xb;}SmsVw4DR+Vd)H3; zX4O}O16v1_KYE6F33u6(WnOc(oX?_;UmNI)OeTW|rve!TVq58BCxp8yvSH$2T5i@Ot9%4=BA zC-Zq8NXsYjrgKRMBBu~q08?~Rxt)wUL8k{z8pY=ok32~SN#$*!+Esya`8NUs)+Y5;!`ih7^y zGR^GS?XkB=S`}kpx}|XR@!qM5(CV&KpIK2X3dFvizHPSFGvA7hDzrk z7R|g?9SPHN-YQ(=x>r6zF8+ghf8P-V<~!r+Ir5wt*b?RZZ!EdE%jML)U#G-LzEZzB zIP`yZ|H~JZM*`<+;YxShPa5?dW^}6W4<|?Zde9zjyyE{#BzQ8==eFnVv8lbkyMW4M zNuxS~)EYa zM1HSi10|#wQAiy5;o_6Hqgp3|tC^VTE;h@1wNXUR7el*pywYwvEWDjK#Jzudl9MGI zUFdVhGUNdl9iiui)BI(%;{MH6?B@WG7lx_1B--;g6&_lhSam4JoLjoLDB93UMZ|B6 z8MQsEOnPfw7VNv#QHY3E3n&z@X}eAJz_mFE6_p;LYJ|}`%M>3UA}lYIhzh(z1wc5) ziBJa@q`%6Gqu_n1En-zApsLJ=AjMOFE3bGH^PU*reo|2uc19R&sqfP2&4-ZD1I;!z za8-r=dyfjTVcGZIxJ@EL0fqjzeXkDSzqn4HB;w3VHdA(I4S2p-H-`j?t{APDNIz3? z4GCLfi$GvGr5zz|DbJEeWF^Gy+=4inf0SvVuz-)}QoGA8(HfG5^4Js1U=>i0Qf3s% z&he22SAQtD+PD^XoeA9gwWqxc$0gd1qq#G^vMN}(>1uX&XXfN{)#5{;=c?xf5uU=oy8M1^VhO8_=4vIRl=BU;X`{@pt;*=S)>UCt5Ii{^aMCPi( zahR#C!>P2KyZA)>w(oQ#nvzirefbj zIwM>XSGGht=aJpu6{%7*Nk)5P!Ff}-Gs`WN7s#e07Qg_F!tR8zv;m!bLSrSLN+hkm zG>n^6&=+IEDEW)6tkg%RCezlf5Zb&T)^REpZOv=^qD^hWotYjRQE8dN`(I_e3R)X9 zBM8UscZy0ko9sQ_j0~|moatZeZ9H^%)tJ9~-Wrb%wD9aOeX24K(OhjwZ?ZozRGSxU zIuJdjaGNv`(W_}~d^k3fv{f#vyPk;Azs~-NP?kalg0jcBgPUQC(Ktu_>G8*m16BcS z>u_t05ZBv5NZ9hZ&VEOwo5}Q8oh=WJqJVm?6{Jk~@j~e9T6J~y&i9zv0M^)VW$SiS zv4H6q6yT5>I~}>@UMM%TgtaSIKtcqz)_Rab|F@qy`hCyz-Q=L@4wJuQ)uwMRXhBRPBeJX^ANDNto z`b$-q-IyZa>ZA9d8LC*`oC^Roi3K`GQH=t3?GFUK!rYng{dyShY2j>Tn_%t+q3mbw z>ov&?sX?|ee1f#f_GPOR(;}=!YFAjY^~9{#94Ozn67QA}o)ADIBMb`iSEGusnBEZ( zXCfeiq*$hAvQ#ZskI_>GkR)*1DO5c{E=}tv7+@`<7xG6pmuCm$*QKrAAum&hU;ou# zR>dNq2JrPD=zKKBcqHK5XWGJ!xN!%+ZH2&+B?mbV<_}6)zHwFV=)`%8NJ&mwi&}rZ ziTV4!()Y*rxnK-}^mB9U(R;nk3*E$+zZ6AJxWg_e@D7OWsA76&>Zj>e<6}d;13%{GqG(|#j3QSbUNu)UZ0d?l_*$sV=tVT%9Jn(ezq85KEczC-Q|r)lC}+-W+7KTQAvx{3lHT zstXSZtC#z4&%$TaInQojVGV!OX;qcFjq1{B?1C%e0%URJ6?e>lyf{0?)_O6!ZrArt zFECpTKf~vrsEli_%{aK|o{?Oh7tK=|xuSGAPb7Q9edQF`@0h_%U;X{EIDj&VbGM*6 z0f!M^5$=7Sdu~XH-NpP5$>DNq_+NF;i?!YcXsp>0L0(TYl3FmtdHmdV*#k>zQ)ZLE zdxK=UUj!;&mk;TqO|zBl$HkW!ubYO$tGF3`v!kc5JQ3Y(?}sNp-sh)^w%o#d%_I0v zx4y);-xl9(C(!8YL|UY)a#=G%^NYT*%nz1C$J~Zo34>@j zXKvGvi00RfOra=tU&|tcfko>SE9w*^E&cvZw@G~GW-3TsIEEJ1jv9T)pO?-w#c!pX zL`Mj^(=_f9-{8bwWw~7jzA>MshM`=o&*E0^zi>OXd1D!^{&CAuf5M8bjNJ&mx&nGB zx)^-X8+LLH9K-HD>f*(H&8R1jz}!tHuKUh+XNw!E9TkbneG|dKimC|IFfagA(YKdej^TQBaHdOZb95mpykDUR9Xm#!k>u@GcQEf zod%$`u@B0q=yBtyDq*PPDB+|Qt20Zf=6C9Q5{lPdG(69>kxXH+OTLNeh^|N7)N=)#d-e!1~hU;8`Ntp@xr!V2yBwM~fc|58NbL2a2>? zm7jNr-zcAce%cOL7X~V4i^&fVKx|7WJI+72stlEHF$m9tVki%i)(@@lI#JR@Xvg!C z{*VgC+fLSY&WT{gpmIsnIi|M~XWJchMruAt|3-s!R+^L0C!Din#PiNMk{HcEzxDta z)^fDQvFBNReJajBIE(?pvtyYYlTxWh50#&Z2vehA0Kg%cGNd`5--+nV6sG&yR}znI z%nBNg)6;O?!UYD#I@Rm_ofx3k^PNSOu`~bdrAoKy$C3n>UJ}rj4w`OZ|D!M@YUf|h ze~kpi?*p9JptQeLzE^)#8CGQW#hNl<)^Cw6u~+su#SB{JkWSW}{!|;VlgH?e(UW9= ztIRu_r`)Ix&&-?ZowcAJY!-ppL~e=RQqDWXX!?%~fju>gq6>(!mWuSlaClhJ+5 z4f6pE{K`-R?IlzC?yyW`XZ@+aVme{bt@k;v0FKXi*0;*&huhM4HufTesR;9g&e3^R z6>wGLDYDll-7mo}$xrAAJ@gobyX+6U4XMLXpL zk^Ub8CDqhXtNIfpLIj5+RXXgKM~*^dS#S{eWn}P%HPO&1BFQAAzL>O>ag zW)J^fqvUi+RPgj+=F_RyY5g%Zx{sW8SaI8nh_3d@fW4oha1D$}MvizBgl@oi!9VD` zh#M=v(wbaIM&?R2e^w}pBo(Ve(aSR%tw>8kv#%&x0e?V)H7W*O)j=&Dp+ z?z(VxN$ZrFLd~0-`n~`D&u!PEqGn2;apd>-Xwm!%uguU`lrHvH3{vt*7us|l8J%Qs zE0}?MAz#k09`K;Gi9tPLEX@$rAU4E>IlYWtjvK61UR_{QiK4prnu&s1{tXeb>Q6z; zTO@k)yzA+Ra`%{=2&)Q|9>coG)wxYsHB18pQ0X*erYrwT~4M~H? z;Cs{wFpSu&Iol$qAmrA??jx2Y(r5>1f3n4U0?66?J5xX?BzsiS>big85&O5qzY0(4VM{Ao>`XV!4F*5Lig`ZY+YwGgdt!1>l!)^^~_tV{9t z1<`7I?a zK=ckXZ@35|H8oY)Qh`)lS%BA*f!73qda9x)QwKzvK#&5s{!0R4D+9jM&dVxuE0GuYbRqKsou*LHkb-(p(P#c0HOQ8Q zMxF9lPs;+`p|QC__clfE9rLoytgUW5ea2<9JM$npDRhh!bJ5=we6p(X}|3r+TPY@e!uJ zcHI$G)98BFzm2$4C5Z%$mK=658RU5E=_0R}g`WKOR&n?F!H)m_jS?zGEMA&mU!6~o zooK^f4mahDy~55Xk{mVB1vKJ1$4EIQyVPfT0zG?|{Y5KAEPRT#(4iNNqOO2Xk%HQm zN}WYlomMX5;)hxpfNu0dDrri(u%OXlgV!QM9@NYA>$y5=Y9=qeg<-&$v_jAg(I1ZR zCRrQnHgd0t*_WP?{P6Im0@=uU8j@bJ$%yqENoirY2y*64kUa&S3N+V=9&KT`3V$-j zw$hg-vmtA=&VS5N-i&z3t{X>kfK#}tGN5fhpmFXlg-8`%i447WnwNI7&Hwn(;SDx? zcHKaVzVDN0&=fLRmMoE%>fp1}Hu8yIs6ZZdmK-SveZWU9s>r!mLl0Xda}T_&qq}q> z(}@_fx(1<7d8ezRv}&KyAUjsW5A7F8=4u?4D8nRQ+=Y<$w7xYh&&!f|!vFK;tU%f8 zr+A#yLG4;<@-tKLQl6xF=`fMa8hHx0zbkDbFZ5cKlOIsCJ8yZKzB0N(#001eXJyD} z6P`1Yd223&Q&JrCps+*4KfBEFjlMXUnl7S;fh9&vU?m8%Y#zAE$=>peWIo3K+et^} z99(Xj8>e&z=1^Jiq03b(z!$9Yr@oW5RS4@Cx?u@tcYe-$jLb6I`Zm+3wUEFRg;cU2 zxYb3Ti|P>5-%GXgWJBmsF@Ys+4Qze%dv5HpM$vqW z_S?!)T-8HG;dI)b| zOSUnNxAc~pqG}m!uE^ZTiG@<9*FeN!$m5*P%8QCKsbW(7twXmX9hvQaBs9h(avI-~ zw&iuBV1s(_Mwh9EYxo+<)D!&nGmED6#4C|&j{W)tqJ7iSjn^g&O)Wi0MerNnQKnzcQ2(?DuO@44LwybO%c3S)rYmaXGrI&Cw6i${RmDS z@=EMNQULHl1DG6}w=Eo{4L407AB?pwB|*veS}-3Xc)&RLd$De!Fn zVn5YR%&=ZQIW;vkJ26`@3sHee$;jxTwv+Xh{fYdAL1w+p6KCs)ug+u3Y7{AF<>k(bf7N~flVMGiL?mj4HCy7Y$$ zf)KxD$k@N1I$i?VrXrMHpPD#bnqTUZc%HCDwHnIO1Jb-g>oQQ&4G+1}1)yQsvIS7J z5>;z6(nqo6;|5q`dGY0MPp+H(%>K^%@9)p+Z?9j5*X(|B`$Y(Xg99G4sS|$rM|%j+ z^M;punaPV5)HF4fw0Pwubds8`kC zGTKi89k+)lx(lH5*gb_gn1F&cH5X3R?dtyP+@-l!1;Xtx-hl)SIXMjW_K|5A! z4(I^}>gsmbp)Ln=n)lXAJUbbeOm3(_l3d`rW8>oxGoiw!;>guZrlINO)I}O{STc`- z$`FR4x%0^=(26GjC@HAa`cH7F6(!L#`|9-4VDhk|R!g_&f`p()%Fv+i;XQM$4cyp! z+yku*>aeFPThe;EDdU^nEjEi8v$<%vRvk{7cm1caB)pGOcGxfqGv<}A+jbAUO(3s` zethi3oF7XMmw)pI2t6h)9&m)R1%+cz3n%NKpE-ITZ+vA>-oL;m=*-*^VLmevdIB8> zzY`AQBvZj2NYzK_;wpBPvXA(bRJ`ok#D+7hiL3hbyz~{W$@J8gOs*X}Qx)%_;5snO zI2+0hy?c#{`xxw1?t4>*JfLvIxNhF$;XCmK5b)wqOOxx&;Jg>>Osuc6TiPV@LQn68 zHo68L@apR9e&3Zh)do;VIDSQMvE7|IE(9qM<{gb@`%3bVBWrt~XC^YN%53!I_GK)w zp1)ysGQ(B|SU`q>uIF3kJHcCMg}d`j!eS3P3&NA2rrKj;XRy(f$E5*nu_xT;Tugnj zsd{0|IGWVY*p-(gMosTWrwY%hos7lDZr@gOCqg|PbmYlUFA=hi{W}?vaJ6Z}u9erx z%+uNZx=nO0C)`M|!tnlXW$tEX4dtlq`Scn(jzpE^g!MWWcy3jofVd%%@B!N(Bu{hr zdeebnJ#Rzo1SJ5WW%a&Gs^Wb189F^WrQZ$K$W$dWEjqtDRKNiAlwLC>raol;BWJi| z`2+^#}hSOy9 zs9Xk8l_}M|!8-Ai>-WFMfb{DGL=h5ds0}nQBKe(7d7A|EB*a`MFw0iXt1a6P3`Q1b zY&Ko``zTYk?lC=^GEAwub zY4Tn!kWRHGDx+2*{Q`?Z}r*^KWQya zAvrIGy4EGLW;u;{u;F(0<3C34^i(Ify*j~cYtKK54399Fr{dLoaQSW?qRC*Pjd)TY zOf{Ah@-pt7ZX=}@msYhlYGTK-nSlqMQMyVEC>Rm-0?ja@u+$lkR@c5nR6l&=c8bcJ zmGsSODP{R;HWAG$p99JV+p3H10QFPcakZ^Am`TNTqJ#v^6diWhdd_{2#g1JI4r9=%Ax z6r_ukBAP)S6pQ$$h5+Tvf~h{8;zW5zI_rs((+JnFwRo!3nK?fOkbkz2zm2E!h_PLU z-ok}hsYHLhutIu*Kj=@n1b*W88-I3%6Mt6CvYELOBf5;I)aA~fxrKzWCRWaXc}%#8 zU_*Qye=6XNat_o9>8v8JMGP5m;%nloYh3{N*eG~`I7BhE=y;_1I0#X6OOS%_7~l(bY;$pJa-+RGU<)*{A$Y_FOfY-#N|j(? znk-Q9>0)>7LQqSR!9eML6<~=WO3yhYNf2@Q2og)dKp|do{#dFdc^gxRKw=hq9{iQ^ z!(_^GsD%pR^$sBZF(l(5qn!I*aL5R0B9mh0SweX`j@rbbeuGom6iRrZ zaujGU=r1j3#36aH2vJhi0N@x(0f_^^PeLV#3~2IXOJhV^wnXSQCh=rQM7bsYV~7Un zKN`rvnduMdWl9<(TPcv@!;TKrvY^cy4d_-CEdKmufvRE$4J&(0jd8&^%25&>nYFGC~J@NH2SI;9h;f-I){MphgVv z@R2c4zz7EF^6u^6*EukKd9q-8=jZ+m4@u|wOWWf$VXx{Y-J{mXz9RQPKl&s z?tQlE26oGu%MYZ!1aof#Yx0Nf;`L(I`J#NT3V#}3+%>nn0(x2RXWM$)dat#v4#1*d zzN$vq{F0;CYx1ZHT}fqZGj+8M#if#3)pR6fWhlL!e{e)p)}oBwV+4(U9@f#2w3xJt z-oi{IZ`~(5H(Otr!aP=Q;2d{0xhu@u?F436=`B>Wif%)Vr$%CoEeWs$S031wZpxhd zyJ2-CYw`+$x~iArf}X37wAZv<;;QCB*5R*_BV7KLN@7@N%R{V7Eoh z4(II|PW;OaMzK69D&6cltygu}-=;}4GGb`LG9u4dlaNe}gnpZ@f7))|d-*KfHw+}~ zzNCe^y#_{GKCj|I<`QshavZ}cbR_u0r!hF6h zj5w+z;2d=BO*iI)sdjyI6!~6k#4M`iQc-HY9g2cAwg|M`bxcok*TGly zc;{)QeZJG?-dYvAqUiao{jzq`EGp63e4WLw{@r+gWR490!n3&9?R0$Cva>%N8E>y# zJ~~KG5)$P`=k0RT8h}WN)BbJv8ml6!RXxrE@?F1BVzQk*_EK{BW;K?o8Gdeggu9lp zbF1Ng9_jdeY%qT`d7n3GXmh2tqPD1l)8;3F+9n-QzQyKKdx||B{CgxtcwV~?_pP{s zQ)}CqiTJll zkh%Jvp|{Rwite6O7K7^1;HnL7z|ZeCwOYLY^wcQobqP1+ z5oLFkp!U#tQqPy=bm;We)QjndM|fPx<>7`*TRP6f6V9WM_%1`#;$5Cjir3ol#_!F_5p9axP2=&8_>#T+ zus{vaa;!K5ge6J1mHZsnGS@PGP__VJStE@2KV~-72;`>7F-I`Sa($L#Wo`VjXXqpJ z1S)}nTVt98Wz-|?v3y;n{!$j}+_wC=z-j`<33w0zq>9R9u8f?qku}`{QIHYLCk?eF zvLwt_)jrb8KaBuK3__RYprybO1%eB}LvDrFj8zr6CxFkCaEP!+fHK7Yvydu@DF#MnThTHH|VZ%pq#N+J<@M;UO!u!ZgsA% zU|rGr4g?GvqR7Tc`0rqPBn%`ZfWZ?HF(eB~H0;Lfb=DcJr5bhEBsPcc$0atF$fgGr zX(n#QBaF_QWhgfrHWy#8s}v5F9CWB;6i3G`X2xH7nV{f{kA^IWm6C76ax%Pbw=z0j zdw;)we`f;m2fzuiT(LFNb9Nk}zt8;I;_*GfU7VU0Kh1Q#N-lTtPddyHyq?xO)``00 zp$&+Yc|p}Iz~W$G@ZLp#KEe0%g1!b8bfVIFAEkb6K=#9WLD;^oOTcbk+vyI};C(;v z2H)v&d%Z_>=<KrdEr zg8@Nr(FpvYAGY0gTz-XIhC~T|)xi1Q!qRRuG`~Xlyf37{e`f#%{qBZzqTqCT{3iUp z4#V<$+*Uh2(fCIA-npCGupUltb^l&&b%@zj5u7;H5fJnGyyt%2*!9LTpY56`{yub{ z(&F)2|1b>Td7%=73JJ4%UsL5}e@yss*vNi^C`teb(tT|`F>>^f?!I=v>^Ap;lE` zweoJ^=NO+X#_=uOn8G`l_GfA|-G7QrXh95-cmIb>8>+Og)_xf{rr9p{7PXbrKfN8f zZXaE86EQ%}gWdBs?YJMf>HlFX*^Tu#{uYxW84u(v#jj}d&NggD=Re%oqV}Ic@tp%5*dC*qBvY|bfW&bk(d2%+UC%ZrY zS`*U{K49Vn@;estUBU%_eZF-3;I4As*i?2b{G$#3`TIZPW&`~2lKCIUf0+tyl_>u2 zbo_6n|5vAnRemp_%0OtN1Tx|B=auMUZc|kN=SJpepzkqxu)x z-){dL7Q6pEE%X(PTj*u~oaoTwc)dLJbw6Dj z{`wy9^1|(W3ja7W!~47>^Zg~-{W-Jqed6vwOZvX1toHp!y}q zIb3CEx%pasYm+P)m_|>uxTxYc<9AVxR-3x&xVp`*n{Qj@3Q|&;a&IBaF_@TnjCfXx5AI~|gs%Xf=-kEn*u^UQ<%IkO2#wGJ$ z8t;p@WidQHj^FIiy+(aFxJ**$r`cLYFv=elA8u|q!#tf~FiNNZ*~VcFxaNjsc1}4< z+F}7BH|Qs%n7fm2CyU;Wi%zOEvwhf~i$ZzL^6KD7fu;U7QvQs!gIp57Q@{#<379+{ z`DW(*A+34Uv#$IW{ACE}oOB%#Fv__s zpL_~1sxaApWkQ};RaIB_Dwx{l_Ga-1t_S>xlo<-Y(b$tvD%0*1RU-!r0Lv-Xpb2`t zeESu>r zB!yOw?<>R3mx@h|x+V=R-XmJ~)P4hGU3&*Q##-k0@#?yo#H7ObonRnd1$|k3KpRkO zTOIX{r4IHOYMOqEmp2nEZNP(Jas5RZgy*tW@9}MOPpGK*$fc6J*Ddbso~LLLjtGbD zg;>+8mIpg{0if+lc+Ld3xNZr~RdZ8ci6IdCdtyD+NW5G|9Re_iCExnd(~* zDf=%asqz~_uy-BW_h_^I_=%?;QKx}cZh}rg=kZ-7X5ZdOmGr~>src;mqGn^Z79h2RtdLNO(a>#gA{`Z+~df$qBi8+QEi4 z|I|n(Rdu5}S@$q;_dk1$m7KQ#K+y#y_BkV-rs!GKVYae)m&1EE?-8MCDI$P&4hvun zEE1m2sF3(GGjsk8g~`Nn{j+dKUgt!5HYP|mh%yV}1DTU5R!!3WD3WJ=PIbM@39ReX zPo~u*flCJhN2mterVC*wJwy_pWJek~lQa+~$?FwJYfY^h7>C}Rkqy-~q(}7@`=o3A ziwa4ScFXS^`t&fEqp_ahcDhi*m6g)8uOc`a`0p!lzat$EtYM%MJ=WJ>a98L~xTXm! zoEraG@Q;^$`ARRLOa5lW+oyTixdK_hVR@+cE{1i2bj_a|RG{_e@VmS#&} zCc|zmge0Rb|2&p&QDL_bu+W03pD)tku?=^TZwj8qxH7WLkJG@s!`fF!A{o zhvZrm$grqjBK9TdksyVn2S5CLo5aaN3P!>LMnX=gXm4N^Fs7@`2==11TCE+w_NFi4 zTGdtawEl4*CrR|oa8E=HCDNNnqLC3s>F z^9X3Cj9W^T3`o!l@IM_mFw_qV92NyMtRNyD2w~rD?D*Z8f6GHCwm09Cp&@nDb!QGu1y)kadv4U-Lddy05YO}UIlC`!xjkT*hiiK%$5(E3YmC!GGbEnVcR^FS#wWc?Y zb5?b9^0CqJ-F>~)gG<%cR+hNAxHxl7%jVcMalJL8$i=2*ed_8=cWSDi^`g{q{o_~* zu-Pg|)YdXLV-s+w+>?{_w9yfv&BeB}JQHJL)G=>OqBh&=)M8D^CTbeLnGy>-r^sDe3! z)N;aU!NE0_gO(+ubQC+#L@LT7W`A8YXq4{2Y`$TlhsyACtS8m^Oc{!AnG%=83*1|4 zK#9ir>!{*gB|6WR_x(Pu=<2CwrAh3RZ`tt{)c0J2h-lsrxeh~41PV23cLA>*w2ELOt~;Sj0ro8TRy$+U&k%0?40=_+)cSnw_pAY}0~Oy9 zMn&8k1%DBYZ;A)b3J`u{h>x~rCpB0ku<7H49VOSM0bA7|2fVSprlcW9z^?)My!!yx zuIXz^>{sw-#Bqe(iYOj`KC-1;BCXkguA1R^;yz+3e}(EqkeEQgAdC&QB%brlh`|8V zZn{2B(;X11Q`T+NZ5$nCv%#fFwj_GKu&2I&JTBM6qNqC+G04J~0JM%Ca{P<$NF5f$ zZOs&!I8*E*p(@OiLon+$$8=^kM>RLXys<8ylnOLW!1XHmDVN7)V-7@&$&e_yF%OK0 zvaRUStQS`S8Wmbe2X|NidG)(^H#wNannZw69WEgmgtrM0~`i7Y#yiYwKu%_#SKdrds+i#+n<#gJMAi{8AZsc zv!tMd(4yW@Xn>Hcn(DgOGF^e$Ow!nF9d^TxKjkz(6!tVXZe;%FA#`Xp&uJbT`}fi* zVef7Gl%+j*i=}+tr{r6c2(OrUTksP^BFIPkj5bxeh?>I^l_P^Xkii=kQ!;i|EI)<# z9t6pEUAQ@2vNI&I9|8VZTEGI2V!a{noi z@sdw)z;oMkJ2tLP<{yb|oos^wn`%v9q)OOjOD5fi314S}aq*E5r7liLVjz6?l#_PI zDMu;(5qhpsmpb`ghjr?>N4!0|EIj*7P@cOdhcpjR7@UtdKGAd^wZZ)08A!TJ(Alc4 zFl;n}xO^ajIv1}T@L2yJU?KrTm@wqwj}~>^aE*6R^IDN1u9EzYFH)*VH|@yI?`mxd zJ#rK}RY^3;&b01$3B4yqG;U<0<8oXFy0eEDsm=*TG{UPFDFgr;sN$38&6&4WNwL`Y zAA1nE1ZISFd$CQbq7uY&4serpUdmdTDR(hO`IQ7U0r>As{H+PCL<_A_OGgi~ln8Ow z+55x^DtvN`J?>rD~{B)K7&BCafnW8nr`c#UtuSqN&Z1QkXq;&hZ-5R2!+FYFghKfR)P0E+IOk{qW>N-$OChKnBZSPm8l6eF|=zAGuU|@wBN(UJQ zk3UR*k<&bATUSXS5fg^MXK~xCHTFOP%s5sn!XO=yrO_wjZ%ZJr`9%GKdjKl19~2r4 zjvWxi2nA(djDrmYp}x( z9A9bJ39gf^F|xWEV$5Wsr`P4A<)BQ|QaqV;GUZwN*Xt(leKL=(!Y2lvn9Zx^e*iuR zJSoiO>;@SM6|%*_=a2;eecXV}x_Rn}HtpvK8#pyXN8Si65Z2#85Fou9xH%!mMO^Cc zrs}Y6kOrcysVv)Ye%(4L{jztdFcNcCmq%T%(&@JZrs46L4y(13obPoXXmVD5a6h1) zSngCdoEl+l&CSW(wY9Gd4-^EjjVC~fQrj3`ohbxeozkdEzR_npvOdy#BHvkbYOiYs z>dz7`gk2V2G6zdrw?vC;TYtem06s|H@~JUJZlEmMxbk*`Sra~!ctd8xhsT&COJ%kY+o zG-)x8*+Y+yC86E?ln$k`gkh^z71!pW~QhBG>V`#SEcrvQYNvkfjl@H!5vKcifG8GFIh381V zoGYYI!dT1%onEpIPNu856C5($^fghGFZE8YqD;`;+z0QQ^+BD151m_Yqy-Hao(XSSXyuhBuzzUGO zCh9kHrc3gb9MU8{?$|X{ozKmq`fD_|0b4`sL=r+`C;>ZXC=X z&&;V&%azPfhsC%cRjE=2Y^$G}b@4_NvSN<xUJjcEaAtANm2|N zn*ZU$I2!latK~P1vQW)G``^;*aCNctY$k?;71l8_s3}ed?l;mdCZVFpEPZ^s^i)|v zM;`5PpyQxWFaL&eBnhc3@cH%m%TI=vEruQq8D{tE*kK6zM1>C43v{i7QPJyN7B$z} z@WBZg2pd^*Pj|pC;4Bc4eLRo-RN}s?*^fAAaGBWG8jpvnPfV81p?LVYMUS&t=fquj z7T1cg2E97Tj7Q~>N~&Elu=K}`0nRt*&NZkBjIuLFC&G|aaE^_idIa@W>Izg9)D-K` zYgM|WGuY~{6*4p^*A9nH7IR^p@Tdozsdx5a|H0~lIZO_08`F13T9XsA58Ah^_SaAq z$CRXaiHI`oe(Ol?PG?J&mPOK0TONi>KsZ7_jVNC>xlg3N)Sx+^BpM>~y#5XO`D3__ zz(_VEO^SGai!lKM5x8yFJDv@`4dCvtUkHXlKVVSnDf4l$ZxzkL5p{^j`Ws;$9-p2O zzn30QMgX&EHW5i=9`zks10^!LPosb`Sy~i<6jez1WEo1jREndO0taWlSGmrw)&s^Q z80gXu(Oi;{AubW!S@ajhnSWbrO@%yV32D85UQ4 zC+CPLz~5xGAESz}c zQSzXsR$A2Lny#TG{5Nvdn?@DvXXOwVeof3X;(JjKWznv2a*%iclbO*&Dz8HV4K>FcZWpEj>8YYA+1&u8duF9N9xnZJc zo*PoKuC)Pi?gMd&uo&d_bS$=)oWmG#R5F{040%f(Yc&zsKz33Ncw8>Zjol@7nScoN zChAzF_2BDbVp$okgy@8M46`L^uK6jVW#Y24Yt?Ag;pI{$OME8F>5itm!E(6~M7w(w@+W5S_3mA>@9ebBO23t7i7^ zuBl)m@EJ{_M?%zog3Tsmxpf&^@}=A%ZKg(@)u}uq6T`;>5^2yYDabtr!-T4|mv=)6 zWO*&#N~m7QgE8!t6emg+AtowZIjigCY0r;I3M*$-&y%3H>y`1!Y+m>3Kep4z8ZxX# z;D5uRbdOY?RMhE;`>Nvn^}@{OChbEND%7e{b~I^JHKIUQmkG}J=5L?*=^-oVbtCFL z5*6P&DOu8ASfXphh@not4qJkUhCf*MHT&uBbW=<;bf0a(N_u0|fev3bn=*Xwh&$QK z(FgiFG*l+k5E;!}Y%1+#r}k3TOxW;HOjO1wEAz*TczEXUIMC2M>#-vI@;YUqE8CRdft>?<-MiCx~Yg@V(yUsiTq+b&38`Ic^EDJJkH_AA?TsTxQ z18kk6NS%wEvjEO{5jwGD#Gb!tg)L3A&T7{hEb$h(eu7WxcUEf3oU$Ant09z9^~L0L z;F-V*8QTYKVuei`dEe33^yT*IZQaZ|DN#?YN$i9->V))udCnSwYz4~ZESiIFMBJEJ z^|qGql!i7DAsRT?$z8WStJJge&|d8_?#WDHaS$79qM~j+;=ua@+)oDtC8fI~*aHJ# z4?-^Gl*7WpxGn=OhmhgmaugXshN{R4np@}5fmecs>yAXA61>T$81D&H8duy8zsbBV z@TVHh$Jfr@HLPKQ8%-cx)hJid!n>^XSNk(~&5+b1jT+Gvj%@yp3nTBaY$d($?-)+Y zrG+oT%_XM`3bU_Cps3-B2y>Dy@(2vCQfD0)B14QUHsKq5Q$Y; zP*7!+&RK*GIVMR(gIc`;8$ z$8BJuo2-w7h}|7Ip-XyRHxs#>ke5`W4r?)#zD}cC5A0jvXKqcpWZ>XChFgN!re`J7 z4mIH*xq&vt$VHhh@cXQ)CFw}r6ZKmG^;upQ+b;eG)g$f9|GkiAta{S_K)l5cb_vas zJCBwaijsF&0$zvip&JX4DX<~}Ikk=lIzJD;5i){RVZg9Hh@2rVyrr_KfQ5$^mh1~c zAot{(yb8M-lrM&rR<4#(xx_H4#)H5SuIA%WUkccSll;rgL?5eUNk?tO!Q&`>ed+jC zJsL4k3aNE-sFbg%6bvSlHFPdO&X9QK z%zZ_MvGHN9f()p}?b%Ir1B?}b=?s`i9}a<{4>n2>OH+oTfb8Pq*gI{F6GiTu8F9Ky zZYJ6x3^>Z6P+6`L?oELD_y7pC>MgzKskrSzkSSg|4L%4-dD*EcY0y%w@B}5%>ReTG zCn_0p%VxuHpu2#S$(}!Klo&FmrJoMO=dW-R1aeEBDZDuc9nCrw_;B@d-QE3?dXIA$ z6UxKF$ZFbkgtEDuGC9%@YbxOF6VbAx`xkZ%5yDCum4nJixCtaJ z2Ci!_9v}U@m55auF~zI{VG>^Yx-CO`Xj)dxdBlD^jr$n8-e7qh1lO`0VOtaP8aF39 z8usN?EJ=2yftqzf7tKshhYZ*V^XyXmPBq_1mTO*|J6yN`S{C#)P{}IuCeRvopj{NQ zI;}6VRwjKxAwohN&}%B1*Kk<7X*b!lK6BkhybNVi{31~}wN@d!$BLq)SdR3-dPI$Q zM}|ppXo+2gxu_$Kal=$pQbRB`0U7)pSvUMVfhM$CB7ar2KJt@OICIdPEP`cPympN{Tz^PHTD}c<<0PGz$EnJ zn?G8&0}HmnqtK%l>N2AT8c8ma!{Mz{@oe^y)o~<;gmD}Sv6q!u_zo!N_j!Yw!l5l5 zbeMl`xi{}5$GNLx6B@3^-V!XA*|jrrSzTYBFY0eqn zl)=iCg{394*G(k%?3DI66B`MVWya&f z#OCQsle#L;FOG`m)j;!RAGKm?R>dmzwIjgjvN<7vQ0d`ytl68NmJtyB zhgNs0Q25USC6w_2VT>1yd?%uN`qm&;RPF^v^-W?|RW|zvk4i#;ww))!2t4vEtJZ;M z@01*eTse#eOqA%xOq>6jEEs)_uVV--gQ%$VPLzA8Yeb6giFc`ML|l~S-&q0!GoK3n z3FKtB$`gRj3SAeZK2~T<ui?ZV zy0ALY51M()iNA)KOtl{XkwQTX8Lld^3T&27Jav#v0(Fqa9CY9)6sufA=R$A$n>h?? z!Wy%$Nn%LR=q$jBMuf0x9?b(GNm6O8o!p9b6Q%AdLpV2R8<`+2c5Jh$3@jCAY$9;7 zs4*DQQ99PpJVvoD9-3gxWFlOs)wC`lLhqdJstyn1W@(x<`SuA1dK=LL_435$Uy2+Q zjyDRGskPUxjccMr!DLp8u~@~332U_W_R&=c12Di6dOD?wwCPTDQ(ONI2&=oD5OQ`p zb=Gb+oV(k0dlwK+A$TAYc=zlIS{F2A1zLyOql$lxvrV6+quv(;;B4g3{|dGDE`j%~ zgHFwzOE|L?eWP#v_uqQ8EkZ=+c}l8~#PHGfP&dJ>Z+h~j(Q1n)p&o?*!ws3iKvWEy zfUSPm^pNO^FNi*l&VOXY@H+;t!;)4 z!b<7hauH}a)9X!r3LZJ#Smjb+JhlFrzAK~w>J3dyObmGvxT)|IWf@-7dY)r$R&&#i zU>5|eiuZw*IrgC(7S#}8nx(VNId0l5V|)>T$u)D8StIu}-eLxi&*f?9eDN`>tIO=v ztj>W)EvD9ITF%U-ecz>y9TOanTOJMREpJ}I(4^Lh|G4h}_*P}O9G)7RD`E01lmY`d zAMJ$23|V{WlfTKdYe|uI`YpDGNr!>jP&OX;9h-SQu06)g;P>*Zv#PVQQ>&(^ zgm+0%s?k~}^+?GQr-yj6u>rsd-P$?`X5{~C@4LgA>Xv?^hy}$00s>ML5RsN1LRWh4 zARwIpp@kAk=&wo@K|p$w-a)!F!3H9|NEHz2O0UxI*0-GZ7|wUU^WEp(`_I|`u=ixv ztohB%npv~MvqCL=pWzCZfZu89`)w!QPv37dqhPKPsJgMHf8~b!7d>fx3h0{QjR+~^ zw5w_ONGzoPEi%OYP{T7D!x4Or!r@Vou+qrKjiSN{gTtNu&|8CL)F=zy%%qAh30?QC zny)!vN}Lb6BZWBo^Uo)z`JZp?+927RAJjc>O-rBN zw9YGKyfy3g^>zF7Y-nJuSz-_Whng72D#32rdBU3g7L&?)P7t<2(91vcy0 zdT}km+UUl^ZXYg<9*p|Cd^b^E6f50YU8WR8)G%AcO)JLwsW7(o?B(tYcN$vczHD}@ z(tZEXB0?Xhb~yrF{$bkmqw)#uQWC{}SVa9@Yl!tdM_Cq5ji-6W z1;!Lxg?+dYy0WD2hjF1&_z|vV^7|p@Vrw?8*+5^=u-M$I-r`RPo5quHjXd~HW+UQP z7hGwqA@i`{88^sLG1{0ju5ZXK6a@x1wX7tV;^AK_29%2gP$pKx;TiYxYicy9tSMJe=7-QuXdn#F}GU;VoNuy)h!p}WzQnvc(vvsOGyV{vYatg9;qjtteX zStuDOIV*5~yKXYfIefUIZGGWwnC9B79B*YhAM^!hw-_!XGBM(;qvPNcn>(jw+^E9F z?<(q{E8k?j!`yR5?WXbn47|I&W_<@;whYTy(ECj+rd zlpL_>?z}e!vM3prs6hi=T`TaYP8PW~cWigDcn(kZtV^iUY7k?R#$j;8n~K|c$8_G$ zaO?CY%J0x)zd@NL{5--_A3al+oWSZmG*I!nw zO|MMw+mimkdsktalrFzWMZRq^`r&r>N&QWTy$C0^qLC_^Q1z?>7nG2?yZ7-16KY)+ zYh><3i^_TsnF_zso2MC=-kqB6Hig$+b8@ML%Th-$OlmsNSKUB=`#|cJV69gkYi3mI zy|uZpqU*d6%*CvlPl}s|2sOVb)fS^jeTE&BfIEB%y>O<|^yWqqZL`(3B~? ztF8DpOD6iB9**~?Tl1stdC+F-Bszhl*Sz2Eq@AA~r$?_o@=ev;HcdgR-V6nkY&Dea zrm=n4xJ^~o^6EbTUp`}?&hYIyWtA=}I|2FqA< zvj*A9e(T7~&9UJ<48!E5W(?*|0`H3AUdj3yT$=a9tQcoG_N0=9qMpJV0`XbsIzlM9tua<~qLcmw#mFciDl8r0nu^N0miy(j^q{KW^Ufs`!i(HniXBb~IYWd;wl_FQ&C6Z}^_VE| z8yGO!n#BbaHEqVOug-v_L-Wrjk2l~Ef3_?!XWY7PyL8o zDoyp`ri;Ph;l}363TOQ+OtRmed+zm)hgzubi_gXBlR@wbv`oCBCMG8}kVOAB@5WQT zN-v=TnS_HkOz%6eEqyo0CvSBp=W~TNrFB(Qe-XF8*-O3NmNa7a)os|1G`goknto}c z&{`MmRe*MT?jXRV~Vp_yFoQdIG#h&g>Ci5#xWP?v=)9Mc!7jmm! z+(XQ;!N2+Rh?URD$rTs!^tO0%hx0@eG)j3sSIC^u;iIid*q~WCsh3O8vU3jOqJMq$ zOS7ZXdsYF&rPn}nMAx3$BZMlt<{7Kl|NSjnv=!KvR|E^rh zsyG(Z*j$v^%z^yAoa8g77Y!wh`i9$1!OUQ`*Zl7^sYZ;03lz2MWbLa@_kVged#b3) z?AwB{c5IsKu*Po@d{I+%ZkMc1R1BANXT~v9ziz(DzP!GhP>3UsgBBdOco2YMm4LHq zA_#3AfjeY~n*@AfsLiu8)t{r;Lg`f33zf4`R}ZX4OgiK4j-!7|OVk-HL*qVmC)#t! zsGZPIv7ot+kPCE|8h4pAut@eeHpiBiAVB6>Huz+c#xL=dxujcV)o@&(bqB|;<{WjS z%MIUG5}a~% zqfr#~`j>l8dITvUYFqM$>&SF9@0d73`ciuIfPIx_3;Xj?$EbZ`ET#PKsmHQ2RKT|1%+^TDHn_RI-K3Z{R z@xhw4G{ZtA4-1KDv}65Y5L#RxYVdI-C9yLM%*L#{7%rGs>__KaO$;_g&8S@~&8X0&aI`n;Gp zsfgbv9#nNU|7MyQ%cLYNq#q?u`t;+H2Q3LA5uRBON6w zuC|XGh}R>Gfzjeg8)Z#4%?45|HTAbTv)CLvi?YJ2C;Zv=Q z!TCVz7T8*T>x+($0SgDyo5)Jd{NVB|_qi%(ZEo|g!L6OoEHxd?L|4gzd2$>cTW~%) zH=L#C8EMKnDoUtJ&fzME?_iZ9N%gM~pweEx9FJ7%xU5lfDH38H7`0BR3Bk)iUS6J< ze`0&OySyx{5ct+d@1DXgaOhPDb4QmxK}PWQSM$oN!gHU{*U2nm z+h(v{zV8Kf1PWai9bL*ga2JPS{Wh#L3oLJ*KSB3Z*Ah#~HF}Y0t8Xm(E^AP%2PNpSK3tlNF7xaY+#Ua62=H@?6siGJgJQ0p@_FB{@_s%srg*H-n= zu*Lh@iX!5jmWJKgxqQw6u4LP$ z!;n3LA?hd@4(+*$2iRe*#-}#5JC=% zOe2NwBSpOnPjv5DFf=z+R8>hnd_uqVKJ+|GTSe8GA$iIs?5sv6>QK<$UP3&0b48Eta_+h_YiT zXCPvo8>E5aJB4p?BRiexLWhWUy+Da~#@3oW;hBAXF&|2bzkYPe+udz3net9$&6HB= zc401osN$0X$WG?I``SuAWWAo>dLe%>3+G5uSY^8#`Z&G+^BvhRuI5LW;nfbF$TDZO zT&e+aDtdAP@)T7&Wq+%!_f1Mps~DZ3sDcUgv_kprImoT{cRUMcXxs+}3#yyWWeaD% z&N{2>DVWwbD-DG)tTH+u>g$Sh5Ky$fzFy20m9o_y-fjg+OSbacKhmM0&U_k%vcDx*1DMDUJ{ImTb z^;TCMgMR4ro`PPjkR{%gs-v4HvhN`(?*3wmBPyCM=*rVNCq{kCGT&-dUnE$tbZ+|$ zm7_zk!IXNkWm}P|y#D)OOr3;@gim7-!SvMN%-bNS^XH0hIF2BsR;S-PQDbKhXSJS& z5-Yc&s)Lke2$2)Fz-d<#nsUne^e__6S|u zy_e6^P|#b1Vg9agPtAaej$5*K5b{o8Y-!B zcAA@Hj@GeySHDZhJdJ2U4%9KYVqrV zYJGj<bAE>8`&Ck3Bqa`8AAkHrf?yfh7!INe>w8#R9vP+DJo&hM^r9M< z|A|MNAgwF%ddlHu<1d!qtbtiJwZ0|lMRDbs zw(SQ3MbjxG$eyJx?A=O>rhB@k9AB!0 zn@Cgi)F*wA*P*^(9td=!tzY=o38(^NY~Wi8AC7gxm21Tj(;!eQ*Xpg9=h0-3OK3rv z4QuB&$Ur`FeI1#}6_-IEo}qdw3eRs6Xam<^udlQqkPpX(luvBSu7XdqkuZpKsy|J8 z>z;!m2}qu4cMSw~{BC;!P~+$2BbRId`tDP490Zb27Da<3fj6r!JbQkE9CXuF zg!E5NkWXy>cXyETU0F?or(;Tq-TucwAhVE?>gG$=K_I4}WZ+T0eAVbL{{P~}NA8%t zS8i-FrC++Y&MeL??%MJFr%7gk($nUdRkhn5qh80n zmxtlE4j8zdjsD?M^M~dCG(w!6?dv=84D{X6>){=Cu*WmUjIrBpC zxMBOX5Is~FyY$2LCnKg$uCltnKkq;}sJPih(2AHc^~t}{@?OJ~bielDJnQg#>bMGj zp1MaoRcvc*==Hi-xT-?g+w`o&v9LL_k`NwmPR|jgdIGIphXUS`eNevNiFCire?DWb zU56z-val$&5G#~e6KkE3Q(4_Ia;L|+=TrR)A;-;>_{>FSRL__mz9#Pz-n_YPaVNoK zL~hIM$&gG>MVF1_tcSV6?kAI)AjPGurFO5Y=}WtFtHZOq!f|Q>v+M7>+iOSGKWZN$ ztJj5hzRthWbg8<%6>y>25!o}9xNxqTkaVyZ)v8m05ym<93(Zb<6yS3_ZR6Go=s)e- zRV>XnDQ*QM;4oX9`@r|SAq%vynZ{3$-Wg%@euVzwx$5M~?j=6Ly`|~s(wCu_3f<)4 zc3-LIZ-mk+YqraLUxp-`SDJ_PYP+2kirZh*9^w+i+MpuI*`ZfV=Hhb%u?9Jj-0T!008@N@3@E>gmX1Gt%8nB^@K9&*J0bM>euT zoj4O6YuqPmMy$TneHfiq$*_!f*LOD8?~#g38dVY@uP(aef-5zL)i9bjC*lLQZl$%; zeoa+7#e3I%lWZ`o8I!fgx9k2OzGu#{W~6QHc8L#Mxw2;Z#f&k2JAT4;O|!aHxSD|- zXY1f-{-ki6IWb=7psxRu$n(W&!dB9Y&u%VX-Z{I(##>;AR@lG18@>1Tig&$ml5W$h zR_(F)Vc3jkv~GR1NX}Rfok=YdQtb^zrr#5#LxqZ$ns>SPy^?N_wZqriwL{gUwoq6) zF%j?S^1UeyNu~O%gsDXA^g`(!H-cVP3oNB+HM;*U%f4biZxAq|FSd2nZ=CCJvV6Pc zTQKSeSq30aYeVX4`{km|XQ*a)anH?m_G?RPVQsbc{H3*6{+7ccn$_s763v|vz0p`R z#l)!Y7G3H$%k;bPv+RM>SvAx8j$zBjt_9|M80UK?R6ed~s0 zv^ivkWKN<xZ5hp9M)lYM)8_>yLx(<=!2qxOfue^9Wh=EWhq1isl(h zFAb1yGJ9Q)nLSTFCLi9P@+@6)B8V5Q00Q-7UjP9w3IEDR%Amy)-+dT?92g_1bi84A zodp#0BpO84DgaWRbtUB0MK#lgC0r|+R<%I@UW}ZrGlhy#KWs|Jl zLt{@KGxV#XxiQa4I>P~qInMjyfC}_k^&MHX4;TcxS4JSkEJ##Uff!O=0?L3hUY-R% z*gt0&UVEOD4MC^n(TqI~sO|{@Kak%#Rr{=Oth8--b4c>z?ZjE;bC;Ly(@AZ(u=>ae{bXW>p>o-8gIFX$n`2 z(13L-`f%VyCJ7$hf@eXn)^A`HE-gD_5SX<3UOZ5swEcOG8T|0qCjK^IF11$I^@XaX zFreqtAppe4d9Vzl-~ClB8rSjgHEK}9`nU~X?6^O51w8|u19^y6{-{xD%{yAV$AsOI zKt5*(=btsyo&@=}zX6={$JG!_P2zLB$4LdLkRk@qVDF>Zn|prLr)c0Q^Ha@UW(jead)E!8J2+iq$DTc+6b0~6ESzT#FCoW z+e$&;H?`*}-#L)7p9HBrYbiei`W)^wORz7+PPp??wydU0>&T@QZ1)Qe-(e|=AGMvj=%ZyqQ_1F z@yLG6aC-U2{^s{f8Dx1(_!;12A8Z*t5RCpH!#hdGZ-VPj`rKi+`;!Y$JniFg(ciQ^ zRW=n;qyVznlPvaTU@OFQQspE7(t-RR9;0vzQ`Bm`q8Blr$+0|l=DT9M2#rs#yHW0s zjZ;ZzFhkE|53Jh-l-VhAJE=6n_c5s9T^?Uf5=MSe)0Gk}_Ayd|0F=lxEUjrjrWjdgn z;5^JyL5mQL|obl`ZJ6un3+-G_xd z?HR&umDE_U-q_aLDJPc;=Vx9T1>x3%?ll)PIn2zSX9}F&)To$$pMsJW_o%9r{c6i; z+j;}fi0GhP`P6A&U8EQ9RfffTzT=iWqVj=4kL*QjcK+@q#YVTZm?ntONUKiDLg4G(VyZfuRz z8dpsP#_478@P(wz7=*Ym3OSF;n^Cg*$&r`3I8*VWCnu{S1w;cq?%RgR>@!fxB=FUm zY1?Y7upDx41TW#Ew@fEH9k+G{KG{DX6$$t2Pw$9NmUimTf8w@EX`G0=AYxfE6U{49 zSismCl_Mq+ye{is&>J{u_cV01iubCUqN0TBW@q60u3paRFlmSM=WJ?C)=0FSU!e3k zneecyfzB@%if9jNyT+g9#5=gh^Fj7zk8O_eFn#~6cX{Zum}4l0GR8ca7Fx9i=bVx7 zx7wbR=E&bYuxerYt}ySdzcRVfVpjJ?yyVOze@5P6@XVx^i2Im5zszco`Q$0{fzh#t znu8ls^h?|y60-(IW)^EEB1dQHFV6v2j`TYE}m zcXa;UT9@zda6(bTjU@FG6E5}ZpVJP3({*>5c3D`ow1bxj2b>aeJi5JX2ygo~d+$;G zg5BL*1IWxylIzTt_sZ*u3sV)B1pD2$b}$DTE|PB^Tu2mvswUN}e+6x~Zkt4t18<5- zH(l#;n)7p$S$2F?9;>XEa(G&+o2c(|bu|TA#y%`o;Z6iAs>`tlQ-16|Ga+7%f6b@D z?S3vTO~)*{QL?->s!6h3{`Ek1l;Rck+ziUbKuf|lg#Y)uxrg?tI{Zcn*-_0y#VR(v z_LEY-kBH{yIB~N6jQnXXh+1gS8Po<;M~<^v2&W}f()&{BAYgaaI4&#rtKb9&GD9 zyOMZnFzd+2wz%mhDVR`nv%8wqqnbs|V#eK6^XwSfThxxbZE^U-6^j{cAZw__bf(hs zc<)7=#hhug_xDb}8sH?9u)a^87W-nHdriA-N@n$(VNcB%*&hr=r9_DND@tl}bhk-5 zG_^vb@c6s(3@NeB?M#nj4BH_}R;a-`;ObZB+{udFnk%{qMZe{@& zm&SOCtwOev9vjFwuupW1raO*iXawQXlJzl3WweEm>!r39aCF1 z&=)cEEOcEPx4X5g7k7KLYSC|Edbx`&$D&_pntZL9C#mB`O_lePrAGzNXBdmnpIW2} zzX&8>o4C4$>v)$MwS~vIaCzK{mp>~#Lx{MxI%mF^W2NBnS^BNMgwG=fQP z*}fLW;=u}a8&;H&t846hBj$C75QU(hj&_Ms{$uNCTgq;ZtXX%bD&B><_+0u;9+@5Wc|XMutYTN*%kii42d0HZv<^_S z+L(10r-1ng9Qz~`^h3?^{1LyE6(u%qK5S;?jU;Csr2v zV^_VW8(!(^nAjTYU~>=sTVK|F{fxunWV@#9Oz_2yxSXdulbW*z%`PsUu2UO0f2oow zZ?|!2i=m;hnz7d+b-QP4&9}QX9X?*msfP$1M6j4~>_h03&KHq4l}?$Tn&Q4W#OBo0 zCu;4u{zlrmEhMn>LcbJQ*OD*k?2OU1oss9K_XWAcMJ}A}T3R5et=D{`PD%DBoppI| zeZ407_j{b|jM-1-?GRv)3Gh#Xz`#RX2YuItk$Y!5e~8+GRiJn3(oc7eT^>F6Lts5U zbxJ*9QK55*O~c2FkvcWm-*?tU$^Z2JqQ#}1_^1ln9m3rJuk)mrb_nVZy%?!dlBFbO zU51q(dX0|9r;Uv*PtUp(aozc;n4iS#mLxEdk+P4MOW99_>uZYJx|FKZZ)%g6?$=X7 zhHuxe1sF+T_k)EQ+nckWb0DwKUf!(Q=c{Ztz_1 z6F&vZuNSXNKRX$(ktj+U%}Pa|mLl$(qd=8Dz)J>K^5y6XpXQVIhzoq`93eAg(9?P! zRtc*rx}M&BA?RZH#Ob+8b_6ncP4%@6QrABV8khs3oE9OyltU9)EDO`gxfreNueYjU zbn%o7xH!SG!>Ok?RtEVNgyS&|WDY`flc$+dU2K{nbB@%eviZJD!2>XR)R4i+3;WwkF`Oz27Z3$cIF<0{t^6Xb* zlInRFj;E#kCgo-;-g9LOC`Z;+@B_&+-)atJRNYS|%nx{# zu&CIRS<#rvEMyn+V6*QyYnY70NoD&_t{=n=v)=UIzbY+yf0J(3s5RuHcIk8cIqs*- z*tC+7n6Ns92=j%S&w)%p>8)2fkebk*Q8k?} zaLc^dIfpfZ;VfNDjUqRdNJedG9m{mGz!xW{p^Cl^Qm6CB@0=h}dRoXw=gbmz3Rk$4HZ$sL;fiRywkuO4IzxR9UFo8L?uR=LC8@MTb#aq7h-i+mY&{X0%X3zT zrKhvn#?6kpE>(mvc?ja#3!G&Hy1tvN1{+{1YCh1iKccAd<|sxift^b4ic>pht_;zT zRPQR)Sj^4SC4J}L?%Ez1v`1i*im>xu?LE(z-jGt&>17SR7KSrw#h%odP`4uS@;#Gb zJ=e2Ieuhc4qCe!xVAiSTrNM*Y&WZ8+S>b`Qp_;OkYpTMkd$tP%4=0IJj*k+IWDj$gS}`kNn{_=Qq6rp5r@@3QVW#8fAXVAAvg>a|q+N z_xHA1w8Bs2(U4VUoEtiM@C9||q)7FlR+Ov*zTMcSGD|pbCO=TZ-%de2bqL3p9ede| zZkPH+)fYo8k_xrR4QiKIk|p)Kh)468SH-M88@a!X;mVaY4~lDhhd3Kpqj^WN+S+O+ zno35@H>b{W(YmjIs*?YgZFLE*0E6NB@@Y?dayy4adgM`Y06! zU8u@z0D;8$K8;vs^2PMBe55vLo3xC^MZ@%Ka4ffn9ae=irt?9Mvdyiet}#(DwUs?{ zyP1)*ECzyWk`!SHSX?Z;vUVfZ(SNEv~ss(G^ z7v2{RPVhc0+8cPUv*Z^_$UVJR9T#Z8D9E0&9x=W~vc7Ivc=vQxH1Y*mils9qmzzaM z(0uO29&=7f$Q7+k|GQtAS@lw4YEPPm>AlXrS3V_L^AJ)+HmT`6s7yM@rd3`dr}gnQ zkDkWan#o*EXO04Pj`uvCzMVYV@~@odEOiDlP+Cv)R$r42O*MuG%!eCf`|8Q65Za{ zqDd%|S(9P{QeSA>l8M1%zn9Y!KikV|u$VSKGV!e=YjABv&18PNx20&Ki-f&NalPw- z3HyM6f1|!Yv6tuj>~o?gd=8Hf>v<~ui?a%m%wT4mu_ZZ~E;Cq{83G1_^_caTe=`3h zL*S@CIRpiH)d_YOUIh%^$kYgL#H;3HjQ>Hnt04c!Ifl$IC=&ellQRWHT;T{kkt8Dsc?`yXW9>&!n{@K!?CVLT9S6c}<{m`u>Y)Qn$MT=I`Wz?0B* z3q0PApO@Fg#f8TO#)ES(=Y^orXkIXs7YgMDIJg}Nws<2~Zd*r|KP8A`98Dasc6cn# zmidQ7BV(KsUg-LD=0D`x{Y|c|BhOF8cua6Myub&%5FQxs4?(~^zp?|))X4Bt+s{FA7=jDV!PHUs_YeQ}_(PY!>GlWSzfq3V z*3{%LBiK1PSpPJEsR=K}8e@a8#XABDLw+i3YQm4l;;k{lKdpG%8vpx^HTDN;erqFJ zbD`_5+@=^aBPVP8bwIlx>R4m{xcSM?`wtnworwd+2#<64U5pyW{!e+rI3p|O>HMr; zB>d#~A>praz`f}|T=9RX*FQ=6sr%my_un)n5R-q|@}C^ZuT_`zU7-d{L>j#R*zV$BHu zosoaz{M`xvBU30S{MW{?vH8;;3JUzp$lDw=D2)G5;sJ{$s9x%L4xv^M9i2-!s?mWgqAhfW7NqjfU_)8WoH! z(4DvdZOFgqnE3wI4~b(P?W~Om!1hM{$L5(C@8E>_(f$B3{^*|2f8+kyJ>6BsnDMG% z-7w4$IGR@r=((8T%uqdMUR4|p4?KXGRe5D>&2Y?o;NS1Xbp<8)Zr>3@z<|Aygt!Bsf)(#>#k++Eof;9Av7gXpB#gB|LR|kw4IT@H4f&c@5{N~V4^wDa43<^Xapbd>k9v@3mSz4*5p6YfcF^CU$H^J5Cn{f z55h-GgTaYua3VWHz)0k;`a!^aNARHmkNu(_1dRCA1`r4Y`Kt{e5GWtf91u9Meh>tj zNM{HNLSzF7AC$;e5Hy@fKPVVUBo7K)zv2MGikJpR1F7qu{Q Date: Sun, 31 Dec 2023 23:54:38 +0800 Subject: [PATCH 25/26] src --- src/kernel/base/shellcmd/hwi_shellcmd.c | 37 ++++--- src/kernel/base/shellcmd/mempt_shellcmd.c | 64 ++++++++--- src/kernel/base/shellcmd/stack_shellcmd.c | 29 +++-- src/kernel/base/shellcmd/swtmr_shellcmd.c | 41 +++---- src/kernel/base/shellcmd/sysinfo_shellcmd.c | 54 ++++++++-- src/kernel/base/shellcmd/task_shellcmd.c | 112 +++++++++++++------- 6 files changed, 236 insertions(+), 101 deletions(-) diff --git a/src/kernel/base/shellcmd/hwi_shellcmd.c b/src/kernel/base/shellcmd/hwi_shellcmd.c index 5ea7227..30a7e5f 100644 --- a/src/kernel/base/shellcmd/hwi_shellcmd.c +++ b/src/kernel/base/shellcmd/hwi_shellcmd.c @@ -25,7 +25,11 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +/* +这个文件是针对LiteOS操作系统中的Shell命令编写的,主要实现了对硬件中断信息的获取和显示功能, +包括了对硬件中断的共享模式、响应次数、CPU利用率等信息的获取和显示。根据操作系统配置不同, +还包括了对CPU利用率的不同时间段(所有时间、最近10秒、最近1秒)的统计和显示。 +*/ #include "los_config.h" #ifdef LOSCFG_SHELL #ifdef LOSCFG_CPUP_INCLUDE_IRQ @@ -39,7 +43,7 @@ extern "C" { #endif /* __cplusplus */ #endif /* __cplusplus */ - +//这个函数实现了打印硬件中断信息的表头 LITE_OS_SEC_TEXT_MINOR STATIC VOID OsShellCmdHwiInfoTitle(VOID) { #ifdef LOSCFG_CPUP_INCLUDE_IRQ @@ -53,7 +57,7 @@ LITE_OS_SEC_TEXT_MINOR STATIC VOID OsShellCmdHwiInfoTitle(VOID) PRINTK("----------- ----- ------------- --------- --------\n"); #endif } - +//这个函数会根据传入的硬件中断句柄信息,获取该中断是否为共享模式 STATIC BOOL GetHwiShare(const HwiHandleInfo *hwiForm) { #ifndef LOSCFG_SHARED_IRQ @@ -64,9 +68,10 @@ STATIC BOOL GetHwiShare(const HwiHandleInfo *hwiForm) } #ifdef LOSCFG_CPUP_INCLUDE_IRQ -STATIC CPUP_INFO_S g_hwiCpupAll[LOSCFG_PLATFORM_HWI_LIMIT]; -STATIC CPUP_INFO_S g_hwiCpup10s[LOSCFG_PLATFORM_HWI_LIMIT]; -STATIC CPUP_INFO_S g_hwiCpup1s[LOSCFG_PLATFORM_HWI_LIMIT]; +STATIC CPUP_INFO_S g_hwiCpupAll[LOSCFG_PLATFORM_HWI_LIMIT];//所有时间段CPU利用率的统计信息 +STATIC CPUP_INFO_S g_hwiCpup10s[LOSCFG_PLATFORM_HWI_LIMIT];//最近10sCPU利用率的统计信息 +STATIC CPUP_INFO_S g_hwiCpup1s[LOSCFG_PLATFORM_HWI_LIMIT];//最近1sCPU利用率的统计信息 +//这个函数实现了硬件中断信息的查询,根据参数argc和argv判断是否有误,并调用其他函数获取硬件中断的各项信息,最终打印输出硬件中断的详细信息。 LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdHwi(INT32 argc, const CHAR **argv) { UINT32 i, intSave; @@ -75,22 +80,24 @@ LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdHwi(INT32 argc, const CHAR **argv) HwiHandleInfo *hwiForm = NULL; (VOID)argv; + //打印错误信息 if (argc > 0) { PRINTK("\nUsage: hwi\n"); return OS_ERROR; } - (VOID)memset_s(g_hwiCpupAll, size, 0, size); - (VOID)memset_s(g_hwiCpup10s, size, 0, size); - (VOID)memset_s(g_hwiCpup1s, size, 0, size); + (VOID)memset_s(g_hwiCpupAll, size, 0, size);//置零 + (VOID)memset_s(g_hwiCpup10s, size, 0, size);//置零 + (VOID)memset_s(g_hwiCpup1s, size, 0, size);//置零 intSave = LOS_IntLock(); (VOID)LOS_AllCpuUsage(LOSCFG_PLATFORM_HWI_LIMIT, g_hwiCpupAll, CPUP_ALL_TIME, 0); (VOID)LOS_AllCpuUsage(LOSCFG_PLATFORM_HWI_LIMIT, g_hwiCpup10s, CPUP_LAST_TEN_SECONDS, 0); (VOID)LOS_AllCpuUsage(LOSCFG_PLATFORM_HWI_LIMIT, g_hwiCpup1s, CPUP_LAST_ONE_SECONDS, 0); LOS_IntRestore(intSave); - + //打印硬件中断信息的表头 OsShellCmdHwiInfoTitle(); + //打印CPU硬件中断的利用率 for (i = 0; i < LOSCFG_PLATFORM_HWI_LIMIT; i++) { if (!HWI_IS_REGISTED(i)) { continue; @@ -101,6 +108,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdHwi(INT32 argc, const CHAR **argv) } /* Different cores has different hwi form implementation */ + //打印各个时间内的硬件中断利用率 hwiForm = OsGetHwiForm(i); PRINTK("%-8u\t %-s\t %-10u\t %-10llu %2u.%-7u %2u.%-7u %2u.%-6u", i, GetHwiShare(hwiForm) ? "Y" : "N", OsGetHwiFormCnt(i), cycles, @@ -110,6 +118,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdHwi(INT32 argc, const CHAR **argv) #ifdef LOSCFG_SHARED_IRQ hwiForm = hwiForm->next; #endif + //打印中断设备ID和信息 if ((hwiForm->registerInfo != 0) && ((HWI_IRQ_PARAM_S *)hwiForm->registerInfo)->pName != NULL) { PRINTK("\t %-16s 0x%-.8x\n", ((HWI_IRQ_PARAM_S *)hwiForm->registerInfo)->pName, @@ -128,24 +137,28 @@ LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdHwi(INT32 argc, const CHAR **argv) return 0; } #else +//这个函数主要实现对hwi命令的解释功能,输出硬件中断信息 LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdHwi(INT32 argc, const CHAR **argv) { UINT32 i; HwiHandleInfo *hwiForm = NULL; + //参数错误,打印错误信息 (VOID)argv; if (argc > 0) { PRINTK("\nUsage: hwi\n"); return OS_ERROR; } - + //打印硬件中断信息的表头 OsShellCmdHwiInfoTitle(); + //遍历所有硬件中断寄存器 for (i = 0; i < LOSCFG_PLATFORM_HWI_LIMIT; i++) { if (!HWI_IS_REGISTED(i)) { continue; } /* Different cores has different hwi form implementation */ + //输出信息 hwiForm = OsGetHwiForm(i); PRINTK("%-8u\t %-s\t %-10u", i, GetHwiShare(hwiForm) ? "Y" : "N", OsGetHwiFormCnt(i)); #ifdef LOSCFG_SHARED_IRQ @@ -170,7 +183,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdHwi(INT32 argc, const CHAR **argv) return 0; } #endif - +//该函数实现了OsShellCmdHwi的函数调用,用户可以输入hwi命令来调用该函数,从而查询和展示硬件中断信息 SHELLCMD_ENTRY(hwi_shellcmd, CMD_TYPE_EX, "hwi", 0, (CmdCallBackFunc)OsShellCmdHwi); #ifdef __cplusplus diff --git a/src/kernel/base/shellcmd/mempt_shellcmd.c b/src/kernel/base/shellcmd/mempt_shellcmd.c index 9c4be25..b67641e 100644 --- a/src/kernel/base/shellcmd/mempt_shellcmd.c +++ b/src/kernel/base/shellcmd/mempt_shellcmd.c @@ -25,7 +25,10 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +/* +这个文件是针对LiteOS操作系统中的Shell命令编写的, +主要实现了系统内存的安全检查、系统内存使用情况的显示、读取指定内存中指定位置指定长度的信息和释放内存空间。 +*/ #include "stdlib.h" #include "stdio.h" #include "los_memory_pri.h" @@ -45,54 +48,60 @@ extern "C" { #define MEM_SIZE_1K 0x400 #define MEM_SIZE_1M 0x100000 - +//这个函数用于检查内存完整性 LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdMemCheck(INT32 argc, const CHAR *argv[]) { + //打印错误信息 if (argc > 0) { PRINTK("\nUsage: memcheck\n"); return OS_ERROR; } - + //调用OsMemIntegrityMultiCheck函数完成内存完整性检查 OsMemIntegrityMultiCheck(); return 0; } #ifdef LOSCFG_SHELL +//这个函数可以读取内存中指定位置指定长度的数据,调用OsDumpMemByte函数完成内存读取并打印数据 LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdMemRead(INT32 argc, const CHAR *argv[]) { size_t tempAddr; size_t length; CHAR *ptrlen = NULL; CHAR *ptrAddr = NULL; - + //读取错误,打印错误信息 if ((argc == 0) || (argc > 2)) { /* argc is num of parameters */ PRINTK("\nUsage: readreg [ADDRESS] [LENGTH]\n"); return OS_ERROR; } - + //读取正确 if (argc == 1) { length = 0; } else { + //读取长度为负数,打印错误信息 length = strtoul(argv[1], &ptrlen, 0); if ((ptrlen == NULL) || (*ptrlen != 0)) { PRINTK("readreg invalid length %s\n", argv[1]); return OS_ERROR; } } + //保存ptrAddr的地址 tempAddr = strtoul(argv[0], &ptrAddr, 0); + //地址错误,打印错误信息 if ((ptrAddr == NULL) || (*ptrAddr != 0) || (tempAddr > g_sys_mem_addr_end) || ((tempAddr + length) > g_sys_mem_addr_end) || (tempAddr > (OS_NULL_INT - length))) { PRINTK("readreg invalid address %s\n", argv[0]); return OS_ERROR; } - + //调用OsDumpMemByte函数,打印指定内存位置读取的信息。 OsDumpMemByte(length, tempAddr); return 0; } - +//这个函数用于输出代码段、数据段、只读数据段和BSS段的大小信息。 LITE_OS_SEC_TEXT_MINOR STATIC VOID OsShellCmdSectionInfo(INT32 argc, const CHAR *argv[]) { + //计算各部分长度 size_t textLen = &__text_end - &__text_start; size_t dataLen = &__ram_data_end - &__ram_data_start; size_t rodataLen = &__rodata_end - &__rodata_start; @@ -103,7 +112,7 @@ LITE_OS_SEC_TEXT_MINOR STATIC VOID OsShellCmdSectionInfo(INT32 argc, const CHAR dataLen += &__fast_data_end - &__fast_data_start; rodataLen += &__fast_rodata_end - &__fast_rodata_start; #endif - + //打印代码段、数据段、只读数据段、BSS段的大小信息 PRINTK("\r\n text data rodata bss\n"); if ((argc == 1) && (strcmp(argv[0], "-k") == 0)) { PRINTK("Mem: %-9lu %-10lu %-10lu %-10lu\n", textLen / MEM_SIZE_1K, dataLen / MEM_SIZE_1K, @@ -115,19 +124,24 @@ LITE_OS_SEC_TEXT_MINOR STATIC VOID OsShellCmdSectionInfo(INT32 argc, const CHAR PRINTK("Mem: %-9lu %-10lu %-10lu %-10lu\n", textLen, dataLen, rodataLen, bssLen); } } - +//这个函数用于输出系统可用的内存总量、已经使用的内存量和剩余内存量的大小 LITE_OS_SEC_TEXT_MINOR STATIC UINT32 OsShellCmdFreeInfo(INT32 argc, const CHAR *argv[]) { #ifdef LOSCFG_EXC_INTERACTION + //调用LOS_MemTotaUsedGet函数得到已经使用的内存量 UINT32 memUsed0 = LOS_MemTotalUsedGet(m_aucSysMem0); + //调用LOS_MemPoolSizeGet函数得到系统可用的内存总量 UINT32 totalMem0 = LOS_MemPoolSizeGet(m_aucSysMem0); + //计算得到系统剩余的内存量 UINT32 freeMem0 = totalMem0 - memUsed0; #endif - + //调用LOS_MemTotaUsedGet函数得到已经使用的内存量 UINT32 memUsed = LOS_MemTotalUsedGet(m_aucSysMem1); + //调用LOS_MemPoolSizeGet函数得到系统可用的内存总量 UINT32 totalMem = LOS_MemPoolSizeGet(m_aucSysMem1); + /计算得到系统剩余的内存量 UINT32 freeMem = totalMem - memUsed; - + //打印统可用的内存总量、已经使用的内存量和剩余内存量的大小 if ((argc == 0) || ((argc == 1) && (strcmp(argv[0], "-k") == 0)) || ((argc == 1) && (strcmp(argv[0], "-m") == 0))) { @@ -157,47 +171,57 @@ LITE_OS_SEC_TEXT_MINOR STATIC UINT32 OsShellCmdFreeInfo(INT32 argc, const CHAR * PRINTK("Mem1: %-9u %-10u %-10u\n", totalMem0, memUsed0, freeMem0); #endif } else { + //打印错误信息 PRINTK("\nUsage: free or free [-k/-m]\n"); return OS_ERROR; } return 0; } - +//这个函数用于显示系统内存的使用情况,调用了OsShellCmdFreeInfo和OsShellCmdSectionInfo函数完成内存使用情况和内存分配情况的打印输出。 LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdFree(INT32 argc, const CHAR *argv[]) { + //打印错误信息 if (argc > 1) { PRINTK("\nUsage: free or free [-k/-m]\n"); return OS_ERROR; } + //打印错误信息 if (OsShellCmdFreeInfo(argc, argv) != 0) { return OS_ERROR; } + //调用OsShellCmdSectionInfo函数输出存使用情况和内存分配情况 OsShellCmdSectionInfo(argc, argv); return 0; } - +//这个函数根据参数选择输出不同的系统信息,在控制台上输出相应的信息。 LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdUname(INT32 argc, const CHAR *argv[]) { + //如果参数为0,在控制台上打印Huawei LiteOS if (argc == 0) { PRINTK("Huawei LiteOS\n"); return 0; } if (argc == 1) { + //系统参数为-a时,打印LiteOS所有的信息 if (strcmp(argv[0], "-a") == 0) { PRINTK("%s %s %s %s %s\n", HW_LITEOS_VER, HW_LITEOS_SYSNAME, HW_LITEOS_KERNEL_VERSION_STRING, __DATE__, __TIME__); return 0; + //系统参数为-s时,打印Huawei LiteOS } else if (strcmp(argv[0], "-s") == 0) { PRINTK("Huawei LiteOS\n"); return 0; + //系统参数为-t时,打印系统创建的时间信息 } else if (strcmp(argv[0], "-t") == 0) { PRINTK("build date : %s %s", __DATE__, __TIME__); return 0; + //系统参数为-v时,打印LiteOS的版本信息和时间信息 } else if (strcmp(argv[0], "-v") == 0) { PRINTK("%s %s %s %s\n", HW_LITEOS_SYSNAME, HW_LITEOS_KERNEL_VERSION_STRING, __DATE__, __TIME__); return 0; + //系统参数为--help时,打印各参数的含义 } else if (strcmp(argv[0], "--help") == 0) { PRINTK("-a, print all information\n" "-s, print the kernel name\n" @@ -206,20 +230,22 @@ LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdUname(INT32 argc, const CHAR *argv[]) return 0; } } - + //如果都不是,打印错误信息,提示用户输入--help来查看信息 PRINTK("uname: invalid option %s\n" "Try 'uname --help' for more information.\n", argv[0]); return OS_ERROR; } #ifdef LOSCFG_MEM_LEAKCHECK +//这个函数打印了系统已使用的内存信息 LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdMemUsed(INT32 argc, const CHAR *argv[]) { + //打印错误信息 if (argc > 0) { PRINTK("\nUsage: memused\n"); return OS_ERROR; } - + //调用OsMemUsedNodeShow函数,输出已使用的节点信息 OsMemUsedNodeShow(m_aucSysMem1); #ifdef LOSCFG_EXC_INTERACTION @@ -230,6 +256,14 @@ LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdMemUsed(INT32 argc, const CHAR *argv[]) } #endif +/* +命令解释器个各个命令调用的函数以及作用 +memcheck命令:检查内存完整性。调用了OsMemIntegrityMultiCheck函数完成内存完整性检查。 +memread [ADDRESS] [LENGTH]命令:读取指定地址和长度的内存数据。调用了OsDumpMemByte函数完成内存数据读取并打印输出。 +free命令:显示系统内存的使用情况。调用了OsShellCmdFreeInfo和OsShellCmdSectionInfo函数完成内存使用情况和内存分配情况的打印输出。 +uname [-a/-s/-t/-v]命令:显示系统信息。根据参数选择输出不同的系统信息。调用了PRINTK宏在控制台上输出相应的信息。 +*/ + #ifdef LOSCFG_MEM_LEAKCHECK SHELLCMD_ENTRY(memused_shellcmd, CMD_TYPE_EX, "memused", 0, (CmdCallBackFunc)OsShellCmdMemUsed); #endif diff --git a/src/kernel/base/shellcmd/stack_shellcmd.c b/src/kernel/base/shellcmd/stack_shellcmd.c index 1ac2386..607fac0 100644 --- a/src/kernel/base/shellcmd/stack_shellcmd.c +++ b/src/kernel/base/shellcmd/stack_shellcmd.c @@ -25,7 +25,10 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +/* +这段文件是针对LiteOS操作系统中的Shell命令编写的, +主要实现了内核异常处理机制中与堆栈相关的功能,包括堆栈信息的获取和检查。 +*/ #include "securec.h" #include "los_config.h" #include "los_stackinfo_pri.h" @@ -34,7 +37,7 @@ #include "shcmd.h" #include "shell.h" #endif - +//这个函数用于检查堆栈是否溢出 VOID OsExcStackCheck(VOID) { UINT32 index; @@ -42,15 +45,17 @@ VOID OsExcStackCheck(VOID) UINTPTR *stackTop = NULL; const StackInfo *stackInfo = NULL; UINT32 stackNum; - + //获取堆栈信息,如果堆栈信息错误,直接返回 OsGetStackInfo(&stackInfo, &stackNum); if ((stackInfo == NULL) || (stackNum == 0)) { return; } - + //从头开始,遍历所有的堆栈 for (index = 0; index < stackNum; index++) { for (cpuid = 0; cpuid < LOSCFG_KERNEL_CORE_NUM; cpuid++) { + //堆栈的栈顶 stackTop = (UINTPTR *)((UINTPTR)stackInfo[index].stackTop + cpuid * stackInfo[index].stackSize); + //检查栈顶信息是否被篡改,如果被篡改输出该堆栈溢出的信息 if (*stackTop != OS_STACK_MAGIC_WORD) { PRINT_ERR("cpu:%u %s overflow , magic word changed to 0x%x\n", LOSCFG_KERNEL_CORE_NUM - 1 - cpuid, stackInfo[index].stackName, *stackTop); @@ -58,7 +63,7 @@ VOID OsExcStackCheck(VOID) } } } - +//这个函数用于获取并打印所有的堆栈信息 VOID OsExcStackInfo(VOID) { UINT32 index; @@ -68,29 +73,31 @@ VOID OsExcStackInfo(VOID) UINTPTR *stack = NULL; const StackInfo *stackInfo = NULL; UINT32 stackNum; - + //获取堆栈信息,如果堆栈信息错误,直接返回 OsGetStackInfo(&stackInfo, &stackNum); if ((stackInfo == NULL) || (stackNum == 0)) { return; } - + //输出堆栈名、CPU ID、堆栈的地址、堆栈的总大小,堆栈已使用的大小 PrintExcInfo("\n stack name cpu id stack addr total size used size\n" " ---------- ------ --------- -------- --------\n"); - + //从头开始,遍历所有的堆栈 for (index = 0; index < stackNum; index++) { for (cpuid = 0; cpuid < LOSCFG_KERNEL_CORE_NUM; cpuid++) { + //获取堆栈的栈顶 stackTop = (UINTPTR *)((UINTPTR)stackInfo[index].stackTop + cpuid * stackInfo[index].stackSize); stack = (UINTPTR *)((UINTPTR)stackTop + stackInfo[index].stackSize); + //调用OsStackWaterLineGet函数计算堆栈已使用的大小 (VOID)OsStackWaterLineGet(stack, stackTop, &size); - + //输出各类信息 PrintExcInfo("%11s %-5d %-10p 0x%-8x 0x%-4x\n", stackInfo[index].stackName, LOSCFG_KERNEL_CORE_NUM - 1 - cpuid, stackTop, stackInfo[index].stackSize, size); } } - + //进行堆栈溢出检查 OsExcStackCheck(); } - +//注册Shell命令stack,调用OsExcStackInfo函数获取并打印所有堆栈信息至控制台。 #ifdef LOSCFG_SHELL SHELLCMD_ENTRY(stack_shellcmd, CMD_TYPE_EX, "stack", 1, (CmdCallBackFunc)OsExcStackInfo); #endif diff --git a/src/kernel/base/shellcmd/swtmr_shellcmd.c b/src/kernel/base/shellcmd/swtmr_shellcmd.c index 476c660..95039e2 100644 --- a/src/kernel/base/shellcmd/swtmr_shellcmd.c +++ b/src/kernel/base/shellcmd/swtmr_shellcmd.c @@ -25,7 +25,10 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +/* +这个文件主要是针对LiteOS系统中软件定时器的命令行操作进行定义和实现的, +主要实现了根据软件定时器的ID输出软件定时器的各种信息。 +*/ #include "los_config.h" #ifdef LOSCFG_SHELL #include "stdlib.h" @@ -42,20 +45,20 @@ extern "C" { #define SWTMR_STRLEN 12 #ifdef LOSCFG_BASE_CORE_SWTMR - +//展示g_shellSwtmrMode的数据 LITE_OS_SEC_DATA_MINOR STATIC CHAR g_shellSwtmrMode[][SWTMR_STRLEN] = { "Once", "Period", "NSD", "OPP", }; - +//展示g_shellSwtmrStatus的数据 LITE_OS_SEC_DATA_MINOR STATIC CHAR g_shellSwtmrStatus[][SWTMR_STRLEN] = { "UnUsed", "Created", "Ticking", }; - +//这个函数用于打印软件定时器的信息,包括定时器ID、状态、模式、间隔、参数和处理函数地址等。 STATIC VOID OsPrintSwtmrMsg(const LosSwtmrCB *swtmr) { PRINTK("0x%08x " @@ -64,20 +67,20 @@ STATIC VOID OsPrintSwtmrMsg(const LosSwtmrCB *swtmr) "%-6u " "0x%08x " "%p\n", - swtmr->timerId % LOSCFG_BASE_CORE_SWTMR_LIMIT, - g_shellSwtmrStatus[swtmr->state], - g_shellSwtmrMode[swtmr->mode], - swtmr->interval, - swtmr->arg, - swtmr->handler); + swtmr->timerId % LOSCFG_BASE_CORE_SWTMR_LIMIT,//打印定时器ID + g_shellSwtmrStatus[swtmr->state],//打印定时器的状态 + g_shellSwtmrMode[swtmr->mode],//打印定时器的模式 + swtmr->interval,//打印定时器的间隔 + swtmr->arg,//打印定时器的参数 + swtmr->handler);//打印定时器的处理函数地址 } - +//这个函数用于打印软件定时器信息的表头 STATIC INLINE VOID OsPrintSwtmrMsgHead(VOID) { PRINTK("\r\nSwTmrID State Mode Interval Arg handlerAddr\n"); PRINTK("---------- ------- ------- --------- ---------- --------\n"); } - +//这个函数用于获取软件定时器的信息。 LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdSwtmrInfoGet(INT32 argc, const UINT8 **argv) { #define OS_ALL_SWTMR_MASK 0xffffffff @@ -87,34 +90,36 @@ LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdSwtmrInfoGet(INT32 argc, const UINT8 **a size_t timerId; UINT16 num = 0; CHAR *endPtr = NULL; - + //打印错误信息 if (argc > 1) { PRINTK("\nUsage: swtmr [ID]\n"); return OS_ERROR; } - + //获取计时器ID if (argc == 0) { timerId = OS_ALL_SWTMR_MASK; } else { + //没有这个ID,打印错误信息 timerId = strtoul((CHAR *)argv[0], &endPtr, 0); if ((endPtr == NULL) || (*endPtr != 0) || (timerId > LOSCFG_BASE_CORE_SWTMR_LIMIT)) { PRINTK("\nswtmr ID can't access %s.\n", argv[0]); return OS_ERROR; } } - + //遍历所有计时器,让计时器的状态加1 for (index = 0; index < LOSCFG_BASE_CORE_SWTMR_LIMIT; index++, swtmr1++) { if (swtmr1->state == 0) { num = num + 1; } } - + //达到时间限制,输出错误信息 if (num == LOSCFG_BASE_CORE_SWTMR_LIMIT) { PRINTK("\r\nThere is no swtmr was created!\n"); return OS_ERROR; } - + //打印软件定时器信息的表头 OsPrintSwtmrMsgHead(); + //打印软件定时器的各类信息 if (timerId == OS_ALL_SWTMR_MASK) { for (index = 0; index < LOSCFG_BASE_CORE_SWTMR_LIMIT; index++, swtmr++) { if (swtmr->state != 0) { @@ -132,7 +137,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdSwtmrInfoGet(INT32 argc, const UINT8 **a } return LOS_OK; } - +//注册Shell命令swtmr,调用OsShellCmdSwtmrInfoGet函数获取软件定时器的信息。根据输入的参数获取特定或者所有软件定时器的状态信息并打印出来。 SHELLCMD_ENTRY(swtmr_shellcmd, CMD_TYPE_EX, "swtmr", 1, (CmdCallBackFunc)OsShellCmdSwtmrInfoGet); #endif diff --git a/src/kernel/base/shellcmd/sysinfo_shellcmd.c b/src/kernel/base/shellcmd/sysinfo_shellcmd.c index 69f73a5..813a2ea 100644 --- a/src/kernel/base/shellcmd/sysinfo_shellcmd.c +++ b/src/kernel/base/shellcmd/sysinfo_shellcmd.c @@ -25,7 +25,10 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +/* +这段文件是针对LiteOS操作系统中的Shell命令编写的, +主要实现了获取系统信息的功能,获取的信息包括进程数量、信号量数量、互斥锁数量、消息队列数量和软件定时器数量。 +*/ #include "los_config.h" #include "los_swtmr.h" #include "los_sem_pri.h" @@ -43,141 +46,173 @@ extern "C" { #endif #endif /* __cplusplus */ - +//这个函数用于获取当系统的进程数量 UINT32 OsShellCmdTaskCntGet(VOID) { UINT32 loop; UINT32 taskCnt = 0; UINT32 intSave; LosTaskCB *taskCB = NULL; - + //加上锁,用于防止中断 intSave = LOS_IntLock(); + //遍历所有进程,并统计进程数量 for (loop = 0; loop < g_taskMaxNum; loop++) { taskCB = (LosTaskCB *)g_taskCBArray + loop; + //若该进程未使用,则直接跳过 if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) { continue; } taskCnt++; } + //为进程解锁 LOS_IntRestore(intSave); + //返回系统的进程数量 return taskCnt; } #ifdef LOSCFG_BASE_IPC_SEM +//这个函数用于获取当前系统信号量的数量 UINT32 OsShellCmdSemCntGet(VOID) { UINT32 loop; UINT32 semCnt = 0; UINT32 intSave; LosSemCB *semNode = NULL; - + //加上锁,用于防止中断 intSave = LOS_IntLock(); + //遍历所有信号量 for (loop = 0; loop < LOSCFG_BASE_IPC_SEM_LIMIT; loop++) { semNode = GET_SEM(loop); + //如果该信号量被使用了,数量加1 if (semNode->semStat == LOS_USED) { semCnt++; } } + //为进程解锁 LOS_IntRestore(intSave); + //返回系统信号量的数量 return semCnt; } #endif #ifdef LOSCFG_BASE_IPC_MUX +//这个函数用于获取当前系统互斥锁的数量 UINT32 OsShellCmdMuxCntGet(VOID) { UINT32 loop; UINT32 muxCnt = 0; UINT32 intSave; LosMuxCB *muxNode = NULL; - + //加上锁,用于防止中断 intSave = LOS_IntLock(); + //遍历所有互斥锁 for (loop = 0; loop < LOSCFG_BASE_IPC_MUX_LIMIT; loop++) { muxNode = GET_MUX(loop); + //如果互斥锁的状态被使用了,数量加1 if (muxNode->muxStat == LOS_USED) { muxCnt++; } } + //为进程解锁 LOS_IntRestore(intSave); + //返回系统互斥锁的数量 return muxCnt; } #endif #ifdef LOSCFG_BASE_IPC_QUEUE +//这个函数用于获取系统消息队列的数量 UINT32 OsShellCmdQueueCntGet(VOID) { UINT32 loop; UINT32 queueCnt = 0; UINT32 intSave; LosQueueCB *queueCB = NULL; - + //加上锁,用于防止中断 intSave = LOS_IntLock(); queueCB = g_allQueue; + //遍历所有消息队列 for (loop = 0; loop < LOSCFG_BASE_IPC_QUEUE_LIMIT; loop++, queueCB++) { + //如果消息队列的状态为使用,数量加1 if (queueCB->queueState == LOS_USED) { queueCnt++; } } + //为进程解锁 LOS_IntRestore(intSave); + //返回系统获取消息队列的数量 return queueCnt; } #endif #ifdef LOSCFG_BASE_CORE_SWTMR +//这个函数用于获取系统软件定时器的数量 UINT32 OsShellCmdSwtmrCntGet(VOID) { UINT32 loop; UINT32 swtmrCnt = 0; UINT32 intSave; LosSwtmrCB *swtmrCB = NULL; - + //加上锁,用于防止中断 intSave = LOS_IntLock(); swtmrCB = g_swtmrCBArray; + //遍历所有软件定时器 for (loop = 0; loop < LOSCFG_BASE_CORE_SWTMR_LIMIT; loop++, swtmrCB++) { + //如果软件定时器的状态不是没有使用,数量加1 if (swtmrCB->state != OS_SWTMR_STATUS_UNUSED) { swtmrCnt++; } } + //为进程解锁 LOS_IntRestore(intSave); + //返回系统软件定时器的数量 return swtmrCnt; } #endif - +//这个函数用于打印系统信息,包括进程数量、信号量数量、互斥锁数量、消息队列数量和软件定时器数量。 LITE_OS_SEC_TEXT_MINOR VOID OsShellCmdSystemInfoGet(VOID) { + //打印表头 PRINTK("\n Module Used Total\n"); PRINTK("--------------------------------\n"); + //打印进程数量 PRINTK(" Task %-10u%-10d\n", OsShellCmdTaskCntGet(), LOSCFG_BASE_CORE_TSK_LIMIT); #ifdef LOSCFG_BASE_IPC_SEM + //打印信号量数量 PRINTK(" Sem %-10u%-10d\n", OsShellCmdSemCntGet(), LOSCFG_BASE_IPC_SEM_LIMIT); #endif #ifdef LOSCFG_BASE_IPC_MUX + //打印互斥锁数量 PRINTK(" Mutex %-10u%-10d\n", OsShellCmdMuxCntGet(), LOSCFG_BASE_IPC_MUX_LIMIT); #endif #ifdef LOSCFG_BASE_IPC_QUEUE + //打印消息队列数量 PRINTK(" Queue %-10u%-10d\n", OsShellCmdQueueCntGet(), LOSCFG_BASE_IPC_QUEUE_LIMIT); #endif #ifdef LOSCFG_BASE_CORE_SWTMR + //打印软件定时器数量 PRINTK(" SwTmr %-10u%-10d\n", OsShellCmdSwtmrCntGet(), LOSCFG_BASE_CORE_SWTMR_LIMIT); #endif } - +//这个函数用于处理shell的systeminfo命令,根据相应的参数,做出相应的处理 INT32 OsShellCmdSystemInfo(INT32 argc, const CHAR **argv) { + //如果参数数量为0,调用OsShellCmdSystemInfoGet函数,打印所有的系统信息。 if (argc == 0) { OsShellCmdSystemInfoGet(); return 0; } + //参数数量不正确,打印错误信息 PRINTK("systeminfo: invalid option %s\n" "Systeminfo has NO ARGS.\n", argv[0]); @@ -185,6 +220,7 @@ INT32 OsShellCmdSystemInfo(INT32 argc, const CHAR **argv) } #ifdef LOSCFG_SHELL +//注册Shell命令systeminfo,调用OsShellCmdSystemInfo,根据参数输出当前系统的程数量、信号量数量、互斥锁数量、消息队列数量和软件定时器数量。。 SHELLCMD_ENTRY(systeminfo_shellcmd, CMD_TYPE_EX, "systeminfo", 1, (CmdCallBackFunc)OsShellCmdSystemInfo); #endif /* LOSCFG_SHELL */ diff --git a/src/kernel/base/shellcmd/task_shellcmd.c b/src/kernel/base/shellcmd/task_shellcmd.c index 43dbde6..35ed967 100644 --- a/src/kernel/base/shellcmd/task_shellcmd.c +++ b/src/kernel/base/shellcmd/task_shellcmd.c @@ -25,7 +25,10 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ - +/* +这段文件是针对LiteOS操作系统中的Shell命令编写的, +主要实现了操作系统的任务管理模块,通过进程号获取该进程的所有信息,或者直接获取所有进程的信息。 +*/ #include "stdio.h" #include "stdlib.h" #include "los_config.h" @@ -53,55 +56,65 @@ extern "C" { #define OS_INVALID_SEM_ID 0xFFFFFFFF #ifdef LOSCFG_KERNEL_CPUP -LITE_OS_SEC_BSS STATIC CPUP_INFO_S g_taskCpupAll[LOSCFG_BASE_CORE_TSK_LIMIT]; -LITE_OS_SEC_BSS STATIC CPUP_INFO_S g_taskCpup10s[LOSCFG_BASE_CORE_TSK_LIMIT]; -LITE_OS_SEC_BSS STATIC CPUP_INFO_S g_taskCpup1s[LOSCFG_BASE_CORE_TSK_LIMIT]; +LITE_OS_SEC_BSS STATIC CPUP_INFO_S g_taskCpupAll[LOSCFG_BASE_CORE_TSK_LIMIT];//所有时间段CPU利用率的统计信息 +LITE_OS_SEC_BSS STATIC CPUP_INFO_S g_taskCpup10s[LOSCFG_BASE_CORE_TSK_LIMIT];//最近10sCPU利用率的统计信息 +LITE_OS_SEC_BSS STATIC CPUP_INFO_S g_taskCpup1s[LOSCFG_BASE_CORE_TSK_LIMIT];//最近1sCPU利用率的统计信息 #endif -LITE_OS_SEC_BSS STATIC UINT32 g_taskWaterLine[LOSCFG_BASE_CORE_TSK_LIMIT]; - +LITE_OS_SEC_BSS STATIC UINT32 g_taskWaterLine[LOSCFG_BASE_CORE_TSK_LIMIT];//记录各个堆栈最低的水位 +//这个函数通过进程状态位来判断进程的状态,并返回相应的字符串表示进程状态。 LITE_OS_SEC_TEXT_MINOR UINT8 *OsShellCmdConvertTskStatus(UINT16 taskStatus) { + //进程处于运行状态,返回Running if (taskStatus & OS_TASK_STATUS_RUNNING) { - return (UINT8 *)"Running"; + return (UINT8 *)"Running"; + //进程处于就绪状态,返回Ready } else if (taskStatus & OS_TASK_STATUS_READY) { return (UINT8 *)"Ready"; + //其他的进程状态 } else { + //进程处于延迟状态,返回Delay if (taskStatus & OS_TASK_STATUS_DELAY) { return (UINT8 *)"Delay"; } else if (taskStatus & OS_TASK_STATUS_PEND_TIME) { + //进程处于定时挂起状态,返回SuspendTime if (taskStatus & OS_TASK_STATUS_SUSPEND) { return (UINT8 *)"SuspendTime"; + //进程处于定时等待状态,返回PendTime } else if (taskStatus & OS_TASK_STATUS_PEND) { return (UINT8 *)"PendTime"; } + //进程处于等待状态,返回Pend } else if (taskStatus & OS_TASK_STATUS_PEND) { return (UINT8 *)"Pend"; + //进程处于挂起状态,返回SusPend } else if (taskStatus & OS_TASK_STATUS_SUSPEND) { return (UINT8 *)"Suspend"; } } - + //进程状态不合法,返回Invalid return (UINT8 *)"Invalid"; } - +//这个函数用于获取所有堆栈的栈水位(堆栈的使用情况) STATIC VOID OsShellCmdTaskWaterLineGet(const LosTaskCB *allTaskArray) { const LosTaskCB *taskCB = NULL; UINT32 loop; - + //遍历所有堆栈 for (loop = 0; loop < g_taskMaxNum; ++loop) { taskCB = allTaskArray + loop; + //如果该堆栈未使用,直接跳过 if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) { continue; } - + //调用OsStackWaterLineGet,输出堆栈的栈水位信息 (VOID)OsStackWaterLineGet((const UINTPTR *)((UINTPTR)taskCB->topOfStack + taskCB->stackSize), (const UINTPTR *)taskCB->topOfStack, &g_taskWaterLine[taskCB->taskId]); } } #ifdef LOSCFG_SHELL_EXCINFO_DUMP +//这个函数用于在异常信息输出缓冲区中打印任务信息的标题。 LITE_OS_SEC_TEXT_MINOR STATIC VOID OsShellCmdTskInfoTitleExc(VOID) { WriteExcInfoToBuf("\r\nName TaskEntryAddr TID "); @@ -133,7 +146,7 @@ LITE_OS_SEC_TEXT_MINOR STATIC VOID OsShellCmdTskInfoTitleExc(VOID) WriteExcInfoToBuf("\n"); } #endif - +//这个函数用于在控制台打印任务信息的标题。 LITE_OS_SEC_TEXT_MINOR STATIC VOID OsShellCmdTskInfoTitle(VOID) { PRINTK("\r\nName TaskEntryAddr TID "); @@ -165,14 +178,15 @@ LITE_OS_SEC_TEXT_MINOR STATIC VOID OsShellCmdTskInfoTitle(VOID) PRINTK("\n"); #ifdef LOSCFG_SHELL_EXCINFO_DUMP + //在异常信息输出缓冲区中打印任务信息的标题。 OsShellCmdTskInfoTitleExc(); #endif } - +//这个函数通过TCB(进程控制块)获取进程所持有的信号量的ID。 LITE_OS_SEC_TEXT_MINOR STATIC INLINE UINT32 OsGetSemID(const LosTaskCB *taskCB) { UINT32 semId = OS_INVALID_SEM_ID; - + //返回该进程的信号量ID if (taskCB->taskSem != NULL) { semId = ((LosSemCB *)taskCB->taskSem)->semId; } @@ -181,12 +195,13 @@ LITE_OS_SEC_TEXT_MINOR STATIC INLINE UINT32 OsGetSemID(const LosTaskCB *taskCB) } #ifdef LOSCFG_SHELL_EXCINFO_DUMP +//这个函数用于将TCB(进程控制块)中的进程信息输出到异常信息输出缓冲区。 LITE_OS_SEC_TEXT_MINOR STATIC VOID OsShellCmdTskInfoDataExc(const LosTaskCB *allTaskArray) { const LosTaskCB *taskCB = NULL; UINT32 loop; UINT32 semId; - + //遍历所有的堆栈 for (loop = 0; loop < g_taskMaxNum; ++loop) { taskCB = allTaskArray + loop; if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) { @@ -194,21 +209,25 @@ LITE_OS_SEC_TEXT_MINOR STATIC VOID OsShellCmdTskInfoDataExc(const LosTaskCB *all } semId = OsGetSemID(taskCB); - + //调用WriteExcInfoToBuf函数,将TCB(进程控制块)的信息写入缓冲区 WriteExcInfoToBuf("%-23s0x%-18.8x0x%-5x", taskCB->taskName, taskCB->taskEntry, taskCB->taskId); #ifdef LOSCFG_KERNEL_SMP + //调用WriteExcInfoToBuf函数,将TCB(进程控制块)的信息写入缓冲区 WriteExcInfoToBuf("0x%04x %4d ", taskCB->cpuAffiMask, (INT16)(taskCB->currCpu)); #endif + //调用WriteExcInfoToBuf函数,将TCB(进程控制块)的信息写入缓冲区 WriteExcInfoToBuf("%-11u%-13s0x%-11x0x%-11x 0x%-.8x 0x%-.8x 0x%-11x", taskCB->priority, OsShellCmdConvertTskStatus(taskCB->taskStatus), taskCB->stackSize, g_taskWaterLine[taskCB->taskId], taskCB->stackPointer, taskCB->topOfStack, semId); #ifdef LOSCFG_BASE_IPC_EVENT + //调用WriteExcInfoToBuf函数,将TCB(进程控制块)的信息写入缓冲区 WriteExcInfoToBuf("0x%-6x", taskCB->eventMask); #endif #ifdef LOSCFG_KERNEL_CPUP + //调用WriteExcInfoToBuf函数,将TCB(进程控制块)的信息写入缓冲区 WriteExcInfoToBuf(" %4u.%1u%9u.%1u%8u.%1u ", g_taskCpupAll[taskCB->taskId].uwUsage / LOS_CPUP_PRECISION_MULT, g_taskCpupAll[taskCB->taskId].uwUsage % LOS_CPUP_PRECISION_MULT, @@ -218,41 +237,47 @@ LITE_OS_SEC_TEXT_MINOR STATIC VOID OsShellCmdTskInfoDataExc(const LosTaskCB *all g_taskCpup1s[taskCB->taskId].uwUsage % LOS_CPUP_PRECISION_MULT); #endif /* LOSCFG_KERNEL_CPUP */ #ifdef LOSCFG_MEM_TASK_STAT + //调用WriteExcInfoToBuf函数,将TCB(进程控制块)的信息写入缓冲区 WriteExcInfoToBuf(" %-11u", OsMemTaskUsage(taskCB->taskId)); #endif + //调用WriteExcInfoToBuf函数,将TCB(进程控制块)的信息写入缓冲区 WriteExcInfoToBuf("\n"); } } #endif - +//这个函数可以将TCB(进程控制块)中的信息输出到控制台。 LITE_OS_SEC_TEXT_MINOR STATIC VOID OsShellCmdTskInfoData(const LosTaskCB *allTaskArray) { const LosTaskCB *taskCB = NULL; UINT32 loop; UINT32 semId; - + //遍历所有的堆栈 for (loop = 0; loop < g_taskMaxNum; ++loop) { taskCB = allTaskArray + loop; if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) { continue; } - + //调用OsGetSemID获取该进程的信号量ID semId = OsGetSemID(taskCB); - + //输出进程信息到控制台 PRINTK("%-23s0x%-18.8x0x%-5x", taskCB->taskName, taskCB->taskEntry, taskCB->taskId); #ifdef LOSCFG_KERNEL_SMP + //输出进程信息到控制台 PRINTK("0x%04x %4d ", taskCB->cpuAffiMask, (INT16)(taskCB->currCpu)); #endif + //输出进程信息到控制台 PRINTK("%-11u%-13s0x%-11x0x%-11x 0x%-.8x 0x%-.8x 0x%-11x", taskCB->priority, OsShellCmdConvertTskStatus(taskCB->taskStatus), taskCB->stackSize, g_taskWaterLine[taskCB->taskId], taskCB->stackPointer, taskCB->topOfStack, semId); #ifdef LOSCFG_BASE_IPC_EVENT + //输出进程信息到控制台 PRINTK("0x%-6x", taskCB->eventMask); #endif #ifdef LOSCFG_KERNEL_CPUP + //输出进程信息到控制台 PRINTK(" %4u.%1u%9u.%1u%8u.%1u ", g_taskCpupAll[taskCB->taskId].uwUsage / LOS_CPUP_PRECISION_MULT, g_taskCpupAll[taskCB->taskId].uwUsage % LOS_CPUP_PRECISION_MULT, @@ -262,16 +287,19 @@ LITE_OS_SEC_TEXT_MINOR STATIC VOID OsShellCmdTskInfoData(const LosTaskCB *allTas g_taskCpup1s[taskCB->taskId].uwUsage % LOS_CPUP_PRECISION_MULT); #endif /* LOSCFG_KERNEL_CPUP */ #ifdef LOSCFG_MEM_TASK_STAT + //输出进程信息到控制台 PRINTK(" %-11u", OsMemTaskUsage(taskCB->taskId)); #endif + //输出进程信息到控制台 PRINTK("\n"); } #ifdef LOSCFG_SHELL_EXCINFO_DUMP + //将进程信息输出到异常信息输出缓冲区。 OsShellCmdTskInfoDataExc(allTaskArray); #endif } - +//这个函数可以通过进程号获取进程的信息 LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdTskInfoGet(UINT32 taskId) { BOOL backupFlag = TRUE; @@ -279,50 +307,57 @@ LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdTskInfoGet(UINT32 taskId) UINT32 size, intSave; LosTaskCB *tcbArray = NULL; INT32 ret; - + //如果是目标进程 if (taskId == OS_ALL_TASK_MASK) { size = g_taskMaxNum * sizeof(LosTaskCB); tcbArray = (LosTaskCB *)LOS_MemAlloc(m_aucSysMem1, size); + //如果目标进程信息为空,输出错误信息,将backup设置为Fasle,不备份该进程信息 if (tcbArray == NULL) { PRINTK("Memory is not enough to save task info!\n"); tcbArray = g_taskCBArray; backupFlag = FALSE; } #ifdef LOSCFG_KERNEL_CPUP - (VOID)memset_s((VOID *)g_taskCpupAll, sizeof(g_taskCpupAll), 0, sizeof(g_taskCpupAll)); - (VOID)memset_s((VOID *)g_taskCpup10s, sizeof(g_taskCpup10s), 0, sizeof(g_taskCpup10s)); - (VOID)memset_s((VOID *)g_taskCpup1s, sizeof(g_taskCpup1s), 0, sizeof(g_taskCpup1s)); + (VOID)memset_s((VOID *)g_taskCpupAll, sizeof(g_taskCpupAll), 0, sizeof(g_taskCpupAll));//置零 + (VOID)memset_s((VOID *)g_taskCpup10s, sizeof(g_taskCpup10s), 0, sizeof(g_taskCpup10s));//置零 + (VOID)memset_s((VOID *)g_taskCpup1s, sizeof(g_taskCpup1s), 0, sizeof(g_taskCpup1s));//置零 #endif - (VOID)memset_s((VOID *)g_taskWaterLine, sizeof(g_taskWaterLine), 0, sizeof(g_taskWaterLine)); - + (VOID)memset_s((VOID *)g_taskWaterLine, sizeof(g_taskWaterLine), 0, sizeof(g_taskWaterLine));//置零 + //如果没有调度器自旋锁,为该进程添加调度器自旋锁 if (LOS_SpinHeld(&g_taskSpin) == FALSE) { SCHEDULER_LOCK(intSave); lockFlag = TRUE; } + //如果需要将进程信息备份 if (backupFlag == TRUE) { + //将进程信息备份到tcbArray ret = memcpy_s(tcbArray, size, g_taskCBArray, size); + //如果没有备份成果返回错误 if (ret != EOK) { return LOS_NOK; } } #ifdef LOSCFG_KERNEL_CPUP - (VOID)LOS_AllCpuUsage(LOSCFG_BASE_CORE_TSK_LIMIT, g_taskCpupAll, CPUP_ALL_TIME, 1); - (VOID)LOS_AllCpuUsage(LOSCFG_BASE_CORE_TSK_LIMIT, g_taskCpup10s, CPUP_LAST_TEN_SECONDS, 1); - (VOID)LOS_AllCpuUsage(LOSCFG_BASE_CORE_TSK_LIMIT, g_taskCpup1s, CPUP_LAST_ONE_SECONDS, 1); + (VOID)LOS_AllCpuUsage(LOSCFG_BASE_CORE_TSK_LIMIT, g_taskCpupAll, CPUP_ALL_TIME, 1);//显示CPU所有时段的使用率信息 + (VOID)LOS_AllCpuUsage(LOSCFG_BASE_CORE_TSK_LIMIT, g_taskCpup10s, CPUP_LAST_TEN_SECONDS, 1);//显示CPU最近10s的使用率信息 + (VOID)LOS_AllCpuUsage(LOSCFG_BASE_CORE_TSK_LIMIT, g_taskCpup1s, CPUP_LAST_ONE_SECONDS, 1);//显示CPU最近1s的使用率信息 #endif + //获取进程的栈水位信息 OsShellCmdTaskWaterLineGet(tcbArray); - + //如果进程有调度器自旋锁,将该进程解锁 if (lockFlag == TRUE) { SCHEDULER_UNLOCK(intSave); } - + //打印进程信息标题 OsShellCmdTskInfoTitle(); + //打印进程信息的数据 OsShellCmdTskInfoData(tcbArray); - + //如果进程信息数据备份成果,释放tcbArrayd的内存空间 if (backupFlag == TRUE) { (VOID)LOS_MemFree(m_aucSysMem1, tcbArray); } } else { + //调用 OsTaskBackTrace函数来获取该任务的回溯信息。 OsTaskBackTrace(taskId); } @@ -330,29 +365,34 @@ LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdTskInfoGet(UINT32 taskId) } #ifdef LOSCFG_SHELL +//这个函数用于处理task命令,通过各种参数输出结果 LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdDumpTask(INT32 argc, const CHAR **argv) { size_t taskId; CHAR *endPtr = NULL; - + //当参数数量合法时 if (argc < 2) { /* 2:Just as number of parameters */ + //如果没有参数,进程号是所有进程 if (argc == 0) { taskId = OS_ALL_TASK_MASK; + //存在一个参数为进程号 } else { taskId = strtoul(argv[0], &endPtr, 0); + //如果进程号不合法,打印错误信息 if ((*endPtr != 0) || (taskId >= g_taskMaxNum)) { PRINTK("\ntask ID can't access %s.\n", argv[0]); return OS_ERROR; } } - + //调用OsShellCmdTskInfoGet函数,输出该进程的进程信息 return OsShellCmdTskInfoGet((UINT32)taskId); } else { + //参数不合法,打印错误信息 PRINTK("\nUsage: task or task ID\n"); return OS_ERROR; } } - +//注册Shell命令task,调用OsShellCmdDumpTask,根据参数(进程号或者没有参数)获取进程信息并输出。 SHELLCMD_ENTRY(task_shellcmd, CMD_TYPE_EX, "task", 1, (CmdCallBackFunc)OsShellCmdDumpTask); #endif From dc810a0753e1095201c44f1069f1765152eb32cc Mon Sep 17 00:00:00 2001 From: cailun <2505225681@qq.com> Date: Sun, 31 Dec 2023 23:54:47 +0800 Subject: [PATCH 26/26] doc --- doc/用例描述_蔡伦.docx | Bin 0 -> 17632 bytes doc/蔡伦_LiteOS阅读泛读报告.docx | Bin 17703 -> 152986 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 doc/用例描述_蔡伦.docx diff --git a/doc/用例描述_蔡伦.docx b/doc/用例描述_蔡伦.docx new file mode 100644 index 0000000000000000000000000000000000000000..7c2941e1a899844dd1509ee8bd94e0b1e9ff2795 GIT binary patch literal 17632 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 S0RXTcFQ5+z9TE8B?EeFPjSr9j literal 0 HcmV?d00001 diff --git a/doc/蔡伦_LiteOS阅读泛读报告.docx b/doc/蔡伦_LiteOS阅读泛读报告.docx index 0a783a053357a4ec994b9e271fdba1e3ebf06a04..6bfadf4a5ffcd27543911dbc2e6ae7c4ded2c299 100644 GIT binary patch delta 147939 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 !rk+Vx4vld{YbXZhp>erT^TPS`~93910;qNJe> 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

      @y7> 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%0A%ZGl0YxVYes$tEeKA4yL!A> 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