Commit Graph

85 Commits

Author SHA1 Message Date
Lephe af5c16a3d3
usb: massively improve writing logic
* Move logic around tracking transfers to asyncio.c.

* Add a "short buffer" holding 0-3 bytes between writes, so that the
  driver performs only 4-byte writes in the FIFO and a short write in
  the commit, if needed.
  - This is partially due to me thinking at some point that degrading
    writing size was impossible, but it might actually be possible by
    writing to FIFO/FIFO+2 or FIFO/FIFO+1/FIFO+2/FIFO+3.
  - In any case I think this new approach wins on performance.

* Get rid of unit_size since we now always use 4 bytes.

* Add a waiting function which is used in usb_close() (and once tested
  should be used in world switches too).

* Eliminate some of the special cases for the DCP, though not all (in
  particular I can't get the commit to rely on the BEMP interrupt yet,
  nor can I properly clear PID to NAK when unbinding).
2023-02-09 23:00:44 +01:00
Lephe db50c9b192
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)
2023-01-25 22:38:39 +01:00
Lephe 74438f5da5
render: add a dgetpixel() function 2022-11-16 19:12:48 +01:00
Lephe b942bc5d19
clock: add overclock support on fx-CG 10/20/50 2022-05-15 19:20:14 +01:00
Lephe a4df076214
render-cg: replace dimage and dsubimage with new renderer 2022-05-04 20:53:56 +01:00
Lephe 904ab74984
(minor) 2022-05-04 19:08:54 +01:00
Lephe b549fd68ba
fs: stat(), proper unlink(), rmdir() 2021-12-30 18:17:13 +01:00
Lephe 9cae0040b5
fs: folder support, part 1 (mkdir/rmdir and the opendir(3) family) 2021-12-21 19:01:00 +01:00
Lephe 4147236343
(minor changes) 2021-05-12 09:17:24 +02:00
Lephe c9264a06d5
kernel: driver and world system overhaul
Changes in the driver and world system:

* Rewrite driver logic to include more advanced concepts. The notion of
  binding a driver to a device is introduced to formalize wait(); power
  management is now built-in instead of being handled by the drivers
  (for instance DMA). The new driver model is described in great detail
  in <gint/drivers.h>

* Formalized the concept of "world switch" where the hardware state is
  saved and later restored. As a tool, the world switch turns out to be
  very stable, and allows a lot of hardware manipulation that would be
  edgy at best when running in the OS world.

* Added a GINT_DRV_SHARED flag for drivers to specify that their state
  is shared between worlds and not saved/restored. This has a couple of
  uses.

* Exposed a lot more of the internal driver/world system as their is no
  particular downside to it. This includes stuff in <gint/drivers.h>
  and the driver's state structures in <gint/drivers/states.h>. This is
  useful for debugging and for cracked concepts, but there is no
  API stability guarantee.

* Added a more flexible driver level system that allows any 2-digit
  level to be used.

Feature changes:

* Added a CPU driver that provides the VBR change as its state save.
  Because the whole context switch relied on interrupts being disabled
  anyway, there is no longer an inversion of control when setting the
  VBR; this is just part of the CPU driver's configuration. The CPU
  driver may also support other features such as XYRAM block transfer
  in the future.

* Moved gint_inthandler() to the INTC driver under the name
  intc_handler(), pairing up again with intc_priority().

* Added a reentrant atomic lock based on the test-and-set primitive.
  Interrupts are disabled with IMASK=15 for the duration of atomic
  operations.

* Enabled the DMA driver on SH7305-based fx-9860G. The DMA provides
  little benefit on this platform because the RAM is generally faster
  and buffers are ultimately small. The DMA is still not available on
  SH3-based fx-9860G models.

* Solved an extremely obnoxious bug in timer_spin_wait() where the
  timer is not freed, causing the callback to be called when interrupts
  are re-enabled. This increments a random value on the stack. As a
  consequence of the change, removed the long delays in the USB driver
  since they are not actually needed.

Minor changes:

* Deprecated some of the elements in <gint/hardware.h>. There really is
  no good way to "enumerate" devices yet.

* Deprecated gint_switch() in favor of a new function
  gint_world_switch() which uses the GINT_CALL abstraction.

* Made the fx-9860G VRAM 32-aligned so that it can be used for tests
  with the DMA.

