1
0
Fork 0
mirror of https://github.com/zeldaret/oot.git synced 2024-11-14 21:40:03 +00:00
oot/src/code/irqmgr.c

230 lines
7.9 KiB
C
Raw Normal View History

2020-03-17 04:31:30 +00:00
#include <global.h>
#include <vt.h>
volatile u32 gIrqMgrResetStatus = 0;
volatile OSTime sIrqMgrResetTime = 0;
volatile OSTime sIrqMgrRetraceTime = 0;
u32 sIrqMgrRetraceCount = 0;
2020-03-22 21:19:43 +00:00
#define RETRACE_MSG 666
#define PRE_NMI_MSG 669
#define PRENMI450_MSG 671
#define PRENMI480_MSG 672
#define PRENMI500_MSG 673
#define STATUS_IDLE 0
#define STATUS_PRENMI 1
#define STATUS_NMI 2
void IrqMgr_AddClient(IrqMgr* this, IrqMgrClient* c, OSMesgQueue* msgQ) {
2020-03-17 04:31:30 +00:00
u32 prevMask;
LogUtils_CheckNullPointer("this", this, "../irqmgr.c", 96);
LogUtils_CheckNullPointer("c", c, "../irqmgr.c", 97);
LogUtils_CheckNullPointer("msgQ", msgQ, "../irqmgr.c", 98);
prevMask = osSetIntMask(1);
c->queue = msgQ;
c->prev = this->clients;
this->clients = c;
osSetIntMask(prevMask);
2020-03-22 21:19:43 +00:00
if (this->resetStatus > STATUS_IDLE) {
osSendMesg(c->queue, (OSMesg) & this->prenmiMsg, OS_MESG_NOBLOCK);
}
2020-03-17 04:31:30 +00:00
2020-03-22 21:19:43 +00:00
if (this->resetStatus >= STATUS_NMI) {
osSendMesg(c->queue, (OSMesg) & this->nmiMsg, OS_MESG_NOBLOCK);
}
2020-03-17 04:31:30 +00:00
}
2020-03-22 21:19:43 +00:00
void IrqMgr_RemoveClient(IrqMgr* this, IrqMgrClient* c) {
2020-03-17 04:31:30 +00:00
IrqMgrClient* iter;
IrqMgrClient* lastIter;
u32 prevMask;
iter = this->clients;
lastIter = NULL;
LogUtils_CheckNullPointer("this", this, "../irqmgr.c", 129);
LogUtils_CheckNullPointer("c", c, "../irqmgr.c", 130);
2020-03-22 21:19:43 +00:00
2020-03-17 04:31:30 +00:00
prevMask = osSetIntMask(1);
2020-03-22 21:19:43 +00:00
while (iter) {
if (iter == c) {
if (lastIter) {
2020-03-17 04:31:30 +00:00
lastIter->prev = c->prev;
2020-03-22 21:19:43 +00:00
} else {
2020-03-17 04:31:30 +00:00
this->clients = c->prev;
2020-03-22 21:19:43 +00:00
}
2020-03-17 04:31:30 +00:00
break;
}
lastIter = iter;
iter = iter->prev;
}
osSetIntMask(prevMask);
}
2020-03-22 21:19:43 +00:00
void IrqMgr_SendMesgForClient(IrqMgr* this, OSMesg msg) {
2020-03-17 04:31:30 +00:00
IrqMgrClient* iter;
iter = this->clients;
2020-03-22 21:19:43 +00:00
while (iter) {
if (iter->queue->validCount >= iter->queue->msgCount) {
// irqmgr_SendMesgForClient: Message queue is overflowing mq=%08x cnt=%d
osSyncPrintf(
VT_COL(RED, WHITE) "irqmgr_SendMesgForClient:メッセージキューがあふれています mq=%08x cnt=%d\n" VT_RST,
iter->queue, iter->queue->validCount);
} else {
2020-03-17 04:31:30 +00:00
osSendMesg(iter->queue, msg, OS_MESG_NOBLOCK);
2020-03-22 21:19:43 +00:00
}
2020-03-17 04:31:30 +00:00
iter = iter->prev;
}
}
2020-03-22 21:19:43 +00:00
void IrqMgr_JamMesgForClient(IrqMgr* this, OSMesg msg) {
2020-03-17 04:31:30 +00:00
IrqMgrClient* iter;
iter = this->clients;
2020-03-22 21:19:43 +00:00
while (iter) {
if (iter->queue->validCount >= iter->queue->msgCount) {
// irqmgr_JamMesgForClient: Message queue is overflowing mq=%08x cnt=%d
osSyncPrintf(
VT_COL(RED, WHITE) "irqmgr_JamMesgForClient:メッセージキューがあふれています mq=%08x cnt=%d\n" VT_RST,
iter->queue, iter->queue->validCount);
} else {
// mistake? the function's name suggests it would use osJamMesg
2020-03-17 04:31:30 +00:00
osSendMesg(iter->queue, msg, OS_MESG_NOBLOCK);
2020-03-22 21:19:43 +00:00
}
2020-03-17 04:31:30 +00:00
iter = iter->prev;
}
}
2020-03-22 21:19:43 +00:00
void IrqMgr_HandlePreNMI(IrqMgr* this) {
u64 temp = STATUS_PRENMI; // required to match
2020-03-17 04:31:30 +00:00
gIrqMgrResetStatus = temp;
this->resetStatus = STATUS_PRENMI;
sIrqMgrResetTime = this->resetTime = osGetTime();
osSetTimer(&this->timer, OS_USEC_TO_CYCLES(450000), 0ull, &this->queue, (OSMesg)PRENMI450_MSG);
2020-03-22 21:19:43 +00:00
IrqMgr_JamMesgForClient(this, (OSMesg) & this->prenmiMsg);
2020-03-17 04:31:30 +00:00
}
2020-03-22 21:19:43 +00:00
void IrqMgr_CheckStack() {
osSyncPrintf("irqmgr.c: PRENMIから0.5秒経過\n"); // 0.5 seconds after PRENMI
if (StackCheck_Check(NULL) == 0) {
osSyncPrintf("スタックは大丈夫みたいです\n"); // The stack looks ok
} else {
2020-03-17 04:31:30 +00:00
osSyncPrintf("%c", 7);
osSyncPrintf(VT_FGCOL(RED));
2020-03-22 21:19:43 +00:00
osSyncPrintf("スタックがオーバーフローしたか危険な状態です\n"); // Stack overflow or dangerous
osSyncPrintf(
"早々にスタックサイズを増やすか、スタックを消費しないようにしてください\n"); // Increase stack size early or
// don't consume stack
2020-03-17 04:31:30 +00:00
osSyncPrintf(VT_RST);
}
}
2020-03-22 21:19:43 +00:00
void IrqMgr_HandlePRENMI450(IrqMgr* this) {
u64 temp = STATUS_NMI; // required to match
2020-03-17 04:31:30 +00:00
gIrqMgrResetStatus = temp;
this->resetStatus = STATUS_NMI;
osSetTimer(&this->timer, OS_USEC_TO_CYCLES(30000), 0ull, &this->queue, (OSMesg)PRENMI480_MSG);
2020-03-22 21:19:43 +00:00
IrqMgr_SendMesgForClient(this, (OSMesg) & this->nmiMsg);
2020-03-17 04:31:30 +00:00
}
2020-03-22 21:19:43 +00:00
void IrqMgr_HandlePRENMI480(IrqMgr* this) {
2020-03-17 04:31:30 +00:00
u32 ret;
osSetTimer(&this->timer, OS_USEC_TO_CYCLES(20000), 0ull, &this->queue, (OSMesg)PRENMI500_MSG);
2020-03-22 21:19:43 +00:00
ret = func_801031F0(); // osAfterPreNMI
if (ret) {
osSyncPrintf("osAfterPreNMIが %d を返しました!?\n", ret); // osAfterPreNMI returned %d !?
2020-03-17 04:31:30 +00:00
osSetTimer(&this->timer, OS_USEC_TO_CYCLES(1000), 0ull, &this->queue, (OSMesg)PRENMI480_MSG);
}
}
2020-03-22 21:19:43 +00:00
void IrqMgr_HandlePRENMI500(IrqMgr* this) {
2020-03-17 04:31:30 +00:00
IrqMgr_CheckStack();
}
2020-03-22 21:19:43 +00:00
void IrqMgr_HandleRetrace(IrqMgr* this) {
if (sIrqMgrRetraceTime == 0ull) {
if (this->retraceTime == 0) {
2020-03-17 04:31:30 +00:00
this->retraceTime = osGetTime();
2020-03-22 21:19:43 +00:00
} else {
2020-03-17 04:31:30 +00:00
sIrqMgrRetraceTime = osGetTime() - this->retraceTime;
2020-03-22 21:19:43 +00:00
}
2020-03-17 04:31:30 +00:00
}
sIrqMgrRetraceCount++;
2020-03-22 21:19:43 +00:00
IrqMgr_SendMesgForClient(this, (OSMesg) & this->retraceMsg);
2020-03-17 04:31:30 +00:00
}
2020-03-22 21:19:43 +00:00
void IrqMgr_ThreadEntry(void* arg0) {
2020-03-17 04:31:30 +00:00
OSMesg msg;
IrqMgr* this;
u8 exit;
this = (IrqMgr*)arg0;
msg = 0;
2020-03-22 21:19:43 +00:00
osSyncPrintf("IRQマネージャスレッド実行開始\n"); // Start IRQ manager thread execution
2020-03-17 04:31:30 +00:00
exit = false;
2020-03-22 21:19:43 +00:00
while (!exit) {
2020-03-17 04:31:30 +00:00
osRecvMesg(&this->queue, &msg, OS_MESG_BLOCK);
2020-03-22 21:19:43 +00:00
switch ((u32)msg) {
2020-03-17 04:31:30 +00:00
case RETRACE_MSG:
IrqMgr_HandleRetrace(this);
break;
case PRE_NMI_MSG:
osSyncPrintf("PRE_NMI_MSG\n");
2020-03-22 21:19:43 +00:00
osSyncPrintf("スケジューラPRE_NMIメッセージを受信\n"); // Scheduler: Receives PRE_NMI message
2020-03-17 04:31:30 +00:00
IrqMgr_HandlePreNMI(this);
break;
case PRENMI450_MSG:
osSyncPrintf("PRENMI450_MSG\n");
2020-03-22 21:19:43 +00:00
osSyncPrintf("スケジューラPRENMI450メッセージを受信\n"); // Scheduler: Receives PRENMI450 message
2020-03-17 04:31:30 +00:00
IrqMgr_HandlePRENMI450(this);
break;
case PRENMI480_MSG:
osSyncPrintf("PRENMI480_MSG\n");
2020-03-22 21:19:43 +00:00
osSyncPrintf("スケジューラPRENMI480メッセージを受信\n"); // Scheduler: Receives PRENMI480 message
2020-03-17 04:31:30 +00:00
IrqMgr_HandlePRENMI480(this);
break;
case PRENMI500_MSG:
osSyncPrintf("PRENMI500_MSG\n");
2020-03-22 21:19:43 +00:00
osSyncPrintf("スケジューラPRENMI500メッセージを受信\n"); // Scheduler: Receives PRENMI500 message
2020-03-17 04:31:30 +00:00
exit = true;
IrqMgr_HandlePRENMI500(this);
break;
default:
2020-03-22 21:19:43 +00:00
osSyncPrintf("irqmgr.c:予期しないメッセージを受け取りました(%08x)\n",
msg); // Unexpected message received
2020-03-17 04:31:30 +00:00
break;
}
}
2020-03-22 21:19:43 +00:00
osSyncPrintf("IRQマネージャスレッド実行終了\n"); // End of IRQ manager thread execution
2020-03-17 04:31:30 +00:00
}
2020-03-22 21:19:43 +00:00
void IrqMgr_Create(IrqMgr* this, void* stack, OSPri pri, u8 retraceCount) {
2020-03-17 04:31:30 +00:00
LogUtils_CheckNullPointer("this", this, "../irqmgr.c", 346);
LogUtils_CheckNullPointer("stack", stack, "../irqmgr.c", 347);
this->clients = NULL;
this->retraceMsg.type = OS_SC_RETRACE_MSG;
this->prenmiMsg.type = OS_SC_PRE_NMI_MSG;
this->nmiMsg.type = OS_SC_NMI_MSG;
this->resetStatus = STATUS_IDLE;
this->resetTime = 0;
osCreateMesgQueue(&this->queue, this->msgBuf, ARRAY_COUNT(this->msgBuf));
osSetEventMesg(OS_EVENT_PRENMI, &this->queue, (OSMesg)PRE_NMI_MSG);
osViSetEvent(&this->queue, (OSMesg)RETRACE_MSG, retraceCount);
osCreateThread(&this->thread, 0x13, IrqMgr_ThreadEntry, this, stack, pri);
osStartThread(&this->thread);
}