mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2024-12-29 13:03:36 +01:00
kernel: more options in System ERROR screen
* Add options to RESET, go to menu, or abort() * Define weak symbols for driver functions so that low-level debugging add-ins can be linked with minimal drivers (CPU/INTC/MMU)
This commit is contained in:
parent
42853103aa
commit
db50c9b192
7 changed files with 104 additions and 19 deletions
3
TODO
3
TODO
|
@ -12,11 +12,10 @@ Extensions on existing code:
|
||||||
* kernel: better restore to userspace before panic (ensure BL=0 IMASK=0)
|
* kernel: better restore to userspace before panic (ensure BL=0 IMASK=0)
|
||||||
* project: add license file
|
* project: add license file
|
||||||
* kernel: group linker script symbols in a single header file
|
* kernel: group linker script symbols in a single header file
|
||||||
* core: try to leave add-in without reset in case of panic
|
|
||||||
* core: use cmp/str for memchr()
|
|
||||||
* r61524: brightness control and clean the file
|
* r61524: brightness control and clean the file
|
||||||
* core: review forgotten globals and MPU addresses not in <gint/mpu/*.h>
|
* core: review forgotten globals and MPU addresses not in <gint/mpu/*.h>
|
||||||
* core: run destructors when a task-switch results in leaving the app
|
* core: run destructors when a task-switch results in leaving the app
|
||||||
|
* fs: support read-only files backed with GetBlockAddress() on fx-CG
|
||||||
|
|
||||||
Future directions:
|
Future directions:
|
||||||
* Audio playback using TSWilliamson's libsnd method
|
* Audio playback using TSWilliamson's libsnd method
|
||||||
|
|
|
@ -2,16 +2,43 @@
|
||||||
#include <gint/display.h>
|
#include <gint/display.h>
|
||||||
#include <gint/clock.h>
|
#include <gint/clock.h>
|
||||||
#include <gint/mpu/dma.h>
|
#include <gint/mpu/dma.h>
|
||||||
|
#include <gint/drivers/keydev.h>
|
||||||
#include <gint/defs/attributes.h>
|
#include <gint/defs/attributes.h>
|
||||||
#include <gint/hardware.h>
|
#include <gint/hardware.h>
|
||||||
|
#include <gint/gint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
void __Reset(void);
|
||||||
|
|
||||||
#define dprint(x, y, ...) dprint(x, y, C_BLACK, __VA_ARGS__)
|
#define dprint(x, y, ...) dprint(x, y, C_BLACK, __VA_ARGS__)
|
||||||
#define dtext(x, y, str) dtext (x, y, C_BLACK, str)
|
#define dtext(x, y, str) dtext (x, y, C_BLACK, str)
|
||||||
|
|
||||||
|
/* Weak implementation of driver functions, which are used if the keyboard and
|
||||||
|
display drivers are not linked in. This allows add-ins to not link in these
|
||||||
|
drivers (which is useful for low-level debugging). */
|
||||||
|
GWEAK void _WEAK_dupdate(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GWEAK keydev_t *_WEAK_keydev_std(void)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
GWEAK bool _WEAK_keydev_keydown(GUNUSED keydev_t *d, GUNUSED int key)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
GWEAK key_event_t _WEAK_keydev_unqueue_event(GUNUSED keydev_t *d)
|
||||||
|
{
|
||||||
|
return (key_event_t){ .type = KEYEV_NONE };
|
||||||
|
}
|
||||||
|
|
||||||
/* gint_panic_default(): Default panic handler */
|
/* gint_panic_default(): Default panic handler */
|
||||||
GNORETURN static void gint_default_panic(GUNUSED uint32_t code)
|
GNORETURN static void gint_default_panic(GUNUSED uint32_t code)
|
||||||
{
|
{
|
||||||
uint32_t TEA, TRA;
|
uint32_t TEA, TRA;
|
||||||
|
keydev_t *kd = _WEAK_keydev_std();
|
||||||
|
|
||||||
if(isSH3())
|
if(isSH3())
|
||||||
{
|
{
|
||||||
|
@ -31,9 +58,9 @@ GNORETURN static void gint_default_panic(GUNUSED uint32_t code)
|
||||||
if(isSH4()) __asm__("stc sgr, %0" : "=r"(SGR));
|
if(isSH4()) __asm__("stc sgr, %0" : "=r"(SGR));
|
||||||
|
|
||||||
dfont(NULL);
|
dfont(NULL);
|
||||||
dclear(C_WHITE);
|
|
||||||
|
|
||||||
#ifdef FX9860G
|
#ifdef FX9860G
|
||||||
|
memset(gint_vram, 0, 1024);
|
||||||
dtext(1, 0, "Exception! (SysERROR)");
|
dtext(1, 0, "Exception! (SysERROR)");
|
||||||
for(int i = 0; i < 32; i++) gint_vram[i] = ~gint_vram[i];
|
for(int i = 0; i < 32; i++) gint_vram[i] = ~gint_vram[i];
|
||||||
|
|
||||||
|
@ -55,16 +82,23 @@ GNORETURN static void gint_default_panic(GUNUSED uint32_t code)
|
||||||
if(name[0]) dtext(1, 9, name);
|
if(name[0]) dtext(1, 9, name);
|
||||||
else dprint(1, 9, "%03x", code);
|
else dprint(1, 9, "%03x", code);
|
||||||
|
|
||||||
dprint(1, 17, " PC :%08x", PC);
|
dprint(1, 17, " PC:%08x TRA:%d", PC, TRA);
|
||||||
dprint(1, 25, "TEA :%08x", TEA);
|
dprint(1, 25, "TEA:%08x", TEA);
|
||||||
dprint(1, 33, "TRA :%08x", TRA);
|
|
||||||
if(isSH4()) dprint(1, 41, "SGR :%08x", SGR);
|
|
||||||
|
|
||||||
dtext(1, 49, "The add-in crashed.");
|
dtext(1, 33, "The add-in crashed.");
|
||||||
dtext(1, 57, "Please reset the calc");
|
if(kd == NULL) {
|
||||||
|
dtext(1, 41, "Please reset the calc");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dtext(1, 41, "[EXIT]:Quit add-in");
|
||||||
|
dtext(1, 49, "[MENU]:Main menu");
|
||||||
|
dtext(1, 57, "[F1]+[F6]: RESET calc");
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef FXCG50
|
#ifdef FXCG50
|
||||||
|
/* Don't require the DMA driver just for a clear */
|
||||||
|
memset(gint_vram, 0xff, DWIDTH*DHEIGHT*2);
|
||||||
dtext(6, 3, "An exception occured! (System ERROR)");
|
dtext(6, 3, "An exception occured! (System ERROR)");
|
||||||
|
|
||||||
uint32_t *long_vram = (void *)gint_vram;
|
uint32_t *long_vram = (void *)gint_vram;
|
||||||
|
@ -99,21 +133,27 @@ GNORETURN static void gint_default_panic(GUNUSED uint32_t code)
|
||||||
dprint(38, 75, "= %#x", TRA);
|
dprint(38, 75, "= %#x", TRA);
|
||||||
dtext(281, 75, "(Trap number)");
|
dtext(281, 75, "(Trap number)");
|
||||||
|
|
||||||
dtext(6, 95, "An unrecoverable error occurred in the add-in.");
|
dtext(6, 95, "The add-in crashed!");
|
||||||
dtext(6, 108, "Please press the RESET button to restart the");
|
if(kd == NULL) {
|
||||||
dtext(6, 121, "calculator.");
|
dtext(6, 108, "Please press the RESET button to restart the");
|
||||||
|
dtext(6, 121, "calculator.");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dtext(6, 121, "[EXIT]: Exit the program with abort()");
|
||||||
|
dtext(6, 134, "[MENU]: Leave to main menu");
|
||||||
|
dtext(6, 147, "[F1]+[F6]: RESET the calculator");
|
||||||
|
}
|
||||||
|
|
||||||
/* DMA address error handler */
|
/* DMA address error handler */
|
||||||
if(code == 0x1020)
|
if(code == 0x1020)
|
||||||
{
|
{
|
||||||
#define DMA SH7305_DMA
|
#define DMA SH7305_DMA
|
||||||
dprint(6, 141, "SAR0: %08x DAR0: %08x TCR0: %08x",
|
dprint(6, 167, "SAR0: %08x DAR0: %08x TCR0: %08x",
|
||||||
DMA.DMA0.SAR, DMA.DMA0.DAR, DMA.DMA0.TCR);
|
DMA.DMA0.SAR, DMA.DMA0.DAR, DMA.DMA0.TCR);
|
||||||
dprint(6, 154, "CHCR0: %08x", DMA.DMA0.CHCR);
|
dprint(6, 180, "CHCR0: %08x", DMA.DMA0.CHCR);
|
||||||
dprint(6, 167, "SAR1: %08x DAR1: %08x TCR1: %08x",
|
dprint(6, 193, "SAR1: %08x DAR1: %08x TCR1: %08x",
|
||||||
DMA.DMA1.SAR, DMA.DMA1.DAR, DMA.DMA1.TCR);
|
DMA.DMA1.SAR, DMA.DMA1.DAR, DMA.DMA1.TCR);
|
||||||
dprint(6, 180, "CHCR1: %08x", DMA.DMA1.CHCR);
|
dprint(6, 206, "CHCR1: %08x DMAOR:%04x", DMA.DMA1.CHCR, DMA.OR);
|
||||||
dprint(6, 193, "DMAOR: %04x", DMA.OR);
|
|
||||||
#undef DMA
|
#undef DMA
|
||||||
}
|
}
|
||||||
/* Illegal instruction handler */
|
/* Illegal instruction handler */
|
||||||
|
@ -125,8 +165,31 @@ GNORETURN static void gint_default_panic(GUNUSED uint32_t code)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
dupdate();
|
_WEAK_dupdate();
|
||||||
while(1) sleep();
|
|
||||||
|
/* Make sure relevant keys are released before taking in events; we don't
|
||||||
|
want the user to RESET through this screen by holding a key */
|
||||||
|
bool has_released = false;
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
while(_WEAK_keydev_unqueue_event(kd).type != KEYEV_NONE) {}
|
||||||
|
|
||||||
|
bool exit = _WEAK_keydev_keydown(kd, KEY_EXIT);
|
||||||
|
bool menu = _WEAK_keydev_keydown(kd, KEY_MENU);
|
||||||
|
bool f1 = _WEAK_keydev_keydown(kd, KEY_F1);
|
||||||
|
bool f6 = _WEAK_keydev_keydown(kd, KEY_F6);
|
||||||
|
|
||||||
|
if(has_released && exit)
|
||||||
|
abort();
|
||||||
|
if(has_released && menu)
|
||||||
|
gint_osmenu();
|
||||||
|
if(has_released && f1 && f6)
|
||||||
|
__Reset();
|
||||||
|
if(!exit && !menu && !f1 && !f6)
|
||||||
|
has_released = true;
|
||||||
|
|
||||||
|
sleep();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Panic handler */
|
/* Panic handler */
|
||||||
|
|
|
@ -44,6 +44,9 @@
|
||||||
.global ___ConfigureStatusArea
|
.global ___ConfigureStatusArea
|
||||||
.global ___SetQuitHandler
|
.global ___SetQuitHandler
|
||||||
|
|
||||||
|
/* Reset */
|
||||||
|
.global ___Reset
|
||||||
|
|
||||||
#define syscall_(id, syscall_table) \
|
#define syscall_(id, syscall_table) \
|
||||||
mov.l syscall_table, r2 ;\
|
mov.l syscall_table, r2 ;\
|
||||||
mov.l 1f, r0 ;\
|
mov.l 1f, r0 ;\
|
||||||
|
@ -115,6 +118,11 @@ ___GetVRAMAddress:
|
||||||
___SetQuitHandler:
|
___SetQuitHandler:
|
||||||
syscall(0x494)
|
syscall(0x494)
|
||||||
|
|
||||||
|
/* Reset */
|
||||||
|
|
||||||
|
___Reset:
|
||||||
|
syscall(0x236)
|
||||||
|
|
||||||
syscall_table:
|
syscall_table:
|
||||||
.long 0x80010070
|
.long 0x80010070
|
||||||
|
|
||||||
|
@ -188,6 +196,11 @@ ___SetQuitHandler:
|
||||||
___SpecialMatrixCodeProcessing:
|
___SpecialMatrixCodeProcessing:
|
||||||
syscall(0x1e60)
|
syscall(0x1e60)
|
||||||
|
|
||||||
|
/* Reset */
|
||||||
|
|
||||||
|
___Reset:
|
||||||
|
syscall(0x1187)
|
||||||
|
|
||||||
syscall_table:
|
syscall_table:
|
||||||
.long 0x80020070
|
.long 0x80020070
|
||||||
|
|
||||||
|
|
|
@ -205,6 +205,8 @@ key_event_t keydev_unqueue_event(keydev_t *d)
|
||||||
|
|
||||||
return ev;
|
return ev;
|
||||||
}
|
}
|
||||||
|
__attribute__((alias("keydev_unqueue_event")))
|
||||||
|
key_event_t _WEAK_keydev_unqueue_event(keydev_t *d);
|
||||||
|
|
||||||
/* keydev_keydown(): Check if a key is down according to generated events */
|
/* keydev_keydown(): Check if a key is down according to generated events */
|
||||||
bool keydev_keydown(keydev_t *d, int key)
|
bool keydev_keydown(keydev_t *d, int key)
|
||||||
|
@ -214,6 +216,8 @@ bool keydev_keydown(keydev_t *d, int key)
|
||||||
|
|
||||||
return (d->state_queue[row] & col) != 0;
|
return (d->state_queue[row] & col) != 0;
|
||||||
}
|
}
|
||||||
|
__attribute__((alias("keydev_keydown")))
|
||||||
|
bool _WEAK_keydev_keydown(keydev_t *d, int key);
|
||||||
|
|
||||||
//---
|
//---
|
||||||
// Event transforms
|
// Event transforms
|
||||||
|
|
|
@ -33,6 +33,8 @@ keydev_t *keydev_std(void)
|
||||||
{
|
{
|
||||||
return &keysc_dev;
|
return &keysc_dev;
|
||||||
}
|
}
|
||||||
|
__attribute__((alias("keydev_std")))
|
||||||
|
keydev_t *_WEAK_keydev_std(void);
|
||||||
|
|
||||||
/* keysc_scan(): Scand the keyboard */
|
/* keysc_scan(): Scand the keyboard */
|
||||||
static void keysc_scan(uint8_t *scan)
|
static void keysc_scan(uint8_t *scan)
|
||||||
|
|
|
@ -18,3 +18,5 @@ void dupdate(void)
|
||||||
/* Switch buffers if triple buffering is enabled */
|
/* Switch buffers if triple buffering is enabled */
|
||||||
dvram_switch();
|
dvram_switch();
|
||||||
}
|
}
|
||||||
|
__attribute__((alias("dupdate")))
|
||||||
|
void _WEAK_dupdate(void);
|
||||||
|
|
|
@ -31,3 +31,5 @@ void dupdate(void)
|
||||||
gint_call_t hook = dupdate_get_hook();
|
gint_call_t hook = dupdate_get_hook();
|
||||||
if(hook.function) gint_call(hook);
|
if(hook.function) gint_call(hook);
|
||||||
}
|
}
|
||||||
|
__attribute__((alias("dupdate")))
|
||||||
|
void _WEAK_dupdate(void);
|
||||||
|
|
Loading…
Reference in a new issue