Some features of the driver and world systems have not been implemented
yet, but may be in the future:

* Some driver flags should be per-world in order to create multiple
  gint worlds. This would be useful in Yatis' hypervisor.
* A GINT_DRV_LAZY flag would be useful for drivers that don't want to
  be started up automatically during a world switch. This is relevant
  for drivers that have a slow start/stop sequence. However, this is
  tricky to do correctly as it requires dynamic start/stop and also
  tracking which world the current hardware state belongs to.
2021-04-23 20:44:08 +02:00
Lephe 770b4e0117
gint: rename the callbacks GINT_CALL, as there are synchronous ones
This will be useful for world switch calls which are not "callbacks" but
simply polymorphic function pointers.
2021-04-20 17:51:53 +02:00
Lephe 52bc1fc848
(typos and TODOs) 2021-04-20 12:19:24 +02:00
Lephe a2fd9e3351
kernel: add a generic callback mechanism
This mechanism allows callbacks to be defined with up to 4 32-bit
arguments, and could be extended later. This will hopefully replace the
timer_callback_t used in timers and RTC, and will be added to the DMA
and USB APIs -- the hard part is to not break source compatibility with
previous versions.
2021-04-11 18:47:17 +02:00
Lephe 3885f10ee1
kernel: move VBR at the end of the user RAM area on fx-9860G
This leaves more space available for the heap.
2021-02-15 09:46:59 +01:00
Lephe 023675d449
improve structure of sources and formatted printer
* Create an `src/3rdparty` folder for third-party code (to add the
  Grisu2B alfogithm soon).
* Split the formatted printer into gint's kprint (src/kprint), its
  extension and interface (include/gint/kprint.h), and its use in the
  standard stdio functions (src/std/print.c).
* Slightly improve the interface of kformat_geometry() to avoid relying
  on knowing format specifiers.
* Add a function to register more formatters, to allow floating-point
  formatters without requiring them.
2021-02-02 18:19:10 +01:00
Lephe 293532024d
kernel: fix gint[HWURAM] not being set on fx-9860G
When switching to dynamic TLB the counting of mapped memory was no
longer required at boot time. This was restored weirdly for fx-CG 50 and
not at all for fx-9860G; this is now fixed.
2021-02-02 18:18:02 +01:00
Lephe 0525b51ba5
switch build system to CMake
This factors the burden of compiler specification in the fxSDK while
providing substantially more support through CMake modules.
2021-01-25 15:31:20 +01:00
Lephe 078edb50b2
small cleanup 2020-10-05 16:31:37 +02:00
Lephe e5abe03b89
kernel: dynamic loading of GMAPPED functions to user RAM
This commit introduces a large architectural change. Unlike previous
models of the fx-9860G series, the G-III models have a new user RAM
address different from 8801c000. The purpose of this change is to
dynamically load GMAPPED functions to this address by querying the TLB,
and call them through a function pointer whose address is determined
when loading.

Because of the overhead of using a function pointer in both assembly and
C code, changes have been made to avoid GMAPPED functions altogether.
Current, only cpu_setVBR() and gint_inth_callback() are left, the second
being used specifically to enable TLB misses when needed.

* Add a .gint.mappedrel section for the function pointers holding
  addresses to GMAPPED functions; add function pointers for
  cpu_setVBR() and gint_inth_callback()
* Move rram to address 0 instead of the hardcoded 0x8801c000
* Load GMAPPED functions at their linked address + the physical address
  user RAM is mapped, to and compute their function pointers
* Remove the GMAPPED macro since no user function needs it anymore
* Add section flags "ax" (code) or "aw" (data) to every custom .section
  in assembler code, as they default to unpredictable values that can
  cause the section to be marked NOLOAD by the linker
* Update the main kernel, TMU, ETMU and RTC interrupt handlers to use
  the new indirect calling method

This is made possible by new MMU functions giving direct access to the
physical area behind any virtualized page.

* Add an mmu_translate() function to query the TLB
* Add an mmu_uram() function to access user RAM from P1

The exception catching mechanism has been modified to avoid the use of
GMAPPED functions altogether.

* Set SR.BL=0 and SR.IMASK=15 before calling exception catchers
* Move gint_exc_skip() to normal text ROM
* Also fix registers not being popped off the stack before a panic

