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