some cleanup in src/core and in the repository

This commit is contained in:
Lephe 2020-06-20 11:41:13 +02:00
parent de4881244e
commit b7de559b78
No known key found for this signature in database
GPG key ID: 1BBA026E13FC0495
10 changed files with 151 additions and 136 deletions

9
TODO
View file

@ -2,37 +2,28 @@ For the 2.1.0 release:
* core: the four basic memory functions (with automated tests)
* bopti: remove the deprecated image_t definition
* project: remove the compat branch
* gray: remove g*() functions
* core: remove the boot log
Issues:
* #3 make drawing functions parameterized
* #8 support fx-CG Manager
* #10 support fx-CG 20
Extensions on existing code:
* bopti: try to display fullscreen images with TLB access + DMA on fxcg50
* gray: add gprint()
* gray: double-buffer gray settings and unify d* with g*
* topti: support unicode fonts
* gray: find good values for more models than the Graph 35+E II
* dma: fx9860g support (need to switch it on and update the Makefile)
* core: try to leave add-in without reset in case of panic
* hardware: fill in the HWMEM_FITTLB flag
* keyboard: think of extended functions
* cpg: spread spectrum on fxcg50
* display: use more of topti's assembler in drect()
* core: use cmp/str for memchr()
* r61524: brightness control and clean the file
* t6k11: check if dupdate() can be done by the DMA
* core: review forgotten globals and MPU addresses not in <gint/mpu/*.h>
* build: make the build system simpler (two targets are enough by default)
* core: run destructors when a task-switch results in leaving the app
* core: invoke main menu instead of returning after main() ends
* prizm: don't hardcode stack address in fxcg50.ld (if possible)
* prizm: detect P1 static RAM (stack) in TLB
* core rtc: use qdiv10 to massively improve division performance
* core: document the SH7305 PFC in <gint/mpu/pfc.h>
Future directions.
* A complete file system abstraction

View file

@ -1,36 +0,0 @@
//---
// core:setup - Installing and unloading the library
//---
#ifndef GINT_CORE_SETUP
#define GINT_CORE_SETUP
#include <gint/defs/types.h>
/* Prototypes for the library management functions are in <gint/gint.h> */
/* gint_setvbr()
Changes the VBR address and calls the configuration function while
interrupts are disabled. The configuration function must disable all
interrupts that the new handlers cannot handle, either by clearing the
priority registers or by setting the interrupt masks.
@vbr New VBR address
@configure Configuration function
Returns the previous VBR address. */
uint32_t gint_setvbr(uint32_t vbr, void (*configure)(void));
void gint_setcpuopm(uint32_t CPUOPM);
uint32_t gint_getcpuopm(void);
/* gint_exch(): Exception handler */
void gint_exch(void);
/* gint_tlbh(): TLB miss handler */
void gint_tlbh(void);
/* gint_inth_7705(): SH7705 exception handler */
void gint_inth_7705(void);
/* gint_inth_7305(): SH7305 exception handler */
void gint_inth_7305(void);
#endif /* GINT_CORE_SETUP */

View file

