1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
| // Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
#![no_main]
#![no_std]
mod exceptions;
mod logger;
mod pl031;
use crate::pl031::Rtc;
use arm_gic::{IntId, Trigger, irq_enable, wfi};
use chrono::{TimeZone, Utc};
use core::hint::spin_loop;
use aarch64_paging::descriptor::El1Attributes;
use aarch64_rt::{InitialPagetable, entry, initial_pagetable};
use arm_gic::gicv3::registers::{Gicd, GicrSgi};
use arm_gic::gicv3::{GicCpuInterface, GicV3};
use arm_pl011_uart::{PL011Registers, Uart};
use core::panic::PanicInfo;
use core::ptr::NonNull;
use log::{LevelFilter, error, info, trace};
use safe_mmio::UniqueMmioPointer;
use smccc::Hvc;
use smccc::psci::system_off;
/// GICv3 的基地址。
const GICD_BASE_ADDRESS: NonNull<Gicd> = NonNull::new(0x800_0000 as _).unwrap();
const GICR_BASE_ADDRESS: NonNull<GicrSgi> = NonNull::new(0x80A_0000 as _).unwrap();
/// 主 PL011 UART 的基地址。
const PL011_BASE_ADDRESS: NonNull<PL011Registers> =
NonNull::new(0x900_0000 as _).unwrap();
/// 用于初始标识映射中的设备内存的属性。
const DEVICE_ATTRIBUTES: El1Attributes = El1Attributes::VALID
.union(El1Attributes::ATTRIBUTE_INDEX_0)
.union(El1Attributes::ACCESSED)
.union(El1Attributes::UXN);
/// 用于初始标识映射中的普通内存的属性。
const MEMORY_ATTRIBUTES: El1Attributes = El1Attributes::VALID
.union(El1Attributes::ATTRIBUTE_INDEX_1)
.union(El1Attributes::INNER_SHAREABLE)
.union(El1Attributes::ACCESSED)
.union(El1Attributes::NON_GLOBAL);
initial_pagetable!({
let mut idmap = [0; 512];
// 1 GiB 设备内存。
idmap[0] = DEVICE_ATTRIBUTES.bits();
// 1 GiB 普通内存。
idmap[1] = MEMORY_ATTRIBUTES.bits() | 0x40000000;
// 另外 1 GiB 设备内存从 256 GiB 开始。
idmap[256] = DEVICE_ATTRIBUTES.bits() | 0x4000000000;
InitialPagetable(idmap)
});
/// PL031 RTC 的基地址。
const PL031_BASE_ADDRESS: NonNull<pl031::Registers> =
NonNull::new(0x901_0000 as _).unwrap();
/// PL031 RTC 使用的 IRQ。
const PL031_IRQ: IntId = IntId::spi(2);
entry!(main);
fn main(x0: u64, x1: u64, x2: u64, x3: u64) -> ! {
// 安全:`PL011_BASE_ADDRESS`是 PL011 设备的基地址,并且
// 没有其他东西可以访问该地址范围。
let uart = unsafe { Uart::new(UniqueMmioPointer::new(PL011_BASE_ADDRESS)) };
logger::init(uart, LevelFilter::Trace).unwrap();
info!("main({:#x}, {:#x}, {:#x}, {:#x})", x0, x1, x2, x3);
// 安全:`GICD_BASE_ADDRESS`和`GICR_BASE_ADDRESS`是基础
// 分别是 GICv3 分发器和再分发器的地址,以及
// 没有其他东西可以访问这些地址范围。
let mut gic = unsafe {
GicV3::new(
UniqueMmioPointer::new(GICD_BASE_ADDRESS),
GICR_BASE_ADDRESS,
1,
false,
)
};
gic.setup(0);
// ANCHOR_END:主要
// 安全:`PL031_BASE_ADDRESS`是 PL031 设备的基地址,并且
// 没有其他东西可以访问该地址范围。
let mut rtc = unsafe { Rtc::new(UniqueMmioPointer::new(PL031_BASE_ADDRESS)) };
let timestamp = rtc.read();
let time = Utc.timestamp_opt(timestamp.into(), 0).unwrap();
info!("RTC: {time}");
GicCpuInterface::set_priority_mask(0xff);
gic.set_interrupt_priority(PL031_IRQ, None, 0x80).unwrap();
gic.set_trigger(PL031_IRQ, None, Trigger::Level).unwrap();
irq_enable();
gic.enable_interrupt(PL031_IRQ, None, true).unwrap();
// 等待 3 秒钟,不要中断。
let target = timestamp + 3;
rtc.set_match(target);
info!("Waiting for {}", Utc.timestamp_opt(target.into(), 0).unwrap());
trace!(
"matched={}, interrupt_pending={}",
rtc.matched(),
rtc.interrupt_pending()
);
while !rtc.matched() {
spin_loop();
}
trace!(
"matched={}, interrupt_pending={}",
rtc.matched(),
rtc.interrupt_pending()
);
info!("Finished waiting");
// 再等待 3 秒以获得中断。
let target = timestamp + 6;
info!("Waiting for {}", Utc.timestamp_opt(target.into(), 0).unwrap());
rtc.set_match(target);
rtc.clear_interrupt();
rtc.enable_interrupt(true);
trace!(
"matched={}, interrupt_pending={}",
rtc.matched(),
rtc.interrupt_pending()
);
while !rtc.interrupt_pending() {
wfi();
}
trace!(
"matched={}, interrupt_pending={}",
rtc.matched(),
rtc.interrupt_pending()
);
info!("Finished waiting");
// 锚点:main_end
system_off::<Hvc>().unwrap();
panic!("system_off returned");
}
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
error!("{info}");
system_off::<Hvc>().unwrap();
loop {}
}
|