Skip to content

Commit eb9754b

Browse files
committed
refactor(rt): split bootloading assemble code into arch modules
Add `riscv_fpu` module. Signed-off-by: Zhouqi Jiang <[email protected]>
1 parent 04ccf25 commit eb9754b

File tree

11 files changed

+184
-123
lines changed

11 files changed

+184
-123
lines changed

.github/workflows/Cargo.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
runs-on: ubuntu-latest
2626
strategy:
2727
matrix:
28-
TARGET: [riscv64imac-unknown-none-elf]
28+
TARGET: [riscv64imac-unknown-none-elf, riscv64gc-unknown-none-elf]
2929
TOOLCHAIN: [nightly]
3030
steps:
3131
- uses: actions/checkout@v4

allwinner-rt/.cargo/config.toml

Lines changed: 0 additions & 2 deletions
This file was deleted.

allwinner-rt/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ embedded-hal = "1.0.0"
2323
embedded-time = "0.12.1"
2424
nb = "1.1.0"
2525
plic = "0.0.2"
26+
cfg-if = "1.0.4"
27+
28+
[build-dependencies]
29+
riscv-target-parser = "0.1.3"
2630

2731
[features]
2832
default = ["nezha"]

allwinner-rt/build.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,33 @@
1+
use riscv_target_parser::RiscvTarget;
12
use std::{env, path::PathBuf};
23

