Skip to content

Commit 4dd9050

Browse files
committed
feat: Add support for the arm-qemu-stm32 platform, update related dependencies and build configurations.
1 parent 8d2e6f9 commit 4dd9050

12 files changed

Lines changed: 235 additions & 28 deletions

File tree

Cargo.lock

Lines changed: 10 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,8 @@ axipi = { path = "modules/axipi" }
6969

7070
[profile.release]
7171
lto = true
72+
73+
[patch.crates-io]
74+
axplat-arm-qemu-stm32 = { path = "crates/axplat_crates/platforms/axplat-arm-qemu-stm32" }
75+
aarch32-cpu = { path = "crates/aarch32-cpu" }
76+
axcpu = { path = "crates/axcpu" }

Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,11 @@ else ifeq ($(ARCH), riscv64)
109109
else ifeq ($(ARCH), loongarch64)
110110
TARGET := loongarch64-unknown-none-softfloat
111111
else ifeq ($(ARCH), arm)
112-
TARGET := armv7a-none-eabi
112+
ifeq ($(PLAT_NAME), arm-qemu-stm32)
113+
TARGET := thumbv7m-none-eabi
114+
else
115+
TARGET := armv7a-none-eabi
116+
endif
113117
else
114118
$(error "ARCH" must be one of "x86_64", "riscv64", "aarch64", "loongarch64" or "arm")
115119
endif

configs/linker_arm-qemu-stm32.lds

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
OUTPUT_ARCH(arm)
2+
3+
/* STM32F100RB: 128KB Flash at 0x08000000, 8KB SRAM at 0x20000000 */
4+
FLASH_BASE = 0x08000000;
5+
FLASH_SIZE = 0x20000; /* 128KB */
6+
SRAM_BASE = 0x20000000;
7+
SRAM_SIZE = 0x2000; /* 8KB */
8+
9+
ENTRY(_start)
10+
11+
MEMORY
12+
{
13+
FLASH (RX) : ORIGIN = FLASH_BASE, LENGTH = FLASH_SIZE
14+
SRAM (RW) : ORIGIN = SRAM_BASE, LENGTH = SRAM_SIZE
15+
}
16+
17+
SECTIONS
18+
{
19+
. = ORIGIN(FLASH);
20+
_skernel = .;
21+
22+
/* Vector table MUST be first — Cortex-M reads initial SP and reset vector from here */
23+
.vector_table : ALIGN(4) {
24+
KEEP(*(.vector_table))
25+
} > FLASH
26+
27+
.text : ALIGN(4) {
28+
_stext = .;
29+
*(.text.boot)
30+
*(.text .text.*)
31+
. = ALIGN(4);
32+
_etext = .;
33+
} > FLASH
34+
35+
_srodata = .;
36+
.rodata : ALIGN(4) {
37+
*(.rodata .rodata.*)
38+
*(.srodata .srodata.*)
39+
*(.sdata2 .sdata2.*)
40+
} > FLASH
41+
42+
.init_array : ALIGN(4) {
43+
__init_array_start = .;
44+
*(.init_array .init_array.*)
45+
__init_array_end = .;
46+
} > FLASH
47+
48+
.ARM.exidx : {
49+
*(.ARM.exidx .ARM.exidx.*)
50+
} > FLASH
51+
52+
. = ALIGN(4);
53+
_erodata = .;
54+
55+
/* .data goes in SRAM but loaded from Flash (AT> FLASH) */
56+
. = ORIGIN(SRAM);
57+
_sidata = LOADADDR(.data);
58+
.data : AT(_erodata) ALIGN(4) {
59+
_sdata = .;
60+
KEEP(*(.data.boot_page_table))
61+
KEEP(*(.data .data.*))
62+
KEEP(*(.sdata .sdata.*))
63+
KEEP(*(.got .got.*))
64+
KEEP(*(linkme_ANY))
65+
KEEP(*(linkm2_ANY))
66+
KEEP(*(linkme_IRQ))
67+
KEEP(*(linkm2_IRQ))
68+
KEEP(*(linkme_PAGE_FAULT))
69+
KEEP(*(linkm2_PAGE_FAULT))
70+
KEEP(*(linkme_SYSCALL))
71+
KEEP(*(linkm2_SYSCALL))
72+
KEEP(*(axns_resource))
73+
74+
. = ALIGN(64);
75+
_percpu_start = .;
76+
_percpu_load_start = .;
77+
KEEP(*(.percpu .percpu.*))
78+
_percpu_load_end = .;
79+
_percpu_end = .;
80+
} > SRAM
81+
82+
.tdata : ALIGN(4) {
83+
_stdata = .;
84+
*(.tdata .tdata.*)
85+
_etdata = .;
86+
} > SRAM AT> FLASH
87+
88+
.tbss : ALIGN(4) {
89+
_stbss = .;
90+
*(.tbss .tbss.*)
91+
*(.tcommon)
92+
_etbss = .;
93+
} > SRAM
94+
95+
. = ALIGN(4);
96+
_edata = .;
97+
98+
.bss.stack (NOLOAD) : ALIGN(8) {
99+
boot_stack = .;
100+
*(.bss.stack .bss.stack.*)
101+
. = ALIGN(8);
102+
boot_stack_top = .;
103+
} > SRAM
104+
105+
/* BSS in SRAM (before stack, so BSS clearing won't corrupt stack frames) */
106+
.bss : ALIGN(4) {
107+
_sbss = .;
108+
*(.bss .bss.*)
109+
*(.sbss .sbss.*)
110+
*(COMMON)
111+
. = ALIGN(4);
112+
_ebss = .;
113+
} > SRAM
114+
115+
_ekernel = .;
116+
117+
/DISCARD/ : {
118+
*(.comment) *(.gnu*) *(.note*) *(.eh_frame*)
119+
}
120+
}

