赞
踩
.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_RESTORE push {r12, lr} blx OsSignalTaskContextRestore pop {r12, lr} cmp r0, #0 mov r1, r0 bne 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_CPACR ldr r1, [r1] and r1, r1, #OS_FPU_CPACR_ENABLE cmp r1, #OS_FPU_CPACR_ENABLE bne __DisabledFPU # if(r1 != 0) 执行__DisabledFPU符号位指令 add r12, r12, #100 ldmfd r12!, {R0-R7} add r12, r12, #72 msr psp, r12 vpush {s0} vpop {s0} mov lr, r5 cpsie i bx 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 # pc跳转到context->uwPC .fnend # HalStartToRun end .type ArchIntLock, %function .global ArchIntLock ArchIntLock: # 关闭中断 .fnstart .cantunwind MRS R0, PRIMASK # 读取寄存器PRIMASK到R0中 CPSID I # 关中断 BX LR # 返回 .fnend .type ArchIntUnLock, %function .global ArchIntUnLock ArchIntUnLock: # 开中断 .fnstart .cantunwind MRS R0, PRIMASK # 读取寄存器PRIMASK到R0中 CPSIE I # 开中断 BX LR # 返回 .fnend .type ArchIntRestore, %function .global ArchIntRestore ArchIntRestore: .fnstart .cantunwind MSR PRIMASK, R0 # 读取R0数据到PRIMAK BX LR # 返回 .fnend .type ArchTaskSchedule, %function .global ArchTaskSchedule ArchTaskSchedule: .fnstart .cantunwind ldr r0, =OS_NVIC_INT_CTRL ldr r1, =OS_NVIC_PENDSVSET str r1, [r0] # 悬起pendSV bx lr # 返回 dsb # 数据同步屏障,确保在下一条指令开始执行前,所有的存储器访问已经完成。 isb # 指令同步屏障,清除流水线并且确保在新指令执行时,之前的指令都已经执行完毕。 .fnend .type HalPendSV, %function .global HalPendSV HalPendSV: # pendSV实现函数 .fnstart .cantunwind mrs r12, PRIMASK # 加载PRIMASK寄存器到r12 cpsid I # 关中断 HalTaskSwitch: SIGNAL_CONTEXT_RESTORE push {r12, lr} blx OsSchedTaskSwitch # 跳转执行任务切换 pop {r12, lr} cmp r0, #0 mov r0, lr bne TaskContextSwitch # 如果cmp r0, #0 执行不等于0时,跳转执行任务上下文切换 msr PRIMASK, r12 # 开中断 bx lr # 若不切换任务上下文,则直接返回 TaskContextSwitch: mov lr, r0 mrs r0, psp # 任务栈指针保存到r0 stmfd r0!, {r4-r12} # r4-r12数据存入任务栈 ldr.w r3, =OS_FPU_CPACR ldr r3, [r3] and r3, r3, #OS_FPU_CPACR_ENABLE cmp r3, #OS_FPU_CPACR_ENABLE bne __DisabledFPU1 vstmdb r0!, {d8-d15} # 如果支持浮点寄存器时,把d8-d15压入栈中。 __DisabledFPU1: ldr r5, =g_losTask # 把g_losTask地址加载到r5 ldr r6, [r5] # 获取当前运行任务栈指针,然后更新当前运行的任务栈指针。 str r0, [r6] ldr r0, [r5, #4] # 获取新任务newTask的地址, str r0, [r5] # 把newTask地址赋值到runTask ldr r1, [r0] # newTask地址赋值到r1 SignalContextRestore: ldr.w r3, =OS_FPU_CPACR ldr r3, [r3] and r3, r3, #OS_FPU_CPACR_ENABLE cmp r3, #OS_FPU_CPACR_ENABLE bne __DisabledFPU2 vldmia r1!, {d8-d15} __DisabledFPU2: #if (LOSCFG_SECURE == 1) ldrh r7, [r0, #4] tst r7, #OS_TASK_FLAG_USER_TASK ite eq moveq r3, #OS_CONTROL_KERNEL_MODE movne r3, #OS_CONTROL_USER_MODE msr CONTROL, r3 #endif ldmfd r1!, {r4-r12} # 加载newTask任务栈数据到r4-r12中 msr psp, r1 # 更新任务栈指针为newTask任务栈地址 msr PRIMASK, r12 # 开中断 bx lr # 返回 .fnend
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。