Feat: gura!!!
This commit is contained in:
@@ -7,34 +7,8 @@
|
||||
|
||||
#define CORE0_TIMER_IRQ_CTRL ((volatile uint32_t *)0x40000040)
|
||||
|
||||
timer_t *global_timer = (timer_t *)0x0;
|
||||
|
||||
MMIO_W_HELPER(_enable_timer_irq, CORE0_TIMER_IRQ_CTRL, 0x1, 1);
|
||||
|
||||
static inline
|
||||
task_t _make_timer_task(uint64_t interval_s, task_callback_func_t func,
|
||||
uint64_t param)
|
||||
{
|
||||
uint64_t cntpct_el0, cntfrq_el0;
|
||||
R_SYSREG(cntpct_el0, cntpct_el0);
|
||||
R_SYSREG(cntfrq_el0, cntfrq_el0);
|
||||
|
||||
return (task_t){
|
||||
.firing_tick = cntpct_el0 + interval_s * cntfrq_el0,
|
||||
.interval = interval_s * cntfrq_el0,
|
||||
|
||||
.func = func,
|
||||
.param = param,
|
||||
};
|
||||
}
|
||||
|
||||
static inline
|
||||
void _scheduler_timeout(uint64_t)
|
||||
{
|
||||
add_timer_task(_make_timer_task(1, _scheduler_timeout, 0x0));
|
||||
schedule();
|
||||
}
|
||||
|
||||
void timer_init()
|
||||
{
|
||||
uint64_t cntkctl_el1, cntfrq_el0;
|
||||
@@ -44,94 +18,7 @@ void timer_init()
|
||||
_enable_timer_irq(true);
|
||||
|
||||
R_SYSREG(cntfrq_el0, cntfrq_el0);
|
||||
W_SYSREG(cntp_tval_el0, cntfrq_el0 >> 1);
|
||||
|
||||
return;
|
||||
add_timer_task(_make_timer_task(1, _scheduler_timeout, 0x0));
|
||||
}
|
||||
|
||||
static inline
|
||||
uint32_t _d(timer_t *t)
|
||||
{ return t ? t->_d : 0; }
|
||||
|
||||
static inline
|
||||
void _swap(timer_t **a, timer_t **b)
|
||||
{
|
||||
timer_t *tmp = *a;
|
||||
*a = *b, *b = tmp;
|
||||
}
|
||||
|
||||
static inline
|
||||
timer_t *_merge(timer_t *a, timer_t *b)
|
||||
{
|
||||
if (!a || !b)
|
||||
return a ?: b;
|
||||
|
||||
if (a->data.firing_tick > b->data.firing_tick)
|
||||
_swap(&a, &b);
|
||||
a->_r = _merge(a->_r, b);
|
||||
|
||||
if (_d(a->_l) < _d(a->_r))
|
||||
_swap(&a->_l, &a->_r);
|
||||
|
||||
a->_d = _d(a->_r) + 1;
|
||||
return a;
|
||||
}
|
||||
|
||||
static inline
|
||||
timer_t *_pop(timer_t *t)
|
||||
{
|
||||
if (!t || (!t->_l && !t->_r)) {
|
||||
kfree(t);
|
||||
return (timer_t *)0x0;
|
||||
}
|
||||
return _merge(t->_l, t->_r);
|
||||
}
|
||||
|
||||
static inline
|
||||
void _check_enable_timer()
|
||||
{
|
||||
if (global_timer) {
|
||||
uint64_t cntpct_el0;
|
||||
R_SYSREG(cntpct_el0, cntpct_el0);
|
||||
DEBUG_EXCEP(cntpct_el0);
|
||||
|
||||
if (global_timer->data.firing_tick < cntpct_el0)
|
||||
W_SYSREG(cntp_tval_el0, 1);
|
||||
else
|
||||
W_SYSREG(cntp_cval_el0, global_timer->data.firing_tick);
|
||||
|
||||
W_SYSREG(cntp_ctl_el0, 1);
|
||||
} else
|
||||
W_SYSREG(cntp_ctl_el0, 0);
|
||||
}
|
||||
|
||||
static inline
|
||||
void _traverse(timer_t *t)
|
||||
{
|
||||
if (!t) return;
|
||||
DEBUG_EXCEP(t->data.firing_tick);
|
||||
t->data.func(t->data.param);
|
||||
_traverse(t->_l);
|
||||
_traverse(t->_r);
|
||||
}
|
||||
|
||||
void add_timer_task(task_t task)
|
||||
{
|
||||
DEBUG_EXCEP("add timer task");
|
||||
timer_t *newtimer = kmalloc(sizeof(timer_t));
|
||||
*newtimer = (timer_t){
|
||||
._l = (timer_t *)0x0,
|
||||
._r = (timer_t *)0x0,
|
||||
._d = 0,
|
||||
|
||||
.data = task,
|
||||
};
|
||||
|
||||
global_timer = _merge(global_timer, newtimer);
|
||||
|
||||
// _traverse(global_timer);
|
||||
_check_enable_timer();
|
||||
W_SYSREG(cntp_tval_el0, cntfrq_el0 >> 5);
|
||||
}
|
||||
|
||||
void sleep(uint64_t ms)
|
||||
@@ -149,42 +36,10 @@ void sleep(uint64_t ms)
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
interrupt_callback_func_t func;
|
||||
uint64_t param;
|
||||
} _timer_task_wrapper_param_t;
|
||||
|
||||
static inline
|
||||
void _timer_task_wrapper(uint64_t param)
|
||||
{
|
||||
_timer_task_wrapper_param_t *data = (void *)param;
|
||||
data->func(data->param);
|
||||
kfree(data);
|
||||
|
||||
_enable_timer_irq(true);
|
||||
}
|
||||
|
||||
void timer_irq_handler(void)
|
||||
{
|
||||
_enable_timer_irq(false);
|
||||
uint64_t cntfrq_el0;
|
||||
R_SYSREG(cntfrq_el0, cntfrq_el0);
|
||||
W_SYSREG(cntp_tval_el0, cntfrq_el0 >> 5);
|
||||
schedule();
|
||||
_enable_timer_irq(true);
|
||||
return;
|
||||
|
||||
uint64_t cntpct_el0;
|
||||
R_SYSREG(cntpct_el0, cntpct_el0);
|
||||
LOG("timer irq"); DEBUG_EXCEP(cntpct_el0);
|
||||
|
||||
if (global_timer) {
|
||||
_timer_task_wrapper_param_t *param =
|
||||
kmalloc(sizeof(_timer_task_wrapper_param_t));
|
||||
*param = (_timer_task_wrapper_param_t){
|
||||
.func = global_timer->data.func,
|
||||
.param = global_timer->data.param,
|
||||
};
|
||||
add_interrupt_task(20, _timer_task_wrapper, (uint64_t)param);
|
||||
|
||||
global_timer = _pop(global_timer);
|
||||
_check_enable_timer();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user