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.
This commit is contained in:
Lephe 2020-05-31 15:52:00 +02:00
parent 14e59690a5
commit 5ff1662e61
No known key found for this signature in database
GPG key ID: 1BBA026E13FC0495
5 changed files with 37 additions and 11 deletions

3
TODO
View file

@ -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

View file

@ -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);
}

View file

@ -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();

View file

@ -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)

View file

@ -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;
}