N64 interrupt registering and servicing routines.
More...
|
#define | MI_INTR_SP 0x01 |
| SP interrupt bit.
|
|
#define | MI_INTR_SI 0x02 |
| SI interrupt bit.
|
|
#define | MI_INTR_AI 0x04 |
| AI interrupt bit.
|
|
#define | MI_INTR_VI 0x08 |
| VI interrupt bit.
|
|
#define | MI_INTR_PI 0x10 |
| PI interrupt bit.
|
|
#define | MI_INTR_DP 0x20 |
| DP interrupt bit.
|
|
#define | MI_MASK_SP 0x01 |
| SP mask bit.
|
|
#define | MI_MASK_SI 0x02 |
| SI mask bit.
|
|
#define | MI_MASK_AI 0x04 |
| AI mask bit.
|
|
#define | MI_MASK_VI 0x08 |
| VI mask bit.
|
|
#define | MI_MASK_PI 0x10 |
| PI mask bit.
|
|
#define | MI_MASK_DP 0x20 |
| DP mask bit.
|
|
#define | MI_MASK_CLR_SP 0x0001 |
| Clear SP mask.
|
|
#define | MI_MASK_SET_SP 0x0002 |
| Set SP mask.
|
|
#define | MI_MASK_CLR_SI 0x0004 |
| Clear SI mask.
|
|
#define | MI_MASK_SET_SI 0x0008 |
| Set SI mask.
|
|
#define | MI_MASK_CLR_AI 0x0010 |
| Clear AI mask.
|
|
#define | MI_MASK_SET_AI 0x0020 |
| Set AI mask.
|
|
#define | MI_MASK_CLR_VI 0x0040 |
| Clear VI mask.
|
|
#define | MI_MASK_SET_VI 0x0080 |
| Set VI mask.
|
|
#define | MI_MASK_CLR_PI 0x0100 |
| Clear PI mask.
|
|
#define | MI_MASK_SET_PI 0x0200 |
| Set PI mask.
|
|
#define | MI_MASK_CLR_DP 0x0400 |
| Clear DP mask.
|
|
#define | MI_MASK_SET_DP 0x0800 |
| Set DP mask.
|
|
#define | PI_CLEAR_INTERRUPT 0x02 |
| Bit to set to clear the PI interrupt.
|
|
#define | SI_CLEAR_INTERRUPT 0 |
| Bit to set to clear the SI interrupt.
|
|
#define | SP_CLEAR_INTERRUPT 0x08 |
| Bit to set to clear the SP interrupt.
|
|
#define | DP_CLEAR_INTERRUPT 0x0800 |
| Bit to set to clear the DP interrupt.
|
|
#define | AI_CLEAR_INTERRUPT 0 |
| Bit to set to clear the AI interrupt.
|
|
|
uint32_t | interrupt_disabled_tick = 0 |
| tick at which interrupts were disabled. More...
|
|
struct callback_link * | AI_callback = 0 |
| Linked list of AI callbacks.
|
|
struct callback_link * | VI_callback = 0 |
| Linked list of VI callbacks.
|
|
struct callback_link * | PI_callback = 0 |
| Linked list of PI callbacks.
|
|
struct callback_link * | DP_callback = 0 |
| Linked list of DP callbacks.
|
|
struct callback_link * | SI_callback = 0 |
| Linked list of SI callbacks.
|
|
struct callback_link * | SP_callback = 0 |
| Linked list of SP callbacks.
|
|
struct callback_link * | TI_callback = 0 |
| Linked list of TI callbacks.
|
|
struct callback_link * | CART_callback = 0 |
| Linked list of CART callbacks.
|
|
N64 interrupt registering and servicing routines.
The N64 interrupt controller provides a software interface to register for interrupts from the various systems in the N64. Most interrupts on the N64 coordinate through the MIPS interface (MI) to allow interrupts to be handled at one spot. A notable exception is the timer interrupt which is generated by the MIPS r4300 itself and not the N64 hardware.
The interrupt controller is automatically initialized before main is called. By default, all interrupts are enabled and any registered callback can be called when an interrupt occurs. Each of the N64-generated interrupts is maskable using the various set accessors.
Interrupts can be enabled or disabled as a whole on the N64 using enable_interrupts and disable_interrupts. It is assumed that once the interrupt system is activated, these will always be called in pairs. Calling enable_interrupts without first calling disable_interrupts is considered a violation of this assumption and should be avoided. Calling disable_interrupts when interrupts are already disabled will have no effect. Calling enable_interrupts again to restore from a critical section will not enable interrupts if interrupts were not enabled when calling disable_interrupts. In this manner, it is safe to nest calls to disable and enable interrupts.
◆ interrupt_state_t
State of interrupts on the system.
Enumerator |
---|
INTERRUPTS_UNINITIALIZED | Interrupt controller has not been initialized.
|
INTERRUPTS_DISABLED | Interrupts are currently disabled.
|
INTERRUPTS_ENABLED | Interrupts are currently enabled.
|
◆ __MI_handler()
void __MI_handler |
( |
void |
| ) |
|
Handle an MI interrupt.
- Note
- This function handles most of the interrupts on the system as they come through the MI.
◆ register_AI_handler()
void register_AI_handler |
( |
void(*)() |
callback | ) |
|
Register an AI callback.
- Parameters
-
[in] | callback | Function to call when an AI interrupt occurs |
◆ unregister_AI_handler()
void unregister_AI_handler |
( |
void(*)() |
callback | ) |
|
Unregister an AI callback.
- Parameters
-
[in] | callback | Function that should no longer be called on AI interrupts |
◆ register_VI_handler()
void register_VI_handler |
( |
void(*)() |
callback | ) |
|
Register a VI callback.
- Parameters
-
[in] | callback | Function to call when a VI interrupt occurs |
◆ unregister_VI_handler()
void unregister_VI_handler |
( |
void(*)() |
callback | ) |
|
Unregister a VI callback.
- Parameters
-
[in] | callback | Function that should no longer be called on VI interrupts |
◆ register_PI_handler()
void register_PI_handler |
( |
void(*)() |
callback | ) |
|
Register a PI callback.
- Parameters
-
[in] | callback | Function to call when a PI interrupt occurs |
◆ unregister_PI_handler()
void unregister_PI_handler |
( |
void(*)() |
callback | ) |
|
Unegister a PI callback.
- Parameters
-
[in] | callback | Function that should no longer be called on PI interrupts |
◆ register_DP_handler()
void register_DP_handler |
( |
void(*)() |
callback | ) |
|
Register a DP callback.
- Parameters
-
[in] | callback | Function to call when a DP interrupt occurs |
◆ unregister_DP_handler()
void unregister_DP_handler |
( |
void(*)() |
callback | ) |
|
Unregister a DP callback.
- Parameters
-
[in] | callback | Function that should no longer be called on DP interrupts |
◆ register_SI_handler()
void register_SI_handler |
( |
void(*)() |
callback | ) |
|
Register a SI callback.
- Parameters
-
[in] | callback | Function to call when a SI interrupt occurs |
◆ unregister_SI_handler()
void unregister_SI_handler |
( |
void(*)() |
callback | ) |
|
Unegister a SI callback.
- Parameters
-
[in] | callback | Function that should no longer be called on SI interrupts |
◆ register_SP_handler()
void register_SP_handler |
( |
void(*)() |
callback | ) |
|
Register a SP callback.
- Parameters
-
[in] | callback | Function to call when a SP interrupt occurs |
◆ unregister_SP_handler()
void unregister_SP_handler |
( |
void(*)() |
callback | ) |
|
Unegister a SP callback.
- Parameters
-
[in] | callback | Function that should no longer be called on SP interrupts |
◆ register_TI_handler()
void register_TI_handler |
( |
void(*)() |
callback | ) |
|
Register a timer callback.
The callback will be used when the timer interrupt is triggered by the CPU. This happens when the COP0 COUNT register reaches the same value of the COP0 COMPARE register.
This function is useful only if you want to do your own low level programming of the internal CPU timer and handle the interrupt yourself. In this case, also remember to activate the timer interrupt using set_TI_interrupt.
- Note
- If you use the timer library (timer_init and new_timer), you do not need to call this function, as timer interrupt are already handled by the timer library.
- Parameters
-
[in] | callback | Function to call when a timer interrupt occurs |
◆ unregister_TI_handler()
void unregister_TI_handler |
( |
void(*)() |
callback | ) |
|
Unregister a timer callback.
- Note
- If you use the timer library (timer_init and new_timer), you do not need to call this function, as timer interrupt are already handled by the timer library.
- Parameters
-
[in] | callback | Function that should no longer be called on timer interrupts |
◆ register_CART_handler()
void register_CART_handler |
( |
void(*)() |
callback | ) |
|
Register a CART interrupt callback.
The callback will be called when a CART interrupt is triggered. CART interrupts are interrupts triggered by devices attached to the PI bus (aka CART bus), for instance the 64DD, or the modem cassette.
CART interrupts are disabled by default in libdragon. Use set_CART_interrupt to enable/disable them.
Notice that there is no generic way to acknowledge those interrupts, so if you activate CART interrupts, make also sure to register an handler that acknowledge them, otherwise the interrupt will deadlock the console.
- Parameters
-
[in] | callback | Function that should no longer be called on CART interrupts |
◆ unregister_CART_handler()
void unregister_CART_handler |
( |
void(*)() |
callback | ) |
|
Unregister a CART interrupt callback.
- Parameters
-
[in] | callback | Function that should no longer be called on CART interrupts |
◆ set_AI_interrupt()
void set_AI_interrupt |
( |
int |
active | ) |
|
Enable or disable the AI interrupt.
- Parameters
-
[in] | active | Flag to specify whether the AI interrupt should be active |
◆ set_VI_interrupt()
void set_VI_interrupt |
( |
int |
active, |
|
|
unsigned long |
line |
|
) |
| |
Enable or disable the VI interrupt.
- Parameters
-
[in] | active | Flag to specify whether the VI interrupt should be active |
[in] | line | The vertical line that causes this interrupt to fire. Ignored when setting the interrupt inactive |
◆ set_PI_interrupt()
void set_PI_interrupt |
( |
int |
active | ) |
|
Enable or disable the PI interrupt.
- Parameters
-
[in] | active | Flag to specify whether the PI interrupt should be active |
◆ set_DP_interrupt()
void set_DP_interrupt |
( |
int |
active | ) |
|
Enable or disable the DP interrupt.
- Parameters
-
[in] | active | Flag to specify whether the DP interrupt should be active |
◆ set_SI_interrupt()
void set_SI_interrupt |
( |
int |
active | ) |
|
Enable or disable the SI interrupt.
- Parameters
-
[in] | active | Flag to specify whether the SI interrupt should be active |
◆ set_SP_interrupt()
void set_SP_interrupt |
( |
int |
active | ) |
|
Enable or disable the SP interrupt.
- Parameters
-
[in] | active | Flag to specify whether the SP interrupt should be active |
◆ set_TI_interrupt()
void set_TI_interrupt |
( |
int |
active | ) |
|
Enable the timer interrupt.
- Note
- If you use the timer library (timer_init and new_timer), you do not need to call this function, as timer interrupt is already handled by the timer library.
- Parameters
-
[in] | active | Flag to specify whether the timer interrupt should be active |
- See also
- register_TI_handler
◆ set_CART_interrupt()
void set_CART_interrupt |
( |
int |
active | ) |
|
Enable the CART interrupt.
- Parameters
-
[in] | active | Flag to specify whether the CART interrupt should be active |
- See also
- register_CART_handler
◆ disable_interrupts()
void disable_interrupts |
( |
| ) |
|
Disable interrupts systemwide.
- Note
- If interrupts are already disabled on the system or interrupts have not been initialized, this function will not modify the system state.
◆ enable_interrupts()
void enable_interrupts |
( |
| ) |
|
Enable interrupts systemwide.
- Note
- If this is called inside a nested disable call, it will have no effect on the system. Therefore it is safe to nest disable/enable calls. After the last nested interrupt is enabled, systemwide interrupts will be reenabled.
◆ get_interrupts_state()
Return the current state of interrupts.
- Return values
-
INTERRUPTS_UNINITIALIZED | if the interrupt system has not been initialized yet. |
INTERRUPTS_DISABLED | if interrupts have been disabled for some reason. |
INTERRUPTS_ENABLED | if interrupts are currently enabled. |
◆ interrupt_disabled_tick
uint32_t interrupt_disabled_tick = 0 |
tick at which interrupts were disabled.
Time at which interrupts were disabled.