mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-22 05:59:15 +01:00
handle irq in the bootloader
This commit is contained in:
parent
31ea6e6016
commit
7d8614e456
@ -11,7 +11,7 @@ N64_ELFCOMPRESS = $(N64_BINDIR)/n64elfcompress
|
||||
N64_TOOL = $(N64_BINDIR)/n64tool
|
||||
PYTHON = python3
|
||||
|
||||
FLAGS = -march=vr4300 -mtune=vr4300 $(USER_FLAGS)
|
||||
FLAGS = -march=vr4300 -mtune=vr4300 -mfix4300 $(USER_FLAGS)
|
||||
CFLAGS = -Os -Wall -ffunction-sections -fdata-sections -ffreestanding -MMD -MP
|
||||
ASFLAGS = -Wa,-I$(N64_INST)/mips64-elf/lib
|
||||
LDFLAGS = -lc -nostartfiles -Wl,--gc-sections
|
||||
|
@ -1,4 +1,3 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include "display.h"
|
||||
#include "font.h"
|
||||
@ -181,6 +180,10 @@ void display_init (uint32_t *background) {
|
||||
}
|
||||
}
|
||||
|
||||
bool display_ready (void) {
|
||||
return vi_configured;
|
||||
}
|
||||
|
||||
void display_vprintf (const char *fmt, va_list args) {
|
||||
char line[256];
|
||||
|
||||
|
@ -3,10 +3,12 @@
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
void display_init (uint32_t *background);
|
||||
bool display_ready (void);
|
||||
void display_vprintf (const char *fmt, va_list args);
|
||||
void display_printf (const char* fmt, ...);
|
||||
|
||||
|
@ -1,13 +1,23 @@
|
||||
#include <stdarg.h>
|
||||
#include "exception.h"
|
||||
#include "display.h"
|
||||
#include "init.h"
|
||||
#include "version.h"
|
||||
#include "../assets/assets.h"
|
||||
|
||||
|
||||
void error_display (const char *fmt, ...) {
|
||||
va_list args;
|
||||
|
||||
deinit();
|
||||
|
||||
display_init((uint32_t *) (&assets_sc64_logo_640_240_dimmed));
|
||||
|
||||
version_print();
|
||||
display_printf("[ Runtime error ]\n");
|
||||
va_start(args, fmt);
|
||||
EXCEPTION_TRIGGER(TRIGGER_CODE_ERROR);
|
||||
display_vprintf(fmt, args);
|
||||
va_end(args);
|
||||
display_printf("\n");
|
||||
|
||||
while (1);
|
||||
}
|
||||
|
@ -96,17 +96,11 @@ exception_handler:
|
||||
move $sp, $k0
|
||||
|
||||
exception_check_type:
|
||||
mfc0 $a0, C0_CAUSE
|
||||
sw $a0, C0_CAUSE_OFFSET($k0)
|
||||
move $a1, $a0
|
||||
move $t0, $a0
|
||||
andi $t0, C0_CR_IP7
|
||||
andi $a0, C0_CR_EC_MASK
|
||||
srl $a0, $a0, C0_CR_EC_BIT
|
||||
andi $a1, C0_CR_IP_MASK
|
||||
srl $a1, $a1, C0_CR_IP_BIT
|
||||
bne $t0, $zero, exception_fatal
|
||||
beq $a0, $zero, exception_interrupt
|
||||
mfc0 $t0, C0_CAUSE
|
||||
sw $t0, C0_CAUSE_OFFSET($k0)
|
||||
andi $a0, $t0, C0_CR_EC_MASK
|
||||
srl $a0, C0_CR_EC_BIT
|
||||
beqz $a0, exception_interrupt
|
||||
|
||||
exception_fatal:
|
||||
sd $k0, K0_OFFSET($k0)
|
||||
@ -117,16 +111,16 @@ exception_fatal:
|
||||
sd $t0, C0_EPC_OFFSET($k0)
|
||||
dmfc0 $t0, C0_BADVADDR
|
||||
sd $t0, C0_BADVADDR_OFFSET($k0)
|
||||
move $a2, $k0
|
||||
la $t1, exception_fatal_handler
|
||||
jalr $t1
|
||||
move $a1, $k0
|
||||
jal exception_fatal_handler
|
||||
ld $t0, C0_EPC_OFFSET($k0)
|
||||
dmtc0 $t0, C0_EPC
|
||||
j exception_restore
|
||||
|
||||
exception_interrupt:
|
||||
la $t1, exception_interrupt_handler
|
||||
jalr $t1
|
||||
andi $a0, $t0, C0_CR_IP_MASK
|
||||
srl $a0, C0_CR_IP_BIT
|
||||
jal exception_interrupt_handler
|
||||
|
||||
exception_restore:
|
||||
.set noat
|
||||
@ -169,8 +163,8 @@ exception_enable_interrupts:
|
||||
.type exception_enable_interrupts, %function
|
||||
.global exception_enable_interrupts
|
||||
mfc0 $t0, C0_STATUS
|
||||
li $t1, C0_SR_IE
|
||||
or $t0, $t0, $t1
|
||||
li $t1, (C0_SR_IM4 | C0_SR_IM3 | C0_SR_IE)
|
||||
or $t0, $t1
|
||||
mtc0 $t0, C0_STATUS
|
||||
jr $ra
|
||||
|
||||
@ -180,8 +174,8 @@ exception_disable_interrupts:
|
||||
.type exception_disable_interrupts, %function
|
||||
.global exception_disable_interrupts
|
||||
mfc0 $t0, C0_STATUS
|
||||
li $t1, ~(C0_SR_IE)
|
||||
and $t0, $t0, $t1
|
||||
li $t1, ~(C0_SR_IM4 | C0_SR_IM3 | C0_SR_IE)
|
||||
and $t0, $t1
|
||||
mtc0 $t0, C0_STATUS
|
||||
jr $ra
|
||||
|
||||
@ -195,7 +189,7 @@ exception_enable_watchdog:
|
||||
mtc0 $t1, C0_COMPARE
|
||||
mfc0 $t0, C0_STATUS
|
||||
li $t1, C0_SR_IM7
|
||||
or $t0, $t0, $t1
|
||||
or $t0, $t1
|
||||
mtc0 $t0, C0_STATUS
|
||||
jr $ra
|
||||
|
||||
@ -206,7 +200,7 @@ exception_disable_watchdog:
|
||||
.global exception_disable_watchdog
|
||||
mfc0 $t0, C0_STATUS
|
||||
li $t1, ~(C0_SR_IM7)
|
||||
and $t0, $t0, $t1
|
||||
and $t0, $t1
|
||||
mtc0 $t0, C0_STATUS
|
||||
mtc0 $zero, C0_COMPARE
|
||||
jr $ra
|
||||
|
@ -8,15 +8,6 @@
|
||||
#include "../assets/assets.h"
|
||||
|
||||
|
||||
#define EXCEPTION_INTERRUPT (0)
|
||||
#define EXCEPTION_SYSCALL (8)
|
||||
|
||||
#define INTERRUPT_MASK_TIMER (1 << 7)
|
||||
|
||||
#define SYSCALL_CODE_MASK (0x03FFFFC0UL)
|
||||
#define SYSCALL_CODE_BIT (6)
|
||||
|
||||
|
||||
static const char *exception_get_description (uint8_t exception_code) {
|
||||
switch (exception_code) {
|
||||
case 0: return "Interrupt";
|
||||
@ -41,48 +32,21 @@ static const char *exception_get_description (uint8_t exception_code) {
|
||||
}
|
||||
|
||||
|
||||
void exception_fatal_handler (uint32_t exception_code, uint32_t interrupt_mask, exception_t *e) {
|
||||
version_t *version = version_get();
|
||||
uint32_t *instruction_address = (((uint32_t *) (e->epc.u32)) + ((e->cr & C0_CR_BD) ? 1 : 0));
|
||||
|
||||
void exception_fatal_handler (uint32_t exception_code, exception_t *e) {
|
||||
display_init((uint32_t *) (&assets_sc64_logo_640_240_dimmed));
|
||||
|
||||
display_printf("[ SC64 bootloader metadata ]\n");
|
||||
display_printf("branch: %s | tag: %s\n", version->git_branch, version->git_tag);
|
||||
display_printf("sha: %s\n", version->git_sha);
|
||||
display_printf("msg: %s\n\n", version->git_message);
|
||||
|
||||
if (exception_code != EXCEPTION_SYSCALL) {
|
||||
display_printf("%s\n", exception_get_description(exception_code));
|
||||
display_printf(" pc: 0x%08lX sr: 0x%08lX cr: 0x%08lX va: 0x%08lX\n", e->epc.u32, e->sr, e->cr, e->badvaddr.u32);
|
||||
display_printf(" zr: 0x%08lX at: 0x%08lX v0: 0x%08lX v1: 0x%08lX\n", e->zr.u32, e->at.u32, e->v0.u32, e->v1.u32);
|
||||
display_printf(" a0: 0x%08lX a1: 0x%08lX a2: 0x%08lX a3: 0x%08lX\n", e->a0.u32, e->a1.u32, e->a2.u32, e->a3.u32);
|
||||
display_printf(" t0: 0x%08lX t1: 0x%08lX t2: 0x%08lX t3: 0x%08lX\n", e->t0.u32, e->t1.u32, e->t2.u32, e->t3.u32);
|
||||
display_printf(" t4: 0x%08lX t5: 0x%08lX t6: 0x%08lX t7: 0x%08lX\n", e->t4.u32, e->t5.u32, e->t6.u32, e->t7.u32);
|
||||
display_printf(" s0: 0x%08lX s1: 0x%08lX s2: 0x%08lX s3: 0x%08lX\n", e->s0.u32, e->s1.u32, e->s2.u32, e->s3.u32);
|
||||
display_printf(" s4: 0x%08lX s5: 0x%08lX s6: 0x%08lX s7: 0x%08lX\n", e->s4.u32, e->s5.u32, e->s6.u32, e->s7.u32);
|
||||
display_printf(" t8: 0x%08lX t9: 0x%08lX k0: 0x%08lX k1: 0x%08lX\n", e->t8.u32, e->t9.u32, e->k0.u32, e->k1.u32);
|
||||
display_printf(" gp: 0x%08lX sp: 0x%08lX s8: 0x%08lX ra: 0x%08lX\n\n", e->gp.u32, e->sp.u32, e->s8.u32, e->ra.u32);
|
||||
} else {
|
||||
display_printf("[ Runtime error ]\n");
|
||||
}
|
||||
|
||||
if (exception_code == EXCEPTION_INTERRUPT) {
|
||||
if (interrupt_mask & INTERRUPT_MASK_TIMER) {
|
||||
exception_disable_watchdog();
|
||||
display_printf("Still loading after 5 second limit...\n\n");
|
||||
return;
|
||||
}
|
||||
} else if (exception_code == EXCEPTION_SYSCALL) {
|
||||
uint32_t code = (((*instruction_address) & SYSCALL_CODE_MASK) >> SYSCALL_CODE_BIT);
|
||||
|
||||
if (code == TRIGGER_CODE_ERROR) {
|
||||
const char *fmt = (const char *) (e->a0.u32);
|
||||
va_list args = *((va_list *) (e->sp.u32));
|
||||
display_vprintf(fmt, args);
|
||||
display_printf("\n");
|
||||
}
|
||||
}
|
||||
version_print();
|
||||
display_printf("[ Unhandled exception ]\n");
|
||||
display_printf("%s\n", exception_get_description(exception_code));
|
||||
display_printf(" pc: 0x%08lX sr: 0x%08lX cr: 0x%08lX va: 0x%08lX\n", e->epc.u32, e->sr, e->cr, e->badvaddr.u32);
|
||||
display_printf(" zr: 0x%08lX at: 0x%08lX v0: 0x%08lX v1: 0x%08lX\n", e->zr.u32, e->at.u32, e->v0.u32, e->v1.u32);
|
||||
display_printf(" a0: 0x%08lX a1: 0x%08lX a2: 0x%08lX a3: 0x%08lX\n", e->a0.u32, e->a1.u32, e->a2.u32, e->a3.u32);
|
||||
display_printf(" t0: 0x%08lX t1: 0x%08lX t2: 0x%08lX t3: 0x%08lX\n", e->t0.u32, e->t1.u32, e->t2.u32, e->t3.u32);
|
||||
display_printf(" t4: 0x%08lX t5: 0x%08lX t6: 0x%08lX t7: 0x%08lX\n", e->t4.u32, e->t5.u32, e->t6.u32, e->t7.u32);
|
||||
display_printf(" s0: 0x%08lX s1: 0x%08lX s2: 0x%08lX s3: 0x%08lX\n", e->s0.u32, e->s1.u32, e->s2.u32, e->s3.u32);
|
||||
display_printf(" s4: 0x%08lX s5: 0x%08lX s6: 0x%08lX s7: 0x%08lX\n", e->s4.u32, e->s5.u32, e->s6.u32, e->s7.u32);
|
||||
display_printf(" t8: 0x%08lX t9: 0x%08lX k0: 0x%08lX k1: 0x%08lX\n", e->t8.u32, e->t9.u32, e->k0.u32, e->k1.u32);
|
||||
display_printf(" gp: 0x%08lX sp: 0x%08lX s8: 0x%08lX ra: 0x%08lX\n\n", e->gp.u32, e->sp.u32, e->s8.u32, e->ra.u32);
|
||||
|
||||
while (1);
|
||||
}
|
||||
|
@ -2,11 +2,6 @@
|
||||
#define EXCEPTION_H__
|
||||
|
||||
|
||||
#define TRIGGER_CODE_ERROR (0)
|
||||
|
||||
#define EXCEPTION_TRIGGER(code) { asm volatile ("syscall %[c]\n" :: [c] "i" (code)); }
|
||||
|
||||
|
||||
void exception_enable_interrupts (void);
|
||||
void exception_disable_interrupts (void);
|
||||
void exception_enable_watchdog (void);
|
||||
|
@ -1,6 +1,69 @@
|
||||
#include "exception_regs.h"
|
||||
#include "display.h"
|
||||
#include "sc64.h"
|
||||
#include "version.h"
|
||||
#include "../assets/assets.h"
|
||||
|
||||
|
||||
void exception_interrupt_handler (uint32_t exception_code, uint32_t interrupt_mask, exception_t *e) {
|
||||
typedef enum {
|
||||
INTERRUPT_SW_0 = (1 << 0),
|
||||
INTERRUPT_SW_1 = (1 << 1),
|
||||
INTERRUPT_RCP = (1 << 2),
|
||||
INTERRUPT_CART = (1 << 3),
|
||||
INTERRUPT_PRENMI = (1 << 4),
|
||||
INTERRUPT_HW_5 = (1 << 5),
|
||||
INTERRUPT_HW_6 = (1 << 6),
|
||||
INTERRUPT_TIMER = (1 << 7),
|
||||
} interrupt_t;
|
||||
|
||||
|
||||
static void exception_interrupt_unhandled (uint8_t interrupt) {
|
||||
display_init((uint32_t *) (&assets_sc64_logo_640_240_dimmed));
|
||||
|
||||
version_print();
|
||||
display_printf("[ Unhandled interrupt ]\n");
|
||||
display_printf("Pending (0x%02X):\n", interrupt);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
switch (interrupt & (1 << i)) {
|
||||
case INTERRUPT_SW_0: display_printf(" Software interrupt (0)\n"); break;
|
||||
case INTERRUPT_SW_1: display_printf(" Software interrupt (1)\n"); break;
|
||||
case INTERRUPT_RCP: display_printf(" RCP interrupt (2)\n"); break;
|
||||
case INTERRUPT_CART: display_printf(" CART interrupt (3)\n"); break;
|
||||
case INTERRUPT_PRENMI: display_printf(" Pre NMI interrupt (4)\n"); break;
|
||||
case INTERRUPT_HW_5: display_printf(" Hardware interrupt (5)\n"); break;
|
||||
case INTERRUPT_HW_6: display_printf(" Hardware interrupt (6)\n"); break;
|
||||
case INTERRUPT_TIMER: display_printf(" Timer interrupt (7)\n"); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
while (1);
|
||||
}
|
||||
|
||||
|
||||
void exception_interrupt_handler (uint8_t interrupt) {
|
||||
if (interrupt & INTERRUPT_CART) {
|
||||
sc64_irq_t irq = sc64_irq_pending();
|
||||
|
||||
if (irq != SC64_IRQ_NONE) {
|
||||
return sc64_irq_callback(irq);
|
||||
}
|
||||
}
|
||||
|
||||
if (interrupt & INTERRUPT_PRENMI) {
|
||||
if (display_ready()) {
|
||||
display_init(NULL);
|
||||
display_printf("Resetting...\n");
|
||||
}
|
||||
while (1);
|
||||
}
|
||||
|
||||
if (interrupt & INTERRUPT_TIMER) {
|
||||
display_init((uint32_t *) (&assets_sc64_logo_640_240_dimmed));
|
||||
version_print();
|
||||
display_printf("[ Watchdog ]\n");
|
||||
display_printf("SC64 bootloader did not finish loading in 5 seconds\n");
|
||||
while (1);
|
||||
}
|
||||
|
||||
exception_interrupt_unhandled(interrupt);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "io.h"
|
||||
#include "sc64.h"
|
||||
#include "error.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
@ -7,13 +8,16 @@ typedef struct {
|
||||
io32_t DATA[2];
|
||||
io32_t IDENTIFIER;
|
||||
io32_t KEY;
|
||||
io32_t IRQ;
|
||||
} sc64_regs_t;
|
||||
|
||||
#define SC64_REGS_BASE (0x1FFF0000UL)
|
||||
#define SC64_REGS ((sc64_regs_t *) SC64_REGS_BASE)
|
||||
|
||||
|
||||
#define SC64_SR_IRQ_PENDING (1 << 29)
|
||||
#define SC64_SR_CMD_IRQ_REQUEST (1 << 8)
|
||||
#define SC64_SR_CMD_IRQ_PENDING (1 << 28)
|
||||
#define SC64_SR_MCU_IRQ_PENDING (1 << 29)
|
||||
#define SC64_SR_CMD_ERROR (1 << 30)
|
||||
#define SC64_SR_CPU_BUSY (1 << 31)
|
||||
|
||||
@ -24,6 +28,9 @@ typedef struct {
|
||||
#define SC64_KEY_UNLOCK_2 (0x4F434B5FUL)
|
||||
#define SC64_KEY_LOCK (0xFFFFFFFFUL)
|
||||
|
||||
#define SC64_IRQ_CMD_CLEAR (1 << 30)
|
||||
#define SC64_IRQ_MCU_CLEAR (1 << 31)
|
||||
|
||||
|
||||
typedef enum {
|
||||
CMD_ID_IDENTIFIER_GET = 'v',
|
||||
@ -67,16 +74,30 @@ typedef struct {
|
||||
} sc64_cmd_t;
|
||||
|
||||
|
||||
static bool use_cmd_irq = false;
|
||||
static volatile bool wait_cmd_irq = false;
|
||||
|
||||
|
||||
static sc64_error_t sc64_execute_cmd (sc64_cmd_t *cmd) {
|
||||
uint32_t sr;
|
||||
|
||||
pi_io_write(&SC64_REGS->DATA[0], cmd->arg[0]);
|
||||
pi_io_write(&SC64_REGS->DATA[1], cmd->arg[1]);
|
||||
|
||||
pi_io_write(&SC64_REGS->SR_CMD, (cmd->id & 0xFF));
|
||||
|
||||
uint32_t sr;
|
||||
do {
|
||||
if (use_cmd_irq) {
|
||||
wait_cmd_irq = true;
|
||||
pi_io_write(&SC64_REGS->SR_CMD, (SC64_SR_CMD_IRQ_REQUEST | (cmd->id & 0xFF)));
|
||||
while (wait_cmd_irq);
|
||||
sr = pi_io_read(&SC64_REGS->SR_CMD);
|
||||
} while (sr & SC64_SR_CPU_BUSY);
|
||||
if (sr & SC64_SR_CPU_BUSY) {
|
||||
error_display("[Unexpected] SC64 CMD busy flag set");
|
||||
}
|
||||
} else {
|
||||
pi_io_write(&SC64_REGS->SR_CMD, (cmd->id & 0xFF));
|
||||
do {
|
||||
sr = pi_io_read(&SC64_REGS->SR_CMD);
|
||||
} while (sr & SC64_SR_CPU_BUSY);
|
||||
}
|
||||
|
||||
if (sr & SC64_SR_CMD_ERROR) {
|
||||
return (sc64_error_t) (pi_io_read(&SC64_REGS->DATA[0]));
|
||||
@ -88,6 +109,18 @@ static sc64_error_t sc64_execute_cmd (sc64_cmd_t *cmd) {
|
||||
return SC64_OK;
|
||||
}
|
||||
|
||||
static void sc64_mcu_irq_callback (void) {
|
||||
error_display("[Unexpected] SC64 MCU interrupt received");
|
||||
}
|
||||
|
||||
static void sc64_cmd_irq_callback (void) {
|
||||
if (wait_cmd_irq) {
|
||||
wait_cmd_irq = false;
|
||||
} else {
|
||||
error_display("[Unexpected] SC64 CMD interrupt received");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const char *sc64_error_description (sc64_error_t error) {
|
||||
sc64_error_type_t type = (sc64_error_type_t) ((error >> 24) & 0xFF);
|
||||
@ -164,12 +197,31 @@ bool sc64_check_presence (void) {
|
||||
}
|
||||
|
||||
|
||||
bool sc64_irq_pending (void) {
|
||||
return (pi_io_read(&SC64_REGS->SR_CMD) & SC64_SR_IRQ_PENDING);
|
||||
void sc64_cmd_irq_enable (bool enable) {
|
||||
use_cmd_irq = enable;
|
||||
}
|
||||
|
||||
void sc64_irq_clear (void) {
|
||||
pi_io_write(&SC64_REGS->IDENTIFIER, 0);
|
||||
sc64_irq_t sc64_irq_pending (void) {
|
||||
uint32_t sr = pi_io_read(&SC64_REGS->SR_CMD);
|
||||
sc64_irq_t irq = SC64_IRQ_NONE;
|
||||
if (sr & SC64_SR_MCU_IRQ_PENDING) {
|
||||
irq |= SC64_IRQ_MCU;
|
||||
}
|
||||
if (sr & SC64_SR_CMD_IRQ_PENDING) {
|
||||
irq |= SC64_IRQ_CMD;
|
||||
}
|
||||
return irq;
|
||||
}
|
||||
|
||||
void sc64_irq_callback (sc64_irq_t irq) {
|
||||
if (irq & SC64_IRQ_MCU) {
|
||||
sc64_mcu_irq_callback();
|
||||
pi_io_write(&SC64_REGS->IRQ, SC64_IRQ_MCU_CLEAR);
|
||||
}
|
||||
if (irq & SC64_IRQ_CMD) {
|
||||
sc64_cmd_irq_callback();
|
||||
pi_io_write(&SC64_REGS->IRQ, SC64_IRQ_CMD_CLEAR);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -159,6 +159,12 @@ typedef enum {
|
||||
SD_CARD_STATUS_BYTE_SWAP = (1 << 4),
|
||||
} sc64_sd_card_status_t;
|
||||
|
||||
typedef enum {
|
||||
SC64_IRQ_NONE = 0,
|
||||
SC64_IRQ_MCU = (1 << 0),
|
||||
SC64_IRQ_CMD = (1 << 1),
|
||||
} sc64_irq_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
volatile uint8_t BUFFER[8192];
|
||||
@ -177,8 +183,9 @@ void sc64_unlock (void);
|
||||
void sc64_lock (void);
|
||||
bool sc64_check_presence (void);
|
||||
|
||||
bool sc64_irq_pending (void);
|
||||
void sc64_irq_clear (void);
|
||||
void sc64_cmd_irq_enable (bool enable);
|
||||
sc64_irq_t sc64_irq_pending (void);
|
||||
void sc64_irq_callback (sc64_irq_t irq);
|
||||
|
||||
sc64_error_t sc64_get_identifier (uint32_t *identifier);
|
||||
sc64_error_t sc64_get_version (uint16_t *major, uint16_t *minor, uint32_t *revision);
|
||||
|
@ -115,6 +115,22 @@ static void test_sc64_cfg (void) {
|
||||
display_printf("%02d:%02d:%02d", FROM_BCD(t.hour), FROM_BCD(t.minute), FROM_BCD(t.second));
|
||||
display_printf(" (%s)", weekdays[FROM_BCD(t.weekday)]);
|
||||
display_printf("\n");
|
||||
|
||||
int count = 65536;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
if ((i % (count / 64)) == 0) {
|
||||
display_printf(".");
|
||||
}
|
||||
if ((error = sc64_get_identifier(&identifier)) != SC64_OK) {
|
||||
error_display("Command IDENTIFIER_GET failed\n (%08X) - %s", error, sc64_error_description(error));
|
||||
}
|
||||
if (identifier != 0x53437632) {
|
||||
error_display("Invalid identifier received: 0x%08X", identifier);
|
||||
}
|
||||
}
|
||||
|
||||
display_printf("\n");
|
||||
}
|
||||
|
||||
static void test_pi (void) {
|
||||
@ -539,8 +555,18 @@ static struct {
|
||||
void test_execute (void) {
|
||||
sc64_error_t error;
|
||||
|
||||
const int test_count = sizeof(tests) / sizeof(tests[0]);
|
||||
int current = 0;
|
||||
|
||||
display_init(NULL);
|
||||
display_printf("SC64 Test suite (%d / %d)\n\n", 0, test_count);
|
||||
|
||||
display_printf("Initializing...\n");
|
||||
|
||||
pi_io_config(0x0F, 0x05, 0x0C, 0x02);
|
||||
|
||||
sc64_cmd_irq_enable(true);
|
||||
|
||||
if ((error = sc64_set_config(CFG_ID_ROM_WRITE_ENABLE, true)) != SC64_OK) {
|
||||
error_display("Command CONFIG_SET [ROM_WRITE_ENABLE] failed\n (%08X) - %s", error, sc64_error_description(error));
|
||||
}
|
||||
@ -551,9 +577,6 @@ void test_execute (void) {
|
||||
|
||||
random_seed = __entropy + c0_count();
|
||||
|
||||
const int test_count = sizeof(tests) / sizeof(tests[0]);
|
||||
int current = 0;
|
||||
|
||||
while (true) {
|
||||
display_init(NULL);
|
||||
display_printf("SC64 Test suite (%d / %d)\n\n", current + 1, test_count);
|
||||
|
@ -1,7 +1,12 @@
|
||||
#include "version.h"
|
||||
#include "display.h"
|
||||
|
||||
|
||||
static version_t version = {
|
||||
const struct {
|
||||
const char *git_branch;
|
||||
const char *git_tag;
|
||||
const char *git_sha;
|
||||
const char *git_message;
|
||||
} version = {
|
||||
#ifdef GIT_BRANCH
|
||||
.git_branch = GIT_BRANCH,
|
||||
#else
|
||||
@ -29,6 +34,10 @@ static version_t version = {
|
||||
};
|
||||
|
||||
|
||||
version_t *version_get (void) {
|
||||
return &version;
|
||||
void version_print (void) {
|
||||
display_printf("[ SC64 bootloader metadata ]\n");
|
||||
display_printf("branch: %s | tag: %s\n", version.git_branch, version.git_tag);
|
||||
display_printf("sha: %s\n", version.git_sha);
|
||||
display_printf("msg: %s\n", version.git_message);
|
||||
display_printf("\n");
|
||||
}
|
||||
|
@ -2,15 +2,7 @@
|
||||
#define VERSION_H__
|
||||
|
||||
|
||||
typedef const struct {
|
||||
const char *git_branch;
|
||||
const char *git_tag;
|
||||
const char *git_sha;
|
||||
const char *git_message;
|
||||
} version_t;
|
||||
|
||||
|
||||
const version_t *version_get (void);
|
||||
void version_print (void);
|
||||
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user