diff --git a/board/fxcg50/fxcg50.ld b/board/fxcg50/fxcg50.ld index 1f6c1ea..6f941a3 100644 --- a/board/fxcg50/fxcg50.ld +++ b/board/fxcg50/fxcg50.ld @@ -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 diff --git a/board/fxcg50/hypervisor.c b/board/fxcg50/hypervisor.c index d33eb4d..4deff5a 100644 --- a/board/fxcg50/hypervisor.c +++ b/board/fxcg50/hypervisor.c @@ -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 */ diff --git a/include/vhex/defs/call.h b/include/vhex/defs/call.h new file mode 100644 index 0000000..50e0d54 --- /dev/null +++ b/include/vhex/defs/call.h @@ -0,0 +1,96 @@ +#ifndef __VHEX_DEFS_CALL__ +# define __VHEX_DEFS_CALL__ + +#include + +/* 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__ */ diff --git a/include/vhex/dma.h b/include/vhex/dma.h new file mode 100644 index 0000000..8624aa6 --- /dev/null +++ b/include/vhex/dma.h @@ -0,0 +1,22 @@ +#ifndef __VHEX_DMA__ +# define __VHEX_DMA__ + +#include + +/* 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__ */ diff --git a/include/vhex/dma/interface.h b/include/vhex/dma/interface.h new file mode 100644 index 0000000..68fe8fc --- /dev/null +++ b/include/vhex/dma/interface.h @@ -0,0 +1,13 @@ +#ifndef __VHEX_DMA_INTERFACE__ +# define __VHEX_DMA_INTERFACE__ + +#include + +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__ */ diff --git a/include/vhex/dma/types.h b/include/vhex/dma/types.h new file mode 100644 index 0000000..e853fe0 --- /dev/null +++ b/include/vhex/dma/types.h @@ -0,0 +1,8 @@ +#ifndef __VHEX_DMA_TYPES__ +# define __VHEX_DMA_TYPES__ + +#include + +typedef uint32_t dma_id_t; + +#endif /* __VHEX_DMA_TYPES__ */ diff --git a/include/vhex/driver/mpu/sh/sh7305/dma.h b/include/vhex/driver/mpu/sh/sh7305/dma.h new file mode 100644 index 0000000..65b09e0 --- /dev/null +++ b/include/vhex/driver/mpu/sh/sh7305/dma.h @@ -0,0 +1,100 @@ +#ifndef __VHEX_DRIVER_MPU_SH_SH7305_DMA__ +# define __VHEX_DRIVER_MPU_SH_SH7305_DMA__ + +#include +#include + +//--- +// 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__ */ diff --git a/include/vhex/driver/mpu/sh/sh7305/intc.h b/include/vhex/driver/mpu/sh/sh7305/intc.h index c8a7d90..dcfb3eb 100644 --- a/include/vhex/driver/mpu/sh/sh7305/intc.h +++ b/include/vhex/driver/mpu/sh/sh7305/intc.h @@ -3,6 +3,7 @@ #include #include +#include /* 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__ */ diff --git a/include/vhex/driver/mpu/sh/sh7305/keysc.h b/include/vhex/driver/mpu/sh/sh7305/keysc.h index cb86700..dd25280 100644 --- a/include/vhex/driver/mpu/sh/sh7305/keysc.h +++ b/include/vhex/driver/mpu/sh/sh7305/keysc.h @@ -77,7 +77,7 @@ struct __sh7305_keysc_s // Internal API //--- -#include +#include /* sh7305_keycache_init() : initialise the keycache information */ extern void sh7305_keycache_init(void); diff --git a/include/vhex/driver/mpu/sh/sh7305/rtc.h b/include/vhex/driver/mpu/sh/sh7305/rtc.h index 245a602..c53af87 100644 --- a/include/vhex/driver/mpu/sh/sh7305/rtc.h +++ b/include/vhex/driver/mpu/sh/sh7305/rtc.h @@ -3,6 +3,7 @@ #include #include +#include //--- // 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 diff --git a/include/vhex/driver/mpu/sh/sh7305/tmu.h b/include/vhex/driver/mpu/sh/sh7305/tmu.h index e41348c..acf909b 100644 --- a/include/vhex/driver/mpu/sh/sh7305/tmu.h +++ b/include/vhex/driver/mpu/sh/sh7305/tmu.h @@ -3,6 +3,7 @@ #include #include +#include /* 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); diff --git a/include/vhex/keyboard/keycode.h b/include/vhex/keyboard/keycode.h index b093991..cb61fd3 100644 --- a/include/vhex/keyboard/keycode.h +++ b/include/vhex/keyboard/keycode.h @@ -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__ */ diff --git a/include/vhex/keyboard/keydown.h b/include/vhex/keyboard/keydown.h index cd03bf6..b544312 100644 --- a/include/vhex/keyboard/keydown.h +++ b/include/vhex/keyboard/keydown.h @@ -2,6 +2,7 @@ # define __VHEX_KEYBOARD_KEYDOWN__ #include +#include //--- // Key state functions diff --git a/include/vhex/keyboard/types.h b/include/vhex/keyboard/types.h index f6d4e89..604e5a3 100644 --- a/include/vhex/keyboard/types.h +++ b/include/vhex/keyboard/types.h @@ -4,8 +4,6 @@ #include #include -#include - /* 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__ */ diff --git a/include/vhex/timer.h b/include/vhex/timer.h index aa6136c..a3713b9 100644 --- a/include/vhex/timer.h +++ b/include/vhex/timer.h @@ -1,7 +1,7 @@ #ifndef __VHEX_TIMER__ #define __VHEX_TIMER__ -#include +#include #include /* 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 diff --git a/include/vhex/timer/call.h b/include/vhex/timer/call.h deleted file mode 100644 index ebcc960..0000000 --- a/include/vhex/timer/call.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef __VHEX_TIMER_CALL__ -# define __VHEX_TIMER_CALL__ - -#include - -/* 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__ */ diff --git a/include/vhex/timer/interface.h b/include/vhex/timer/interface.h index 7fbbea4..e48237b 100644 --- a/include/vhex/timer/interface.h +++ b/include/vhex/timer/interface.h @@ -1,7 +1,7 @@ #ifndef __VHEX_TIMER_INTERFACE__ # define __VHEX_TIMER_INTERFACE__ -#include +#include #include #include @@ -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); diff --git a/src/dma/dma.c b/src/dma/dma.c new file mode 100644 index 0000000..740788e --- /dev/null +++ b/src/dma/dma.c @@ -0,0 +1,44 @@ +#include +#include +#include +#include + +#include + +/* 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); diff --git a/src/dma/memcpy.c b/src/dma/memcpy.c new file mode 100644 index 0000000..89d5d70 --- /dev/null +++ b/src/dma/memcpy.c @@ -0,0 +1,15 @@ +#include +#include + +/* 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; +} diff --git a/src/dma/memset.c b/src/dma/memset.c new file mode 100644 index 0000000..6fba87c --- /dev/null +++ b/src/dma/memset.c @@ -0,0 +1,15 @@ +#include +#include + +/* 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; +} diff --git a/src/dma/wait.c b/src/dma/wait.c new file mode 100644 index 0000000..fa1fd1e --- /dev/null +++ b/src/dma/wait.c @@ -0,0 +1,15 @@ +#include +#include + +/* 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; +} diff --git a/src/driver/mpu/sh/sh7305/dma/dma.c b/src/driver/mpu/sh/sh7305/dma/dma.c new file mode 100644 index 0000000..0f811ea --- /dev/null +++ b/src/driver/mpu/sh/sh7305/dma/dma.c @@ -0,0 +1,160 @@ +#include +#include +//#include +#include +#include + +#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 diff --git a/src/driver/mpu/sh/sh7305/dma/memcpy.c b/src/driver/mpu/sh/sh7305/dma/memcpy.c new file mode 100644 index 0000000..93f2cec --- /dev/null +++ b/src/driver/mpu/sh/sh7305/dma/memcpy.c @@ -0,0 +1,9 @@ +#include + +/* 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; +} diff --git a/src/driver/mpu/sh/sh7305/dma/memset.c b/src/driver/mpu/sh/sh7305/dma/memset.c new file mode 100644 index 0000000..7399646 --- /dev/null +++ b/src/driver/mpu/sh/sh7305/dma/memset.c @@ -0,0 +1,9 @@ +#include + +/* 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; +} diff --git a/src/driver/mpu/sh/sh7305/intc/intc.c b/src/driver/mpu/sh/sh7305/intc/intc.c index 1e48fc3..454c855 100644 --- a/src/driver/mpu/sh/sh7305/intc/intc.c +++ b/src/driver/mpu/sh/sh7305/intc/intc.c @@ -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; } diff --git a/src/driver/mpu/sh/sh7305/intc/inth.S b/src/driver/mpu/sh/sh7305/intc/inth.S index 2893e23..61b198c 100644 --- a/src/driver/mpu/sh/sh7305/intc/inth.S +++ b/src/driver/mpu/sh/sh7305/intc/inth.S @@ -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 */ diff --git a/src/driver/mpu/sh/sh7305/intc/inth_generic.S b/src/driver/mpu/sh/sh7305/intc/inth_generic.S new file mode 100644 index 0000000..5ce18bc --- /dev/null +++ b/src/driver/mpu/sh/sh7305/intc/inth_generic.S @@ -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) */ diff --git a/src/driver/mpu/sh/sh7305/keysc/keycache.c b/src/driver/mpu/sh/sh7305/keysc/keycache.c index fbd22b8..4ef5afa 100644 --- a/src/driver/mpu/sh/sh7305/keysc/keycache.c +++ b/src/driver/mpu/sh/sh7305/keysc/keycache.c @@ -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); diff --git a/src/driver/mpu/sh/sh7305/keysc/keysc.c b/src/driver/mpu/sh/sh7305/keysc/keysc.c index d593cad..e80620e 100644 --- a/src/driver/mpu/sh/sh7305/keysc/keysc.c +++ b/src/driver/mpu/sh/sh7305/keysc/keysc.c @@ -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 */ diff --git a/src/driver/mpu/sh/sh7305/rtc/rtc.c b/src/driver/mpu/sh/sh7305/rtc/rtc.c index 05a8d61..104521d 100644 --- a/src/driver/mpu/sh/sh7305/rtc/rtc.c +++ b/src/driver/mpu/sh/sh7305/rtc/rtc.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -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 */ diff --git a/src/driver/mpu/sh/sh7305/tmu/tmu.c b/src/driver/mpu/sh/sh7305/tmu/tmu.c index 09bd32c..9f79ff4 100644 --- a/src/driver/mpu/sh/sh7305/tmu/tmu.c +++ b/src/driver/mpu/sh/sh7305/tmu/tmu.c @@ -12,7 +12,7 @@ #include /* 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; diff --git a/src/driver/screen/R61524/r61524.c b/src/driver/screen/R61524/r61524.c index e898a6d..2851a3b 100644 --- a/src/driver/screen/R61524/r61524.c +++ b/src/driver/screen/R61524/r61524.c @@ -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); } diff --git a/src/keyboard/keyboard.c b/src/keyboard/keyboard.c index 02bac79..eaba131 100644 --- a/src/keyboard/keyboard.c +++ b/src/keyboard/keyboard.c @@ -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); diff --git a/src/keyboard/keycache.c b/src/keyboard/keycache.c index 26b29d3..18b9097 100644 --- a/src/keyboard/keycache.c +++ b/src/keyboard/keycache.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include diff --git a/src/timer/timer.c b/src/timer/timer.c index f9c0292..51d6dd9 100644 --- a/src/timer/timer.c +++ b/src/timer/timer.c @@ -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);