CPU有哪几种工作模式?每种模式都有独立堆栈,如何用汇编初始化这些栈?

    搜索 @note_pic 可查看绘制的全部字符图
    搜索 @note_why 是尚未看明白的地方,有看明白的,请Pull Request完善
    搜索 @note_thinking 是一些的思考和建议
    搜索 @note_#if0 是由第三方项目提供不在内核源码中定义的极为重要结构体,为方便理解而添加的。
    搜索 @note_good 是给源码点赞的地方
上级 11f61d6a
......@@ -42,28 +42,28 @@
.global OsIrqHandler /*硬中断处理*/
.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
.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 /* 汇编带参数的宏定义*/
.macro STACK_ALIGN, reg /* 栈对齐*/
MOV \reg, sp
TST SP, #4
SUBEQ SP, #4
PUSH { \reg }
.endm
.macro STACK_RESTORE, reg /*汇编带参数的宏定义*/
POP { \reg } @
.macro STACK_RESTORE, reg /*栈恢复*/
POP { \reg }
MOV sp, \reg
.endm
/* FPU(floating-point processor unit)浮点运算单元*/
/* macros to save and restore fpu regs */
.macro PUSH_FPU_REGS reg1 /* 汇编宏定义,类似于 #define PUSH_FPU_REGS(reg1) ... */
#if !defined(LOSCFG_ARCH_FPU_DISABLE)
.macro PUSH_FPU_REGS reg1 /* 保存fpu寄存器 */
#if !defined(LOSCFG_ARCH_FPU_DISABLE) @FPU使能
VMRS \reg1, FPEXC
PUSH {\reg1}
VMRS \reg1, FPSCR
......@@ -75,7 +75,7 @@
#endif
.endm
.macro POP_FPU_REGS reg1
.macro POP_FPU_REGS reg1 /* 恢复fpu寄存器 */
#if !defined(LOSCFG_ARCH_FPU_DISABLE)
VPOP {D0-D15}
#if defined(LOSCFG_ARCH_FPU_VFP_D32)
......@@ -94,12 +94,12 @@ OsStartToRun:
MSR CPSR_c, #(CPSR_INT_DISABLE | CPSR_SVC_MODE) @禁止中断并切到管理模式
LDRH R1, [R0, #4] @将存储器地址为R0+4 的低16位数据读入寄存器R1,并将R1 的高16 位清零
ORR R1, #OS_TASK_STATUS_RUNNING
STRH R1, [R0, #4]
ORR R1, #OS_TASK_STATUS_RUNNING @或指令 R1=R1|OS_TASK_STATUS_RUNNING
STRH R1, [R0, #4] @将寄存器R1中的低16位写入以R0+4地址的存储器中
/* R0 is new task, save it on tpidrprw */
MCR p15, 0, R0, c13, c0, 4
ISB
MCR p15, 0, R0, c13, c0, 4 @ C5=C4=R0
ISB @指令同步屏障,清除流水线并且确保在新指令执行时,之前的指令都已经执行完毕。
VPUSH {S0} /* fpu */
VPOP {S0}
......@@ -149,15 +149,15 @@ OsTaskContextLoad:
MOV R4, R0 @R4=R0 说明R4也记录了CPSR内容,这个内容将用于 OsKernelTaskLoad中保存到SPSR
AND R0, R0, #CPSR_MASK_MODE @R0 =R0&CPSR_MASK_MODE ,目的是清除高16
CMP R0, #CPSR_USER_MODE @比较R0是否为用户模式
BNE OsKernelTaskLoad @不相等则跳转到OsKernelTaskLoad执行
BNE OsKernelTaskLoad @不相等则跳转到OsKernelTaskLoad执行,return回去了
#ifdef LOSCFG_KERNEL_SMP
#ifdef LOSCFG_KERNEL_SMP_LOCKDEP
/* 8 bytes stack align */
SUB SP, SP, #4
LDR R0, =g_taskSpin
BL OsLockDepCheckOut
ADD SP, SP, #4
SUB SP, SP, #4 @sp = sp -4
LDR R0, =g_taskSpin @R0 = g_taskSpin
BL OsLockDepCheckOut @带链接的跳转指令。指令将下一条指令的地址拷贝到R14(LR)链接寄存器中,然后跳转到指定地址运行程序
ADD SP, SP, #4 @sp=sp+4
#endif
/* R0 = &g_taskSpin.rawLock */
LDR R0, =g_taskSpin
......
......@@ -285,14 +285,14 @@ STATIC VOID OsExcType(UINT32 excType, ExcContext *excBufAddr, UINT32 far, UINT32
}
STATIC const CHAR *g_excTypeString[] = {//异常类型的字符说明,在鸿蒙内核中什么才算是异常? 看这里
"reset", //重置命令
"undefined instruction", //未定义的指令
"software interrupt", //软中断,比如定时器
"prefetch abort", //取指异常
"data abort", //数据异常
"fiq", //快中断异常
"address abort", //地址异常
"irq" //中断异常
"reset", //复位异常源 - SVC模式(Supervisor保护模式)
"undefined instruction", //未定义指令异常源- und模式
"software interrupt", //软中断异常源 - SVC模式
"prefetch abort", //取指异常源 - abort模式
"data abort", //数据异常源 - abort模式
"fiq", //快中断异常源 - FIQ模式
"address abort", //地址异常源 - abort模式
"irq" //中断异常源 - IRQ模式
};
//打印系统信息
STATIC VOID OsExcSysInfo(UINT32 excType, const ExcContext *excBufAddr)
......@@ -705,7 +705,7 @@ VOID BackTrace(UINT32 regFP)//fp:R11寄存器
BackTraceSub(regFP);
}
//异常处理模块的初始化
//异常接管模块的初始化
VOID OsExcInit(VOID)
{
OsExcStackInfoReg(g_excStack, sizeof(g_excStack) / sizeof(g_excStack[0]));//异常模式下注册内核栈信息
......
......@@ -36,6 +36,10 @@
#include "los_mmu_descriptor_v6.h"
#undef ASSEMBLY
/******************************************************************************
CPU下异常向量表
******************************************************************************/
.global __exc_stack_top
.global __irq_stack_top
......@@ -68,16 +72,16 @@
.fpu vfpv4
.arm
/* 设置异常模式栈的SP 参数1为栈底, 参数2为栈大小 r11 存放的是 cpu id */
/* param0 is stack bottom, param1 is stack size, r11 hold cpu id */
.macro EXC_SP_SET param0, param1
ldr r1, =\param0
mov r0, \param1
bl sp_set
ldr r1, =\param0 @r1 = 栈底
mov r0, \param1 @r0 = 栈大小
bl sp_set @跳到设置SP
.endm
/* param0 is stack top, param1 is stack size, param2 is magic num */
.macro STACK_MAGIC_SET param0, param1, param2
.macro STACK_MAGIC_SET param0, param1, param2 @设置栈魔法数字
ldr r0, =\param0
mov r1, \param1
ldr r2, =\param2
......@@ -332,12 +336,12 @@ cpu_start: /* 启动CPU */
/*
* set sp for current cpu
* r1 is stack bottom, r0 is stack size, r11 hold cpu id
*/
*/@设置当前CPUSP, r1为栈底, r0为栈大小 r11 cpu id
sp_set:
mul r3, r0, r11
sub r2, r1, r3
mov sp, r2
bx lr /* set sp */
mul r3, r0, r11 @r3=r0*r11 先计算偏移量
sub r2, r1, r3 @r2=r1-r3 如此得到r2cpuSP位置,从这里可以看出 栈底地址是要高于栈顶的
mov sp, r2 @sp = r2 设置栈指针位置,SP默认指向了栈底
bx lr /* set sp */ @跳回去继续执行
/*
* r4: page table base address
......
......@@ -37,8 +37,8 @@
#include "shell.h"
#endif
const StackInfo *g_stackInfo = NULL;
UINT32 g_stackNum;
const StackInfo *g_stackInfo = NULL; //CPU所有工作模式的栈信息
UINT32 g_stackNum; //CPU所有工作模式的栈数量
//获取栈的吃水线
UINT32 OsStackWaterLineGet(const UINTPTR *stackBottom, const UINTPTR *stackTop, UINT32 *peakUsed)
{
......@@ -130,7 +130,7 @@ VOID OsExcStackInfo(VOID)
//注册栈信息
VOID OsExcStackInfoReg(const StackInfo *stackInfo, UINT32 stackNum)
{
g_stackInfo = stackInfo; //g_excStack
g_stackInfo = stackInfo; //全局变量指向g_excStack
g_stackNum = stackNum;
}
//task栈的初始化,设置固定的值. 0xcccccccc 和 0xcacacaca
......
git add -A
git commit -m '注解汇编代码,原来它们竟如此可爱,爱了爱了.
git commit -m 'CPU有哪几种工作模式?每种模式都有独立堆栈,如何用汇编初始化这些栈?
搜索 @note_pic 可查看绘制的全部字符图
搜索 @note_why 是尚未看明白的地方,有看明白的,请Pull Request完善
搜索 @note_thinking 是一些的思考和建议
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册