diff --git a/testbins/test-hal-scb/src/main.rs b/testbins/test-hal-scb/src/main.rs index dd7c29b1..91bbebaf 100644 --- a/testbins/test-hal-scb/src/main.rs +++ b/testbins/test-hal-scb/src/main.rs @@ -4,6 +4,10 @@ //! possible to use RTT to reliably communicate with test host. Therefore, this test writes out //! it's D-cache test results via UART after performing a simple handshake with test platform to //! mitigate that issue. +//! +//! It's also worth noting that neither D-Cache nor I-Cache effects can't be "observed", they serve +//! as a "black box", so the validation is performed by analysis of output assembly code that +//! confirms the proper instructions were placed to manage the caches. #![no_std] #![no_main] @@ -12,11 +16,15 @@ extern crate calldwell; extern crate cortex_m; extern crate cortex_m_rt as rt; +use core::fmt::Arguments; + use aerugo::hal::{ drivers::{ pio::{pin::Peripheral, Port}, pmc::config::PeripheralId, - uart::{Bidirectional, Config as UartConfig, Read, ReceiverConfig, Uart, Write}, + uart::{ + writer::Writer, Bidirectional, Config as UartConfig, Read, ReceiverConfig, Uart, Write, + }, }, user_peripherals::{CPUID, PIOD, PMC, SCB, UART4}, }; @@ -42,6 +50,9 @@ impl Default for DummyData { fn perform_dcache_tests(scb: &mut SCB, cpuid: &mut CPUID) { // Check cache enabling/disabling + // From now on, all test data will be sent via UART, because with RTT the cache must be disabled + // as currently it's not possible to disable RTT region caching due to lack of support from + // `rtt_target` library for that. scb.enable_dcache(cpuid); assert!( SCB::dcache_enabled(), @@ -62,16 +73,13 @@ fn perform_dcache_tests(scb: &mut SCB, cpuid: &mut CPUID) { scb.clean_invalidate_dcache(cpuid); - // TODO: Migrate from RTT to UART, because with RTT the cache must be - // disabled as currently it's not possible to disable RTT region - // caching due to lack of support from `rtt_target` library for that. - // scb.disable_dcache(cpuid); - // assert!( - // !SCB::dcache_enabled(), - // "D-Cache was disabled, yet it's reported as enabled" - // ); + scb.disable_dcache(cpuid); + assert!( + !SCB::dcache_enabled(), + "D-Cache was disabled, yet it's reported as enabled" + ); - write_str("dcache tests successful"); + write_via_uart(format_args!("D-Cache management test successful\n")); } fn perform_icache_tests(scb: &mut SCB) { @@ -91,13 +99,13 @@ fn perform_icache_tests(scb: &mut SCB) { !SCB::icache_enabled(), "I-Cache was disabled, yet it's reported as enabled" ); - write_str("icache tests successful"); + write_str("I-Cache management test successful"); } fn perform_scb_tests(mut scb: SCB, mut cpuid: CPUID) { perform_icache_tests(&mut scb); perform_dcache_tests(&mut scb, &mut cpuid); - write_str("all tests finished successfully"); + write_via_uart(format_args!("All SCB tests finished successfully!\n")); } fn configure_uart_io(port: Port) { @@ -119,6 +127,16 @@ fn perform_uart_handshake(uart: &mut Uart) { reader.read_exact(&mut handshake_buffer).unwrap(); assert_eq!(handshake_buffer, "Hello!".as_bytes()); writer.write_fmt(format_args!("World!")).unwrap(); + + uart.put_reader(reader); + unsafe { UART_WRITER.replace(writer) }; +} + +static mut UART_WRITER: Option> = None; + +/// This function will panic if called before `perform_uart_handshake`. +fn write_via_uart(fmt: Arguments) { + unsafe { UART_WRITER.as_mut().unwrap().write_fmt(fmt).unwrap() }; } #[entry] diff --git a/tests/requirements/test/test_hal_scb.py b/tests/requirements/test/test_hal_scb.py index 108b2b1c..0a4d4946 100644 --- a/tests/requirements/test/test_hal_scb.py +++ b/tests/requirements/test/test_hal_scb.py @@ -5,7 +5,7 @@ import logging import sys -from test_utils import finish_test, init_test, wait_for_messages +from test_utils import finish_test, init_test, wait_for_messages, wait_for_uart_messages from calldwell import init_default_logger from calldwell.uart import RemoteUARTConfig, RemoteUARTConnection @@ -38,9 +38,16 @@ def main() -> None: rtt, ssh, [ - "icache tests successful", - "dcache tests successful", - "all tests finished successfully", + "I-Cache management test successful", + ], + ) + + wait_for_uart_messages( + uart, + ssh, + [ + "D-Cache management test successful", + "All SCB tests finished successfully!", ], ) diff --git a/tests/requirements/test/test_hal_scb.rs b/tests/requirements/test/test_hal_scb.rs index bcad4840..6400a532 100644 --- a/tests/requirements/test/test_hal_scb.rs +++ b/tests/requirements/test/test_hal_scb.rs @@ -1,9 +1,9 @@ // Test scenario: -// - Verify that icache can be disabled/enabled/cleared -// - Verify that dcache can be disabled/enabled/cleared -// TODO: SCB-030 requirement coverage +// - Verify that I-Cache can be disabled/enabled/invalidated +// - Verify that D-Cache can be disabled/enabled/cleared/invalidated /// @SRS{ROS-FUN-BSP-SCB-020} +/// @SRS{ROS-FUN-BSP-SCB-030} /// @SRS{ROS-FUN-BSP-SCB-040} /// @SRS{ROS-FUN-BSP-SCB-050} /// @SRS{ROS-FUN-BSP-SCB-060} diff --git a/tests/requirements/test/test_utils.py b/tests/requirements/test/test_utils.py index a4e8cabc..afa589c2 100644 --- a/tests/requirements/test/test_utils.py +++ b/tests/requirements/test/test_utils.py @@ -26,6 +26,7 @@ from calldwell.gdb_client import GDBClient from calldwell.rtt_client import CalldwellRTTClient from calldwell.ssh_client import SSHClient + from calldwell.uart import RemoteUARTConnection def init_test( @@ -93,3 +94,27 @@ def wait_for_messages( ) finish_test(ssh) sys.exit(2) + + +def wait_for_uart_messages( + uart: RemoteUARTConnection, + ssh: SSHClient, + expected_messages: list[str], +) -> None: + """Same as `wait_for_messages`, but via UART. + Assumes that every message ends with single newline (`\\n`) character.""" + for message in expected_messages: + logging.info(f"Expecting '{message}' via UART") + received_message = uart.read_string(b"\n") + logging.info(f"Received '{received_message}'") + if ( + received_message.is_ok + and (received_message_content := received_message.unwrap().strip()) != message + ): + logging.critical( + "TEST FAILED: UNEXPECTED MESSAGE RECEIVED VIA UART " + f"(expected '{message}', got '{received_message_content}')", + ) + uart.close_uart() + finish_test(ssh) + sys.exit(2)