serial_transfer: self-relocate to the end of system memory

The serial_transfer loader, as long as the target program voluntarily
terminates itself at some point, is able to load multiple programs
consecutively without requiring a physical power cycle to reload the
transfer program from CD.

The current example.mk juggles between two different "memory layouts",
one for "burn to a physical CD" and another for "load via serial
cable". Because the serial_transfer program now relocates itself to
the end of system memory, this means the 0x8c010000 area is now usable
by programs that are loaded by serial_transfer.
This commit is contained in:
Zack Buhman 2024-03-13 20:56:37 +08:00
parent 0806ed9ac7
commit d912278afd
14 changed files with 209 additions and 40 deletions

View File

@ -1,7 +1,8 @@
OUTPUT_FORMAT("elf32-shl", "elf32-shl", "elf32-shl") OUTPUT_FORMAT("elf32-shl", "elf32-shl", "elf32-shl")
MEMORY MEMORY
{ {
p1ram : ORIGIN = 0x8c020000, LENGTH = 0xff0000 p1ram : ORIGIN = 0x8c020000, LENGTH = 0xfe0000
p2ram : ORIGIN = 0xac020000, LENGTH = 0xff0000 p2ram : ORIGIN = 0xac020000, LENGTH = 0xfe0000
} }
__stack_reservation = 0x1000;
INCLUDE "common.lds" INCLUDE "common.lds"

View File

@ -70,7 +70,11 @@ def do(ser, b):
sync(ser, b'prime', wait=0) sync(ser, b'prime', wait=0)
do(ser, b) do(ser, b)
print("\nDATA") print("\nDATA")
start = time.monotonic()
ret = symmetric(ser, b) ret = symmetric(ser, b)
end = time.monotonic()
duration = end - start
print("duration", duration)
print(ret[-5:]) print(ret[-5:])
if ret[:-5] != b: if ret[:-5] != b:
print("ret != b; dumped to asdf.bin") print("ret != b; dumped to asdf.bin")
@ -96,8 +100,8 @@ def console(ser):
with open(sys.argv[1], 'rb') as f: with open(sys.argv[1], 'rb') as f:
b = f.read() b = f.read()
#with serial.Serial('/dev/ttyUSB0', 120192, timeout=1) as ser: with serial.Serial('/dev/ttyUSB0', 120192, timeout=1) as ser:
with serial.Serial('/dev/ttyUSB0', 312500, timeout=1) as ser: #with serial.Serial('/dev/ttyUSB0', 312500, timeout=1) as ser:
#console(ser) #console(ser)
print("waiting: ", end=' ') print("waiting: ", end=' ')
sys.stdout.flush() sys.stdout.flush()

View File

@ -44,13 +44,5 @@ SECTIONS
INCLUDE "debug.lds" INCLUDE "debug.lds"
} }
__p1ram_start = ORIGIN(p1ram); INCLUDE "symbols.lds"
__p1ram_end = ORIGIN(p1ram) + LENGTH(p1ram);
__bss_link_start = ADDR(.bss);
__bss_link_end = ADDR(.bss) + SIZEOF(.bss);
__ctors_link_start = ADDR(.ctors);
__ctors_link_end = ADDR(.ctors) + SIZEOF(.ctors);
INCLUDE "addresses.lds" INCLUDE "addresses.lds"

View File

@ -2,7 +2,7 @@ MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
DIR := $(dir $(MAKEFILE_PATH)) DIR := $(dir $(MAKEFILE_PATH))
LIB ?= . LIB ?= .
OPT ?= -O3 OPT ?= -Og
GENERATED ?= GENERATED ?=
AARCH = --isa=sh4 --little AARCH = --isa=sh4 --little
@ -32,6 +32,11 @@ IP_OBJ = \
sg/sg_ini.o \ sg/sg_ini.o \
sg/aip.o sg/aip.o
%.o: %.obj
$(OBJCOPY) -g \
--rename-section IP=.text.$* \
$< $@
ip.elf: $(IP_OBJ) ip.elf: $(IP_OBJ)
$(LD) --orphan-handling=error --print-memory-usage -T $(LIB)/ip.lds $^ -o $@ $(LD) --orphan-handling=error --print-memory-usage -T $(LIB)/ip.lds $^ -o $@
@ -42,11 +47,6 @@ START_OBJ = \
include base.mk include base.mk
%.o: %.obj
$(OBJCOPY) -g \
--rename-section IP=.text.$* \
$< $@
sine.pcm: common.mk sine.pcm: common.mk
sox \ sox \
--rate 44100 \ --rate 44100 \

