Skip to content

Commit 2a63c58

Browse files
am009andre-richter
authored andcommitted
Add README.CN.md for 02_runtime_init.
Fix some translation.
1 parent b585f64 commit 2a63c58

File tree

3 files changed

+203
-4
lines changed

3 files changed

+203
-4
lines changed

00_before_we_start/README.CN.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@
2121
## BSP 代码
2222
`BSP` 表示 Board Support Package。`BSP`代码在`src/bsp.rs`中,而且包含目标主板特殊的定义和功能。这些是诸如主板的内存映射或相应主板上的设备驱动程序实例之类的东西。
2323

24-
就像处理器架构代码一样,`BSP`代码模块架构也是试着镜像`kernel`的子系统模块,但是这次它没有明显的重新导入。这意味着必须从bsp名称空间开始调用提供的所有内容,例如,`bsp::driver::driver_manager()`
24+
就像处理器架构代码一样,`BSP`代码模块架构也是试着镜像`kernel`的子系统模块,但是这次它没有明显的重新导出。这意味着必须从bsp名称空间开始调用提供的所有内容,例如,`bsp::driver::driver_manager()`
2525

2626
## 内核接口
2727

28-
`arch``bsp`都包含根据实际目标和主板不同而编译的代码。例如,`interrupt controller`对于硬件`Raspberry Pi 3``Raspberry Pi 4`是不同的,但是我们想要`kernel`剩下的代码可以轻松的适配它们
28+
`arch``bsp`都包含根据实际目标和主板不同而编译的代码。例如,`interrupt controller`对于硬件`Raspberry Pi 3``Raspberry Pi 4`是不同的,但是我们想让`kernel`剩下的代码可以轻松地适配它们
2929

30-
为了在`arch``bsp``generic kernel code`之间提供一个清晰的抽象,`interface`特征在*在可能的情况下**在可能的地方*被提供。它们在各自的子系统模块中定义,并有助于将程序的惯用法强制执行到接口,而不是实现上。例如,有一个通用IRQ处理接口,由两个树莓派不同的中断控制器驱动将实现的,并且仅将接口导出到`kernel`剩下的代码中。
30+
为了在`arch``bsp``generic kernel code`之间提供一个清晰的抽象,`interface`特征在*在可能的情况下**在可能的地方*被提供。它们在各自的子系统模块中定义,并有助于将程序的调用方法体现到接口,而不是具体实现上。例如,有一个通用IRQ处理接口,由两个树莓派不同的中断控制器驱动将实现的,并且仅将接口导出到`kernel`剩下的代码中。
3131

