* Add the power management functions (mostly stable even under
overclock; requires some testing, but no known issue)
* Add a dynamic configuration system where interfaces can declare
descriptors with arbitrary endpoint numbers and additional
parameters, and the driver allocates USB resources (endpoints, pipes
and FIFO memory) between interfaces at startup. This allows
implementations of different classes to be independent from each
other.
* Add responses to common SETUP requests.
* Add pipe logic that allows programs to write data synchronously or
asynchronously to pipes, in a single or several fragments, regardless
of the buffer size (still WIP with a few details to polish and the
API is not public yet).
* Add a WIP bulk IN interface that allows sending data to the host.
This will eventually support the fxlink protocol.
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.
The question of how to handle a partially-restored world state begs for
an elegant symmetrical answer, but that doesn't work unless both kernels
do the save/restore for themselves. So far, things have worked out
because any order works since interrupts are disabled therefore
partially-restored drivers are inactive.
However the USB module requires waits that are best performed with
timers, so the order cannot be chosen arbitrarily. This commit enforces
a gint-centric order where code from a gint driver is only run when all
lower-level drivers are active. This solves some pretty bad freezes with
the USB module.
The new allocator uses a segregated best-fit algorithm with exact-size
lists for all sizes between 8 bytes (the minimum) and 60 bytes, one list
for blocks of size 64-252 and one for larger blocks.
Arenas managed by this allocator have built-in statistics that track
used and free memory (accounting for block headers), peak memory, and
various allocation results.
In addition, the allocator has self-checks in the form of integrity
verifications, that can be enabled with -DGINT_KMALLOC_DEBUG=1 at
configuration time or with the :dev configuration for GiteaPC. This is
used by gintctl.
The kmalloc interface is extended with a new arena covering all unused
memory in user RAM, managed by gint's allocator. It spans about 4 kB on
SH3 fx-9860G, 16 kB on SH4 fx-9860G, and 500 kB on fx-CG 50, in addition
to the OS heap. This new arena is now the default arena for malloc(),
except on SH3 where some heap problems are currently known.
This change introduces a centralized memory allocator in the kernel.
This interface can call into multiple arenas, including the default OS
heap and planned arenas managed by a gint algorithm.
The main advantage of this method is that it allows the heap to be
extended over previously-unused areas of RAM such as the end of the
static RAM region (apart from where the stack resides). Not using the OS
heap is also sometimes a matter of correctness since on some OS versions
the heap is known to fragment badly and degrade over time.
I hope the deep control this interfaces gives over meomry allocation
will allow very particular applications like object-specific allocators
in fragmented SPU memory.
This change does not introduce any new algorithm or arena so programs
should behave exactly as before.
The new keyboard device (keydev) interface implements the kernel's view
of a keyboard providing input events. Its main role is to abstract all
the globals of the KEYSC driver and getkey functions into a separate
object: the "keyboard device".
The device implements event transformations such as modifiers and
repeats, instead of leaving them to getkey. While this can seem
surprising at first, a real keyboard controller is responsible for
repeats and modifier actions depend on the state of the keyboard which
is only tracked in real-time.
In this commit, getkey() has not changed yet apart from indirectly using
the keydev interface with pollevent(). It will be changed soon to use
event transforms in keydev_read(), and will be left in charge of
providing repeat profiles, handling return-to-menu, backlight changes
and timeouts, all of which are user convenience features.
* dnsize() works like dsize() but a limit on the number of bytes is
specified. This is useful to obtain the length of a substring.
* drsize() has a reverse limit; the input specifies a number of pixels
and the function determines how much of the input fits. This is useful
for word wrapping algorithms.
This parameter controls the maximum number of glyphs to print.
For backwards compatibility, it is automatically inserted by a macro in
older calls with only 7 parameters.
This function performs a more rigorous analysis of the mapped region by
checking continuity. So far all pages mapped in userpsace have been
contiguous, so the results are identical to gint[HWURAM].
Page size is now optionnaly provided in mmu_translate() and its
subfunctions; programs that use this function need to add a second NULL
parameter.
* 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.
The repeat delays of getkey() are adjusted automatically, however a
repeat that is currently going on might be affected.
Also, repeat delays are always approximated as a whole number of
keyboard scans so an increase in scan frequency can impact the speed at
which repeats are emitted.
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.
This change moves the gint version declaration from a symbol in a
compile-time generated object file to a preprocessed header installed in
the library tree.
This makes it possible to determine the gint version statically from the
headers, which is much more robust in complex build systems that use
version information such as CMake's find_package().
Some very trivial applications might not require its symbols explicitly,
thus the need to force a dependency (otherwise OS interrupts such as the
KEYSC are not disabled and crash the handler very quickly).
This change adds a new TMU function timer_spinwait() which waits for a
timer to raise its UNF flag. This makes it possible to wait even when
interrupts are disabled.
This is used by the new CPG function sleep_us_spin() which waits for a
given delay without using interrupts. This is currently used in SPU
initialization.
* Specify a line height for the default fx-CG 50 font so that the height
returned by dsize() is correctly 9, not 11.
* Adjust vertical and horizontal alignment in dtext_opt() and
dprint_opt() by a full pixel (DTEXT_BOTTOM, DTEXT_RIGHT) and half a
pixel (DTEXT_MIDDLE, DTEXT_CENTER) to make sure that the specified
position is within rendered text (as in DTEXT_LEFT and TEXT_TOP) and
to improve centering of strings with odd width or odd height, for
which there is only one valid position.
This commit introduces custom character spacing with a new fxconv
parameter "char-spacing". Word spacing is also tied to the width of the
space character (0x20). This removes the need for special semantics on
the space character, but requires that its size be specified with gray
pixels for proportional fonts.
This also fixes problems with the size of spaces in dsize() not being
correlated with their size during rendering, since on fx-9860G topti
already used the glyph's with as word spacing.
Since fxconv changes but gint's Makefile does not track updates to
external tools, a full rebuild of gint is required past this commit.
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.