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