Relocated monitor to top 16k
This commit is contained in:
@@ -9,10 +9,13 @@ METAL_RELFILES := $(METAL_ASM_SRCFILES:%.asm=$(BUILDDIR)/metal/%.rel) \
|
||||
METAL_CC := sdcc
|
||||
METAL_AS := sdasz80
|
||||
METAL_MAKEBIN := makebin
|
||||
METAL_FLAGS := -mz80 --no-std-crt0 --code-loc 0x0080 --data-loc 0x8000
|
||||
METAL_FLAGS := -mz80 --no-std-crt0 --code-loc 0xC080 --code-size 0x2F80 --data-loc 0xF000
|
||||
METAL_CPPFLAGS := -I src -I $(BUILDDIR)/metal/generated --disable-warning 283
|
||||
METAL_BIN_SIZE := 32768
|
||||
METAL_RAM_SIZE := 32768
|
||||
METAL_RAM_SIZE := 16384
|
||||
METAL_IMAGE_SIZE := 65536
|
||||
MONITOR_BASE := 0xC000
|
||||
MONITOR_ROM_OFFSET := 128
|
||||
|
||||
.DEFAULT_GOAL := metal
|
||||
|
||||
@@ -21,24 +24,34 @@ METAL_RAM_SIZE := 32768
|
||||
all: metal
|
||||
|
||||
metal: $(BUILDDIR)/metal/$(TARGET).ihx $(BUILDDIR)/metal/$(TARGET).bin $(BUILDDIR)/metal/$(TARGET).prog.bin
|
||||
@awk -v rom_capacity=$(METAL_BIN_SIZE) -v ram_capacity=$(METAL_RAM_SIZE) '\
|
||||
$$1 ~ /^_(CODE|HOME|GSINIT|GSFINAL|INITIALIZER|ITABLE[0-7]*)$$/ { rom += $$5 } \
|
||||
$$1 ~ /^_(DATA|INITIALIZED|BSEG|BSS|HEAP|STACK)$$/ { ram += $$5 } \
|
||||
@stored=$$(wc -c < $(BUILDDIR)/metal/$(TARGET).prog.bin); \
|
||||
awk -v rom_capacity=$(METAL_BIN_SIZE) -v stored=$$stored -v ram_capacity=$(METAL_RAM_SIZE) '\
|
||||
$$1 ~ /^_(CODE|HOME|GSINIT|GSFINAL|INITIALIZER)$$/ || $$1 ~ /^_ITABLE/ { code += $$5 } \
|
||||
$$1 ~ /^_(DATA|INITIALIZED|BSEG|BSS|HEAP)$$/ { data += $$5 } \
|
||||
END { \
|
||||
printf "\nMemory usage:\n"; \
|
||||
printf " ROM: %5u / %5u bytes (%5.1f%%), %5u bytes free\n", rom, rom_capacity, 100 * rom / rom_capacity, rom_capacity - rom; \
|
||||
printf " RAM: %5u / %5u bytes (%5.1f%%), %5u bytes free\n", ram, ram_capacity, 100 * ram / ram_capacity, ram_capacity - ram; \
|
||||
printf " ROM storage: %5u / %5u bytes (%5.1f%%)\n", stored, rom_capacity, 100 * stored / rom_capacity; \
|
||||
printf " Runtime RAM: %5u / %5u bytes (%5.1f%%), %5u bytes for growth/stack\n", code + data, ram_capacity, 100 * (code + data) / ram_capacity, ram_capacity - code - data; \
|
||||
printf " code/vector: %5u bytes; static data: %5u bytes\n", code, data; \
|
||||
}' $(BUILDDIR)/metal/$(TARGET).map
|
||||
|
||||
$(BUILDDIR)/metal/$(TARGET).ihx: $(METAL_RELFILES)
|
||||
@mkdir -p $(@D)
|
||||
$(METAL_CC) $(METAL_FLAGS) -o $@ $(METAL_RELFILES)
|
||||
|
||||
$(BUILDDIR)/metal/$(TARGET).bin: $(BUILDDIR)/metal/$(TARGET).ihx
|
||||
$(METAL_MAKEBIN) -s $(METAL_BIN_SIZE) $< $@
|
||||
$(BUILDDIR)/metal/$(TARGET).flat.bin: $(BUILDDIR)/metal/$(TARGET).ihx
|
||||
$(METAL_MAKEBIN) -s $(METAL_IMAGE_SIZE) $< $@
|
||||
|
||||
$(BUILDDIR)/metal/$(TARGET).prog.bin: $(BUILDDIR)/metal/$(TARGET).ihx
|
||||
$(METAL_MAKEBIN) -p $< $@
|
||||
$(BUILDDIR)/metal/$(TARGET).prog.bin: $(BUILDDIR)/metal/$(TARGET).flat.bin
|
||||
@payload_end=$$(awk '$$1 == "DEF" && $$2 == "monitor_image_end" { print $$3 }' $(BUILDDIR)/metal/$(TARGET).noi); \
|
||||
payload_size=$$((payload_end - $(MONITOR_BASE))); \
|
||||
test $$payload_size -gt 0; \
|
||||
dd if=$< of=$@ bs=1 count=$(MONITOR_ROM_OFFSET) status=none; \
|
||||
dd if=$< of=$@ bs=1 skip=$$(( $(MONITOR_BASE) )) seek=$(MONITOR_ROM_OFFSET) count=$$payload_size conv=notrunc status=none
|
||||
|
||||
$(BUILDDIR)/metal/$(TARGET).bin: $(BUILDDIR)/metal/$(TARGET).flat.bin $(BUILDDIR)/metal/$(TARGET).prog.bin
|
||||
dd if=$< of=$@ bs=$(METAL_BIN_SIZE) count=1 status=none
|
||||
dd if=$(BUILDDIR)/metal/$(TARGET).prog.bin of=$@ conv=notrunc status=none
|
||||
|
||||
$(BUILDDIR)/metal/%.rel: %.c
|
||||
@mkdir -p $(@D)
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
# Z80 UART monitor
|
||||
|
||||
This ROM provides a small interactive monitor on the UART/CTC card at I/O base
|
||||
`20`. Connect a terminal at **2400 baud, 8 data bits, no parity, 1 stop bit**.
|
||||
`20`. At reset, a small ROM bootstrap copies the monitor into the top 16 KiB of
|
||||
RAM at `C000-FFFF` and starts it there. Only the occupied vector/code bytes are
|
||||
stored and copied; uninitialized data is cleared directly in high RAM. The low ROM can subsequently be disabled
|
||||
without taking the monitor, its data, or its interrupt table away. Runtime code
|
||||
and vectors occupy the lower part of this window, globals begin at `F000`, and
|
||||
the stack grows downward from `FFFF`; no RAM below `C000` is used.
|
||||
|
||||
Connect a terminal at **2400 baud, 8 data bits, no parity, 1 stop bit**.
|
||||
Commands are case-insensitive and all numeric arguments are hexadecimal; an
|
||||
optional `0x` prefix is accepted.
|
||||
|
||||
@@ -26,4 +33,12 @@ make
|
||||
```
|
||||
|
||||
The outputs are `build/metal/monitor.bin` (32 KiB ROM image) and
|
||||
`build/metal/monitor.prog.bin` (compact programmer image).
|
||||
`build/metal/monitor.prog.bin` (compact programmer image). The ROM layout is:
|
||||
|
||||
- `0000-007F`: reset/copy bootstrap
|
||||
- `0080...`: compact vector/code image copied to RAM starting at `C000`
|
||||
- Remaining bytes: unused and available for additional ROM content
|
||||
|
||||
The monitor executable starts at `C080`; its IM 2 vector table is at `C040`.
|
||||
`monitor.prog.bin` ends immediately after the occupied payload, while
|
||||
`monitor.bin` remains a complete 32 KiB chip image.
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
STACK_TOP = 0xFFFF
|
||||
DELAY_LOOPS_PER_MS = 40
|
||||
MONITOR_BASE = 0xC000
|
||||
MONITOR_ROM_SOURCE = 0x0080
|
||||
|
||||
.globl _main
|
||||
.globl _delay_ms
|
||||
@@ -8,33 +10,49 @@ DELAY_LOOPS_PER_MS = 40
|
||||
.globl _enable_interrupts
|
||||
.globl _disable_interrupts
|
||||
.globl _jump_to
|
||||
.globl monitor_image_end
|
||||
.globl s__DATA
|
||||
.globl l__DATA
|
||||
.globl s__INITIALIZER
|
||||
.globl s__INITIALIZED
|
||||
.globl l__INITIALIZER
|
||||
|
||||
.area _ITABLE (ABS)
|
||||
.area _BOOT (ABS)
|
||||
|
||||
.org 0x00
|
||||
jp init
|
||||
jp boot_copy
|
||||
.org 0x08
|
||||
boot_copy:
|
||||
di
|
||||
ld sp, #STACK_TOP
|
||||
ld hl, #MONITOR_ROM_SOURCE
|
||||
ld de, #MONITOR_BASE
|
||||
ld bc, #(monitor_image_end - MONITOR_BASE)
|
||||
ldir
|
||||
jp init
|
||||
|
||||
.area _ITABLE (ABS)
|
||||
|
||||
; The executable vector page is part of the image copied to high RAM.
|
||||
.org MONITOR_BASE
|
||||
jp init
|
||||
.org MONITOR_BASE + 0x08
|
||||
reti
|
||||
.org 0x10
|
||||
.org MONITOR_BASE + 0x10
|
||||
reti
|
||||
.org 0x18
|
||||
.org MONITOR_BASE + 0x18
|
||||
reti
|
||||
.org 0x20
|
||||
.org MONITOR_BASE + 0x20
|
||||
reti
|
||||
.org 0x28
|
||||
.org MONITOR_BASE + 0x28
|
||||
reti
|
||||
.org 0x30
|
||||
.org MONITOR_BASE + 0x30
|
||||
reti
|
||||
.org 0x38
|
||||
.org MONITOR_BASE + 0x38
|
||||
reti
|
||||
|
||||
; ITABLE
|
||||
.org 0x40
|
||||
; IM 2 table: the CTC supplies vectors 40, 42, 44, and 46.
|
||||
.org MONITOR_BASE + 0x40
|
||||
.dw ctc_isr ; CTC channel 0: vector 0x40
|
||||
.dw ctc_isr ; CTC channel 1: vector 0x42
|
||||
.dw ctc_isr ; CTC channel 2: vector 0x44
|
||||
@@ -48,7 +66,7 @@ init:
|
||||
call gsinit
|
||||
|
||||
; Setup interrupt mode 2
|
||||
xor a
|
||||
ld a, #0xC0
|
||||
ld i, a
|
||||
im 2
|
||||
call _main
|
||||
@@ -88,6 +106,7 @@ clear_loop:
|
||||
gsinit_done:
|
||||
.area _GSFINAL
|
||||
ret
|
||||
monitor_image_end:
|
||||
|
||||
.area _CODE
|
||||
|
||||
|
||||
Reference in New Issue
Block a user