赞
踩
如果有问题,请加QQ群 891339868 进行交流
一、汇编部分
具体路径为:
1、多核处理器:arch/arm/arm/src/startup/reset_vector_mp.S;
2、单核处理器:arm/arm/arm/src/startup/reset_vector_up.S
汇编看的不是特别明白,但是备注写的还是比较清楚的,根据备注的意思主要是做了以下工作:
(1)、reset相关的寄存器,做一些CPU早期的配置
(2)、计算cpu虚拟地址与物理地址的线性映射关系
(3)、配置MMU相关参数
(4)、物理地址与虚拟地址之间映射页表的创建
、、、
最后跳转到C语言main函数
汇编能力有限,有时间了再深入研究
二、C语言部分
具体的路径为:platform/main.c
1、main函数分析:
- LITE_OS_SEC_TEXT_INIT INT32 main(VOID)
- {
- UINT32 uwRet = LOS_OK;
-
- OsSetMainTask();//配置系统初始化的任务
- OsCurrTaskSet(OsGetMainTask());
-
- /* set smp system counter freq */
- #if (LOSCFG_KERNEL_SMP == YES)
- #ifndef LOSCFG_TEE_ENABLE
- HalClockFreqWrite(OS_SYS_CLOCK);
- #endif
- #endif
-
- /* system and chip info */
- OsSystemInfo();//打印系统的相关信息
-
- PRINT_RELEASE("\nmain core booting up...\n");
-
- uwRet = OsMain();
- if (uwRet != LOS_OK) {
- return LOS_NOK;
- }
-
- #if (LOSCFG_KERNEL_SMP == YES)
- PRINT_RELEASE("releasing %u secondary cores\n", LOSCFG_KERNEL_SMP_CORE_NUM - 1);
- release_secondary_cores();
- #endif
-
- CPU_MAP_SET(0, OsHwIDGet());
-
- OsSchedStart();//系统使能调度器
-
- while (1) {
- __asm volatile("wfi");
- }
- }
这一段代码就是liteos-a的main函数代码,其中的每一个代码段,都非常重要,都有各自非常关键的任务,下面一条一条进行分析:
(1)、OsSetMainTask()
根据函数的名称,应该是设置主函数的任务。跟进去看一下去代码:
- 备注:
- g_mainTask:struct LosTaskCB结构体数组,每一个元素代表一个任务
-
- VOID OsSetMainTask()
- {
- UINT32 i;
- CHAR *name = "osMain";
-
- for (i = 0; i < LOSCFG_KERNEL_CORE_NUM; i++) {//遍历cpu所有核心,配置相关参数
- //LOSCFG_KERNEL_CORE_NUM,CPU核心数目
- g_mainTask[i].taskStatus = OS_TASK_STATUS_UNUSED;//初始化当前任务的状态为unused
- g_mainTask[i].taskID = LOSCFG_BASE_CORE_TSK_LIMIT;//初始化当前任务ID都为128
- g_mainTask[i].priority = OS_TASK_PRIORITY_LOWEST;//初始化当前任务的优先级都为低
- #if (LOSCFG_KERNEL_SMP_LOCKDEP == YES)
- g_mainTask[i].lockDep.lockDepth = 0;
- g_mainTask[i].lockDep.waitLock = NULL;
- #endif
- (VOID)strncpy_s(g_mainTask[i].taskName, OS_TCB_NAME_LEN, name, OS_TCB_NAME_LEN - 1);
- LOS_ListInit(&g_mainTask[i].lockList);//
- }
- }
(2)、OsGetMainTask()
应该是获取当前cpu绑定的task,代码跟进去看一下:
- 备注:代码很短,就是活动当前CPU所运行的任务,返回当前task指针
- LosTaskCB *OsGetMainTask()
- {
- return (LosTaskCB *)(g_mainTask + ArchCurrCpuid());
- }
(3)、OsCurrTaskSet(OsGetMainTask())
名称看不出来,代码跟进去看一下:
- //第一级
- STATIC INLINE VOID OsCurrTaskSet(LosTaskCB *task)
- {
- ArchCurrTaskSet(task);
- }
- //第二级
- STATIC INLINE VOID ArchCurrTaskSet(VOID *val)
- {
- ARM_SYSREG_WRITE(TPIDRPRW, (UINT32)(UINTPTR)val);
- }
- //第三级
- #define ARM_SYSREG_WRITE(REG, val) \
- ({ \
- __asm__ volatile("mcr " REG :: "r" (val)); \
- ISB; \
- })
-
- 备注:
- TPIDRPRW = CP15_REG(c13, 0, c0, 4)
- #define CP15_REG(CRn, Op1, CRm, Op2) "p15, "#Op1", %0, "#CRn","#CRm","#Op2
-
- 这样一级一级追下去,最终通过汇编代码对寄存器赋值
(4)、HalClockFreqWrite(OS_SYS_CLOCK)
从名称上猜测,应该是时钟的设置,代码追进去看一下:
- 第一级:
- VOID HalClockFreqWrite(UINT32 freq)
- {
- WRITE_TIMER_REG32(TIMER_REG_CNTFRQ, freq);
- }
- 第二级:
- #define WRITE_TIMER_REG32(reg, val) ARM_SYSREG_WRITE(reg, val)
- 第三级:
- #define ARM_SYSREG_WRITE(REG, val) \
- ({ \
- __asm__ volatile("mcr " REG :: "r" (val)); \
- ISB; \
- })
-
- 备注:
- 从代码中可以很清楚的看出来,和上面同样的套路,最终调用arm的汇编语言对相关寄存器进行配置
(5)、OsSystemInfo()
从名称上看应该是系统的相关信息,代码追进去看一下:
- LITE_OS_SEC_TEXT_INIT VOID OsSystemInfo(VOID)
- {
- #ifdef LOSCFG_DEBUG_VERSION
- const CHAR *buildType = "debug";
- #else
- const CHAR *buildType = "release";
- #endif /* LOSCFG_DEBUG_VERSION */
-
- PRINT_RELEASE("\n******************Welcome******************\n\n"
- "Processor : %s"
- #if (LOSCFG_KERNEL_SMP == YES)
- " * %d\n"
- "Run Mode : SMP\n"
- #else
- "\n"
- "Run Mode : UP\n"
- #endif
- "GIC Rev : %s\n"
- "build time : %s %s\n"
- "Kernel : %s %d.%d.%d.%d/%s\n"
- "\n*******************************************\n",
- LOS_CpuInfo(),
- #if (LOSCFG_KERNEL_SMP == YES)
- LOSCFG_KERNEL_SMP_CORE_NUM,
- #endif
- HalIrqVersion(), __DATE__, __TIME__,\
- KERNEL_NAME, KERNEL_MAJOR, KERNEL_MINOR, KERNEL_PATCH, KERNEL_ITRE, buildType);
- }
- 备注:
- 从代码上看,这个子程序就是一个PRINT_RELEASE宏,打印内核名称,主版本号,次版本号,内核补丁等内容,只是打印,没有操作
-
(6)、OsMain()
从名字上看,貌似很重要,代码追进去看一看:
- LITE_OS_SEC_TEXT_INIT INT32 OsMain(VOID)
- {
- UINT32 ret;
-
- osRegister();//看名称是系统注册,其实内容是获取时钟等基本信息
- //展开上面osRegister()这个函数看一下
- /******************************************************/
- LITE_OS_SEC_TEXT_INIT VOID osRegister(VOID)
- {
- g_sysClock = OS_SYS_CLOCK;//获取系统时钟
- g_tickPerSecond = LOSCFG_BASE_CORE_TICK_PER_SECOND;//获取系统每秒钟的tick数目(类似于人的心跳)
-
- return;
- }
- /******************************************************/
-
- #ifdef LOSCFG_SHELL_DMESG
- ret = OsDmesgInit();//Dmesg工具的初始化
- if (ret != LOS_OK) {
- return ret;
- }
- //展开上面OsDmesgInit()这个函数看一下
- /******************************************************/
- UINT32 OsDmesgInit(VOID)
- {
- CHAR* buffer = NULL;
-
- buffer = (CHAR *)malloc(KERNEL_LOG_BUF_SIZE + sizeof(DmesgInfo));
- if (buffer == NULL) {
- return LOS_NOK;
- }
- g_mallocAddr = buffer;
- g_dmesgInfo = (DmesgInfo *)buffer;
- g_dmesgInfo->logHead = 0;
- g_dmesgInfo->logTail = 0;
- g_dmesgInfo->logSize = 0;
- g_dmesgInfo->logBuf = buffer + sizeof(DmesgInfo);
- g_logBufSize = KERNEL_LOG_BUF_SIZE;
-
- return LOS_OK;
- }
- //从上面的代码中,很容易能看出来,就是为了给dmesg工具分配内存,并初始化
- /******************************************************/
- #endif
-
- #ifdef LOSCFG_SHELL_LK
- OsLkLoggerInit(NULL);
- //展开上面OsLkLoggerInit(NULL)这个函数看一下
- /**************************************************************/
- VOID OsLkLoggerInit(const CHAR *str)
- {
- (VOID)str;
- (VOID)memset_s(&g_logger, sizeof(Logger), 0, sizeof(Logger));//相关内存清零
- OsLkTraceLvSet(TRACE_DEFAULT);//设置内核信息追踪级别
- LOS_LkRegHook(OsLkDefaultFunc);//设置绑定函数
- #ifdef LOSCFG_SHELL_DMESG
- (VOID)LOS_DmesgLvSet(TRACE_DEFAULT);//设置dmesg打印级别
- #endif
- }
- 这里面的一个核心结构是Logger,它具体的内容为:
- typedef struct {
- INT32 module_level;
- INT32 trace_level;
- FILE *fp;
- } Logger;
- 从这里面可以大概猜出来,就是任务log的级别
- /**************************************************************/
- #endif
-
- #if (LOSCFG_KERNEL_TRACE == YES)
- LOS_TraceInit();
- #endif
-
- #ifdef LOSCFG_EXC_INTERACTION
- #ifdef LOSCFG_ARCH_CORTEX_M7
- /* 4096: 4K space for Stack */
- ret = OsMemExcInteractionInit((UINT32)&__bss_end + 4096);
- #else
- ret = OsMemExcInteractionInit((UINTPTR)&__bss_end);
- #endif
- if (ret != LOS_OK) {
- return ret;
- }
- #endif
-
- #if (LOSCFG_PLATFORM_HWI == YES)
- OsHwiInit();//硬件中断初始化
- #endif
-
- OsExcInit();//栈初始化
-
- ret = OsTickInit(g_sysClock, LOSCFG_BASE_CORE_TICK_PER_SECOND);//滴答定时初始化
- if (ret != LOS_OK) {
- return ret;
- }
-
- #ifdef LOSCFG_PLATFORM_UART_WITHOUT_VFS
- #ifdef LOSCFG_DRIVERS
- uart_init();
- #endif
- #ifdef LOSCFG_SHELL
- #endif //LOSCFG_SHELL
- #endif //LOSCFG_PLATFORM_UART_WITHOUT_VFS
- ret = OsTaskInit();//系统的任务初始化
- if (ret != LOS_OK) {
- PRINT_ERR("OsTaskInit error\n");
- return ret;
- }
- /*上面那个OsTaskInit()函数展开看一下*/
- /************************************************/
- LITE_OS_SEC_TEXT_INIT UINT32 OsTaskInit(VOID)
- {
- UINT32 index;
- UINT32 size;
-
- g_taskMaxNum = LOSCFG_BASE_CORE_TSK_LIMIT;//设置系统的同时运行任务最大数
- size = (g_taskMaxNum + 1) * sizeof(LosTaskCB);
- /*
- * This memory is resident memory and is used to save the system resources
- * of task control block and will not be freed.
- */
- g_taskCBArray = (LosTaskCB *)LOS_MemAlloc(m_aucSysMem0, size);//申请空间
- if (g_taskCBArray == NULL) {
- return LOS_ERRNO_TSK_NO_MEMORY;
- }
- (VOID)memset_s(g_taskCBArray, size, 0, size);//空间初始化
-
- LOS_ListInit(&g_losFreeTask);//空闲任务链表初始化
- LOS_ListInit(&g_taskRecyleList);//回收任务链表初始化
- for (index = 0; index < g_taskMaxNum; index++) {//遍历所有任务并初始化
- g_taskCBArray[index].taskStatus = OS_TASK_STATUS_UNUSED;//设置任务状态
- g_taskCBArray[index].taskID = index;//根据任务在数组的位置设置任务id
- LOS_ListTailInsert(&g_losFreeTask, &g_taskCBArray[index].pendList);//将该任务绑定挂起的链表结点加入到空闲任务链表中
- }
-
- #if (LOSCFG_KERNEL_TRACE == YES)
- LOS_TraceReg(LOS_TRACE_TASK, OsTaskTrace, LOS_TRACE_TASK_NAME, LOS_TRACE_ENABLE);
- #endif
-
- return OsSchedInit();
- }
- /**************************************************************************/
- #if ((LOSCFG_BASE_IPC_QUEUE == YES) || (LOSCFG_BASE_IPC_MUX == YES) || \
- (LOSCFG_BASE_IPC_SEM == YES) || (LOSCFG_BASE_IPC_RWLOCK == YES))
- ret = OsIpcInit();
- if (ret != LOS_OK) {
- return ret;
- }
- //展开上面的OsIpcInit()这个函数
- LITE_OS_SEC_TEXT_INIT STATIC UINT32 OsIpcInit(VOID)
- {
- UINT32 ret;
- #if (LOSCFG_BASE_IPC_SEM == YES)
- ret = OsSemInit();//信号量初始化,具体的可以跟进去看一下,其实还是一个套路,按照系统信号量最大的数目限制申请内存,并一一初始化,并将每一个信号量加入到空闲信号量的链表中
- if (ret != LOS_OK) {
- return ret;
- }
- #endif
-
- #if (LOSCFG_BASE_IPC_QUEUE == YES)
- ret = OsQueueInit();//信号量队列初始化,具体的可以跟进去看一下,和信号量的初始化差不多
- if (ret != LOS_OK) {
- return ret;
- }
- #endif
- return LOS_OK;
- }
-
- #endif
-
- ret = OsSysMemInit();//系统内存初始化,内容还是比较复杂的,包括内存空间的初始化,虚拟内存与物理内存的转换关系,页表的产生,内存映射等内容
- if (ret != LOS_OK) {
- PRINT_ERR("OsSysMemInit error\n");
- return ret;
- }
-
- SyscallHandleInit();
-
- /*
- * CPUP should be inited before first task creation which depends on the semaphore
- * when LOSCFG_KERNEL_SMP_TASK_SYNC is enabled. So don't change this init sequence
- * if not neccessary. The sequence should be like this:
- * 1. OsIpcInit
- * 2. OsCpupInit
- * 3. other inits have task creation
- */
- #ifdef LOSCFG_KERNEL_CPUP
- ret = OsCpupInit();
- if (ret != LOS_OK) {
- PRINT_ERR("OsCpupInit error\n");
- return ret;
- }
- #endif
-
- ret = OsSystemProcessCreate();//创建系统进程
- if (ret != LOS_OK) {
- return ret;
- }
-
- #if (LOSCFG_BASE_CORE_SWTMR == YES)
- ret = OsSwtmrInit();//软件定时器的初始化
- if (ret != LOS_OK) {
- return ret;
- }
- #endif
-
- #ifdef LOSCFG_KERNEL_CPUP
- OsCpupGuardCreator();//cpu占有率监控进程创建,其实就是定时去采样cpu的状态,里面用到了软件定时器,所以必须在软件定时器初始化以后再创建
- #endif
-
- #if (LOSCFG_KERNEL_SMP == YES)
- (VOID)OsMpInit();//多核模式下,循环去查询所有的有效任务(线程)的状态,里面也用到了软件定时器
- #endif
-
- #if defined(LOSCFG_HW_RANDOM_ENABLE) || defined (LOSCFG_DRIVERS_RANDOM)
- random_alg_context.ra_init_alg(NULL);
- run_harvester_iterate(NULL);
- #endif
-
- #ifdef LOSCFG_COMPAT_BSD
- ret = OsBsdInit();
- if (ret != LOS_OK) {
- PRINT_ERR("init bsd failed!\n");
- return ret;
- }
- #endif
-
- #ifdef LOSCFG_KERNEL_PIPE
- OsDriverPipeInit();
- #endif
-
- ret = OsSystemInit();//系统相关的内容初始化,包括虚拟文件系统,创建SystemInit任务等
- if (ret != LOS_OK) {
- return ret;
- }
- #if (LOSCFG_BASE_CORE_HILOG == YES)
- ret = HiLogDriverInit();//看名字是HiLog设备的驱动初始化,可是HiLog是什么设备呢?和海思处理器相关?
- if (ret != LOS_OK) {
- return ret;
- }
- #endif
-
- #if LOSCFG_DRIVERS_HIEVENT
- OsDriverHiEventInit();
- #endif
-
- #if (LOSCFG_KERNEL_LITEIPC == YES)
- ret = LiteIpcInit();
- if (ret != LOS_OK) {
- return ret;
- }
- #endif
-
- #ifdef LOSCFG_KERNEL_VDSO
- ret = OsInitVdso();
- if (ret != LOS_OK) {
- return ret;
- }
- #endif
-
- ret = OsFutexInit(); //看名字是fast mutex 初始化,具体功能不详
- if (ret != LOS_OK) {
- PRINT_ERR("Create futex failed : %d!\n", ret);
- return ret;
- }
-
- ret = OomTaskInit(); //看名字是out of memory 任务初始化,具体功能不详
- if (ret != LOS_OK) {
- return ret;
- }
-
- return LOS_OK;
- }
(7)、 release_secondary_cores()
从名称上看,应该是启动其他cpu核心,具体代码没有看明白,后期补充
(8)、CPU_MAP_SET(0, OsHwIDGet())
从名称上看,应该是设置cpu核心的ID
(9)、OsSchedStart()
从名称上看,应该是开启系统的各项task,代码跟进去看一下:
- VOID OsSchedStart(VOID)
- {
- UINT32 cpuid = ArchCurrCpuid();//获得当前任务的cpu核心id
- UINT32 intSave;
-
- SCHEDULER_LOCK(intSave);
-
- OsTickStart();//滴答定时器启动
-
- LosTaskCB *newTask = OsGetTopTask();//启动栈顶部的任务
- LosProcessCB *newProcess = OS_PCB_FROM_PID(newTask->processID);//根据当前任务绑定的进程ID创建一个进程
-
- newTask->taskStatus |= OS_TASK_STATUS_RUNNING;//设置任务(线程)的状态
- newProcess->processStatus |= OS_PROCESS_STATUS_RUNNING;//设置进程的状态
- newProcess->processStatus = OS_PROCESS_RUNTASK_COUNT_ADD(newProcess->processStatus);
-
- OsSchedSetStartTime(HalClockGetCycles());
- newTask->startTime = OsGerCurrSchedTimeCycle();
-
- #if (LOSCFG_KERNEL_SMP == YES)
- /*
- * attention: current cpu needs to be set, in case first task deletion
- * may fail because this flag mismatch with the real current cpu.
- */
- newTask->currCpu = cpuid;
- #endif
-
- OsCurrTaskSet((VOID *)newTask);
-
- /* System start schedule */
- OS_SCHEDULER_SET(cpuid);
-
- OsPercpuGet()->responseID = OS_INVALID;
- OsSchedSetNextExpireTime(newTask->startTime, newTask->taskID, newTask->startTime + newTask->timeSlice, OS_INVALID);
-
- PRINTK("cpu %d entering scheduler\n", cpuid);
- OsTaskContextLoad(newTask);
- }
到这里,openharmony的liteos-a内核的初始化过程基本上分析完成。好了,今天就记录到这里
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。