examples/helloworld-myplat/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ aarch64-phytium-pi = ["dep:axplat-aarch64-phytium-pi"]
1313
riscv64-qemu-virt = ["dep:axplat-riscv64-qemu-virt"]
1414
loongarch64-qemu-virt = ["dep:axplat-loongarch64-qemu-virt"]
1515
arm-qemu-virt = ["dep:axplat-arm-qemu-virt"]
16+
arm-qemu-stm32 = ["dep:axplat-arm-qemu-stm32"]
1617

1718
[dependencies]
1819
cfg-if = "1.0"
@@ -29,9 +30,10 @@ axplat-aarch64-phytium-pi = { version = "0.4", features = ["smp", "irq"], option
2930

3031
[target.'cfg(target_arch = "arm")'.dependencies]
3132
axplat-arm-qemu-virt = { version = "0.4", features = ["smp", "irq"], optional = true }
33+
axplat-arm-qemu-stm32 = { version = "0.1", optional = true }
3234

3335
[target.'cfg(target_arch = "riscv64")'.dependencies]
3436
axplat-riscv64-qemu-virt = { version = "0.4", features = ["smp", "irq"], optional = true }
3537

3638
[target.'cfg(target_arch = "loongarch64")'.dependencies]
37-
axplat-loongarch64-qemu-virt = { version = "0.4", features = ["smp", "irq"], optional = true }
39+
axplat-loongarch64-qemu-virt = { version = "0.4", features = ["smp", "irq"], optional = true }

examples/helloworld-myplat/src/main.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ cfg_if::cfg_if! {
1818
extern crate axplat_loongarch64_qemu_virt;
1919
} else if #[cfg(all(target_arch = "arm", feature = "arm-qemu-virt"))] {
2020
extern crate axplat_arm_qemu_virt;
21+
} else if #[cfg(all(target_arch = "arm", feature = "arm-qemu-stm32"))] {
22+
extern crate axplat_arm_qemu_stm32;
2123
} else {
2224
#[cfg(target_os = "none")] // ignore in rust-analyzer & cargo test
2325
compile_error!("No platform crate linked!\n\nPlease add `extern crate <platform>` in your code.");

modules/axhal/Cargo.toml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,17 @@ repository = "https://github.com/arceos-org/arceos/tree/main/modules/axhal"
1010
documentation = "https://arceos-org.github.io/arceos/axhal/index.html"
1111

1212
[features]
13-
smp = ["axplat-x86-pc?/smp", "axplat-aarch64-qemu-virt?/smp", "axplat-riscv64-qemu-virt?/smp", "axplat-loongarch64-qemu-virt?/smp", "axplat-arm-qemu-virt?/smp", "axplat/smp"]
14-
irq = ["linkme", "axplat-x86-pc?/irq", "axplat-aarch64-qemu-virt?/irq", "axplat-riscv64-qemu-virt?/irq", "axplat-loongarch64-qemu-virt?/irq", "axplat-arm-qemu-virt?/irq", "axplat/irq"]
15-
fp-simd = ["axcpu/fp-simd", "axplat-x86-pc?/fp-simd", "axplat-aarch64-qemu-virt?/fp-simd", "axplat-riscv64-qemu-virt?/fp-simd", "axplat-loongarch64-qemu-virt?/fp-simd", "axplat-arm-qemu-virt?/fp-simd"]
16-
rtc = ["axplat-x86-pc?/rtc", "axplat-aarch64-qemu-virt?/rtc", "axplat-riscv64-qemu-virt?/rtc", "axplat-loongarch64-qemu-virt?/rtc", "axplat-arm-qemu-virt?/rtc"]
13+
smp = ["axplat-x86-pc?/smp", "axplat-aarch64-qemu-virt?/smp", "axplat-riscv64-qemu-virt?/smp", "axplat-loongarch64-qemu-virt?/smp", "axplat-arm-qemu-virt?/smp", "axplat-arm-qemu-stm32?/smp", "axplat/smp"]
14+
irq = ["linkme", "axplat-x86-pc?/irq", "axplat-aarch64-qemu-virt?/irq", "axplat-riscv64-qemu-virt?/irq", "axplat-loongarch64-qemu-virt?/irq", "axplat-arm-qemu-virt?/irq", "axplat-arm-qemu-stm32?/irq", "axplat/irq"]
15+
fp-simd = ["axcpu/fp-simd", "axplat-x86-pc?/fp-simd", "axplat-aarch64-qemu-virt?/fp-simd", "axplat-riscv64-qemu-virt?/fp-simd", "axplat-loongarch64-qemu-virt?/fp-simd", "axplat-arm-qemu-virt?/fp-simd", "axplat-arm-qemu-stm32?/fp-simd"]
16+
rtc = ["axplat-x86-pc?/rtc", "axplat-aarch64-qemu-virt?/rtc", "axplat-riscv64-qemu-virt?/rtc", "axplat-loongarch64-qemu-virt?/rtc", "axplat-arm-qemu-virt?/rtc", "axplat-arm-qemu-stm32?/rtc"]
1717
paging = ["axalloc", "page_table_multiarch"]
1818
tls = ["axcpu/tls"]
1919
uspace = ["paging", "axcpu/uspace"]
2020

2121
# Custom or default platforms
2222
myplat = []
23-
defplat = ["dep:axplat-x86-pc", "dep:axplat-aarch64-qemu-virt", "dep:axplat-riscv64-qemu-virt", "dep:axplat-loongarch64-qemu-virt", "dep:axplat-arm-qemu-virt"]
23+
defplat = ["dep:axplat-x86-pc", "dep:axplat-aarch64-qemu-virt", "dep:axplat-riscv64-qemu-virt", "dep:axplat-loongarch64-qemu-virt", "dep:axplat-arm-qemu-virt", "dep:axplat-arm-qemu-stm32"]
2424

2525
default = []
2626
ipi = ["irq"]
@@ -50,6 +50,7 @@ axplat-aarch64-qemu-virt = { version = "0.4", optional = true }
5050

5151
[target.'cfg(target_arch = "arm")'.dependencies]
5252
axplat-arm-qemu-virt = { version = "0.4", optional = true }
53+
axplat-arm-qemu-stm32 = { version = "0.1", optional = true }
5354

5455
[target.'cfg(target_arch = "riscv64")'.dependencies]
5556
axplat-riscv64-qemu-virt = { version = "0.4", optional = true }

modules/axhal/build.rs

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,31 @@ fn main() {
1111

1212
fn gen_linker_script(arch: &str, platform: &str) -> Result<()> {
1313
let fname = format!("linker_{platform}.lds");
14-
let output_arch = if arch == "x86_64" {
15-
"i386:x86-64"
16-
} else if arch.contains("riscv") {
17-
"riscv" // OUTPUT_ARCH of both riscv32/riscv64 is "riscv"
14+
let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
15+
let workspace_dir = Path::new(&manifest_dir).join("../..");
16+
let platform_ld = workspace_dir
17+
.join("configs")
18+
.join(format!("linker_{platform}.lds"));
19+
println!("cargo:rerun-if-changed=linker.lds.S");
20+
println!("cargo:rerun-if-changed={}", platform_ld.display());
21+
let ld_content = if platform_ld.exists() {
22+
std::fs::read_to_string(platform_ld)?
1823
} else {
19-
arch
24+
let output_arch = if arch == "x86_64" {
25+
"i386:x86-64"
26+
} else if arch.contains("riscv") {
27+
"riscv" // OUTPUT_ARCH of both riscv32/riscv64 is "riscv"
28+
} else {
29+
arch
30+
};
31+
let ld_content = std::fs::read_to_string("linker.lds.S")?;
32+
let ld_content = ld_content.replace("%ARCH%", output_arch);
33+
let ld_content = ld_content.replace(
34+
"%KERNEL_BASE%",
35+
&format!("{:#x}", axconfig::plat::KERNEL_BASE_VADDR),
36+
);
37+
ld_content.replace("%CPU_NUM%", &format!("{}", axconfig::plat::MAX_CPU_NUM))
2038
};
21-
let ld_content = std::fs::read_to_string("linker.lds.S")?;
22-
let ld_content = ld_content.replace("%ARCH%", output_arch);
23-
let ld_content = ld_content.replace(
24-
"%KERNEL_BASE%",
25-
&format!("{:#x}", axconfig::plat::KERNEL_BASE_VADDR),
26-
);
27-
let ld_content = ld_content.replace("%CPU_NUM%", &format!("{}", axconfig::plat::MAX_CPU_NUM));
2839

2940
// target/<target_triple>/<mode>/build/axhal-xxxx/out
3041
let out_dir = std::env::var("OUT_DIR").unwrap();

modules/axhal/src/lib.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,14 @@ use core::sync::atomic::{AtomicUsize, Ordering};
119119
/// This function should be called as early as possible, as other initializations
120120
/// may acess the CPU-local data.
121121
pub fn init_percpu(cpu_id: usize) {
122-
self::percpu::init_primary(cpu_id);
122+
#[cfg(target_feature = "mclass")]
123+
{
124+
let _ = cpu_id;
125+
}
126+
#[cfg(not(target_feature = "mclass"))]
127+
{
128+
self::percpu::init_primary(cpu_id);
129+
}
123130
}
124131

125132
/// Initializes CPU-local data structures for secondary cores.

modules/axhal/src/mem.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ pub use axplat::mem::{
1212
};
1313
pub use memory_addr::{PAGE_SIZE_4K, PhysAddr, PhysAddrRange, VirtAddr, VirtAddrRange, pa, va};
1414

15+
#[cfg(target_feature = "mclass")]
16+
const MAX_REGIONS: usize = 16;
17+
#[cfg(not(target_feature = "mclass"))]
1518
const MAX_REGIONS: usize = 128;
1619

1720
static ALL_MEM_REGIONS: LazyInit<Vec<PhysMemRegion, MAX_REGIONS>> = LazyInit::new();
@@ -29,6 +32,12 @@ pub fn memory_regions() -> impl Iterator<Item = PhysMemRegion> {
2932
///
3033
/// This function is unsafe because it writes `.bss` section directly.
3134
pub unsafe fn clear_bss() {
35+
#[cfg(target_feature = "mclass")]
36+
{
37+
// Cortex-M platforms clear BSS in their reset handler, before Rust
38+
// creates stack frames that may overlap the BSS area in tiny SRAM.
39+
}
40+
#[cfg(not(target_feature = "mclass"))]
3241
unsafe {
3342
core::slice::from_raw_parts_mut(_sbss as usize as *mut u8, _ebss as usize - _sbss as usize)
3443
.fill(0);
@@ -85,8 +94,16 @@ pub fn init() {
8594
}
8695

8796
// Combine kernel image range and reserved ranges
88-
let kernel_start = virt_to_phys(va!(_skernel as usize)).as_usize();
89-
let kernel_size = _ekernel as usize - _skernel as usize;
97+
#[cfg(target_feature = "mclass")]
98+
let (kernel_start, kernel_size) = (
99+
virt_to_phys(va!(_sdata as usize)).as_usize(),
100+
_ekernel as usize - _sdata as usize,
101+
);
102+
#[cfg(not(target_feature = "mclass"))]
103+
let (kernel_start, kernel_size) = (
104+
virt_to_phys(va!(_skernel as usize)).as_usize(),
105+
_ekernel as usize - _skernel as usize,
106+
);
90107
let mut reserved_ranges = reserved_phys_ram_ranges()
91108
.iter()
92109
.cloned()

0 commit comments

Comments
 (0)