Feat: lab 3
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
#include <interrupt.h>
|
||||
#include <kmalloc.h>
|
||||
#include <uart.h>
|
||||
#include <timer.h>
|
||||
#include <utils.h>
|
||||
@@ -8,6 +9,8 @@
|
||||
#define CORE0_TIMER_IRQ_CTRL ((volatile uint32_t *)0x40000040)
|
||||
#define CORE0_IRQ_SOURCE ((volatile uint32_t *)0x40000060)
|
||||
|
||||
interrupt_t *global_interrupt_pool = (interrupt_t *)0x0;
|
||||
|
||||
static inline
|
||||
void _enable_interrupt(void)
|
||||
{ W_SYSREG_IMM(DAIFClr, 0xf); }
|
||||
@@ -21,6 +24,61 @@ MMIO_W_HELPER(_enable_timer_irq, CORE0_TIMER_IRQ_CTRL, 0x1, 1);
|
||||
MMIO_R_HELPER(_irq_source_timer, CORE0_IRQ_SOURCE, 0x1, 1);
|
||||
MMIO_R_HELPER(_irq_source_uart, CORE0_IRQ_SOURCE, 0x1, 8);
|
||||
|
||||
static inline
|
||||
uint32_t _d(interrupt_t *interrupt)
|
||||
{ return interrupt ? interrupt->_d : 0; }
|
||||
|
||||
static inline
|
||||
void _swap(interrupt_t **a, interrupt_t **b)
|
||||
{
|
||||
interrupt_t *tmp = *a;
|
||||
*a = *b, *b = tmp;
|
||||
}
|
||||
|
||||
static inline
|
||||
interrupt_t *_merge(interrupt_t *a, interrupt_t *b)
|
||||
{
|
||||
if (!a || !b)
|
||||
return a ?: b;
|
||||
|
||||
if (a->priority < b->priority)
|
||||
_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
|
||||
interrupt_t *_pop(interrupt_t *interrupt)
|
||||
{
|
||||
if (!interrupt || (!interrupt->_l && !interrupt->_r))
|
||||
return (interrupt_t *)0x0;
|
||||
return _merge(interrupt->_l, interrupt->_r);
|
||||
}
|
||||
|
||||
void add_interrupt_task(uint64_t priority,
|
||||
interrupt_callback_func_t func,
|
||||
uint64_t param)
|
||||
{
|
||||
// DEBUG_EXCEP("add interrupt");
|
||||
interrupt_t *newint = kmalloc(sizeof(interrupt_t));
|
||||
*newint = (interrupt_t){
|
||||
._l = (interrupt_t *)0x0,
|
||||
._r = (interrupt_t *)0x0,
|
||||
._d = 0,
|
||||
|
||||
.priority = priority,
|
||||
.func = func,
|
||||
.param = param
|
||||
};
|
||||
|
||||
global_interrupt_pool = _merge(global_interrupt_pool, newint);
|
||||
}
|
||||
|
||||
void init_interrupt(void)
|
||||
{
|
||||
uint64_t cntfrq_el0;
|
||||
@@ -43,3 +101,17 @@ void irq_handler(void)
|
||||
if (_irq_source_uart())
|
||||
uart_irq_handler();
|
||||
}
|
||||
|
||||
void wfe(void)
|
||||
{
|
||||
if (!global_interrupt_pool) {
|
||||
asm volatile("wfe");
|
||||
return;
|
||||
}
|
||||
|
||||
interrupt_t *interrupt = global_interrupt_pool;
|
||||
global_interrupt_pool = _merge(global_interrupt_pool->_l,
|
||||
global_interrupt_pool->_r);
|
||||
|
||||
interrupt->func(interrupt->param);
|
||||
}
|
||||
|
||||
@@ -22,14 +22,15 @@ static inline
|
||||
void _help (void)
|
||||
{
|
||||
uart_puts(
|
||||
"help : print this help menu" ENDL
|
||||
"hello : print Hello World!" ENDL
|
||||
"hwinfo : print hardware info" ENDL
|
||||
"memalloc <size>: alloate memory and print" ENDL
|
||||
"ls : list directory contents" ENDL
|
||||
"cat <file>: concatenate files and print" ENDL
|
||||
"exec <file>: execute file in usermode" ENDL
|
||||
"reboot : reboot the device" ENDL
|
||||
"help : print this help menu" ENDL
|
||||
"hello : print Hello World!" ENDL
|
||||
"hwinfo : print hardware info" ENDL
|
||||
"memalloc <size> : alloate memory and print" ENDL
|
||||
"ls : list directory contents" ENDL
|
||||
"cat <file> : concatenate files and print" ENDL
|
||||
"exec <file> : execute file in usermode" ENDL
|
||||
"settimeout <sec> <message...>: pring message after a few seconds" ENDL
|
||||
"reboot : reboot the device" ENDL
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <timer.h>
|
||||
#include <interrupt.h>
|
||||
#include <logger.h>
|
||||
#include <utils.h>
|
||||
#include <kmalloc.h>
|
||||
@@ -14,10 +15,10 @@ uint32_t _d(timer_t *t)
|
||||
{ return t ? t->_d : 0; }
|
||||
|
||||
static inline
|
||||
void _swap(timer_t *a, timer_t *b)
|
||||
void _swap(timer_t **a, timer_t **b)
|
||||
{
|
||||
timer_t *tmp = a;
|
||||
a = b, b = tmp;
|
||||
timer_t *tmp = *a;
|
||||
*a = *b, *b = tmp;
|
||||
}
|
||||
|
||||
static inline
|
||||
@@ -27,11 +28,11 @@ timer_t *_merge(timer_t *a, timer_t *b)
|
||||
return a ?: b;
|
||||
|
||||
if (a->data.firing_tick > b->data.firing_tick)
|
||||
_swap(a, b);
|
||||
_swap(&a, &b);
|
||||
a->_r = _merge(a->_r, b);
|
||||
|
||||
if (_d(a->_l) < _d(a->_r))
|
||||
_swap(a->_l, a->_r);
|
||||
_swap(&a->_l, &a->_r);
|
||||
|
||||
a->_d = _d(a->_r) + 1;
|
||||
return a;
|
||||
@@ -87,7 +88,7 @@ void timer_irq_handler(void)
|
||||
DEBUG_EXCEP(cntpct_el0);
|
||||
|
||||
if (global_timer) {
|
||||
global_timer->data.func(global_timer->data.param);
|
||||
add_interrupt_task(20, global_timer->data.func, global_timer->data.param);
|
||||
global_timer = _pop(global_timer);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#include <uart.h>
|
||||
#include <kmalloc.h>
|
||||
#include <interrupt.h>
|
||||
#include <logger.h>
|
||||
#include <errcode.h>
|
||||
#include <utils.h>
|
||||
@@ -87,11 +89,31 @@ void uart_transmit_interrupt_handler()
|
||||
_uart_write_data(ringbuffer_bump(uart_writebuf));
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
ringbuffer_t *buf;
|
||||
uint8_t val;
|
||||
} uart_interrupt_callback_payload_t;
|
||||
|
||||
static inline
|
||||
void uart_receive_interrupt_callback(uint64_t param)
|
||||
{
|
||||
uart_interrupt_callback_payload_t *payload = (void *)param;
|
||||
ringbuffer_push(payload->buf, payload->val);
|
||||
kfree(payload);
|
||||
}
|
||||
|
||||
void uart_receive_interrupt_handler()
|
||||
{
|
||||
if (uart_readbuf->size < uart_readbuf->cap) {
|
||||
uint8_t b = _uart_read_data();
|
||||
ringbuffer_push(uart_readbuf, b);
|
||||
|
||||
uart_interrupt_callback_payload_t *param = kmalloc(
|
||||
sizeof(uart_interrupt_callback_payload_t));
|
||||
*param = (uart_interrupt_callback_payload_t){
|
||||
.buf = uart_readbuf,
|
||||
.val = b,
|
||||
};
|
||||
add_interrupt_task(10, uart_receive_interrupt_callback, (uint64_t)param);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,7 +161,7 @@ size_t uart_getb_async(uint8_t *bytes, size_t len)
|
||||
size_t recvlen = 0;
|
||||
for (; recvlen < len; ++bytes, ++recvlen) {
|
||||
while (!uart_readbuf->size)
|
||||
asm volatile("wfe"); // wait for interrupt
|
||||
wfe(); // wait for interrupt
|
||||
*bytes = ringbuffer_bump(uart_readbuf);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user