rejoice! tasks suck no more

master
Clyne Sullivan 7 years ago
parent 5a6c8f4c22
commit eee1be766d

@ -20,3 +20,4 @@ do
while (y < 270) while (y < 270)
line 80 250 380 90 511 line 80 250 380 90 511

@ -1 +0,0 @@
Hello, world!

@ -1,3 +0,0 @@
print "yay"
yesyesye

Binary file not shown.

@ -1,4 +1,5 @@
#include "heap.h" #include <heap.h>
#include <task.h>
#define HEAP_ALIGN 16 #define HEAP_ALIGN 16
@ -20,6 +21,9 @@ void heap_init(void *buf)
void *malloc(uint32_t size) void *malloc(uint32_t size)
{ {
task_hold(1);
if (size < 16)
size = 16;
alloc_t *node = &root; alloc_t *node = &root;
while (node->next & 1 || node->size < size) { while (node->next & 1 || node->size < size) {
if ((node->next & ~(1)) == 0) { if ((node->next & ~(1)) == 0) {
@ -34,6 +38,7 @@ void *malloc(uint32_t size)
} }
node->next |= 1; node->next |= 1;
task_hold(0);
return (void *)((uint32_t)node + sizeof(alloc_t)); return (void *)((uint32_t)node + sizeof(alloc_t));
} }
@ -53,4 +58,3 @@ void free(void *buf)
alloc_t *alloc = (alloc_t *)((uint32_t)buf - sizeof(alloc_t)); alloc_t *alloc = (alloc_t *)((uint32_t)buf - sizeof(alloc_t));
alloc->next &= ~(1); alloc->next &= ~(1);
} }

