commit 5f62d443dc4e8c6820bedffbf6ed1239d4afa342 Author: Victor Mignot Date: Sun Aug 18 22:04:55 2024 +0200 Initial Cortex-M4F bootstrap code diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..ff32d13 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,5 @@ +[build] +target = "thumbv7em-none-eabihf" + +[target.thumbv7em-none-eabihf] +rustflags = ["-C", "link-arg=-Tlink.x"] diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..7ef42a8 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "wocchi" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..b951cfc --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "wocchi" +version = "0.1.0" +edition = "2021" + +[dependencies] + +[[bin]] +name = "wocchi" +test = false +bench = false diff --git a/link.x b/link.x new file mode 100644 index 0000000..20d2842 --- /dev/null +++ b/link.x @@ -0,0 +1,66 @@ +/* SoC Memory Layout */ +MEMORY +{ + FLASH : ORIGIN = 0x00000000, LENGTH = 512K + RAM : ORIGIN = 0x20000000, LENGTH = 64K +} + +/* Declare the program entrypoint, each sections and variable called from it will not be + discarded by the linker. */ +ENTRY(reset_handler); + +PROVIDE(reset_handler = default_exception_handler); +PROVIDE(nmi_handler = default_exception_handler); +PROVIDE(hardfault_handler = default_exception_handler); +PROVIDE(memmanager_handler = default_exception_handler); +PROVIDE(busfault_handler = default_exception_handler); +PROVIDE(usagefault_handler = default_exception_handler); +PROVIDE(svcall_handler = default_exception_handler); +PROVIDE(debugmonitor_handler = default_exception_handler); +PROVIDE(pendsv_handler = default_exception_handler); +PROVIDE(systick_handler = default_exception_handler); + +SECTIONS +{ + _sp_init = ORIGIN(RAM) + LENGTH(RAM); + + .vector_table ORIGIN(FLASH) : + { + KEEP(*(.vector_table .vector_table)); + } > FLASH + + .text : + { + *(.text .text.*); + } > FLASH + + .rodata : + { + *(.rodata .rodata.*); + } > FLASH + + .bss : + { + . = ALIGN(4); + _bss_section_start = .; + *(.bss .bss.*); + . = ALIGN(4); + _bss_section_end = .; + } > RAM + + .data : AT(ADDR(.rodata) + SIZEOF(.rodata)) + { + . = ALIGN(4); + _data_section_start = .; + *(.data .data.*); + . = ALIGN(4); + _data_section_end = .; + } > RAM + _data_section_lma = LOADADDR(.data); + + /DISCARD/ : + { + *(.ARM.exidx .ARM.exidx.*); + } + +} diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..f7ab7bb --- /dev/null +++ b/shell.nix @@ -0,0 +1,22 @@ +let + pkgs = import { + crossSystem = (import ).systems.examples.armv7l-hf-multiplatform; + overlays = [(import (builtins.fetchTarball "https://github.com/oxalica/rust-overlay/archive/master.tar.gz"))]; + }; +in + pkgs.mkShell { + packages = with pkgs.buildPackages; [ + rust-analyzer + ]; + + nativeBuildInputs = with pkgs.buildPackages; [ + (rust-bin.stable.latest.default.override { + extensions = [ "rust-src" ]; + targets = [ "thumbv7em-none-eabihf" ]; + }) + ]; + + env = { + CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER = "${pkgs.stdenv.cc.targetPrefix}cc"; + }; + } diff --git a/src/bootstrap.s b/src/bootstrap.s new file mode 100644 index 0000000..61c6499 --- /dev/null +++ b/src/bootstrap.s @@ -0,0 +1,92 @@ +/* Use the UAL syntax */ + .syntax unified + +/* Symbols declared in the linker script */ + .global _sp_init + .global _bss_section_start + .global _bss_section_end + .global _data_section_start + .global _data_section_end + .global _data_section_lma + +/* Main function of the program to which this script is linked */ + .global main + +/* ARM vector table (aka isr_vector) */ + .section .vector_table + .align 2 + .word _sp_init /* Initialisation value of the stack pointer register */ +/* Exceptions handlers */ + .word reset_handler /* Reset Exception */ + .word nmi_handler /* NMI Exception */ + .word hardfault_handler /* HardFault Exception */ + .word memmanager_handler /* MemManage Exception */ + .word busfault_handler /* BusFault Exception */ + .word usagefault_handler /* UsageFault Exception */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word svcall_handler /* SVCall Exception */ + .word debugmonitor_handler /* DebugMonitor Exception */ + .word 0 /* Reserved */ + .word pendsv_handler /* PendSV Exception */ + .word systick_handler /* SysTick Exception */ + + .text + .align + + .global default_exception_handler + .thumb_func +default_exception_handler: + b . + +/* The CPU Reset Exception Handler, initializing register and data section, then call the main function */ + .global reset_handler + .thumb_func +reset_handler: +/* Initialize the CPU general purpose registers */ + mov r0, 0 + mov r1, 0 + mov r2, 0 + mov r3, 0 + mov r4, 0 + mov r5, 0 + mov r6, 0 + mov r7, 0 + mov r8, 0 + mov r9, 0 + mov r10, 0 + mov r11, 0 + mov r12, 0 + +/* .bss section initialization (see linker script) */ +bss_init: + mov r0, 0 + ldr r1, =_bss_section_start + ldr r2, =_bss_section_end + +bss_init_loop: +/* Fill the section word-by-word with zeros */ + cmp r1, r2 + beq data_init + str r0, [r1], 4 + b bss_init_loop + +/* Data section initialization */ +data_init: + ldr r1, =_data_section_start + ldr r2, =_data_section_end + ldr r3, =_data_section_lma + +/* Load the initial values of the variables from the section LMA */ +data_init_loop: + cmp r1, r2 + beq bootstrap_end + ldr r0, [r3], 4 + str r0, [r1], 4 + b data_init_loop + +/* Bootstrap completed, branch to Rust code now ! */ +bootstrap_end: + bl main diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..4817e68 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,16 @@ +#![no_main] +#![no_std] + +use core::{arch::global_asm, panic::PanicInfo}; + +global_asm!(include_str!("bootstrap.s")); + +#[panic_handler] +fn panic(_: &PanicInfo<'_>) -> ! { + loop {} +} + +#[no_mangle] +fn main() -> ! { + loop {} +}