Tested Spimonitor with Emulated BMC master for write protected region.
diff --git a/target/ast10x0/board/src/spim_wiring.rs b/target/ast10x0/board/src/spim_wiring.rs
index 1348917..f540d52 100644
--- a/target/ast10x0/board/src/spim_wiring.rs
+++ b/target/ast10x0/board/src/spim_wiring.rs
@@ -339,7 +339,7 @@
         let mut policy = profile::zephyr_default();
         let _ = policy.add_region(
             0,
-            0x0800_0000,
+            0x0010_0000,
             PrivilegeDirection::Write,
             PrivilegeOp::Disable,
         );
diff --git a/target/ast10x0/tests/spimonitor/BUILD.bazel b/target/ast10x0/tests/spimonitor/BUILD.bazel
index 5d961b1..47f0d66 100644
--- a/target/ast10x0/tests/spimonitor/BUILD.bazel
+++ b/target/ast10x0/tests/spimonitor/BUILD.bazel
@@ -1,12 +1,10 @@
 # Licensed under the Apache-2.0 license
 # SPDX-License-Identifier: Apache-2.0
 
-load("@pigweed//pw_kernel/tooling:system_image.bzl", "system_image", "system_image_test")
 load("@pigweed//pw_kernel/tooling:target_codegen.bzl", "target_codegen")
 load("@pigweed//pw_kernel/tooling:target_linker_script.bzl", "target_linker_script")
-load("@pigweed//pw_kernel/tooling/panic_detector:rust_binary_no_panics_test.bzl", "rust_binary_no_panics_test")
-load("@rules_rust//rust:defs.bzl", "rust_binary")
 load("//target/ast10x0:defs.bzl", "TARGET_COMPATIBLE_WITH")
+load(":spimonitor_test.bzl", "spimonitor_setup_all", "spimonitor_test")
 
 filegroup(
     name = "system_config",
@@ -28,48 +26,20 @@
     template = "//target/ast10x0:linker_script_template",
 )
 
