Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
423 changes: 423 additions & 0 deletions .github/workflows/hardware-test.yml

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <path to UART> 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.)

150 changes: 150 additions & 0 deletions docs/ci-aspeed.md
Original file line number Diff line number Diff line change
@@ -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.
221 changes: 221 additions & 0 deletions scripts/ast-bin-create-and-package.sh
Original file line number Diff line number Diff line change
@@ -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('<I', size))
# Write binary data
f.write(data)

if not quiet:
print(f'Created UART boot image: {output_path}')
print(f'Header size: 4 bytes')
print(f'Payload size: {size} bytes')
print(f'Total size: {size + 4} bytes')

except Exception as e:
print(f'Error creating UART boot image: {e}')
sys.exit(1)
"
else
# Use existing script
if ! "$UART_BOOT_SCRIPT" "$RAW_BINARY_PATH" "$OUTPUT_PATH"; then
echo "Error: Failed to create UART boot image"
exit 1
fi
fi

# Verify final binary was created
if [[ ! -f "$OUTPUT_PATH" ]]; then
echo "Error: UART boot image was not created"
exit 1
fi

# Get final sizes
UART_SIZE=$(stat -c%s "$OUTPUT_PATH")

log ""
log "Binary generation completed successfully!"
log "========================================"
log "Raw binary: $RAW_BINARY_PATH ($RAW_SIZE bytes)"
log "UART image: $OUTPUT_PATH ($UART_SIZE bytes)"
log "Header overhead: $((UART_SIZE - RAW_SIZE)) bytes"

# Calculate utilization
UTILIZATION=$((RAW_SIZE * 100 / MAX_SIZE))
log "Flash utilization: $UTILIZATION% of ${MAX_SIZE} bytes"

if [[ $UTILIZATION -gt 90 ]]; then
log "Warning: Flash utilization is high (>90%)"
fi

log ""
log "Ready for UART upload to AST1060!"
Loading
Loading