diff --git a/.github/workflows/hardware-test.yml b/.github/workflows/hardware-test.yml new file mode 100644 index 0000000..46d114a --- /dev/null +++ b/.github/workflows/hardware-test.yml @@ -0,0 +1,423 @@ +# Licensed under the Apache-2.0 license + +# Hardware-in-the-Loop Testing Workflow +# +# This workflow runs in two stages: +# +# Stage 1: precommit-checks (ubuntu-22.04) +# • Checkout code +# • Install packages +# • Verify Cargo.lock +# • Run cargo xtask precommit (format/lint/build) +# • Upload bloat reports +# +# Stage 2: hardware-functional-tests (self-hosted with AST1060) +# • Checkout code +# • Install Rust toolchain +# • Build firmware with test features +# • Generate binary image +# • Power off board +# • Upload firmware via UART (following AST1060 UART boot flow) +# • Power cycle for normal boot +# • Monitor test execution via UART +# • Parse results (PASS/FAIL/SKIP) +# • Upload test logs +# +# Hardware tests only run if precommit checks pass (needs: precommit-checks) +# Can be triggered manually with test suite selection (hmac, hash, rsa, ecdsa, all) +# +# Workflow Diagram: +# +# ┌─────────────────────────────────────────────┐ +# │ Stage 1: precommit-checks │ +# │ Runner: ubuntu-22.04 (GitHub-hosted) │ +# ├─────────────────────────────────────────────┤ +# │ • Verify Cargo.lock │ +# │ • cargo xtask precommit │ +# │ • Upload bloat reports │ +# └──────────────────┬──────────────────────────┘ +# │ +# │ (only if passes) +# ▼ +# ┌─────────────────────────────────────────────┐ +# │ Stage 2: hardware-functional-tests │ +# │ Runner: self-hosted (with AST1060) │ +# ├─────────────────────────────────────────────┤ +# │ • Build firmware (release profile) │ +# │ • Generate binary │ +# │ • UART upload to AST1060 │ +# │ • Monitor test execution │ +# │ • Parse PASS/FAIL/SKIP results │ +# │ • Upload test logs │ +# └─────────────────────────────────────────────┘ +# +# AST1060 UART Upload Flow: +# 1. Power off device +# 2. Enable FWSPICK strap (J156 pins 1-2 or SW6 pin 3) +# 3. Execute uart_fw_py command +# 4. Power on device (while uart_fw is running) +# 5. uart_fw uploads firmware to flash +# 6. Remove FWSPICK strap +# 7. Power cycle for normal boot +# 8. Monitor UART output for test results + +name: Hardware-in-the-Loop Functional Tests + +on: + push: + branches: + - main + - ci-hil + pull_request: + branches: + - main + workflow_dispatch: + inputs: + test_suite: + description: 'Test suite to run (hmac, hash, rsa, ecdsa, all)' + required: false + default: 'all' + +env: + CARGO_TERM_COLOR: always + CARGO_INCREMENTAL: 0 + EXTRA_CARGO_CONFIG: "target.'cfg(all())'.rustflags = [\"-Dwarnings\"]" + UART_BAUDRATE: 921600 + UART_PORT: /dev/ttyUSB0 # Adjust for your CI runner + AST1060_PLATFORM: ast1060 + +jobs: + # First stage: Build checks on standard CI runner + precommit-checks: + runs-on: ubuntu-22.04 + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install packages + run: | + sudo apt-get update -qy + sudo apt-get install -qy build-essential curl gcc-multilib gcc-riscv64-unknown-elf git + + - name: Install cargo-bloat + run: cargo install cargo-bloat + + - name: Verify Cargo.lock is up to date + run: | + cargo tree --locked > /dev/null || ( + echo "Please update Cargo.lock" + cargo tree + git diff Cargo.lock + exit 1 + ) + + - name: Run precommit checks (build/format/lint) + run: | + cargo --config "$EXTRA_CARGO_CONFIG" xtask precommit + + - name: Upload binary size reports + uses: actions/upload-artifact@v4 + if: always() && hashFiles('target/bloat-reports/*') != '' + with: + name: bloat-reports + path: target/bloat-reports/ + retention-days: 30 + + # Second stage: Hardware tests on self-hosted runner with AST1060 + hardware-functional-tests: + needs: precommit-checks + runs-on: self-hosted # Must be self-hosted runner with AST1060 hardware + timeout-minutes: 30 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install Rust toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: nightly-2024-09-17 + target: thumbv7em-none-eabihf + override: true + components: rust-src, clippy + + - name: Install dependencies + run: | + # Install required tools + sudo apt-get update -qy + sudo apt-get install -qy build-essential python3 python3-serial gcc-arm-none-eabi + + # Install UART firmware upload tool (adjust path as needed) + # Assuming uart_fw_py is in your repo or available + if [ ! -f ./scripts/uart_fw_py ]; then + echo "Error: uart_fw_py not found in scripts/" + exit 1 + fi + chmod +x ./scripts/uart_fw_py + + - name: Build functional test firmware + run: | + # Determine test suite features + SUITE="${{ github.event.inputs.test_suite || 'all' }}" + + if [ "$SUITE" = "all" ]; then + FEATURES="test-hmac,test-hash,test-rsa,test-ecdsa" + else + FEATURES="test-$SUITE" + fi + + echo "Building with features: $FEATURES" + cargo build --release --target thumbv7em-none-eabihf --features "$FEATURES" + + - name: Generate binary image + run: | + # Convert ELF to raw binary + arm-none-eabi-objcopy \ + -O binary \ + target/thumbv7em-none-eabihf/release/aspeed-ddk \ + target/functional-tests-raw.bin + + # Wrap with UART boot header (4-byte size prefix) + ./scripts/gen_uart_booting_image.sh \ + target/functional-tests-raw.bin \ + target/functional-tests.bin + + # Verify binary sizes + RAW_SIZE=$(stat -c%s target/functional-tests-raw.bin) + UART_SIZE=$(stat -c%s target/functional-tests.bin) + echo "Raw binary size: $RAW_SIZE bytes" + echo "UART boot image size: $UART_SIZE bytes (includes 4-byte header)" + + if [ $RAW_SIZE -gt 1048576 ]; then + echo "Error: Binary too large for 1MB flash" + exit 1 + fi + + - name: Prepare hardware - Power off + run: | + echo "Powering off AST1060 board..." + # Add your power control command here (e.g., PDU control, GPIO, etc.) + # Example: ./scripts/power_control.sh off + sleep 2 + + - name: Check UART port availability + run: | + if [ ! -e "$UART_PORT" ]; then + echo "Error: UART port $UART_PORT not found" + echo "Available ports:" + ls -la /dev/ttyUSB* /dev/ttyACM* 2>/dev/null || echo "No USB serial ports found" + exit 1 + fi + + # Ensure port is not in use + sudo fuser -k $UART_PORT 2>/dev/null || true + sleep 1 + + - name: Verify FWSPICK strap (manual check) + run: | + echo "======================================" + echo "HARDWARE CHECK REQUIRED:" + echo "Ensure FWSPICK is connected to VCC_3V3" + echo " - AST1060 EVB: J156 pins 1-2 connected" + echo " - DC-SCM: SW6 pin 3 ON" + echo "======================================" + + # In a real CI setup, you'd have automated strap control + # For now, this is a documentation step + # You could add a GPIO-controlled relay here + + - name: Upload firmware via UART + run: | + echo "Starting UART firmware upload..." + echo "Command will wait for power-on..." + + # Run UART upload in background + sudo ./scripts/uart_fw_py \ + --platform $AST1060_PLATFORM \ + --spi 0 \ + --cs 0 \ + --comport $UART_PORT \ + --baudrate $UART_BAUDRATE \ + --input_image target/functional-tests.bin \ + --erase_all & + + UART_PID=$! + + # Give uart_fw time to initialize + sleep 3 + + # Power on the board + echo "Powering on AST1060 board..." + # Add your power control command here + # Example: ./scripts/power_control.sh on + + # Wait for UART upload to complete + wait $UART_PID + UPLOAD_STATUS=$? + + if [ $UPLOAD_STATUS -ne 0 ]; then + echo "Error: UART firmware upload failed with exit code $UPLOAD_STATUS" + exit 1 + fi + + echo "Firmware upload completed successfully" + + - name: Remove FWSPICK strap (manual or automated) + run: | + echo "======================================" + echo "HARDWARE ACTION REQUIRED:" + echo "Remove FWSPICK connection" + echo " - AST1060 EVB: Disconnect J156 pins" + echo " - DC-SCM: Turn OFF SW6 pin 3" + echo "======================================" + + # In automated setup, control via GPIO/relay + sleep 2 + + - name: Power cycle board for normal boot + run: | + echo "Power cycling for normal boot..." + + # Power off + # ./scripts/power_control.sh off + sleep 2 + + # Power on + # ./scripts/power_control.sh on + sleep 5 + + echo "Board booted in normal mode" + + - name: Monitor test execution via UART + run: | + echo "Monitoring test execution..." + + # Capture UART output for test results + timeout 60 sudo python3 - <<'EOF' +import serial +import sys +import re + +port = "${{ env.UART_PORT }}" +baudrate = 115200 # Tests run at standard baud after boot + +try: + ser = serial.Serial(port, baudrate, timeout=1) + print(f"Listening on {port} at {baudrate} baud...") + + test_results = { + 'passed': 0, + 'failed': 0, + 'skipped': 0 + } + + output_buffer = [] + + while True: + line = ser.readline().decode('utf-8', errors='ignore').strip() + if not line: + continue + + output_buffer.append(line) + print(line) + + # Parse test results + if 'PASS' in line: + test_results['passed'] += 1 + elif 'FAIL' in line: + test_results['failed'] += 1 + elif 'SKIP' in line: + test_results['skipped'] += 1 + + # Check for completion + if 'Test Suite' in line and 'Complete' in line: + break + if 'panic' in line.lower(): + print("ERROR: Panic detected!") + sys.exit(1) + + # Print summary + print("\n" + "="*50) + print("Test Results Summary:") + print(f" Passed: {test_results['passed']}") + print(f" Failed: {test_results['failed']}") + print(f" Skipped: {test_results['skipped']}") + print("="*50) + + # Exit with appropriate code + if test_results['failed'] > 0: + sys.exit(1) + else: + sys.exit(0) + +except serial.SerialException as e: + print(f"Serial port error: {e}") + sys.exit(1) +except KeyboardInterrupt: + print("Monitoring interrupted") + sys.exit(1) +finally: + if 'ser' in locals(): + ser.close() +EOF + + TEST_STATUS=$? + + if [ $TEST_STATUS -ne 0 ]; then + echo "Tests FAILED or monitoring error" + exit 1 + fi + + echo "All tests PASSED" + + - name: Save test logs + if: always() + run: | + # Save logs for analysis + mkdir -p test-results + + # Capture final UART output + timeout 5 sudo python3 -c " +import serial +import sys +with serial.Serial('${{ env.UART_PORT }}', 115200, timeout=1) as ser: + for _ in range(50): + line = ser.readline().decode('utf-8', errors='ignore') + if line: + print(line, end='') +" > test-results/uart-output.log 2>&1 || true + + echo "Test logs saved to test-results/" + + - name: Upload test artifacts + if: always() + uses: actions/upload-artifact@v4 + with: + name: test-results-${{ github.run_number }} + path: | + test-results/ + target/functional-tests.bin + retention-days: 30 + + - name: Cleanup + if: always() + run: | + # Ensure board is in normal state + # ./scripts/power_control.sh off + sudo fuser -k $UART_PORT 2>/dev/null || true + echo "Cleanup completed" + + - name: Report status + if: always() + run: | + if [ ${{ job.status }} == 'success' ]; then + echo "✅ Hardware tests PASSED" + else + echo "❌ Hardware tests FAILED" + exit 1 + fi diff --git a/README.md b/README.md index 200a6f6..b622487 100644 --- a/README.md +++ b/README.md @@ -74,3 +74,24 @@ $ cargo build --release Hello, world! aspeed_ddk! ``` + +## Running the app on Hardware + +### Host Platform + +The recommended host platform is a Raspberry Pi, per ASpeed. Connecting two GPIO from the Pi to SRST pin 1 and FWSPICK pin 2 will allow the upload script to manage UART boot state and device ready. Check the upload script for the correct pins. + +### Test Execution + +Using the UART boot image created above, the uart-test-exec.py script will load the binary on the device and monitor all output. + +$ python3 ./scripts/uart-test-exec.py uart_ast10x0.bin + +The script will toggle the GPIOs in the necessary order to reset the device into UART boot mode, then once "U" is observed from the device, it will upload the binary and begin observing the output. All test output will be printed to the screen and logged for later use. + +Running + +$ pythone3 ./scripts/uart-test-exec.py --help + +will provide details on multiple additional options including manual toggling of GPIOs, altering the GPIO number, and other configuration options (UART baud rate, timeouts, quiet operation, etc.) + diff --git a/docs/ci-aspeed.md b/docs/ci-aspeed.md new file mode 100644 index 0000000..6e0667b --- /dev/null +++ b/docs/ci-aspeed.md @@ -0,0 +1,150 @@ +# CI Setup for the ASPEED AST1060 + EVB A3 + +## Overview + +The ASPEED AST1060 EVB A3 features two AST1060 evaluation boards linked over a larger test fixture. One device is equipped with a JTAG pigtail on the underside of the board. + +Control of the AST1060 for testing purposes requires both boards, but only one needs to be loaded regularly. It is recommended that the secondary board (without JTAG) have an appropriate image written to SPI. + +## Resources + +To set up CI for the AST1060, the following devices will be needed: + +* A Raspberry Pi 4 or 5 +* An ASpeed PRoT Fixture vA3.0 with two EVB cards. +* 2x USB UART adapters + * Recommended: https://www.amazon.com/DTECH-Adapter-Compatible-Windows-Genuine/dp/B0D97VR3CY/ + * Any M USB UART adapter will work as well. +* 4x F-to-F fly leads + +## Setup + +### Raspberry Pi + +#### OS + +Install the latest Raspberry Pi OS on a uSD card. Do not enable SPI or I2C. + +Recommended packages: xxd, picocom, ack, libglib2.0-dev, liblua5.2-dev, tio + +### EVB + +Ensure power is supplied to the board and the USB UART cables are plugged in. + +### Hardware Configuration + +* Connect the USB uart cables to the UART header on each EVB. Plug these into the Raspberry Pi and note their path via /dev/serial/by-id/uart_... + * Alternatively, just plug in the DB-9 +* Using an F-to-F fly lead, connect RPi pin 12 (GPIO 18) to pin 2 of J1 (FWSPICK) +* Using an F-to-F fly lead, connect RPi pin 16 (GPIO 23) to pin 1 of J3 (SRST) + +## Testing + +All builds and tests are executed by the Raspberry Pi using a support script within the repository. + +### Build + +Build is managed via Cargo + +``` +\$ cargo build +``` + +### Package + +First, we dump the ELF to a binary file: + +``` +$ cargo objcopy -- -O binary ast10x0.bin +``` + +The AST1060 UART requires a 4-byte header that informs the ROM of the size of the incoming payload. + +``` + ./scripts/gen_uart_booting_image.sh ast10x0.bin uart_ast10x0.bin + ``` + +### Execute + +A support script in the repository, uart-test-exec.py, is designed to give both high level test contorl and fine-grained device control. + +``` +$ python3 uart-test-exec.py --help + +usage: uart-test-exec.py [-h] [--srst-pin SRST_PIN] [--fwspick-pin FWSPICK_PIN] [--manual-srst {low,high,dl,dh}] + [--manual-fwspick {low,high,dl,dh}] [--sequence {fwspick-mode,normal-mode}] [-b BAUDRATE] + [--test-timeout TEST_TIMEOUT] [--log-file LOG_FILE] [--skip-uart] [-q] [--dry-run] + [uart_device] [firmware] + +AST1060 UART Test Execution Script + +positional arguments: + uart_device UART device path (e.g., /dev/ttyUSB0) + firmware Firmware binary file path + +options: + -h, --help show this help message and exit + --srst-pin SRST_PIN SRST GPIO pin number (default: 23) + --fwspick-pin FWSPICK_PIN + FWSPICK GPIO pin number (default: 18) + --manual-srst {low,high,dl,dh} + Manually toggle SRST pin + --manual-fwspick {low,high,dl,dh} + Manually toggle FWSPICK pin + --sequence {fwspick-mode,normal-mode} + Run GPIO sequence + -b BAUDRATE, --baudrate BAUDRATE + UART baud rate (default: 115200) + --test-timeout TEST_TIMEOUT + Test execution monitoring timeout in seconds (default: 600) + --log-file LOG_FILE Log file path (auto-generated if not specified) + --skip-uart Skip all UART operations + -q, --quiet Run silently (no output) + --dry-run Show what would be done without executing + +Examples: + # Full test sequence + ./uart-test-exec.py /dev/ttyUSB0 firmware.bin + + # Manual GPIO control + ./uart-test-exec.py --manual-srst low + ./uart-test-exec.py --manual-fwspick high + + # Sequence control + ./uart-test-exec.py --sequence fwspick-mode + ./uart-test-exec.py --sequence normal-mode + + # Custom pin numbers and timeout + ./uart-test-exec.py --srst-pin 25 --fwspick-pin 20 --test-timeout 300 /dev/ttyUSB0 firmware.bin +``` + +To execute the test: + +``` +$ python3 uart-test-exec.py /dev/serial/by-id/usb-... uart_ast10x0.bin +``` + +The script will execute the following sequence: +- Assert SRST# +- Ensure FWSPICK is asserted (J1) +- Deassert SRST# +- Read uart waiting for "U" +- Upload the firmware +- Read UART output until "COMPLETE" is seen or a timeout happens. + +While running the script looks for three tokens: + +"panic" - The test executable has suffered an unrecoverable fault +"PASS" - A test has completed successfully +"FAIL" - A test has failed + +If "panic" or "FAIL" is seen anywhere in the test, the script will print all UART output and return non-zero. Otherwise the script will return zero. + +## Automation + +When using a Github runner, it is recommended that the following things be set in environment variables and passed in via the YAML: +- UART device for the EVB +- SRST GPIO pin +- FWSPICK GPIO pin + +The last two can be overridden on the command-line, allowing the script to operate automatically against multiple devices connected to the same Raspberry Pi. \ No newline at end of file diff --git a/scripts/ast-bin-create-and-package.sh b/scripts/ast-bin-create-and-package.sh new file mode 100755 index 0000000..a8bf6a9 --- /dev/null +++ b/scripts/ast-bin-create-and-package.sh @@ -0,0 +1,221 @@ +#!/bin/bash +set -euo pipefail + +# AST1060 Binary Creation and Packaging Script +# Converts ELF firmware to UART bootable binary format + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" + +usage() { + echo "Usage: $0 [OPTIONS]" + echo "" + echo "OPTIONS:" + echo " -t, --target TARGET Target triple (default: thumbv7em-none-eabihf)" + echo " -b, --binary NAME Binary name (default: aspeed-ddk)" + echo " -o, --output OUTPUT Output binary path (default: target/functional-tests.bin)" + echo " -s, --max-size SIZE Maximum binary size in bytes (default: 1048576)" + echo " -q, --quiet Suppress informational output" + echo " -h, --help Show this help message" + echo "" + echo "EXAMPLES:" + echo " $0 # Use defaults" + echo " $0 -b my-firmware -o my-firmware.bin # Custom binary name and output" + echo " $0 -s 2097152 # Allow 2MB max size" + echo " $0 -q # Run silently" +} + +# Default values +TARGET="thumbv7em-none-eabihf" +BINARY_NAME="aspeed-ddk" +OUTPUT_PATH="target/functional-tests.bin" +MAX_SIZE=1048576 # 1MB default +QUIET=false + +# Helper function for conditional echo +log() { + if [[ "$QUIET" != "true" ]]; then + echo "$@" + fi +} + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + case $1 in + -t|--target) + TARGET="$2" + shift 2 + ;; + -b|--binary) + BINARY_NAME="$2" + shift 2 + ;; + -o|--output) + OUTPUT_PATH="$2" + shift 2 + ;; + -s|--max-size) + MAX_SIZE="$2" + shift 2 + ;; + -q|--quiet) + QUIET=true + shift + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Error: Unknown option $1" + usage + exit 1 + ;; + esac +done + +# Validate inputs +if [[ ! "$MAX_SIZE" =~ ^[0-9]+$ ]]; then + echo "Error: max-size must be a positive integer" + exit 1 +fi + +# Change to project root +cd "$PROJECT_ROOT" + +# Define paths +ELF_PATH="target/$TARGET/release/$BINARY_NAME" +RAW_BINARY_PATH="target/functional-tests-raw.bin" + +log "AST1060 Binary Generation" +log "=========================" +log "Target: $TARGET" +log "Binary: $BINARY_NAME" +log "Output: $OUTPUT_PATH" +log "Max size: $MAX_SIZE bytes" +log "" + +# Check if ELF file exists +if [[ ! -f "$ELF_PATH" ]]; then + echo "Error: ELF file not found at $ELF_PATH" + echo "Please build the firmware first with:" + echo " cargo build --release --target $TARGET" + exit 1 +fi + +# Check for required tools +if ! command -v arm-none-eabi-objcopy >/dev/null 2>&1; then + echo "Error: arm-none-eabi-objcopy not found" + echo "Please install gcc-arm-none-eabi package" + exit 1 +fi + +log "Converting ELF to raw binary..." + +# Convert ELF to raw binary +if ! arm-none-eabi-objcopy \ + -O binary \ + "$ELF_PATH" \ + "$RAW_BINARY_PATH"; then + echo "Error: Failed to convert ELF to binary" + exit 1 +fi + +# Verify raw binary was created +if [[ ! -f "$RAW_BINARY_PATH" ]]; then + echo "Error: Raw binary was not created" + exit 1 +fi + +# Get raw binary size +RAW_SIZE=$(stat -c%s "$RAW_BINARY_PATH") +log "Raw binary size: $RAW_SIZE bytes" + +# Check size limits +if [[ $RAW_SIZE -gt $MAX_SIZE ]]; then + echo "Error: Binary too large ($RAW_SIZE bytes > $MAX_SIZE bytes limit)" + echo "Consider:" + echo " - Enabling more aggressive optimizations" + echo " - Reducing feature set" + echo " - Using release profile with size optimization" + exit 1 +fi + +log "Wrapping with UART boot header..." + +# Check if UART boot image generator exists +UART_BOOT_SCRIPT="$SCRIPT_DIR/gen_uart_booting_image.sh" +if [[ ! -f "$UART_BOOT_SCRIPT" ]]; then + echo "Error: UART boot image generator not found at $UART_BOOT_SCRIPT" + log "Creating simple 4-byte size prefix wrapper..." + + # Create simple wrapper if script doesn't exist + # Write 4-byte little-endian size prefix followed by binary data + python3 -c " +import struct +import sys + +raw_path = '$RAW_BINARY_PATH' +output_path = '$OUTPUT_PATH' +max_size = $MAX_SIZE +quiet = '$QUIET' == 'true' + +try: + with open(raw_path, 'rb') as f: + data = f.read() + + size = len(data) + if size > max_size: + print(f'Error: Binary size {size} exceeds limit {max_size}') + sys.exit(1) + + with open(output_path, 'wb') as f: + # Write 4-byte little-endian size header + f.write(struct.pack('90%)" +fi + +log "" +log "Ready for UART upload to AST1060!" diff --git a/scripts/uart-test-exec.py b/scripts/uart-test-exec.py new file mode 100644 index 0000000..7eb6950 --- /dev/null +++ b/scripts/uart-test-exec.py @@ -0,0 +1,494 @@ +#!/usr/bin/env python3 +""" +AST1060 UART Test Execution Script + +Provides GPIO control for SRST/FWSPICK pins and automated firmware upload +with test execution monitoring via pyserial. +""" + +import argparse +import subprocess +import time +import os +import sys +import threading +from pathlib import Path +from typing import Optional, Tuple + +try: + import serial +except ImportError: + print("Error: pyserial not installed. Install with: pip install pyserial") + sys.exit(1) + + +class UartTestExecutor: + """Handles AST1060 UART test execution with GPIO control.""" + + def __init__(self, args): + self.args = args + self.serial_port: Optional[serial.Serial] = None + self.log_file = args.log_file or f"uart-test-{os.getpid()}.log" + self.log_file_handle = None + + def log(self, message: str): + """Print message unless in quiet mode.""" + if not self.args.quiet: + print(message) + + def run_command(self, cmd: list, check: bool = True) -> Tuple[int, str, str]: + """Run command and return (returncode, stdout, stderr).""" + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=False + ) + if check and result.returncode != 0: + raise subprocess.CalledProcessError( + result.returncode, cmd, result.stdout, result.stderr + ) + return result.returncode, result.stdout, result.stderr + except FileNotFoundError: + raise RuntimeError(f"Command not found: {cmd[0]}") + + def gpio_set(self, pin: int, state: str): + """Set GPIO pin state using pinctrl.""" + cmd = ["pinctrl", "set", str(pin), "op", state] + self.log(f"GPIO {pin}: {state}") + + if self.args.dry_run: + self.log(f"DRY RUN: {' '.join(cmd)}") + return + + try: + self.run_command(cmd) + except Exception as e: + raise RuntimeError(f"Failed to set GPIO {pin} to {state}: {e}") + + def toggle_srst(self, state: str): + """Toggle SRST pin (dl=low, dh=high).""" + self.gpio_set(self.args.srst_pin, state) + + def toggle_fwspick(self, state: str): + """Toggle FWSPICK pin (dh=high, dl=low).""" + # Note: FWSPICK uses 'pn dh' for high state as in original script + if state == "dh": + cmd_state = "pn dh" + else: + cmd_state = state + + cmd = ["pinctrl", "set", str(self.args.fwspick_pin), "op"] + cmd_state.split() + self.log(f"GPIO {self.args.fwspick_pin} (FWSPICK): {state}") + + if self.args.dry_run: + self.log(f"DRY RUN: {' '.join(cmd)}") + return + + try: + self.run_command(cmd) + except Exception as e: + raise RuntimeError(f"Failed to set FWSPICK {self.args.fwspick_pin} to {state}: {e}") + + def sequence_to_fwspick_mode(self): + """Execute sequence to enter FWSPICK mode.""" + self.log("Entering FWSPICK mode sequence...") + self.toggle_srst("dl") # SRST low + time.sleep(0.1) + self.toggle_fwspick("dh") # FWSPICK high + time.sleep(1) + self.toggle_srst("dh") # SRST high + time.sleep(1) + self.log("FWSPICK mode sequence complete") + + def sequence_to_normal_mode(self): + """Execute sequence to enter normal boot mode.""" + self.log("Entering normal boot mode sequence...") + self.toggle_fwspick("dl") # FWSPICK low + time.sleep(0.1) + self.toggle_srst("dl") # SRST low + time.sleep(0.5) + self.toggle_srst("dh") # SRST high + time.sleep(2) + self.log("Normal boot mode sequence complete") + + def open_serial(self) -> bool: + """Open serial port connection.""" + if self.args.skip_uart: + self.log("Skipping UART setup") + return True + + if self.args.dry_run: + self.log("DRY RUN: Would open serial port") + return True + + try: + self.serial_port = serial.Serial( + port=self.args.uart_device, + baudrate=self.args.baudrate, + timeout=1.0, + write_timeout=1.0 + ) + + # Open log file + self.log_file_handle = open(self.log_file, 'w') + + self.log(f"Serial port opened: {self.args.uart_device} @ {self.args.baudrate} baud") + self.log(f"Logging to: {self.log_file}") + return True + + except Exception as e: + raise RuntimeError(f"Failed to open serial port: {e}") + + def close_serial(self): + """Close serial port connection.""" + if self.serial_port: + self.serial_port.close() + self.serial_port = None + + if self.log_file_handle: + self.log_file_handle.close() + self.log_file_handle = None + + def read_serial_data(self, timeout_seconds: float = 1.0) -> str: + """Read available data from serial port.""" + if not self.serial_port or self.args.skip_uart: + return "" + + if self.args.dry_run: + return "" + + try: + # Set a short timeout for non-blocking read + self.serial_port.timeout = timeout_seconds + data = self.serial_port.read(1024) + + if data: + decoded = data.decode('utf-8', errors='ignore') + + # Log to file + if self.log_file_handle: + self.log_file_handle.write(decoded) + self.log_file_handle.flush() + + return decoded + + return "" + + except Exception as e: + self.log(f"Serial read error: {e}") + return "" + + def write_serial_data(self, data: bytes) -> bool: + """Write data to serial port.""" + if not self.serial_port or self.args.skip_uart: + return True + + if self.args.dry_run: + self.log(f"DRY RUN: Would write {len(data)} bytes to serial") + return True + + try: + bytes_written = self.serial_port.write(data) + self.serial_port.flush() + return bytes_written == len(data) + + except Exception as e: + self.log(f"Serial write error: {e}") + return False + + def wait_for_uart_ready(self, timeout: int = 30) -> bool: + """Wait for 'U' character indicating UART bootloader ready.""" + if self.args.skip_uart: + self.log("Skipping UART ready check") + return True + + self.log(f"Waiting for UART ready signal ('U') with {timeout}s timeout...") + + if self.args.dry_run: + self.log("DRY RUN: Would wait for UART ready") + return True + + start_time = time.time() + buffer = "" + + while time.time() - start_time < timeout: + data = self.read_serial_data(0.1) + if data: + buffer += data + if not self.args.quiet: + print(data, end='', flush=True) + + # Look for 'U' character + if 'U' in buffer: + self.log("\nUART bootloader ready detected!") + return True + + self.log("\nTimeout waiting for UART ready signal") + return False + + def upload_firmware(self) -> bool: + """Upload firmware via serial port.""" + if self.args.skip_uart or not self.args.firmware: + self.log("Skipping firmware upload") + return True + + firmware_path = Path(self.args.firmware) + if not firmware_path.exists(): + raise RuntimeError(f"Firmware file not found: {firmware_path}") + + self.log(f"Uploading firmware: {firmware_path}") + + if self.args.dry_run: + self.log("DRY RUN: Would upload firmware") + return True + + try: + with open(firmware_path, 'rb') as f: + firmware_data = f.read() + + self.log(f"Uploading {len(firmware_data)} bytes...") + + # Upload firmware in chunks to avoid overwhelming the bootloader + chunk_size = 1024 + bytes_sent = 0 + + for i in range(0, len(firmware_data), chunk_size): + chunk = firmware_data[i:i + chunk_size] + + if not self.write_serial_data(chunk): + self.log("Failed to write firmware chunk") + return False + + bytes_sent += len(chunk) + + # Small delay between chunks + time.sleep(0.01) + + # Progress indicator + if not self.args.quiet and bytes_sent % (chunk_size * 10) == 0: + progress = (bytes_sent * 100) // len(firmware_data) + print(f"\rProgress: {progress}%", end='', flush=True) + + if not self.args.quiet: + print() # New line after progress + + self.log("Firmware upload completed") + return True + + except Exception as e: + self.log(f"Failed to upload firmware: {e}") + return False + + def monitor_test_execution(self, timeout: int = 600) -> bool: + """Monitor test execution via serial port.""" + if self.args.skip_uart: + self.log("Skipping test monitoring") + return True + + # Use command line timeout if provided, otherwise use parameter default + actual_timeout = getattr(self.args, 'test_timeout', timeout) + self.log(f"Monitoring test execution with {actual_timeout}s timeout...") + + if self.args.dry_run: + self.log("DRY RUN: Would monitor test execution") + return True + + start_time = time.time() + buffer = "" + test_results = {"passed": 0, "failed": 0, "skipped": 0} + + while time.time() - start_time < actual_timeout: + data = self.read_serial_data(0.5) + if data: + buffer += data + if not self.args.quiet: + print(data, end='', flush=True) + + # Parse test results + lines = buffer.split('\n') + for line in lines: + if 'PASS' in line: + test_results['passed'] += 1 + elif 'FAIL' in line: + test_results['failed'] += 1 + elif 'SKIP' in line: + test_results['skipped'] += 1 + + # Check for completion or failure + if 'COMPLETE' in line: + self.log(f"\nTest execution completed!") + self.log(f"Results: {test_results}") + return test_results['failed'] == 0 + + if 'panic' in line.lower(): + self.log(f"\nPanic detected in test execution!") + return False + + # Keep only last few lines in buffer + buffer = '\n'.join(lines[-10:]) + + self.log(f"\nTest monitoring timeout. Results so far: {test_results}") + return test_results['failed'] == 0 + + def cleanup(self): + """Clean up resources.""" + self.close_serial() + + def run_full_test_sequence(self) -> bool: + """Execute the complete test sequence.""" + try: + # Open serial port + if not self.open_serial(): + return False + + # Enter FWSPICK mode + self.sequence_to_fwspick_mode() + + # Wait for UART ready + if not self.wait_for_uart_ready(): + return False + + # Upload firmware + if not self.upload_firmware(): + return False + + # Monitor test execution (starts immediately after upload) + return self.monitor_test_execution() + + finally: + self.cleanup() + + +def main(): + parser = argparse.ArgumentParser( + description="AST1060 UART Test Execution Script", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +Examples: + # Full test sequence + ./uart-test-exec.py /dev/ttyUSB0 firmware.bin + + # Manual GPIO control + ./uart-test-exec.py --manual-srst low + ./uart-test-exec.py --manual-fwspick high + + # Sequence control + ./uart-test-exec.py --sequence fwspick-mode + ./uart-test-exec.py --sequence normal-mode + + # Custom pin numbers and timeout + ./uart-test-exec.py --srst-pin 25 --fwspick-pin 20 --test-timeout 300 /dev/ttyUSB0 firmware.bin + + # Upload-only (no GPIO, no monitoring) + ./uart-test-exec.py --upload-only /dev/ttyUSB0 firmware.bin + """ + ) + + # Positional arguments + parser.add_argument("uart_device", nargs='?', + help="UART device path (e.g., /dev/ttyUSB0)") + parser.add_argument("firmware", nargs='?', + help="Firmware binary file path") + + # GPIO control + parser.add_argument("--srst-pin", type=int, default=23, + help="SRST GPIO pin number (default: 23)") + parser.add_argument("--fwspick-pin", type=int, default=18, + help="FWSPICK GPIO pin number (default: 18)") + + # Manual GPIO operations + parser.add_argument("--manual-srst", choices=['low', 'high', 'dl', 'dh'], + help="Manually toggle SRST pin") + parser.add_argument("--manual-fwspick", choices=['low', 'high', 'dl', 'dh'], + help="Manually toggle FWSPICK pin") + + # Sequence operations + parser.add_argument("--sequence", choices=['fwspick-mode', 'normal-mode'], + help="Run GPIO sequence") + + # UART settings + parser.add_argument("-b", "--baudrate", type=int, default=115200, + help="UART baud rate (default: 115200)") + parser.add_argument("--test-timeout", type=int, default=600, + help="Test execution monitoring timeout in seconds (default: 600)") + parser.add_argument("--log-file", + help="Log file path (auto-generated if not specified)") + + # Control flags + parser.add_argument("--skip-uart", action="store_true", + help="Skip all UART operations") + parser.add_argument("-q", "--quiet", action="store_true", + help="Run silently (no output)") + parser.add_argument("--dry-run", action="store_true", + help="Show what would be done without executing") + # NEW: upload-only mode (no GPIO, no monitoring) + parser.add_argument("--upload-only", action="store_true", + help="Skip all GPIO commands, open UART, upload firmware, then exit") + + args = parser.parse_args() + + # Validate arguments + # NEW: validation for upload-only mode + if args.upload_only: + if not args.uart_device or not args.firmware: + parser.error("--upload-only requires UART device and firmware file") + else: + if not any([args.manual_srst, args.manual_fwspick, args.sequence, args.uart_device]): + parser.error("Must specify either manual GPIO control, sequence, or UART device") + + if args.uart_device and not args.skip_uart and not Path(args.uart_device).exists(): + parser.error(f"UART device not found: {args.uart_device}") + + executor = UartTestExecutor(args) + + try: + # Handle manual GPIO operations + if args.manual_srst: + state = "dl" if args.manual_srst in ['low', 'dl'] else "dh" + executor.toggle_srst(state) + return 0 + + if args.manual_fwspick: + state = "dh" if args.manual_fwspick in ['high', 'dh'] else "dl" + executor.toggle_fwspick(state) + return 0 + + # NEW: upload-only execution path (no GPIO, no monitoring) + if args.upload_only: + if not executor.open_serial(): + return 1 + # Directly upload firmware, skip GPIO and waiting/monitoring + ok = executor.upload_firmware() + executor.cleanup() + return 0 if ok else 1 + + # Handle sequence operations + if args.sequence == 'fwspick-mode': + executor.sequence_to_fwspick_mode() + return 0 + elif args.sequence == 'normal-mode': + executor.sequence_to_normal_mode() + return 0 + + # Run full test sequence + if executor.run_full_test_sequence(): + executor.log("✅ Test execution completed successfully!") + return 0 + else: + executor.log("❌ Test execution failed!") + return 1 + + except KeyboardInterrupt: + executor.log("\nInterrupted by user") + return 130 + except Exception as e: + executor.log(f"Error: {e}") + return 1 + finally: + executor.cleanup() + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/src/main.rs b/src/main.rs index e352595..13c7026 100644 --- a/src/main.rs +++ b/src/main.rs @@ -177,10 +177,10 @@ fn validate_digest( } if matches && byte_index == expected.len() { - writeln!(uart, "{algorithm} test vector validation: PASSED ✅").unwrap(); + writeln!(uart, "{algorithm} test vector validation: PASS").unwrap(); true } else { - writeln!(uart, "{algorithm} test vector validation: FAILED ❌").unwrap(); + writeln!(uart, "{algorithm} test vector validation: FAIL").unwrap(); write!(uart, "Expected: ").unwrap(); for &byte in expected { write!(uart, "{byte:02x}").unwrap(); @@ -226,9 +226,9 @@ fn test_owned_sha256(uart: &mut UartController<'_>, hace: ast1060_pac::Hace) { ]; if validate_digest(&digest.value, &expected_sha256, "SHA256", uart) { - writeln!(uart, "SHA256 owned API: PASSED ✅").unwrap(); + writeln!(uart, "SHA256 owned API: PASS").unwrap(); } else { - writeln!(uart, "SHA256 owned API: FAILED ❌").unwrap(); + writeln!(uart, "SHA256 owned API: FAIL").unwrap(); } } @@ -254,9 +254,9 @@ fn test_owned_sha384(uart: &mut UartController<'_>, hace: ast1060_pac::Hace) { ]; if validate_digest(&digest.value, &expected_sha384, "SHA384", uart) { - writeln!(uart, "SHA384 owned API: PASSED ✅").unwrap(); + writeln!(uart, "SHA384 owned API: PASS").unwrap(); } else { - writeln!(uart, "SHA384 owned API: FAILED ❌").unwrap(); + writeln!(uart, "SHA384 owned API: FAIL").unwrap(); } // Demonstrate controller recovery by using it again @@ -264,7 +264,7 @@ fn test_owned_sha384(uart: &mut UartController<'_>, hace: ast1060_pac::Hace) { let context2 = context2.update(b"Reused controller").unwrap(); let (_digest2, _final_controller) = context2.finalize().unwrap(); - writeln!(uart, "Controller recovery: PASSED ✅").unwrap(); + writeln!(uart, "Controller recovery: PASS").unwrap(); } /// Test owned SHA512 API demonstrating cancellation @@ -278,7 +278,7 @@ fn test_owned_sha512(uart: &mut UartController<'_>, hace: ast1060_pac::Hace) { // Demonstrate cancellation - returns controller without computing digest let recovered_controller = context.cancel(); - writeln!(uart, "SHA512 cancellation: PASSED ✅").unwrap(); + writeln!(uart, "SHA512 cancellation: PASS").unwrap(); // Use recovered controller for actual computation with known test vector // Test with known test vector: "abc" -> SHA512 @@ -300,9 +300,9 @@ fn test_owned_sha512(uart: &mut UartController<'_>, hace: ast1060_pac::Hace) { ]; if validate_digest(&digest.value, &expected_sha512, "SHA512", uart) { - writeln!(uart, "SHA512 owned API: PASSED ✅").unwrap(); + writeln!(uart, "SHA512 owned API: PASS").unwrap(); } else { - writeln!(uart, "SHA512 owned API: FAILED ❌").unwrap(); + writeln!(uart, "SHA512 owned API: FAIL").unwrap(); } } @@ -372,6 +372,9 @@ fn main() -> ! { gpio_test::test_gpio_flash_power(&mut uart_controller); spi::spitest::test_spi2(&mut uart_controller); } + + writeln!(uart_controller, "\r\nCOMPLETE\r\n").unwrap(); + // Initialize the peripherals here if needed loop { cortex_m::asm::wfi(); diff --git a/src/spi/spitest.rs b/src/spi/spitest.rs index 7c94b72..cace60e 100644 --- a/src/spi/spitest.rs +++ b/src/spi/spitest.rs @@ -187,7 +187,7 @@ pub fn test_read_jedec, E>(uart: &mut UartController< astdebug::print_array_u8(uart, &id); } _ => { - test_log!(uart, "Error:: Failed to read JEDEC ID"); + test_log!(uart, "Error:: Failed to read JEDEC ID (FAIL)"); } } } @@ -282,9 +282,9 @@ pub fn test_cs, E>( == core::slice::from_raw_parts(ptr_read, len); } if result { - test_log!(uart, "read write test passed!"); + test_log!(uart, "read write test PASS!"); } else { - test_log!(uart, "ERROR:: read write test failed!!"); + test_log!(uart, "ERROR:: read write test FAIL!!"); test_log!(uart, "write buffer:"); astdebug::print_array_u8(uart, wbuf); test_log!(uart, "read buffer:"); @@ -448,10 +448,10 @@ pub fn test_spi(uart: &mut UartController<'_>) { match flash_device.nor_read_jedec_id() { Ok(id) => match NorFlashBlockDevice::from_jedec_id(flash_device, id) { Ok(mut blockdev) => test_block_device::<_>(&mut blockdev), - Err(_e) => test_log!(uart, "start block device using jedec id failed"), + Err(_e) => test_log!(uart, "start block device using jedec id failed (FAIL)"), }, _ => { - test_log!(uart, "Error:: Failed to read JEDEC ID"); + test_log!(uart, "Error:: Failed to read JEDEC ID (FAIL)"); } } } else { @@ -591,8 +591,8 @@ pub fn test_block_device(blockdev: &mut NorFlashBlockDevice) testsize ); match blockdev.program(norflashblockdevice::BlockAddrUsize(addr), wbuf) { - Ok(()) => test_log!(uartc, "program successful"), - Err(_e) => test_log!(uartc, "program failed"), + Ok(()) => test_log!(uartc, "program PASS"), + Err(_e) => test_log!(uartc, "program FAIL"), } let _ = blockdev.read(norflashblockdevice::BlockAddrUsize(addr), rbuf); @@ -603,9 +603,9 @@ pub fn test_block_device(blockdev: &mut NorFlashBlockDevice) == core::slice::from_raw_parts(ptr_read, testsize); } if result { - test_log!(uartc, "read write test passed!"); + test_log!(uartc, "read write test passed (PASS)!"); } else { - test_log!(uartc, "ERROR:: read write test failed!!"); + test_log!(uartc, "ERROR:: read write test failed (FAIL)!!"); test_log!(uartc, "write buffer:"); astdebug::print_array_u8(&mut uartc, wbuf); test_log!(uartc, "read buffer:"); diff --git a/src/tests/functional/ecdsa_test.rs b/src/tests/functional/ecdsa_test.rs index 39d6601..611ccd5 100644 --- a/src/tests/functional/ecdsa_test.rs +++ b/src/tests/functional/ecdsa_test.rs @@ -107,9 +107,9 @@ pub fn run_ecdsa_tests( writeln!(uart, "\r\nTest case {i}... ").unwrap(); let _ = match (result.is_ok(), vec.result) { - (true, true) => writeln!(uart, "\rresult expected (pass), Pass"), - (false, false) => writeln!(uart, "\rresult expected (fail), Pass"), - _ => writeln!(uart, "\rresult unexpected (got {result:?}), Failed"), + (true, true) => writeln!(uart, "\rresult expected (pass), PASS"), + (false, false) => writeln!(uart, "\rresult expected (fail), PASS"), + _ => writeln!(uart, "\rresult unexpected (got {result:?}), FAIL"), }; } } diff --git a/src/tests/functional/gpio_test.rs b/src/tests/functional/gpio_test.rs index c971ba6..35c4a74 100644 --- a/src/tests/functional/gpio_test.rs +++ b/src/tests/functional/gpio_test.rs @@ -34,24 +34,24 @@ pub fn test_gpioa(uart: &mut UartController<'_>) { let mut pa3 = gpioa.pa3.into_open_drain_output::(); pa3.set_low().unwrap(); if pa3.is_set_low().unwrap() { - uart.write_all(b"\rGPIOA pin3 set low successfully\r\n") + uart.write_all(b"\rGPIOA pin3 set low successfully (PASS)\r\n") .unwrap(); } pa3.set_high().unwrap(); if pa3.is_set_high().unwrap() { - uart.write_all(b"\rGPIOA pin3 set high successfully\r\n") + uart.write_all(b"\rGPIOA pin3 set high successfully (PASS)\r\n") .unwrap(); } let mut pa4 = gpioa.pa4.into_push_pull_output(); pa4.set_low().unwrap(); if pa4.is_set_low().unwrap() { - uart.write_all(b"\rGPIOA pin4 set low successfully\r\n") + uart.write_all(b"\rGPIOA pin4 set low successfully (PASS)\r\n") .unwrap(); } pa4.set_high().unwrap(); if pa4.is_set_high().unwrap() { - uart.write_all(b"\rGPIOA pin4 set high successfully\r\n") + uart.write_all(b"\rGPIOA pin4 set high successfully (PASS)\r\n") .unwrap(); } } @@ -90,12 +90,12 @@ pub fn test_gpio_bmc_reset(uart: &mut UartController<'_>) { let mut pm5 = gpiom.pm5.into_push_pull_output(); pm5.set_low().unwrap(); if pm5.is_set_low().unwrap() { - uart.write_all(b"\r\nGPIOM pin5 set low successfully\r\n") + uart.write_all(b"\r\nGPIOM pin5 set low successfully (PASS)\r\n") .unwrap(); } pm5.set_high().unwrap(); if pm5.is_set_high().unwrap() { - uart.write_all(b"\r\nGPIOM pin5 set high successfully\r\n") + uart.write_all(b"\r\nGPIOM pin5 set high successfully (PASS)\r\n") .unwrap(); } } @@ -111,12 +111,12 @@ pub fn test_gpio_bmc_reset(uart: &mut UartController<'_>) { let mut ph2 = gpioh.ph2.into_push_pull_output(); ph2.set_low().unwrap(); if ph2.is_set_low().unwrap() { - uart.write_all(b"\r\nGPIOH pin2 set low successfully\r\n") + uart.write_all(b"\r\nGPIOH pin2 set low successfully (PASS)\r\n") .unwrap(); } ph2.set_high().unwrap(); if ph2.is_set_high().unwrap() { - uart.write_all(b"\r\nGPIOH pin2 set high successfully\r\n") + uart.write_all(b"\r\nGPIOH pin2 set high successfully (PASS)\r\n") .unwrap(); } } diff --git a/src/tests/functional/hash_test.rs b/src/tests/functional/hash_test.rs index bec1fef..604ee92 100644 --- a/src/tests/functional/hash_test.rs +++ b/src/tests/functional/hash_test.rs @@ -93,9 +93,9 @@ where if let Some(expected) = expected { if output.as_ref() == expected { - writeln!(uart, "\r\n{}: Test passed!", core::any::type_name::()).unwrap(); + writeln!(uart, "\r\n{}: Test PASS", core::any::type_name::()).unwrap(); } else { - writeln!(uart, "\r\n{}: Test failed!", core::any::type_name::()).unwrap(); + writeln!(uart, "\r\n{}: Test FAIL", core::any::type_name::()).unwrap(); writeln!(uart, "Expected:").unwrap(); print_hex_array(uart, expected, 16); writeln!(uart, "Got:").unwrap(); diff --git a/src/tests/functional/hmac_test.rs b/src/tests/functional/hmac_test.rs index 37a28b4..62ec57f 100644 --- a/src/tests/functional/hmac_test.rs +++ b/src/tests/functional/hmac_test.rs @@ -99,9 +99,9 @@ where if let Some(expected) = expected { if output.as_ref() == expected { - writeln!(uart, "\r\n{}: Test passed!", core::any::type_name::()).unwrap(); + writeln!(uart, "\r\n{}: Test PASS", core::any::type_name::()).unwrap(); } else { - writeln!(uart, "\r\n{}: Test failed!", core::any::type_name::()).unwrap(); + writeln!(uart, "\r\n{}: Test FAIL", core::any::type_name::()).unwrap(); writeln!(uart, "Expected:").unwrap(); print_hex_array(uart, expected, 16); writeln!(uart, "Got:").unwrap(); diff --git a/src/tests/functional/i2c_test.rs b/src/tests/functional/i2c_test.rs index 2f33a50..29ef642 100644 --- a/src/tests/functional/i2c_test.rs +++ b/src/tests/functional/i2c_test.rs @@ -112,8 +112,8 @@ pub fn test_i2c_master(uart: &mut UartController<'_>) { .smbus_alert(false) .speed(I2cSpeed::Standard) .build(); - let mut i2c1: I2cController< - Ast1060I2c, + let mut i2c2: I2cController< + Ast1060I2c, NoOpLogger, > = I2cController { hardware: Ast1060I2c::new(UartLogger::new(&mut dbg_uart)), @@ -121,26 +121,26 @@ pub fn test_i2c_master(uart: &mut UartController<'_>) { logger: NoOpLogger {}, }; - pinctrl::Pinctrl::apply_pinctrl_group(pinctrl::PINCTRL_I2C1); - i2c1.hardware.init(&mut i2c1.config); + pinctrl::Pinctrl::apply_pinctrl_group(pinctrl::PINCTRL_I2C2); + i2c2.hardware.init(&mut i2c2.config); let addr = 0x2e; //device ADT7490 let mut buf = [0x4e]; if true { - match i2c1.hardware.write(addr, &buf) { + match i2c2.hardware.write(addr, &buf) { Ok(val) => { - writeln!(uart, "i2c write ok: {val:?}\r").unwrap(); + writeln!(uart, "i2c write PASS: {val:?}\r").unwrap(); } Err(e) => { - writeln!(uart, "i2c write err: {e:?}\r").unwrap(); + writeln!(uart, "i2c write FAIL: {e:?}\r").unwrap(); } } - match i2c1.hardware.read(addr, &mut buf) { + match i2c2.hardware.read(addr, &mut buf) { Ok(val) => { - writeln!(uart, "i2c read ok: {val:?}\r").unwrap(); + writeln!(uart, "i2c read PASS: {val:?}\r").unwrap(); } Err(e) => { - writeln!(uart, "i2c read err: {e:?}\r").unwrap(); + writeln!(uart, "i2c read FAIL: {e:?}\r").unwrap(); } } writeln!(uart, "after read data {:#x}, expected: 0x81\r\n", buf[0]).unwrap(); @@ -150,20 +150,20 @@ pub fn test_i2c_master(uart: &mut UartController<'_>) { let mut buf = [0x0]; for (i, &off) in reg_addr.iter().enumerate() { buf[0] = off; - match i2c1.hardware.write(addr, &buf) { + match i2c2.hardware.write(addr, &buf) { Ok(val) => { - writeln!(uart, "i2c write ok: {val:?}\r").unwrap(); + writeln!(uart, "i2c write PASS: {val:?}\r").unwrap(); } Err(e) => { - writeln!(uart, "i2c write err: {e:?}\r").unwrap(); + writeln!(uart, "i2c write FAIL: {e:?}\r").unwrap(); } } - match i2c1.hardware.read(addr, &mut buf) { + match i2c2.hardware.read(addr, &mut buf) { Ok(val) => { - writeln!(uart, "i2c read ok: {val:?}\r").unwrap(); + writeln!(uart, "i2c read PASS: {val:?}\r").unwrap(); } Err(e) => { - writeln!(uart, "i2c read err: {e:?}\r").unwrap(); + writeln!(uart, "i2c read FAIL: {e:?}\r").unwrap(); } } writeln!( @@ -176,30 +176,30 @@ pub fn test_i2c_master(uart: &mut UartController<'_>) { if false { writeln!(uart, "########### write 0x3 to offset 0x82 \r\n").unwrap(); let buf2 = [0x82, 0x3]; - match i2c1.hardware.write(addr, &buf2) { + match i2c2.hardware.write(addr, &buf2) { Ok(val) => { - writeln!(uart, "i2c write ok: {val:?}\r").unwrap(); + writeln!(uart, "i2c write PASS: {val:?}\r").unwrap(); } Err(e) => { - writeln!(uart, "i2c write err: {e:?}\r").unwrap(); + writeln!(uart, "i2c write FAIL: {e:?}\r").unwrap(); } } buf[0] = 0x82; writeln!(uart, "########### read 0x82 \r\n").unwrap(); - match i2c1.hardware.write(addr, &buf) { + match i2c2.hardware.write(addr, &buf) { Ok(val) => { - writeln!(uart, "i2c write ok: {val:?}\r").unwrap(); + writeln!(uart, "i2c write PASS: {val:?}\r").unwrap(); } Err(e) => { - writeln!(uart, "i2c write err: {e:?}\r").unwrap(); + writeln!(uart, "i2c write FAIL: {e:?}\r").unwrap(); } } - match i2c1.hardware.read(addr, &mut buf) { + match i2c2.hardware.read(addr, &mut buf) { Ok(val) => { - writeln!(uart, "i2c read ok: {val:?}\r").unwrap(); + writeln!(uart, "i2c read PASS: {val:?}\r").unwrap(); } Err(e) => { - writeln!(uart, "i2c read err: {e:?}\r").unwrap(); + writeln!(uart, "i2c read FAIL: {e:?}\r").unwrap(); } } writeln!( @@ -286,10 +286,10 @@ pub fn test_i2c_slave(uart: &mut UartController<'_>) { .i2c_aspeed_slave_register(TEST_TARGET.address, None) { Ok(val) => { - writeln!(uart, "i2c slave register ok: {val:?}\r").unwrap(); + writeln!(uart, "i2c slave register PASS: {val:?}\r").unwrap(); } Err(e) => { - writeln!(uart, "i2c slave register err: {e:?}\r").unwrap(); + writeln!(uart, "i2c slave register FAIL: {e:?}\r").unwrap(); } } diff --git a/src/tests/functional/rsa_test.rs b/src/tests/functional/rsa_test.rs index caace49..92cc62e 100644 --- a/src/tests/functional/rsa_test.rs +++ b/src/tests/functional/rsa_test.rs @@ -90,10 +90,10 @@ where continue; } - writeln!(uart, "\rRSA vector[{i}] sign passed").ok(); + writeln!(uart, "\rRSA vector[{i}] sign PASS").ok(); } Err(_err) => { - writeln!(uart, "\rRSA vector[{i}] sign failed").ok(); + writeln!(uart, "\rRSA vector[{i}] sign FAIL").ok(); } } } @@ -170,10 +170,10 @@ where match result { Ok(_decrypted) => { - writeln!(uart, "\rRSA vector[{i}] verify passed").ok(); + writeln!(uart, "\rRSA vector[{i}] verify PASS").ok(); } Err(err) => { - writeln!(uart, "\rRSA vector[{i}] verify failed: {err:?}").ok(); + writeln!(uart, "\rRSA vector[{i}] verify FAIL: {err:?}").ok(); } } }