VxKernel 0.6.0-18 : Add Vhex indirect call + prepare DMA driver

@add
<> vhex/defs/call
  | add common `vhex_call_t` which allow indirect call invocation
  | add default helper macros to generate internal struct
  | add default helper macros to involve manually the vhex call
<> vhex/dma
  | add DMA user-level API
  | add DMA user-level types
  | add DNA driver-level interface
<> vhex/driver/mpu/sh/sh7305
  | [dma] add hardware definition
  | [dma] prepare DMA driver definition (WIP)
  | [dma] add DMA driver declaration (WIP)
  | [dma] prepare DMA primitives     (WIP)
<> src/dma
  | wrap the DMA driver
  | expose the DMA user-level API
  | expose the DMA module

@update
<> board/fxcg50/fxcg50.ld
  | expose the two VRAM for the future frame render which use the triple
     buffering. For now, this method add ~347ko in the generated ELF, but it's a
     temporary.
<> driver/mpu/sh/sh7305
  | [intc] rename some kernel-level function
  | [intc] use the new vhex call mechanism instead of timer-specific indirect call
  | [intc] update the generic interrupt handler installation
  | [intc] isolate the generic interrupt handler
  | [rtc] use the new vhex call mechanism instead of rtc-specific indirect call
  | [keysc] use the new vhex call mechanism

@fix
<> src
  | [keyboard] fix key_t type definition
  | [keyboard] fix the driver priority
  | [timer] fix the driver priority
This commit is contained in:
Yann MAGNIN 2022-08-11 19:21:02 +02:00
parent e8e63016d5
commit 7e01fb8444
35 changed files with 602 additions and 109 deletions

View File

@ -111,6 +111,21 @@ SECTIONS
/* dynamic BSS information (move me ?) */
*(.dynbss)
/* Video RAM symbols
The Video RAM contains a full pixel sized frame for the
screen. Its size is 396x224 and each pixel depth is 16bits,
so (3996 * 224) * 2 = 177408
Thus, we use a double buffering methods to speed-up the
render, this is why we define two VRAM */
_vhex_vram0 = ALIGN(32);
. = _vhex_vram0 + 177408;
_vhex_vram1 = ALIGN(32);
. = _vhex_vram1 + 177408;
} > userram
/* Vhex VBR management geometry

View File

@ -7,7 +7,6 @@ void hypervisor_init(void)
hyp_world_t vhex = hypervisor_world_new("vhex");
hypervisor_world_switch(casio, vhex);
}
/* hypervisor_quit() : quit the hypervisor module */

96
include/vhex/defs/call.h Normal file
View File

@ -0,0 +1,96 @@
#ifndef __VHEX_DEFS_CALL__
# define __VHEX_DEFS_CALL__
#include <vhex/defs/types.h>
/* vhex_call_arg_t: All types of arguments allowed in an indirect call
Because a function call cannot be easily pieced together, there are
restrictions on what arguments can be passed. The following union lists all
of the available types. Other types can be used if casted, mainly pointers;
see the description of VHEX_CALL() for details. */
typedef union {
/* 32-bit integers */
int i;
unsigned int u;
int32_t i32;
uint32_t u32;
/* 32-bit floating-point */
float f;
/* Pointers to most common types, in all possible const/volatile
qualifications */
#define POINTER(type, name) \
type *name; \
type const *name ## _c; \
type volatile *name ## _v; \
type volatile const *name ## _cv;
POINTER(void, pv)
POINTER(char, pc)
POINTER(unsigned char, puc)
POINTER(short, ps)
POINTER(unsigned short, pus)
POINTER(int, pi)
POINTER(unsigned int, pui)
POINTER(int8_t, pi8)
POINTER(uint8_t, pu8)
POINTER(int16_t, pi16)
POINTER(uint16_t, pu16)
POINTER(int32_t, pi32)
POINTER(uint32_t, pu32)
POINTER(int64_t, pi64)
POINTER(uint64_t, pu64)
POINTER(long long int, pll)
POINTER(unsigned long long int, pull)
POINTER(float, pf)
POINTER(double, pd)
#undef POINTER
} vhex_call_arg_t;
/* vhex_call_t: Indirect call with up to 4 register arguments */
struct vhex_call {
void *function;
vhex_call_arg_t args[4];
};
typedef struct vhex_call vhex_call_t;
/* VHEX_CALL(): Build an callback from function and arguments */
#define VHEX_CALL(fct, ...) \
(vhex_call_t){ \
.function = (void*)fct, \
.args = { __VA_OPT__(VHEX_CALL_ARGS1(__VA_ARGS__)) } \
}
#define VHEX_CALL_ARGS1(a1, ...) \
(vhex_call_arg_t)(a1), __VA_OPT__(VHEX_CALL_ARGS2(__VA_ARGS__))
#define VHEX_CALL_ARGS2(a2, ...) \
(vhex_call_arg_t)(a2), __VA_OPT__(VHEX_CALL_ARGS3(__VA_ARGS__))
#define VHEX_CALL_ARGS3(a3, ...) \
(vhex_call_arg_t)(a3), __VA_OPT__(VHEX_CALL_ARGS4(__VA_ARGS__))
#define VHEX_CALL_ARGS4(a4, ...) \
({ \
__VA_OPT__( \
_Static_assert( \
0, \ \
"VHEX_CALL: too many arguments (maximum 4)" \
); \
) \
(vhex_call_arg_t)(a4); \
})
/* VHEX_CALL_NULL: Empty function call */
#define VHEX_CALL_NULL ((vhex_call_t){ .function = NULL, .args = {} })
/* vhex_call(): Perform an indirect call */
static VINLINE int vhex_call(vhex_call_t callback)
{
return ((int(*)(int r4, int r5, int r6, int r7))callback.function)(
callback.args[0].i,
callback.args[1].i,
callback.args[2].i,
callback.args[3].i
);
}
#endif /* __VHEX_DEFS_CALL__ */

