Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
鸿蒙内核源码分析
注释鸿蒙内核源码
提交
1bd145f7
注释鸿蒙内核源码
项目概览
鸿蒙内核源码分析
/
注释鸿蒙内核源码
通知
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 搜索 >>
提交
1bd145f7
编写于
3月 09, 2021
作者:
鸿蒙内核源码分析
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
注解用户空间,内核空间的汇编拷贝代码
百万汉字注解 + 百篇博客分析 => 挖透鸿蒙内核源码
https://weharmony.gitee.io
上级
5d3039f7
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
91 addition
and
69 deletion
+91
-69
arch/arm/arm/src/hw_user_get.S
arch/arm/arm/src/hw_user_get.S
+42
-25
arch/arm/arm/src/los_dispatch.S
arch/arm/arm/src/los_dispatch.S
+22
-18
arch/arm/arm/src/startup/reset_vector_mp.S
arch/arm/arm/src/startup/reset_vector_mp.S
+17
-17
platform/main.c
platform/main.c
+9
-8
zzz/git/push.sh
zzz/git/push.sh
+1
-1
未找到文件。
arch/arm/arm/src/hw_user_get.S
浏览文件 @
1bd145f7
...
...
@@ -30,42 +30,59 @@
*/
#include "asm.h"
/*********************************************
BEQ
相等
BNE
不等
BPL
非负
BMI
负
BCC
无进位
BCS
有进位
BLO
小于(无符号数)
BHS
大于等于(无符号数)
BHI
大于(无符号数)
BLS
小于等于(无符号数)
BVC
无溢出(有符号数)
BVS
有溢出(有符号数)
BGT
大于(有符号数)
BGE
大于等于(有符号数)
BLT
小于(有符号数)
BLE
小于等于(有符号数)
*********************************************/
.
syntax
unified
.
arm
//
errno_t
_arm_get_user
(
void
*
dst
,
const
void
*
src
,
size_t
dstTypeLen
,
size_t
srcTypeLen
)
FUNCTION
(
_arm_get_user
)
stmdb
sp
!,
{
r0
,
r1
,
r2
,
r3
,
lr
}
cmp
r2
,
#
0
beq
.
Lget_user_return
cmp
r2
,
r3
bne
.
Lget_user_err
cmp
r2
,
#
1
bhi
.
Lget_user_half
.
Lget_user_byte
:
0
:
ldrbt
r3
,
[
r1
],
#
0
1
:
strb
r3
,
[
r0
],
#
0
b
.
Lget_user_return
stmdb
sp
!,
{
r0
,
r1
,
r2
,
r3
,
lr
}
@
四个参数入栈
,
保存
LR
cmp
r2
,
#
0
@
r2
和
0
比较
beq
.
Lget_user_return
@
相等
跳到
Lget_user_return
直接返回
cmp
r2
,
r3
@
r2
和
r3
比较
bne
.
Lget_user_err
@
不等
,
说明函数要返回错误
cmp
r2
,
#
1
@
r2
和
1
比较
bhi
.
Lget_user_half
@
if
(
dstTypeLen
>
1
)
跳转到
Lget_user_half
.
Lget_user_byte
:
@按字节拷贝数据
0
:
ldrbt
r3
,
[
r1
],
#
0
@
r3
=*
r1
1
:
strb
r3
,
[
r0
],
#
0
@
*
r0
=
r3
b
.
Lget_user_return
.
Lget_user_half
:
cmp
r2
,
#
2
bhi
.
Lget_user_word
2
:
ldrht
r3
,
[
r1
],
#
0
3
:
strh
r3
,
[
r0
],
#
0
cmp
r2
,
#
2
@
r2
和
2
比较
bhi
.
Lget_user_word
@
if
(
dstTypeLen
>
2
)
Lget_user_word
2
:
ldrht
r3
,
[
r1
],
#
0
@
完成最后一个字节的拷贝
3
:
strh
r3
,
[
r0
],
#
0
@
完成最后一个字节的拷贝
b
.
Lget_user_return
.
Lget_user_word
:
cmp
r2
,
#
4
bhi
.
Lget_user_err
cmp
r2
,
#
4
@
r2
和
4
比较
bhi
.
Lget_user_err
@
if
(
dstTypeLen
>
4
)
跳转到
Lget_user_err
4
:
ldrt
r3
,
[
r1
],
#
0
5
:
str
r3
,
[
r0
],
#
0
.
Lget_user_return
:
ldmia
sp
!,
{
r0
,
r1
,
r2
,
r3
,
lr
}
mov
r0
,
0
bx
lr
.
Lget_user_return
:
@返回锚点
ldmia
sp
!,
{
r0
,
r1
,
r2
,
r3
,
lr
}
@
保存的内容出栈
,
恢复各寄存器值
mov
r0
,
0
@
r0
保存返回值为
0
bx
lr
@
跳回调用函数继续执行
,
_arm_get_user
到此结束
!
.
Lget_user_err
:
ldmia
sp
!,
{
r0
,
r1
,
r2
,
r3
,
lr
}
mov
r0
,
#-
14
bx
lr
ldmia
sp
!,
{
r0
,
r1
,
r2
,
r3
,
lr
}
@
保存的内容出栈
,
恢复各寄存器值
mov
r0
,
#-
14
@
r0
保存返回值为
-
14
bx
lr
@
跳回调用函数继续执行
,
_arm_get_user
到此结束
!
.
pushsection
__exc_table
,
"a"
.
long
0
b
,
.
Lget_user_err
...
...
arch/arm/arm/src/los_dispatch.S
浏览文件 @
1bd145f7
...
...
@@ -97,6 +97,10 @@ ARM的指令系统中关于栈指令的内容比较容易引起迷惑,这是
|
变量
2
|
|---------------|
|---------------|
低地址
LDMFD
SP
!,
{PC}
^
LDM
/
STR
架构中{∧}为可选后缀,当指令为
LDM
且寄存器列表中包含
R15
(
PC
),
选用该后缀时表示:除了正常的数据传送之外,还将
SPSR
复制到
CPSR
(将备份的程序状态寄存器
SPCR
恢复到当前程序状态寄存器
CPSR
)。
******************************************************************************/
#ifdef LOSCFG_KERNEL_SMP_LOCKDEP
.
extern
OsLockDepCheckOut
/*
使用外部定义的函数
*/
...
...
@@ -196,7 +200,7 @@ OsTaskSchedule: /*新老任务切换上下文*/
PUSH_FPU_REGS
R2
/*
保存
fpu
寄存器
*/
/
*
store
sp
on
running
task
*/
STR
SP
,
[
R1
]
@
存储任务到栈
STR
SP
,
[
R1
]
@
在运行的任务栈中保存
SP
OsTaskContextLoad
:
/
*
clear
the
flag
of
ldrex
*/
@
LDREX
可从内存加载数据
,
如果物理地址有共享
TLB
属性,则
LDREX
会将该物理地址标记为由当前处理器独占访问,并且会清除该处理器对其他任何物理地址的任何独占访问标记。
...
...
@@ -237,9 +241,9 @@ OsTaskContextLoad:
STR
R2
,
[
R3
,
#
OS_PERCPU_TASK_LOCK_OFFSET
]
#
endif
MVN
R3
,
#
CPSR_INT_DISABLE
MVN
R3
,
#
CPSR_INT_DISABLE
@
按位取反
R3
=
0x3F
AND
R4
,
R4
,
R3
MSR
SPSR_cxsf
,
R4
MSR
SPSR_cxsf
,
R4
@
修改
spsr
值
/
*
restore
r0
-
r12
,
lr
*/
LDMFD
SP
!,
{
R0
-
R12
}
...
...
@@ -282,30 +286,30 @@ OsIrqFromKernel: @从内核发起中断
SUB
SP
,
SP
,
#(
2
*
4
)
@
申请
8
个栈空间
/
*
pop
r0
-
r3
from
irq
stack
*/
LDMFD
R0
,
{
R0
-
R3
}
@
出栈
LDMFD
R0
,
{
R0
-
R3
}
@
从
R0
位置依次
出栈
/
*
push
caller
saved
regs
as
trashed
regs
in
svc
stack
*/
STMFD
SP
!,
{
R0
-
R3
,
R12
}
STMFD
SP
!,
{
R0
-
R3
,
R12
}
@
R0
~
R3
入栈
,
R12
入栈
/
*
8
bytes
stack
align
*/
SUB
SP
,
SP
,
#
4
SUB
SP
,
SP
,
#
4
@
栈对齐
/*
*
save
fpu
regs
in
case
in
case
those
been
*
altered
in
interrupt
handlers
.
*/
PUSH_FPU_REGS
R0
#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
PUSH_FPU_REGS
R0
@
保存
fpu
regs
,以防中断处理程序中的
fpu
regs
被修改。
#ifdef LOSCFG_IRQ_USE_STANDALONE_STACK @
是否使用了独立的IRQ
栈
PUSH
{
R4
}
@
R4
先入栈保存
,
接下来要切换栈
,
需保存现场
MOV
R4
,
SP
@
R4
=
SP
EXC_SP_SET
__svc_stack_top
,
OS_EXC_SVC_STACK_SIZE
,
R1
,
R2
@
切换到
svc
栈
#
endif
/*
BLX
带链接和状态切换的跳转
*/
BLX
HalIrqHandler
/*
调用硬中断处理程序
,
无参
*/
BLX
HalIrqHandler
/*
调用硬中断处理程序
,
无参
,
说明
HalIrqHandler
在
svc
栈中执行
*/
#ifdef LOSCFG_IRQ_USE_STANDALONE_STACK @是否使用了独立的IRQ栈
MOV
SP
,
R4
POP
{
R4
}
MOV
SP
,
R4
@
恢复现场
,
sp
=
R4
POP
{
R4
}
@
弹出
R4
#
endif
/
*
process
pending
signals
*/
@
处理挂起信号
...
...
@@ -327,10 +331,10 @@ OsIrqFromKernel: @从内核发起中断
OsIrqContextRestore
:
@恢复硬中断环境
LDR
R0
,
[
SP
,
#(
4
*
7
)]
@
读取
SP
+
28
位置数据给
R0
MSR
SPSR_cxsf
,
R0
@
恢复
spsr
AND
R0
,
R0
,
#
CPSR_MASK_MODE
CMP
R0
,
#
CPSR_USER_MODE
@
AND
R0
,
R0
,
#
CPSR_MASK_MODE
@
掩码找出当前工作模式
CMP
R0
,
#
CPSR_USER_MODE
@
是否为用户模式
?
LDMFD
SP
!,
{
R0
-
R3
,
R12
}
@
LDMFD
SP
!,
{
R0
-
R3
,
R12
}
@
从
SP
位置依次出栈
BNE
OsIrqContextRestoreToKernel
@
CPU
工作在非用户模式
...
...
@@ -339,7 +343,7 @@ OsIrqContextRestore: @恢复硬中断环境
ADD
SP
,
SP
,
#(
3
*
4
)
/
*
return
to
user
mode
*/
LDMFD
SP
!,
{PC}
^
LDMFD
SP
!,
{PC}
^
@
回到用户模式
OsIrqContextRestoreToKernel
:
/
*
svc
mode
not
load
sp
*/
...
...
arch/arm/arm/src/startup/reset_vector_mp.S
浏览文件 @
1bd145f7
...
...
@@ -200,31 +200,31 @@ reloc_img_to_bottom_done:
warm_reset
:
@初始化
CPU
各异常工作模式环境
/
*
initialize
interrupt
/
exception
environments
*/
mov
r0
,
#(
CPSR_IRQ_DISABLE
|CPSR_FIQ_DISABLE|CPSR_IRQ_MODE
)
msr
cpsr
,
r0
@
先切到
IRQ
模式
msr
cpsr
,
r0
@
设置为普通中断模式和栈
EXC_SP_SET
__irq_stack_top
,
#
OS_EXC_IRQ_STACK_SIZE
mov
r0
,
#(
CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_UNDEF_MODE
)
msr
cpsr
,
r0
msr
cpsr
,
r0
@
设置为未定义模式和栈
EXC_SP_SET
__undef_stack_top
,
#
OS_EXC_UNDEF_STACK_SIZE
mov
r0
,
#(
CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_ABT_MODE
)
msr
cpsr
,
r0
msr
cpsr
,
r0
@
设置为终止模式和栈
EXC_SP_SET
__abt_stack_top
,
#
OS_EXC_ABT_STACK_SIZE
mov
r0
,
#(
CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_FIQ_MODE
)
msr
cpsr
,
r0
msr
cpsr
,
r0
@
设置为快中断模式和栈
EXC_SP_SET
__fiq_stack_top
,
#
OS_EXC_FIQ_STACK_SIZE
/
*
initialize
CPSR
(
machine
state
register
)
*/
mov
r0
,
#(
CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_SVC_MODE
)
msr
cpsr
,
r0
msr
cpsr
,
r0
@
设置为管理模式和栈
/
*
Note
:
some
functions
in
LIBGCC1
will
cause
a
"restore from SPSR"
!!
*/
msr
spsr
,
r0
msr
spsr
,
r0
@
同步设置
spsr
/
*
get
cpuid
and
keep
it
in
r12
*/
mrc
p15
,
0
,
r12
,
c0
,
c0
,
5
@
从
C0
获取
CPUID
给
R12
and
r12
,
r12
,
#
MPIDR_CPUID_MASK
@
掩码操作
mrc
p15
,
0
,
r12
,
c0
,
c0
,
5
@
R12
保存
CPUID
and
r12
,
r12
,
#
MPIDR_CPUID_MASK
@
掩码操作
获取当前
cpu
id
/
*
set
svc
stack
,
every
cpu
has
OS_EXC_SVC_STACK_SIZE
stack
*//*
设置每一个
SVC
栈
,
每个
CPU
都有独立的
SVC
栈
*/
ldr
r0
,
=
__svc_stack_top
@
栈底位置
,
注意这里虽然使用了
top
,
但实际是栈底
...
...
@@ -340,7 +340,7 @@ cpu_start: /* 启动次级CPU */
ldr
r4
,
[
r4
]
add
r4
,
r4
,
r11
/*
r4
=
tt_trampoline
paddr
*/
bl
mmu_setup
bl
mmu_setup
/*
安装
MMU
*/
bl
secondary_cpu_start
/*
启动次级
CPU
*/
b
.
...
...
@@ -357,19 +357,19 @@ secondary_cpu_init: /* 次级CPU初始化 */
mcr
p15
,
0
,
r1
,
c1
,
c1
,
0
cps
#
0x13
#
endif
bl
warm_reset
bl
warm_reset
@
重置次级
CPU
/*
*
set
sp
for
current
cpu
*
r1
is
stack
bottom
,
r0
is
stack
size
,
r12
hold
cpu
id
*/
sp_set
:
mrc
p15
,
0
,
r12
,
c0
,
c0
,
5
and
r12
,
r12
,
#
MPIDR_CPUID_MASK
mul
r3
,
r0
,
r12
sub
r2
,
r1
,
r3
mov
sp
,
r2
bx
lr
/*
set
sp
*/
sp_set
:
/
*
设置当前
cpu
栈顶指针
,
r1
是栈底
,
r0
是栈大小
,
r12
是
cpuid
*/
mrc
p15
,
0
,
r12
,
c0
,
c0
,
5
@
从协处理器取出
cpuid
and
r12
,
r12
,
#
MPIDR_CPUID_MASK
@
掩码获取当前运行
cpu
id
mul
r3
,
r0
,
r12
@
r3
=
r0
*
r12
计算出偏移量
sub
r2
,
r1
,
r3
@
r2
=
r1
-
r3
算出
cpuid
对应的栈顶位置
mov
sp
,
r2
@
将栈顶指针
sp
移到栈顶位置
.
bx
lr
/*
set
sp
*/
@
跳回到
LR
执行
/*
*
r4
:
page
table
base
address
...
...
platform/main.c
浏览文件 @
1bd145f7
...
...
@@ -71,11 +71,12 @@ LITE_OS_SEC_TEXT_INIT VOID OsSystemInfo(VOID)
HalIrqVersion
(),
__DATE__
,
__TIME__
,
\
KERNEL_NAME
,
KERNEL_MAJOR
,
KERNEL_MINOR
,
KERNEL_PATCH
,
KERNEL_ITRE
,
buildType
);
}
//次级CPU初始化,本函数执行的次数由次级CPU的个数决定. 例如:在四核情况下,会被执行3次, 0号通常被定义为主CPU 执行main
//次级CPU初始化,本函数执行的次数由次级CPU的个数决定.
//例如:在四核情况下,会被执行3次, 0号通常被定义为主CPU 执行main
LITE_OS_SEC_TEXT_INIT
VOID
secondary_cpu_start
(
VOID
)
{
#if (LOSCFG_KERNEL_SMP == YES)
UINT32
cpuid
=
ArchCurrCpuid
();
#if (LOSCFG_KERNEL_SMP == YES)
//支持多cpu核开关
UINT32
cpuid
=
ArchCurrCpuid
();
//获取当前cpu id
OsArchMmuInitPerCPU
();
//每个CPU都需要初始化MMU
...
...
@@ -91,10 +92,10 @@ LITE_OS_SEC_TEXT_INIT VOID secondary_cpu_start(VOID)
OsCurrProcessSet
(
OS_PCB_FROM_PID
(
OsGetKernelInitProcessID
()));
//设置内核进程为CPU进程
OsSwtmrInit
();
//定时任务初始化,每个CPU维护自己的定时器队列
OsIdleTaskCreate
();
//创建空闲任务,每个CPU维护自己的任务队列
OsStart
();
//
本CPU
正式启动在内核层的工作
OsStart
();
//正式启动在内核层的工作
while
(
1
)
{
__asm
volatile
(
"wfi"
);
//wait for Interrupt 等待中断,即下一次中断发生前都在此
hold住
不干活
}
//类似的还有 WFE: wait for Events 等待事件,即下一次事件发生前都在此
hold住
不干活
__asm
volatile
(
"wfi"
);
//wait for Interrupt 等待中断,即下一次中断发生前都在此
呆着
不干活
}
//类似的还有 WFE: wait for Events 等待事件,即下一次事件发生前都在此
呆着
不干活
#endif
}
...
...
@@ -150,7 +151,7 @@ LITE_OS_SEC_TEXT_INIT VOID release_secondary_cores(VOID)//调动次级CPU干活
内核入口函数,由汇编调用,见于reset_vector_up.S 和 reset_vector_mp.S
up指单核CPU, mp指多核CPU
******************************************************************************/
LITE_OS_SEC_TEXT_INIT
INT32
main
(
VOID
)
//由主CPU执行,默认
0号
为主CPU
LITE_OS_SEC_TEXT_INIT
INT32
main
(
VOID
)
//由主CPU执行,默认
0号CPU
为主CPU
{
UINT32
uwRet
=
LOS_OK
;
...
...
@@ -167,7 +168,7 @@ LITE_OS_SEC_TEXT_INIT INT32 main(VOID)//由主CPU执行,默认 0号为主CPU
/* system and chip info */
OsSystemInfo
();
//输出系统和芯片的信息
PRINT_RELEASE
(
"
\n
main core booting up...
\n
"
);
//主内核启动中...
PRINT_RELEASE
(
"
\n
main core booting up...
\n
"
);
//
控制台输出
主内核启动中...
uwRet
=
OsMain
();
// 内核各模块初始化
if
(
uwRet
!=
LOS_OK
)
{
...
...
zzz/git/push.sh
浏览文件 @
1bd145f7
git add
-A
git commit
-m
'注解
异常分发汇编
代码
git commit
-m
'注解
用户空间,内核空间的汇编拷贝
代码
百万汉字注解 + 百篇博客分析 => 挖透鸿蒙内核源码
https://weharmony.gitee.io
'
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录