The timer drivers have also been modified to avoid GMAPPED functions.

* Invoke timer_stop() through gint_inth_callback() and move it to ROM
* Move and expand the ETMU driver to span 3 blocks at 0xd00 (ETMU4)
* Remove the timer_clear() function by inlining it into the ETMU handler
  (TCR is provided within the storage block of each timer)
* Also split src/timer/inth.s into src/timer/inth-{tmu,etmu}.s

Additionally, VBR addresses are now determined at runtime to further
reduce hardcoded memory layout addresses in the linker script.

* Determine fx-9860G VBR addresses dynamically from mmu_uram()
* Determine fx-CG 50 VBR addresses dynamically from mmu_uram()
* Remove linker symbols for VBR addresses

Comments and documentation have been updated throughout the code to
reflect the changes.
2020-09-17 14:48:54 +02:00
Lephe d12be8add0
remove features that are deprecated as of v2.1 2020-07-26 11:47:23 +02:00
Lephe 4cb1555708
kernel: add an add-in restart mechanism using gint_osmenu()
This new mechanism allows an add-in to be restarted after exiting by
just never exiting in the first place, calling gint_osmenu() instead.
This makes sure that we can relaunch the add-in immediately, which is
normally possible through an option in the OS though no OS-independent
method of setting it is currently known.

Because this is gint_osmenu(), known pitfalls apply. On all platforms,
it is necessary to prepare the first frame before leaving. On fx-CG 50,
the inevitable display border is also there.
2020-07-20 20:37:34 +02:00
Lephe 6c535bf7df
cpg: add spread spectrum control
Disables spread spectrum by default so that the frequency estimations of
the CPG driver (notably used by the timer driver and libprof) are more
accurate.
2020-07-20 17:10:47 +02:00
Lephe 77de9e7796
move private headers to subfolders of src/
This keeps the include/ folder clean.
2020-07-13 17:47:21 +02:00
Lephe 94fb300e72
gray: finalize the gray engine API
* Define dgray() to replace gray_start() and gray_stop()
* Introduce a mechanism to override the d*() functions rather than using
  another set of functions, namely g*(). Gray rendering should now be
  done with d*() (a compatibility macro for g*() is available until v2.1).
* Gray engine now reserves TMU0 at the start of the add-in to prevent
  surprises if timers are exhausted, so it nevers fails to start
* Replace other gray engine functions with dgray_*()
* More general rendering functions (in render/) to lessen the burden of
  porting them to the gray engine. As a consequence, dtext_opt(),
  dprint_opt() and drect_border() are now available in the gray engine,
  which was an omission from 230b796.
* Allow C_NONE in more functions, mainly on fx-CG 50
* Remove the now-unused dupdate_noint()
2020-07-13 13:49:07 +02:00
Lephe 0aceb6f93e
kernel: compact VBR even more on SH3
This change moves interrupt handler from VBR + 0x640 to VBR + 0x200, in
the gap between the exception and TLB miss handlers.

This new scheme is not limited to VBR+0x200 .. VBR+0x400 as new large
block numbers can be used to jump over the TLB miss handler and the
interrupt handler entry points.
2020-07-10 13:07:12 +02:00
Lephe 9d1187b5b4
string: optimized memcpy, memcmp, memset; decent memmove
This change adds optimized versions of the core memory functions,
relying on 4-alignment, 2-alignment, and the SH4's unaligned move
instruction to (hopefully) attain good performance in all situations.
2020-07-04 15:05:28 +02:00
Lephe 4a0fc65c34
gray: add decent defaults for older fx9860g-like models
Gray quality is better on the Graph 35+E II, it still flickers a lot on
other models (as I remembered). There might be better settings out there
but I'm not sure we can reach the quality of the current Graph 35+E II
defaults. The Graph 75+E with which I tested might also be different
from other T6K11 such as the smaller Graph 35+E.
2020-06-20 19:16:42 +02:00
Lephe b7de559b78
some cleanup in src/core and in the repository 2020-06-20 11:41:13 +02:00
Lephe 2fd4238d31
core: finalize TLB management in timer callbacks (STABLE)
This change enables interrupts within timer callbacks, making it
possible to load pages to MMU while handling a timer underflow. The call
to TLB_LoadPTEH() has been moved directly into the VBR handler to avoid
jumping to ILRAM for a short call on SH4.

