You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
135 lines
5.8 KiB
135 lines
5.8 KiB
//--- |
|
// gint - An alternative runtime environment for fx9860g and fxcg50 |
|
//--- |
|
|
|
#ifndef GINT_GINT |
|
#define GINT_GINT |
|
|
|
#include <gint/defs/types.h> |
|
|
|
/* GINT_VERSION - the library version number |
|
|
|
gint is versioned from its repository commits on the master branch. The |
|
GINT_VERSION integer contains the short commit hash. |
|
|
|
For instance, 0x03f7c0a0 means commit 3f7c0a0. */ |
|
extern char GINT_VERSION; |
|
#define GINT_VERSION ((uint32_t)&GINT_VERSION) |
|
|
|
//--- |
|
// Library management |
|
//--- |
|
|
|
/* gint_install() - install and start gint |
|
This function installs event handlers, masks interrupts and switches VBR. |
|
Unless you are doing experimental runtime switching and you know how this |
|
function is implemented, you should not call it. */ |
|
void gint_install(void); |
|
|
|
/* gint_unload() - unload gint and give back control to the system |
|
This function restores the runtime environment saved by gint_install(). It |
|
is only called when the add-in terminates. To temporarily leave gint during |
|
execution, use gint_switch(). When possible, use syscalls without leaving |
|
gint for better performance. */ |
|
void gint_unload(void); |
|
|
|
/* gint_switch() - temporarily switch out of gint |
|
|
|
This function can be used to leave gint, restore the system's driver |
|
context, and execute code there before returning to gint. By doing this one |
|
can effectively interleave gint with the standard OS execution. The |
|
limitations are quite extreme though, so unless you know precisely why |
|
you're calling this function, you're likely doing it wrong. |
|
|
|
This switch is used to get back to the main menu and to answer TLB misses. |
|
To go back to the menu, use getkey(), or getkey_opt() with the GETKEY_MENU |
|
flag set, or call gint_osmenu() for an immediate return. |
|
|
|
@function Function to call in OS mode */ |
|
void gint_switch(void (*function)(void)); |
|
|
|
/* gint_osmenu() - switch out of gint and call the calculator's main menu |
|
|
|
This function safely invokes the calculator's main menu by unloading gint. |
|
If the user selects the gint application again in the menu, this function |
|
reloads gint and returns. Otherwise, the add-in is fully unloaded by the |
|
system and the application terminates. |
|
|
|
This function is typically called when the [MENU] key is pressed during a |
|
getkey() call. */ |
|
void gint_osmenu(void); |
|
|
|
//--- |
|
// Public functions |
|
//--- |
|
|
|
/* gint_intlevel() - configure the level of interrupts |
|
|
|
This function changes the interrupt level of the requested interrupt. Make |
|
sure you are aware of interrupt assignments to avoid breaking other code. |
|
This function is mainly used by drivers to enable the interrupts that they |
|
support. |
|
|
|
The first parameter 'intid' identifies an interrupt by its position in the |
|
sequence: |
|
|
|
IPRA & 0xf000 ; IPRA & 0x0f00 .. IPRA & 0x000f ; IPRB & 0xf000 .. |
|
|
|
For instance ID 7 refers to the low nibble of IPRB. These IDs and the range |
|
for which there are valid is heavily platform-dependent and any call to this |
|
function should be wrapped inside an MPU type check. This function will |
|
crash if the provided interrupt ID is invalid. |
|
|
|
The interrupt level should be in the range 0 (disabled) .. 15 (highest |
|
priority). |
|
|
|
@intid Interrupt ID of the targeted interrupt |
|
@level Requested interrupt level |
|
Returns the interrupt level that was assigned before the call. */ |
|
int gint_intlevel(int intid, int level); |
|
|
|
/* gint_inthandler() - configure interrupt handlers |
|
|
|
This function installs (copies) interrupt handlers in the VBR space of the |
|
application. Each handler is a 32-byte block aligned on a 32-byte boundary. |
|
When an interrupt request is accepted, the hardware jumps to a specific |
|
interrupt handler at an address that depends on the interrupt source. |
|
|
|
For safety, interrupt handlers should avoid referring to data from other |
|
blocks because the arrangement of blocks at runtime depends on event codes. |
|
The assembler program will assume that consecutive blocks in the source code |
|
will be consecutive in memory, which is not always true. Avoiding cross- |
|
references is a practical rule to avoid problems. (gint breaks this rule |
|
very often but does it carefully... I guess?) |
|
|
|
This function allows anyone to replace any interrupt handler so make sure |
|
you're not interfering with usual interrupt assignments. |
|
|
|
The first parameter event_code represents the event code associated with the |
|
interrupt. If it's not a multiple of 0x20 then you're doing something wrong. |
|
The codes are normally platform-dependent, but gint always uses SH7305 |
|
codes: SH3 platforms have a translation table. See the documentation for a |
|
list of event codes and their associated interrupts. |
|
|
|
The handler function must be an interrupt handler: it must not raise |
|
exceptions, must end with 'rts', and it will use the kernel register bank. |
|
You read that right, it must end with rts because gint's main handler saves |
|
registers besides the automated r0..r7. Do *not* use 'rte' in the handler. |
|
For convenience I allow any block size to be loaded as an interrupt handler, |
|
but it should really be a multiple of 0x20 bytes and not override other |
|
handlers. If it's not written in assembler, then you're likely doing |
|
something wrong, especially with __attribute__((interrupt_handler)) which |
|
uses rte. |
|
|
|
It is common for interrupt handlers to have a few bytes of data, such as the |
|
address of a callback function. gint often stores this data in the last |
|
bytes of the block. This function returns the VBR address of the block which |
|
has just been installed, to allow the caller to edit the parameters later. |
|
|
|
@event_code Identifier of the interrupt block |
|
@handler Address of handler function |
|
@size How many bytes to copy |
|
Returns the VBR address where the handlers was installed. */ |
|
void *gint_inthandler(int event_code, void const *handler, size_t size); |
|
|
|
#endif /* GINT_GINT */
|
|
|