minos/Makefile
Шурупов Илья Викторович 775a02cf3f Add D1/Lichee RV hardware boot and UART input
Bring up minos on the Allwinner D1 (Lichee RV) over FEL/xfel and add
bidirectional UART so the console can read keystrokes, not just print.

D1 / Lichee RV boot:
- riscv arch.c: select UART0 base by -DBOARD_D1 (0x02500000 vs QEMU
  0x10000000) and add a reg-shift abstraction (uart_rd/uart_wr): the D1's
  Synopsys DW-8250 uses 32-bit registers at 4-byte spacing, which is what
  made the first hardware boot silent.
- d1_uart0_init(): gate/deassert UART0 clock, mux PB8/PB9 to UART0, set
  115200 8N1, clear FIFOs, force non-loopback, drain stale RX.
- link-d1.ld: link for DRAM at 0x40000000 (xfel exec target, M-mode).
- Makefile: 'lichee' builds the flat binary; 'run-lichee' loads it via
  xfel (ddr d1 / write / exec).
- arch_name() reports the concrete board.

UART input (all archs):
- arch contract gains arch_uart_getc() and arch_uart_rx_ready(),
  implemented for riscv, x86 (COM1) and arm (Cadence UART).
- console gains getc() and drain_rx().
- kmain() runs an interactive echo loop (seed of the M3 console).

Verified: echo works under QEMU on x86/riscv/arm, and on real D1
hardware (banner once, then live keystroke echo over UART0 @115200).
2026-09-25 21:13:59 +03:00

110 lines
3.8 KiB
Makefile

# minos — minimal multi-arch kernel (M1)
# One clang, three ISAs. Build all in parallel: make -j
#
# make build all three (x86, riscv, arm)
# make x86 build one arch
# make run-riscv build + boot that arch under QEMU (-nographic; Ctrl-A X to quit)
# make sizes compare code size across arches
# make clean
CC := clang
LD := ld.lld
OBJCOPY := llvm-objcopy
ARCHES := x86 riscv arm
# Shared flags. Per-arch target/flags below.
CFLAGS := -ffreestanding -nostdlib -fno-pic -O2 -Wall -Wextra -Iinclude -g -MMD -MP
COMMON := common/main.c common/console.c
# --- per-arch knobs -------------------------------------------------------
x86_TARGET := --target=i386-unknown-none -m32
x86_LDEMU := elf_i386
x86_SRC := arch/x86/boot.S arch/x86/arch.c $(COMMON)
x86_QEMU := qemu-system-i386 -kernel build/x86/minos.elf -nographic
riscv_TARGET := --target=riscv64-unknown-none-elf -march=rv64imac -mabi=lp64 -mcmodel=medany
riscv_LDEMU := elf64lriscv
riscv_SRC := arch/riscv/boot.S arch/riscv/trap.S arch/riscv/arch.c $(COMMON)
riscv_QEMU := qemu-system-riscv64 -machine virt -bios none -nographic -kernel build/riscv/minos.elf
arm_TARGET := --target=arm-none-eabi -mcpu=cortex-a9 -marm
arm_LDEMU := armelf
arm_SRC := arch/arm/boot.S arch/arm/vectors.S arch/arm/arch.c $(COMMON)
arm_QEMU := qemu-system-arm -machine xilinx-zynq-a9 -cpu cortex-a9 -nographic -kernel build/arm/minos.elf
.PHONY: all clean sizes $(ARCHES) $(addprefix run-,$(ARCHES))
all: $(ARCHES)
# Generate per-arch build rules.
define ARCH_rules
$(1)_OBJS := $$(patsubst %,build/$(1)/%.o,$$(basename $$(notdir $$($(1)_SRC))))
build/$(1)/%.o: arch/$(1)/%.S | build/$(1)
$$(CC) $$($(1)_TARGET) $$(CFLAGS) -c $$< -o $$@
build/$(1)/%.o: arch/$(1)/%.c | build/$(1)
$$(CC) $$($(1)_TARGET) $$(CFLAGS) -c $$< -o $$@
build/$(1)/%.o: common/%.c | build/$(1)
$$(CC) $$($(1)_TARGET) $$(CFLAGS) -c $$< -o $$@
build/$(1):
mkdir -p $$@
build/$(1)/minos.elf: $$($(1)_OBJS) arch/$(1)/link.ld
$$(LD) -m $$($(1)_LDEMU) -T arch/$(1)/link.ld -nostdlib $$($(1)_OBJS) -o $$@
@echo " [$(1)] linked -> $$@"
$(1): build/$(1)/minos.elf
run-$(1): build/$(1)/minos.elf
@echo "== booting $(1) (Ctrl-A X to quit) =="
$$($(1)_QEMU)
-include $$($(1)_OBJS:.o=.d)
endef
$(foreach a,$(ARCHES),$(eval $(call ARCH_rules,$(a))))
sizes: all
@echo "arch text+data+bss (bytes)"; \
for a in $(ARCHES); do \
printf '%-7s ' $$a; \
$(OBJCOPY) -O binary build/$$a/minos.elf /tmp/_sz.bin 2>/dev/null; \
stat -c '%s' /tmp/_sz.bin; \
done; rm -f /tmp/_sz.bin
# --- real hardware: Allwinner D1 / Lichee RV via xfel ------------------------
# Same RISC-V sources, rebuilt with -DBOARD_D1 (UART 0x02500000) and linked
# for DRAM 0x40000000, emitted as a flat binary xfel can load.
XFEL ?= xfel
D1_TARGET := $(riscv_TARGET) -DBOARD_D1
D1_OBJS := $(patsubst %,build/lichee/%.o,$(basename $(notdir $(riscv_SRC))))
build/lichee/%.o: arch/riscv/%.S | build/lichee
$(CC) $(D1_TARGET) $(CFLAGS) -c $< -o $@
build/lichee/%.o: arch/riscv/%.c | build/lichee
$(CC) $(D1_TARGET) $(CFLAGS) -c $< -o $@
build/lichee/%.o: common/%.c | build/lichee
$(CC) $(D1_TARGET) $(CFLAGS) -c $< -o $@
build/lichee:
mkdir -p $@
build/lichee/minos.elf: $(D1_OBJS) arch/riscv/link-d1.ld
$(LD) -m $(riscv_LDEMU) -T arch/riscv/link-d1.ld -nostdlib $(D1_OBJS) -o $@
build/lichee/minos.bin: build/lichee/minos.elf
$(OBJCOPY) -O binary $< $@
@echo " [lichee] flat binary -> $@ ($$(stat -c%s $@) bytes)"
.PHONY: lichee run-lichee
lichee: build/lichee/minos.bin ## build the D1 flat binary
# Load & run on the board (must be in FEL mode; needs sudo for USB).
run-lichee: build/lichee/minos.bin
@echo "== loading minos onto D1 via xfel =="
$(XFEL) ddr d1
$(XFEL) write 0x40000000 build/lichee/minos.bin
$(XFEL) exec 0x40000000
@echo "== running. Watch /dev/ttyUSB0 @115200 for output. =="
clean:
rm -rf build