diff --git a/arch/arm/arm/include/arch_config.h b/arch/arm/arm/include/arch_config.h index 1a4fd418afa1e7691f6be79faf84b372982a85f1..5a4e62cc7bac682cef32b86eb2e5f95f7bdfd3db 100644 --- a/arch/arm/arm/include/arch_config.h +++ b/arch/arm/arm/include/arch_config.h @@ -77,12 +77,12 @@ MRS{条件} 通用寄存器,程序状态寄存器(CPSR 或SPSR) MRS R0,SPSR @传送SPSR 的内容到R0 @MRS指令是唯一可以直接读取CPSR和SPSR寄存器的指令 -SPSR - 程序状态保护寄存器,每一种模式下都有一个状态寄存器SPSR,用于保存CPSR的状态, +SPSR(saved program status register)程序状态保存寄存器. + 每一种模式下都有一个状态寄存器SPSR,用于保存CPSR的状态, 以便异常返回后恢复异常发生时的工作状态。用户模式和系统模式不是异常状态, 所以没有SPSR,在这两种模式下访问SPSR,将产生不可预知的后果。 1、SPSR 为 CPSR 中断时刻的副本,退出中断后,将SPSR中数据恢复到CPSR中。 - 2、用户模式和系统模式下SPSR不可用。 + 2、用户模式和系统模式下SPSR不可用,所以SPSR寄存器只有5个 ******************************************************************************/ #define CPSR_INT_DISABLE 0xC0 /* Disable both FIQ and IRQ */ //禁止IRQ和FIQ中断,因为0xC0 = 0x80 + 0x40 #define CPSR_IRQ_DISABLE 0x80 /* IRQ disabled when =1 */ //禁止IRQ 中断 @@ -99,7 +99,7 @@ SPSR /* Define exception type ID */ //ARM处理器一共有7种工作模式,除了用户和系统模式其余都叫异常工作模式 #define OS_EXCEPT_RESET 0x00 //重置功能,例如:开机就进入CPSR_SVC_MODE模式 #define OS_EXCEPT_UNDEF_INSTR 0x01 //未定义的异常,就是others -#define OS_EXCEPT_SWI 0x02 //软件定时器中断 +#define OS_EXCEPT_SWI 0x02 //软中断 #define OS_EXCEPT_PREFETCH_ABORT 0x03 //预取异常(取指异常), 指令三步骤: 取指,译码,执行, #define OS_EXCEPT_DATA_ABORT 0x04 //数据异常 #define OS_EXCEPT_FIQ 0x05 //快中断异常 diff --git a/arch/arm/arm/src/los_dispatch.S b/arch/arm/arm/src/los_dispatch.S index b35474d3c1fa3e93075d79dd968e1260737737fa..6e365726a456a03852db5b876e29e464b7008dfa 100644 --- a/arch/arm/arm/src/los_dispatch.S +++ b/arch/arm/arm/src/los_dispatch.S @@ -109,16 +109,16 @@ ARM的指令系统中关于栈指令的内容比较容易引起迷惑,这是 .global ArchSpinUnlock /*自旋锁解锁*/ .global OsSchedToUserSpinUnlock /*尚未实现*/ /* @note_why 为何要重新定义OS_TASK_STATUS_RUNNING? */ - .equ OS_TASK_STATUS_RUNNING, 0x0010U /* .equ用于把常量值设置为可以在文本段中使用的符号 #define OS_TASK_STATUS_RUNNING 0x0010U */ - .equ OS_PERCPU_STRUCT_SIZE, 0x28U - .equ OS_PERCPU_TASK_LOCK_OFFSET, 0x14U + .equ OS_TASK_STATUS_RUNNING, 0x0010U /* .equ用于把常量值设置为可以在文本段中使用的符号 #define OS_TASK_STATUS_RUNNING 0x0010U */ + .equ OS_PERCPU_STRUCT_SIZE, 0x28U /*宏定义 #define OS_PERCPU_STRUCT_SIZE 0x28U*/ + .equ OS_PERCPU_TASK_LOCK_OFFSET, 0x14U /*宏定义 #define OS_PERCPU_TASK_LOCK_OFFSET 0x14U*/ .fpu vfpv4 /* .fpu @note_why 尚未知这句话的含义 */ /* 此宏用于对齐和不对齐8字节边界上的堆栈以符合ABI */ /* macros to align and unalign the stack on 8 byte boundary for ABI compliance */ .macro STACK_ALIGN, reg /* 栈对齐*/ - MOV \reg, sp - TST SP, #4 - SUBEQ SP, #4 + MOV \reg, sp @reg=sp + TST SP, #4 @来检查是否设置了特定的位 + SUBEQ SP, #4 @表示相等时相减 PUSH { \reg } .endm @@ -226,13 +226,13 @@ OsTaskContextLoad: ADD SP, SP, #4 @sp=sp+4 #endif /* R0 = &g_taskSpin.rawLock */ - LDR R0, =g_taskSpin - BL ArchSpinUnlock - LDR R2, =g_percpu - MRC P15, 0, R3, C0, C0, 5 - UXTB R3, R3 - MOV R1, #OS_PERCPU_STRUCT_SIZE - MLA R3, R1, R3, R2 + LDR R0, =g_taskSpin @ R0 = &g_taskSpin.rawLock 将作为 ArchSpinUnlock的参数 + BL ArchSpinUnlock @释放自旋锁g_taskSpin + LDR R2, =g_percpu + MRC P15, 0, R3, C0, C0, 5 @获取CPUID给R3 + UXTB R3, R3 @字节被无符号扩展到32位(高24位清0) + MOV R1, #OS_PERCPU_STRUCT_SIZE @R1 = sizeof(Percpu) + MLA R3, R1, R3, R2 @R3=R1*R3 MOV R2, #0 STR R2, [R3, #OS_PERCPU_TASK_LOCK_OFFSET] #endif @@ -254,18 +254,18 @@ OsKernelTaskLoad: @内核任务的加载 ADD SP, SP, #4 @sp=SP+4 LDMFD SP!, {LR, PC}^ @返回地址赋给pc指针 -OsIrqHandler: @硬中断处理 +OsIrqHandler: @硬中断处理,此时已切换到硬中断栈 SUB LR, LR, #4 /* push r0-r3 to irq stack */ - STMFD SP, {R0-R3} @r0-r3寄存器入栈 - SUB R0, SP, #(4 * 4) + STMFD SP, {R0-R3} @r0-r3寄存器入 irq 栈 + SUB R0, SP, #(4 * 4)@r0 = sp - 16 MRS R1, SPSR @获取程序状态控制寄存器 - MOV R2, LR + MOV R2, LR @r2=lr /* disable irq, switch to svc mode */@超级用户模式(SVC 模式),主要用于 SWI(软件中断)和 OS(操作系统)。 CPSID i, #0x13 @切换到SVC模式,此处一切换,后续指令将入SVC的栈 - @CPSID i为关中断指令,对应的是CPSIE + @CPSID i为关中断指令,对应的是CPSIE /* push spsr and pc in svc stack */ STMFD SP!, {R1, R2} @实际是将 SPSR,和LR入栈,入栈顺序为 R1,R2,SP自增 STMFD SP, {LR} @LR再入栈,SP不自增 @@ -275,14 +275,14 @@ OsIrqHandler: @硬中断处理 BNE OsIrqFromKernel @中断不发生在用户模式下则跳转到OsIrqFromKernel /* push user sp, lr in svc stack */ - STMFD SP, {R13, R14}^ + STMFD SP, {R13, R14}^ @sp和LR入svc栈 OsIrqFromKernel: @从内核发起中断 - /* from svc not need save sp and lr */ - SUB SP, SP, #(2 * 4) + /* from svc not need save sp and lr */@svc模式下发生的中断不需要保存sp和lr寄存器值 + SUB SP, SP, #(2 * 4) @申请8个栈空间 - /* pop r0-r3 form irq stack*/ - LDMFD R0, {R0-R3} + /* pop r0-r3 from irq stack*/ + LDMFD R0, {R0-R3} @出栈 /* push caller saved regs as trashed regs in svc stack */ STMFD SP!, {R0-R3, R12} @@ -295,34 +295,34 @@ OsIrqFromKernel: @从内核发起中断 * altered in interrupt handlers. */ PUSH_FPU_REGS R0 -#ifdef LOSCFG_IRQ_USE_STANDALONE_STACK +#ifdef LOSCFG_IRQ_USE_STANDALONE_STACK @IRQ使用独立栈 PUSH {R4} MOV R4, SP EXC_SP_SET __svc_stack_top, OS_EXC_SVC_STACK_SIZE, R1, R2 #endif + /*BLX 带链接和状态切换的跳转*/ + BLX HalIrqHandler /* 调用硬中断处理程序,无参 */ - BLX HalIrqHandler /* 调用硬中断处理程序 */ - -#ifdef LOSCFG_IRQ_USE_STANDALONE_STACK +#ifdef LOSCFG_IRQ_USE_STANDALONE_STACK @是否使用了独立的IRQ栈 MOV SP, R4 POP {R4} #endif - /* process pending signals */ - BL OsTaskProcSignal + /* process pending signals */ @处理挂起信号 + BL OsTaskProcSignal @跳转至C代码 - /* check if needs to schedule */ - CMP R0, #0 - BLNE OsSchedPreempt + /* check if needs to schedule */@检查是否需要调度 + CMP R0, #0 @是否需要调度,R0为参数保存值 + BLNE OsSchedPreempt @不相等,即R0非0,一般是 1 - MOV R0,SP - MOV R1,R7 - BL OsSaveSignalContextIrq + MOV R0,SP @ OsSaveSignalContextIrq 参数1来源 + MOV R1,R7 @ OsSaveSignalContextIrq 参数2来源 + BL OsSaveSignalContextIrq @跳转至C代码 /* restore fpu regs */ - POP_FPU_REGS R0 + POP_FPU_REGS R0 @恢复fpu寄存器值 - ADD SP, SP, #4 + ADD SP, SP, #4 @sp = sp + 4 OsIrqContextRestore: @中断环境恢复 LDR R0, [SP, #(4 * 7)] @读取 SP+28 位置数据给R0 diff --git a/arch/arm/arm/src/los_exc.c b/arch/arm/arm/src/los_exc.c index fa521ad17d8ce15e7208ca739d23c31c4d842a53..a328219e8a5bcada92936e04f8a53b0188dc407a 100644 --- a/arch/arm/arm/src/los_exc.c +++ b/arch/arm/arm/src/los_exc.c @@ -1108,7 +1108,7 @@ __attribute__((noinline)) VOID LOS_Panic(const CHAR *fmt, ...) va_start(ap, fmt); UartVprintf(fmt, ap); va_end(ap); - __asm__ __volatile__("swi 0"); + __asm__ __volatile__("swi 0");//触发断异常 } /* stack protector */ diff --git a/arch/arm/arm/src/los_hw.c b/arch/arm/arm/src/los_hw.c index db045a2f6d0f1a4e3056085fa7786841801c531f..ecb58a61725f21f03055483e448cbfbe68b952bb 100644 --- a/arch/arm/arm/src/los_hw.c +++ b/arch/arm/arm/src/los_hw.c @@ -56,7 +56,7 @@ UINT64 g_cpuMap[LOSCFG_KERNEL_CORE_NUM] = { LITE_OS_SEC_TEXT_INIT VOID OsTaskExit(VOID) {// swi {cond} __asm__ __volatile__("swi 0");//处理器产生软中断异常,swi指令的低24位存放的是0 -}//该指令可以产生SWI异常,ARM通过该指令可以实现用户模式中对操作系统中特权模式的程序的调用,即系统调用实现的基础; +}//该指令可以产生SWI异常,ARM通过该指令从用户模式切到SVC模式. #ifdef LOSCFG_GDB STATIC VOID OsTaskEntrySetupLoopFrame(UINT32) __attribute__((noinline, naked)); diff --git a/arch/arm/arm/src/los_hw_exc.S b/arch/arm/arm/src/los_hw_exc.S index 1f31d2b6b410761b16054766f0d15296b2390b77..f3c6a44281d55c36a5f49208dda056042d09d772 100644 --- a/arch/arm/arm/src/los_hw_exc.S +++ b/arch/arm/arm/src/los_hw_exc.S @@ -211,7 +211,7 @@ _osExceptSwiHdl: @软中断异常处理 LDMFD SP!, {PC}^ @ Return to user 弹出值给PC寄存器 OsKernelSVCHandler: - ADD R0, SP, #(4 * 16) + ADD R0, SP, #(4 * 16) @R0=sp+64 MOV R5, R0 STMFD R0!, {R4} @ Store PC STMFD R0!, {R4} diff --git a/arch/arm/arm/src/startup/reset_vector_mp.S b/arch/arm/arm/src/startup/reset_vector_mp.S index df26bd3aef78b07e043cd6fbf35447acd51f574a..bc19c72f6f457bfc743a22cdbec9985a2c155f6a 100644 --- a/arch/arm/arm/src/startup/reset_vector_mp.S +++ b/arch/arm/arm/src/startup/reset_vector_mp.S @@ -100,7 +100,7 @@ __exception_handlers: *Assumption: ROM code has these vectors at the hardware reset address. *A simple jump removes any address-space dependencies [i.e. safer] *///一个简单的跳转将删除任何地址空间依赖关系 - b reset_vector @所有的异常中断入口组成了reset vector + b reset_vector @开机代码 b _osExceptUndefInstrHdl @异常处理之CPU碰到不认识的指令 b _osExceptSwiHdl @异常处理之:软中断 b _osExceptPrefetchAbortHdl @异常处理之:取指异常 @@ -136,7 +136,7 @@ reset_vector: adr r4, __exception_handlers /* r4: base of load address */ @r4获得加载基地址 ldr r5, =SYS_MEM_BASE /* r5: base of physical address */@r5获得物理基地址 subs r12, r4, r5 /* r12: delta of load address and physical address */ @r12=r4-r5 加载地址和物理地址的增量 - beq reloc_img_to_bottom_done /* if we load image at the bottom of physical address */ + beq reloc_img_to_bottom_done /* if we load image at the bottom of physical address */@物理地址底部加载镜像 /* we need to relocate image at the bottom of physical address */ ldr r7, =__exception_handlers /* r7: base of linked address (or vm address) */ @@ -229,9 +229,9 @@ warm_reset: @初始化CPU各异常工作模式环境 /* set svc stack, every cpu has OS_EXC_SVC_STACK_SIZE stack *//*设置每一个SVC栈,每个CPU都有独立的 SVC栈*/ ldr r0, =__svc_stack_top @栈底位置,注意这里虽然使用了top,但实际是栈底 mov r2, #OS_EXC_SVC_STACK_SIZE @栈大小 - mul r2, r2, r12 @定位到栈位置,CPU SVC栈是连在一块的 - sub r0, r0, r2 @计算栈顶位置,使用sub也说明了栈底大于栈顶 - mov sp, r0 @栈顶位置 + mul r2, r2, r12 @定位到栈位置,CPU SVC栈是连在一块的 + sub r0, r0, r2 @计算栈顶位置,使用sub也说明了栈底大于栈顶 + mov sp, r0 @栈顶位置 /* enable fpu+neon */ #ifndef LOSCFG_TEE_ENABLE @@ -479,7 +479,7 @@ init_flag: */ .section ".int_stack", "wa", %nobits .align 3 -@申请对应的内存空间 +@六种特权模式申请对应的栈运行空间 __undef_stack: .space OS_EXC_UNDEF_STACK_SIZE * CORE_NUM __undef_stack_top: diff --git a/kernel/base/sched/sched_sq/los_sched.c b/kernel/base/sched/sched_sq/los_sched.c index c9ab36c7fbdcb53bc4b91ddd7e5db34763e211f4..eb9a8f25eb3a61fa7fc2a0d82bb0155d99bd1e7e 100644 --- a/kernel/base/sched/sched_sq/los_sched.c +++ b/kernel/base/sched/sched_sq/los_sched.c @@ -147,7 +147,11 @@ VOID OsSchedResched(VOID) /* do the task context switch */ OsTaskSchedule(newTask, runTask);//切换任务上下文,注意OsTaskSchedule是一个汇编函数 见于 los_dispatch.s } -//抢占式调度,调用极为频繁的函数 +/****************************************************** + 抢占式调度函数 + 1.LOS_Schedule会判断是否发生硬件中断 + 2.硬件中断处理完成后由汇编调用: ..\arch\arm\arm\src\los_dispatch.S +******************************************************/ VOID OsSchedPreempt(VOID) { LosTaskCB *runTask = NULL; diff --git a/zzz/git/push.sh b/zzz/git/push.sh index f7aed6010ceaa4d4361bab8180fb79f4094e2607..a3fd0c9ac5a84327e4e024f35e8cd97d2a33da41 100644 --- a/zzz/git/push.sh +++ b/zzz/git/push.sh @@ -1,5 +1,5 @@ git add -A -git commit -m '开机的第一条汇编指令在哪里? 注解开机汇编代码部分 +git commit -m '硬中断汇编代码注解 百万汉字注解 + 百篇博客分析 => 挖透鸿蒙内核源码 https://weharmony.gitee.io '