View File

@ -16,7 +16,9 @@ SPRITE_OBJ = \
holly/core.o \ holly/core.o \
holly/region_array.o \ holly/region_array.o \
holly/background.o \ holly/background.o \
holly/ta_fifo_polygon_converter.o holly/ta_fifo_polygon_converter.o \
sh7091/serial.o \
$(LIBGCC)
example/sprite.elf: LDSCRIPT = $(LIB)/alt.lds example/sprite.elf: LDSCRIPT = $(LIB)/alt.lds
example/sprite.elf: $(START_OBJ) $(SPRITE_OBJ) example/sprite.elf: $(START_OBJ) $(SPRITE_OBJ)
@ -149,7 +151,7 @@ WIFFLE_ATTENUATION_OBJ = \
holly/background.o \ holly/background.o \
holly/ta_fifo_polygon_converter.o holly/ta_fifo_polygon_converter.o
example/wiffle_attenuation.elf: LDSCRIPT = $(LIB)/alt.lds example/wiffle_attenuation.elf: LDSCRIPT = $(LIB)/main.lds
example/wiffle_attenuation.elf: $(START_OBJ) $(WIFFLE_ATTENUATION_OBJ) example/wiffle_attenuation.elf: $(START_OBJ) $(WIFFLE_ATTENUATION_OBJ)
MODIFIER_VOLUME_OBJ = \ MODIFIER_VOLUME_OBJ = \
@ -322,7 +324,7 @@ SERIAL_TRANSFER_OBJ = \
sh7091/serial.o \ sh7091/serial.o \
serial_load.o serial_load.o
example/serial_transfer.elf: LDSCRIPT = $(LIB)/main.lds example/serial_transfer.elf: LDSCRIPT = $(LIB)/loader.lds
example/serial_transfer.elf: $(START_OBJ) $(SERIAL_TRANSFER_OBJ) example/serial_transfer.elf: $(START_OBJ) $(SERIAL_TRANSFER_OBJ)
INTERRUPT_OBJ = \ INTERRUPT_OBJ = \

View File

@ -185,5 +185,8 @@ void main()
theta += half_degree; theta += half_degree;
frame_ix += 1; frame_ix += 1;
if (frame_ix > 10)
break;
} }
} }

View File

@ -6,24 +6,19 @@
#include "serial_load.hpp" #include "serial_load.hpp"
extern uint32_t __bss_link_start __asm("__bss_link_start"); void main() __attribute__((section(".text.main")));
extern uint32_t __bss_link_end __asm("__bss_link_end");
void main() void main()
{ {
serial::init(4); //serial::init(12);
load_init(); load_init();
while (1) { while (1) {
using namespace scif; using namespace scif;
while ((sh7091.SCIF.SCFSR2 & scfsr2::tdfe::bit_mask) == 0) {
// wait
}
while ((scfdr2::receive_data_bytes(sh7091.SCIF.SCFDR2)) > 0) { while ((scfdr2::receive_data_bytes(sh7091.SCIF.SCFDR2)) > 0) {
uint8_t c = sh7091.SCIF.SCFRDR2; const uint8_t c = sh7091.SCIF.SCFRDR2;
load_recv(c); load_recv(c);
} }
sh7091.SCIF.SCFSR2 = sh7091.SCIF.SCFSR2 & (~scfsr2::rdf::bit_mask);
} }
} }

61
loader.lds Normal file
View File

@ -0,0 +1,61 @@
OUTPUT_FORMAT("elf32-shl", "elf32-shl", "elf32-shl")
MEMORY
{
p1ram : ORIGIN = 0x8c020000, LENGTH = 0xfe0000
p2ram : ORIGIN = 0xac020000, LENGTH = 0xfe0000
ldram : ORIGIN = 0x8cfff000, LENGTH = 0x1000
}
SECTIONS
{
. = ORIGIN(p2ram);
.text.startup ALIGN(4) : SUBALIGN(4)
{
KEEP(*(.text.start))
*(.text.startup.*)
. = ALIGN(4);
} > p2ram AT> p2ram
.ctors ALIGN(4) : SUBALIGN(4)
{
KEEP(*(.ctors))
KEEP(*(.ctors.*))
. = ALIGN(4);
} > p2ram AT> p2ram
. = ORIGIN(ldram);
.text ALIGN(4) : SUBALIGN(4)
{
*(.text.*)
*(.text)
. = ALIGN(4);
} > ldram AT> p2ram
.data ALIGN(4) : SUBALIGN(4)
{
*(.data)
*(.data.*)
. = ALIGN(4);
} > ldram AT> p2ram
.rodata ALIGN(4) : SUBALIGN(4)
{
*(.rodata)
*(.rodata.*)
. = ALIGN(4);
} > ldram AT> p2ram
.bss ALIGN(4) (NOLOAD) : SUBALIGN(4)
{
*(.bss)
*(.bss.*)
*(COMMON)
. = ALIGN(4);
} > ldram
INCLUDE "debug.lds"
}
__stack_reservation = 0x0000;
INCLUDE "symbols.lds"
INCLUDE "addresses.lds"

