Skip to main content

sparreal_kernel/hal/
al.rs

1use core::ptr::NonNull;
2
3use alloc::boxed::Box;
4pub use heapless::Vec as StackVec;
5use kernutil::define_type;
6pub use kernutil::memory::{MemoryDescriptor, PageTableInfo};
7pub use page_table_generic::{AccessFlags, MemAttributes, MemConfig, PagingError};
8pub use rdrive::register::DriverRegisterSlice;
9
10use crate::os::mem::{__io, page_size};
11
12#[trait_ffi::def_extern_trait(mod_path = "hal::al")]
13pub trait Memory {
14    fn _va(paddr: PhysAddr) -> VirtAddr;
15    fn _io(paddr: PhysAddr) -> VirtAddr;
16    fn _percpu(paddr: PhysAddr) -> VirtAddr;
17
18    /// 内核镜像在虚拟地址空间中的偏移
19    fn kimage_offset() -> isize;
20
21    /// Convert virtual address to physical address
22    fn virt_to_phys(virt: VirtAddr) -> PhysAddr;
23
24    fn page_size() -> usize;
25    fn memory_map() -> &'static [MemoryDescriptor];
26
27    fn page_table_new() -> Result<Box<dyn PageTable>, PagingError>;
28
29    fn kernel_page_table() -> PhysAddr;
30    fn set_kernel_page_table(pt: PhysAddr);
31    fn user_page_table() -> PageTableInfo;
32    fn set_user_page_table(pt: PageTableInfo);
33}
34
35#[trait_ffi::def_extern_trait(not_def_impl, mod_path = "hal::al")]
36pub trait Platform {
37    fn post_allocator();
38    fn irq_is_enabled(irq: IrqId) -> bool;
39    fn irq_set_enabled(irq: IrqId, enabled: bool);
40
41    fn shutdown() -> !;
42
43    fn fdt_addr() -> Option<NonNull<u8>>;
44    fn post_paging();
45}
46
47#[trait_ffi::def_extern_trait(not_def_impl, mod_path = "hal::al")]
48pub trait Cpu {
49    fn current_cpu_id() -> usize;
50    fn irq_local_is_enabled() -> bool;
51    fn irq_local_set_enable(enabled: bool);
52    fn systick_irq_id() -> IrqId;
53    fn systick_enable();
54    fn systick_irq_enable();
55    fn systick_irq_disable();
56    fn systick_irq_is_enabled() -> bool;
57    // fn systimer_set_next_event(intval: Duration);
58    fn systick_ack();
59    fn systick_frequency() -> usize;
60    // fn systimer_since_boot() -> Duration;
61    fn systick_ticks() -> usize;
62    /// Set next irq interval in ticks
63    fn systick_set_interval(ticks: usize);
64}
65
66#[trait_ffi::def_extern_trait(mod_path = "hal::al", not_def_impl)]
67pub trait Console {
68    fn early_write(bytes: &[u8]) -> usize;
69    fn early_read() -> Option<u8>;
70}
71
72pub fn handle_irq(irq: IrqId) {
73    crate::os::irq::handle_irq(irq);
74}
75
76pub trait PageTable: Send + 'static {
77    fn addr(&self) -> PhysAddr;
78    fn map(
79        &mut self,
80        virt_start: VirtAddr,
81        phys_start: PhysAddr,
82        size: usize,
83        settings: MemConfig,
84        flush: bool,
85    ) -> Result<(), PagingError>;
86    fn unmap(&mut self, virt_start: VirtAddr, size: usize) -> Result<(), PagingError>;
87
88    fn ioremap(
89        &mut self,
90        phys_start: PhysAddr,
91        size: usize,
92        flush: bool,
93    ) -> Result<IoMemAddr, PagingError> {
94        let virt = __io(phys_start);
95        let end = virt + size;
96        let vaddr = virt.align_down(page_size());
97        let paddr = phys_start.align_down(page_size());
98        let end = end.align_up(page_size());
99        let size = end - vaddr;
100        debug!("ioremap: phys={}, virt={}, size=0x{:x}", paddr, vaddr, size);
101        let settings = MemConfig {
102            access: AccessFlags::READ | AccessFlags::WRITE,
103            attrs: MemAttributes::Device,
104        };
105
106        self.map(
107            vaddr.raw().into(),
108            paddr.raw().into(),
109            size,
110            settings,
111            flush,
112        )?;
113
114        Ok(virt.raw().into())
115    }
116}
117
118define_type! {
119    /// Interrupt Request Identifier
120    IrqId(usize, "{:#x}"),
121    /// Physical Address
122    PhysAddr(usize, "{:#x}"),
123    /// Virtual Address
124    VirtAddr(usize, "{:#x}"),
125    /// I/O Memory Address
126    IoMemAddr(usize, "{:#x}"),
127    ///
128    Asid(usize, "{:#x}"),
129}