Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
鸿蒙内核源码分析
注释鸿蒙内核源码
提交
4b9e2476
注释鸿蒙内核源码
项目概览
鸿蒙内核源码分析
/
注释鸿蒙内核源码
通知
270
Star
29
Fork
11
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
106
Wiki
分析
仓库
DevOps
项目成员
Pages
注释鸿蒙内核源码
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
106
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
4b9e2476
编写于
3月 18, 2021
作者:
鸿蒙内核源码分析
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
鸿蒙内核源码分析(中断切换篇) | 自下而上逐行分析保存和恢复中断现场全过程 | 百篇博客分析鸿蒙源码 | v42.01
百万汉字注解 + 百篇博客分析 => 挖透鸿蒙内核源码
https://weharmony.gitee.io
上级
95734ecf
变更
6
展开全部
隐藏空白更改
内联
并排
Showing
6 changed file
with
1042 addition
and
1037 deletion
+1042
-1037
arch/arm/arm/src/los_dispatch.S
arch/arm/arm/src/los_dispatch.S
+34
-29
arch/arm/arm/src/startup/reset_vector_mp.S
arch/arm/arm/src/startup/reset_vector_mp.S
+2
-2
kernel/base/include/los_task_pri.h
kernel/base/include/los_task_pri.h
+1
-1
kernel/base/ipc/los_signal.c
kernel/base/ipc/los_signal.c
+1
-1
syscall/process_syscall.c
syscall/process_syscall.c
+1003
-1003
zzz/git/push.sh
zzz/git/push.sh
+1
-1
未找到文件。
arch/arm/arm/src/los_dispatch.S
浏览文件 @
4b9e2476
...
...
@@ -259,46 +259,49 @@ OsKernelTaskLoad: @内核任务的加载
LDMFD
SP
!,
{
LR
,
PC
}^
@
返回地址赋给
pc
指针
,
直接跳出
.
OsIrqHandler
:
@硬中断处理,此时已切换到硬中断栈
SUB
LR
,
LR
,
#
4
SUB
LR
,
LR
,
#
4
@
记录译码指令地址
,
以防切换过程丢失指令
.
/
*
push
r0
-
r3
to
irq
stack
*/
STMFD
SP
,
{
R0
-
R3
}
@
r0
-
r3
寄存器入
irq
栈
SUB
R0
,
SP
,
#(
4
*
4
)
@
r0
=
sp
-
16
SUB
R0
,
SP
,
#(
4
*
4
)
@
r0
=
sp
-
16
,
目的是记录
{
R0
-
R3
}
4
个寄存器保存的开始位置
,
届时从
R3
开始出栈
MRS
R1
,
SPSR
@
获取程序状态控制寄存器
MOV
R2
,
LR
@
r2
=
lr
/
*
disable
irq
,
switch
to
svc
mode
*/
@
超级用户模式
(
SVC
模式
)
,主要用于
SWI
(
软件中断
)
和
OS
(
操作系统
)
。
CPSID
i
,
#
0x13
@
切换到
SVC
模式
,
此处一切换
,
后续指令将
入
SVC
的栈
CPSID
i
,
#
0x13
@
切换到
SVC
模式
,
此处一切换
,
后续指令将
在
SVC
栈运行
@
CPSID
i
为关中断指令
,
对应的是
CPSIE
@
TaskIrqContext
开始保存中断现场
......
/
*
push
spsr
and
pc
in
svc
stack
*/
STMFD
SP
!,
{
R1
,
R2
}
@
实际是将
SPSR
,
和
LR
入栈
,
入栈顺序为
R1
,
R2
,
SP
自增
STMFD
SP
,
{
LR
}
@
LR
再入栈
,
SP
不自增
STMFD
SP
!,
{
R1
,
R2
}
@
实际是将
SPSR
,
和
PC
入栈对应
TaskIrqContext
.
PC
,
TaskIrqContext
.
CPSR
,
STMFD
SP
,
{
LR
}
@
LR
再入栈
,
SP
不自增
,
如果是用户模式
,
LR
值将被
282
行:
STMFD
SP
,
{
R13
,
R14
}^
覆盖
@如果非用户模式,将被
286
行:
SUB
SP
,
SP
,
#(
2
*
4
)
跳过
.
AND
R3
,
R1
,
#
CPSR_MASK_MODE
@
获取
CPU
的运行模式
CMP
R3
,
#
CPSR_USER_MODE
@
中断是否发生在用户模式
BNE
OsIrqFromKernel
@
中断不发生在用户模式下则跳转到
OsIrqFromKernel
BNE
OsIrqFromKernel
@
非用户模式不用将
USP
,
ULR
保存在
TaskIrqContext
/
*
push
user
sp
,
lr
in
svc
stack
*/
STMFD
SP
,
{
R13
,
R14
}^
@
sp
和
LR
入
svc
栈
STMFD
SP
,
{
R13
,
R14
}^
@
将用户模式的
sp
和
LR
入
svc
栈
OsIrqFromKernel
:
@从内核发起中断
/
*
from
svc
not
need
save
sp
and
lr
*/
@
svc
模式下发生的中断不需要保存
sp
和
lr
寄存器值
SUB
SP
,
SP
,
#(
2
*
4
)
@
申请
8
个栈空间
SUB
SP
,
SP
,
#(
2
*
4
)
@
目的是为了留白给
TaskIrqContext
.
USP
,
TaskIrqContext
.
ULR
@
TaskIrqContext
.
ULR
已经在
276
行保存了
,
276
行用的是
SP
而不是
SP
!,
所以此处要跳
2
个空间
/
*
pop
r0
-
r3
from
irq
stack
*/
LDMFD
R0
,
{
R0
-
R3
}
@
从
R0
位置依次出栈
LDMFD
R0
,
{
R0
-
R3
}
@
从
R0
位置依次出栈
/
*
push
caller
saved
regs
as
trashed
regs
in
svc
stack
*/
STMFD
SP
!,
{
R0
-
R3
,
R12
}
@
R0
~
R3
入栈
,
R12
入栈
STMFD
SP
!,
{
R0
-
R3
,
R12
}
@
寄存器入栈
,
对应
TaskIrqContext
.
R0
~
R3
,
R12
/
*
8
bytes
stack
align
*/
SUB
SP
,
SP
,
#
4
@
栈对齐
SUB
SP
,
SP
,
#
4
@
栈对齐
对应
TaskIrqContext
.
resved
/*
*
save
fpu
regs
in
case
in
case
those
been
*
altered
in
interrupt
handlers
.
*/
PUSH_FPU_REGS
R0
@
保存
fpu
regs
,以防中断处理程序中的
fpu
regs
被修改。
@
TaskIrqContext
结束保存中断现场
......
@开始执行真正的中断处理函数了.
#ifdef LOSCFG_IRQ_USE_STANDALONE_STACK @是否使用了独立的IRQ栈
PUSH
{
R4
}
@
R4
先入栈保存
,
接下来要切换栈
,
需保存现场
MOV
R4
,
SP
@
R4
=
SP
...
...
@@ -319,8 +322,8 @@ OsIrqFromKernel: @从内核发起中断
CMP
R0
,
#
0
@
是否需要调度
,
R0
为参数保存值
BLNE
OsSchedPreempt
@
不相等
,
即
R0
非
0
,
一般是
1
MOV
R0
,
SP
@
OsSaveSignalContextIrq
参数
1
来源
MOV
R1
,
R7
@
OsSaveSignalContextIrq
参数
2
来源
MOV
R0
,
SP
@
参数
MOV
R1
,
R7
@
参数
BL
OsSaveSignalContextIrq
@
跳转至
C
代码
/
*
restore
fpu
regs
*/
...
...
@@ -329,29 +332,31 @@ OsIrqFromKernel: @从内核发起中断
ADD
SP
,
SP
,
#
4
@
sp
=
sp
+
4
OsIrqContextRestore
:
@恢复硬中断环境
LDR
R0
,
[
SP
,
#(
4
*
7
)]
@
读取
SP
+
28
位置数据给
R0
MSR
SPSR_cxsf
,
R0
@
恢复
spsr
LDR
R0
,
[
SP
,
#(
4
*
7
)]
@
R0
=
sp
+
7
,
目的是跳到恢复中断现场
TaskIrqContext
.
CPSR
位置
,
刚好是
TaskIrqContext
倒数第
7
的位置
.
MSR
SPSR_cxsf
,
R0
@
恢复
spsr
即:
spsr
=
TaskIrqContext
.
CPSR
AND
R0
,
R0
,
#
CPSR_MASK_MODE
@
掩码找出当前工作模式
CMP
R0
,
#
CPSR_USER_MODE
@
是否为用户模式
?
LDMFD
SP
!,
{
R0
-
R3
,
R12
}
@
从
SP
位置依次出栈
BNE
OsIrqContextRestoreToKernel
@
CPU
工作在非用户模式
@
TaskIrqContext
开始恢复中断现场
......
LDMFD
SP
!,
{
R0
-
R3
,
R12
}
@
从
SP
位置依次出栈
对应
TaskIrqContext
.
R0
~
R3
,
R12
@此时已经恢复了5个寄存器,接来下是
TaskIrqContext
.
USP
,
TaskIrqContext
.
ULR
BNE
OsIrqContextRestoreToKernel
@
看非用户模式
,
怎么恢复中断现场
.
/
*
load
user
sp
and
lr
,
and
jump
cpsr
*/
LDMFD
SP
,
{
R13
,
R14
}^
ADD
SP
,
SP
,
#(
3
*
4
)
LDMFD
SP
,
{
R13
,
R14
}^
@
出栈
,
恢复用户模式
sp
和
lr
值
即:
TaskIrqContext
.
USP
,
TaskIrqContext
.
ULR
ADD
SP
,
SP
,
#(
3
*
4
)
@
跳
3
个位置
,
跳过
CPSR
,
因为上一句不是
SP
!,
所以跳
3
个位置
,
刚好到了保存
TaskIrqContext
.
PC
的位置
/
*
return
to
user
mode
*/
LDMFD
SP
!,
{PC}
^
@
回到用户模式
LDMFD
SP
!,
{PC}
^
@
回到用户模式
,
整个中断过程完成
@
TaskIrqContext
结束恢复中断现场
(
用户模式下
)
......
OsIrqContextRestoreToKernel
:
OsIrqContextRestoreToKernel
:
@从内核恢复中断
/
*
svc
mode
not
load
sp
*/
ADD
SP
,
SP
,
#
4
LDMFD
SP
!,
{
LR
}
ADD
SP
,
SP
,
#
4
@
其实是跳过
TaskIrqContext
.
USP
,
因为在内核模式下并没有保存这个值
,
翻看
287
行
LDMFD
SP
!,
{
LR
}
@
弹出
LR
/
*
jump
cpsr
and
return
to
svc
mode
*/
ADD
SP
,
SP
,
#
4
LDMFD
SP
!,
{PC}
^
ADD
SP
,
SP
,
#
4
@
跳过
cpsr
LDMFD
SP
!,
{PC}
^
@
回到
svc
模式
,
整个中断过程完成
@
TaskIrqContext
结束恢复中断现场
(
内核模式下
)
......
FUNCTION
(
ArchSpinLock
)
@非要拿到锁
mov
r1
,
#
1
@
r1
=
1
...
...
arch/arm/arm/src/startup/reset_vector_mp.S
浏览文件 @
4b9e2476
...
...
@@ -348,7 +348,7 @@ cpu_start: /* CPU 启动 */
bl
mmu_setup
/*
安装
MMU
*/
bl
secondary_cpu_start
/*
启动次级
CPU
*/
b
.
//
注意
b
.
就会跳转到当前地址
,
相当死循环
b
.
//
注意
b
.
就会跳转到当前地址
,
相当
于
死循环
secondary_cpu_init
:
/
*
次级
CPU
初始化
*/
#ifdef LOSCFG_TEE_ENABLE
...
...
@@ -495,7 +495,7 @@ __abt_stack:
__abt_stack_top
:
__irq_stack
:
.
space
OS_EXC_IRQ_STACK_SIZE
*
CORE_NUM
.
space
OS_EXC_IRQ_STACK_SIZE
*
CORE_NUM
//
64
__irq_stack_top
:
__fiq_stack
:
...
...
kernel/base/include/los_task_pri.h
浏览文件 @
4b9e2476
...
...
@@ -334,7 +334,7 @@ typedef struct {
SchedStat
schedStat
;
/**< Schedule statistics */
//调度统计
#endif
#endif
UINTPTR
userArea
;
//
使用
区域,由运行时划定,根据运行态不同而不同
UINTPTR
userArea
;
//
用户
区域,由运行时划定,根据运行态不同而不同
UINTPTR
userMapBase
;
//用户模式下的栈底位置
UINT32
userMapSize
;
/**< user thread stack size ,real size : userMapSize + USER_STACK_MIN_SIZE */
UINT32
processID
;
/**< Which belong process */
//所属进程ID
...
...
kernel/base/ipc/los_signal.c
浏览文件 @
4b9e2476
...
...
@@ -632,7 +632,7 @@ void OsSaveSignalContextIrq(unsigned int *sp, unsigned int r7)
sig_cb
*
sigcb
=
NULL
;
unsigned
long
cpsr
;
UINT32
intSave
;
TaskIrqContext
*
context
=
(
TaskIrqContext
*
)(
sp
);
//汇编设置
好SP位置
TaskIrqContext
*
context
=
(
TaskIrqContext
*
)(
sp
);
//汇编设置
SP,从SP位置取出TaskIrqContext
OS_RETURN_IF_VOID
(
sp
==
NULL
);
cpsr
=
context
->
CPSR
;
...
...
syscall/process_syscall.c
浏览文件 @
4b9e2476
此差异已折叠。
点击以展开。
zzz/git/push.sh
浏览文件 @
4b9e2476
git add
-A
git commit
-m
'
注解汇编代码如何保存任务上下文
git commit
-m
'
鸿蒙内核源码分析(中断切换篇) | 自下而上逐行分析保存和恢复中断现场全过程 | 百篇博客分析鸿蒙源码 | v42.01
百万汉字注解 + 百篇博客分析 => 挖透鸿蒙内核源码
https://weharmony.gitee.io
'
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录