mirror of
https://github.com/esp-rs/esp-idf-hal.git
synced 2025-10-02 06:40:55 +00:00
RiscV ULP boot code no longer dependent on the riscv-rt crate
This commit is contained in:
parent
9fc1b78add
commit
b0e5629869
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,3 @@
|
|||||||
/target
|
/target
|
||||||
**/*.rs.bk
|
ulp/ulp_start.o
|
||||||
Cargo.lock
|
Cargo.lock
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "esp-idf-hal"
|
name = "esp-idf-hal"
|
||||||
version = "0.17.0"
|
version = "0.17.1"
|
||||||
authors = ["sapir <yasapir@gmail.com>", "Ivan Markov <ivan.markov@gmail.com>"]
|
authors = ["sapir <yasapir@gmail.com>", "Ivan Markov <ivan.markov@gmail.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
categories = ["embedded", "hardware-support"]
|
categories = ["embedded", "hardware-support"]
|
||||||
|
13
build.rs
13
build.rs
@ -6,4 +6,17 @@ fn main() {
|
|||||||
let mcu = "esp32s2";
|
let mcu = "esp32s2";
|
||||||
|
|
||||||
println!("cargo:rustc-cfg={}", mcu);
|
println!("cargo:rustc-cfg={}", mcu);
|
||||||
|
|
||||||
|
#[cfg(feature = "ulp")]
|
||||||
|
{
|
||||||
|
let ulp_dir = std::env::current_dir().unwrap().join("ulp");
|
||||||
|
|
||||||
|
println!("cargo:rustc-link-search={}", ulp_dir.display());
|
||||||
|
|
||||||
|
println!("cargo:rustc-link-lib=static=ulp_start");
|
||||||
|
|
||||||
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
|
println!("cargo:rerun-if-changed={}", ulp_dir.join("libulp_start.a").display());
|
||||||
|
println!("cargo:rerun-if-changed={}", ulp_dir.join("ulp_link.x").display());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,8 @@ mod reg;
|
|||||||
pub mod sys;
|
pub mod sys;
|
||||||
#[cfg(feature = "ulp")]
|
#[cfg(feature = "ulp")]
|
||||||
pub mod delay;
|
pub mod delay;
|
||||||
|
#[cfg(feature = "ulp")]
|
||||||
|
pub mod start;
|
||||||
|
|
||||||
#[cfg(not(feature = "ulp"))]
|
#[cfg(not(feature = "ulp"))]
|
||||||
#[cfg(any(esp32, esp32s2, esp32s3))]
|
#[cfg(any(esp32, esp32s2, esp32s3))]
|
||||||
|
175
src/ulp/start.rs
Normal file
175
src/ulp/start.rs
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
//! Minimal startup / runtime for ESP32-SXX RISC-V ULPs
|
||||||
|
//! Adapted from riscv-rt/src/lib.rs
|
||||||
|
|
||||||
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
|
use super::sys::cpu;
|
||||||
|
|
||||||
|
#[export_name = "error: ulp_start appears more than once in the dependency graph"]
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub static __ONCE__: () = ();
|
||||||
|
|
||||||
|
/// Rust entry point (_start_rust)
|
||||||
|
///
|
||||||
|
/// Calls main. This function never returns.
|
||||||
|
#[link_section = ".start.rust"]
|
||||||
|
#[export_name = "_start_rust"]
|
||||||
|
pub unsafe extern "C" fn start_rust() -> ! {
|
||||||
|
#[rustfmt::skip]
|
||||||
|
extern "Rust" {
|
||||||
|
// This symbol will be provided by the user
|
||||||
|
fn main();
|
||||||
|
}
|
||||||
|
|
||||||
|
cpu::rescue_from_monitor();
|
||||||
|
|
||||||
|
main();
|
||||||
|
|
||||||
|
cpu::shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Registers saved in trap handler
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct TrapFrame {
|
||||||
|
pub ra: usize,
|
||||||
|
pub t0: usize,
|
||||||
|
pub t1: usize,
|
||||||
|
pub t2: usize,
|
||||||
|
pub t3: usize,
|
||||||
|
pub t4: usize,
|
||||||
|
pub t5: usize,
|
||||||
|
pub t6: usize,
|
||||||
|
pub a0: usize,
|
||||||
|
pub a1: usize,
|
||||||
|
pub a2: usize,
|
||||||
|
pub a3: usize,
|
||||||
|
pub a4: usize,
|
||||||
|
pub a5: usize,
|
||||||
|
pub a6: usize,
|
||||||
|
pub a7: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Trap entry point rust (_start_trap_rust)
|
||||||
|
///
|
||||||
|
/// `mcause` is read to determine the cause of the trap. XLEN-1 bit indicates
|
||||||
|
/// if it's an interrupt or an exception. The result is examined and ExceptionHandler
|
||||||
|
/// or one of the core interrupt handlers is called.
|
||||||
|
#[link_section = ".trap.rust"]
|
||||||
|
#[export_name = "_start_trap_rust"]
|
||||||
|
pub extern "C" fn start_trap_rust(trap_frame: *const TrapFrame) {
|
||||||
|
// use riscv::register::mcause;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
fn ExceptionHandler(trap_frame: &TrapFrame);
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn DefaultHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
// let cause = mcause::read();
|
||||||
|
// if cause.is_exception() {
|
||||||
|
ExceptionHandler(&*trap_frame)
|
||||||
|
// } else {
|
||||||
|
// let code = cause.code();
|
||||||
|
// if code < __INTERRUPTS.len() {
|
||||||
|
// let h = &__INTERRUPTS[code];
|
||||||
|
// if h.reserved == 0 {
|
||||||
|
// DefaultHandler();
|
||||||
|
// } else {
|
||||||
|
// (h.handler)();
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// DefaultHandler();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[no_mangle]
|
||||||
|
#[allow(unused_variables, non_snake_case)]
|
||||||
|
pub fn DefaultExceptionHandler(trap_frame: &TrapFrame) -> ! {
|
||||||
|
loop {
|
||||||
|
// Prevent this from turning into a UDF instruction
|
||||||
|
// see rust-lang/rust#28728 for details
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[no_mangle]
|
||||||
|
#[allow(unused_variables, non_snake_case)]
|
||||||
|
pub fn DefaultInterruptHandler() {
|
||||||
|
loop {
|
||||||
|
// Prevent this from turning into a UDF instruction
|
||||||
|
// see rust-lang/rust#28728 for details
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Interrupts */
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub enum Interrupt {
|
||||||
|
UserSoft,
|
||||||
|
SupervisorSoft,
|
||||||
|
MachineSoft,
|
||||||
|
UserTimer,
|
||||||
|
SupervisorTimer,
|
||||||
|
MachineTimer,
|
||||||
|
UserExternal,
|
||||||
|
SupervisorExternal,
|
||||||
|
MachineExternal,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub use self::Interrupt as interrupt;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
fn UserSoft();
|
||||||
|
fn SupervisorSoft();
|
||||||
|
fn MachineSoft();
|
||||||
|
fn UserTimer();
|
||||||
|
fn SupervisorTimer();
|
||||||
|
fn MachineTimer();
|
||||||
|
fn UserExternal();
|
||||||
|
fn SupervisorExternal();
|
||||||
|
fn MachineExternal();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub union Vector {
|
||||||
|
handler: unsafe extern "C" fn(),
|
||||||
|
reserved: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[no_mangle]
|
||||||
|
pub static __INTERRUPTS: [Vector; 12] = [
|
||||||
|
Vector { handler: UserSoft },
|
||||||
|
Vector {
|
||||||
|
handler: SupervisorSoft,
|
||||||
|
},
|
||||||
|
Vector { reserved: 0 },
|
||||||
|
Vector {
|
||||||
|
handler: MachineSoft,
|
||||||
|
},
|
||||||
|
Vector { handler: UserTimer },
|
||||||
|
Vector {
|
||||||
|
handler: SupervisorTimer,
|
||||||
|
},
|
||||||
|
Vector { reserved: 0 },
|
||||||
|
Vector {
|
||||||
|
handler: MachineTimer,
|
||||||
|
},
|
||||||
|
Vector {
|
||||||
|
handler: UserExternal,
|
||||||
|
},
|
||||||
|
Vector {
|
||||||
|
handler: SupervisorExternal,
|
||||||
|
},
|
||||||
|
Vector { reserved: 0 },
|
||||||
|
Vector {
|
||||||
|
handler: MachineExternal,
|
||||||
|
},
|
||||||
|
];
|
BIN
ulp/libulp_start.a
Normal file
BIN
ulp/libulp_start.a
Normal file
Binary file not shown.
88
ulp/ulp_link.x
Normal file
88
ulp/ulp_link.x
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
PROVIDE(_ram_size = 2K);
|
||||||
|
|
||||||
|
PROVIDE(UserSoft = DefaultHandler);
|
||||||
|
PROVIDE(SupervisorSoft = DefaultHandler);
|
||||||
|
PROVIDE(MachineSoft = DefaultHandler);
|
||||||
|
PROVIDE(UserTimer = DefaultHandler);
|
||||||
|
PROVIDE(SupervisorTimer = DefaultHandler);
|
||||||
|
PROVIDE(MachineTimer = DefaultHandler);
|
||||||
|
PROVIDE(UserExternal = DefaultHandler);
|
||||||
|
PROVIDE(SupervisorExternal = DefaultHandler);
|
||||||
|
PROVIDE(MachineExternal = DefaultHandler);
|
||||||
|
|
||||||
|
PROVIDE(DefaultHandler = DefaultInterruptHandler);
|
||||||
|
PROVIDE(ExceptionHandler = DefaultExceptionHandler);
|
||||||
|
|
||||||
|
ENTRY(reset_vector)
|
||||||
|
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
ram(RW) : ORIGIN = 0, LENGTH = _ram_size
|
||||||
|
}
|
||||||
|
|
||||||
|
PROVIDE(_stext = ORIGIN(ram));
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
.text.dummy (NOLOAD) :
|
||||||
|
{
|
||||||
|
/* This section is intended to make _stext address work */
|
||||||
|
. = ABSOLUTE(_stext);
|
||||||
|
} > ram
|
||||||
|
|
||||||
|
.text _stext :
|
||||||
|
{
|
||||||
|
KEEP(*(.init)); // Default reset vector must link to offset 0x0
|
||||||
|
KEEP(*(.start.rust));
|
||||||
|
KEEP(*(.trap.rust));
|
||||||
|
|
||||||
|
*(.text .text.*);
|
||||||
|
} > ram
|
||||||
|
|
||||||
|
.rodata ALIGN(4):
|
||||||
|
{
|
||||||
|
*(.srodata .srodata.*);
|
||||||
|
*(.rodata .rodata.*);
|
||||||
|
|
||||||
|
/* 4-byte align the end (VMA) of this section.
|
||||||
|
This is required by LLD to ensure the LMA of the following .data
|
||||||
|
section will have the correct alignment. */
|
||||||
|
. = ALIGN(4);
|
||||||
|
} > ram
|
||||||
|
|
||||||
|
.data ALIGN(4):
|
||||||
|
{
|
||||||
|
/* Must be called __global_pointer$ for linker relaxations to work. */
|
||||||
|
PROVIDE(__global_pointer$ = . + 0x800);
|
||||||
|
*(.sdata .sdata.* .sdata2 .sdata2.*);
|
||||||
|
*(.data .data.*);
|
||||||
|
. = ALIGN(4);
|
||||||
|
} > ram
|
||||||
|
|
||||||
|
.bss ALIGN(4) :
|
||||||
|
{
|
||||||
|
*(.sbss .sbss.* .bss .bss.*);
|
||||||
|
. = ALIGN(4);
|
||||||
|
} > ram
|
||||||
|
|
||||||
|
/* fake output .got section */
|
||||||
|
/* Dynamic relocations are unsupported. This section is only used to detect
|
||||||
|
relocatable code in the input files and raise an error if relocatable code
|
||||||
|
is found */
|
||||||
|
.got (INFO) :
|
||||||
|
{
|
||||||
|
KEEP(*(.got .got.*));
|
||||||
|
}
|
||||||
|
|
||||||
|
.eh_frame (INFO) :
|
||||||
|
{
|
||||||
|
KEEP(*(.eh_frame))
|
||||||
|
}
|
||||||
|
|
||||||
|
.eh_frame_hdr (INFO) :
|
||||||
|
{
|
||||||
|
*(.eh_frame_hdr)
|
||||||
|
}
|
||||||
|
|
||||||
|
_stack_top = ORIGIN(ram) + LENGTH(ram);
|
||||||
|
}
|
117
ulp/ulp_start.S
Normal file
117
ulp/ulp_start.S
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
// NOTE: Adapted from riscv-rt/asm.S
|
||||||
|
#define REGBYTES (1 << 2)
|
||||||
|
|
||||||
|
.section .init, "ax"
|
||||||
|
.global reset_vector
|
||||||
|
.global irq_vector
|
||||||
|
|
||||||
|
// The reset vector, jumps to startup code
|
||||||
|
reset_vector:
|
||||||
|
j _start
|
||||||
|
|
||||||
|
// Interrupt handler
|
||||||
|
.option push
|
||||||
|
.option norelax // To prevent an unsupported R_RISCV_ALIGN relocation from being generated
|
||||||
|
.balign 16
|
||||||
|
irq_vector:
|
||||||
|
addi sp, sp, -16*REGBYTES
|
||||||
|
|
||||||
|
sw ra, 0*REGBYTES(sp)
|
||||||
|
sw t0, 1*REGBYTES(sp)
|
||||||
|
sw t1, 2*REGBYTES(sp)
|
||||||
|
sw t2, 3*REGBYTES(sp)
|
||||||
|
sw t3, 4*REGBYTES(sp)
|
||||||
|
sw t4, 5*REGBYTES(sp)
|
||||||
|
sw t5, 6*REGBYTES(sp)
|
||||||
|
sw t6, 7*REGBYTES(sp)
|
||||||
|
sw a0, 8*REGBYTES(sp)
|
||||||
|
sw a1, 9*REGBYTES(sp)
|
||||||
|
sw a2, 10*REGBYTES(sp)
|
||||||
|
sw a3, 11*REGBYTES(sp)
|
||||||
|
sw a4, 12*REGBYTES(sp)
|
||||||
|
sw a5, 13*REGBYTES(sp)
|
||||||
|
sw a6, 14*REGBYTES(sp)
|
||||||
|
sw a7, 15*REGBYTES(sp)
|
||||||
|
|
||||||
|
add a0, sp, zero
|
||||||
|
jal ra, _start_trap_rust
|
||||||
|
|
||||||
|
lw ra, 0*REGBYTES(sp)
|
||||||
|
lw t0, 1*REGBYTES(sp)
|
||||||
|
lw t1, 2*REGBYTES(sp)
|
||||||
|
lw t2, 3*REGBYTES(sp)
|
||||||
|
lw t3, 4*REGBYTES(sp)
|
||||||
|
lw t4, 5*REGBYTES(sp)
|
||||||
|
lw t5, 6*REGBYTES(sp)
|
||||||
|
lw t6, 7*REGBYTES(sp)
|
||||||
|
lw a0, 8*REGBYTES(sp)
|
||||||
|
lw a1, 9*REGBYTES(sp)
|
||||||
|
lw a2, 10*REGBYTES(sp)
|
||||||
|
lw a3, 11*REGBYTES(sp)
|
||||||
|
lw a4, 12*REGBYTES(sp)
|
||||||
|
lw a5, 13*REGBYTES(sp)
|
||||||
|
lw a6, 14*REGBYTES(sp)
|
||||||
|
lw a7, 15*REGBYTES(sp)
|
||||||
|
|
||||||
|
addi sp, sp, 16*REGBYTES
|
||||||
|
ret
|
||||||
|
.option pop
|
||||||
|
|
||||||
|
_start:
|
||||||
|
.cfi_startproc
|
||||||
|
.cfi_undefined ra
|
||||||
|
|
||||||
|
li x1, 0
|
||||||
|
li x2, 0
|
||||||
|
li x3, 0
|
||||||
|
li x4, 0
|
||||||
|
li x5, 0
|
||||||
|
li x6, 0
|
||||||
|
li x7, 0
|
||||||
|
li x8, 0
|
||||||
|
li x9, 0
|
||||||
|
li x10,0
|
||||||
|
li x11,0
|
||||||
|
li x12,0
|
||||||
|
li x13,0
|
||||||
|
li x14,0
|
||||||
|
li x15,0
|
||||||
|
li x16,0
|
||||||
|
li x17,0
|
||||||
|
li x18,0
|
||||||
|
li x19,0
|
||||||
|
li x20,0
|
||||||
|
li x21,0
|
||||||
|
li x22,0
|
||||||
|
li x23,0
|
||||||
|
li x24,0
|
||||||
|
li x25,0
|
||||||
|
li x26,0
|
||||||
|
li x27,0
|
||||||
|
li x28,0
|
||||||
|
li x29,0
|
||||||
|
li x30,0
|
||||||
|
li x31,0
|
||||||
|
|
||||||
|
.option push
|
||||||
|
.option norelax // To prevent an unsupported R_RISCV_ALIGN relocation from being generated
|
||||||
|
la gp, __global_pointer$
|
||||||
|
.option pop
|
||||||
|
|
||||||
|
// Allocate stack
|
||||||
|
la sp, _stack_top
|
||||||
|
|
||||||
|
// Set frame pointer
|
||||||
|
add s0, sp, zero
|
||||||
|
|
||||||
|
jal zero, _start_rust
|
||||||
|
|
||||||
|
.cfi_endproc
|
||||||
|
|
||||||
|
loop:
|
||||||
|
j loop
|
||||||
|
|
||||||
|
// Make sure there is an abort when linking
|
||||||
|
.globl abort
|
||||||
|
abort:
|
||||||
|
j abort
|
7
ulp/ulp_start_assemble.ps1
Normal file
7
ulp/ulp_start_assemble.ps1
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# remove existing blob because otherwise this will append object file to the old blob
|
||||||
|
Remove-Item -Force ulp_start.a
|
||||||
|
|
||||||
|
riscv32-esp-elf-gcc -Desp_ulp -ggdb3 -fdebug-prefix-map=$(pwd)=/ulp_start -c -mabi=ilp32 -march=rv32imc ulp_start.S -o ulp_start.o
|
||||||
|
riscv32-esp-elf-ar crs libulp_start.a ulp_start.o
|
||||||
|
|
||||||
|
Remove-Item ulp_start.o
|
11
ulp/ulp_start_assemble.sh
Executable file
11
ulp/ulp_start_assemble.sh
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euxo pipefail
|
||||||
|
|
||||||
|
# remove existing blob because otherwise this will append object file to the old blob
|
||||||
|
rm -f ulp_start.a
|
||||||
|
|
||||||
|
riscv32-esp-elf-gcc -Desp_ulp -ggdb3 -fdebug-prefix-map=$(pwd)=/ulp_start -c -mabi=ilp32 -march=rv32imc ulp_start.S -o ulp_start.o
|
||||||
|
riscv32-esp-elf-ar crs libulp_start.a ulp_start.o
|
||||||
|
|
||||||
|
rm ulp_start.o
|
Loading…
x
Reference in New Issue
Block a user