22
include/vhex/dma.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef __VHEX_DMA__
# define __VHEX_DMA__
#include <vhex/dma/types.h>
/* dma_memcpy() : memcpy-like using the DMA
As set in the short function description, we use the DMA transfert to perform
the copy which allow us to do other things in parallele.
This function act like memcpy except that it will not return the destination
address but the dma ID that should be used to wait the end of the transfert
afterwards. */
extern dma_id_t dma_memcpy(void * restrict dst, void * restrict src, size_t sz);
/* dma_memset() : memset using the DMA */
extern dma_id_t dma_memset(void *dst, int c, size_t sz);
/* dma_wait() : wait dma transfert end (dma_memset or dma_memcpy) */
extern int dma_wait(dma_id_t id);
#endif /* __VHEX_DMA__ */

View File

@ -0,0 +1,13 @@
#ifndef __VHEX_DMA_INTERFACE__
# define __VHEX_DMA_INTERFACE__
#include <vhex/dma/types.h>
struct dma_drv_interface
{
dma_id_t (*dma_memcpy)(void * restrict, void * restrict, size_t);
dma_id_t (*dma_memset)(void * restrict, int, size_t);
int (*dma_wait)(dma_id_t);
};
#endif /* __VHEX_DMA_INTERFACE__ */

8
include/vhex/dma/types.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef __VHEX_DMA_TYPES__
# define __VHEX_DMA_TYPES__
#include <vhex/defs/types.h>
typedef uint32_t dma_id_t;
#endif /* __VHEX_DMA_TYPES__ */

View File

