diff --git a/Makefile b/Makefile index 41f1385..a125c3a 100644 --- a/Makefile +++ b/Makefile @@ -106,5 +106,51 @@ run-lichee: build/lichee/minos.bin $(XFEL) exec 0x40000000 @echo "== running. Watch /dev/ttyUSB0 @115200 for output. ==" +# --- real hardware: Zynq-7000 PS (Cortex-A9) via JTAG/OpenOCD ---------------- +# Same ARM sources, re-linked into on-chip RAM (OCM at 0x0) so no FSBL/DDR +# init is needed. Loaded over JTAG with OpenOCD (the on-board FT2232H is a +# generic 0403:6010 that Xilinx hw_server won't auto-detect, but OpenOCD does). +OPENOCD ?= openocd +OOCD_CFG := zynq/openocd-zynq.cfg +ZYNQ_OBJS := $(patsubst %,build/zynq/%.o,$(basename $(notdir $(arm_SRC)))) + +build/zynq/%.o: arch/arm/%.S | build/zynq + $(CC) $(arm_TARGET) $(CFLAGS) -c $< -o $@ +build/zynq/%.o: arch/arm/%.c | build/zynq + $(CC) $(arm_TARGET) $(CFLAGS) -c $< -o $@ +build/zynq/%.o: common/%.c | build/zynq + $(CC) $(arm_TARGET) $(CFLAGS) -c $< -o $@ +build/zynq: + mkdir -p $@ + +build/zynq/minos.elf: $(ZYNQ_OBJS) arch/arm/link-zynq-ocm.ld + $(LD) -m $(arm_LDEMU) -T arch/arm/link-zynq-ocm.ld -nostdlib $(ZYNQ_OBJS) -o $@ + @echo " [zynq] OCM ELF -> $@" + +.PHONY: zynq run-zynq +zynq: build/zynq/minos.elf ## build the Zynq OCM ELF + +# Halt A9 core0, load the ELF into OCM, set PC to _start, resume. +# Watch the UART console (ttyUSB1 @115200) for output. +# +# Critical: the on-board boot firmware leaves the core with MMU + D-cache + +# I-cache enabled (SCTLR bits 0/2/12). If we resume like that, the stale +# TLB/cache shadow our freshly loaded OCM and nothing runs. So we clear those +# bits (SCTLR -> 0x08C54C78) and force SVC mode before resuming. We keep the +# firmware's PS clock setup (incl. UART) by halting rather than resetting. +run-zynq: build/zynq/minos.elf + @echo "== loading minos into Zynq OCM via OpenOCD ==" + $(OPENOCD) -f $(OOCD_CFG) \ + -c "init" \ + -c "targets zynq.cpu0" \ + -c "halt" \ + -c "load_image build/zynq/minos.elf" \ + -c "arm mcr 15 0 1 0 0 0x08C54C78" \ + -c "reg pc 0x00000000" \ + -c "reg cpsr 0x000001d3" \ + -c "resume" \ + -c "shutdown" + @echo "== running. Watch /dev/ttyUSB1 @115200 for output. ==" + clean: rm -rf build diff --git a/arch/arm/link-zynq-ocm.ld b/arch/arm/link-zynq-ocm.ld new file mode 100644 index 0000000..3dd3cbb --- /dev/null +++ b/arch/arm/link-zynq-ocm.ld @@ -0,0 +1,40 @@ +/* link-zynq-ocm.ld (ARM, Zynq-7000 real hardware via JTAG) — + * + * On real Zynq the external DDR is NOT usable until an FSBL/ps7_init runs. + * The on-chip RAM (OCM), however, is alive from reset: 192 KiB mapped at + * 0x00000000..0x0002FFFF. We link minos entirely into that low OCM so it + * can be loaded straight over JTAG (OpenOCD) with no FSBL and no DDR init. + * + * We keep the PS clocks that the on-board boot firmware already configured + * by HALTing the A9 (not resetting the whole PS) before loading, so the + * UART remains clocked. QEMU still uses link.ld (DDR at 0x00100000). */ +OUTPUT_FORMAT(elf32-littlearm) +ENTRY(_start) + +MEMORY +{ + OCM (rwx) : ORIGIN = 0x00000000, LENGTH = 192K +} + +SECTIONS +{ + . = 0x00000000; + + .text : { + KEEP(*(.text.boot)) /* _start must be first */ + *(.text .text.*) + } > OCM + + .rodata : { *(.rodata .rodata.*) } > OCM + .data : { *(.data .data.*) } > OCM + + . = ALIGN(8); + __bss_start = .; + .bss : { *(.bss .bss.*) *(COMMON) } > OCM + . = ALIGN(8); + __bss_end = .; + + . = ALIGN(16); + . += 0x4000; /* 16 KiB boot stack */ + _stack_top = .; +} diff --git a/zynq/openocd-zynq.cfg b/zynq/openocd-zynq.cfg new file mode 100644 index 0000000..d842cc9 --- /dev/null +++ b/zynq/openocd-zynq.cfg @@ -0,0 +1,16 @@ +# OpenOCD config for the on-board FT2232H JTAG on this Zynq-7000 board. +# The EEPROM identifies as VID:PID 0403:6010 ("Adapt Device"), a generic +# FT2232H that Xilinx hw_server refuses to auto-detect but OpenOCD drives +# directly. JTAG is FTDI channel 0; channel 1 is the UART console. + +adapter driver ftdi +ftdi vid_pid 0x0403 0x6010 +ftdi channel 0 +# Standard FT2232H JTAG pin layout (TCK/TDI/TDO/TMS on ADBUS0-3). +ftdi layout_init 0x0088 0x008b +reset_config none + +adapter speed 1000 + +# Zynq-7000 PS (dual Cortex-A9) + PL boundary-scan TAP. +source [find target/zynq_7000.cfg]