-rust_binary(
+spimonitor_test(1, TARGET_COMPATIBLE_WITH)
+spimonitor_test(2, TARGET_COMPATIBLE_WITH)
+spimonitor_test(3, TARGET_COMPATIBLE_WITH)
+spimonitor_test(4, TARGET_COMPATIBLE_WITH)
+spimonitor_setup_all(TARGET_COMPATIBLE_WITH)
+
+alias(
     name = "target",
-    srcs = ["target.rs"],
-    edition = "2024",
-    tags = ["kernel"],
-    target_compatible_with = TARGET_COMPATIBLE_WITH,
-    deps = [
-        ":codegen",
-        ":linker_script",
-        "//target/ast10x0:entry",
-        "//target/ast10x0/board:ast10x0_board",
-        "//target/ast10x0/peripherals",
-        "@pigweed//pw_kernel/subsys/console:console_backend",
-        "@pigweed//pw_kernel/target:target_common",
-        "@pigweed//pw_log/rust:pw_log",
-    ],
+    actual = ":target_spim1",
+    visibility = ["//visibility:public"],
 )
 
-system_image(
+alias(
     name = "spimonitor_test",
-    kernel = ":target",
-    platform = "//target/ast10x0",
-    system_config = ":system_config",
-    tags = ["kernel"],
-    target_compatible_with = TARGET_COMPATIBLE_WITH,
-    userspace = False,
+    actual = ":spimonitor1_test",
     visibility = ["//visibility:public"],
 )
-
-system_image_test(
-    name = "spimonitor_evb_test",
-    image = ":spimonitor_test",
-    tags = ["hardware"],
-    target_compatible_with = select({
-        "//target/ast10x0:qemu_enabled": ["@platforms//:incompatible"],
-        "//conditions:default": [],
-    }),
-    visibility = ["//visibility:public"],
-)
-
-rust_binary_no_panics_test(
-    name = "no_panics_test",
-    binary = ":spimonitor_test",
-    tags = ["kernel"],
-)
diff --git a/target/ast10x0/tests/spimonitor/setup_all_spim.rs b/target/ast10x0/tests/spimonitor/setup_all_spim.rs
new file mode 100644
index 0000000..a041959
--- /dev/null
+++ b/target/ast10x0/tests/spimonitor/setup_all_spim.rs
@@ -0,0 +1,142 @@
+// Licensed under the Apache-2.0 license
+// SPDX-License-Identifier: Apache-2.0
+
+//! Configure SPIM1 through SPIM4 and keep all monitors active.
+
+#![no_std]
+#![no_main]
+
+use core::cell::UnsafeCell;
+
+#[path = "test_common.rs"]
+mod test_common;
+
+use ast10x0_peripherals::scu::{ScuRegisters, SpiMonitorInstance};
+use ast10x0_peripherals::spimonitor::{
+    MonitorPolicy, PrivilegeDirection, PrivilegeOp, SpiMonitorController,
+};
+use target_common::{declare_target, TargetInterface};
+use {console_backend as _, entry as _};
+
+struct Spim1Config;
+struct Spim2Config;
+struct Spim3Config;
+struct Spim4Config;
+
+impl test_common::TestConfig for Spim1Config {
+    const INSTANCE: SpiMonitorInstance = SpiMonitorInstance::Spim0;
+    const CONTROLLER: SpiMonitorController = SpiMonitorController::Spim0;
+}
+
+impl test_common::TestConfig for Spim2Config {
+    const INSTANCE: SpiMonitorInstance = SpiMonitorInstance::Spim1;
+    const CONTROLLER: SpiMonitorController = SpiMonitorController::Spim1;
+}
+
+impl test_common::TestConfig for Spim3Config {
+    const INSTANCE: SpiMonitorInstance = SpiMonitorInstance::Spim2;
+    const CONTROLLER: SpiMonitorController = SpiMonitorController::Spim2;
+}
+
+impl test_common::TestConfig for Spim4Config {
+    const INSTANCE: SpiMonitorInstance = SpiMonitorInstance::Spim3;
+    const CONTROLLER: SpiMonitorController = SpiMonitorController::Spim3;
+}
+
+#[repr(align(16))]
+struct LogRam(UnsafeCell<[u32; test_common::LOG_RAM_WORDS]>);
+
+// SAFETY: Each buffer is exclusively assigned to one SPIPF instance.
+unsafe impl Sync for LogRam {}
+
+static SPIM1_LOG: LogRam = LogRam(UnsafeCell::new([0; test_common::LOG_RAM_WORDS]));
+static SPIM2_LOG: LogRam = LogRam(UnsafeCell::new([0; test_common::LOG_RAM_WORDS]));
+static SPIM3_LOG: LogRam = LogRam(UnsafeCell::new([0; test_common::LOG_RAM_WORDS]));
+static SPIM4_LOG: LogRam = LogRam(UnsafeCell::new([0; test_common::LOG_RAM_WORDS]));
+
+const WRITE_PROTECTED_LENGTH: u32 = 0x0010_0000;
+const ALLOW_COMMANDS: [u8; 32] = [
+    0x03, 0x13, 0x0b, 0x0c, 0x6b, 0x6c, 0x01, 0x05, 0x35, 0x06, 0x04, 0x20, 0x21, 0x9f, 0x5a,
+    0xb7, 0xe9, 0x32, 0x34, 0xd8, 0xdc, 0x02, 0x12, 0x3b, 0x3c, 0x70, 0xbb, 0xbc, 0x50, 0xeb,
+    0xec, 0xc2,
+];
+
+fn log_buffer(log: &'static LogRam) -> &'static mut [u32] {
+    // SAFETY: The caller assigns each static buffer to exactly one monitor.
+    unsafe { &mut *log.0.get() }
+}
+
+fn production_policy() -> MonitorPolicy {
+    let mut policy = MonitorPolicy::empty();
+    policy.allow_commands.copy_from_slice(&ALLOW_COMMANDS);
+    policy.allow_command_count = ALLOW_COMMANDS.len();
+    let _ = policy.add_region(
+        0,
+        WRITE_PROTECTED_LENGTH,
+        PrivilegeDirection::Write,
+        PrivilegeOp::Disable,
+    );
+    policy
+}
+
+fn setup_all_spim() -> Result<(), test_common::TestError> {
+    let scu = unsafe { ScuRegisters::new_global_unlocked() };
+    let policy = production_policy();
+
+    pw_log::info!("=== SPIM1 ===");
+    test_common::configure_wiring::<Spim1Config>(&scu)?;
+    let spim1 = test_common::initialize_monitor_with_policy::<Spim1Config>(
+        log_buffer(&SPIM1_LOG),
+        &policy,
+    )?;
+    test_common::dump_policy(&spim1, WRITE_PROTECTED_LENGTH)?;
+    let _spim1 = test_common::lock_monitor(spim1)?;
+
+    pw_log::info!("=== SPIM2 ===");
+    test_common::configure_wiring::<Spim2Config>(&scu)?;
+    let spim2 = test_common::initialize_monitor_with_policy::<Spim2Config>(
+        log_buffer(&SPIM2_LOG),
+        &policy,
+    )?;
+    test_common::dump_policy(&spim2, WRITE_PROTECTED_LENGTH)?;
+    let _spim2 = test_common::lock_monitor(spim2)?;
+
+    pw_log::info!("=== SPIM3 ===");
+    test_common::configure_wiring::<Spim3Config>(&scu)?;
+    let spim3 = test_common::initialize_monitor_with_policy::<Spim3Config>(
+        log_buffer(&SPIM3_LOG),
+        &policy,
+    )?;
+    test_common::dump_policy(&spim3, WRITE_PROTECTED_LENGTH)?;
+    let _spim3 = test_common::lock_monitor(spim3)?;
+
+    pw_log::info!("=== SPIM4 ===");
+    test_common::configure_wiring::<Spim4Config>(&scu)?;
+    let spim4 = test_common::initialize_monitor_with_policy::<Spim4Config>(
+        log_buffer(&SPIM4_LOG),
+        &policy,
+    )?;
+    test_common::dump_policy(&spim4, WRITE_PROTECTED_LENGTH)?;
+    let _spim4 = test_common::lock_monitor(spim4)?;
+
+    pw_log::info!("All SPIM1-4 monitors are configured and locked");
+    pw_log::info!("Firmware will remain active until the user stops or resets it");
+    Ok(())
+}
+
+struct Target;
+
+impl TargetInterface for Target {
+    const NAME: &'static str = "AST10x0 Setup All External SPI Monitors";
+
+    fn main() -> ! {
+        if setup_all_spim().is_err() {
+            pw_log::info!("FAIL: setup all SPIM monitors");
+        }
+
+        #[expect(clippy::empty_loop)]
+        loop {}
+    }
+}
+
+declare_target!(Target);
diff --git a/target/ast10x0/tests/spimonitor/spimonitor_test.bzl b/target/ast10x0/tests/spimonitor/spimonitor_test.bzl
new file mode 100644
index 0000000..e229ed1
--- /dev/null
+++ b/target/ast10x0/tests/spimonitor/spimonitor_test.bzl
@@ -0,0 +1,100 @@
+# Licensed under the Apache-2.0 license
+# SPDX-License-Identifier: Apache-2.0
+
+load("@pigweed//pw_kernel/tooling:system_image.bzl", "system_image", "system_image_test")
+load("@pigweed//pw_kernel/tooling/panic_detector:rust_binary_no_panics_test.bzl", "rust_binary_no_panics_test")
+load("@rules_rust//rust:defs.bzl", "rust_binary")
+
+def spimonitor_test(index, target_compatible_with):
+    target_name = "target_spim{}".format(index)
+    image_name = "spimonitor{}_test".format(index)
+
+    rust_binary(
+        name = target_name,
+        srcs = [
+            "test_common.rs",
+            "test_spim{}.rs".format(index),
+        ],
+        crate_root = "test_spim{}.rs".format(index),
+        edition = "2024",
+        tags = ["kernel"],
+        target_compatible_with = target_compatible_with,
+        deps = [
+            ":codegen",
+            ":linker_script",
+            "//target/ast10x0:entry",
+            "//target/ast10x0/board:ast10x0_board",
+            "//target/ast10x0/peripherals",
+            "@pigweed//pw_kernel/subsys/console:console_backend",
+            "@pigweed//pw_kernel/target:target_common",
+            "@pigweed//pw_log/rust:pw_log",
+        ],
+    )
+
+    system_image(
+        name = image_name,
+        kernel = ":" + target_name,
+        platform = "//target/ast10x0",
+        system_config = ":system_config",
+        tags = ["kernel"],
+        target_compatible_with = target_compatible_with,
+        userspace = False,
+        visibility = ["//visibility:public"],
+    )
+
+    system_image_test(
+        name = "spimonitor{}_evb_test".format(index),
+        image = ":" + image_name,
+        tags = ["hardware"],
+        target_compatible_with = select({
+            "//target/ast10x0:qemu_enabled": ["@platforms//:incompatible"],
+            "//conditions:default": [],
+        }),
+        visibility = ["//visibility:public"],
+    )
+
+    rust_binary_no_panics_test(
+        name = "spimonitor{}_no_panics_test".format(index),
+        binary = ":" + image_name,
+        tags = ["kernel"],
+    )
+
+def spimonitor_setup_all(target_compatible_with):
+    rust_binary(
+        name = "setup_all_spim",
+        srcs = [
+            "setup_all_spim.rs",
+            "test_common.rs",
+        ],
+        crate_root = "setup_all_spim.rs",
+        edition = "2024",
+        tags = ["kernel"],
+        target_compatible_with = target_compatible_with,
+        deps = [
+            ":codegen",
+            ":linker_script",
+            "//target/ast10x0:entry",
+            "//target/ast10x0/board:ast10x0_board",
+            "//target/ast10x0/peripherals",
+            "@pigweed//pw_kernel/subsys/console:console_backend",
+            "@pigweed//pw_kernel/target:target_common",
+            "@pigweed//pw_log/rust:pw_log",
+        ],
+    )
+
+    system_image(
+        name = "setup_all_spim_image",
+        kernel = ":setup_all_spim",
+        platform = "//target/ast10x0",
+        system_config = ":system_config",
+        tags = ["kernel"],
+        target_compatible_with = target_compatible_with,
+        userspace = False,
+        visibility = ["//visibility:public"],
+    )
+
+    rust_binary_no_panics_test(
+        name = "setup_all_spim_no_panics_test",
+        binary = ":setup_all_spim_image",
+        tags = ["kernel"],
+    )
diff --git a/target/ast10x0/tests/spimonitor/target.rs b/target/ast10x0/tests/spimonitor/test_common.rs
similarity index 71%
rename from target/ast10x0/tests/spimonitor/target.rs
rename to target/ast10x0/tests/spimonitor/test_common.rs
index 3792b23..d252f89 100644
--- a/target/ast10x0/tests/spimonitor/target.rs
+++ b/target/ast10x0/tests/spimonitor/test_common.rs
@@ -1,10 +1,9 @@
 // Licensed under the Apache-2.0 license
 // SPDX-License-Identifier: Apache-2.0
 
-//! AST10x0 SPI monitor configuration hardware test.
+//! Shared AST10x0 external SPI monitor configuration tests.
 
-#![no_std]
-#![no_main]
+#![allow(dead_code)]
 
 use core::cell::UnsafeCell;
 
@@ -20,30 +19,29 @@
     PrivilegeDirection, PrivilegeOp, SpiMonitor, SpiMonitorController, SpiMonitorError,
     Uninitialized,
 };
-use console_backend::console_backend_write_all;
-use target_common::{declare_target, TargetInterface};
-use {console_backend as _, entry as _};
 
-pub struct Target {}
-
-const SPIM: SpiMonitorInstance = SpiMonitorInstance::Spim0;
-const PROTECTED_LENGTH: u32 = 0x0010_0000;
+pub const PROTECTED_LENGTH: u32 = 0x0010_0000;
 const LOG_RAM_BYTES: usize = 0x200;
-const LOG_RAM_WORDS: usize = LOG_RAM_BYTES / core::mem::size_of::<u32>();
+pub const LOG_RAM_WORDS: usize = LOG_RAM_BYTES / core::mem::size_of::<u32>();
 const COMMAND_VALID_MASK: u32 = (1 << 30) | (1 << 31);
 const COMMAND_LOCKED: u32 = 1 << 23;
 const LOCK_REQUIRED: u32 = (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 30) | (1 << 31);
 
+pub trait TestConfig {
+    const INSTANCE: SpiMonitorInstance;
+    const CONTROLLER: SpiMonitorController;
+}
+
 #[repr(align(16))]
 struct LogRam(UnsafeCell<[u32; LOG_RAM_WORDS]>);
 
-// SAFETY: This test is single-threaded and gives the buffer exclusively to SPIPF.
+// SAFETY: Each test image is single-threaded and owns one SPIPF log buffer.
 unsafe impl Sync for LogRam {}
 
 static LOG_RAM: LogRam = LogRam(UnsafeCell::new([0; LOG_RAM_WORDS]));
 
 #[derive(Clone, Copy)]
-enum TestError {
+pub enum TestError {
     Monitor,
     Scu,
     Check,
@@ -75,36 +73,34 @@
     unsafe { &mut *LOG_RAM.0.get() }
 }
 
-fn configure_wiring(scu: &ScuRegisters) -> Result<(), TestError> {
+pub fn configure_wiring<C: TestConfig>(scu: &ScuRegisters) -> Result<(), TestError> {
     pw_log::info!("START: external monitor pinctrl, routing, and mux");
-    apply_spim_pinctrl(scu, SPIM);
-    scu.disable_spim_cs_internal_pull_down(SPIM);
+    apply_spim_pinctrl(scu, C::INSTANCE);
+    scu.disable_spim_cs_internal_pull_down(C::INSTANCE);
 
-    // SPIPF observes external BMC/host traffic. Do not detour SPI1 or SPI2
-    // internally into the monitor.
+    // SPIPF observes external BMC/host traffic. Do not detour SPI1 or SPI2.
     scu.set_spim_internal_mux(SpiMonitorSource::Spi1, 0)?;
     test_check!(
         scu.route_control_raw() & 0x0f == 0,
         "FAIL: internal SPI master detour is enabled"
     );
 
-    // This SCU bit enables the SPIPF signal path. Controller bypass/filtering
-    // is controlled independently by SPIPF000[1:0].
-    scu.set_spim_passthrough(SPIM, SpiMonitorPassthrough::Enabled);
-    scu.set_spim_miso_multi_func(SPIM, true);
-    scu.set_spim_filter(SPIM, true);
+    // SCU passthrough enables the external signal path through SPIPF.
+    scu.set_spim_passthrough(C::INSTANCE, SpiMonitorPassthrough::Enabled);
+    scu.set_spim_miso_multi_func(C::INSTANCE, true);
+    scu.set_spim_filter(C::INSTANCE, true);
 
-    apply_spim_external_mux(SPIM, ScuExtMuxSelect::Mux0);
+    apply_spim_external_mux(C::INSTANCE, ScuExtMuxSelect::Mux0);
     test_check!(
-        spim_external_mux_state(SPIM) == Some(ScuExtMuxSelect::Mux0),
+        spim_external_mux_state(C::INSTANCE) == Some(ScuExtMuxSelect::Mux0),
         "FAIL: external mux 0 GPIO readback"
     );
-    apply_spim_external_mux(SPIM, ScuExtMuxSelect::Mux1);
+    apply_spim_external_mux(C::INSTANCE, ScuExtMuxSelect::Mux1);
     test_check!(
-        spim_external_mux_state(SPIM) == Some(ScuExtMuxSelect::Mux1),
+        spim_external_mux_state(C::INSTANCE) == Some(ScuExtMuxSelect::Mux1),
         "FAIL: external mux 1 GPIO readback"
     );
-    scu.set_spim_ext_mux(SPIM, ScuExtMuxSelect::Mux1);
+    scu.set_spim_ext_mux(C::INSTANCE, ScuExtMuxSelect::Mux1);
 
     test_check!(
         scu.route_control_raw() & 0x0f == 0,
@@ -114,7 +110,7 @@
     Ok(())
 }
 
-fn build_policy() -> MonitorPolicy {
+pub fn build_policy() -> MonitorPolicy {
     let mut policy = MonitorPolicy::empty();
     policy.allow_commands[..9]
         .copy_from_slice(&[0x9f, 0x05, 0x06, 0x04, 0x02, 0x12, 0x20, 0x21, 0x0c]);
@@ -128,22 +124,31 @@
     policy
 }
 
-fn initialize_monitor() -> Result<ConfiguredSpiMonitor, TestError> {
+pub fn initialize_monitor<C: TestConfig>(
+    buffer: &'static mut [u32],
+) -> Result<ConfiguredSpiMonitor, TestError> {
+    initialize_monitor_with_policy::<C>(buffer, &build_policy())
+}
+
+pub fn initialize_monitor_with_policy<C: TestConfig>(
+    buffer: &'static mut [u32],
+    policy: &MonitorPolicy,
+) -> Result<ConfiguredSpiMonitor, TestError> {
     pw_log::info!("START: monitor reset, policy, and log RAM");
-    let monitor = unsafe { SpiMonitor::<Uninitialized>::new(SpiMonitorController::Spim0) };
+    let monitor = unsafe { SpiMonitor::<Uninitialized>::new(C::CONTROLLER) };
     monitor.software_reset();
     test_check!(
         monitor.regs().read_ctrl() & (1 << 15) == 0,
         "FAIL: software reset did not deassert"
     );
 
-    let configured = monitor.apply_policy(&build_policy())?;
+    let configured = monitor.apply_policy(policy)?;
     test_check!(
         configured.state() == MonitorState::Configured,
         "FAIL: monitor did not enter configured state"
     );
 
-    configured.configure_log(log_buffer())?;
+    configured.configure_log(buffer)?;
     test_check!(
         configured.regs().read_log_capacity_entries() as usize == LOG_RAM_WORDS,
         "FAIL: 0x200-byte log RAM configuration"
@@ -164,6 +169,38 @@
     Ok(configured)
 }
 
+#[allow(dead_code)]
+pub fn dump_policy(
+    configured: &ConfiguredSpiMonitor,
+    write_protected_length: u32,
+) -> Result<(), TestError> {
+    pw_log::info!("allow-command table:");
+    for slot in 0..32 {
+        let value = configured.regs().read_allow_cmd_slot(slot);
+        if value != 0 {
+            pw_log::info!(
+                "  slot {:02}: cmd=0x{:02x}, raw=0x{:08x}",
+                slot as u32,
+                (value & 0xff) as u32,
+                value as u32
+            );
+        }
+    }
+
+    pw_log::info!(
+        "write-protected region: start=0x00000000, length=0x{:08x}",
+        write_protected_length as u32
+    );
+    Ok(())
+}
+
+#[allow(dead_code)]
+pub fn lock_monitor(
+    configured: ConfiguredSpiMonitor,
+) -> Result<ast10x0_peripherals::spimonitor::LockedSpiMonitor, TestError> {
+    Ok(configured.lock()?)
+}
+
 fn test_passthrough_control(configured: &ConfiguredSpiMonitor) -> Result<(), TestError> {
     pw_log::info!("START: passthrough control readback");
     configured.set_passthrough(PassthroughMode::Enabled);
@@ -239,12 +276,12 @@
     Ok(())
 }
 
-fn run_spimonitor_test() -> Result<(), TestError> {
+pub fn run<C: TestConfig>() -> Result<(), TestError> {
     pw_log::info!("=== AST10x0 external SPI monitor configuration test ===");
 
     let scu = unsafe { ScuRegisters::new_global_unlocked() };
-    configure_wiring(&scu)?;
-    let configured = initialize_monitor()?;
+    configure_wiring::<C>(&scu)?;
+    let configured = initialize_monitor::<C>(log_buffer())?;
     test_passthrough_control(&configured)?;
     test_command_policy(&configured)?;
     test_address_policy(&configured)?;
@@ -254,21 +291,3 @@
     pw_log::info!("=== all SPI monitor configuration tests passed ===");
     Ok(())
 }
-
-impl TargetInterface for Target {
-    const NAME: &'static str = "AST10x0 External SPI Monitor Configuration Test";
-
-    fn main() -> ! {
-        let sentinel = if run_spimonitor_test().is_ok() {
-            b"TEST_RESULT:PASS\n"
-        } else {
-            b"TEST_RESULT:FAIL\n"
-        };
-        let _ = console_backend_write_all(sentinel);
-
-        #[expect(clippy::empty_loop)]
-        loop {}
-    }
-}
-
-declare_target!(Target);
diff --git a/target/ast10x0/tests/spimonitor/test_spim1.rs b/target/ast10x0/tests/spimonitor/test_spim1.rs
new file mode 100644
index 0000000..0aa6a20
--- /dev/null
+++ b/target/ast10x0/tests/spimonitor/test_spim1.rs
@@ -0,0 +1,40 @@
+// Licensed under the Apache-2.0 license
+// SPDX-License-Identifier: Apache-2.0
+
+#![no_std]
+#![no_main]
+
+#[path = "test_common.rs"]
+mod test_common;
+
+use ast10x0_peripherals::scu::SpiMonitorInstance;
+use ast10x0_peripherals::spimonitor::SpiMonitorController;
+use console_backend::console_backend_write_all;
+use target_common::{declare_target, TargetInterface};
+use {console_backend as _, entry as _};
+
+struct Spim1Config;
+
+impl test_common::TestConfig for Spim1Config {
+    const INSTANCE: SpiMonitorInstance = SpiMonitorInstance::Spim0;
+    const CONTROLLER: SpiMonitorController = SpiMonitorController::Spim0;
+}
+
+struct Target;
+
+impl TargetInterface for Target {
+    const NAME: &'static str = "AST10x0 External SPIM1 Configuration Test";
+
+    fn main() -> ! {
+        let sentinel = if test_common::run::<Spim1Config>().is_ok() {
+            b"TEST_RESULT:PASS\n"
+        } else {
+            b"TEST_RESULT:FAIL\n"
+        };
+        let _ = console_backend_write_all(sentinel);
+        #[expect(clippy::empty_loop)]
+        loop {}
+    }
+}
+
+declare_target!(Target);
diff --git a/target/ast10x0/tests/spimonitor/test_spim2.rs b/target/ast10x0/tests/spimonitor/test_spim2.rs
new file mode 100644
index 0000000..cae247c
--- /dev/null
+++ b/target/ast10x0/tests/spimonitor/test_spim2.rs
@@ -0,0 +1,40 @@
+// Licensed under the Apache-2.0 license
+// SPDX-License-Identifier: Apache-2.0
+
+#![no_std]
+#![no_main]
+
+#[path = "test_common.rs"]
+mod test_common;
+
+use ast10x0_peripherals::scu::SpiMonitorInstance;
+use ast10x0_peripherals::spimonitor::SpiMonitorController;
+use console_backend::console_backend_write_all;
+use target_common::{declare_target, TargetInterface};
+use {console_backend as _, entry as _};
+
+struct Spim2Config;
+
+impl test_common::TestConfig for Spim2Config {
+    const INSTANCE: SpiMonitorInstance = SpiMonitorInstance::Spim1;
+    const CONTROLLER: SpiMonitorController = SpiMonitorController::Spim1;
+}
+
+struct Target;
+
+impl TargetInterface for Target {
+    const NAME: &'static str = "AST10x0 External SPIM2 Configuration Test";
+
+    fn main() -> ! {
+        let sentinel = if test_common::run::<Spim2Config>().is_ok() {
+            b"TEST_RESULT:PASS\n"
+        } else {
+            b"TEST_RESULT:FAIL\n"
+        };
+        let _ = console_backend_write_all(sentinel);
+        #[expect(clippy::empty_loop)]
+        loop {}
+    }
+}
+
+declare_target!(Target);
diff --git a/target/ast10x0/tests/spimonitor/test_spim3.rs b/target/ast10x0/tests/spimonitor/test_spim3.rs
new file mode 100644
index 0000000..e6ce159
--- /dev/null
+++ b/target/ast10x0/tests/spimonitor/test_spim3.rs
@@ -0,0 +1,40 @@
+// Licensed under the Apache-2.0 license
+// SPDX-License-Identifier: Apache-2.0
+
+#![no_std]
+#![no_main]
+
+#[path = "test_common.rs"]
+mod test_common;
+
+use ast10x0_peripherals::scu::SpiMonitorInstance;
+use ast10x0_peripherals::spimonitor::SpiMonitorController;
+use console_backend::console_backend_write_all;
+use target_common::{declare_target, TargetInterface};
+use {console_backend as _, entry as _};
+
+struct Spim3Config;
+
+impl test_common::TestConfig for Spim3Config {
+    const INSTANCE: SpiMonitorInstance = SpiMonitorInstance::Spim2;
+    const CONTROLLER: SpiMonitorController = SpiMonitorController::Spim2;
+}
+
+struct Target;
+
+impl TargetInterface for Target {
+    const NAME: &'static str = "AST10x0 External SPIM3 Configuration Test";
+
+    fn main() -> ! {
+        let sentinel = if test_common::run::<Spim3Config>().is_ok() {
+            b"TEST_RESULT:PASS\n"
+        } else {
+            b"TEST_RESULT:FAIL\n"
+        };
+        let _ = console_backend_write_all(sentinel);
+        #[expect(clippy::empty_loop)]
+        loop {}
+    }
+}
+
+declare_target!(Target);
diff --git a/target/ast10x0/tests/spimonitor/test_spim4.rs b/target/ast10x0/tests/spimonitor/test_spim4.rs
new file mode 100644
index 0000000..3d43715
--- /dev/null
+++ b/target/ast10x0/tests/spimonitor/test_spim4.rs
@@ -0,0 +1,40 @@
+// Licensed under the Apache-2.0 license
+// SPDX-License-Identifier: Apache-2.0
+
+#![no_std]
+#![no_main]
+
+#[path = "test_common.rs"]
+mod test_common;
+
+use ast10x0_peripherals::scu::SpiMonitorInstance;
+use ast10x0_peripherals::spimonitor::SpiMonitorController;
+use console_backend::console_backend_write_all;
+use target_common::{declare_target, TargetInterface};
+use {console_backend as _, entry as _};
+
+struct Spim4Config;
+
+impl test_common::TestConfig for Spim4Config {
+    const INSTANCE: SpiMonitorInstance = SpiMonitorInstance::Spim3;
+    const CONTROLLER: SpiMonitorController = SpiMonitorController::Spim3;
+}
+
+struct Target;
+
+impl TargetInterface for Target {
+    const NAME: &'static str = "AST10x0 External SPIM4 Configuration Test";
+
+    fn main() -> ! {
+        let sentinel = if test_common::run::<Spim4Config>().is_ok() {
+            b"TEST_RESULT:PASS\n"
+        } else {
+            b"TEST_RESULT:FAIL\n"
+        };
+        let _ = console_backend_write_all(sentinel);
+        #[expect(clippy::empty_loop)]
+        loop {}
+    }
+}
+
+declare_target!(Target);