mirror of
https://github.com/drasko/codezero.git
synced 2026-01-12 02:43:15 +01:00
Timer service enhanced for sleep
This commit is contained in:
36
conts/baremetal/timer_service/include/timer.h
Normal file
36
conts/baremetal/timer_service/include/timer.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef __TIMER_H__
|
||||
#define __TIMER_H__
|
||||
|
||||
/*
|
||||
* Timer specific things are here
|
||||
*/
|
||||
#include <l4lib/mutex.h>
|
||||
#include <l4/lib/list.h>
|
||||
|
||||
/*
|
||||
* Structure representing the sleeping tasks,
|
||||
* tgid: tgid of sleeping task
|
||||
* wait_count: time left, in microseconds, after which task
|
||||
* will be signalled to get out of sleep
|
||||
*/
|
||||
struct timer_task {
|
||||
struct link list;
|
||||
l4id_t tgid;
|
||||
unsigned int wait_count;
|
||||
};
|
||||
|
||||
/*
|
||||
* Timer structure,
|
||||
* base: base address of sp804 timer encapsulated
|
||||
* count: Count in microseconds from the start of this timer
|
||||
* tasklist: list of tasks sleeping for some value of count
|
||||
* lock: lock protecting the corruption of tasklist
|
||||
*/
|
||||
struct sp804_timer {
|
||||
unsigned int base;
|
||||
unsigned int count;
|
||||
struct link tasklist;
|
||||
struct l4_mutex lock;
|
||||
};
|
||||
|
||||
#endif /* __TIMER_H__ */
|
||||
@@ -9,11 +9,12 @@
|
||||
#include <l4/api/errno.h>
|
||||
|
||||
#include <l4/api/space.h>
|
||||
#include <malloc/malloc.h>
|
||||
#include <capability.h>
|
||||
#include <container.h>
|
||||
#include "sp804_timer.h"
|
||||
#include <linker.h>
|
||||
|
||||
#include <timer.h>
|
||||
|
||||
/* Frequency of timer in MHz */
|
||||
#define TIMER_FREQUENCY 1
|
||||
@@ -148,11 +149,31 @@ int timer_probe_devices(void)
|
||||
|
||||
static struct sp804_timer timer[TIMERS_TOTAL];
|
||||
|
||||
struct timer_task *get_timer_task(l4id_t tgid)
|
||||
{
|
||||
/* May be we can prepare a cache for timer_task structs */
|
||||
struct timer_task *task = (struct timer_task *)kzalloc(sizeof(struct timer_task));
|
||||
|
||||
link_init(&task->list);
|
||||
task->tgid = tgid;
|
||||
task->wait_count = timer[0].count;
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
void free_timer_task(struct timer_task *task)
|
||||
{
|
||||
kfree(task);
|
||||
}
|
||||
|
||||
int timer_setup_devices(void)
|
||||
{
|
||||
for (int i = 0; i < TIMERS_TOTAL; i++) {
|
||||
/* Get one page from address pool */
|
||||
timer[i].base = (unsigned long)l4_new_virtual(1);
|
||||
timer[i].count = 0;
|
||||
link_init(&timer[i].tasklist);
|
||||
l4_mutex_init(&timer[i].lock);
|
||||
|
||||
/* Map timers to a virtual address region */
|
||||
if (IS_ERR(l4_map((void *)__pfn_to_addr(timer_cap[i].start),
|
||||
@@ -166,10 +187,12 @@ int timer_setup_devices(void)
|
||||
}
|
||||
|
||||
/* Initialise timer */
|
||||
sp804_init(timer[i].base, SP804_TIMER_RUNMODE_FREERUN, \
|
||||
sp804_init(timer[i].base, SP804_TIMER_RUNMODE_PERIODIC, \
|
||||
SP804_TIMER_WRAPMODE_WRAPPING, SP804_TIMER_WIDTH32BIT, \
|
||||
SP804_TIMER_IRQDISABLE);
|
||||
|
||||
/* Request IRQ for this timer */
|
||||
|
||||
/* Enable Timer */
|
||||
sp804_enable(timer[i].base, 1);
|
||||
}
|
||||
@@ -226,18 +249,48 @@ void *l4_new_virtual(int npages)
|
||||
return address_new(&device_vaddr_pool, npages, PAGE_SIZE);
|
||||
}
|
||||
|
||||
int timer_gettime(int devno)
|
||||
void timer_irq_handler(void)
|
||||
{
|
||||
return sp804_read_value(timer[devno].base);
|
||||
struct timer_task *struct_ptr, *temp_ptr;
|
||||
|
||||
timer[0].count += 1;
|
||||
|
||||
/*
|
||||
* FIXME:
|
||||
* Traverse through the sleeping process list and
|
||||
* wake any process if required, we need to put this part in bottom half
|
||||
*/
|
||||
list_foreach_removable_struct(struct_ptr, temp_ptr, &timer[0].tasklist, list)
|
||||
if (struct_ptr->wait_count == timer[0].count) {
|
||||
|
||||
/* Remove task from list */
|
||||
l4_mutex_lock(&timer[0].lock);
|
||||
list_remove(&struct_ptr->list);
|
||||
l4_mutex_unlock(&timer[0].lock);
|
||||
|
||||
/* wake the sleeping process, send wake ipc */
|
||||
|
||||
free_timer_task(struct_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void timer_sleep(int sec)
|
||||
int timer_gettime(void)
|
||||
{
|
||||
/*
|
||||
* TODO: We need to have a timer struct already present to be used
|
||||
* as reference for us. to implement this call
|
||||
*/
|
||||
return timer[0].count;
|
||||
}
|
||||
|
||||
void timer_sleep(l4id_t tgid, int sec)
|
||||
{
|
||||
struct timer_task *task = get_timer_task(tgid);
|
||||
|
||||
/* Check for overflow */
|
||||
task->wait_count += (sec * 1000000);
|
||||
|
||||
l4_mutex_lock(&timer[0].lock);
|
||||
list_insert_tail(&task->list, &timer[0].tasklist);
|
||||
l4_mutex_unlock(&timer[0].lock);
|
||||
}
|
||||
|
||||
void handle_requests(void)
|
||||
{
|
||||
u32 mr[MR_UNUSED_TOTAL];
|
||||
@@ -273,11 +326,12 @@ void handle_requests(void)
|
||||
*/
|
||||
switch (tag) {
|
||||
case L4_IPC_TAG_TIMER_GETTIME:
|
||||
timer_gettime(1);
|
||||
mr[0] = timer_gettime();
|
||||
break;
|
||||
|
||||
case L4_IPC_TAG_TIMER_SLEEP:
|
||||
timer_sleep(mr[0]);
|
||||
timer_sleep(senderid, mr[0]);
|
||||
/* TODO: Halt the caller for mr[0] seconds */
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -56,10 +56,6 @@
|
||||
#define SP804_TIMERMIS 0x14
|
||||
#define SP804_TIMERBGLOAD 0x18
|
||||
|
||||
struct sp804_timer {
|
||||
unsigned int base;
|
||||
};
|
||||
|
||||
void sp804_init(unsigned int timer_base, int runmode, int wrapmode, \
|
||||
int width, int irq_enable);
|
||||
void sp804_irq_handler(unsigned int timer_base);
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#define setbit(bit, a) write(read(a) | bit, a)
|
||||
#define clrbit(bit, a) write(read(a) & ~bit, a)
|
||||
|
||||
extern void timer_irq_handler(void);
|
||||
|
||||
void sp804_irq_handler(unsigned int timer_base)
|
||||
{
|
||||
/*
|
||||
@@ -17,6 +19,7 @@ void sp804_irq_handler(unsigned int timer_base)
|
||||
* as it automatically reloads and wraps
|
||||
*/
|
||||
write(1, (timer_base + SP804_TIMERINTCLR));
|
||||
timer_irq_handler();
|
||||
}
|
||||
|
||||
static inline void sp804_control(unsigned int timer_base, int bit, int setclr)
|
||||
|
||||
Reference in New Issue
Block a user