34
fn main() {
5+
load_linker_script();
6+
load_fpu_features();
7+
}
8+
9+
fn load_fpu_features() {
10+
// Adapted from `riscv-rt` crate.
11+
// List of all possible RISC-V configurations to check for in allwinner-rt
12+
const RISCV_CFG: [&str; 3] = ["riscvf", "riscvd", "riscvq"];
13+
// Required until target_feature risc-v is stable and in-use (rust 1.75)
14+
for ext in RISCV_CFG.iter() {
15+
println!("cargo:rustc-check-cfg=cfg({ext})");
16+
}
17+
let target = env::var("TARGET").unwrap();
18+
let cargo_flags = env::var("CARGO_ENCODED_RUSTFLAGS").unwrap();
19+
20+
if let Ok(target) = RiscvTarget::build(&target, &cargo_flags) {
21+
for flag in target.rustc_flags() {
22+
// Required until target_feature risc-v is stable and in-use
23+
if RISCV_CFG.contains(&flag.as_str()) {
24+
println!("cargo:rustc-cfg={}", flag.as_str());
25+
}
26+
}
27+
}
28+
}
29+
30+
fn load_linker_script() {
431
let out = PathBuf::from(env::var_os("OUT_DIR").unwrap());
532
let ld = &out.join("allwinner-rt.ld");
633

@@ -23,7 +50,7 @@ SECTIONS {
2350
KEEP(*(.head.meta))
2451
} > SRAM
2552
.text : ALIGN(4) {
26-
KEEP(*(.text.entry))
53+
*(.text.entry)
2754
*(.text .text.*)
2855
} > SRAM
2956
.rodata : ALIGN(8) {

allwinner-rt/examples/fn-main.rs

Lines changed: 0 additions & 30 deletions
This file was deleted.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/// Jump over head data to executable code.
2+
///
3+
/// TODO Andes start code.
4+
#[cfg(feature = "v821")]
5+
#[unsafe(naked)]
6+
#[unsafe(link_section = ".text.entry")]
7+
pub unsafe extern "C" fn start() -> ! {
8+
const STACK_SIZE: usize = 8 * 1024;
9+
#[unsafe(link_section = ".bss.uninit")]
10+
static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE];
11+
core::arch::naked_asm!(
12+
// Disable interrupt
13+
"csrw mie, zero",
14+
// Prepare programming language stack
15+
"la sp, {stack}
16+
li t0, {stack_size}
17+
add sp, sp, t0",
18+
// Clear `.bss` section
19+
"la t1, sbss
20+
la t2, ebss
21+
3: bgeu t1, t2, 3f
22+
sd zero, 0(t1)
23+
addi t1, t1, 8
24+
j 3b
25+
3: ",
26+
// TODO Enable floating point unit
27+
// Start Rust main function
28+
"call {main}",
29+
// Platform halt if main function returns
30+
"3: wfi
31+
j 3b",
32+
stack = sym STACK,
33+
stack_size = const STACK_SIZE,
34+
main = sym crate::main,
35+
)
36+
}

allwinner-rt/src/arch/riscv_fpu.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#[cfg(riscvf)]
2+
pub unsafe extern "C" fn init_floating_point() {
3+
unsafe {
4+
core::arch::asm! {
5+
"li t0, 0x4000
6+
li t1, 0x2000
7+
csrrc x0, mstatus, t0
8+
csrrs x0, mstatus, t1
9+
fscsr x0",
10+
}
11+
}
12+
}
13+
14+
#[cfg(not(riscvf))]
15+
pub unsafe extern "C" fn init_floating_point() {}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/// Jump over head data to executable code.
2+
///
3+
/// # Safety
4+
///
5+
/// Naked function.
6+
///
7+
/// NOTE: `mxstatus` is a custom T-Head register. Do not confuse with `mstatus`.
8+
/// It allows for configuring special eXtensions. See further below for details.
9+
#[cfg(any(all(feature = "d1", target_arch = "riscv64"), doc))]
10+
#[unsafe(naked)]
11+
#[unsafe(link_section = ".text.entry")]
12+
pub unsafe extern "C" fn start() -> ! {
13+
use super::riscv_fpu::init_floating_point;
14+
use crate::main;
15+
const STACK_SIZE: usize = 8 * 1024;
16+
#[unsafe(link_section = ".bss.uninit")]
17+
static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE];
18+
core::arch::naked_asm!(
19+
// Disable interrupt
20+
"csrw mie, zero",
21+
// Enable T-Head ISA extension
22+
"li t1, 1 << 22",
23+
"csrs 0x7C0, t1",
24+
// Enable T-Head caches
25+
"li t0, 0x70013
26+
csrw 0x7C2, t0
27+
li t0, 0x11ff
28+
csrw 0x7C1, t0
29+
li t0, 0x638000
30+
csrs 0x7C0, t0
31+
li t0, 0x16e30c
32+
csrw 0x7C5, t0",
33+
// Invalidate instruction and data cache, branch history table
34+
// and branch target buffer table
35+
"li t1, 0x30013",
36+
"csrs 0x7C2, t1",
37+
// Prepare programming language stack
38+
"la sp, {stack}
39+
li t0, {stack_size}
40+
add sp, sp, t0",
41+
// Clear `.bss` section
42+
"la t1, sbss
43+
la t2, ebss
44+
3: bgeu t1, t2, 3f
45+
sd zero, 0(t1)
46+
addi t1, t1, 8
47+
j 3b
48+
3: ",
49+
// Enable floating point unit
50+
"call {init_floating_point}",
51+
// Start Rust main function
52+
"call {main}",
53+
// Platform halt if main function returns
54+
"3: wfi
55+
j 3b",
56+
stack = sym STACK,
57+
stack_size = const STACK_SIZE,
58+
init_floating_point = sym init_floating_point,
59+
main = sym main,
60+
)
61+
}

allwinner-rt/src/boot0.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use crate::start;
2+
13
/// eGON.BT0 identifying structure.
24
// TODO verify with original ROM source code
35
#[repr(C)]
@@ -27,3 +29,10 @@ static EGON_HEAD: EgonHead = EgonHead {
2729
boot_cpu: 0,
2830
platform: *b"\0\03.0.0\0",
2931
};
32+
33+
core::arch::global_asm! {
34+
".section .text.head",
35+
"head_jump:",
36+
"j {}",
37+
sym start,
38+
}

allwinner-rt/src/lib.rs

Lines changed: 29 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -28,104 +28,45 @@ pub use mctl::init as dram_init;
2828

2929
pub use allwinner_rt_macros::entry;
3030

31+
pub mod arch {
32+
pub mod andes_a27l2;
33+
pub mod riscv_fpu;
34+
pub mod thead_c906;
35+
}
36+
3137
pub mod soc {
3238
pub mod d1;
3339
pub mod v821;
3440
pub mod v853;
3541
}
3642

