目录
- 一、cortex-m4 los_dispatch.S代码分析
- 坚持就有收获
一、cortex-m4 los_dispatch.S代码分析
.syntax unified #.syntax [unified | divided], 指定arm 汇编语法规则
.arch armv7e-m #指定平台, 与命令行参数-march同样的作用
.fpu fpv4-sp-d16 #指定浮点运算单元,与命令行参数-mfpu同样的作用
.thumb # .thumb伪操作等同于.code 16, 表明使用Thumb指令# .equ 定义静态符号,把常量值设置为可以在文本段中使用的符号
.equ OS_FPU_CPACR, 0xE000ED88
.equ OS_FPU_CPACR_ENABLE, 0x00F00000
.equ OS_NVIC_INT_CTRL, 0xE000ED04
.equ OS_NVIC_SYSPRI2, 0xE000ED20
.equ OS_NVIC_PENDSV_PRI, 0xF0F00000
.equ OS_NVIC_PENDSVSET, 0x10000000
.equ OS_TASK_STATUS_RUNNING, 0x0010
.equ OS_CONTROL_FPCA_ENABLE, 0x4
.equ OS_CONTROL_KERNEL_MODE, 0x2
#if (LOSCFG_SECURE == 1)
.equ OS_CONTROL_USER_MODE, 0x3
.equ OS_TASK_FLAG_USER_TASK, 0x0200
#endif.section .text # 后面那些指令都属于.text段.thumb# .macro/.endm 定义一个宏,可以把需要重复执行的一段代码,或者是一组指令缩写成一个宏,
# 在程序调用的时候就可以直接去调用这个宏而使代码更加简洁清晰
.macro SIGNAL_CONTEXT_RESTOREpush {r12, lr}blx OsSignalTaskContextRestorepop {r12, lr}cmp r0, #0mov r1, r0bne SignalContextRestore
.endm.type HalStartToRun, %function # HalStartToRun 类型为函数.global HalStartToRun # 声明全局符号。全局符号是指在本程序外可访问的符号
HalStartToRun: # .fnstart # 函数开始.cantunwind # 可以被栈回溯# ldr Rt, label 从label加载一个字到寄存器Rt中# str Rt, label 从地址Rt读取一个字到label中# [Rt]表示读取地址Rt处数据ldr r4, =OS_NVIC_SYSPRI2 # 加载OS_NVIC_SYSPRI2 符号到寄存器r4中ldr r5, =OS_NVIC_PENDSV_PRI # 加载OS_NVIC_PENDSV_PRI 符号到寄存器r4中str r5, [r4] # 读取地址r5处一个字数据,到r4地址中# 以上3条指令等效于:*((volatile u32 *)0xE000ED20) = 0xF0F00000# 设置PENDSV优先级为最低# 给寄存器传递一个立即数,此时需要用“#”来修饰立即数,并且立即数为8位的,其值不能超过255.# 特殊寄存器必须用MRS(),MSR 指令访问# MRS <gp_reg>, <special_reg> ;读特殊功能寄存器的值到通用寄存器# MSR <special_reg>, <gp_reg> ;写通用寄存器的值到特殊功能寄存器mov r0, #OS_CONTROL_KERNEL_MODE msr CONTROL, r0 # 将r0数据写入CONTROL特殊寄存器中# 以上2条指令完成,sp使用进程堆栈指针ldr r1, =g_losTask # 将g_losTask结构体变量地址加载到r1中ldr r0, [r1, #4] # 将g_losTask.newTask地址加载到r1中,r1此时为newTask的TaskCB的内存地址ldr r12, [r0] # g_losTask->newTask->stackPointer加载到寄存器r12# g以上3条指令完成,任务上下文加载ldr.w r1, =OS_FPU_CPACRldr r1, [r1]and r1, r1, #OS_FPU_CPACR_ENABLEcmp r1, #OS_FPU_CPACR_ENABLEbne __DisabledFPU # if(r1 != 0) 执行__DisabledFPU符号位指令add r12, r12, #100ldmfd r12!, {R0-R7}add r12, r12, #72msr psp, r12vpush {s0}vpop {s0}mov lr, r5cpsie ibx r6__DisabledFPU:add r12, r12, #36 # 加载数据变为context->uwR0 = taskID;ldmfd r12!, {r0-r7} # 加载context->uwR0~context->uwxPSR 到 r0-r7中msr psp, r12 # 加载r12地址中一个字到psp中mov lr, r5 # 加载r5 context->uwLR到lr寄存器中cpsie I # 开中断bx r6 # context->uwPC.fnend # HalStartToRun end.type ArchIntLock, %function.global ArchIntLock
ArchIntLock:.fnstart.cantunwindMRS R0, PRIMASKCPSID IBX LR.fnend.type ArchIntUnLock, %function.global ArchIntUnLock
ArchIntUnLock:.fnstart.cantunwindMRS R0, PRIMASKCPSIE IBX LR.fnend.type ArchIntRestore, %function.global ArchIntRestore
ArchIntRestore:.fnstart.cantunwindMSR PRIMASK, R0BX LR.fnend.type ArchTaskSchedule, %function.global ArchTaskSchedule
ArchTaskSchedule:.fnstart.cantunwindldr r0, =OS_NVIC_INT_CTRLldr r1, =OS_NVIC_PENDSVSETstr r1, [r0]bx lrdsbisb.fnend.type HalPendSV, %function.global HalPendSV
HalPendSV:.fnstart.cantunwindmrs r12, PRIMASKcpsid IHalTaskSwitch:SIGNAL_CONTEXT_RESTOREpush {r12, lr}blx OsSchedTaskSwitchpop {r12, lr}cmp r0, #0mov r0, lrbne TaskContextSwitchmsr PRIMASK, r12bx lrTaskContextSwitch:mov lr, r0mrs r0, pspstmfd r0!, {r4-r12}ldr.w r3, =OS_FPU_CPACRldr r3, [r3]and r3, r3, #OS_FPU_CPACR_ENABLEcmp r3, #OS_FPU_CPACR_ENABLEbne __DisabledFPU1vstmdb r0!, {d8-d15}__DisabledFPU1:ldr r5, =g_losTaskldr r6, [r5]str r0, [r6]ldr r0, [r5, #4]str r0, [r5]ldr r1, [r0]SignalContextRestore:ldr.w r3, =OS_FPU_CPACRldr r3, [r3]and r3, r3, #OS_FPU_CPACR_ENABLEcmp r3, #OS_FPU_CPACR_ENABLEbne __DisabledFPU2vldmia r1!, {d8-d15}__DisabledFPU2:
#if (LOSCFG_SECURE == 1)ldrh r7, [r0, #4]tst r7, #OS_TASK_FLAG_USER_TASKite eqmoveq r3, #OS_CONTROL_KERNEL_MODEmovne r3, #OS_CONTROL_USER_MODEmsr CONTROL, r3
#endifldmfd r1!, {r4-r12}msr psp, r1msr PRIMASK, r12bx lr.fnend
二、LOS_KernelInit代码分析
/*****************************************************************************Function : LOS_KernelInitDescription : System kernel initialization function, configure all system modulesInput : NoneOutput : NoneReturn : LOS_OK on success or error code on failure*****************************************************************************/
LITE_OS_SEC_TEXT_INIT UINT32 LOS_KernelInit(VOID)
{UINT32 ret;PRINTK("entering kernel init...\n");#if (LOSCFG_BACKTRACE_TYPE != 0) //LOSCFG_XXX 宏定义为make menuconfig生成的宏OsBackTraceInit(); //函数目前用于初始化内存泄漏检查钩子
#endif#ifdef LOSCFG_KERNEL_LMSOsLmsInit(); //初始化 LMS全称为Lite Memory Sanitizer,是一种实时检测内存操作合法性的调测工具
#endifret = OsMemSystemInit();if (ret != LOS_OK) {PRINT_ERR("OsMemSystemInit error %d\n", ret);return ret;}ArchInit();ret = OsTickTimerInit();if (ret != LOS_OK) {PRINT_ERR("OsTickTimerInit error! 0x%x\n", ret);return ret;}ret = OsTaskInit();if (ret != LOS_OK) {PRINT_ERR("OsTaskInit error\n");return ret;}#if (LOSCFG_BASE_CORE_TSK_MONITOR == 1)OsTaskMonInit();
#endif#if (LOSCFG_BASE_CORE_CPUP == 1)ret = OsCpupInit();if (ret != LOS_OK) {PRINT_ERR("OsCpupInit error\n");return ret;}
#endif#if (LOSCFG_BASE_IPC_SEM == 1)ret = OsSemInit();if (ret != LOS_OK) {return ret;}
#endif#if (LOSCFG_BASE_IPC_MUX == 1)ret = OsMuxInit();if (ret != LOS_OK) {return ret;}
#endif#if (LOSCFG_BASE_IPC_QUEUE == 1)ret = OsQueueInit();if (ret != LOS_OK) {PRINT_ERR("OsQueueInit error\n");return ret;}
#endif#if (LOSCFG_BASE_CORE_SWTMR == 1)ret = OsSwtmrInit();if (ret != LOS_OK) {PRINT_ERR("OsSwtmrInit error\n");return ret;}
#endif#if (LOSCFG_CPUP_INCLUDE_IRQ == 1)ret = OsCpupDaemonInit();if (ret != LOS_OK) {PRINT_ERR("OsCpupDaemonInit error\n");return ret;}
#endif#if (LOSCFG_FS_VFS == 1)ret = OsVfsInit();if (ret != LOS_OK) {PRINT_ERR("OsVfsInit error\n");return ret;}
#endifret = OsIdleTaskCreate();if (ret != LOS_OK) {return ret;}#if (LOSCFG_KERNEL_TRACE == 1)ret = OsTraceInit();if (ret != LOS_OK) {PRINT_ERR("OsTraceInit error\n");return ret;}
#endif#if (LOSCFG_KERNEL_PM == 1)ret = OsPmInit();if (ret != LOS_OK) {PRINT_ERR("Pm init failed!\n");return ret;}
#endif#if (LOSCFG_KERNEL_LMK == 1)OsLmkInit();
#endif#if (LOSCFG_PLATFORM_EXC == 1)OsExcMsgDumpInit();
#endif#if (LOSCFG_DYNLINK == 1)ret = LOS_DynlinkInit();if (ret != LOS_OK) {return ret;}
#endif#if (LOSCFG_POSIX_PIPE_API == 1)ret = OsPipeInit();if (ret != LOS_OK) {PRINT_ERR("Pipe init failed!\n");return ret;}
#endif#if (LOSCFG_KERNEL_SIGNAL == 1)ret = OsSignalInit();if (ret != LOS_OK) {PRINT_ERR("Signal init failed!\n");return ret;}
#endif#if (LOSCFG_SECURE == 1)OsSyscallHandleInit();LOS_BoxStart();
#endifreturn LOS_OK;
}