@ -0,0 +1,100 @@
#ifndef __VHEX_DRIVER_MPU_SH_SH7305_DMA__
# define __VHEX_DRIVER_MPU_SH_SH7305_DMA__
#include <vhex/defs/attributes.h>
#include <vhex/defs/types.h>
//---
// SH7305 Direct Memory Access Controller. Refer to:
// "Renesas SH7724 User's Manual: Hardware"
// Section 16: "Direct Memory Access Controller (DMAC)"
//
// However, there is some (minor) differencies with the DMA controller of
// the SH7305. Mainly, only the first channel have special features that
// other don't.
//---
/* sh7305_dma_channel_t - One of the main 6 channels of the DMA
Note that the many settings are only available on channels 0 to 3 (denoted
by [0..3]) or on channels 0 (denoted by [0]).
The documentation is apparently wrong about the placement is TS[3:2], the
neighboring read-only bit must be swapped before TS[3:2]. */
struct __sh7305_dma_channel
{
uint32_t SAR;
uint32_t DAR;
/* Mind that the 8 upper bits should always be written as 0 */
uint32_t TCR;
lword_union(CHCR,
uint32_t :1;
uint32_t LCKN :1; /* Bus Right Release Enable */
uint32_t :2;
uint32_t RPT :3; /* Repeat setting [0..3] */
uint32_t DA :1; /* DREQ Asynchronous [0] */
uint32_t DO :1; /* DMA Overrun [0] */
uint32_t :1;
uint32_t TS3 :1; /* Transfer Size (bit3) */
uint32_t TS2 :1; /* Transfer Size (bit2) */
uint32_t HE :1; /* Half-End flag [0..3] */
uint32_t HIE :1; /* Half-end Interrupt Enable [0..3] */
uint32_t AM :1; /* Acknowledge mode [0] */
uint32_t AL :1; /* Acknowledge level [0] */
uint32_t DM :2; /* Destination address Mode */
uint32_t SM :2; /* Source address Mode */
uint32_t RS :4; /* Resource Select */
uint32_t DL :1; /* DREQ Level [0] */
uint32_t DS :1; /* DREQ Source select[0] */
uint32_t TB :1; /* Transfer Bus Mode */
uint32_t TS1 :1; /* Transfer Size (bit1) */
uint32_t TS0 :1; /* Transfer Size (bit0) */
uint32_t IE :1; /* Interrupt Enable */
uint32_t TE :1; /* Transfer End flag */
uint32_t DE :1; /* DMA Enable */
);
} VPACKED(4);
/* sh7305_dma_t - DMA Controller */
struct __sh7305_dma
{
struct __sh7305_dma_channel DMA0;
struct __sh7305_dma_channel DMA1;
struct __sh7305_dma_channel DMA2;
struct __sh7305_dma_channel DMA3;
word_union(DMAOR,
uint16_t CMS :4; /* Cycle steal Mode Select */
uint16_t :2;
uint16_t PR :2; /* PRiority mode */
uint16_t :4;
uint16_t :1;
uint16_t AE :1; /* Address Error flag */
uint16_t NMIF :1; /* NMI Flag */
uint16_t DME :1; /* DMA Master Enable */
);
pad(14);
struct __sh7305_dma_channel DMA4;
struct __sh7305_dma_channel DMA5;
} VPACKED(4);
#define SH7305_DMA (*((volatile struct __sh7305_dma *)0xfe008020))
#endif /* __VHEX_DRIVER_MPU_SH_SH7305_DMA__ */

View File

@ -3,6 +3,7 @@
#include <vhex/defs/attributes.h>
#include <vhex/defs/types.h>
#include <vhex/defs/call.h>
/* sh7305_intc_ipc - Interrupt Priority Controller
Some of the fields have been left unnamed because they correspond to SH7724
@ -460,12 +461,12 @@ enum {
//---
/* sh7305_intc_install_inth() : install interrupt gate */
extern void *sh7305_intc_install_inth(int blockid, void *gate, size_t size);
extern void *sh7305_intc_install_inth_gate(int blockid, void *gate, size_t size);
/* sh7305_intc_priority() : set the interrupt name priority */
extern int sh7305_intc_priority(int intname, int level);
/* sh7305_intc_generic_handler() : install generic interrupt handler */
extern void *sh7305_intc_generic_handler(int event_code, void *user_inth);
extern void *sh7305_intc_install_inth_generic(int event_code, vhex_call_t cb);
#endif /* __VHEX_ARCH_SH7305_INTC__ */

View File

@ -77,7 +77,7 @@ struct __sh7305_keysc_s
// Internal API
//---
#include <vhex/keyboard.h>
#include <vhex/keyboard/types.h>
/* sh7305_keycache_init() : initialise the keycache information */
extern void sh7305_keycache_init(void);

View File

@ -3,6 +3,7 @@
#include <vhex/defs/attributes.h>
#include <vhex/defs/types.h>
#include <vhex/defs/call.h>
//---
// Hybrid SH7705-SH7305 Real-Time Clock. Refer to:
@ -98,19 +99,6 @@ enum
RTC_NONE = 0,
};
/* rtc_call: Indirect call with up to 4 register arguments */
struct rtc_call {
void *function;
uint32_t args[4];
};
/* RTC_CALL(): Build an callback from function and arguments */
#define RTC_CALL(fct, ...) \
(struct rtc_call){ \
.function = (void*)fct, \
.args = { __VA_ARGS__ } \
}
/* rtc_periodic_enable(): Enable the periodic interrupt
This function sets up the periodic interrupt to invoke the provided callback
@ -124,7 +112,7 @@ struct rtc_call {
@frequency Periodic interrupt frequency
@callback Function to call back at the specified frequency
Returns true on success, false if the interrupt is already in use. */
extern bool sh7305_rtc_periodic_enable(int frequency, struct rtc_call callback);
extern bool sh7305_rtc_periodic_enable(int frequency, vhex_call_t callback);
/* rtc_periodic_disable(): Stop the periodic interrupt

View File

@ -3,6 +3,7 @@
#include <vhex/defs/attributes.h>
#include <vhex/defs/types.h>
#include <vhex/defs/call.h>
/* Clock input
@ -92,7 +93,7 @@ typedef volatile etmu_t sh7305_etmu_t[6];
extern tid_t sh7305_tmu_reserve(uint64_t delay);
/* sh7305_tmu_configure() : configure timer */
extern tid_t sh7305_tmu_configure(uint64_t delay, timer_call_t call);
extern tid_t sh7305_tmu_configure(uint64_t delay, vhex_call_t callback);
/* sh7305_tmu_start() - start a configured timer */
extern int sh7305_tmu_start(tid_t id);

