gint/src/core/bootlog.c

196 lines
3.8 KiB
C
Raw Normal View History

//---
// gint:core:bootlog - Boot-time on-screen log for extreme debugging
//---
#include <gint/defs/types.h>
#include <gint/std/string.h>
#include <gint/std/stdio.h>
#include <core/mmu.h>
#include <gint/hardware.h>
#include <gint/mpu/intc.h>
#include <gint/gint.h>
#include <gint/display.h>
#include <gint/clock.h>
#ifdef GINT_BOOT_LOG
#ifdef FXCG50
void Bdisp_AllClr_VRAM(void);
void Bdisp_PutDisp_DD(void);
void PrintXY(int x, int y, const char *str, int fg, int bg);
#define dclear(c) Bdisp_AllClr_VRAM()
#define dupdate() Bdisp_PutDisp_DD()
#endif
/* A copy of the bootlog */
2019-07-04 18:13:31 +02:00
GDATA char gint_bootlog[22*8] = { 0 };
/* Linker script symbols - see core/start.c for details */
extern char
brom, srom,
sgdata, sgbss, sdata, sbss,
btors, mtors, etors;
/* print() - formatted printing shorthand */
static void print(int x, int y, const char *format, ...)
{
char str[45];
va_list args;
va_start(args, format);
2019-07-17 00:34:10 +02:00
vsnprintf(str + 2, 43, format, args);
#ifdef FX9860G
2019-07-04 18:14:31 +02:00
dtext(6 * (x-1) + 1, 8 * (y-1), str + 2, C_BLACK, C_WHITE);
#endif
#ifdef FXCG50
PrintXY(x, y, str, 0, 0);
#endif
2019-07-04 18:13:31 +02:00
memcpy(gint_bootlog + 22 * (y-1) + (x-1), str + 2, strlen(str + 2));
va_end(args);
}
/* bootlog_loaded() - section loading stage */
GSECTION(".pretext")
void bootlog_loaded(void)
{
2019-07-04 18:13:31 +02:00
memset(gint_bootlog, 0x20, 22*8);
for(int i = 0; i < 8; i++) gint_bootlog[22 * i + 21] = 0;
/* Size of memory sections */
uint32_t rom_size = (uint32_t)&srom;
uint32_t ram_size = (uint32_t)&sdata + (uint32_t)&sbss;
uint32_t gint_size = (uint32_t)&sgdata + (uint32_t)&sgbss;
/* MPU type */
int mpu = gint[HWMPU];
const char *names = "SH7337\0 SH7305\0 SH7355\0 SH7724";
/* TODO: Use a solid API for boot-time printing */
2019-07-04 18:14:31 +02:00
dclear(C_WHITE);
print(1, 1, "gint @%7x SLmkd", GINT_VERSION);
if(mpu >= 1 && mpu <= 4) print(1, 2, names + 8 * (mpu - 1));
else print(1, 2, "%6d", mpu);
#ifdef FX9860G
print(8, 2, "%c?-", gint[HWRAM] >= (512 << 10) ? 'R' : 'r');
#endif
#ifdef FXCG50
print(8, 2, "---");
#endif
core, tmu: add gint_switch(), return to menu, and improve timer code * Add the gint_switch() function which executes user-provided code from the system (CASIOWIN) context. * Added interrupt masks to the core context (should have been there long ago). * Added the gint_osmenu() function that switches out of gint to invoke GetKeyWait() and inject KEY_CTRL_MENU to trigger the main menu. This uses many CASIOWIN syscalls, but we don't care because gint is unloaded. Trickery is used to catch the key following the return in the add-in and/or display a new application frame before GetKeyWait() even finishes after coming back. This is only available on fx9860g for now. * Removed any public syscall definition to clear up interfaces. * Patched the DMA interruption problem in a weird way on fxcg50, a driver function will be used to do that properly eventually. * Changed the driver model to save driver contexts in preallocated spaces instead of on the stack for overall less risk. * Enabled return-to-menu with the MENU key on fx9860g in getkey(). * Changed the keyboard driver to emit releases before presses, as a return-to-menu acts as a press+release of different keys in a single driver frame, which confuses getkey(). * Fixed a really stupid bug in memcpy() that made the function really not work. Improvements in the timer driver: * Expose ETMU modules as SH7705_TMU and SH7305_TMU in <gint/mpu/tmu.h>. * Remove the timer_t structures, using SH*_ETMU and SH*_TMU instead. Only interrupt gate entries are left hardcoded. * Discovered that not only every write to the TCNT or TCR of an ETMU takes about 1/32k of a second (hinting at registers being powered by the same clock as the timer), but every write occuring while a previous write is pending is *lost*. This led to terrible bugs when switching ETMU contexts too fast in gint_switch(). * Removed an internal timer_address() function. * Overall simplified the handling of timers and the initialization step.
2020-05-10 14:03:41 +02:00
#ifdef FX9860G
char const *osversion = (void *)0x80010020;
char os[11] = { 0 };
for(int i = 0; i < 10; i++) os[i] = osversion[i];
print(12, 2, "OS%2s%2s%4s", os, os+3, os+6);
core, tmu: add gint_switch(), return to menu, and improve timer code * Add the gint_switch() function which executes user-provided code from the system (CASIOWIN) context. * Added interrupt masks to the core context (should have been there long ago). * Added the gint_osmenu() function that switches out of gint to invoke GetKeyWait() and inject KEY_CTRL_MENU to trigger the main menu. This uses many CASIOWIN syscalls, but we don't care because gint is unloaded. Trickery is used to catch the key following the return in the add-in and/or display a new application frame before GetKeyWait() even finishes after coming back. This is only available on fx9860g for now. * Removed any public syscall definition to clear up interfaces. * Patched the DMA interruption problem in a weird way on fxcg50, a driver function will be used to do that properly eventually. * Changed the driver model to save driver contexts in preallocated spaces instead of on the stack for overall less risk. * Enabled return-to-menu with the MENU key on fx9860g in getkey(). * Changed the keyboard driver to emit releases before presses, as a return-to-menu acts as a press+release of different keys in a single driver frame, which confuses getkey(). * Fixed a really stupid bug in memcpy() that made the function really not work. Improvements in the timer driver: * Expose ETMU modules as SH7705_TMU and SH7305_TMU in <gint/mpu/tmu.h>. * Remove the timer_t structures, using SH*_ETMU and SH*_TMU instead. Only interrupt gate entries are left hardcoded. * Discovered that not only every write to the TCNT or TCR of an ETMU takes about 1/32k of a second (hinting at registers being powered by the same clock as the timer), but every write occuring while a previous write is pending is *lost*. This led to terrible bugs when switching ETMU contexts too fast in gint_switch(). * Removed an internal timer_address() function. * Overall simplified the handling of timers and the initialization step.
2020-05-10 14:03:41 +02:00
#endif
print(1, 3, "ROM%4dk RAM%3d+%1dk ??",
(rom_size + 0x3ff) >> 10,
(ram_size + 0x3ff) >> 10,
(gint_size + 0x3ff) >> 10);
dupdate();
}
/* bootlog_mapped() - ROM mapping stage */
GSECTION(".pretext")
void bootlog_mapped(int rom, GUNUSED int ram)
{
/* Check whether all ROM is mapped */
uint32_t rom_size = (uint32_t)&srom;
print(20, 3, "%c%c", (rom >= (int)rom_size) ? 'F' : 'f',
isSH3() ? 'u' : 'U');
print(19, 1, "M");
#ifdef FX9860G
print(9, 2, (ram > 8192) ? "E" : "e");
#endif
dupdate();
}
/* bootlog_kernel() - gint loading stage */
void bootlog_kernel(void)
{
print(20, 1, "K");
2019-05-03 17:12:22 +02:00
dupdate();
}
/* bootlog_driver() - driver load
Called for very loaded driver. */
void bootlog_driver(const char *drv, const char *status)
{
/* Positioning for the driver name */
static int x = 1, y = 4;
if(y > 5)
{
print(21, 4, "+");
return;
}
print(x, y, "%3s", drv);
x += 4;
if(x + y >= 22) x=1, y++;
/* Positioning for the driver message */
if(!status) return;
int len = strlen(status);
static int mx = 1, my = 6;
if(mx + len > 22) mx = 1, my++;
if(my > 8) return;
print(mx, my, "%s", status);
mx += len + 1;
dupdate();
}
/* bootlog_driver_summary() - all drivers loaded */
void bootlog_driver_summary(void)
{
int interrupts = 0;
uint16_t ipr;
print(21, 1, "D");
/* Count number of enabled interrupts */
if(isSH3()) for(int i = 0; i < 8; i++)
{
ipr = *SH7705_INTC.IPRS[i];
while(ipr > 0)
{
interrupts += (ipr & 0xf) != 0;
ipr >>= 4;
}
}
else for(int i = 0; i < 12; i++)
{
ipr = SH7305_INTC.IPRS[2 * i];
while(ipr > 0)
{
interrupts += (ipr & 0xf) != 0;
ipr >>= 4;
}
}
print(19, 5, "#%2d", interrupts);
dupdate();
}
#endif /* GINT_BOOT_LOG */