Skip to content

Commit

Permalink
debug: added support for SummerCart64 AUX register
Browse files Browse the repository at this point in the history
  • Loading branch information
Polprzewodnikowy committed Aug 25, 2024
1 parent 26bb3dd commit 2b629b4
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 16 deletions.
11 changes: 10 additions & 1 deletion include/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ extern "C" {
#define DEBUG_FEATURE_FILE_SD (1 << 3)


#define DEBUG_FEATURE_CART_INTERRUPT (1 << 4)


/**
* @brief Flag to activate all supported debugging features.
*
Expand All @@ -142,6 +145,10 @@ extern "C" {
/** @brief Shutdown SD filesystem. */
void debug_close_sdfs(void);


bool debug_init_cart_interrupt(void);
void debug_close_cart_interrupt(void);

/**
* @brief Initialize debugging features of libdragon.
*
Expand All @@ -163,7 +170,9 @@ extern "C" {
if (features & DEBUG_FEATURE_FILE_SD)
ok = debug_init_sdfs("sd:/", -1) || ok;
if (features & DEBUG_FEATURE_LOG_SD)
ok = debug_init_sdlog("sd:/libdragon.log", "a");
ok = debug_init_sdlog("sd:/libdragon.log", "a") || ok;
if (features & DEBUG_FEATURE_CART_INTERRUPT)
ok = debug_init_cart_interrupt() || ok;
return ok;
}

Expand Down
5 changes: 5 additions & 0 deletions include/n64sys.h
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,8 @@ void wait_ticks( unsigned long wait );
*/
void wait_ms( unsigned long wait_ms );

void halt(void);

/**
* @brief Force a complete halt of all processors
*
Expand All @@ -292,6 +294,9 @@ void wait_ms( unsigned long wait_ms );
__attribute__((noreturn))
void die(void);

__attribute__((noreturn))
void reboot(void);

/**
* @brief Force a data cache invalidate over a memory region
*
Expand Down
2 changes: 2 additions & 0 deletions include/regsinternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ typedef struct PI_regs_s {
uint32_t dom1_latency;
/** @brief Cartridge domain 1 pulse width in RCP clock cycles. Requires DMA status bit guards to work reliably */
uint32_t dom1_pulse_width;
uint32_t dom1_page_size;
uint32_t dom1_release;
// TODO: add remaining registers
} PI_regs_t;

Expand Down
84 changes: 84 additions & 0 deletions src/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,90 @@ void debug_close_sdfs(void)
}
}

#define SC64_SCR (0x1FFF0000)
#define SC64_IRQ (0x1FFF0014)
#define SC64_AUX (0x1FFF0018)

#define SC64_SCR_AUX_IRQ_PENDING (1 << 23)
#define SC64_SCR_AUX_IRQ_MASK (1 << 22)

#define SC64_IRQ_AUX_CLEAR (1 << 28)
#define SC64_IRQ_AUX_DISABLE (1 << 9)
#define SC64_IRQ_AUX_ENABLE (1 << 8)

#define AUX_PING (0xFF000000)
#define AUX_HALT (0xFF000001)
#define AUX_REBOOT (0xFF000002)

static void debug_cart_handler_sc64(void)
{
bool halt_requested = false;

do {
uint32_t scr = io_read(SC64_SCR);

if ((scr & SC64_SCR_AUX_IRQ_MASK) && (scr & SC64_SCR_AUX_IRQ_PENDING)) {
io_write(SC64_IRQ, SC64_IRQ_AUX_CLEAR);

switch (io_read(SC64_AUX)) {
case AUX_PING:
io_write(SC64_AUX, AUX_PING);
break;

case AUX_HALT:
if (!halt_requested) {
halt();
halt_requested = true;
}
io_write(SC64_AUX, AUX_HALT);
break;

case AUX_REBOOT:
io_write(SC64_IRQ, SC64_IRQ_AUX_DISABLE);
io_write(SC64_AUX, AUX_REBOOT);
reboot();
break;

default:
break;
}
}
} while (halt_requested);
}

bool debug_init_cart_interrupt(void)
{
if (!sd_initialize_once())
return false;

if (cart_type == CART_SC) {
register_CART_handler(debug_cart_handler_sc64);
set_CART_interrupt(true);

io_write(SC64_IRQ, SC64_IRQ_AUX_ENABLE);

enabled_features |= DEBUG_FEATURE_CART_INTERRUPT;

return true;
}

return false;
}

void debug_close_cart_interrupt(void)
{
if (enabled_features & DEBUG_FEATURE_CART_INTERRUPT) {
enabled_features &= ~(DEBUG_FEATURE_CART_INTERRUPT);

if (cart_type == CART_SC) {
io_write(SC64_IRQ, SC64_IRQ_AUX_DISABLE);

set_CART_interrupt(false);
unregister_CART_handler(debug_cart_handler_sc64);
}
}
}