View File

@ -1,14 +1,12 @@
#ifndef __VHEX_KEYBOARD_KEYCODE__
# define __VHEX_KEYBOARD_KEYCODE__
/* KEYSCODE_GEN() : generate keycode */
#define KEYCODE_GEN(row, column) \
(((row & 0x0f) << 4) | ((column & 0x0f) << 0))
/* key_t : Define all keycode */
typedef enum key_e
/* Define all keycode */
enum
{
KEY_F1 = 0x41,
KEY_F2 = 0x42,
@ -70,6 +68,6 @@ typedef enum key_e
KEY_UNUSED = 0xff,
KEY_NONE = 0xfe,
} key_t;
};
#endif /* __VHEX_KEYBOARD_KEYCODE__ */

View File

@ -2,6 +2,7 @@
# define __VHEX_KEYBOARD_KEYDOWN__
#include <vhex/keyboard/types.h>
#include <vhex/keyboard/keycode.h>
//---
// Key state functions

View File

@ -4,8 +4,6 @@
#include <vhex/defs/types.h>
#include <vhex/defs/attributes.h>
#include <vhex/keyboard/keycode.h>
/* key_event_t: Low-level or high-level keyboard event
This structure represents an event that occurs on the keyboard. It is first
@ -56,5 +54,7 @@ enum
KEYEV_REP_NEXT = 2,
};
/* keyboard key */
typedef int key_t;
#endif /* __VHEX_KEYBOARD_TYPES__ */

View File

