From 5ff1662e611095fd62c3ea580d88e9469a505f06 Mon Sep 17 00:00:00 2001 From: Lephe Date: Sun, 31 May 2020 15:52:00 +0200 Subject: [PATCH] bfile: solve stability issues on fx9860g and fxcg50 This commit improves the stability of gint_switch() in two ways: 1. Wait for hardware availability every time driver contexts are saved or reloaded; this solves crashes due to DMA use when gint takes control after a BFile call, since BFile_Create() (and possibly BFile_Write()) leave the DMA running after returning. 2. Remap the add-in after a switch, as apparently calling BFile functions causes some pages to be evicted. This is more noticeable on fxcg50 when the size of add-ins nears 220k. Additionally, dma_transfer_wait() has been updated to not sleep() unless it is certain that the conditions for wakeup are fulfilled, as this would sometimes freeze. --- TODO | 3 ++- src/core/setup.c | 26 ++++++++++++++++++++++---- src/core/start.c | 3 +++ src/core/syscalls.S | 3 +++ src/dma/dma.c | 13 +++++++------ 5 files changed, 37 insertions(+), 11 deletions(-) diff --git a/TODO b/TODO index a382c3e..ac8b04e 100644 --- a/TODO +++ b/TODO @@ -7,7 +7,7 @@ For the 2.0.0 release: Crucial, missing things. ! core: the four basic memory functions (with automated tests) ! core: use gint_switch() to handle TLB misses -! bfile: solve stability issues +! core: recheck SH3 compatibility Issues. * #3 make drawing functions parameterized @@ -16,6 +16,7 @@ Issues. * #10 support fx-CG 20 Complementary elements on existing code. +* gray: add gprint() * gray: double-buffer gray settings and unify d* with g* * display: deprecate image_t and rename it bopti_image_t * topti: support unicode fonts diff --git a/src/core/setup.c b/src/core/setup.c index b46b5f0..052fefe 100644 --- a/src/core/setup.c +++ b/src/core/setup.c @@ -162,18 +162,18 @@ static void gint_switch_out(void) gint_ctx_save(&gint_ctx); /* Restore the system context */ - for(gint_driver_t *drv = &edrv; (--drv) >= &bdrv;) + gint_ctx_restore(&sys_ctx); + for(gint_driver_t *drv = &bdrv; drv < &edrv; drv++) { if(!drv->ctx_save || !drv->ctx_restore) continue; drv->ctx_restore(drv->sys_ctx); } - gint_ctx_restore(&sys_ctx); } static void gint_switch_in(void) { /* Save system state again */ - for(gint_driver_t *drv = &bdrv; drv < &edrv; drv++) + for(gint_driver_t *drv = &edrv; (--drv) >= &bdrv;) { if(!drv->ctx_save || !drv->ctx_restore) continue; drv->ctx_save(drv->sys_ctx); @@ -181,12 +181,12 @@ static void gint_switch_in(void) gint_ctx_save(&sys_ctx); /* Restore all drivers to their gint state */ + gint_ctx_restore(&gint_ctx); for(gint_driver_t *drv = &bdrv; drv < &edrv; drv++) { if(!drv->ctx_save || !drv->ctx_restore) continue; drv->ctx_restore(drv->gint_ctx); } - gint_ctx_restore(&gint_ctx); } /* gint_switch() - temporarily switch out of gint */ @@ -200,6 +200,24 @@ void gint_switch(void (*function)(void)) gint_setvbr(system_vbr, gint_switch_out); if(function) function(); + + /* Remap all of the ROM */ + extern uint32_t brom, srom; + volatile void *b = &brom; + int32_t s = (int32_t)&srom; + GUNUSED uint8_t x; + while(s > 0) + { + x = *(volatile uint8_t *)b; + b += 1024; + s -= 1024; + } + + /* Wait for the OS to finish working */ + for(gint_driver_t *drv = &edrv; (--drv) >= &bdrv;) + { + if(drv->wait) drv->wait(); + } gint_setvbr((uint32_t)&gint_vbr, gint_switch_in); } diff --git a/src/core/start.c b/src/core/start.c index 09b330a..2936d45 100644 --- a/src/core/start.c +++ b/src/core/start.c @@ -156,6 +156,9 @@ int start(int isappli, int optnum) /* Initialize all drivers by saving the system settings */ for(drv = &bdrv; drv < &edrv; drv++) { + /* Wait for hardware availability */ + if(drv->wait) drv->wait(); + /* Hook for old SH3 fx9860g machines */ if(isSH3() && drv->driver_sh3) drv->driver_sh3(); diff --git a/src/core/syscalls.S b/src/core/syscalls.S index 5db34e6..fefc997 100644 --- a/src/core/syscalls.S +++ b/src/core/syscalls.S @@ -45,6 +45,7 @@ mov.l 1f, r0 ;\ jmp @r2 ;\ nop ;\ +.align 4 ;\ 1: .long id #ifdef FX9860G @@ -123,10 +124,12 @@ _realloc: /* BFile driver */ _BFile_Remove: + mov #0, r5 syscall(0x1db4) _BFile_Create: syscall(0x1dae) _BFile_Open: + mov #0, r6 syscall(0x1da3) _BFile_Close: syscall(0x1da4) diff --git a/src/dma/dma.c b/src/dma/dma.c index 263e53e..e4a480f 100644 --- a/src/dma/dma.c +++ b/src/dma/dma.c @@ -138,9 +138,10 @@ void dma_transfer_wait(int channel) if(ch->SAR >= 0xe5007000 && ch->SAR < 0xe5204000) onchip = 1; if(ch->DAR >= 0xe5007000 && ch->DAR < 0xe5204000) onchip = 1; - while(ch->CHCR.DE) + while(ch->CHCR.DE && !ch->CHCR.TE) { - if(!onchip) sleep(); + /* Sleep only if the interrupt is enabled to wake us up */ + if(!onchip && ch->CHCR.IE) sleep(); } } @@ -228,8 +229,8 @@ static void wait(void) typedef struct { channel_t ch[6]; - uint16_t OR; int clock; + uint16_t OR; } GPACKED(4) ctx_t; @@ -257,8 +258,6 @@ static void ctx_save(void *buf) static void ctx_restore(void *buf) { - dma_transfer_wait(-1); - ctx_t *ctx = buf; /* Restore the supply status of the DMA0 clock first. If the DMA was @@ -267,6 +266,9 @@ static void ctx_restore(void *buf) power it up again for the writes to registers to have any effect */ POWER.MSTPCR0.DMAC0 = ctx->clock; + /* Disable the DMA while editing */ + DMA.OR.DME = 0; + for(int i = 0; i < 6; i++) { channel_t *ch = dma_channel(i); @@ -275,7 +277,6 @@ static void ctx_restore(void *buf) ch->TCR = ctx->ch[i].TCR; ch->CHCR.lword = ctx->ch[i].CHCR.lword; } - DMA.OR.word = ctx->OR; }