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:
Lephe 2023-01-25 16:26:04 +01:00
parent 42853103aa
commit db50c9b192
No known key found for this signature in database
GPG key ID: 1BBA026E13FC0495
7 changed files with 104 additions and 19 deletions

3
TODO
View file

@ -12,11 +12,10 @@ Extensions on existing code:
* kernel: better restore to userspace before panic (ensure BL=0 IMASK=0)
* project: add license 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
* core: review forgotten globals and MPU addresses not in <gint/mpu/*.h>
* 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:
* Audio playback using TSWilliamson's libsnd method

View file

@ -2,16 +2,43 @@
#include <gint/display.h>
#include <gint/clock.h>
#include <gint/mpu/dma.h>
#include <gint/drivers/keydev.h>
#include <gint/defs/attributes.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 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 */
GNORETURN static void gint_default_panic(GUNUSED uint32_t code)
{
uint32_t TEA, TRA;
keydev_t *kd = _WEAK_keydev_std();
if(isSH3())
{
@ -31,9 +58,9 @@ GNORETURN static void gint_default_panic(GUNUSED uint32_t code)
if(isSH4()) __asm__("stc sgr, %0" : "=r"(SGR));
dfont(NULL);
dclear(C_WHITE);
#ifdef FX9860G
memset(gint_vram, 0, 1024);
dtext(1, 0, "Exception! (SysERROR)");
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);
else dprint(1, 9, "%03x", code);
dprint(1, 17, " PC :%08x", PC);
dprint(1, 25, "TEA :%08x", TEA);
dprint(1, 33, "TRA :%08x", TRA);
if(isSH4()) dprint(1, 41, "SGR :%08x", SGR);
dprint(1, 17, " PC:%08x TRA:%d", PC, TRA);
dprint(1, 25, "TEA:%08x", TEA);
dtext(1, 49, "The add-in crashed.");
dtext(1, 57, "Please reset the calc");
dtext(1, 33, "The add-in crashed.");
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
#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)");
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);
dtext(281, 75, "(Trap number)");
dtext(6, 95, "An unrecoverable error occurred in the add-in.");
dtext(6, 108, "Please press the RESET button to restart the");
dtext(6, 121, "calculator.");
dtext(6, 95, "The add-in crashed!");
if(kd == NULL) {
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 */
if(code == 0x1020)
{
#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);
dprint(6, 154, "CHCR0: %08x", DMA.DMA0.CHCR);
dprint(6, 167, "SAR1: %08x DAR1: %08x TCR1: %08x",
dprint(6, 180, "CHCR0: %08x", DMA.DMA0.CHCR);
dprint(6, 193, "SAR1: %08x DAR1: %08x TCR1: %08x",
DMA.DMA1.SAR, DMA.DMA1.DAR, DMA.DMA1.TCR);
dprint(6, 180, "CHCR1: %08x", DMA.DMA1.CHCR);
dprint(6, 193, "DMAOR: %04x", DMA.OR);
dprint(6, 206, "CHCR1: %08x DMAOR:%04x", DMA.DMA1.CHCR, DMA.OR);
#undef DMA
}
/* Illegal instruction handler */
@ -125,8 +165,31 @@ GNORETURN static void gint_default_panic(GUNUSED uint32_t code)
}
#endif
dupdate();
while(1) sleep();
_WEAK_dupdate();
/* 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 */

View file

@ -44,6 +44,9 @@
.global ___ConfigureStatusArea
.global ___SetQuitHandler
/* Reset */
.global ___Reset
#define syscall_(id, syscall_table) \
mov.l syscall_table, r2 ;\
mov.l 1f, r0 ;\
@ -115,6 +118,11 @@ ___GetVRAMAddress:
___SetQuitHandler:
syscall(0x494)
/* Reset */
___Reset:
syscall(0x236)
syscall_table:
.long 0x80010070
@ -188,6 +196,11 @@ ___SetQuitHandler:
___SpecialMatrixCodeProcessing:
syscall(0x1e60)
/* Reset */
___Reset:
syscall(0x1187)
syscall_table:
.long 0x80020070

View file

@ -205,6 +205,8 @@ key_event_t keydev_unqueue_event(keydev_t *d)
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 */
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;
}
__attribute__((alias("keydev_keydown")))
bool _WEAK_keydev_keydown(keydev_t *d, int key);
//---
// Event transforms

View file

@ -33,6 +33,8 @@ keydev_t *keydev_std(void)
{
return &keysc_dev;
}
__attribute__((alias("keydev_std")))
keydev_t *_WEAK_keydev_std(void);
/* keysc_scan(): Scand the keyboard */
static void keysc_scan(uint8_t *scan)

View file

@ -18,3 +18,5 @@ void dupdate(void)
/* Switch buffers if triple buffering is enabled */
dvram_switch();
}
__attribute__((alias("dupdate")))
void _WEAK_dupdate(void);

View file

@ -31,3 +31,5 @@ void dupdate(void)
gint_call_t hook = dupdate_get_hook();
if(hook.function) gint_call(hook);
}
__attribute__((alias("dupdate")))
void _WEAK_dupdate(void);