View File

@ -4,4 +4,5 @@ MEMORY
p1ram : ORIGIN = 0x8c010000, LENGTH = 0xff0000 p1ram : ORIGIN = 0x8c010000, LENGTH = 0xff0000
p2ram : ORIGIN = 0xac010000, LENGTH = 0xff0000 p2ram : ORIGIN = 0xac010000, LENGTH = 0xff0000
} }
__stack_reservation = 0x1000;
INCLUDE "common.lds" INCLUDE "common.lds"

View File

@ -1,27 +1,76 @@
#include <cstdint> #include <cstdint>
#include <type_traits>
#include "sh7091/cache.hpp" #include "sh7091/cache.hpp"
#include "string.hpp"
extern uint32_t __text_link_start __asm("__text_link_start");
extern uint32_t __text_link_end __asm("__text_link_end");
extern uint32_t __text_load_start __asm("__text_load_start");
extern uint32_t __data_link_start __asm("__data_link_start");
extern uint32_t __data_link_end __asm("__data_link_end");
extern uint32_t __data_load_start __asm("__data_load_start");
extern uint32_t __rodata_link_start __asm("__rodata_link_start");
extern uint32_t __rodata_link_end __asm("__rodata_link_end");
extern uint32_t __rodata_load_start __asm("__rodata_load_start");
extern uint32_t __ctors_link_start __asm("__ctors_link_start");
extern uint32_t __ctors_link_end __asm("__ctors_link_end");
extern uint32_t __bss_link_start __asm("__bss_link_start"); extern uint32_t __bss_link_start __asm("__bss_link_start");
extern uint32_t __bss_link_end __asm("__bss_link_end"); extern uint32_t __bss_link_end __asm("__bss_link_end");
extern void main(); extern void main();
typedef void(init_t)(void);
extern "C" extern "C"
void runtime_init() void runtime_init()
__attribute__((section(".text.startup.runtime_init"))); __attribute__((section(".text.startup.runtime_init")));
void copy(uint32_t * start, const uint32_t * end, uint32_t * load)
__attribute__((section(".text.startup.copy")));
void copy(uint32_t * start, const uint32_t * end, uint32_t * load)
{
if (start != load) {
while (start < end) {
*start++ = *load++;
}
}
}
extern "C" extern "C"
void runtime_init() void runtime_init()
{ {
// relocate text (if necessary)
copy(&__text_link_start, &__text_link_end, &__text_load_start);
// relocate data (if necessary)
copy(&__data_link_start, &__data_link_end, &__data_load_start);
// relocate rodata (if necessary)
copy(&__rodata_link_start, &__rodata_link_end, &__rodata_load_start);
uint32_t * start;
uint32_t * end;
// clear BSS // clear BSS
uint32_t * start = &__bss_link_start; start = &__bss_link_start;
uint32_t * end = &__bss_link_end; end = &__bss_link_end;
while (start < end) { while (start < end) {
*start++ = 0; *start++ = 0;
} }
cache::init(); // call ctors
start = &__ctors_link_start;
end = &__ctors_link_end;
while (start < end) {
((init_t*)(*start++))();
}
main(); cache::init();
} }

View File