@ -8,60 +8,74 @@
#include <gint/defs/attributes.h>
#include <gint/defs/types.h>
//---
// Driver procedure flow
//
// Drivers are initialized in priority order, and in linking order within
// the same priority level (pretty much undefined). Make sure every
// driver's priority level is higher than those of its dependencies. In
// the description below, every function can be NULL.
//
// At initialization, the following functions are called:
// 1. driver_sh3() [on SH3-based fx9860g only]
// 2. ctx_save(sys_ctx)
// 3. init()
//
// If the gint_switch() function is called to temporarily give back
// control to the operating system, the state of each driver is saved to
// the stack, then restored from there.
// 4. wait()
// 5. ctx_save(gint_ctx)
// 6. ctx_restore(sys_ctx)
// (stuff happening outside of gint)
// 7. ctx_save(sys_ctx)
// 8. ctx_restore(gint_ctx)
//
// When finally the driver is unloaded, the system context is restored.
// 9. wait()
// 10. ctx_restore(sys_ctx)
//---
/* Driver procedure flow
/* gint_driver_t - driver meta-information used by gint */
Drivers are initialized in priority order, and in linking order within the
the same priority level (which is pretty much undefined). Every driver's
priority level must be higher than those of its dependencies; the numbers
are fixed, see the documentation for level assignments.
At initialization, drivers are first called to wait for the hardware to
become available before initialization. Then the system state is saved. We
still support SH3-based SH7705-like MPUs, so a function init_sh3() is called
for every driver that need to make adjustments to support them. Finally, the
driver is initialized. The calls are as follow; every function pointer can
be NULL in which case it is ignored.
1. wait()
2. ctx_save(sys_ctx)
3. driver_sh3() [SH3-based fx9860g]
4. init()
During the execution, gint_switch() can be called to temporarily give back
control to the OS. In this case, the state of each driver is saved to a
context from gint, then restored from there afterwards.
5. wait()
6. ctx_save(gint_ctx)
7. ctx_restore(sys_ctx)
(stuff happening outside of gint)
8. wait()
9. ctx_save(sys_ctx)
10. ctx_restore(gint_ctx)
When finally the driver is unloaded, the system context is restored.
11. wait()
12. ctx_restore(sys_ctx)
The wait() function is called both when gint has control and when the OS has
control; thus, it must not rely on any internal state other than the
hardware itself.
The ctx_save() and ctx_restore() function are called with interrupts
disabled (IMASK=15) so you should not rely on interrupts. However, TLB
misses are still enabled so you can rely on TLB updates. */
/* gint_driver_t: Metadata and interface of kernel drivers */
typedef struct
{
/* Driver name */
char const *name;
/* SH3-specific preinitializaton; called before init() when running on
SH3. May be NULL. */
/* SH3-specific initialization step. May be NULL. */
void (*driver_sh3)(void);
/* Must initialize the hardware so that the driver can start working.
This is called only once when the add-in starts, and should not save
hardware state (ctx_save() is called before). May be NULL. */
/* Should initialize the hardware so that the driver can start working.
Usually installs interrupt handlers and configures interrupts. Only
called once when the add-in starts. May be NULL. */
void (*init)(void);
/* This function can be used to enforce a waiting period before the
driver is unloaded. It is called before returning to the OS in
gint_switch() and if the add-in exits. May be NULL. */
/* Should wait for the hardware to become available. Called both under
gint control and OS control every time control is passed around. It
is used for instance to wait for DMA transfers. May be NULL. */
void (*wait)(void);
/* System's context and gint's context. These should point to enough
memory to store a full driver state each. These are used when
switching from the system to gint and back to the main menu. If they
don't need to be initialized, put them in gint's uninitialized BSS
section using the GBSS macro of <gint/defs/attributes.h>. May be
NULL only if both ctx_save() and ctx_restore() are NULL. */
memory to store a full driver state each. Used when switching from
the system to gint and back to the main menu. If they don't need to
be initialized, put them in gint's uninitialized BSS section using
the GBSS macro of <gint/defs/attributes.h>. May be NULL only if both
ctx_save() and ctx_restore() are NULL. */
void *sys_ctx;
void *gint_ctx;
@ -69,30 +83,29 @@ typedef struct
possible (memory-mapped MPU registers, port state, etc). This
function is called to save the system's hardware state and gint's
hardware state when moving from one into the other. The parameter
[ctx] is always either [sys_ctx] or [gint_ctx]. */
is always either sys_ctx or gint_ctx. */
void (*ctx_save)(void *ctx);
/* Must restore the state of the driver as saved by ctx_save(). */
void (*ctx_restore)(void *ctx);
} GPACKED(4) gint_driver_t;
/* GINT_DECLARE_DRIVER() - make a driver visible to gint
/* GINT_DECLARE_DRIVER(): Declare a driver to the kernel
Use this macro to expose a driver by passing it the name of a gint_driver_t
Use this macro to declare a driver by passing it the name of a gint_driver_t
structure. This macro moves the structure to the .gint.drivers.* sections,
which are automatically traversed at startup.
The @level argument represents the priority level: lower numbers mean that
The level argument represents the priority level: lower numbers mean that
drivers will be loaded sooner. This numbering allows a primitive form of
dependency for drivers. You need to specify a level which is strictly
higher than the level of all the drivers you depend on. */
#define GINT_DECLARE_DRIVER(level, name) \
GSECTION(".gint.drivers." #level) extern gint_driver_t name;
/* GINT_DRIVER_SH3() - declare a function for SH3 preinitialization
This macro makes its argument NULL on fxcg50, this way the named function
can be defined under #ifdef FX9860G while keeping the structure clean. */
/* GINT_DRIVER_SH3(): Declare an init_sh3() function
This macro is NULL on fxcg50, so that the named function can be defined
under #ifdef FX9860G while keeping the structure clean. */
#ifdef FXCG50
#define GINT_DRIVER_SH3(name) NULL

View file

@ -95,6 +95,7 @@ version_hash = 0x0$(shell git rev-parse --short HEAD)
all: $(target)
$(target): $(obj)
@ rm -f $@
$(call cmd_l,ar,$@) $(ar) rcs $(arflags) $@ $^
# Assembler sources

34
src/core/cpu.h Normal file
View file

@ -0,0 +1,34 @@
//---
// core:cpu - CPU registers and operation management
//---
#ifndef GINT_CORE_CPU
#define GINT_CORE_CPU
#include <gint/defs/types.h>
/* cpu_setVBR(): Change VBR address
Blocks interrupts then changes the VBR address and calls the provided INTC
configuration function before restoring interrupts. This function must
configure the INTC in a way that is safe for the new VBR controller,
including disabling all interrupts that it cannot handle.
@vbr New VBR address
@conf_intc Configuration function
Returns the previous VBR address. */
uint32_t cpu_setVBR(uint32_t vbr, void (*conf_intc)(void));
/* cpu_setCPUOPM(): Change the CPU Operation Mode register
Updates the CPU Operation Mode with the specified settings, then performs a
read and an ICBI to register the change. Only writable bits of CPUOPM should
be changed, other bits must be left at the value given by cpu_getcpuopm().
@CPUOPM New operation mode */
void cpu_setCPUOPM(uint32_t CPUOPM);
/* cpu_getCPUOPM(): Get the CPU OperatioN Mode register */
uint32_t cpu_getCPUOPM(void);
#endif /* GINT_CORE_CPU */

View file

@ -2,22 +2,14 @@
** gint:core:vbr - Assembler-level VBR management
*/
.global _gint_setvbr
.global _gint_setcpuopm
.global _gint_getcpuopm
.global _cpu_setVBR
.global _cpu_setCPUOPM
.global _cpu_getCPUOPM
.section .gint.mapped
/* gint_setvbr()
Changes the VBR address and the calls the configuration function while
interrupts are disabled. The configuration function must change either the
priority registers or the interrupt masks, and make sure that all the
interrupts that it leaves enabled are handled by the new VBR handlers.
@r4 vbr New VBR address (uint32_t)
@r5 configure Configuration function (void -> void)
Returns the previous VBR address. */
_gint_setvbr:
/* cpu_setVBR(): Change VBR address */
_cpu_setVBR:
mov.l r9, @-r15
mov.l r8, @-r15
sts.l pr, @-r15
@ -53,11 +45,8 @@ _gint_setvbr:
.text
/* gint_setcpuopm()
Changes the CPUOPM value and executes an ICBI to register the change.
@r4 New value of CPUOPM (uint32_t) */
_gint_setcpuopm:
/* cpu_setCPUOPM(): Change the CPU Operation Mode register */
_cpu_setCPUOPM:
/* Set CPUOPM as requested */
mov.l 1f, r0
mov.l r4, @r0
@ -74,7 +63,8 @@ _gint_setcpuopm:
rts
nop
_gint_getcpuopm:
/* cpu_getCPUOPM(): Get the CPU OperatioN Mode register */
_cpu_getCPUOPM:
mov.l 1f, r0
rts
mov.l @r0, r0

View file

@ -6,6 +6,7 @@
#include <gint/std/string.h>
#include <gint/hardware.h>
#include <gint/mpu/intc.h>
#include "vbr.h"
/* Interrupt controllers */
@ -49,8 +50,6 @@ int gint_intlevel(int intid, int level)
/* gint_inthandler() - configure interrupt handlers */
void *gint_inthandler(int event_code, const void *handler, size_t size)
{
extern uint32_t gint_vbr;
/* Normalize the event code */
event_code -= 0x400;
event_code &= ~0x1f;

View file

@ -5,27 +5,16 @@
#include <gint/gint.h>
#include <gint/drivers.h>
#include <gint/std/string.h>
#include <core/setup.h>
#include <gint/hardware.h>
#include <gint/mpu/intc.h>
#include <gint/defs/util.h>
#include <gint/display.h>
/* VBR address, from the linker script */
#ifdef FX9860G
extern char gint_vbr_fx9860g[];
#endif
#ifdef FXCG50
extern char gint_vbr_fxcg50[];
extern char gint_vbr_fxcg20[];
#endif
#include "cpu.h"
#include "vbr.h"
/* VBR addresses for gint and the system */
GBSS uint32_t gint_vbr;
GBSS static uint32_t system_vbr;
/* Size of exception and TLB handler */
extern char gint_exch_size;
extern char gint_tlbh_size;
/* Driver table */
extern gint_driver_t bdrv, edrv;
@ -59,7 +48,7 @@ GMAPPED static void gint_ctx_save(gint_core_ctx *ctx)
for(int i = 0; i < 13; i++, IMR += 4)
ctx->masks[i] = *IMR;
ctx->CPUOPM = gint_getcpuopm();
ctx->CPUOPM = cpu_getCPUOPM();
}
}
@ -86,7 +75,7 @@ GMAPPED static void gint_ctx_restore(gint_core_ctx *ctx)
*IMR = ctx->masks[i];
}
gint_setcpuopm(ctx->CPUOPM);
cpu_setCPUOPM(ctx->CPUOPM);
}
}
@ -106,7 +95,7 @@ GMAPPED static void lock(void)
else for(int i = 0; i < 12; i++)
SH7305_INTC.IPRS[2 * i] = 0x0000;
gint_setcpuopm(gint_getcpuopm() | 0x00000008);
cpu_setCPUOPM(cpu_getCPUOPM() | 0x00000008);
}
/* gint_install() - install and start gint */
@ -141,7 +130,7 @@ void gint_install(void)
memcpy(vbr + 0x600, inth_entry, 64);
/* Time to switch VBR and roll! */
system_vbr = gint_setvbr(gint_vbr, lock);
system_vbr = cpu_setVBR(gint_vbr, lock);
}
/* unlock() - unlock interrupts, restoring system settings */
@ -166,7 +155,7 @@ void gint_unload(void)
if(drv->wait) drv->wait();
}
gint_setvbr(system_vbr, unlock);
cpu_setVBR(system_vbr, unlock);
}
//---
@ -223,7 +212,7 @@ void gint_switch(void (*function)(void))
if(drv->wait) drv->wait();
}
gint_setvbr(system_vbr, gint_switch_out);
cpu_setVBR(system_vbr, gint_switch_out);
if(function) function();
/* Wait for the OS to finish working */
@ -231,7 +220,7 @@ void gint_switch(void (*function)(void))
{
if(drv->wait) drv->wait();
}
gint_setvbr(gint_vbr, gint_switch_in);
cpu_setVBR(gint_vbr, gint_switch_in);
}
int __Timer_Install(int id, void (*handler)(void), int delay);