void debug_assert_func_f(const char *file, int line, const char *func, const char *failedexpr, const char *msg, ...)
{
disable_interrupts();
Expand Down
14 changes: 8 additions & 6 deletions src/entrypoint.S
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,14 @@ _start:
sw t1, %gprel(__entropy_state+4)(gp)

/* Copy other bootcode flags */
lbu t0, 0x0009(v0)
lbu t1, 0x000A(v0)
lbu t2, 0x000B(v0)
sw t0, %gprel(__boot_tvtype)(gp)
sw t1, %gprel(__boot_resettype)(gp)
sw t2, %gprel(__boot_consoletype)(gp)
lbu t0, 0x0008(v0)
lbu t1, 0x0009(v0)
lbu t2, 0x000A(v0)
lbu t3, 0x000B(v0)
sw t0, %gprel(__boot_romtype)(gp)
sw t1, %gprel(__boot_tvtype)(gp)
sw t2, %gprel(__boot_resettype)(gp)
sw t3, %gprel(__boot_consoletype)(gp)

la t0, debug_assert_func /* install assert function in system.c */
la t1, __assert_func_ptr
Expand Down
70 changes: 61 additions & 9 deletions src/n64sys.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@
#include <malloc.h>
#include "n64sys.h"
#include "regsinternal.h"
#include "dma.h"
#include "interrupt.h"
#include "vi.h"
#include "rsp.h"
#include "rdp.h"
#include "utils.h"

int __boot_memsize; ///< Memory size as detected by IPL3
int __boot_romtype; ///< ROM type as detected by IPL3
int __boot_tvtype; ///< TV type as detected by IPL3
int __boot_resettype; ///< Reset type as detected by IPL3
int __boot_consoletype; ///< Console type as detected by IPL3
Expand All @@ -27,6 +29,9 @@ static uint32_t ticks64_base_tick;
/** @brief Last value of the 64-bit counter */
static uint64_t ticks64_base;

/** @brief Structure used to interact with the PI registers */
static volatile struct PI_regs_s * const PI_regs = (struct PI_regs_s *)0xa4600000;

/**
* @brief Helper macro to perform cache refresh operations
*
Expand Down Expand Up @@ -175,6 +180,19 @@ void wait_ms( unsigned long wait_ms )
wait_ticks(TICKS_FROM_MS(wait_ms));
}

void halt(void)
{
// Can't have any interrupts here
disable_interrupts();
// Halt the RSP
*SP_STATUS = SP_WSTATUS_SET_HALT;
// Flush the RDP
*DP_STATUS = DP_WSTATUS_SET_FLUSH | DP_WSTATUS_SET_FREEZE;
*DP_STATUS = DP_WSTATUS_RESET_FLUSH | DP_WSTATUS_RESET_FREEZE;
// Shut the video off
*VI_CTRL = *VI_CTRL & (~VI_CTRL_TYPE);
}

/**
* @brief Force a complete halt of all processors
*
Expand All @@ -187,19 +205,53 @@ void wait_ms( unsigned long wait_ms )
*/
void die(void)
{
// Can't have any interrupts here
disable_interrupts();
// Halt the RSP
*SP_STATUS = SP_WSTATUS_SET_HALT;
// Flush the RDP
*DP_STATUS = DP_WSTATUS_SET_FLUSH | DP_WSTATUS_SET_FREEZE;
*DP_STATUS = DP_WSTATUS_RESET_FLUSH | DP_WSTATUS_RESET_FREEZE;
// Shut the video off
*VI_CTRL = *VI_CTRL & (~VI_CTRL_TYPE);
// Terminate the RCP execution
halt();
// Terminate the CPU execution
abort();
}

void reboot(void)
{
halt();

const uint32_t ROM_ADDRESS = 0x10000000;

const int IPL3_SIZE = 0xFC0;
const uint32_t IPL3_OFFSET = 0x40;

uint8_t ipl3_data[IPL3_SIZE] __attribute__((aligned(8)));

C0_WRITE_STATUS(0x34000000);

uint32_t pi_config = io_read(ROM_ADDRESS);

PI_regs->dom1_latency = pi_config;
PI_regs->dom1_pulse_width = (pi_config >> 8);
PI_regs->dom1_page_size = (pi_config >> 16);
PI_regs->dom1_release = (pi_config >> 20);

dma_read_raw_async(&ipl3_data, (ROM_ADDRESS + IPL3_OFFSET), sizeof(ipl3_data));
dma_wait();
rsp_load_data(ipl3_data, sizeof(ipl3_data), IPL3_OFFSET);

void (*run_ipl3)(void) = (void (*)(void))((uint32_t)(SP_DMEM) + IPL3_OFFSET);

register uint32_t rom_type asm ("s3") = __boot_romtype;
register uint32_t tv_type asm ("s4") = __boot_tvtype;
register uint32_t reset_type asm ("s5") = RESET_WARM;

asm volatile (
"jalr %[run_ipl3] \n" ::
[run_ipl3] "r" (run_ipl3),
[rom_type] "r" (rom_type),
[tv_type] "r" (tv_type),
[reset_type] "r" (reset_type)
);

abort();
}

/**
* @brief Initialize COP1 with default settings that prevent undesirable exceptions.
*
Expand Down

0 comments on commit 2b629b4

Please sign in to comment.