Skip to main content

somehal_macros/
lib.rs

1use proc_macro::TokenStream;
2
3mod _entry;
4mod trap;
5
6/// Attribute to declare the entry point of the program
7///
8/// **IMPORTANT**: This attribute must appear exactly *once* in the dependency graph. Also, if you
9/// are using Rust 1.30 the attribute must be used on a reachable item (i.e. there must be no
10/// private modules between the item and the root of the crate); if the item is in the root of the
11/// crate you'll be fine. This reachability restriction doesn't apply to Rust 1.31 and newer releases.
12///
13/// The specified function will be called by the reset handler *after* RAM has been initialized.
14/// If present, the FPU will also be enabled before the function is called.
15///
16/// The type of the specified function must be `[unsafe] fn() -> !` (never ending function)
17///
18/// # 属性参数
19///
20/// 此宏**必需**接受一个内核类型参数:
21///
22/// - **参数**: 指定实现 `somehal::KernelOp` trait 的类型标识符
23/// - **行为**: 自动在函数开头插入 `somehal::init(&<type>)` 调用
24///
25/// # Properties
26///
27/// The entry point will be called by the reset handler. The program can't reference to the entry
28/// point, much less invoke it.
29///
30/// # Examples
31///
32/// - Entry point with kernel initialization
33///
34/// ``` no_run
35/// # #![no_main]
36/// # use pie_boot::entry;
37/// # struct Kernel;
38/// # impl somehal::KernelOp for Kernel {
39/// #     fn ioremap(&self, paddr: usize, size: usize) -> somehal::PagingResult<*mut u8> {
40/// #         Ok(std::ptr::null_mut())
41/// #     }
42/// # }
43/// #[entry(Kernel)]
44/// fn main() -> ! {
45///     // somehal::init(&Kernel) 已自动生成
46///     loop {
47///         /* .. */
48///     }
49/// }
50/// ```
51#[proc_macro_attribute]
52pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream {
53    _entry::entry(args, input, "__someboot_main")
54}
55
56/// Attribute to declare the secondary entry point of the program
57///
58/// # Examples
59///
60/// - Simple entry point
61///
62/// ``` no_run
63/// # #![no_main]
64/// # use pie_boot::secondary_entry;
65/// #[entry]
66/// fn secondary(cpu_id: usize) -> ! {
67///     loop {
68///         /* .. */
69///     }
70/// }
71/// ```
72#[proc_macro_attribute]
73pub fn someboot_secondary_entry(args: TokenStream, input: TokenStream) -> TokenStream {
74    _entry::entry_secondary(args, input, true)
75}
76
77/// Attribute to declare the secondary entry point of the program
78///
79/// # Examples
80///
81/// - Simple entry point
82///
83/// ``` no_run
84/// # #![no_main]
85/// # use pie_boot::secondary_entry;
86/// #[entry]
87/// fn secondary(cpu_id: usize) -> ! {
88///     loop {
89///         /* .. */
90///     }
91/// }
92/// ```
93#[proc_macro_attribute]
94pub fn somehal_secondary_entry(args: TokenStream, input: TokenStream) -> TokenStream {
95    _entry::entry_secondary(args, input, false)
96}
97
98/// 中断处理器属性宏
99///
100/// 将用户函数转换为标准中断处理器,自动生成正确的函数签名。
101///
102/// # 要求
103///
104/// 函数必须:
105/// - 不能是 `const`、`async` 或有泛型参数
106/// - 必须有且仅有一个参数,类型为 `someboot::irq::IrqId`
107/// - 无返回类型
108/// - 不应有显式的可见性声明(宏自动设为 `pub`)
109///
110/// # 示例
111///
112/// ```
113/// # #![no_std]
114/// # use somehal_macros::irq_handler;
115/// # use someboot::irq::IrqId;
116/// #[irq_handler]
117/// fn my_irq_handler(irq: IrqId) {
118///     // 处理中断
119///     sparreal_kernel::os::irq::handle_irq(irq);
120/// }
121/// ```
122///
123/// # 生成代码
124///
125/// 宏展开为:
126///
127/// ```ignore
128/// #[unsafe(no_mangle)]
129/// pub extern "Rust" fn _someboot_handle_irq(irq: someboot::irq::IrqId) {
130///     // 你的代码
131/// }
132/// ```
133///
134/// # 平台集成
135///
136/// 该函数由 HAL 的 trap 处理代码自动调用:
137///
138/// - AArch64: `crates/somehal/src/arch/aarch64/trap.rs`
139/// - LoongArch64: `crates/somehal/src/arch/loongarch64/trap.rs`
140///
141/// 中断号随后通过 `sparreal_kernel::os::irq::handle_irq()` 分发到注册的处理函数。
142///
143/// # 注意
144///
145/// - 每个平台只能有一个全局中断入口(符号名固定为 `_someboot_handle_irq`)
146/// - 参数名会被保留(如 `irq`、`hwirq` 等),不会被强制修改
147#[proc_macro_attribute]
148pub fn irq_handler(args: TokenStream, input: TokenStream) -> TokenStream {
149    trap::irq_handler(args, input)
150}