intc: allow any call in intc_handler_function()

This commit is contained in:
Lephe 2021-04-28 17:37:40 +02:00
parent 0233088565
commit 42081c9968
No known key found for this signature in database
GPG key ID: 1BBA026E13FC0495
5 changed files with 19 additions and 28 deletions

View file

@ -6,6 +6,7 @@
#define GINT_INTC
#include <gint/defs/types.h>
#include <gint/defs/call.h>
//---
// Interrupt names
@ -120,7 +121,7 @@ void *intc_handler(int event_code, void const *handler, size_t size);
/* intc_handler_function(): Install a function as an interrupt handler
This function can be used to install simple interrupt handlers. It installs
a pre-written interrupt handler that calls back the provided function.
a pre-written interrupt handler that performs the provided indirect call.
Essentially it means that the interrupt handler can be written in C without
the numerous constraints of intc_handler(), at the cost of always going back
to userspace and a small time overhead.
@ -128,6 +129,6 @@ void *intc_handler(int event_code, void const *handler, size_t size);
@event_code Identifier of the interrupt block
@function Function to use as a handler
Returns true on success, false if the event code is invalid. */
bool intc_handler_function(int event_code, void (*function)(void));
bool intc_handler_function(int event_code, gint_call_t function);
#endif /* GINT_INTC */

View file

@ -1,3 +1,5 @@
#include <gint/intc.h>
#include <gint/gint.h>
#include <gint/drivers.h>
#include <gint/drivers/states.h>
#include <gint/hardware.h>
@ -170,15 +172,17 @@ void *intc_handler(int event_code, const void *handler, size_t size)
return memcpy(dest, handler, size);
}
bool intc_handler_function(int event_code, void (*function)(void))
bool intc_handler_function(int event_code, gint_call_t function)
{
/* Install the genric handler */
/* Install the generic handler */
extern void intc_generic_handler(void);
void *h = intc_handler(event_code, intc_generic_handler, 32);
if(!h) return false;
/* Set the function to be called */
*(void **)(h + 24) = function;
/* Copy the call */
memcpy(h + 8, &function, 20);
/* Copy the runtime address of gint_inth_callback() */
*(void **)(h + 28) = gint_inth_callback;
return true;
}

View file

@ -10,24 +10,10 @@
.align 4
_intc_generic_handler:
/* Create a GINT_CALL() object with no arguments */
sts.l pr, @-r15
add #-20, r15
mov.l .function, r0
mov.l r0, @r15
mova 1f, r0
mov.l 2f, r1
jmp @r1
mov r0, r4
/* Call back to the function in userspace */
mov.l .gint_inth_callback, r0
mov.l @r0, r0
jsr @r0
mov r15, r4
add #20, r15
lds.l @r15+, pr
rts
nop
.function:
.long 0 /* Function, set when handler is installed */
.gint_inth_callback:
.long _gint_inth_callback
1: .zero 20 /* Indirect call to be made */
2: .long 0 /* Address of _gint_inth_callback at runtime */

View file

@ -164,7 +164,7 @@ static void configure(void)
RTC->RCR2.PEF = 0;
/* Install the RTC interrupt handler */
intc_handler_function(0xaa0, rtc_periodic_interrupt);
intc_handler_function(0xaa0, GINT_CALL(rtc_periodic_interrupt));
/* Disable the RTC interrupts for now. Give them priority 1; higher
priorities cause freezes when going back to the system on SH3

View file

@ -169,7 +169,7 @@ int usb_open(usb_interface_t const **interfaces, gint_call_t callback)
USB.NRDYENB.word = 0x0000;
USB.BEMPENB.word = 0x0000;
intc_handler_function(0xa20, usb_interrupt_handler);
intc_handler_function(0xa20, GINT_CALL(usb_interrupt_handler));
intc_priority(INTC_USB, 15);
usb_open_status = true;