The TMU and ETMU handlers have been changed to callback through a new
function gint_inth_callback() that saves the user bank and a few
registers, then invokes the callback with interrupts enabled and in user
bank; until now, callbacks were invoked with interrupts disabled and in
kernel bank. Note that IMASK is still set so a callback can only be
interrupted by a high-priority interrupt.

A timer_wait() function has also been added to simplify tests that
involve timers. Finally, the priority level of the TMU0 underflow
interrupt has been set to 13 (as per the comments) instead of 7.

This version is the first stable version that handles TLB misses
transparently for large add-ins. It is suitable for every gint
application.
2020-06-17 11:43:26 +02:00
Lephe 4ad2110efc
core: accept large add-ins and setup TLB management (UNSTABLE)
This change modifies the fx-CG 50 linker script to allow add-ins up to
2M and no longer complains about add-ins that don't fit in the TLB.

It also exposes the __TLB_LoadPTEH() syscall (%003 on fx9860g, %00c on
fxcg50) that answers TLB misses. This syscall can be called manually
from an add-in to load some pages and seems to work without problem.

However, this version does not provide any automatic TLB management,
some key areas of the kernel are still under TLB and some user code
(such as timer callbacks) is not! This version is suitable only for
add-ins smaller than 220k!
2020-06-14 11:01:27 +02:00
Lephe caa4f675c9
bopti: deprecate image_t, renamed to bopti_image_t 2020-06-01 12:11:59 +02:00
Lephe 5ff1662e61
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.
2020-05-31 15:52:00 +02:00
Lephe 4036a583df
bfile: add BFile syscalls on fx-CG 50 (still unstable)
For some reason these syscalls tend to crash in a basic delete, create,
open, write, close workflow (after the write is finished). I'll look
into using the new gint/fxlib switch to use them safely.
2020-05-16 17:11:55 +02:00
Lephe e217309adf
render-cg: expose vram buffers with dgetvram() and dsetvram() 2020-05-10 23:03:02 +02:00
Lephe 85311a0b31
drivers: update the model, replacing unload() with wait()
The unload() function is not very relevant for drivers because hardware
state is managed by ctx_save() and ctx_restore() and software state is
managed by underlying drivers when there are dependencies.

For now, it's been replaced with a wait() function that allows drivers
to not be interrupted at any point. It is currently used by the DMA to
wait for ongoing transfers to finish before disabling interrupts (which
would prevent the transfer end from being detected) and switching in and
out of gint.
2020-05-10 16:36:21 +02:00
Lephe 4485e7f865
core, tmu: add gint_switch(), return to menu, and improve timer code
* Add the gint_switch() function which executes user-provided code from
  the system (CASIOWIN) context.
* Added interrupt masks to the core context (should have been there long
  ago).
* Added the gint_osmenu() function that switches out of gint to invoke
  GetKeyWait() and inject KEY_CTRL_MENU to trigger the main menu. This
  uses many CASIOWIN syscalls, but we don't care because gint is unloaded.
  Trickery is used to catch the key following the return in the add-in
  and/or display a new application frame before GetKeyWait() even finishes
  after coming back. This is only available on fx9860g for now.
* Removed any public syscall definition to clear up interfaces.
* Patched the DMA interruption problem in a weird way on fxcg50, a
  driver function will be used to do that properly eventually.
* Changed the driver model to save driver contexts in preallocated
  spaces instead of on the stack for overall less risk.
* Enabled return-to-menu with the MENU key on fx9860g in getkey().
* Changed the keyboard driver to emit releases before presses, as a
  return-to-menu acts as a press+release of different keys in a single
  driver frame, which confuses getkey().
* Fixed a really stupid bug in memcpy() that made the function really
  not work.

Improvements in the timer driver:

* Expose ETMU modules as SH7705_TMU and SH7305_TMU in <gint/mpu/tmu.h>.
* Remove the timer_t structures, using SH*_ETMU and SH*_TMU instead.
  Only interrupt gate entries are left hardcoded.
* Discovered that not only every write to the TCNT or TCR of an ETMU
  takes about 1/32k of a second (hinting at registers being powered by
  the same clock as the timer), but every write occuring while a previous
  write is pending is *lost*. This led to terrible bugs when switching
  ETMU contexts too fast in gint_switch().