@ -9,6 +9,7 @@
#include <initrd.h> #include <initrd.h>
#include <serial.h> #include <serial.h>
#include <parser.h> #include <parser.h>
#include <builtins.h>
#include <stack.h> #include <stack.h>
#include <string.h> #include <string.h>
@ -100,6 +101,32 @@ int script_ppos(interpreter *it)
return 0; return 0;
} }
int script_color(interpreter *it)
{
uint16_t c = dsp_color(igetarg_integer(it, 0), igetarg_integer(it, 1),
igetarg_integer(it, 2));
variable v;
v.valtype = INTEGER;
v.value = c;
v.svalue = 0;
isetstr(&v);
iret(it, &v);
return 0;
}
int script_rand(interpreter *it)
{
static uint32_t next = 1;
next = (next * 182 + 1829) % igetarg_integer(it, 0);
variable v;
v.valtype = INTEGER;
v.value = next;
v.svalue = 0;
isetstr(&v);
iret(it, &v);
return 0;
}
void task_interpreter(void) void task_interpreter(void)
{ {
interpreter it; interpreter it;
@ -110,6 +137,8 @@ void task_interpreter(void)
inew_cfunc(&it, "rect", script_rect); inew_cfunc(&it, "rect", script_rect);
inew_cfunc(&it, "ppos", script_ppos); inew_cfunc(&it, "ppos", script_ppos);
inew_cfunc(&it, "line", script_line); inew_cfunc(&it, "line", script_line);
inew_cfunc(&it, "color", script_color);
inew_cfunc(&it, "rand", script_rand);
/*int ret = 0; /*int ret = 0;
char *linebuf = malloc(100), c[2] = {0, 0}; char *linebuf = malloc(100), c[2] = {0, 0};
@ -134,8 +163,10 @@ void task_interpreter(void)
}*/ }*/
char *s = initrd_getfile("init"); char *s = initrd_getfile("init");
if (s == 0) if (s == 0) {
dsp_puts("init not found");
goto end; goto end;
}
char *linebuf = (char *)malloc(120); char *linebuf = (char *)malloc(120);
uint32_t i = 0, prev = 0, lc; uint32_t i = 0, prev = 0, lc;
@ -150,7 +181,9 @@ void task_interpreter(void)
} }
strncpy(linebuf, s + prev, lc + 1); strncpy(linebuf, s + prev, lc + 1);
linebuf[lc] = '\0'; linebuf[lc] = '\0';
//task_hold(1);
ret = idoline(&it, linebuf); ret = idoline(&it, linebuf);
//task_hold(0);
if (ret < 0) if (ret < 0)
break; break;
prev = ++i; prev = ++i;
@ -171,7 +204,6 @@ end:
void kmain(void) void kmain(void)
{ {
asm("cpsie i"); asm("cpsie i");
dsp_init(); dsp_init();
dsp_rect(0, 0, LCD_WIDTH, LCD_HEIGHT, dsp_color(0, 0, 0)); dsp_rect(0, 0, LCD_WIDTH, LCD_HEIGHT, dsp_color(0, 0, 0));
dsp_cursoron(); dsp_cursoron();

@ -3,77 +3,78 @@
#include <stm32l476xx.h> #include <stm32l476xx.h>
typedef struct { typedef struct {
uint32_t *sp; void *next;
uint8_t use;
uint32_t *stack; uint32_t *stack;
void (*code)(void); uint32_t *sp;
} task_t; } task_t;
#define MAX_TASKS 6 static task_t *current;
static uint8_t task_disable = 0;
static task_t tasks[MAX_TASKS]; void task_hold(uint8_t hold)
static volatile int next_idx = 0; {
if (hold != 0)
task_disable++;
else if (task_disable > 0)
task_disable--;
}
static uint8_t task_enable = 0; void task_exit(void)
{
// TODO free stack?
// TODO remove from chain
// hopefully current is preserved..?
while (1); // bye
}
void task_hold(uint8_t hold) task_t *task_create(void (*code)(void), uint32_t stackSize)
{ {
task_enable = !hold; task_t *t = (task_t *)malloc(sizeof(task_t));
t->next = 0;
t->stack = (uint32_t *)malloc(stackSize);
t->sp = (void *)t->stack + stackSize - 64;//16;
t->sp[13] = (uint32_t)task_exit;
t->sp[14] = (uint32_t)code;
t->sp[15] = 0x01000000;
return t;
} }
void task_init(void (*init)(void)) void task_init(void (*init)(void))
{ {
for (int i = 0; i < MAX_TASKS; i++) current = task_create(init, 4096);
tasks[i].use = 0; current->next = current;
// bit 0 - priv, bit 1 - psp/msp
task_start(init, 4096);
asm("\ asm("\
msr psp, %0; \ msr psp, %0; \
mrs r0, control; \ mrs r0, control; \
orr r0, r0, #3; \ orr r0, r0, #2; \
msr control, r0; \ msr control, r0; \
isb; \ isb; \
" :: "r" (tasks[0].sp)); " :: "r" (current->sp));
task_enable = 1; task_disable = 0;
init(); init();
} // you dirty dirty dog
/*asm("\
extern void _exit(int); cpsie i; \
void task_exit(void) mov pc, %0; \
{ " :: "r" (init + 4));*/
// TODO free stack?
asm("cpsid i"); // hope to catch next_idx
tasks[next_idx].use = 0;
asm("cpsie i");
while (1); // bye
} }
void task_start(void (*task)(void), uint16_t stackSize) void task_start(void (*task)(void), uint16_t stackSize)
{ {
asm("cpsid i"); // just to be safe task_hold(1);
task_t *t = task_create(task, stackSize);
for (int i = 0; i < MAX_TASKS; i++) { task_t *next = (task_t *)current->next;
if (tasks[i].use == 0) { current->next = t;
tasks[i].stack = malloc(stackSize); t->next = next;
tasks[i].sp = tasks[i].stack + stackSize - 16; task_hold(0);
tasks[i].sp[13] = (uint32_t)task_exit;
tasks[i].sp[14] = (uint32_t)task;
tasks[i].sp[15] = 0x01000000;
tasks[i].use = 1;
tasks[i].code = task;
asm("cpsie i");
return;
}
}
// TODO handle error
} }
__attribute__ ((naked)) __attribute__ ((naked))
void PendSV_Handler(void) void PendSV_Handler(void)
{ {
if (task_enable == 0) if (task_disable != 0)
asm("bx lr"); asm("bx lr");
// save state // save state
@ -84,15 +85,9 @@ void PendSV_Handler(void)
mrs r0, psp; \ mrs r0, psp; \
stmdb r0!, {r4-r11}; \ stmdb r0!, {r4-r11}; \
mov %0, r0; \ mov %0, r0; \
" : "=r" (tasks[next_idx].sp)); " : "=r" (current->sp));
// find next task (round-robin style) current = current->next;
do {
if (++next_idx == MAX_TASKS) {
next_idx = 0;
break; // task 0 better exist
}
} while (tasks[next_idx].use == 0);
// restore // restore
asm("\ asm("\
@ -101,11 +96,10 @@ void PendSV_Handler(void)
msr psp, r0; \ msr psp, r0; \
isb; \ isb; \
dsb; \ dsb; \
" :: "r" (tasks[next_idx].sp)); " :: "r" (current->sp));
// end // end
asm("\ asm("\
mov r0, #0xFFFFFFFD; \
cpsie i; \ cpsie i; \
bx lr; \ bx lr; \
"); ");

Loading…
Cancel
Save