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:
parent
0806ed9ac7
commit
d912278afd
5
alt.lds
5
alt.lds
@ -1,7 +1,8 @@
|
||||
OUTPUT_FORMAT("elf32-shl", "elf32-shl", "elf32-shl")
|
||||
MEMORY
|
||||
{
|
||||
p1ram : ORIGIN = 0x8c020000, LENGTH = 0xff0000
|
||||
p2ram : ORIGIN = 0xac020000, LENGTH = 0xff0000
|
||||
p1ram : ORIGIN = 0x8c020000, LENGTH = 0xfe0000
|
||||
p2ram : ORIGIN = 0xac020000, LENGTH = 0xfe0000
|
||||
}
|
||||
__stack_reservation = 0x1000;
|
||||
INCLUDE "common.lds"
|
||||
|
@ -70,7 +70,11 @@ def do(ser, b):
|
||||
sync(ser, b'prime', wait=0)
|
||||
do(ser, b)
|
||||
print("\nDATA")
|
||||
start = time.monotonic()
|
||||
ret = symmetric(ser, b)
|
||||
end = time.monotonic()
|
||||
duration = end - start
|
||||
print("duration", duration)
|
||||
print(ret[-5:])
|
||||
if ret[:-5] != b:
|
||||
print("ret != b; dumped to asdf.bin")
|
||||
@ -96,8 +100,8 @@ def console(ser):
|
||||
with open(sys.argv[1], 'rb') as f:
|
||||
b = f.read()
|
||||
|
||||
#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', 120192, timeout=1) as ser:
|
||||
#with serial.Serial('/dev/ttyUSB0', 312500, timeout=1) as ser:
|
||||
#console(ser)
|
||||
print("waiting: ", end=' ')
|
||||
sys.stdout.flush()
|
||||
|
10
common.lds
10
common.lds
@ -44,13 +44,5 @@ SECTIONS
|
||||
INCLUDE "debug.lds"
|
||||
}
|
||||
|
||||
__p1ram_start = ORIGIN(p1ram);
|
||||
__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 "symbols.lds"
|
||||
INCLUDE "addresses.lds"
|
||||
|
12
common.mk
12
common.mk
@ -2,7 +2,7 @@ MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
|
||||
DIR := $(dir $(MAKEFILE_PATH))
|
||||
|
||||
LIB ?= .
|
||||
OPT ?= -O3
|
||||
OPT ?= -Og
|
||||
GENERATED ?=
|
||||
|
||||
AARCH = --isa=sh4 --little
|
||||
@ -32,6 +32,11 @@ IP_OBJ = \
|
||||
sg/sg_ini.o \
|
||||
sg/aip.o
|
||||
|
||||
%.o: %.obj
|
||||
$(OBJCOPY) -g \
|
||||
--rename-section IP=.text.$* \
|
||||
$< $@
|
||||
|
||||
ip.elf: $(IP_OBJ)
|
||||
$(LD) --orphan-handling=error --print-memory-usage -T $(LIB)/ip.lds $^ -o $@
|
||||
|
||||
@ -42,11 +47,6 @@ START_OBJ = \
|
||||
|
||||
include base.mk
|
||||
|
||||
%.o: %.obj
|
||||
$(OBJCOPY) -g \
|
||||
--rename-section IP=.text.$* \
|
||||
$< $@
|
||||
|
||||
sine.pcm: common.mk
|
||||
sox \
|
||||
--rate 44100 \
|
||||
|
@ -16,7 +16,9 @@ SPRITE_OBJ = \
|
||||
holly/core.o \
|
||||
holly/region_array.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: $(START_OBJ) $(SPRITE_OBJ)
|
||||
@ -149,7 +151,7 @@ WIFFLE_ATTENUATION_OBJ = \
|
||||
holly/background.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)
|
||||
|
||||
MODIFIER_VOLUME_OBJ = \
|
||||
@ -322,7 +324,7 @@ SERIAL_TRANSFER_OBJ = \
|
||||
sh7091/serial.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)
|
||||
|
||||
INTERRUPT_OBJ = \
|
||||
|
@ -185,5 +185,8 @@ void main()
|
||||
|
||||
theta += half_degree;
|
||||
frame_ix += 1;
|
||||
|
||||
if (frame_ix > 10)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -6,24 +6,19 @@
|
||||
|
||||
#include "serial_load.hpp"
|
||||
|
||||
extern uint32_t __bss_link_start __asm("__bss_link_start");
|
||||
extern uint32_t __bss_link_end __asm("__bss_link_end");
|
||||
void main() __attribute__((section(".text.main")));
|
||||
|
||||
void main()
|
||||
{
|
||||
serial::init(4);
|
||||
//serial::init(12);
|
||||
load_init();
|
||||
|
||||
while (1) {
|
||||
using namespace scif;
|
||||
|
||||
while ((sh7091.SCIF.SCFSR2 & scfsr2::tdfe::bit_mask) == 0) {
|
||||
// wait
|
||||
}
|
||||
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);
|
||||
}
|
||||
sh7091.SCIF.SCFSR2 = sh7091.SCIF.SCFSR2 & (~scfsr2::rdf::bit_mask);
|
||||
}
|
||||
}
|
||||
|
61
loader.lds
Normal file
61
loader.lds
Normal 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"
|
1
main.lds
1
main.lds
@ -4,4 +4,5 @@ MEMORY
|
||||
p1ram : ORIGIN = 0x8c010000, LENGTH = 0xff0000
|
||||
p2ram : ORIGIN = 0xac010000, LENGTH = 0xff0000
|
||||
}
|
||||
__stack_reservation = 0x1000;
|
||||
INCLUDE "common.lds"
|
||||
|
57
runtime.cpp
57
runtime.cpp
@ -1,27 +1,76 @@
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
#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_end __asm("__bss_link_end");
|
||||
|
||||
extern void main();
|
||||
|
||||
typedef void(init_t)(void);
|
||||
|
||||
extern "C"
|
||||
void 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"
|
||||
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
|
||||
uint32_t * start = &__bss_link_start;
|
||||
uint32_t * end = &__bss_link_end;
|
||||
start = &__bss_link_start;
|
||||
end = &__bss_link_end;
|
||||
while (start < end) {
|
||||
*start++ = 0;
|
||||
}
|
||||
|
||||
cache::init();
|
||||
// call ctors
|
||||
start = &__ctors_link_start;
|
||||
end = &__ctors_link_end;
|
||||
while (start < end) {
|
||||
((init_t*)(*start++))();
|
||||
}
|
||||
|
||||
main();
|
||||
cache::init();
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "sh7091/sh7091.hpp"
|
||||
#include "sh7091/sh7091_bits.hpp"
|
||||
#include "sh7091/serial.hpp"
|
||||
#include "holly/holly.hpp"
|
||||
|
||||
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)
|
||||
{
|
||||
if (state.command == CMD_NONE)
|
||||
@ -119,8 +138,7 @@ void load_recv(uint8_t c)
|
||||
state.command = CMD_NONE;
|
||||
debug("prejump\n");
|
||||
holly.VO_BORDER_COL = (31 << 11);
|
||||
void (*fptr)(void) = (void (*)(void))state.addr1;
|
||||
fptr();
|
||||
jump_to_func(state.addr1);
|
||||
holly.VO_BORDER_COL = (63 << 5) | (31 << 0);
|
||||
debug("postjump\n");
|
||||
return;
|
||||
|
@ -19,11 +19,20 @@ void init(uint8_t bit_rate)
|
||||
|
||||
sh7091.SCIF.SCFCR2 = scfcr2::tfrst::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.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
|
||||
| scscr2::re::reception_enabled;
|
||||
|
13
start.s
13
start.s
@ -10,8 +10,19 @@ _start:
|
||||
or r1,r0
|
||||
ldc r0,sr
|
||||
|
||||
/* save pr */
|
||||
sts.l pr,@-r15
|
||||
|
||||
/* jump to runtime_init */
|
||||
mov.l runtime_init_ptr,r0
|
||||
jsr @r0
|
||||
nop
|
||||
|
||||
/* restore pr */
|
||||
lds.l @r15+,pr
|
||||
|
||||
/* jump to main */
|
||||
mov.l main_ptr,r0
|
||||
jmp @r0
|
||||
nop
|
||||
|
||||
@ -22,3 +33,5 @@ imask_all:
|
||||
.long 0xf0
|
||||
runtime_init_ptr:
|
||||
.long _runtime_init
|
||||
main_ptr:
|
||||
.long _main
|
||||
|
21
symbols.lds
Normal file
21
symbols.lds
Normal 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);
|
Loading…
x
Reference in New Issue
Block a user