@ -1,7 +1,7 @@
#ifndef __VHEX_TIMER__
#define __VHEX_TIMER__
#include <vhex/timer/call.h>
#include <vhex/defs/call.h>
#include <vhex/timer/types.h>
/* TIMER_DELAY_MS() : convert ms into us */
@ -25,7 +25,7 @@ enum {
the supplied callback function at the end of this delay. The callback
function can then decide whether to leave the timer running (and be called
again after the same delay) or stop the timer. */
extern tid_t timer_configure(uint64_t delay_us, timer_call_t callback);
extern tid_t timer_configure(uint64_t delay_us, vhex_call_t callback);
/* timer_reserve() : reserve a timer

View File

@ -1,20 +0,0 @@
#ifndef __VHEX_TIMER_CALL__
# define __VHEX_TIMER_CALL__
#include <vhex/defs/types.h>
/* timer_call_t: Indirect call with up to 4 register arguments */
struct timer_call {
void *function;
uint32_t args[4];
};
typedef struct timer_call timer_call_t;
/* TIMER_CALL(): Build an callback from function and arguments */
#define TIMER_CALL(fct, ...) \
(timer_call_t){ \
.function = (void*)fct, \
.args = { __VA_ARGS__ } \
}
#endif /* __VHEX_TIMER_CALL__ */

View File

@ -1,7 +1,7 @@
#ifndef __VHEX_TIMER_INTERFACE__
# define __VHEX_TIMER_INTERFACE__
#include <vhex/timer/call.h>
#include <vhex/defs/call.h>
#include <vhex/timer/types.h>
#include <vhex/timer/fps.h>
@ -10,7 +10,7 @@ struct timer_drv_interface
{
/* timer API */
tid_t (*timer_reserve)(uint64_t delay_us);
tid_t (*timer_configure)(uint64_t delay_us, timer_call_t callback);
tid_t (*timer_configure)(uint64_t delay_us, vhex_call_t callback);
int (*timer_start)(tid_t timer);
int (*timer_pause)(tid_t timer);
int (*timer_stop)(tid_t timer);

44
src/dma/dma.c Normal file
View File

@ -0,0 +1,44 @@
#include <vhex/dma/interface.h>
#include <vhex/dma.h>
#include <vhex/module.h>
#include <vhex/driver.h>
#include <string.h>
/* internal timer information */
struct {
struct dma_drv_interface driver;
} dma_info;
/* __dma_init() : initialize the DMA module */
static void __dma_init(void)
{
memset(&dma_info, 0x00, sizeof(dma_info));
struct vhex_driver *driver = vhex_driver_table();
for (int i = 0; i < vhex_driver_count(); ++i) {
if (driver[i].flags.DMA) {
memcpy(
&rtc_info.driver,
driver[i].module_data,
sizeof(struct dma_drv_interface)
);
break;
}
}
}
/* __dma_quit() : uninitialize the DMA module */
static void __dma_quit(void)
{
;
}
/* declare the timer module */
struct vhex_module mod_rtc = {
.name = "DMA",
.init = &__dma_init,
.quit = &__dma_quit,
};
VHEX_DECLARE_MODULE(04, mod_dma);

15
src/dma/memcpy.c Normal file
View File

@ -0,0 +1,15 @@
#include <vhex/dma/interface.h>
#include <vhex/dma.h>
/* internal driver information */
extern struct {
struct dma_drv_interface driver;
} dma_info;
/* dma_memcpy() : memcpy using DMA */
dma_id_t dma_memcpy(void * restrict dst, void * restrict src, size_t sz)
{
if (dma_info.driver.dma_memcpy != NULL)
return dma_info.driver.dma_memcpy(dst, src, sz);
return -1;
}

15
src/dma/memset.c Normal file
View File

@ -0,0 +1,15 @@
#include <vhex/dma/interface.h>
#include <vhex/dma.h>
/* internal driver information */
extern struct {
struct dma_drv_interface driver;
} dma_info;
/* dma_memcpy() : memcpy using DMA */
dma_id_t dma_memset(void * restrict dst, int c, size_t sz)
{
if (dma_info.driver.dma_memset != NULL)
return dma_info.driver.dma_memset(dst, c, sz);
return -1;
}

15
src/dma/wait.c Normal file
View File

@ -0,0 +1,15 @@
#include <vhex/dma/interface.h>
#include <vhex/dma.h>
/* internal driver information */
extern struct {
struct dma_drv_interface driver;
} dma_info;
/* dma_memcpy() : memcpy using DMA */
int dma_wait(dma_id_t id)
{
if (dma_info.driver.dma_wait != NULL)
return dma_info.driver.dma_wait(id);
return -1;
}

View File

@ -0,0 +1,160 @@
#include <vhex/driver/mpu/sh/sh7305/dma.h>
#include <vhex/driver/mpu/sh/sh7305/intc.h>
//#include <vhex/driver/mpu/sh/sh7305/power.h>
#include <vhex/driver.h>
#include <vhex/defs/call.h>
#define DMA SH7305_DMA
//#define POWER SH7305_POWER
typedef volatile struct __sh7305_dma_channel channel_t;
//---
// Driver public API
//---
static channel_t *sh7305_dma_channel(int channel)
{
if (channel < 0 || channel >= 6)
return NULL;
return (channel_t *[6]){
&DMA.DMA0, &DMA.DMA1, &DMA.DMA2,
&DMA.DMA3, &DMA.DMA4, &DMA.DMA5,
}[channel];
}
static void sh7305_dma_spinwait(channel_t *ch)
{
(void)ch;
}
//---
// Kernel-level API
//---
/* Interrupt handler for all finished DMA transfers */
static void sh7305_dma_interrupt_transfer_ended(channel_t *ch)
{
(void)ch;
}
//---
// Declare driver
//---
//FIXME: avoid manualy sync DMAOR with header o(x_x)o
struct dma_ctx {
channel_t ch[6];
word_union(DMAOR,
uint16_t CMS :4; /* Cycle steal Mode Select */
uint16_t :2;
uint16_t PR :2; /* PRiority mode */
uint16_t :4;
uint16_t :1;
uint16_t AE :1; /* Address Error flag */
uint16_t NMIF :1; /* NMI Flag */
uint16_t DME :1; /* DMA Master Enable */
);
};
/* __dma_configure() : configure the DMA */
static void __dma_configure(struct dma_ctx *s)
{
extern void sh7305_dma_inth_te(void);
extern void sh7305_dma_inth_ae(void);
int codes[] = { 0x800, 0x820, 0x840, 0x860, 0xb80, 0xba0 };
for(int i = 0; i < 6; i++)
{
sh7305_intc_install_inth_generic(
codes[i],
VHEX_CALL(
sh7305_dma_interrupt_transfer_ended,
(void*)sh7305_dma_channel(i)
)
);
s->ch[i].SAR = 0x00000000;
s->ch[i].DAR = 0x00000000;
s->ch[i].TCR = 0x00000000;
s->ch[i].CHCR.DE = 0;
}
/* Configure the DMA operations
<> select normal cycle steal mode
<> select "normal" priority (CH0->CH1->CH2->...)
<> clear address error flags
<> clear NMIF flags
<> enable the master switch */
s->DMAOR.CMS = 0b0000;
s->DMAOR.PR = 0b00;
s->DMAOR.AE = 0;
s->DMAOR.NMIF = 0;
s->DMAOR.DME = 1;
/* Install Address Error interrupt gate */
sh7305_intc_install_inth_gate(0xbc0, sh7305_dma_inth_ae, 32);
/* Set interrupt priority to 3, except for the channels that are
used by the USB driver (channel 0) */
sh7305_intc_priority(INTC_DMA_DEI0, 9);
sh7305_intc_priority(INTC_DMA_DEI1, 3);
sh7305_intc_priority(INTC_DMA_DEI2, 3);
sh7305_intc_priority(INTC_DMA_DEI3, 3);
sh7305_intc_priority(INTC_DMA_DEI4, 3);
sh7305_intc_priority(INTC_DMA_DEI5, 3);
sh7305_intc_priority(INTC_DMA_DADERR, 3);
}
/* __rtc_hsave() : save hardware information */
static void __dma_hsave(struct dma_ctx *s)
{
for(int i = 0; i < 6; i++) {
channel_t *ch = sh7305_dma_channel(i);
sh7305_dma_spinwait(ch);
ch->SAR = s->ch[i].SAR;
ch->DAR = s->ch[i].DAR;
ch->TCR = s->ch[i].TCR;
ch->CHCR.lword = s->ch[i].CHCR.lword;
}
DMA.DMAOR.word = s->DMAOR.word;
}
/* __dma_hrestore() : restore hardware information */
static void __dma_hrestore(struct dma_ctx *s)
{
DMA.DMAOR.DME = 0;
for(int i = 0; i < 6; i++)
{
channel_t *ch = sh7305_dma_channel(i);
ch->SAR = s->ch[i].SAR;
ch->DAR = s->ch[i].DAR;
ch->TCR = s->ch[i].TCR;
ch->CHCR.lword = s->ch[i].CHCR.lword;
}
DMA.DMAOR.word = s->DMAOR.word;
}
#if 0
struct vhex_driver drv_rtc = {
.name = "DMA",
.hsave = (void*)&__dma_hsave,
.hrestore = (void*)&__dma_hrestore,
.configure = (void*)&__dma_configure,
.state_size = sizeof(struct dma_ctx),
.flags = {
.DMA = 1,
.SHARED = 0,
.UNUSED = 0,
},
};
VHEX_DECLARE_DRIVER(05, drv_dma);
#endif

View File

@ -0,0 +1,9 @@
#include <vhex/dma.h>
/* dma_memcpy() : memcpy using DMA */
dma_id_t sh7305_dma_memcpy(void * restrict dst, void * restrict src, size_t sz)
{
(void)dst;
(void)src;
(void)sz;
}

View File

@ -0,0 +1,9 @@
#include <vhex/dma.h>
/* dma_memset() : memset using the DMA */
dma_id_t sh7305_dma_memset(void *dst, int c, size_t sz)
{
(void)dst;
(void)c;
(void)sz;
}

View File

@ -109,7 +109,7 @@ int sh7305_intc_priority(int intname, int level)
}
/* sh7305_intc_install_inth() : install interrupt gate */
void *sh7305_intc_install_inth(int event_code, void *gate, size_t size)
void *sh7305_intc_install_inth_gate(int event_code, void *gate, size_t size)
{
extern uintptr_t vhex_vbr;
@ -121,18 +121,21 @@ void *sh7305_intc_install_inth(int event_code, void *gate, size_t size)
}
/* sh7305_intc_generic_handler() : install generic interrupt handler */
void *sh7305_intc_generic_handler(int event_code, void *user_inth)
void *sh7305_intc_install_inth_generic(int event_code, vhex_call_t callback)
{
extern void vhex_sh7305_intc_generic_handler(void);
extern void sh7305_intc_inth_generic_gate(void);
extern void sh7305_inth_callback(void);
void *h = sh7305_intc_install_inth(
uint8_t *h = sh7305_intc_install_inth_gate(
event_code,
sh7305_intc_generic_handler,
sh7305_intc_inth_generic_gate,
32
);
if(!h) return false;
if(h == NULL)
return false;
*(void **)(h + 28) = user_inth;
memcpy(&h[8], &callback, 20);
memcpy(&h[28], &sh7305_inth_callback, 4);
return h;
}

View File

@ -65,22 +65,3 @@ _vhex_inth_sh7305:
1: .long 0xff000028
.first_entry:
/* _vhex_sh7305_intc_generic_handler: Standard interrupt handler
This is a generic interrupt handler that calls back into a C function,
useful for complex handling or simple drivers that benefit more from
simplicity than razor-sharp performance. */
.section .vhex.blocks, "ax"
.align 4
.global _vhex_sh7305_intc_generic_handler /* 32 bytes */
_vhex_sh7305_intc_generic_handler:
mov.l 1f, r1
jmp @r1
mov r0, r4
.zero 22 /* Indirect call to be made */
1: .long 0 /* Address of the runtime */

View File

@ -0,0 +1,19 @@
/* _sh7305_intc_generic_handler_fate: Standard interrupt handler
This is a generic interrupt handler that calls back into a C function,
useful for complex handling or simple drivers that benefit more from
simplicity than razor-sharp performance. */
.section .vhex.blocks, "ax"
.align 4
.global _sh7305_intc_inth_generic_gate /* 32 bytes */
_sh7305_intc_inth_generic_gate:
mova 1f, r0
mov.l 2f, r1
jmp @r1
mov r0, r4
1: .zero 20 /* Indirect call to be made (set at runtine) */
2: .long 0 /* _sh7305_vhex_inth_callback (set at runtime) */

View File

@ -48,9 +48,9 @@ void sh7305_keycache_init(void)
keyinfo.timer.id = sh7305_tmu_configure(
7215,
TIMER_CALL(
VHEX_CALL(
&__sh7305_keycache_keyframe,
(uintptr_t)&keyinfo.timer.counter
&keyinfo.timer.counter
)
);
sh7305_tmu_start(keyinfo.timer.id);

View File

@ -83,7 +83,7 @@ static void __keysc_configure(struct keysc_ctx *ctx)
/* intall the KEYSC interupt handler */
extern void sh7305_keysc_inth(void);
sh7305_intc_install_inth(0xbe0, &sh7305_keysc_inth, 64);
sh7305_intc_install_inth_gate(0xbe0, &sh7305_keysc_inth, 64);
}
/* __keysc_hsave() : save hardware information */

View File

@ -1,6 +1,7 @@
#include <vhex/driver/mpu/sh/sh7305/rtc.h>
#include <vhex/driver/mpu/sh/sh7305/intc.h>
#include <vhex/rtc/interface.h>
#include <vhex/defs/call.h>
#include <vhex/driver.h>
#include <string.h>
@ -9,24 +10,12 @@
// RTC periodic interrupt
//---
static struct rtc_call rtc_call;
static vhex_call_t rtc_call;
/* rtc_periodic interrupt() : internal interrupt handler */
static void sh7305_rtc_periodic_inth(void)
{
int (*routine)(
uintptr_t,
uintptr_t,
uintptr_t,
uintptr_t
) = rtc_call.function;
int rc = routine(
rtc_call.args[0],
rtc_call.args[1],
rtc_call.args[2],
rtc_call.args[3]
);
int rc = vhex_call(rtc_call);
/* Clear the interrupt flag */
do SH7305_RTC.RCR2.PEF = 0;
@ -37,7 +26,7 @@ static void sh7305_rtc_periodic_inth(void)
}
/* rtc_periodic_enable(): Enable the periodic interrupt */
bool sh7305_rtc_periodic_enable(int frequency, struct rtc_call callback)
bool sh7305_rtc_periodic_enable(int frequency, vhex_call_t callback)
{
/* Refuse to override an existing interrupt */
if(SH7305_RTC.RCR2.PES != RTC_NONE) return false;
@ -49,7 +38,7 @@ bool sh7305_rtc_periodic_enable(int frequency, struct rtc_call callback)
/* Temporarily disable the interrupt and set up the callback */
SH7305_RTC.RCR2.PES = RTC_NONE;
memcpy(&rtc_call, &callback, sizeof(struct rtc_call));
memcpy(&rtc_call, &callback, sizeof(vhex_call_t));
/* Clear the interrupt flag */
do SH7305_RTC.RCR2.PEF = 0;
@ -99,7 +88,10 @@ static void __rtc_configure(struct rtc_ctx *state)
sh7305_intc_priority(INTC_RTC_PRI, 1);
/* intall the RTC interupt handler */
sh7305_intc_generic_handler(0xaa0, &sh7305_rtc_periodic_inth);
sh7305_intc_install_inth_generic(
0xaa0,
VHEX_CALL(&sh7305_rtc_periodic_inth)
);
}
/* __rtc_hsave() : save hardware information */

View File

@ -12,7 +12,7 @@
#include <string.h>
/* Callbacks for all timers */
timer_call_t sh7305_tmu_callbacks[9];
vhex_call_t sh7305_tmu_callbacks[9];
/* Arrays of standard and extra timers */
tmu_t *TMU = SH7305_TMU.TMU;
@ -84,7 +84,7 @@ static tid_t reserve(tid_t id, uint32_t delay, int clock)
}
/* conf(): Configure a fixed timer */
static tid_t conf(tid_t id, timer_call_t call)
static tid_t conf(tid_t id, vhex_call_t call)
{
if(id < 3) {
/* Refuse to setup timers that are already in use */
@ -200,14 +200,14 @@ tid_t sh7305_tmu_reserve(uint64_t delay)
}
/* sh7305_tmu_configure() : configure timer */
tid_t sh7305_tmu_configure(uint64_t delay, timer_call_t call)
tid_t sh7305_tmu_configure(uint64_t delay, vhex_call_t call)
{
tid_t timer = sh7305_tmu_reserve(delay);
if (timer < 0)
return -1;
if(call.function == NULL)
call = TIMER_CALL(&stop_callback);
call = VHEX_CALL(&stop_callback);
return conf(timer, call);
}
@ -498,7 +498,7 @@ static void __tmu_configure(struct tmu_ctx *s)
/* install the TMUs interupt handler */
extern uint32_t sh7305_inth_tmu;
sh7305_intc_install_inth(0x400, &sh7305_inth_tmu, 96);
sh7305_intc_install_inth_gate(0x400, &sh7305_inth_tmu, 96);
/* install all ETMUx interrupt handler
@ -517,7 +517,7 @@ static void __tmu_configure(struct tmu_ctx *s)
void *h;
uint16_t etmu_evt[6] = { 0x9e0, 0xc20, 0xc40, 0x900, 0xd00, 0xfa0 };
h4 = sh7305_intc_install_inth(etmu_evt[4], &sh7305_inth_etmu4, 96);
h4 = sh7305_intc_install_inth_gate(etmu_evt[4], &sh7305_inth_etmu4, 96);
for (int i = 0; i < 6; ++i) {
/* skip the core ETMUx core handler */
@ -525,7 +525,11 @@ static void __tmu_configure(struct tmu_ctx *s)
continue;
/* install the default interrupt handler */
h = sh7305_intc_install_inth(etmu_evt[i], &sh7305_inth_etmux, 32);
h = sh7305_intc_install_inth_gate(
etmu_evt[i],
&sh7305_inth_etmux,
32
);
/* Timer ID, used for sh7305_tmu_stop() after the callback */
*(uint16_t *)(h + 16) = i + 3;

View File

@ -7,7 +7,11 @@
// R61524 driver API
//---
uint32_t vhex_vram[396*(224/2)];
/* defined by the linker script */
extern uint32_t vhex_vram0;
extern uint32_t vhex_vram1;
static uint32_t *vhex_vram = &vhex_vram0;
/* r61524_frame_start() - prepar the screen and reset surfaces */
VALIGNED(4) int r61524_frame_start(dsurface_t *surface)
@ -33,15 +37,15 @@ VALIGNED(4) int r61524_frame_start(dsurface_t *surface)
/* initialize surface information */
// surface->vram = (void*)0xe5017000;
// surface->width = 396;
// surface->height = 10;
surface->vram = (void*)vhex_vram;
surface->width = 396;
surface->height = 224;
// surface->height = 10;
surface->x1 = 0;
surface->y1 = 0;
surface->x2 = 395;
surface->y2 = 223;
// surface->y2 = 9;
return (0);
}

View File

@ -23,4 +23,4 @@ struct vhex_module mod_keyboard = {
.init = &__keyboard_init,
.quit = &__keyboard_quit,
};
VHEX_DECLARE_MODULE(04, mod_keyboard);
VHEX_DECLARE_MODULE(05, mod_keyboard);

View File

@ -1,5 +1,6 @@
#include <vhex/keyboard.h>
#include <vhex/keyboard/interface.h>
#include <vhex/keyboard/keycode.h>
#include <vhex/driver/cpu.h>
#include <vhex/timer.h>
#include <vhex/driver.h>

View File

@ -23,7 +23,7 @@ tid_t timer_reserve(uint64_t delay_us)
}
/* timer_configure(): Reserve and configure a timer */
tid_t timer_configure(uint64_t delay_us, timer_call_t callback)
tid_t timer_configure(uint64_t delay_us, vhex_call_t callback)
{
if (timer_info.driver.timer_configure != NULL)
return (timer_info.driver.timer_configure(delay_us, callback));
@ -118,4 +118,4 @@ struct vhex_module mod_timer = {
.init = &__timer_init,
.quit = &__timer_quit,
};
VHEX_DECLARE_MODULE(02, mod_timer);
VHEX_DECLARE_MODULE(04, mod_timer);