aboutsummaryrefslogtreecommitdiff
path: root/later
diff options
context:
space:
mode:
Diffstat (limited to 'later')
-rw-r--r--later/schedule.S58
-rw-r--r--later/schedule.c83
-rw-r--r--later/schedule.flat.c32
-rw-r--r--later/schedule.h43
-rw-r--r--later/schedule.ll.c13
-rw-r--r--later/schedule.q.c118
6 files changed, 347 insertions, 0 deletions
diff --git a/later/schedule.S b/later/schedule.S
new file mode 100644
index 0000000..1811c7c
--- /dev/null
+++ b/later/schedule.S
@@ -0,0 +1,58 @@
+.section .text
+.globl preserveregs
+preserveregs:
+ str r4, [r0, #0x10]
+ str r5, [r0, #0x14]
+ str r6, [r0, #0x18]
+ str r7, [r0, #0x1c]
+ str r8, [r0, #0x20]
+ str r9, [r0, #0x24]
+ str r10, [r0, #0x28]
+ str r11, [r0, #0x2c]
+ bx lr
+
+.globl restoreregs
+restoreregs:
+ ldr r4, [r0, #0x10]
+ ldr r5, [r0, #0x14]
+ ldr r6, [r0, #0x18]
+ ldr r7, [r0, #0x1c]
+ ldr r8, [r0, #0x20]
+ ldr r9, [r0, #0x24]
+ ldr r10, [r0, #0x28]
+ ldr r11, [r0, #0x2c]
+ bx lr
+
+.globl exetask
+exetask:
+ push {r0, r4, r5, r6, r7, r8, r9, r10, r11, lr}
+ // Restore registers from context switch
+ ldr r4, [r0, #0x10]
+ ldr r5, [r0, #0x14]
+ ldr r6, [r0, #0x18]
+ ldr r7, [r0, #0x1c]
+ ldr r8, [r0, #0x20]
+ ldr r9, [r0, #0x24]
+ ldr r10, [r0, #0x28]
+ ldr r11, [r0, #0x2c]
+
+ // Preserve system stack
+ ldr r1, =msp
+ str sp, [r1]
+ // Setup task's stack
+ ldr sp, [r0, #0x34]
+ // Switch to task
+ ldr lr, [r0, #0x3c]
+ blx lr
+ // Restore system stack
+ ldr r1, =msp
+ ldr sp, [r1]
+ pop {r0, r4, r5, r6, r7, r8, r9, r10, r11, pc}
+
+.section .data
+msp:
+ .space 4
+.section .data.stacks
+.globl stacks
+stacks:
+ .space 0x100000
diff --git a/later/schedule.c b/later/schedule.c
new file mode 100644
index 0000000..8cf2780
--- /dev/null
+++ b/later/schedule.c
@@ -0,0 +1,83 @@
+#include "../sys/schedule.h"
+#include "../lib/ll.h"
+#include "../lib/q.h"
+
+#ifdef IGNORE
+#ifdef FLAT
+static struct Task* task_list[256];
+
+static struct Scheduler scheduler = {
+ .tasks = task_list,
+};
+
+static unsigned int ntask_i = 0;
+
+void add_task(struct Task* t)
+{
+ scheduler.tasks[ntask_i] = t;
+ ntask_i += 1;
+ if (ntask_i > 256) {
+ ntask_i = 0;
+ }
+}
+
+unsigned int get_task_length(void)
+{
+ return ntask_i;
+}
+
+void execute_task(void)
+{
+ if (scheduler.tasks[ntask_i-1] != 0)
+ scheduler.tasks[ntask_i-1]->task();
+}
+#elseif LL
+static struct LL bl = {
+ .prev = 0,
+ .next = 0,
+};
+static struct Scheduler scheduler = {
+ .tasks = &bl,
+};
+#else
+static struct Q_base bq = {
+ .next = 0,
+ .last = 0,
+};
+static struct Scheduler scheduler = {
+ .tasks = &bq,
+};
+
+void add_task(struct Task* t)
+{
+ pushq(scheduler.tasks, t);
+}
+
+unsigned int get_task_length(void)
+{
+ unsigned int length = 0;
+ if (scheduler.tasks->last == 0)
+ return length;
+ else if (scheduler.tasks->next == scheduler.tasks->last)
+ return 1;
+ else {
+ struct Q* q = scheduler.tasks->next;
+ length += 1;
+ while (q->next != 0) {
+ q = q->next;
+ length += 1;
+ }
+ return length;
+ }
+}
+
+void execute_task(void)
+{
+ if (scheduler.tasks->last != 0) {
+ struct Task* tsk = (struct Task*)scheduler.tasks->next->data;
+ (tsk->task)();
+ popq(scheduler.tasks);
+ }
+}
+#endif
+#endif
diff --git a/later/schedule.flat.c b/later/schedule.flat.c
new file mode 100644
index 0000000..6eb0d14
--- /dev/null
+++ b/later/schedule.flat.c
@@ -0,0 +1,32 @@
+#ifdef FLAT
+
+#include "../sys/schedule.h"
+static struct Task* task_list[256];
+
+static struct Scheduler scheduler = {
+ .tasks = task_list,
+};
+
+static unsigned int ntask_i = 0;
+
+void add_task(struct Task* t)
+{
+ scheduler.tasks[ntask_i] = t;
+ ntask_i += 1;
+ if (ntask_i > 256) {
+ ntask_i = 0;
+ }
+}
+
+unsigned int get_task_length(void)
+{
+ return ntask_i;
+}
+
+void execute_task(void)
+{
+ if (scheduler.tasks[ntask_i-1] != 0)
+ scheduler.tasks[ntask_i-1]->task();
+}
+
+#endif
diff --git a/later/schedule.h b/later/schedule.h
new file mode 100644
index 0000000..77da7eb
--- /dev/null
+++ b/later/schedule.h
@@ -0,0 +1,43 @@
+#ifndef SYS_SCHEDULE_H
+#define SYS_SCHEDULE_H
+
+#define S_WAITING 0
+#define S_READY 1
+
+#define STACK_SIZE 0x800
+struct Task {
+ unsigned char priority;
+ unsigned char status;
+ unsigned long pid;
+ void (*task)(void);
+ unsigned long reg[16];
+ unsigned long stacki;
+ void* stack;
+};
+
+#ifdef FLAT
+struct Scheduler {
+ unsigned long running_pid;
+ struct Task** tasks;
+};
+#elseif LL
+#include "../lib/ll.h"
+struct Scheduler {
+ unsigned long running_pid;
+ struct LL* tasks;
+};
+#else
+#include "../lib/q.h"
+struct Scheduler {
+ unsigned long running_pid;
+ struct Q_base* tasks;
+};
+#endif
+
+void add_fxn(void (*task)(void), unsigned char priority);
+unsigned char exists(void (*task)(void));
+void add_no_repeat(void (*task)(void), unsigned char priority);
+unsigned int get_task_length(void);
+void execute_task(void);
+
+#endif
diff --git a/later/schedule.ll.c b/later/schedule.ll.c
new file mode 100644
index 0000000..d9ab954
--- /dev/null
+++ b/later/schedule.ll.c
@@ -0,0 +1,13 @@
+#ifdef LL
+
+#include "../sys/schedule.h"
+#include "../lib/ll.h"
+static struct LL bl = {
+ .prev = 0,
+ .next = 0,
+};
+static struct Scheduler scheduler = {
+ .tasks = &bl,
+};
+
+#endif
diff --git a/later/schedule.q.c b/later/schedule.q.c
new file mode 100644
index 0000000..4a5ff85
--- /dev/null
+++ b/later/schedule.q.c
@@ -0,0 +1,118 @@
+#if !(defined(LL) || defined(FLAT))
+#include "../sys/schedule.h"
+#include "../lib/q.h"
+#include "../lib/mem.h"
+#include "../drivers/uart.h"
+
+extern void preserveregs(void*);
+extern void restoreregs(void*);
+extern void exetask(void*);
+
+static unsigned long next_pid = 3;
+unsigned char table[256] = {0, };
+
+static struct __attribute__((packed,align(4))) Q_base bq = {
+ .next = 0,
+ .last = 0,
+};
+struct __attribute__((packed,align(4))) Scheduler scheduler = {
+ .running_pid = 0,
+ .tasks = &bq,
+};
+
+extern unsigned long __stacks_start;
+
+unsigned long getstack(void)
+{
+ for(unsigned int i = 0; i < 256; i++) {
+ if (table[i] == 0) {
+ table[i] = 1;
+ return i;
+ }
+ }
+ return -1;
+}
+
+void add_fxn(void (*task)(void), unsigned char priority)
+{
+ struct Task* t = (struct Task*)malloc(sizeof(struct Task));
+ // Allocate a stack frame and space for registers to be preserved on context switches
+ t->priority = priority;
+ t->task = task;
+ t->stacki = getstack();
+ t->pid = next_pid;
+ next_pid += 1;
+ if(t->stacki > 256)
+ t->stack = 0;
+ else
+ t->stack = (void*)(__stacks_start + STACK_SIZE*t->stacki);
+ t->status = S_READY;
+ for(unsigned char i = 0; i < 13; i++)
+ t->reg[i] = 0;
+ t->reg[13] = (unsigned long)t->stack;
+ t->reg[14] = 0; // LR
+ t->reg[15] = (unsigned long)task; // PC
+ pushq(scheduler.tasks, t);
+}
+
+unsigned char exists(void (*task)(void))
+{
+ if (scheduler.tasks->next == 0)
+ return 0;
+ struct Q* q = scheduler.tasks->next;
+ while (q != 0) {
+ struct Task* t = q->data;
+ if (t->task == task)
+ return 1;
+ q = q->next;
+ }
+ return 0;
+}
+
+void add_no_repeat(void (*task)(void), unsigned char priority)
+{
+ if (!(exists(task)))
+ add_fxn(task, priority);
+}
+
+unsigned int get_task_length(void)
+{
+ unsigned int length = 0;
+ if (scheduler.tasks->last == 0)
+ return length;
+ else if (scheduler.tasks->next == scheduler.tasks->last)
+ return 1;
+ else {
+ struct Q* q = scheduler.tasks->next;
+ length += 1;
+ while (q->next != 0) {
+ q = q->next;
+ length += 1;
+ }
+ return length;
+ }
+}
+void execute_task(void)
+{
+ // Preserve Current Running PID's Data
+ if (scheduler.tasks->last != 0) {
+ struct Q* q = (struct Q*)scheduler.tasks->next;
+ while (((struct Task*)q->data)->status == S_WAITING) {
+ q = q->next;
+ }
+ struct Task* tsk = (struct Task*)q->data;
+ // Restore registers
+ // Including program counter as the entry point
+ // Including allocated stack position
+ // Set lr to the return address to restore system stack
+ //preserveregs(tsk->reg);
+ //restoreregs(tsk->reg);
+ scheduler.running_pid = tsk->pid;
+ exetask(tsk->reg);
+ scheduler.running_pid = 0;
+ table[tsk->stacki] = 0;
+ popq(scheduler.tasks);
+ }
+}
+
+#endif