mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-25 15:16:53 +01:00
mooore cleanup
This commit is contained in:
parent
42d060a518
commit
5d94225f77
4
.vscode/launch.json
vendored
4
.vscode/launch.json
vendored
@ -40,14 +40,14 @@
|
||||
"linux": {
|
||||
"args": [
|
||||
"-f", "/dev/ttyUSB0",
|
||||
"-b", "4",
|
||||
"-b", "1",
|
||||
"-q",
|
||||
]
|
||||
},
|
||||
"windows": {
|
||||
"args": [
|
||||
"-f", "\\\\.\\D:",
|
||||
"-b", "4",
|
||||
"-b", "1",
|
||||
"-q",
|
||||
]
|
||||
}
|
||||
|
@ -10,8 +10,12 @@ fi
|
||||
|
||||
__SC64_VERSION=$(printf "[ %q | %q | %q ]" $GIT_BRANCH $GIT_TAG $GIT_SHA)
|
||||
|
||||
if [ -t 1 ]; then
|
||||
DOCKER_OPTIONS="-it"
|
||||
fi
|
||||
|
||||
docker run \
|
||||
--rm \
|
||||
--rm $DOCKER_OPTIONS \
|
||||
--user $(id -u):$(id -g) \
|
||||
--mount type=bind,src="$(pwd)",target="/workdir" \
|
||||
-e __SC64_VERSION="$__SC64_VERSION" \
|
||||
|
@ -132,8 +132,6 @@ void boot (boot_info_t *info) {
|
||||
io_write(&ipl3_dst[i], pi_io_read(&ipl3_src[i]));
|
||||
}
|
||||
|
||||
deinit();
|
||||
|
||||
register void (*entry_point)(void) asm ("t3");
|
||||
register uint32_t boot_device asm ("s3");
|
||||
register uint32_t tv_type asm ("s4");
|
||||
|
@ -5,3 +5,8 @@ void error_display (const char *fmt, ...) {
|
||||
EXCEPTION_TRIGGER(TRIGGER_CODE_ERROR);
|
||||
while (1);
|
||||
}
|
||||
|
||||
void __assert_func (const char *file, int line, const char *func, const char *failedexpr) {
|
||||
EXCEPTION_TRIGGER(TRIGGER_CODE_ASSERT);
|
||||
while (1);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "regs.h"
|
||||
#include "vr4300.h"
|
||||
|
||||
|
||||
#define WATCHDOG_TIMEOUT (10 * (93750000UL / 2))
|
||||
#define WATCHDOG_TIMEOUT (1 * (93750000UL / 2))
|
||||
|
||||
#define VECTOR_LOCATION (0xA0000000UL)
|
||||
#define VECTOR_SIZE (0x80)
|
||||
@ -91,7 +91,7 @@ exception_check_type:
|
||||
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
|
||||
bne $t0, $zero, exception_fatal
|
||||
beq $a0, $zero, exception_interrupt
|
||||
|
||||
exception_fatal:
|
||||
|
@ -3,7 +3,8 @@
|
||||
#include "exception.h"
|
||||
#include "font.h"
|
||||
#include "io.h"
|
||||
#include "regs.h"
|
||||
#include "sc64.h"
|
||||
#include "vr4300.h"
|
||||
|
||||
|
||||
typedef union {
|
||||
@ -105,7 +106,7 @@ static const vi_regs_t vi_config[] = {{
|
||||
.V_SCALE = ((0x100 * SCREEN_HEIGHT) / 60),
|
||||
}};
|
||||
|
||||
static io32_t *exception_framebuffer = (io32_t *) (0x00200000UL);
|
||||
static io32_t *exception_framebuffer = (io32_t *) (0x0026A000UL);
|
||||
|
||||
|
||||
static void exception_init_screen (void) {
|
||||
@ -151,31 +152,35 @@ static void exception_draw_character (int x, int y, char c) {
|
||||
}
|
||||
}
|
||||
|
||||
static void exception_print_string (int *x, int *y, const char *s) {
|
||||
int line_x = *x;
|
||||
static void exception_print_string (const char *s) {
|
||||
static int x = BORDER_WIDTH;
|
||||
static int y = BORDER_HEIGHT;
|
||||
|
||||
while (*s != '\0') {
|
||||
if (*s == '\n') {
|
||||
line_x = BORDER_WIDTH;
|
||||
*y += LINE_HEIGHT;
|
||||
x = BORDER_WIDTH;
|
||||
y += LINE_HEIGHT;
|
||||
s++;
|
||||
} else {
|
||||
exception_draw_character(line_x, *y, *s++);
|
||||
line_x += FONT_WIDTH;
|
||||
exception_draw_character(x, y, *s++);
|
||||
x += FONT_WIDTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void exception_print (int *x, int *y, const char* fmt, ...) {
|
||||
static void exception_vprint (const char *fmt, va_list args) {
|
||||
char line[256];
|
||||
|
||||
vsniprintf(line, sizeof(line), fmt, args);
|
||||
exception_print_string(line);
|
||||
sc64_uart_print_string(line);
|
||||
}
|
||||
|
||||
static void exception_print (const char* fmt, ...) {
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
|
||||
vsniprintf(line, sizeof(line), fmt, args);
|
||||
exception_print_string(x, y, line);
|
||||
*y += LINE_HEIGHT;
|
||||
|
||||
exception_vprint(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
@ -206,40 +211,38 @@ 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) {
|
||||
uint32_t sc64_version = pi_io_read(&SC64->VERSION);
|
||||
uint32_t *instruction_address = (((uint32_t *) (e->epc.u32)) + ((e->cr & C0_CR_BD) ? 1 : 0));
|
||||
int x = BORDER_WIDTH;
|
||||
int y = BORDER_HEIGHT;
|
||||
|
||||
exception_init_screen();
|
||||
|
||||
exception_print(&x, &y, "%s at pc: 0x%08lX\n", exception_get_description(exception_code), e->epc.u32);
|
||||
exception_print(&x, &y, "sr: 0x%08lX cr: 0x%08lX", e->sr, e->cr);
|
||||
exception_print(&x, &y, "zr: 0x%08lX at: 0x%08lX v0: 0x%08lX v1: 0x%08lX", e->zr.u32, e->at.u32, e->v0.u32, e->v1.u32);
|
||||
exception_print(&x, &y, "a0: 0x%08lX a1: 0x%08lX a2: 0x%08lX a3: 0x%08lX", e->a0.u32, e->a1.u32, e->a2.u32, e->a3.u32);
|
||||
exception_print(&x, &y, "t0: 0x%08lX t1: 0x%08lX t2: 0x%08lX t3: 0x%08lX", e->t0.u32, e->t1.u32, e->t2.u32, e->t3.u32);
|
||||
exception_print(&x, &y, "t4: 0x%08lX t5: 0x%08lX t6: 0x%08lX t7: 0x%08lX", e->t4.u32, e->t5.u32, e->t6.u32, e->t7.u32);
|
||||
exception_print(&x, &y, "s0: 0x%08lX s1: 0x%08lX s2: 0x%08lX s3: 0x%08lX", e->s0.u32, e->s1.u32, e->s2.u32, e->s3.u32);
|
||||
exception_print(&x, &y, "s4: 0x%08lX s5: 0x%08lX s6: 0x%08lX s7: 0x%08lX", e->s4.u32, e->s5.u32, e->s6.u32, e->s7.u32);
|
||||
exception_print(&x, &y, "t8: 0x%08lX t9: 0x%08lX k0: 0x%08lX k1: 0x%08lX", e->t8.u32, e->t9.u32, e->k0.u32, e->k1.u32);
|
||||
exception_print(&x, &y, "gp: 0x%08lX sp: 0x%08lX fp: 0x%08lX ra: 0x%08lX\n", e->gp.u32, e->sp.u32, e->fp.u32, e->ra.u32);
|
||||
exception_print(&x, &y, "vr: 0x%08lX = [%4s]", sc64_version, (char *) (&sc64_version));
|
||||
exception_print(&x, &y, "%s\n", XSTR(__SC64_VERSION));
|
||||
exception_print("%s at pc: 0x%08lX\n\n", exception_get_description(exception_code), e->epc.u32);
|
||||
exception_print("sr: 0x%08lX cr: 0x%08lX\n", e->sr, e->cr);
|
||||
exception_print("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);
|
||||
exception_print("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);
|
||||
exception_print("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);
|
||||
exception_print("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);
|
||||
exception_print("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);
|
||||
exception_print("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);
|
||||
exception_print("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);
|
||||
exception_print("gp: 0x%08lX sp: 0x%08lX fp: 0x%08lX ra: 0x%08lX\n\n", e->gp.u32, e->sp.u32, e->fp.u32, e->ra.u32);
|
||||
exception_print("vr: 0x%08lX = [%4s]\n", sc64_version, (char *) (&sc64_version));
|
||||
exception_print("%s\n\n", XSTR(__SC64_VERSION));
|
||||
|
||||
if (exception_code == EXCEPTION_INTERRUPT) {
|
||||
if (interrupt_mask & INTERRUPT_MASK_TIMER) {
|
||||
exception_print(&x, &y, "Bootloader did not finish within 10 seconds limit");
|
||||
exception_print("Bootloader did not finish within 1 second limit\n");
|
||||
}
|
||||
} else if (exception_code == EXCEPTION_SYSCALL) {
|
||||
uint32_t code = (((*instruction_address) & SYSCALL_CODE_MASK) >> SYSCALL_CODE_BIT);
|
||||
|
||||
if (code == TRIGGER_CODE_ERROR) {
|
||||
exception_print(&x, &y, (const char *) (e->a0.u32), e->a1.u32, e->a2.u32, e->a3.u32);
|
||||
exception_vprint((const char *) (e->a0.u32), (va_list) (e->sp.u32 + 8));
|
||||
} else if (code == TRIGGER_CODE_ASSERT) {
|
||||
const char *file = (const char *) (e->a0.u32);
|
||||
int line = (int) (e->a1.u32);
|
||||
const char *func = (const char *) (e->a2.u32);
|
||||
const char *failedexpr = (const char *) (e->a3.u32);
|
||||
exception_print(&x, &y, "Assertion \"%s\" failed:", failedexpr);
|
||||
exception_print(&x, &y, " file \"%s\", line %d, %s%s", file, line, func ? "function: " : "", func);
|
||||
exception_print("Assertion \"%s\" failed:\n", failedexpr);
|
||||
exception_print(" file \"%s\", line %d, %s%s\n", file, line, func ? "function: " : "", func);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "diskio.h"
|
||||
#include "../sc64.h"
|
||||
|
||||
|
||||
DSTATUS disk_status (BYTE pdrv) {
|
||||
return 0;
|
||||
}
|
||||
@ -11,26 +12,22 @@ DSTATUS disk_initialize (BYTE pdrv) {
|
||||
}
|
||||
|
||||
DRESULT disk_read (BYTE pdrv, BYTE *buff, LBA_t sector, UINT count) {
|
||||
sc64_storage_type_t storage_type;
|
||||
|
||||
if (pdrv == 0) {
|
||||
return RES_NOTRDY;
|
||||
storage_type = SC64_STORAGE_TYPE_SD;
|
||||
} else if (pdrv == 1) {
|
||||
sc64_debug_fsd_read(buff, sector, count);
|
||||
return RES_OK;
|
||||
}
|
||||
storage_type = SC64_STORAGE_TYPE_USB;
|
||||
} else {
|
||||
return RES_PARERR;
|
||||
}
|
||||
|
||||
#if FF_FS_READONLY == 0
|
||||
DRESULT disk_write (BYTE pdrv, const BYTE *buff, LBA_t sector, UINT count) {
|
||||
if (pdrv == 0) {
|
||||
return RES_NOTRDY;
|
||||
} else if (pdrv == 1) {
|
||||
sc64_debug_fsd_write(buff, sector, count);
|
||||
if (sc64_storage_read(storage_type, buff, sector, count) != SC64_STORAGE_OK) {
|
||||
return RES_ERROR;
|
||||
}
|
||||
|
||||
return RES_OK;
|
||||
}
|
||||
return RES_PARERR;
|
||||
}
|
||||
#endif
|
||||
|
||||
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void *buff) {
|
||||
return RES_PARERR;
|
||||
|
@ -217,18 +217,6 @@ typedef struct {
|
||||
#define ROM_CART ((io32_t *) ROM_CART_BASE)
|
||||
|
||||
|
||||
typedef struct {
|
||||
io32_t ID;
|
||||
io32_t __padding_1[4];
|
||||
io32_t RD_PTR;
|
||||
io32_t __padding_2[2];
|
||||
io8_t BUFFER[(64 * 1024) - 0x20];
|
||||
} is_viewer_t;
|
||||
|
||||
#define ISV_BASE (0x13FF0000UL)
|
||||
#define ISV ((is_viewer_t *) ISV_BASE)
|
||||
|
||||
|
||||
#define PIFRAM_BASE (0x1FC007C0UL)
|
||||
#define PIFRAM ((io8_t *) PIFRAM_BASE)
|
||||
|
||||
@ -239,7 +227,7 @@ typedef struct {
|
||||
io32_t VERSION;
|
||||
} sc64_regs_t;
|
||||
|
||||
#define SC64_BASE (0x1FFF0000)
|
||||
#define SC64_BASE (0x1FFF0000UL)
|
||||
#define SC64 ((sc64_regs_t *) SC64_BASE)
|
||||
|
||||
#define SC64_SR_CMD_ERROR (1 << 28)
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "boot.h"
|
||||
#include "error.h"
|
||||
#include "init.h"
|
||||
#include "sc64.h"
|
||||
#include "storage.h"
|
||||
|
||||
@ -8,17 +9,15 @@ void main (void) {
|
||||
boot_info_t boot_info;
|
||||
sc64_info_t sc64_info;
|
||||
|
||||
boot_info.reset_type = OS_INFO->reset_type;
|
||||
|
||||
sc64_get_info(&sc64_info);
|
||||
|
||||
switch (sc64_info.boot_mode) {
|
||||
case BOOT_MODE_MENU_SD:
|
||||
storage_run_menu(STORAGE_BACKEND_SD, &boot_info, &sc64_info);
|
||||
storage_run_menu(STORAGE_BACKEND_SD);
|
||||
break;
|
||||
|
||||
case BOOT_MODE_MENU_USB:
|
||||
storage_run_menu(STORAGE_BACKEND_USB, &boot_info, &sc64_info);
|
||||
storage_run_menu(STORAGE_BACKEND_USB);
|
||||
break;
|
||||
|
||||
case BOOT_MODE_ROM:
|
||||
@ -30,10 +29,12 @@ void main (void) {
|
||||
break;
|
||||
|
||||
default:
|
||||
error_display("Unknown boot mode selected [%d]", sc64_info.boot_mode);
|
||||
error_display("Unknown boot mode selected [%d]\n", sc64_info.boot_mode);
|
||||
break;
|
||||
}
|
||||
|
||||
boot_info.reset_type = OS_INFO->reset_type;
|
||||
|
||||
if (sc64_info.tv_type != TV_TYPE_UNKNOWN) {
|
||||
boot_info.tv_type = sc64_info.tv_type;
|
||||
} else {
|
||||
@ -42,7 +43,7 @@ void main (void) {
|
||||
}
|
||||
}
|
||||
|
||||
if (sc64_info.cic_seed != 0xFFFF) {
|
||||
if (sc64_info.cic_seed != CIC_SEED_UNKNOWN) {
|
||||
boot_info.cic_seed = sc64_info.cic_seed & 0xFF;
|
||||
boot_info.version = (sc64_info.cic_seed >> 8) & 0x01;
|
||||
} else {
|
||||
@ -52,5 +53,7 @@ void main (void) {
|
||||
}
|
||||
}
|
||||
|
||||
deinit();
|
||||
|
||||
boot(&boot_info);
|
||||
}
|
||||
|
@ -1,9 +1,6 @@
|
||||
#include "sc64.h"
|
||||
|
||||
|
||||
extern char header_text_info __attribute__((section(".data")));
|
||||
|
||||
|
||||
bool sc64_check_presence (void) {
|
||||
uint32_t version = pi_io_read(&SC64->VERSION);
|
||||
return (version == SC64_VERSION_2);
|
||||
@ -51,148 +48,162 @@ void sc64_set_config (cfg_id_t id, uint32_t value) {
|
||||
}
|
||||
|
||||
void sc64_get_info (sc64_info_t *info) {
|
||||
info->dd_enabled = (bool) sc64_get_config(CFG_ID_DD_ENABLE);
|
||||
info->is_viewer_enabled = (bool) sc64_get_config(CFG_ID_IS_VIEWER_ENABLE);
|
||||
info->save_type = (save_type_t) sc64_get_config(CFG_ID_SAVE_TYPE);
|
||||
// info->dd_enabled = (bool) sc64_get_config(CFG_ID_DD_ENABLE);
|
||||
// info->is_viewer_enabled = (bool) sc64_get_config(CFG_ID_IS_VIEWER_ENABLE);
|
||||
// info->save_type = (save_type_t) sc64_get_config(CFG_ID_SAVE_TYPE);
|
||||
info->cic_seed = (uint16_t) sc64_get_config(CFG_ID_CIC_SEED);
|
||||
info->tv_type = (tv_type_t) sc64_get_config(CFG_ID_TV_TYPE);
|
||||
info->save_location = (io32_t *) (0x10000000 | sc64_get_config(CFG_ID_SAVE_OFFEST));
|
||||
info->ddipl_location = (io32_t *) (0x10000000 | sc64_get_config(CFG_ID_DDIPL_OFFEST));
|
||||
// info->save_location = (io32_t *) (0x10000000 | sc64_get_config(CFG_ID_SAVE_OFFEST));
|
||||
// info->ddipl_location = (io32_t *) (0x10000000 | sc64_get_config(CFG_ID_DDIPL_OFFEST));
|
||||
info->boot_mode = (boot_mode_t) sc64_get_config(CFG_ID_BOOT_MODE);
|
||||
}
|
||||
|
||||
void sc64_wait_usb_rx_ready (uint32_t *type, uint32_t *length) {
|
||||
uint32_t result[2];
|
||||
do {
|
||||
sc64_perform_cmd(SC64_CMD_DEBUG_RX_READY, NULL, result);
|
||||
} while (result[0] == 0 && result[1] == 0);
|
||||
*type = result[0];
|
||||
*length = result[1];
|
||||
// void sc64_wait_usb_rx_ready (uint32_t *type, uint32_t *length) {
|
||||
// uint32_t result[2];
|
||||
// do {
|
||||
// sc64_perform_cmd(SC64_CMD_DEBUG_RX_READY, NULL, result);
|
||||
// } while (result[0] == 0 && result[1] == 0);
|
||||
// *type = result[0];
|
||||
// *length = result[1];
|
||||
// }
|
||||
|
||||
// void sc64_wait_usb_rx_busy (void) {
|
||||
// uint32_t result[2];
|
||||
// do {
|
||||
// sc64_perform_cmd(SC64_CMD_DEBUG_RX_BUSY, NULL, result);
|
||||
// } while (result[0]);
|
||||
// }
|
||||
|
||||
// void sc64_usb_rx_data (io32_t *address, uint32_t length) {
|
||||
// uint32_t args[2] = { (uint32_t) (address), ALIGN(length, 2) };
|
||||
// sc64_perform_cmd(SC64_CMD_DEBUG_RX_DATA, args, NULL);
|
||||
// }
|
||||
|
||||
// void sc64_wait_usb_tx_ready (void) {
|
||||
// uint32_t result[2];
|
||||
// do {
|
||||
// sc64_perform_cmd(SC64_CMD_DEBUG_TX_READY, NULL, result);
|
||||
// } while (!result[0]);
|
||||
// }
|
||||
|
||||
// void sc64_usb_tx_data (io32_t *address, uint32_t length) {
|
||||
// uint32_t args[2] = { (uint32_t) (address), ALIGN(length, 2) };
|
||||
// sc64_perform_cmd(SC64_CMD_DEBUG_TX_DATA, args, NULL);
|
||||
// }
|
||||
|
||||
// void sc64_debug_write (uint8_t type, const void *data, uint32_t len) {
|
||||
// char *dma = "DMA@";
|
||||
// char *cmp = "CMPH";
|
||||
|
||||
// io32_t *sdram = (io32_t *) (SC64_DEBUG_WRITE_ADDRESS);
|
||||
|
||||
// uint8_t *src = (uint8_t *) (data);
|
||||
// uint32_t tmp;
|
||||
// io32_t *dst = sdram;
|
||||
|
||||
// uint32_t copy_length = ALIGN(len, 4);
|
||||
|
||||
// sc64_wait_usb_tx_ready();
|
||||
|
||||
// bool writable = sc64_get_config(CFG_ID_SDRAM_WRITABLE);
|
||||
// bool sdram_switched = sc64_get_config(CFG_ID_SDRAM_SWITCH);
|
||||
|
||||
// if (!writable) {
|
||||
// sc64_set_config(CFG_ID_SDRAM_WRITABLE, true);
|
||||
// }
|
||||
// if (!sdram_switched) {
|
||||
// sc64_set_config(CFG_ID_SDRAM_SWITCH, true);
|
||||
// }
|
||||
|
||||
// pi_io_write(dst++, *((uint32_t *) (dma)));
|
||||
// pi_io_write(dst++, (type << 24) | len);
|
||||
|
||||
// while (src < ((uint8_t *) (data + copy_length))) {
|
||||
// tmp = ((*src++) << 24);
|
||||
// tmp |= ((*src++) << 16);
|
||||
// tmp |= ((*src++) << 8);
|
||||
// tmp |= ((*src++) << 0);
|
||||
// pi_io_write(dst++, tmp);
|
||||
// if (dst >= (io32_t *) ((void *) (sdram) + SC64_DEBUG_MAX_SIZE)) {
|
||||
// sc64_usb_tx_data(sdram, (dst - sdram) * sizeof(uint32_t));
|
||||
// sc64_wait_usb_tx_ready();
|
||||
// dst = sdram;
|
||||
// }
|
||||
// }
|
||||
|
||||
// pi_io_write(dst++, *((uint32_t *) (cmp)));
|
||||
|
||||
// if (!writable) {
|
||||
// sc64_set_config(CFG_ID_SDRAM_WRITABLE, false);
|
||||
// }
|
||||
// if (!sdram_switched) {
|
||||
// sc64_set_config(CFG_ID_SDRAM_SWITCH, false);
|
||||
// }
|
||||
|
||||
// sc64_usb_tx_data(sdram, (dst - sdram) * sizeof(uint32_t));
|
||||
// }
|
||||
|
||||
// void sc64_debug_fsd_read (const void *data, uint32_t sector, uint32_t count) {
|
||||
// uint32_t type;
|
||||
// uint32_t length;
|
||||
|
||||
// io32_t *sdram = (io32_t *) (SC64_DEBUG_READ_ADDRESS);
|
||||
|
||||
// io32_t *src = sdram;
|
||||
// uint32_t tmp;
|
||||
// uint8_t *dst = (uint8_t *) (data);
|
||||
|
||||
// uint32_t read_length = count * 512;
|
||||
|
||||
// sc64_debug_write(SC64_DEBUG_ID_FSD_SECTOR, §or, 4);
|
||||
// sc64_debug_write(SC64_DEBUG_ID_FSD_READ, &read_length, 4);
|
||||
// sc64_wait_usb_rx_ready(&type, &length);
|
||||
// sc64_usb_rx_data(sdram, length);
|
||||
// sc64_wait_usb_rx_busy();
|
||||
|
||||
// uint32_t copy_length = ALIGN(length, 4);
|
||||
|
||||
// bool sdram_switched = sc64_get_config(CFG_ID_SDRAM_SWITCH);
|
||||
|
||||
// if (!sdram_switched) {
|
||||
// sc64_set_config(CFG_ID_SDRAM_SWITCH, true);
|
||||
// }
|
||||
|
||||
// for (int i = 0; i < copy_length; i += 4) {
|
||||
// tmp = pi_io_read(src++);
|
||||
// *dst++ = (tmp >> 24);
|
||||
// *dst++ = (tmp >> 16);
|
||||
// *dst++ = (tmp >> 8);
|
||||
// *dst++ = (tmp & 0xFF);
|
||||
// }
|
||||
|
||||
// if (!sdram_switched) {
|
||||
// sc64_set_config(CFG_ID_SDRAM_SWITCH, false);
|
||||
// }
|
||||
// }
|
||||
|
||||
// void sc64_debug_fsd_write (const void *data, uint32_t sector, uint32_t count) {
|
||||
// sc64_debug_write(SC64_DEBUG_ID_FSD_SECTOR, §or, 4);
|
||||
// sc64_debug_write(SC64_DEBUG_ID_FSD_WRITE, data, count * 512);
|
||||
// }
|
||||
|
||||
// void sc64_init_is_viewer (void) {
|
||||
// sc64_set_config(CFG_ID_SDRAM_WRITABLE, true);
|
||||
// pi_io_write(&ISV->ID, 0);
|
||||
// }
|
||||
|
||||
sc64_storage_error_t sc64_storage_read(sc64_storage_type_t storage_type, const void *buff, uint32_t sector, uint32_t count) {
|
||||
return SC64_STORAGE_ERROR;
|
||||
}
|
||||
|
||||
void sc64_wait_usb_rx_busy (void) {
|
||||
uint32_t result[2];
|
||||
do {
|
||||
sc64_perform_cmd(SC64_CMD_DEBUG_RX_BUSY, NULL, result);
|
||||
} while (result[0]);
|
||||
void sc64_uart_print_string (const char *text) {
|
||||
#ifdef DEBUG
|
||||
uint32_t args[2] = { 0, 0 };
|
||||
while (*text != '\0') {
|
||||
args[0] = (uint32_t) (*text++);
|
||||
sc64_perform_cmd(SC64_CMD_UART_PUT, args, NULL);
|
||||
}
|
||||
|
||||
void sc64_usb_rx_data (io32_t *address, uint32_t length) {
|
||||
uint32_t args[2] = { (uint32_t) (address), ALIGN(length, 2) };
|
||||
sc64_perform_cmd(SC64_CMD_DEBUG_RX_DATA, args, NULL);
|
||||
}
|
||||
|
||||
void sc64_wait_usb_tx_ready (void) {
|
||||
uint32_t result[2];
|
||||
do {
|
||||
sc64_perform_cmd(SC64_CMD_DEBUG_TX_READY, NULL, result);
|
||||
} while (!result[0]);
|
||||
}
|
||||
|
||||
void sc64_usb_tx_data (io32_t *address, uint32_t length) {
|
||||
uint32_t args[2] = { (uint32_t) (address), ALIGN(length, 2) };
|
||||
sc64_perform_cmd(SC64_CMD_DEBUG_TX_DATA, args, NULL);
|
||||
}
|
||||
|
||||
void sc64_debug_write (uint8_t type, const void *data, uint32_t len) {
|
||||
char *dma = "DMA@";
|
||||
char *cmp = "CMPH";
|
||||
|
||||
io32_t *sdram = (io32_t *) (SC64_DEBUG_WRITE_ADDRESS);
|
||||
|
||||
uint8_t *src = (uint8_t *) (data);
|
||||
uint32_t tmp;
|
||||
io32_t *dst = sdram;
|
||||
|
||||
uint32_t copy_length = ALIGN(len, 4);
|
||||
|
||||
sc64_wait_usb_tx_ready();
|
||||
|
||||
bool writable = sc64_get_config(CFG_ID_SDRAM_WRITABLE);
|
||||
bool sdram_switched = sc64_get_config(CFG_ID_SDRAM_SWITCH);
|
||||
|
||||
if (!writable) {
|
||||
sc64_set_config(CFG_ID_SDRAM_WRITABLE, true);
|
||||
}
|
||||
if (!sdram_switched) {
|
||||
sc64_set_config(CFG_ID_SDRAM_SWITCH, true);
|
||||
}
|
||||
|
||||
pi_io_write(dst++, *((uint32_t *) (dma)));
|
||||
pi_io_write(dst++, (type << 24) | len);
|
||||
|
||||
while (src < ((uint8_t *) (data + copy_length))) {
|
||||
tmp = ((*src++) << 24);
|
||||
tmp |= ((*src++) << 16);
|
||||
tmp |= ((*src++) << 8);
|
||||
tmp |= ((*src++) << 0);
|
||||
pi_io_write(dst++, tmp);
|
||||
if (dst >= (io32_t *) ((void *) (sdram) + SC64_DEBUG_MAX_SIZE)) {
|
||||
sc64_usb_tx_data(sdram, (dst - sdram) * sizeof(uint32_t));
|
||||
sc64_wait_usb_tx_ready();
|
||||
dst = sdram;
|
||||
}
|
||||
}
|
||||
|
||||
pi_io_write(dst++, *((uint32_t *) (cmp)));
|
||||
|
||||
if (!writable) {
|
||||
sc64_set_config(CFG_ID_SDRAM_WRITABLE, false);
|
||||
}
|
||||
if (!sdram_switched) {
|
||||
sc64_set_config(CFG_ID_SDRAM_SWITCH, false);
|
||||
}
|
||||
|
||||
sc64_usb_tx_data(sdram, (dst - sdram) * sizeof(uint32_t));
|
||||
}
|
||||
|
||||
void sc64_debug_fsd_read (const void *data, uint32_t sector, uint32_t count) {
|
||||
uint32_t type;
|
||||
uint32_t length;
|
||||
|
||||
io32_t *sdram = (io32_t *) (SC64_DEBUG_READ_ADDRESS);
|
||||
|
||||
io32_t *src = sdram;
|
||||
uint32_t tmp;
|
||||
uint8_t *dst = (uint8_t *) (data);
|
||||
|
||||
uint32_t read_length = count * 512;
|
||||
|
||||
sc64_debug_write(SC64_DEBUG_ID_FSD_SECTOR, §or, 4);
|
||||
sc64_debug_write(SC64_DEBUG_ID_FSD_READ, &read_length, 4);
|
||||
sc64_wait_usb_rx_ready(&type, &length);
|
||||
sc64_usb_rx_data(sdram, length);
|
||||
sc64_wait_usb_rx_busy();
|
||||
|
||||
uint32_t copy_length = ALIGN(length, 4);
|
||||
|
||||
bool sdram_switched = sc64_get_config(CFG_ID_SDRAM_SWITCH);
|
||||
|
||||
if (!sdram_switched) {
|
||||
sc64_set_config(CFG_ID_SDRAM_SWITCH, true);
|
||||
}
|
||||
|
||||
for (int i = 0; i < copy_length; i += 4) {
|
||||
tmp = pi_io_read(src++);
|
||||
*dst++ = (tmp >> 24);
|
||||
*dst++ = (tmp >> 16);
|
||||
*dst++ = (tmp >> 8);
|
||||
*dst++ = (tmp & 0xFF);
|
||||
}
|
||||
|
||||
if (!sdram_switched) {
|
||||
sc64_set_config(CFG_ID_SDRAM_SWITCH, false);
|
||||
}
|
||||
}
|
||||
|
||||
void sc64_debug_fsd_write (const void *data, uint32_t sector, uint32_t count) {
|
||||
sc64_debug_write(SC64_DEBUG_ID_FSD_SECTOR, §or, 4);
|
||||
sc64_debug_write(SC64_DEBUG_ID_FSD_WRITE, data, count * 512);
|
||||
}
|
||||
|
||||
void sc64_init_is_viewer (void) {
|
||||
sc64_set_config(CFG_ID_SDRAM_WRITABLE, true);
|
||||
pi_io_write(&ISV->ID, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void sc64_init (void) {
|
||||
|
@ -4,28 +4,29 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
// #include <stdio.h>
|
||||
#include "io.h"
|
||||
|
||||
|
||||
#define SC64_CMD_CONFIG ('C')
|
||||
#define SC64_CMD_QUERY ('Q')
|
||||
#define SC64_CMD_DEBUG_RX_DATA ('E')
|
||||
#define SC64_CMD_DEBUG_RX_READY ('A')
|
||||
#define SC64_CMD_DEBUG_RX_BUSY ('F')
|
||||
#define SC64_CMD_DEBUG_TX_DATA ('D')
|
||||
#define SC64_CMD_DEBUG_TX_READY ('S')
|
||||
// #define SC64_CMD_DEBUG_RX_DATA ('E')
|
||||
// #define SC64_CMD_DEBUG_RX_READY ('A')
|
||||
// #define SC64_CMD_DEBUG_RX_BUSY ('F')
|
||||
// #define SC64_CMD_DEBUG_TX_DATA ('D')
|
||||
// #define SC64_CMD_DEBUG_TX_READY ('S')
|
||||
#define SC64_CMD_UART_PUT ('Z')
|
||||
|
||||
#define SC64_VERSION_2 (0x53437632)
|
||||
|
||||
#define SC64_DEBUG_WRITE_ADDRESS (0x13FF8000UL)
|
||||
#define SC64_DEBUG_READ_ADDRESS (0x13FF0000UL)
|
||||
#define SC64_DEBUG_MAX_SIZE (32 * 1024)
|
||||
// #define SC64_DEBUG_WRITE_ADDRESS (0x13FF8000UL)
|
||||
// #define SC64_DEBUG_READ_ADDRESS (0x13FF0000UL)
|
||||
// #define SC64_DEBUG_MAX_SIZE (32 * 1024)
|
||||
|
||||
#define SC64_DEBUG_ID_TEXT (0x01)
|
||||
#define SC64_DEBUG_ID_FSD_READ (0xF1)
|
||||
#define SC64_DEBUG_ID_FSD_WRITE (0xF2)
|
||||
#define SC64_DEBUG_ID_FSD_SECTOR (0xF3)
|
||||
// #define SC64_DEBUG_ID_TEXT (0x01)
|
||||
// #define SC64_DEBUG_ID_FSD_READ (0xF1)
|
||||
// #define SC64_DEBUG_ID_FSD_WRITE (0xF2)
|
||||
// #define SC64_DEBUG_ID_FSD_SECTOR (0xF3)
|
||||
|
||||
|
||||
typedef enum {
|
||||
@ -49,15 +50,15 @@ typedef enum {
|
||||
CFG_ID_IS_VIEWER_ENABLE,
|
||||
} cfg_id_t;
|
||||
|
||||
typedef enum {
|
||||
SAVE_TYPE_NONE = 0,
|
||||
SAVE_TYPE_EEPROM_4K = 1,
|
||||
SAVE_TYPE_EEPROM_16K = 2,
|
||||
SAVE_TYPE_SRAM = 3,
|
||||
SAVE_TYPE_FLASHRAM = 4,
|
||||
SAVE_TYPE_SRAM_BANKED = 5,
|
||||
SAVE_TYPE_FLASHRAM_PKST2 = 6,
|
||||
} save_type_t;
|
||||
// typedef enum {
|
||||
// SAVE_TYPE_NONE = 0,
|
||||
// SAVE_TYPE_EEPROM_4K = 1,
|
||||
// SAVE_TYPE_EEPROM_16K = 2,
|
||||
// SAVE_TYPE_SRAM = 3,
|
||||
// SAVE_TYPE_FLASHRAM = 4,
|
||||
// SAVE_TYPE_SRAM_BANKED = 5,
|
||||
// SAVE_TYPE_FLASHRAM_PKST2 = 6,
|
||||
// } save_type_t;
|
||||
|
||||
typedef enum {
|
||||
TV_TYPE_PAL = 0,
|
||||
@ -66,6 +67,10 @@ typedef enum {
|
||||
TV_TYPE_UNKNOWN = 3,
|
||||
} tv_type_t;
|
||||
|
||||
typedef enum {
|
||||
CIC_SEED_UNKNOWN = 0xFFFF,
|
||||
} cic_seed_t;
|
||||
|
||||
typedef enum {
|
||||
BOOT_MODE_MENU_SD = 0,
|
||||
BOOT_MODE_MENU_USB = 1,
|
||||
@ -75,17 +80,28 @@ typedef enum {
|
||||
} boot_mode_t;
|
||||
|
||||
typedef struct {
|
||||
bool dd_enabled;
|
||||
bool is_viewer_enabled;
|
||||
save_type_t save_type;
|
||||
// bool dd_enabled;
|
||||
// bool is_viewer_enabled;
|
||||
// save_type_t save_type;
|
||||
boot_mode_t boot_mode;
|
||||
uint16_t cic_seed;
|
||||
tv_type_t tv_type;
|
||||
io32_t *save_location;
|
||||
io32_t *ddipl_location;
|
||||
boot_mode_t boot_mode;
|
||||
// io32_t *save_location;
|
||||
// io32_t *ddipl_location;
|
||||
} sc64_info_t;
|
||||
|
||||
|
||||
typedef enum {
|
||||
SC64_STORAGE_TYPE_SD,
|
||||
SC64_STORAGE_TYPE_USB,
|
||||
} sc64_storage_type_t;
|
||||
|
||||
typedef enum {
|
||||
SC64_STORAGE_OK,
|
||||
SC64_STORAGE_ERROR,
|
||||
} sc64_storage_error_t;
|
||||
|
||||
|
||||
bool sc64_check_presence (void);
|
||||
void sc64_wait_cpu_ready (void);
|
||||
bool sc64_wait_cpu_busy (void);
|
||||
@ -93,15 +109,17 @@ bool sc64_perform_cmd (uint8_t cmd, uint32_t *args, uint32_t *result);
|
||||
uint32_t sc64_get_config (cfg_id_t id);
|
||||
void sc64_set_config (cfg_id_t id, uint32_t value);
|
||||
void sc64_get_info (sc64_info_t *info);
|
||||
void sc64_wait_usb_rx_ready (uint32_t *type, uint32_t *length);
|
||||
void sc64_wait_usb_rx_busy (void);
|
||||
void sc64_usb_rx_data (io32_t *address, uint32_t length);
|
||||
void sc64_wait_usb_tx_ready (void);
|
||||
void sc64_usb_tx_data (io32_t *address, uint32_t length);
|
||||
void sc64_debug_write (uint8_t type, const void *data, uint32_t len);
|
||||
void sc64_debug_fsd_read (const void *data, uint32_t sector, uint32_t count);
|
||||
void sc64_debug_fsd_write (const void *data, uint32_t sector, uint32_t count);
|
||||
void sc64_init_is_viewer (void);
|
||||
// void sc64_wait_usb_rx_ready (uint32_t *type, uint32_t *length);
|
||||
// void sc64_wait_usb_rx_busy (void);
|
||||
// void sc64_usb_rx_data (io32_t *address, uint32_t length);
|
||||
// void sc64_wait_usb_tx_ready (void);
|
||||
// void sc64_usb_tx_data (io32_t *address, uint32_t length);
|
||||
// void sc64_debug_write (uint8_t type, const void *data, uint32_t len);
|
||||
// void sc64_debug_fsd_read (const void *data, uint32_t sector, uint32_t count);
|
||||
// void sc64_debug_fsd_write (const void *data, uint32_t sector, uint32_t count);
|
||||
// void sc64_init_is_viewer (void);
|
||||
void sc64_uart_print_string (const char *text);
|
||||
sc64_storage_error_t sc64_storage_read(sc64_storage_type_t storage_type, const void *buff, uint32_t sector, uint32_t count);
|
||||
void sc64_init (void);
|
||||
|
||||
|
||||
|
@ -16,7 +16,6 @@ header_crc:
|
||||
|
||||
.org 0x20, 0x00
|
||||
header_text_info:
|
||||
.global header_text_info
|
||||
.ascii "n64boot SummerCart64"
|
||||
.org 0x40, 0x00
|
||||
|
||||
|
@ -1,43 +1,42 @@
|
||||
#include <assert.h>
|
||||
#include "error.h"
|
||||
#include "sc64.h"
|
||||
#include "init.h"
|
||||
#include "storage.h"
|
||||
#include "fatfs/ff.h"
|
||||
|
||||
|
||||
static const char *fatfs_error_codes[] = {
|
||||
"Succeeded [0]",
|
||||
"A hard error occurred in the low level disk I/O layer [1]",
|
||||
"Assertion failed [2]",
|
||||
"The physical drive cannot work [3]",
|
||||
"Could not find the file [4]",
|
||||
"Could not find the path [5]",
|
||||
"The path name format is invalid [6]",
|
||||
"Access denied due to prohibited access or directory full [7]",
|
||||
"Access denied due to prohibited access [8]",
|
||||
"The file/directory object is invalid [9]",
|
||||
"The physical drive is write protected [10]",
|
||||
"The logical drive number is invalid [11]",
|
||||
"The volume has no work area [12]",
|
||||
"There is no valid FAT volume [13]",
|
||||
"The f_mkfs() aborted due to any problem [14]",
|
||||
"Could not get a grant to access the volume within defined period [15]",
|
||||
"The operation is rejected according to the file sharing policy [16]",
|
||||
"LFN working buffer could not be allocated [17]",
|
||||
"Number of open files > FF_FS_LOCK [18]",
|
||||
"Given parameter is invalid [19]",
|
||||
"Succeeded",
|
||||
"A hard error occurred in the low level disk I/O layer",
|
||||
"Assertion failed",
|
||||
"The physical drive cannot work",
|
||||
"Could not find the file",
|
||||
"Could not find the path",
|
||||
"The path name format is invalid",
|
||||
"Access denied due to prohibited access or directory full",
|
||||
"Access denied due to prohibited access",
|
||||
"The file/directory object is invalid",
|
||||
"The physical drive is write protected",
|
||||
"The logical drive number is invalid",
|
||||
"The volume has no work area",
|
||||
"There is no valid FAT volume",
|
||||
"The f_mkfs() aborted due to any problem",
|
||||
"Could not get a grant to access the volume within defined period",
|
||||
"The operation is rejected according to the file sharing policy",
|
||||
"LFN working buffer could not be allocated",
|
||||
"Number of open files > FF_FS_LOCK",
|
||||
"Given parameter is invalid",
|
||||
};
|
||||
|
||||
|
||||
#define FF_CHECK(x, message) { \
|
||||
FRESULT fatfs_result = x; \
|
||||
if (fatfs_result != FR_OK) { \
|
||||
error_display("%s:\n %s", message, fatfs_error_codes[fatfs_result]); \
|
||||
error_display("%s:\n %s\n", message, fatfs_error_codes[fatfs_result]); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
void storage_run_menu (storage_backend_t storage_backend, boot_info_t *boot_info, sc64_info_t *sc64_info) {
|
||||
void storage_run_menu (storage_backend_t storage_backend) {
|
||||
FATFS fs;
|
||||
FIL fil;
|
||||
|
||||
@ -48,7 +47,7 @@ void storage_run_menu (storage_backend_t storage_backend, boot_info_t *boot_info
|
||||
FF_CHECK(f_mount(&fs, "1:", 1), "Couldn't mount USB drive");
|
||||
FF_CHECK(f_chdrive("1:"), "Couldn't chdrive to USB drive");
|
||||
} else {
|
||||
error_display("Unknown storage backend [%d]", storage_backend);
|
||||
error_display("Unknown storage backend [%d]\n", storage_backend);
|
||||
}
|
||||
|
||||
FF_CHECK(f_open(&fil, "sc64menu.elf", FA_READ), "Couldn't open menu file");
|
||||
@ -57,8 +56,7 @@ void storage_run_menu (storage_backend_t storage_backend, boot_info_t *boot_info
|
||||
|
||||
FF_CHECK(f_close(&fil), "Couldn't close menu file");
|
||||
|
||||
// TODO: Execute ELF here
|
||||
// menu(&boot_info, &sc64_info);
|
||||
deinit();
|
||||
|
||||
boot_info->device_type = BOOT_DEVICE_TYPE_ROM;
|
||||
// menu();
|
||||
}
|
||||
|
@ -2,17 +2,13 @@
|
||||
#define STORAGE_H__
|
||||
|
||||
|
||||
#include "boot.h"
|
||||
#include "sc64.h"
|
||||
|
||||
|
||||
typedef enum {
|
||||
STORAGE_BACKEND_SD = 0,
|
||||
STORAGE_BACKEND_USB = 1,
|
||||
} storage_backend_t;
|
||||
|
||||
|
||||
void storage_run_menu (storage_backend_t storage_backend, boot_info_t *boot_info, sc64_info_t *sc64_info);
|
||||
void storage_run_menu (storage_backend_t storage_backend);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include "exception.h"
|
||||
|
||||
|
||||
extern char _sheap __attribute__((section(".data")));
|
||||
@ -21,9 +20,3 @@ caddr_t _sbrk_r (struct _reent *prt, ptrdiff_t incr) {
|
||||
|
||||
return (caddr_t) prev_heap_end;
|
||||
}
|
||||
|
||||
|
||||
void __assert_func (const char *file, int line, const char *func, const char *failedexpr) {
|
||||
EXCEPTION_TRIGGER(TRIGGER_CODE_ASSERT);
|
||||
while (1);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
#ifndef REGS_H__
|
||||
#define REGS_H__
|
||||
#ifndef VR4300_H__
|
||||
#define VR4300_H__
|
||||
|
||||
|
||||
#define HIT_INVALIDATE_I ((4 << 2) | 0)
|
@ -840,6 +840,7 @@ if __name__ == "__main__":
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
finally:
|
||||
if (sc64):
|
||||
sc64.reset_link()
|
||||
if (disk_file):
|
||||
print(f"Setting 64DD disk state to [Ejected]")
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "isv.h"
|
||||
#include "joybus.h"
|
||||
#include "usb.h"
|
||||
#include "uart.h"
|
||||
|
||||
|
||||
#define SAVE_SIZE_EEPROM_4K (512)
|
||||
@ -303,6 +304,10 @@ void process_cfg (void) {
|
||||
usb_debug_reset();
|
||||
break;
|
||||
|
||||
case 'Z':
|
||||
uart_put((char) (args[0] & 0xFF));
|
||||
break;
|
||||
|
||||
default:
|
||||
change_scr_bits(CFG_SCR_CMD_ERROR, true);
|
||||
break;
|
||||
|
@ -8,11 +8,17 @@ static const char hex_char_map[16] = {
|
||||
};
|
||||
#endif
|
||||
|
||||
void uart_put (char c) {
|
||||
#ifdef DEBUG
|
||||
while (!(UART->SCR & UART_SCR_TXE));
|
||||
UART->DR = c;
|
||||
#endif
|
||||
}
|
||||
|
||||
void uart_print (const char *text) {
|
||||
#ifdef DEBUG
|
||||
while (*text != '\0') {
|
||||
while (!(UART->SCR & UART_SCR_TXE));
|
||||
UART->DR = *text++;
|
||||
uart_put(*text++);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "sys.h"
|
||||
|
||||
|
||||
void uart_put (char c);
|
||||
void uart_print (const char *text);
|
||||
void uart_print_02hex (uint8_t number);
|
||||
void uart_print_08hex (uint32_t number);
|
||||
|
Loading…
Reference in New Issue
Block a user