blob: 7cf5e714f0ff2113f0b3add2f9d20adbdc1ce440 [file] [view] [edit]
# AST1060 Target Guide
This document explains the out-of-tree Pigweed kernel targets for AST1060.
## Overview
There are two AST1060 targets in this workspace:
| Target | Purpose | Console | Use Case |
|--------|---------|---------|----------|
| `ast1060` | QEMU emulation | Semihosting | Development, CI testing |
| `ast1060-evb` | Physical hardware | UART | Real board testing |
## Architecture
```
bazel-stuff/
├── target/
│ ├── ast1060/ # QEMU target
│ │ ├── BUILD.bazel # Platform + rust_library targets
│ │ ├── defs.bzl # TARGET_COMPATIBLE_WITH constraint
│ │ ├── config.rs # KernelConfig (SysTick, MPU regions)
│ │ ├── entry.rs # Reset handler + boot sequence
│ │ ├── target.ld.tmpl # Linker script template
│ │ └── threads/kernel/ # Threads test application
│ │ ├── BUILD.bazel
│ │ ├── system.json5 # Memory layout
│ │ └── target.rs # Application entry point
│ │
│ └── ast1060-evb/ # Physical board target
│ ├── BUILD.bazel
│ ├── defs.bzl
│ ├── config.rs
│ ├── entry.rs # Initializes UART before kernel
│ ├── console_backend.rs # UART driver via aspeed-ddk
│ ├── target.ld.tmpl
│ └── threads/kernel/
│ ├── BUILD.bazel
│ ├── system.json5
│ └── target.rs
```
## How It Works
### 1. Platform Definition (`BUILD.bazel`)
Each target defines a Bazel platform with CPU and OS constraints:
```python
platform(
name = "ast1060",
constraint_values = [
"@platforms//cpu:armv7-m",
"@platforms//os:none",
"@pigweed//pw_kernel:os_freestanding",
"//platform:ast1060", # Custom constraint
],
)
```
The platform tells Bazel which toolchain to use (ARM Cortex-M cross-compiler).
### 2. Kernel Configuration (`config.rs`)
Provides hardware-specific settings to the kernel:
```rust
impl KernelConfig for Config {
const SYSTICK_HZ: u32 = 12_000_000; // 12 MHz clock
const ARM_V7_MPU_REGIONS: usize = 8; // MPU region count
}
```
### 3. Boot Entry (`entry.rs`)
The reset handler that runs at power-on:
```rust
#[cortex_m_rt::entry]
fn main() -> ! {
// For ast1060-evb: Initialize UART here
uart_init();
// Jump to kernel target
target_common::enter_kernel_main()
}
```
### 4. Console Backend
**QEMU (`ast1060`):** Uses ARM semihosting - debug output goes through QEMU to host terminal.
**Physical Board (`ast1060-evb`):** Uses UART via aspeed-ddk driver:
```rust
// console_backend.rs
static UART: Mutex<RefCell<Option<Uart>>> = ...;
pub fn uart_write(data: &[u8]) {
critical_section::with(|cs| {
if let Some(ref mut uart) = *UART.borrow_ref_mut(cs) {
for byte in data {
uart.write_byte(*byte);
}
}
});
}
```
### 5. Memory Layout (`system.json5`)
Defines memory regions for the linker:
```json5
{
memory: {
vector_table: { start: 0x00000000, size: 0x400 },
flash: { start: 0x00000400, size: 0x000ffc00 },
ram: { start: 0x80000000, size: 0x00100000 },
}
}
```
### 6. Linker Script (`target.ld.tmpl`)
Template processed by Bazel to generate final linker script with memory addresses from `system.json5`.
## Build Commands
### QEMU Target
```bash
# Build
bazelisk build //target/ast1060/threads/kernel:threads --config=k_qemu_ast1060
# Run in QEMU
bazelisk run //target/ast1060/threads/kernel:threads --config=k_qemu_ast1060
```
### Physical Board Target
```bash
# Build
bazelisk build //target/ast1060-evb/threads/kernel:threads --config=k_ast1060_evb
# The output binary is at:
# bazel-bin/target/ast1060-evb/threads/kernel/threads.bin
```
### Output Files
| File | Header | Use Case |
|------|--------|----------|
| `threads.bin` | No | OpenOCD/JTAG flashing, direct memory load |
| `threads_uart.bin` | **Yes** (4-byte size) | UART bootloader upload |
### Generate UART Boot Image
The AST1060 UART bootloader requires a special header format:
- 4 bytes: image size (little-endian, 4-byte aligned)
- N bytes: binary image data
- 0-3 bytes: zero padding to 4-byte alignment
This is automated via the `uart_boot_image` Bazel rule:
```bash
# Build the UART-bootable image
bazelisk build //target/ast1060-evb/threads/kernel:threads_uart --config=k_ast1060_evb
# Output file:
# bazel-bin/target/ast1060-evb/threads/kernel/threads_uart.bin
```
The rule is defined in `//target:uart_boot_image.bzl` and used in BUILD.bazel:
```python
load("//target:uart_boot_image.bzl", "uart_boot_image")
uart_boot_image(
name = "threads_uart",
src = ":threads", # system_image target
out = "threads_uart.bin",
)
```
## Flashing to Hardware
After building the ast1060-evb target:
```bash
# Using the UART boot image (with header)
# Upload via serial bootloader tool
uart_upload /dev/ttyUSB0 bazel-bin/target/ast1060-evb/threads/kernel/threads_uart.bin
# Or using OpenOCD with raw binary (no header needed)
openocd -f interface/cmsis-dap.cfg -f target/aspeed_ast1060.cfg \
-c "program bazel-bin/target/ast1060-evb/threads/kernel/threads.bin verify reset exit"
```
## Serial Console
Connect to the AST1060-EVB serial port:
```bash
# Find the USB-UART device
ls /dev/ttyUSB*
# Connect at 115200 baud
screen /dev/ttyUSB2 115200
# or
picocom -b 115200 /dev/ttyUSB2
```
Expected output:
```
Hello from AST1060-EVB!
=== pw_kernel ===
...
```
## Key Dependencies
| Crate | Purpose |
|-------|---------|
| `@ast1060_pac` | AST1060 Peripheral Access Crate (register definitions) |
| `aspeed-ddk` | ASPEED device driver kit (UART driver) |
| `cortex-m-rt` | Cortex-M runtime (reset handler, vector table) |
| `cortex-m-semihosting` | ARM semihosting support |
## Configuration Files
### `.bazelrc` Configs
```bash
# QEMU config
common:k_qemu_ast1060 --config=k_common
common:k_qemu_ast1060 --platforms=//target/ast1060
run:k_qemu_ast1060 --run_under="@pigweed//pw_kernel/tooling:qemu ..."
# Physical board config
common:k_ast1060_evb --config=k_common
common:k_ast1060_evb --platforms=//target/ast1060-evb
```
### `MODULE.bazel` Dependencies
The AST1060 PAC is fetched via git:
```python
ast1060_pac = use_extension("//third_party:ast1060_pac.bzl", "ast1060_pac")
use_repo(ast1060_pac, "ast1060_pac")
```
## Differences: QEMU vs Physical Board
| Aspect | ast1060 (QEMU) | ast1060-evb (Physical) |
|--------|----------------|------------------------|
| Console | Semihosting | UART @ 115200 |
| Exit | `semihosting::exit()` | Loop or reset |
| Clock | Emulated | Real 12 MHz |
| Debug | GDB via QEMU | JTAG/SWD |
| Build config | `k_qemu_ast1060` | `k_ast1060_evb` |
## Troubleshooting
### Build Errors
**"No matching toolchains found"**
- Ensure `--platforms=//target/ast1060` is specified
- Check that ARM toolchain is configured in MODULE.bazel
**"unresolved import `ast1060_pac`"**
- Run `cargo generate-lockfile` in `third_party/crates_io/`
- Verify `Cargo.toml` has the ast1060-pac dependency
### Runtime Issues
**No UART output on physical board**
- Check baud rate (115200)
- Verify TX/RX pin connections
- Ensure UART is initialized before any print calls
**QEMU hangs**
- Check CPU type matches (`cortex-m4` for ast1030-evb machine)
- Verify semihosting is enabled in run_under config