heap; multitasking
parent
de7c4fb07d
commit
058c283919
@ -0,0 +1,38 @@
|
|||||||
|
#include <heap.h>
|
||||||
|
#include <stm32l476xx.h>
|
||||||
|
|
||||||
|
#define RAM_END 0x20018000
|
||||||
|
|
||||||
|
//extern void *end;
|
||||||
|
//extern uint32_t _total_ram;
|
||||||
|
static uint32_t offset = 0;
|
||||||
|
|
||||||
|
__attribute__ ((section(".data")))
|
||||||
|
uint8_t heap[8192];
|
||||||
|
void *end = heap;
|
||||||
|
|
||||||
|
void heap_init(void)
|
||||||
|
{
|
||||||
|
// what to do...
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t heap_available(void)
|
||||||
|
{
|
||||||
|
return 0;// return _total_ram - offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *hmalloc(uint32_t size)
|
||||||
|
{
|
||||||
|
void *alloc = end + offset;
|
||||||
|
offset += size;
|
||||||
|
return alloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *hcalloc(uint32_t count, uint32_t size)
|
||||||
|
{
|
||||||
|
uint32_t total = count * size;
|
||||||
|
void *alloc = hmalloc(total);
|
||||||
|
for (uint32_t i = 0; i < total; i++)
|
||||||
|
((uint8_t *)alloc)[i] = 0;
|
||||||
|
return alloc;
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
#ifndef HEAP_H_
|
||||||
|
#define HEAP_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
uint32_t heap_available(void);
|
||||||
|
|
||||||
|
void *hmalloc(uint32_t size);
|
||||||
|
void *hcalloc(uint32_t count, uint32_t size);
|
||||||
|
|
||||||
|
#endif // HEAP_H_
|
@ -0,0 +1,10 @@
|
|||||||
|
#ifndef TASK_H_
|
||||||
|
#define TASK_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void task_init(void (*init)(void));
|
||||||
|
|
||||||
|
void task_start(void (*task)(void), uint16_t stackSize);
|
||||||
|
|
||||||
|
#endif // TASK_H_
|
@ -0,0 +1,108 @@
|
|||||||
|
#include <task.h>
|
||||||
|
#include <heap.h>
|
||||||
|
#include <stm32l476xx.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t *sp;
|
||||||
|
uint8_t use;
|
||||||
|
uint32_t *stack;
|
||||||
|
void (*code)(void);
|
||||||
|
} task_t;
|
||||||
|
|
||||||
|
#define MAX_TASKS 4
|
||||||
|
|
||||||
|
static task_t tasks[MAX_TASKS];
|
||||||
|
static int next_idx = 0;
|
||||||
|
|
||||||
|
void task_init(void (*init)(void))
|
||||||
|
{
|
||||||
|
for (int i = 0; i < MAX_TASKS; i++)
|
||||||
|
tasks[i].use = 0;
|
||||||
|
|
||||||
|
task_start(init, 1024);
|
||||||
|
asm("\
|
||||||
|
msr psp, %0; \
|
||||||
|
mrs r0, control; \
|
||||||
|
orr r0, r0, #2; \
|
||||||
|
msr control, r0; \
|
||||||
|
isb; \
|
||||||
|
" :: "r" (tasks[0].sp));
|
||||||
|
|
||||||
|
init();
|
||||||
|
|
||||||
|
// force switch to tasking, call pendsv
|
||||||
|
//SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
//_exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = hmalloc(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
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__ ((naked))
|
||||||
|
void PendSV_Handler(void)
|
||||||
|
{
|
||||||
|
// save state
|
||||||
|
//stmdb r0!, {r4-r11};
|
||||||
|
asm("\
|
||||||
|
cpsid i; \
|
||||||
|
isb; \
|
||||||
|
dsb; \
|
||||||
|
mrs r0, psp; \
|
||||||
|
stmdb r0!, {r4-r11}; \
|
||||||
|
mov %0, r0; \
|
||||||
|
" : "=r" (tasks[next_idx].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);
|
||||||
|
|
||||||
|
// restore
|
||||||
|
//ldmia r0!, {r4-r11};
|
||||||
|
asm("\
|
||||||
|
mov r0, %0; \
|
||||||
|
ldmia r0!, {r4-r11}; \
|
||||||
|
msr psp, r0; \
|
||||||
|
isb; \
|
||||||
|
dsb; \
|
||||||
|
" :: "r" (tasks[next_idx].sp));
|
||||||
|
|
||||||
|
// end
|
||||||
|
asm("\
|
||||||
|
mov r0, #0xFFFFFFFD; \
|
||||||
|
cpsie i; \
|
||||||
|
bx r0; \
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue