mirror of
https://gitee.com/anod/open_agb_firm.git
synced 2025-05-06 22:04:10 +08:00
134 lines
3.2 KiB
C
134 lines
3.2 KiB
C
/*
|
|
* This file is part of open_agb_firm
|
|
* Copyright (C) 2021 derrek, profi200
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/*#include <stdlib.h>
|
|
#include "types.h"
|
|
#include "ktimer.h"
|
|
#include "internal/list.h"
|
|
#include "arm11/drivers/interrupt.h"
|
|
//#include "arm11/drivers/timer.h"
|
|
#include "internal/kernel_private.h"
|
|
#include "internal/slabheap.h"
|
|
#include "internal/config.h"
|
|
//#include "arm11/fmt.h"
|
|
|
|
|
|
typedef struct
|
|
{
|
|
ListNode node;
|
|
u32 delta;
|
|
u32 ticks;
|
|
const bool pulse;
|
|
ListNode waitQueue;
|
|
} KTimer;
|
|
|
|
|
|
static SlabHeap g_timerSlab = {0};
|
|
static ListNode g_deltaQueue = {0};
|
|
|
|
|
|
|
|
static void timerIsr(UNUSED u32 intSource);
|
|
static void addToDeltaQueue(KTimer *const timer, u32 ticks);
|
|
|
|
void _timerInit(void)
|
|
{
|
|
slabInit(&g_timerSlab, sizeof(KTimer), MAX_TIMERS);
|
|
listInit(&g_deltaQueue);
|
|
IRQ_registerIsr(IRQ_TIMER, 12, 0, timerIsr);
|
|
}
|
|
|
|
KHandle createTimer(bool pulse)
|
|
{
|
|
KTimer *const ktimer = (KTimer*)slabAlloc(&g_timerSlab);
|
|
|
|
*(bool*)&ktimer->pulse = pulse;
|
|
listInit(&ktimer->waitQueue);
|
|
|
|
return (KHandle)ktimer;
|
|
}
|
|
|
|
void deleteTimer(KHandle const ktimer)
|
|
{
|
|
KTimer *const timer = (KTimer*)ktimer;
|
|
|
|
kernelLock();
|
|
waitQueueWakeN(&timer->waitQueue, (u32)-1, KRES_HANDLE_DELETED, true);
|
|
|
|
slabFree(&g_timerSlab, timer);
|
|
}
|
|
|
|
static void timerIsr(UNUSED u32 intSource)
|
|
{
|
|
kernelLock();
|
|
//if(listEmpty(&g_deltaQueue)) *((vu32*)4) = 4; // This should never happen
|
|
KTimer *ktimer = LIST_ENTRY(listPop(&g_deltaQueue), KTimer, node);
|
|
if(ktimer->pulse) addToDeltaQueue(ktimer, ktimer->ticks);
|
|
if(!listEmpty(&g_deltaQueue))
|
|
{
|
|
// Don't use fp math in ISRs.
|
|
TIMER_start(1, LIST_FIRST_ENTRY(&g_deltaQueue, KTimer, node)->delta, false, true);
|
|
}
|
|
waitQueueWakeN(&ktimer->waitQueue, (u32)-1, KRES_OK, false);
|
|
}
|
|
|
|
static void addToDeltaQueue(KTimer *const ktimer, u32 ticks)
|
|
{
|
|
KTimer *pos;
|
|
u32 deltaSum = 0;
|
|
LIST_FOR_EACH_ENTRY(pos, &g_deltaQueue, node)
|
|
{
|
|
deltaSum += pos->delta;
|
|
if(deltaSum > ticks)
|
|
{
|
|
ktimer->delta = ticks - (deltaSum - pos->delta);
|
|
listAddBefore(&pos->node, &ktimer->node);
|
|
return;
|
|
}
|
|
}
|
|
|
|
ktimer->delta = ticks;
|
|
listPush(&g_deltaQueue, &ktimer->node);
|
|
}
|
|
|
|
void startTimer(KHandle const ktimer, uint32_t usec)
|
|
{
|
|
KTimer *const timer = (KTimer*)ktimer;
|
|
|
|
const u32 ticks = TIMER_FREQ(1, 1000000) * usec;
|
|
timer->ticks = ticks;
|
|
|
|
kernelLock();
|
|
const bool firstTimer = listEmpty(&g_deltaQueue);
|
|
addToDeltaQueue(timer, ticks);
|
|
kernelUnlock();
|
|
if(firstTimer) TIMER_start(1, ticks, false, true);
|
|
}
|
|
|
|
void stopTimer(KHandle const ktimer)
|
|
{
|
|
}
|
|
|
|
KRes waitForTimer(KHandle const ktimer)
|
|
{
|
|
KTimer *const timer = (KTimer*)ktimer;
|
|
|
|
kernelLock();
|
|
return waitQueueBlock(&timer->waitQueue);
|
|
}*/
|