mirror of
https://github.com/esp-rs/esp-idf-hal.git
synced 2025-09-27 04:10:30 +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
|
||||
**/*.rs.bk
|
||||
ulp/ulp_start.o
|
||||
Cargo.lock
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "esp-idf-hal"
|
||||
version = "0.17.0"
|
||||
version = "0.17.1"
|
||||
authors = ["sapir <yasapir@gmail.com>", "Ivan Markov <ivan.markov@gmail.com>"]
|
||||
edition = "2018"
|
||||
categories = ["embedded", "hardware-support"]
|
||||
|
13
build.rs
13
build.rs
@ -6,4 +6,17 @@ fn main() {
|
||||
let mcu = "esp32s2";
|
||||
|
||||
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;
|
||||
#[cfg(feature = "ulp")]
|
||||
pub mod delay;
|
||||
#[cfg(feature = "ulp")]
|
||||
pub mod start;
|
||||
|
||||
#[cfg(not(feature = "ulp"))]
|
||||
#[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