3232
```
3333
+-------------------+

02_runtime_init/README.CN.md

+199
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
# 教程 02 - 执行初始化
2+
3+
## tl;dr
4+
5+
我们拓展了`cpu.S`,在第一次启动的时候调用Rust代码。在Rust的代码中先清零了[bss] section,然后通过调用`panic()`挂起CPU。再次运行`make qemu`看看新增加的代码是怎么运行的。
6+
7+
## 值得注意的变化
8+
9+
- 链接脚本(linker script)中有了更多的section。
10+
- `.rodata`, `.data`
11+
- `.bss`
12+
- `_start()`:
13+
- 当核心不是`core0`第0号核心的时候,挂起该CPU核心。
14+
- `core0`会调用Rust的函数`runtime_init()`
15+
- `runtime_init.rs`内的`runtime_init()`
16+
- 清零了`.bss` section.
17+
- 它调用了`kernel_init()`, 这个函数又调用了`panic!()`, panic函数最终把`core0`和其他核心一样挂起了。
18+
19+
[bss]: https://en.wikipedia.org/wiki/.bss
20+
21+
## 相比之前的变化(diff)
22+
```diff
23+
24+
diff -uNr 01_wait_forever/src/_arch/aarch64/cpu.S 02_runtime_init/src/_arch/aarch64/cpu.S
25+
--- 01_wait_forever/src/_arch/aarch64/cpu.S
26+
+++ 02_runtime_init/src/_arch/aarch64/cpu.S
27+
@@ -7,5 +7,15 @@
28+
.global _start
29+
30+
_start:
31+
-1: wfe // Wait for event
32+
- b 1b // In case an event happened, jump back to 1
33+
+ mrs x1, mpidr_el1 // Read Multiprocessor Affinity Register
34+
+ and x1, x1, #3 // Clear all bits except [1:0], which hold core id
35+
+ cbz x1, 2f // Jump to label 2 if we are core 0
36+
+1: wfe // Wait for event
37+
+ b 1b // In case an event happened, jump back to 1
38+
+2: // If we are here, we are core0
39+
+ ldr x1, =_start // Load address of function "_start()"
40+
+ mov sp, x1 // Set start of stack to before our code, aka first
41+
+ // address before "_start()"
42+
+ bl runtime_init // Jump to the "runtime_init()" kernel function
43+
+ b 1b // We should never reach here. But just in case,
44+
+ // park this core aswell
45+
46+
diff -uNr 01_wait_forever/src/bsp/raspberrypi/link.ld 02_runtime_init/src/bsp/raspberrypi/link.ld
47+
--- 01_wait_forever/src/bsp/raspberrypi/link.ld
48+
+++ 02_runtime_init/src/bsp/raspberrypi/link.ld
49+
@@ -13,5 +13,24 @@
50+
*(.text._start) *(.text*)
51+
}
52+
53+
+ .rodata :
54+
+ {
55+
+ *(.rodata*)
56+
+ }
57+
+
58+
+ .data :
59+
+ {
60+
+ *(.data*)
61+
+ }
62+
+
63+
+ /* Section is zeroed in u64 chunks, align start and end to 8 bytes */
64+
+ .bss ALIGN(8):
65+
+ {
66+
+ __bss_start = .;
67+
+ *(.bss*);
68+
+ . = ALIGN(8);
69+
+ __bss_end = .;
70+
+ }
71+
+
72+
/DISCARD/ : { *(.comment*) }
73+
}
74+
75+
diff -uNr 01_wait_forever/src/main.rs 02_runtime_init/src/main.rs
76+
--- 01_wait_forever/src/main.rs
77+
+++ 02_runtime_init/src/main.rs
78+
@@ -97,10 +97,20 @@
79+
#![no_main]
80+
#![no_std]
81+
82+
-// `mod cpu` provides the `_start()` function, the first function to run.
83+
+// `mod cpu` provides the `_start()` function, the first function to run. `_start()` then calls
84+
+// `runtime_init()`, which jumps to `kernel_init()`.
85+
86+
mod bsp;
87+
mod cpu;
88+
+mod memory;
89+
mod panic_wait;
90+
+mod runtime_init;
91+
92+
-// Kernel code coming next tutorial.
93+
+/// Early init code.
94+
+///
95+
+/// # Safety
96+
+///
97+
+/// - Only a single core must be active and running this function.
98+
+unsafe fn kernel_init() -> ! {
99+
+ panic!()
100+
+}
101+
102+
diff -uNr 01_wait_forever/src/memory.rs 02_runtime_init/src/memory.rs
103+
--- 01_wait_forever/src/memory.rs
104+
+++ 02_runtime_init/src/memory.rs
105+
@@ -0,0 +1,29 @@
106+
+// SPDX-License-Identifier: MIT OR Apache-2.0
107+
+//
108+
+// Copyright (c) 2018-2020 Andre Richter <andre.o.richter@gmail.com>
109+
+
110+
+//! Memory Management.
111+
+
112+
+use core::ops::Range;
113+
+
114+
+//--------------------------------------------------------------------------------------------------
115+
+// Public Code
116+
+//--------------------------------------------------------------------------------------------------
117+
+
118+
+/// Zero out a memory region.
119+
+///
120+
+/// # Safety
121+
+///
122+
+/// - `range.start` and `range.end` must be valid.
123+
+/// - `range.start` and `range.end` must be `T` aligned.
124+
+pub unsafe fn zero_volatile<T>(range: Range<*mut T>)
125+
+where
126+
+ T: From<u8>,
127+
+{
128+
+ let mut ptr = range.start;
129+
+
130+
+ while ptr < range.end {
131+
+ core::ptr::write_volatile(ptr, T::from(0));
132+
+ ptr = ptr.offset(1);
133+
+ }
134+
+}
135+
136+
diff -uNr 01_wait_forever/src/runtime_init.rs 02_runtime_init/src/runtime_init.rs
137+
--- 01_wait_forever/src/runtime_init.rs
138+
+++ 02_runtime_init/src/runtime_init.rs
139+
@@ -0,0 +1,58 @@
140+
+// SPDX-License-Identifier: MIT OR Apache-2.0
141+
+//
142+
+// Copyright (c) 2018-2020 Andre Richter <andre.o.richter@gmail.com>
143+
+
144+
+//! Rust runtime initialization code.
145+
+
146+
+use crate::memory;
147+
+use core::ops::Range;
148+
+
149+
+//--------------------------------------------------------------------------------------------------
150+
+// Private Code
151+
+//--------------------------------------------------------------------------------------------------
152+
+
153+
+/// Return the range spanning the .bss section.
154+
+///
155+
+/// # Safety
156+
+///
157+
+/// - The symbol-provided addresses must be valid.
158+
+/// - The symbol-provided addresses must be usize aligned.
159+
+unsafe fn bss_range() -> Range<*mut usize> {
160+
+ extern "C" {
161+
+ // Boundaries of the .bss section, provided by linker script symbols.
162+
+ static mut __bss_start: usize;
163+
+ static mut __bss_end: usize;
164+
+ }
165+
+
166+
+ Range {
167+
+ start: &mut __bss_start,
168+
+ end: &mut __bss_end,
169+
+ }
170+
+}
171+
+
172+
+/// Zero out the .bss section.
173+
+///
174+
+/// # Safety
175+
+///
176+
+/// - Must only be called pre `kernel_init()`.
177+
+#[inline(always)]
178+
+unsafe fn zero_bss() {
179+
+ memory::zero_volatile(bss_range());
180+
+}
181+
+
182+
+//--------------------------------------------------------------------------------------------------
183+
+// Public Code
184+
+//--------------------------------------------------------------------------------------------------
185+
+
186+
+/// Equivalent to `crt0` or `c0` code in C/C++ world. Clears the `bss` section, then jumps to kernel
187+
+/// init code.
188+
+///
189+
+/// # Safety
190+
+///
191+
+/// - Only a single core must be active and running this function.
192+
+#[no_mangle]
193+
+pub unsafe extern "C" fn runtime_init() -> ! {
194+
+ zero_bss();
195+
+
196+
+ crate::kernel_init()
197+
+}
198+
199+
```

README.CN.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ _带上我最诚挚的问候,<br>Andre ([@andre-richter])_
2525
- 每篇教程都包含一个独立可引导的二进制内核文件。
2626
- 每篇新的教程都在之前的基础上扩展。
2727
- 每篇教程的指南里面都有一个简短的章节来总结新增的代码和功能,也会展示源代码的区别,方便检查和同步。
28-
- 部分教程中有除了`tl;dr`章节外还有非常详细、具体的介绍。长期计划是所有的教程都会有详细的文字说明。但是现在我认为教程独特的地方是`tl;dr``diff`还不够详细
28+
- 部分教程中有除了`tl;dr`章节外还有非常详细、具体的介绍。长期计划是所有的教程都会有详细的文字说明。但是目前只有那些我认为教程的`tl;dr``diff`还不够详细的章节会详细说明
2929
- 教程中所用的代码可以在**树莓派 3 和 4**上运行。
3030
- 教程的第一到五章是基础内容,只能运行在`QEMU`上。
3131
- 到了[第六章]时(06_drivers_gpio_uart),你可以在树莓派上加载和运行内核并通过`UART`来观察输出结果。

0 commit comments

Comments
 (0)