Initial Cortex-M4F bootstrap code

This commit is contained in:
Victor Mignot 2024-08-18 22:04:55 +02:00
commit 5f62d443dc
Signed by: dala
GPG key ID: 5E7F2CE1BEAFED3D
8 changed files with 220 additions and 0 deletions

5
.cargo/config.toml Normal file
View file

@ -0,0 +1,5 @@
[build]
target = "thumbv7em-none-eabihf"
[target.thumbv7em-none-eabihf]
rustflags = ["-C", "link-arg=-Tlink.x"]

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/target

7
Cargo.lock generated Normal file
View file

@ -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"

11
Cargo.toml Normal file
View file

@ -0,0 +1,11 @@
[package]
name = "wocchi"
version = "0.1.0"
edition = "2021"
[dependencies]
[[bin]]
name = "wocchi"
test = false
bench = false

66
link.x Normal file
View file

@ -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.*);
}
}

22
shell.nix Normal file
View file

@ -0,0 +1,22 @@
let
pkgs = import <nixpkgs> {
crossSystem = (import <nixpkgs/lib>).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";
};
}

92
src/bootstrap.s Normal file
View file

@ -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

16
src/main.rs Normal file
View file

@ -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 {}
}