Skip to main content

mpfs_hal/
lib.rs

1#![no_std]
2
3#[cfg(feature = "alloc")]
4mod alloc;
5#[cfg(feature = "alloc")]
6use alloc::init_heap;
7
8use riscv::register::mstatus;
9
10mod critical_section_impl;
11critical_section::set_impl!(critical_section_impl::MPFSCriticalSection);
12
13pub use mpfs_hal_procmacros::{hart1_main, hart2_main, hart3_main, hart4_main, init_once};
14
15mod mutex;
16pub use mutex::Mutex;
17
18pub use mpfs_pac as pac;
19pub use pac::hart_id;
20
21mod peripheral;
22pub use peripheral::*;
23
24#[cfg(feature = "print")]
25mod print;
26#[cfg(feature = "print")]
27pub use print::*;
28
29#[cfg(feature = "log")]
30mod logger;
31#[cfg(feature = "log")]
32pub use logger::*;
33
34pub mod ethernet;
35pub mod gpio;
36pub mod qspi;
37pub mod spi;
38pub mod uart;
39
40/// Put in a panic handler to put the core into a low power loop
41pub fn low_power_loop_forever() -> ! {
42    loop {
43        unsafe {
44            core::arch::asm!("wfi");
45        }
46    }
47}
48
49//----------------------------------------------------------
50// Entry points
51
52unsafe extern "C" {
53    fn __init_once();
54    fn __init_once_embassy();
55    fn __hart1_entry();
56    fn __hart2_entry();
57    fn __hart3_entry();
58    fn __hart4_entry();
59}
60
61fn init_once() {
62    unsafe {
63        pac::mss_config_clk_rst(
64            pac::mss_peripherals__MSS_PERIPH_CFM,
65            pac::MPFS_HAL_FIRST_HART as u8,
66            pac::PERIPH_RESET_STATE__PERIPHERAL_ON,
67        );
68        pac::mss_enable_fabric();
69
70        #[cfg(feature = "alloc")]
71        init_heap();
72
73        uart::init_uart();
74
75        #[cfg(feature = "print")]
76        init_print();
77
78        __init_once_embassy();
79        __init_once();
80    }
81}
82
83#[unsafe(no_mangle)]
84extern "C" fn u54_1() {
85    unsafe {
86        // Rest of hardware initialization
87        pac::clear_soft_interrupt();
88        core::arch::asm!("csrs mie, {}", const pac::MIP_MSIP, options(nomem, nostack));
89        pac::PLIC_init();
90        pac::__enable_irq();
91        init_fpu();
92
93        // All other harts are put into wfi when they boot, so we can init_once from here
94        init_once();
95
96        // Now we wake up the other harts
97        pac::raise_soft_interrupt(2);
98        pac::raise_soft_interrupt(3);
99        pac::raise_soft_interrupt(4);
100
101        __hart1_entry();
102    }
103}
104
105#[unsafe(no_mangle)]
106extern "C" fn u54_2() {
107    unsafe {
108        // Rest of hardware initialization
109        pac::clear_soft_interrupt();
110        core::arch::asm!("csrs mie, {}", const pac::MIP_MSIP, options(nomem, nostack));
111        pac::PLIC_init();
112        pac::__enable_irq();
113        init_fpu();
114
115        // Wait for the software interrupt
116        core::arch::asm!("wfi", options(nomem, nostack));
117        __hart2_entry();
118    }
119}
120
121#[unsafe(no_mangle)]
122extern "C" fn u54_3() {
123    unsafe {
124        // Rest of hardware initialization
125        pac::clear_soft_interrupt();
126        core::arch::asm!("csrs mie, {}", const pac::MIP_MSIP, options(nomem, nostack));
127        pac::PLIC_init();
128        pac::__enable_irq();
129        init_fpu();
130
131        // Wait for the software interrupt
132        core::arch::asm!("wfi", options(nomem, nostack));
133        __hart3_entry();
134    }
135}
136
137#[unsafe(no_mangle)]
138extern "C" fn u54_4() {
139    unsafe {
140        // Rest of hardware initialization
141        pac::clear_soft_interrupt();
142        core::arch::asm!("csrs mie, {}", const pac::MIP_MSIP, options(nomem, nostack));
143        pac::PLIC_init();
144        pac::__enable_irq();
145        init_fpu();
146
147        // Wait for the software interrupt
148        core::arch::asm!("wfi", options(nomem, nostack));
149
150        __hart4_entry();
151    }
152}
153
154fn init_fpu() {
155    unsafe {
156        // Enable FPU
157        mstatus::set_fs(mstatus::FS::Initial);
158        // Clear any pending exceptions
159        core::arch::asm!("csrwi fflags, 0");
160        // Clear FPU control and status register
161        core::arch::asm!("csrwi fcsr, 0");
162    }
163}