diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0982a1c0..b5027fcc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,14 +26,11 @@ jobs: # Build the workspace for a target architecture using the MSRV build-tier2-msrv: runs-on: ubuntu-24.04 + timeout-minutes: 10 needs: setup strategy: matrix: target: ${{ fromJSON(needs.setup.outputs.msrv-targets) }} - action: - - build - - clippy - - doc steps: - name: Checkout uses: actions/checkout@v7 @@ -43,21 +40,25 @@ jobs: run: | rustup install 1.93 rustup target add ${{ matrix.target }} --toolchain=1.93 - - name: Run just + rustup component add clippy --toolchain=1.93 + - name: Run build run: | - RUSTUP_TOOLCHAIN=1.93 just ${{ matrix.action }}-tier2 ${{ matrix.target }} + RUSTUP_TOOLCHAIN=1.93 just build-tier2 ${{ matrix.target }} + - name: Run clippy + run: | + RUSTUP_TOOLCHAIN=1.93 just clippy-tier2 ${{ matrix.target }} + - name: Run doc + run: | + RUSTUP_TOOLCHAIN=1.93 just doc-tier2 ${{ matrix.target }} # Build the workspace for a target architecture using latest stable build-tier2-stable: runs-on: ubuntu-24.04 + timeout-minutes: 10 needs: setup strategy: matrix: target: ${{ fromJSON(needs.setup.outputs.stable-targets) }} - action: - - build - - clippy - - doc steps: - name: Checkout uses: actions/checkout@v7 @@ -67,73 +68,90 @@ jobs: run: | rustup install stable rustup target add ${{ matrix.target }} --toolchain=stable - - name: Run just + rustup component add clippy --toolchain=stable + - name: Run build + run: | + RUSTUP_TOOLCHAIN=stable just build-tier2 ${{ matrix.target }} + - name: Run clippy + run: | + RUSTUP_TOOLCHAIN=stable just clippy-tier2 ${{ matrix.target }} + - name: Run doc run: | - RUSTUP_TOOLCHAIN=stable just ${{ matrix.action }}-tier2 ${{ matrix.target }} + RUSTUP_TOOLCHAIN=stable just doc-tier2 ${{ matrix.target }} # Build the workspace for all tier2 target architectures using rust-toolchain.toml build-tier2-nightly: runs-on: ubuntu-24.04 + timeout-minutes: 10 needs: setup strategy: matrix: target: ${{ fromJSON(needs.setup.outputs.nightly-tier2-targets) }} - action: - - build - - clippy - - doc steps: - name: Checkout uses: actions/checkout@v7 - name: Install Just uses: taiki-e/install-action@just - - name: Run just + - name: Run build + run: | + just build-tier2 ${{ matrix.target }} + - name: Run clippy + run: | + just clippy-tier2 ${{ matrix.target }} + - name: Run doc run: | - just ${{ matrix.action }}-tier2 ${{ matrix.target }} + just doc-tier2 ${{ matrix.target }} # Build the workspace for all tier3 target architectures using rust-toolchain.toml build-tier3-nightly: runs-on: ubuntu-24.04 + timeout-minutes: 10 needs: setup strategy: matrix: target: ${{ fromJSON(needs.setup.outputs.nightly-tier3-targets) }} - action: - - build - - clippy - - doc steps: - name: Checkout uses: actions/checkout@v7 - name: Install Just uses: taiki-e/install-action@just - - name: Run just + - name: Run build + run: | + just build-tier3 ${{ matrix.target }} + - name: Run clippy run: | - just ${{ matrix.action }}-tier3 ${{ matrix.target }} + just clippy-tier3 ${{ matrix.target }} + - name: Run doc + run: | + just doc-tier3 ${{ matrix.target }} # Build the workspace for all tier3 non atomic target architectures using rust-toolchain.toml build-tier3-no-atomics: runs-on: ubuntu-24.04 + timeout-minutes: 10 needs: setup strategy: matrix: target: ${{ fromJSON(needs.setup.outputs.nightly-tier3-noatomic-targets) }} - action: - - build - - clippy - - doc steps: - name: Checkout uses: actions/checkout@v7 - name: Install Just uses: taiki-e/install-action@just - - name: Run just + - name: Run build + run: | + just build-tier3-no-atomics ${{ matrix.target }} + - name: Run clippy + run: | + just clippy-tier3-no-atomics ${{ matrix.target }} + - name: Run doc run: | - just ${{ matrix.action }}-tier3-no-atomics ${{ matrix.target }} + just doc-tier3-no-atomics ${{ matrix.target }} # Build the host-only stuff on stable and MSRV build-arm-targets: runs-on: ubuntu-24.04 + timeout-minutes: 10 needs: setup strategy: matrix: @@ -165,6 +183,7 @@ jobs: # Gather all the above build jobs together for the purposes of getting an overall pass-fail build-all: runs-on: ubuntu-24.04 + timeout-minutes: 10 needs: - build-tier2-msrv - build-tier2-stable @@ -178,6 +197,7 @@ jobs: # Format the workspace fmt-check: runs-on: ubuntu-24.04 + timeout-minutes: 10 needs: setup steps: - name: Checkout @@ -191,6 +211,7 @@ jobs: # Run clippy on the examples clippy-examples: runs-on: ubuntu-24.04 + timeout-minutes: 10 needs: setup steps: - name: Checkout @@ -208,6 +229,7 @@ jobs: # Run the unit tests test-cargo: runs-on: ubuntu-24.04 + timeout-minutes: 10 needs: setup steps: - name: Checkout @@ -221,6 +243,7 @@ jobs: # Run some programs in QEMU 9 test-qemu: runs-on: ubuntu-24.04 + timeout-minutes: 10 needs: setup strategy: matrix: diff --git a/aarch32-tests/tests/tests.rs b/aarch32-tests/tests/tests.rs index fe33b3a2..73a11545 100644 --- a/aarch32-tests/tests/tests.rs +++ b/aarch32-tests/tests/tests.rs @@ -137,25 +137,26 @@ fn main() { for group in MATRIX { for &target in group.targets { for variant in group.variants { - let mut name = format!("{}/{}", group.example, target); - if !variant.label.is_empty() { - name.push_str(&format!(" [{}]", variant.label)); - } - let example = group.example; - let target = target.to_string(); let rustflags = group.rustflags; - let flags: Vec<&'static str> = group - .flags - .iter() - .chain(variant.extra_flags) - .copied() - .collect(); - - tests.push(Trial::test(name, move || { - run_target(example, &target, &flags, rustflags); - Ok(()) - })); + let dir = test_utils::test_dir(&format!("examples/{example}")); + for bin in test_utils::discover_bins(&dir) { + let target = target.to_string(); + let flags: Vec<&'static str> = group + .flags + .iter() + .chain(variant.extra_flags) + .copied() + .collect(); + let mut name = format!("{}/{}/{}", group.example, target, bin); + if !variant.label.is_empty() { + name.push_str(&format!(" [{}]", variant.label)); + } + tests.push(Trial::test(name, move || { + run_target_bin(example, &bin, &target, &flags, rustflags); + Ok(()) + })); + } } } } @@ -163,7 +164,7 @@ fn main() { libtest_mimic::run(&args, tests).exit(); } -fn run_target(example: &str, target: &str, flags: &[&str], rustflags: Option<&str>) { +fn run_target_bin(example: &str, bin: &str, target: &str, flags: &[&str], rustflags: Option<&str>) { let dir = test_utils::test_dir(&format!("examples/{example}")); // Per-example folder: snapshots//-.snap @@ -174,8 +175,6 @@ fn run_target(example: &str, target: &str, flags: &[&str], rustflags: Option<&st settings.set_prepend_module_to_snapshot(false); let _guard = settings.bind_to_scope(); - for bin in test_utils::discover_bins(&dir) { - let stdout = test_utils::run_bin(&dir, &bin, target, flags, rustflags); - insta::assert_snapshot!(format!("{bin}-{target}"), stdout); - } + let stdout = test_utils::run_bin(&dir, &bin, target, flags, rustflags); + insta::assert_snapshot!(format!("{bin}-{target}"), stdout); } diff --git a/examples/mps3-an536-el2/memory.x b/examples/mps3-an536-el2/memory.x index 89a0be65..91e74004 100644 --- a/examples/mps3-an536-el2/memory.x +++ b/examples/mps3-an536-el2/memory.x @@ -23,4 +23,18 @@ PROVIDE(_irq_stack_size = 8); PROVIDE(_fiq_stack_size = 8); PROVIDE(_sys_stack_size = 8); -PROVIDE(_num_cores = 2); \ No newline at end of file +PROVIDE(_num_cores = 2); + +EXTERN(_unexpected_undefined_exception_handler); +EXTERN(_unexpected_svc_exception_handler); +EXTERN(_unexpected_hvc_exception_handler); +EXTERN(_unexpected_prefetch_abort_exception_handler); +EXTERN(_unexpected_data_abort_exception_handler); +EXTERN(_unexpected_irq_exception_handler); + +PROVIDE(_undefined_handler = _unexpected_undefined_exception_handler); +PROVIDE(_svc_handler = _unexpected_svc_exception_handler); +PROVIDE(_hvc_handler = _unexpected_hvc_exception_handler); +PROVIDE(_prefetch_abort_handler = _unexpected_prefetch_abort_exception_handler); +PROVIDE(_data_abort_handler = _unexpected_data_abort_exception_handler); +PROVIDE(_irq_handler = _unexpected_irq_exception_handler); diff --git a/examples/mps3-an536-el2/src/lib.rs b/examples/mps3-an536-el2/src/lib.rs index 604ca126..57ebc6ae 100644 --- a/examples/mps3-an536-el2/src/lib.rs +++ b/examples/mps3-an536-el2/src/lib.rs @@ -254,3 +254,39 @@ unsafe fn make_gic() -> arm_gic::gicv3::GicV3<'static> { arm_gic::gicv3::GicCpuInterface::set_priority_mask(0x80); gic } + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_undefined_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_undefined_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_svc_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_svc_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_hvc_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_hvc_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_prefetch_abort_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_prefetch_abort_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_data_abort_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_data_abort_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_irq_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_irq_exception_handler!"); + semihosting::process::exit(1); +} diff --git a/examples/mps3-an536/memory.x b/examples/mps3-an536/memory.x index aefc73c5..8f52ae80 100644 --- a/examples/mps3-an536/memory.x +++ b/examples/mps3-an536/memory.x @@ -46,3 +46,17 @@ PROVIDE(_inter_stack_padding = 64); PROVIDE(_region_alignment = 64K); PROVIDE(_num_cores = 2); + +EXTERN(_unexpected_undefined_exception_handler); +EXTERN(_unexpected_svc_exception_handler); +EXTERN(_unexpected_hvc_exception_handler); +EXTERN(_unexpected_prefetch_abort_exception_handler); +EXTERN(_unexpected_data_abort_exception_handler); +EXTERN(_unexpected_irq_exception_handler); + +PROVIDE(_undefined_handler = _unexpected_undefined_exception_handler); +PROVIDE(_svc_handler = _unexpected_svc_exception_handler); +PROVIDE(_hvc_handler = _unexpected_hvc_exception_handler); +PROVIDE(_prefetch_abort_handler = _unexpected_prefetch_abort_exception_handler); +PROVIDE(_data_abort_handler = _unexpected_data_abort_exception_handler); +PROVIDE(_irq_handler = _unexpected_irq_exception_handler); diff --git a/examples/mps3-an536/src/lib.rs b/examples/mps3-an536/src/lib.rs index 2d7bf4c3..f441bb1f 100644 --- a/examples/mps3-an536/src/lib.rs +++ b/examples/mps3-an536/src/lib.rs @@ -298,3 +298,39 @@ pub extern "C" fn _asm_secondary_core_park() { fpga_led = const FPGA_LED ); } + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_undefined_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_undefined_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_svc_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_svc_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_hvc_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_hvc_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_prefetch_abort_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_prefetch_abort_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_data_abort_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_data_abort_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_irq_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_irq_exception_handler!"); + semihosting::process::exit(1); +} diff --git a/examples/versatileab/memory.x b/examples/versatileab/memory.x index 65a2a3d9..eec1806a 100644 --- a/examples/versatileab/memory.x +++ b/examples/versatileab/memory.x @@ -20,3 +20,18 @@ PROVIDE(_abt_stack_size = 16K); PROVIDE(_irq_stack_size = 64); PROVIDE(_fiq_stack_size = 64); PROVIDE(_sys_stack_size = 16K); + +EXTERN(_unexpected_undefined_exception_handler); +EXTERN(_unexpected_svc_exception_handler); +EXTERN(_unexpected_hvc_exception_handler); +EXTERN(_unexpected_prefetch_abort_exception_handler); +EXTERN(_unexpected_data_abort_exception_handler); +EXTERN(_unexpected_irq_exception_handler); + +PROVIDE(_undefined_handler = _unexpected_undefined_exception_handler); +PROVIDE(_svc_handler = _unexpected_svc_exception_handler); +PROVIDE(_hvc_handler = _unexpected_hvc_exception_handler); +PROVIDE(_prefetch_abort_handler = _unexpected_prefetch_abort_exception_handler); +PROVIDE(_data_abort_handler = _unexpected_data_abort_exception_handler); +PROVIDE(_irq_handler = _unexpected_irq_exception_handler); + diff --git a/examples/versatileab/src/lib.rs b/examples/versatileab/src/lib.rs index 3d6ff6e9..a233e7d7 100644 --- a/examples/versatileab/src/lib.rs +++ b/examples/versatileab/src/lib.rs @@ -103,3 +103,39 @@ fn stack_dump() { } } } + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_undefined_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_undefined_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_svc_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_svc_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_hvc_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_hvc_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_prefetch_abort_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_prefetch_abort_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_data_abort_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_data_abort_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_irq_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_irq_exception_handler!"); + semihosting::process::exit(1); +} diff --git a/examples/xilinx-zynq-a9/memory.x b/examples/xilinx-zynq-a9/memory.x index 13de51cd..8667b2c5 100644 --- a/examples/xilinx-zynq-a9/memory.x +++ b/examples/xilinx-zynq-a9/memory.x @@ -27,3 +27,17 @@ PROVIDE(_sys_stack_size = 16K); /* This is a dual-core Cortex-A9, so reserve a set of stacks per core. */ PROVIDE(_num_cores = 2); + +EXTERN(_unexpected_undefined_exception_handler); +EXTERN(_unexpected_svc_exception_handler); +EXTERN(_unexpected_hvc_exception_handler); +EXTERN(_unexpected_prefetch_abort_exception_handler); +EXTERN(_unexpected_data_abort_exception_handler); +EXTERN(_unexpected_irq_exception_handler); + +PROVIDE(_undefined_handler = _unexpected_undefined_exception_handler); +PROVIDE(_svc_handler = _unexpected_svc_exception_handler); +PROVIDE(_hvc_handler = _unexpected_hvc_exception_handler); +PROVIDE(_prefetch_abort_handler = _unexpected_prefetch_abort_exception_handler); +PROVIDE(_data_abort_handler = _unexpected_data_abort_exception_handler); +PROVIDE(_irq_handler = _unexpected_irq_exception_handler); diff --git a/examples/xilinx-zynq-a9/src/lib.rs b/examples/xilinx-zynq-a9/src/lib.rs index ffde4ec7..5e3fd2cb 100644 --- a/examples/xilinx-zynq-a9/src/lib.rs +++ b/examples/xilinx-zynq-a9/src/lib.rs @@ -187,3 +187,39 @@ pub unsafe fn make_gic() -> arm_gic::gicv2::GicV2<'static> { gic.setup(); gic } + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_undefined_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_undefined_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_svc_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_svc_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_hvc_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_hvc_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_prefetch_abort_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_prefetch_abort_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_data_abort_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_data_abort_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_irq_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_irq_exception_handler!"); + semihosting::process::exit(1); +} diff --git a/justfile b/justfile index 07c293e1..7d851ce4 100644 --- a/justfile +++ b/justfile @@ -238,9 +238,9 @@ clippy-tier3 target: # Checks all the cross-compiled workspace passes the clippy lints clippy-tier2 target: - cargo build --target {{target}} {{verbose}} - cargo build --target {{target}} --features "serde, defmt, critical-section-multi-core, check-asm" {{verbose}} - cargo build --target {{target}} --features "serde, defmt, critical-section-single-core, check-asm" {{verbose}} + cargo clippy --target {{target}} {{verbose}} + cargo clippy --target {{target}} --features "serde, defmt, critical-section-multi-core, check-asm" {{verbose}} + cargo clippy --target {{target}} --features "serde, defmt, critical-section-single-core, check-asm" {{verbose}} # Run all the tests test: test-cargo test-qemu