From aad0bc2f0974ad2da70c0a572e3e84dd6793cb41 Mon Sep 17 00:00:00 2001 From: Cuyler36 Date: Sat, 29 Apr 2023 08:04:22 -0400 Subject: [PATCH 1/3] Implement irqmgr --- config/rel_slices.yml | 4 + include/dolphin/os/OSTimer.h | 1 + include/irqmgr.h | 24 +++- include/libultra/os_thread.h | 18 +++ rel/irqmgr.c | 217 +++++++++++++++++++++++++++++++++++ 5 files changed, 261 insertions(+), 3 deletions(-) create mode 100644 include/libultra/os_thread.h create mode 100644 rel/irqmgr.c diff --git a/config/rel_slices.yml b/config/rel_slices.yml index 745039a7..35e58d8e 100644 --- a/config/rel_slices.yml +++ b/config/rel_slices.yml @@ -52,6 +52,10 @@ graph.c: .text: [0x80405518, 0x80405EC8] .data: [0x8065ECA8, 0x8065ECB0] .bss: [0x812F31E8, 0x812F3560] +#irqmgr.c: +# .text: [0x80405EC8, 0x80406480] +# .data: [0x8065ECB0, 0x8065ECD0] +# .bss: [0x812F3560, 0x812F4CB0] lb_rtc.c: .text: [0x80406480, 0x8040752C] .rodata: [0x806436F8, 0x806437A0] diff --git a/include/dolphin/os/OSTimer.h b/include/dolphin/os/OSTimer.h index a45137ec..e1ec2433 100644 --- a/include/dolphin/os/OSTimer.h +++ b/include/dolphin/os/OSTimer.h @@ -5,6 +5,7 @@ #include "types.h" #include "dolphin/os/OSAlarm.h" +#include "dolphin/os/OSMessage.h" #ifdef __cplusplus extern "C" { diff --git a/include/irqmgr.h b/include/irqmgr.h index 92030758..d4ca499e 100644 --- a/include/irqmgr.h +++ b/include/irqmgr.h @@ -4,6 +4,7 @@ #include "types.h" #include "dolphin/os/OSTime.h" #include "dolphin/os/OSTimer.h" +#include "dolphin/os/OSMessage.h" #ifdef __cplusplus extern "C" { @@ -31,16 +32,33 @@ typedef struct { irqmgr_mesg_t msgDelayPreNMI; OSMessageQueue _msgQueue; OSMessage _msgBuf[IRQMGR_MESSAGES_MAX]; - OSThread thread; - irqmgr_client_t* clients; - u8 prenmi; + + union { + OSThread thread; + struct { + u8 unused[sizeof(OSThread) - 2 * sizeof(void*)]; + irqmgr_client_t* clients; + u8 prenmi; + }; + }; + OSTime prenmi_time; OSTimer timer; OSTime retraceTime; } irqmgr_t; +extern void irqmgr_AddClient(irqmgr_client_t* client, OSMessageQueue* msgqueue); +/* @unused extern void irqmgr_RemoveClient(irqmgr_client_t* client) */ +extern void CreateIRQManager(void* stack, size_t stack_size, int priority, u8 retracecount); + +/* probably declared in os_vi.h */ +extern void osViSetEvent(OSMessageQueue* mesgq, OSMessage msg, u32 retcount); + extern volatile int ResetStatus; extern volatile OSTime ResetTime; +extern volatile OSTime RetraceTime; +extern volatile int RetraceCount; +extern irqmgr_t irqmgr_class; #ifdef __cplusplus }; diff --git a/include/libultra/os_thread.h b/include/libultra/os_thread.h new file mode 100644 index 00000000..3c21805f --- /dev/null +++ b/include/libultra/os_thread.h @@ -0,0 +1,18 @@ +#ifndef LIBULTRA_OS_THREAD_H +#define LIBULTRA_OS_THREAD_H + +#include "types.h" +#include "dolphin/os/OSThread.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern void osCreateThread2(OSThread* t, int id, void(*entry)(void*), void* arg, void* stack_pointer, size_t stack_size, OSPriority priority); +extern void osStartThread(OSThread* t); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/rel/irqmgr.c b/rel/irqmgr.c new file mode 100644 index 00000000..17785fc2 --- /dev/null +++ b/rel/irqmgr.c @@ -0,0 +1,217 @@ +#include "irqmgr.h" +#include "libultra/os_thread.h" +#include "dolphin/os.h" +#include "dolphin/os/OSMessage.h" +#include "dolphin/os/OSTime.h" + +#define MSEC(x) OSMicrosecondsToTicks((x) * (OSTime)1000) + +volatile int ResetStatus; // 0x00 +volatile OSTime ResetTime; // 0x08 +volatile OSTime RetraceTime; // 0x10 +volatile int RetraceCount; // 0x18 +static irqmgr_t* this; // 0x1C +irqmgr_t irqmgr_class; + +#define IRQ_RETRACE_MSG 666 +#define IRQ_PRENMI_MSG 669 +#define IRQ_PRENMI450_MSG 671 +#define IRQ_PRENMI480_MSG 672 +#define IRQ_PRENMI500_MSG 673 + +/** + * @brief Adds anew client to the IRQ manager with a callback message queue. + * + * @param client The new client to add + * @param msgqueue The callback message queue + **/ +extern void irqmgr_AddClient(irqmgr_client_t* client, OSMessageQueue* msgqueue) { + BOOL enable = OSDisableInterrupts(); + client->msgQueue = msgqueue; + client->next = this->clients; + this->clients = client; + OSRestoreInterrupts(enable); + + if (this->prenmi >= 1) { + osSendMesg(client->msgQueue, &this->msgPreNMI, 0); + } + if (this->prenmi >= 2) { + osSendMesg(client->msgQueue, &this->msgDelayPreNMI, 0); + } +} + +/* @unused extern void irqmgr_RemoveClient(irqmgr_client_t* client) */ + +/** + * @brief Sends a new message to all active IRQ clients. + * + * @param msg The message which will be sent + **/ +static void irqmgr_SendMesgForClient(irqmgr_mesg_t* msg) { + irqmgr_client_t* i; + OSMessageQueue* mesgq; + for (i = this->clients; i != NULL; i = i->next) { + mesgq = i->msgQueue; + if (mesgq->usedCount < mesgq->msgCount) { + osSendMesg(mesgq, msg, 0); + } + } +} + +/** + * @brief Sends a new message to all active IRQ clients. Duplicate of above. + * + * @param msg The message which will be sent + **/ +static void irqmgr_JamMesgForClient(irqmgr_mesg_t* msg) { + irqmgr_client_t* i; + OSMessageQueue* mesgq; + for (i = this->clients; i != NULL; i = i->next) { + mesgq = i->msgQueue; + if (mesgq->usedCount < mesgq->msgCount) { + osSendMesg(mesgq, msg, 0); + } + } +} + +#pragma pool_data on +/** + * @brief Handler function for pre-NMI message. + **/ +static void irqmgr_HandlePreNMI() { + ResetStatus = 1; + this->prenmi = 1; + ResetTime = this->prenmi_time = osGetTime(); + + osSetTimer(&this->timer, MSEC(400), 0, &this->_msgQueue, (OSMessage)IRQ_PRENMI450_MSG); + irqmgr_JamMesgForClient(&this->msgPreNMI); +} +#pragma pool_data reset + +/** + * @brief Handler for pre-NMI message (post 400ms). + **/ +static void irqmgr_HandlePreNMI450() { + ResetStatus = 2; + this->prenmi = 2; + osSetTimer(&this->timer, MSEC(50), 0, &this->_msgQueue, (OSMessage)IRQ_PRENMI480_MSG); + irqmgr_SendMesgForClient(&this->msgDelayPreNMI); +} + +/** + * @brief Handler for pre-NMI message (post 450ms). + **/ +static void irqmgr_HandlePreNMI480() { + osSetTimer(&this->timer, MSEC(50), 0, &this->_msgQueue, (OSMessage)IRQ_PRENMI500_MSG); +} + +/** + * @brief Handler for pre-NMI message (post 500ms). + **/ +static void irqmgr_HandlePreNMI500() {} + +#pragma pool_data on +/** + * @brief Handler for retrace message. + **/ +static void irqmgr_HandleRetrace() { + OSTime time; + if (RetraceTime == 0) { + if (this->retraceTime == 0) { + time = osGetTime(); + this->retraceTime = time; + } + else { + time = osGetTime(); + RetraceTime = time - this->retraceTime; + } + } + RetraceCount++; + irqmgr_SendMesgForClient(&this->msgRetrace); +} +#pragma pool_data reset + +/** + * @brief Main IRQ manager handler. + * + * @param arg unused OSThread func arg + **/ +static void irqmgr_Main(void* arg) { + OSMessage msg = (OSMessage)0; + + while (TRUE) { + osRecvMesg(&this->_msgQueue, &msg, 1); + switch ((u32)msg) { + case IRQ_RETRACE_MSG: + irqmgr_HandleRetrace(); + break; + case IRQ_PRENMI_MSG: + irqmgr_HandlePreNMI(); + break; + case IRQ_PRENMI450_MSG: + irqmgr_HandlePreNMI450(); + break; + case IRQ_PRENMI480_MSG: + irqmgr_HandlePreNMI480(); + break; + case IRQ_PRENMI500_MSG: + irqmgr_HandlePreNMI500(); + break; + default: + break; + } + } +} + +/** + * @brief Creates a new IRQ manager. + * + * @param stack The IRQ manager's stack + * @param stack_size The IRQ manager's stack size + * @param priority The thread's priority + * @param retracecount Taken by osViSetEvent, unused + **/ +extern void CreateIRQManager(void* stack, size_t stack_size, int priority, u8 retracecount) { + this = &irqmgr_class; + this->clients = NULL; + this->msgRetrace.type = 1; + this->msgPreNMI.type = 4; + this->msgDelayPreNMI.type = 3; + this->prenmi = 0; + this->prenmi_time = 0; + + osCreateMesgQueue(&this->_msgQueue, this->_msgBuf, 8); + osViSetEvent(&this->_msgQueue, (OSMessage)IRQ_RETRACE_MSG, retracecount); + osCreateThread2(&this->thread, 9, irqmgr_Main, NULL, stack, stack_size, priority); + osStartThread(&this->thread); +} + +/* these were probably written in a header directly and included here */ + +#define VI_STACK_SIZE 0x1000 + +static OSMessage vc_msg; +static OSMessageQueue* vc_msgq; +static u16 vc_retraceCount; +static u16 retrace; /* this probably belongs in one of the unused vi functions below */ +static u8 viThreadStack[VI_STACK_SIZE]; +static OSThread viThread; + +/* @unused ? viMgrMain(?) */ + +/* @unused ? osCreateViManager(?) */ + +#pragma pool_data on +/** + * @brief Sets the VI event info. Stubbed outside this functionality. + * + * @param msgq The OSMessageQueue which would be notified upon event invocation + * @param msg The OSMessage which would be sent upon event invocation + * @param retcount The retrace count before invoking the event + **/ +extern void osViSetEvent(OSMessageQueue* mesgq, OSMessage msg, u32 retcount) { + vc_msgq = mesgq; + vc_msg = msg; + vc_retraceCount = retcount; +} +#pragma pool_data reset From d099c2d3874a5b11a86a5ed3c363e78ec29bee80 Mon Sep 17 00:00:00 2001 From: Cuyler36 Date: Sat, 29 Apr 2023 08:21:36 -0400 Subject: [PATCH 2/3] Add missing headers --- config/rel_slices.yml | 8 ++++---- include/libultra/osMesg.h | 11 ++++++++--- include/libultra/os_timer.h | 18 ++++++++++++++++++ rel/irqmgr.c | 3 +++ 4 files changed, 33 insertions(+), 7 deletions(-) create mode 100644 include/libultra/os_timer.h diff --git a/config/rel_slices.yml b/config/rel_slices.yml index 35e58d8e..8071945b 100644 --- a/config/rel_slices.yml +++ b/config/rel_slices.yml @@ -52,10 +52,10 @@ graph.c: .text: [0x80405518, 0x80405EC8] .data: [0x8065ECA8, 0x8065ECB0] .bss: [0x812F31E8, 0x812F3560] -#irqmgr.c: -# .text: [0x80405EC8, 0x80406480] -# .data: [0x8065ECB0, 0x8065ECD0] -# .bss: [0x812F3560, 0x812F4CB0] +irqmgr.c: + .text: [0x80405EC8, 0x80406480] + .data: [0x8065ECB0, 0x8065ECD0] + .bss: [0x812F3560, 0x812F4CB0] lb_rtc.c: .text: [0x80406480, 0x8040752C] .rodata: [0x806436F8, 0x806437A0] diff --git a/include/libultra/osMesg.h b/include/libultra/osMesg.h index d2b960ed..d7241fa6 100644 --- a/include/libultra/osMesg.h +++ b/include/libultra/osMesg.h @@ -3,16 +3,21 @@ #include "types.h" #include "dolphin/os/OSThread.h" +#include "dolphin/os/OSMessage.h" typedef void* OSMesg; typedef struct OSMesgQueue { /* 0x00 */ OSThread* mtqueue; /* 0x04 */ OSThread* fullqueue; - /* 0x08 */ s32 validCount; - /* 0x0C */ s32 first; - /* 0x10 */ s32 msgCount; + /* 0x08 */ int validCount; + /* 0x0C */ int first; + /* 0x10 */ int msgCount; /* 0x14 */ OSMesg* msg; } OSMesgQueue; // size = 0x18 +extern void osCreateMesgQueue(OSMessageQueue* mq ,OSMessage msg, int flags); +extern int osSendMesg(OSMessageQueue* mq, OSMessage msg, int flags); +extern int osRecvMesg(OSMessageQueue* mq, OSMessage msg, int flags); + #endif diff --git a/include/libultra/os_timer.h b/include/libultra/os_timer.h new file mode 100644 index 00000000..4c7580a6 --- /dev/null +++ b/include/libultra/os_timer.h @@ -0,0 +1,18 @@ +#ifndef LIBULTRA_OS_TIMER_H +#define LIBULTRA_OS_TIMER_H + +#include "types.h" +#include "dolphin/os/OSTimer.h" +#include "dolphin/os/OSMessage.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern int osSetTimer(OSTimer* t, OSTime countdown, OSTime interval, OSMessageQueue* mq, OSMessage msg); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/rel/irqmgr.c b/rel/irqmgr.c index 17785fc2..32f137bd 100644 --- a/rel/irqmgr.c +++ b/rel/irqmgr.c @@ -1,5 +1,8 @@ #include "irqmgr.h" #include "libultra/os_thread.h" +#include "libultra/libultra.h" +#include "libultra/os_timer.h" +#include "libultra/osMesg.h" #include "dolphin/os.h" #include "dolphin/os/OSMessage.h" #include "dolphin/os/OSTime.h" From f678127ffaa163ae5487e6a0e89ac4c3c9001ff1 Mon Sep 17 00:00:00 2001 From: Cuyler36 Date: Sat, 29 Apr 2023 08:28:32 -0400 Subject: [PATCH 3/3] Get irqmgr matching --- config/rel_slices.yml | 8 ++++---- include/libultra/os_timer.h | 1 + rel/irqmgr.c | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/config/rel_slices.yml b/config/rel_slices.yml index 8071945b..35e58d8e 100644 --- a/config/rel_slices.yml +++ b/config/rel_slices.yml @@ -52,10 +52,10 @@ graph.c: .text: [0x80405518, 0x80405EC8] .data: [0x8065ECA8, 0x8065ECB0] .bss: [0x812F31E8, 0x812F3560] -irqmgr.c: - .text: [0x80405EC8, 0x80406480] - .data: [0x8065ECB0, 0x8065ECD0] - .bss: [0x812F3560, 0x812F4CB0] +#irqmgr.c: +# .text: [0x80405EC8, 0x80406480] +# .data: [0x8065ECB0, 0x8065ECD0] +# .bss: [0x812F3560, 0x812F4CB0] lb_rtc.c: .text: [0x80406480, 0x8040752C] .rodata: [0x806436F8, 0x806437A0] diff --git a/include/libultra/os_timer.h b/include/libultra/os_timer.h index 4c7580a6..78ee4515 100644 --- a/include/libultra/os_timer.h +++ b/include/libultra/os_timer.h @@ -2,6 +2,7 @@ #define LIBULTRA_OS_TIMER_H #include "types.h" +#include "dolphin/os/OSTime.h" #include "dolphin/os/OSTimer.h" #include "dolphin/os/OSMessage.h" diff --git a/rel/irqmgr.c b/rel/irqmgr.c index 32f137bd..6aa65f26 100644 --- a/rel/irqmgr.c +++ b/rel/irqmgr.c @@ -7,7 +7,7 @@ #include "dolphin/os/OSMessage.h" #include "dolphin/os/OSTime.h" -#define MSEC(x) OSMicrosecondsToTicks((x) * (OSTime)1000) +#define MSEC(x) OSMicrosecondsToTicks(((u64)(x)) * (u64)1000) volatile int ResetStatus; // 0x00 volatile OSTime ResetTime; // 0x08