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