@ -2,6 +2,7 @@
#include "sh7091/sh7091.hpp" #include "sh7091/sh7091.hpp"
#include "sh7091/sh7091_bits.hpp" #include "sh7091/sh7091_bits.hpp"
#include "sh7091/serial.hpp"
#include "holly/holly.hpp" #include "holly/holly.hpp"
enum load_command { enum load_command {
@ -54,6 +55,24 @@ void debug(const char * s)
} }
} }
void jump_to_func(const uint32_t addr)
{
serial::string("jump to: ");
serial::integer<uint32_t>(addr);
// save our stack
asm volatile ("ldc r15, gbr; "
"mov #0, r15; "
"jsr @%0; "
"nop; "
"stc gbr, r15; "
:
: "r"(addr) /* input */
/* clobbered register */
: "r0","r1","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12","macl","mach","gbr","pr"
);
// restore our stack
}
void load_recv(uint8_t c) void load_recv(uint8_t c)
{ {
if (state.command == CMD_NONE) if (state.command == CMD_NONE)
@ -119,8 +138,7 @@ void load_recv(uint8_t c)
state.command = CMD_NONE; state.command = CMD_NONE;
debug("prejump\n"); debug("prejump\n");
holly.VO_BORDER_COL = (31 << 11); holly.VO_BORDER_COL = (31 << 11);
void (*fptr)(void) = (void (*)(void))state.addr1; jump_to_func(state.addr1);
fptr();
holly.VO_BORDER_COL = (63 << 5) | (31 << 0); holly.VO_BORDER_COL = (63 << 5) | (31 << 0);
debug("postjump\n"); debug("postjump\n");
return; return;

View File

@ -19,11 +19,20 @@ void init(uint8_t bit_rate)
sh7091.SCIF.SCFCR2 = scfcr2::tfrst::reset_operation_enabled sh7091.SCIF.SCFCR2 = scfcr2::tfrst::reset_operation_enabled
| scfcr2::rfrst::reset_operation_enabled; | scfcr2::rfrst::reset_operation_enabled;
// tx/rx trigger on 1 byte
sh7091.SCIF.SCFCR2 = 0; sh7091.SCIF.SCFCR2 = scfcr2::rtrg::trigger_on_1_byte
| scfcr2::ttrg::trigger_on_8_bytes
| scfcr2::mce::modem_signals_disabled;
sh7091.SCIF.SCSPTR2 = 0; sh7091.SCIF.SCSPTR2 = 0;
sh7091.SCIF.SCLSR2 = 0; sh7091.SCIF.SCFSR2 = (~scfsr2::er::bit_mask)
& (~scfsr2::tend::bit_mask)
& (~scfsr2::tdfe::bit_mask)
& (~scfsr2::brk::bit_mask)
& (~scfsr2::rdf::bit_mask)
& (~scfsr2::dr::bit_mask)
& 0xffff;
sh7091.SCIF.SCLSR2 = 0; // clear ORER
sh7091.SCIF.SCSCR2 = scscr2::te::transmission_enabled sh7091.SCIF.SCSCR2 = scscr2::te::transmission_enabled
| scscr2::re::reception_enabled; | scscr2::re::reception_enabled;

15
start.s
View File

@ -10,11 +10,22 @@ _start:
or r1,r0 or r1,r0
ldc r0,sr ldc r0,sr
/* save pr */
sts.l pr,@-r15
/* jump to runtime_init */ /* jump to runtime_init */
mov.l runtime_init_ptr,r0 mov.l runtime_init_ptr,r0
jmp @r0 jsr @r0
nop nop
/* restore pr */
lds.l @r15+,pr
/* jump to main */
mov.l main_ptr,r0
jmp @r0
nop
.align 4 .align 4
p1ram_end_ptr: p1ram_end_ptr:
.long __p1ram_end .long __p1ram_end
@ -22,3 +33,5 @@ imask_all:
.long 0xf0 .long 0xf0
runtime_init_ptr: runtime_init_ptr:
.long _runtime_init .long _runtime_init
main_ptr:
.long _main

21
symbols.lds Normal file
View File

@ -0,0 +1,21 @@
__p1ram_start = ORIGIN(p1ram);
/* reserve bytes for serial program loader */
__p1ram_end = ORIGIN(p1ram) + LENGTH(p1ram) - __stack_reservation;
__text_link_start = ADDR(.text);
__text_link_end = ADDR(.text) + SIZEOF(.text);
__text_load_start = LOADADDR(.text);
__data_link_start = ADDR(.data);
__data_link_end = ADDR(.data) + SIZEOF(.data);
__data_load_start = LOADADDR(.data);
__rodata_link_start = ADDR(.rodata);
__rodata_link_end = ADDR(.rodata) + SIZEOF(.rodata);
__rodata_load_start = LOADADDR(.rodata);
__ctors_link_start = ADDR(.ctors);
__ctors_link_end = ADDR(.ctors) + SIZEOF(.ctors);
__bss_link_start = ADDR(.bss);
__bss_link_end = ADDR(.bss) + SIZEOF(.bss);