====== Writing interrupt handlers ======
===== C interrupt handlers =====
For less performance-sensitive interrupts (such as the vertical blank interrupt), it is possible to write the relevant handlers using only C. This is done by marking the interrupt function with special attributes:
__attribute__((assume_ss_data, interrupt))
void __far vblank_int_handler(void) {
vbl_ticks++;
// Acknowledge the hardware interrupt.
ws_hwint_ack(HWINT_VBLANK);
}
These mean the following:
* ''%%__far%%'' - This function is always a "far" call. This is required for interrupt functions - while all functions are "far" calls by default on ''wswan/medium'', this is not true on other subtargets.
* ''interrupt'' - This function is an interrupt. This ensures it saves/restores all registers and that it uses ''IRET'' to return from the function.
* ''assume_ss_data'' - This function can assume that ''SS'' points to the default data segment when it is called. This assumption holds true throughout the Wonderful toolchain's default libraries. However, beware that any assembler code which modifies the location of the stack segment ''SS'' must ensure that an interrupt function with this attribute is never called during its execution.
===== Configuring interrupt handlers =====
libws provides useful functions for configuring interrupt handlers:
// Set the function "vblank_int_handler" to run during vertical blank.
ws_hwint_set_handler(HWINT_IDX_VBLANK, (ws_int_handler_t) vblank_int_handler);
// Enable the vertical blank hardware interrupt.
ws_hwint_enable(HWINT_VBLANK);
// Disable the vertical blank hardware interrupt.
ws_hwint_disable(HWINT_VBLANK);
Watch out! ''ws_hwint_set_handler'' expects a ''HWINT_IDX'' parameter, while most other ''ws_hwint'' operations - ''enable'', ''disable'', ''ack'' - expect a ''HWINT'' parameter.
I admit, this is a little confusing. ^^;