37-
/// Jump over head data to executable code.
38-
///
39-
/// # Safety
40-
///
41-
/// Naked function.
42-
///
43-
/// NOTE: `mxstatus` is a custom T-Head register. Do not confuse with `mstatus`.
44-
/// It allows for configuring special eXtensions. See further below for details.
45-
#[unsafe(naked)]
46-
#[unsafe(link_section = ".text.entry")]
47-
unsafe extern "C" fn start() -> ! {
48-
const STACK_SIZE: usize = 8 * 1024;
49-
#[unsafe(link_section = ".bss.uninit")]
50-
static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE];
51-
core::arch::naked_asm!(
52-
// Disable interrupt
53-
"csrw mie, zero",
54-
// Enable T-Head ISA extension
55-
"li t1, 1 << 22",
56-
"csrs 0x7C0, t1",
57-
// Enable T-Head caches
58-
"li t0, 0x70013
59-
csrw 0x7C2, t0
60-
li t0, 0x11ff
61-
csrw 0x7C1, t0
62-
li t0, 0x638000
63-
csrs 0x7C0, t0
64-
li t0, 0x16e30c
65-
csrw 0x7C5, t0",
66-
// Invalidate instruction and data cache, branch history table
67-
// and branch target buffer table
68-
"li t1, 0x30013",
69-
"csrs 0x7C2, t1",
70-
// Prepare programming language stack
71-
"la sp, {stack}
72-
li t0, {stack_size}
73-
add sp, sp, t0",
74-
// Clear `.bss` section
75-
"la t1, sbss
76-
la t2, ebss
77-
3: bgeu t1, t2, 3f
78-
sd zero, 0(t1)
79-
addi t1, t1, 8
80-
j 3b
81-
3: ",
82-
// Enable floating point unit
83-
"li t0, 0x4000",
84-
"li t1, 0x2000",
85-
"csrrc x0, mstatus, t0",
86-
"csrrs x0, mstatus, t1",
87-
"fscsr x0",
88-
// Start Rust main function
89-
"call {main}",
90-
// Platform halt if main function returns
91-
"3: wfi
92-
j 3b",
93-
stack = sym STACK,
94-
stack_size = const STACK_SIZE,
95-
main = sym main,
96-
)
97-
}
98-
43+
#[allow(unused)]
9944
#[rustfmt::skip]
10045
unsafe extern "Rust" {
10146
// This symbol is generated by `#[entry]` macro in allwinner-rt or other ROM-stage software packages.
10247
fn main();
10348
}
10449

105-
core::arch::global_asm! {
106-
".section .text.head",
107-
"head_jump:",
108-
"j {}",
109-
sym start,
110-
}
111-
112-
#[cfg(feature = "d1")]
113-
pub use {
114-
self::soc::d1::{__rom_init_params, Peripherals},
115-
allwinner_hal::ccu::Clocks,
116-
};
117-
#[cfg(feature = "v821")]
118-
pub use {
119-
self::soc::v821::{__rom_init_params, Peripherals},
120-
allwinner_hal::ccu::Clocks,
121-
};
122-
123-
#[cfg(not(any(feature = "d1", feature = "v821")))]
124-
pub struct Peripherals {}
125-
#[cfg(not(any(feature = "d1", feature = "v821")))]
126-
pub struct Clocks {}
127-
#[cfg(not(any(feature = "d1", feature = "v821")))]
128-
#[doc(hidden)]
129-
pub fn __rom_init_params() -> (Peripherals, Clocks) {
130-
(Peripherals {}, Clocks {})
50+
cfg_if::cfg_if! {
51+
if #[cfg(all(feature = "d1", target_arch = "riscv64"))] {
52+
pub use {
53+
self::arch::thead_c906::start,
54+
self::soc::d1::{__rom_init_params, Peripherals},
55+
allwinner_hal::ccu::Clocks,
56+
};
57+
} else if #[cfg(feature = "v821")] {
58+
pub use {
59+
self::arch::andes_a27l2::start,
60+
self::soc::v821::{__rom_init_params, Peripherals},
61+
allwinner_hal::ccu::Clocks,
62+
};
63+
} else {
64+
pub struct Peripherals {}
65+
pub struct Clocks {}
66+
#[doc(hidden)]
67+
pub fn __rom_init_params() -> (Peripherals, Clocks) {
68+
(Peripherals {}, Clocks {})
69+
}
70+
pub fn start() {}
71+
}
13172
}

0 commit comments

Comments
 (0)