arm7: copy to exclusive internal ram

Before this commit, attempting to start the rom on real NDS/DSi
hardware would result in the display of a solid white screen, with
no apparent evidence of the arm9 program running.

After much testing, I found that this issue was directly caused "main
mmeory" bus contention. Because arm7 and arm9 are both attempting to
read instructions from ewram at the same time, and arm9 bus access
stalls completely.

I also found that this could not be mitigated with giving arm9
priority in EXMEMCNT.

The solution appears to be to relocate arm7 code execution from
main/shared memory to an arm7-internal memory.

After this commit, the examples now function as intended on real
NDS/DSi hardware.
This commit is contained in:
Zack Buhman 2024-09-10 11:56:15 -05:00
parent 95baf481d7
commit 62d6a3b2a6
7 changed files with 45 additions and 17 deletions

View File

@ -15,6 +15,7 @@ registers:
DEFAULT = header.o arm7/arm7.bin.o
2d_engine.elf: $(DEFAULT) arm9/2d_engine.bin.o
triangle.elf: $(DEFAULT) arm9/triangle.bin.o
triangle_rotating.elf: $(DEFAULT) arm9/triangle_rotating.bin.o
texture.elf: $(DEFAULT) arm9/texture.bin.o

View File

@ -2,47 +2,50 @@ OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
MEMORY
{
ram : ORIGIN = 0x02000000, LENGTH = 4M
main_memory : ORIGIN = 0x02390000, LENGTH = 256K
arm7_exclusive_internal_work_ram : ORIGIN = 0x03800000, LENGTH = 64K
}
SECTIONS
{
. = ORIGIN(ram) + 0x390000;
. = ORIGIN(arm7_exclusive_internal_work_ram);
.text ALIGN(4) :
{
KEEP(*(.text.start))
*(.text)
*(.text.*)
*(.glue_7t)
*(.glue_7)
*(.vfp11_veneer)
*(.v4_bx)
} > ram
. = ALIGN(32);
} >arm7_exclusive_internal_work_ram AT>main_memory
.data ALIGN(4) :
{
*(.data)
*(.data.*)
} > ram
} >arm7_exclusive_internal_work_ram AT>main_memory
.rodata ALIGN(4) :
{
*(.rodata)
*(.rodata.*)
} > ram
} >arm7_exclusive_internal_work_ram AT>main_memory
.ctors ALIGN(4) :
{
KEEP(*(.ctors))
KEEP(*(.ctors.*))
} > ram
} >arm7_exclusive_internal_work_ram AT>main_memory
.bss ALIGN(4) (NOLOAD) :
{
*(.bss)
*(.bss.*)
*(COMMON)
} > ram
} >arm7_exclusive_internal_work_ram
/DISCARD/ :
{
*(.glue_7) *(.glue_7t) *(.vfp11_veneer) *(.v4_bx)
}
INCLUDE "../debug.lds"
}

View File

@ -1,4 +1,26 @@
.macro COPY_32_BYTE_ALIGNED
cmp r1, r10
beq _fill_break.\@
_fill_loop.\@:
ldmia r0!, {r2 - r9}
stmia r1!, {r2 - r9}
cmp r1, r10
bne _fill_loop.\@
_fill_break.\@:
.endm
.section .text.start
.global _start
_start:
b _start
// copy .text to internal ram
ldr r0, =__text_load_start
ldr r1, =__text_link_start
ldr r10, =__text_link_end
COPY_32_BYTE_ALIGNED
// jump to internal ram
ldr r3,=_loop_forever
bx r3
_loop_forever:
b _loop_forever

View File

@ -49,3 +49,5 @@ SECTIONS
INCLUDE "../symbols.lds"
INCLUDE "addresses.lds"
__stack_end = ORIGIN(ram) + LENGTH(ram) - 4;

View File

@ -58,10 +58,12 @@ for name, offset, size in fields:
print(f'{b:02x}', end='')
pad = ' ' * (17 * 2 - size * 2)
if size == 4:
if name in {'game title', 'game code'}:
print(pad, buf[offset:offset+size], end='')
elif size == 4:
n, = struct.unpack('<I', buf[offset:offset+size])
print(pad, f"0x{n:08x}", end='')
if size == 2:
elif size == 2:
n, = struct.unpack('<H', buf[offset:offset+size])
print(pad, f"0x{n:04x}", end='')
print()

View File

@ -1,7 +1,7 @@
.section .text.header
.ascii "game title " /* Game Title */
.ascii "AAAA" /* Game Code */
.ascii "####" /* Game Code */
.ascii "00" /* Maker Code */
.byte 0x0 /* Unit Code */
.byte 0x0 /* Device type */

View File

@ -1,5 +1,3 @@
__stack_end = ORIGIN(ram) + LENGTH(ram) - 4;
__text_link_start = ADDR(.text);
__text_link_end = ADDR(.text) + SIZEOF(.text);
__text_load_start = LOADADDR(.text);