32
src/core/vbr.h Normal file
View file

@ -0,0 +1,32 @@
//---
// core:vbr - VBR-related functions and linker script symbols
//---
#ifndef GINT_CORE_VBR
#define GINT_CORE_VBR
#include <gint/defs/types.h>
/* VBR addresses from the linker script */
#ifdef FX9860G
extern char gint_vbr_fx9860g[];
#endif
#ifdef FXCG50
extern char gint_vbr_fxcg50[];
extern char gint_vbr_fxcg20[];
#endif
/* gint's VBR address as determined at runtime; not valid before kinit() */
extern uint32_t gint_vbr;
/* The kernel's interrupt and exception handlers' entry points */
void gint_exch(void);
void gint_tlbh(void);
void gint_inth_7705(void);
void gint_inth_7305(void);
/* Size of exception and TLB handlers */
extern char gint_exch_size;
extern char gint_tlbh_size;
#endif /* GINT_CORE_VBR */

View file

@ -4,6 +4,8 @@
static uint16_t *main = (void *)0xac0f0000;
static uint16_t *scnd = (void *)0xac11b500;
/* On Prizm: should be: 0xa80f0000 and 0xa811b500 */
/* Shared VRAM pointer, the one exposed by <gint/display.h> */
uint16_t *gint_vram = (void *)0xac0f0000;