* Removed an internal timer_address() function.
* Overall simplified the handling of timers and the initialization step.
2020-05-10 14:03:41 +02:00
Lephe 61da7debc8
code review and display driver changes
t6k11: use the gint array for variant detection
r61524: use true triple buffering by default
display: define DWIDTH and DHEIGHT
display: add C_RGB(r,g,b) (0 ≤ r,g,b ≤ 31) [fxcg50]
2020-02-23 16:05:25 +01:00
Lephe 3147045196
bopti-cg: add p8, p4, and fix alignment issues on r5g6b5 2019-11-15 13:31:44 +01:00
Lephe 9eb723ee53
render: remove the GINT_NEED_VRAM macro
This macro used to protect the declaration of the [vram] variable of
gint. This variable was short to keep drawing functions short but could
clutter the namespace.

That being said, it's even better to just [#define vram gint_vram] if
you need. This change renames the variable to [gint_vram], exposes it
whenever <gint/display.h> is included, and removes the GINT_NEED_VRAM
macro altogether.
2019-10-27 08:14:42 +01:00
Lephe 95a3345326
keyboard: add keydown() in the model
This change adds a keydown() function that is synchronized with events,
ie. it returns the key state as seen by previously read events.

It also completely eliminates low-level repeat events, which are not
very meaningul as the keyboard scan frequency goes up (and would be
meaningless if KEYSC interrupts were used), and adapts getkey() by
giving it access to the current driver time through pollevent().
2019-09-28 19:25:01 +02:00
Lephe 86cd9b98d4
small improvements
* Update TOTO list
* Change the type of gint_vbr to comply with a new warning in GCC 9
* Add strcmp()
2019-09-19 15:59:38 +02:00
Lephe 5630814897
core: allow custom panics and exception catching
This change introduces two new mechanismes for executing user code when
an exception occurs.

* This first is the custom panic message, which usually displays "System
  ERROR". The function that performs this task can now be user-defined.
  It is also run in user mode because the exception handler rte's into
  it, allowing it to execute any kind of interrupt-inducing task. The
  behavior is undefined if this function raises an exception.

* The second is an exception-catching function, which (when set) is
  called every time an exception occurs, and is granted the chance of
  handling the exception to continue execution normally. It can be used
  in various ways, the most primitive of which is recording the
  exception and going back. It runs in interrupt mode and must not raise
  any kind of exception.
2019-09-13 08:10:30 +02:00
Lephe 61e68d01bb
expose more platform-agnostic code
May be useful later on for libraries such as libprof.
2019-09-06 12:16:31 +02:00
lephe e1aca8d89b
exc: add exception handlers, use them in the DMA
This change introduces exception handlers that default to a fatal error
with an on-screen description of the exception and some debugging
information.

It also adds the dprint() function as a definitely-needed helper and
removes bootlog_unmapped() by using the exception handler for the fatal
error display. (Also printf() is now required in all gint add-ins; this
is sad, but space is not as much of a constraint as debugging.)

Finally, the exception handler is used to handle an interrupt which is
an exception in practice, the DMA address error. On fx-CG 50, additional
DMA-related information is displayed on the screen. This is left out on
fx-9860G as there is not enough space.
2019-09-03 22:15:00 +02:00
lephe 64dbe6021d some formatting and comment updates 2019-08-04 13:59:17 +02:00
lephe ae4f7af172 gray: add engine, basic drawing and text
This revision includes the base gray engine with sensible starting
defaults, gclear() and grect(), as well as gtext().
2019-07-20 12:31:46 -04:00
lephe c80debacd7 keyboard stdio: some fixes 2019-07-17 19:29:12 -04:00
lephe ff2db385a8 TODO update and miscellaneous style 2019-07-16 18:34:10 -04:00
lephe f33cb3cf80 core: better bootlog API and implementation
* Now uses topti instead of fxlib for text (including MMU failure)
* Fit .pretext into 4k for everything before MMU succeeds
* A short version of sprintf() for dynamic messages
* Support a driver function, status(), to allow early driver debug
* Expose more useful platform information in <gint/mpu.h>
* Expose the first of a few CASIOWIN syscalls
2019-03-06 14:32:51 +01:00
lephe 3f7c0a04ad way too much, including bopti/topti, timers, and more. 2019-02-21 21:00:26 +01:00