做了一个比较简单的调度器. 可以多任务运行,不支持抢占。
由于这个OS不支持抢占,不需要修改中断服务程序,可以方便的嵌入到ARM任何裸机代码或者OS中。
以后再慢慢完善
运行环境: cygwin skyeye 2410.
底层api, 需要一个定时器和几行汇编即可
在timer中设置一个全局变量 类似linux中的jiffies
volatile unsigned int jiffies;
void timer_handler(void)
{
static int count = 0;
jiffies++;
}
调度器的核心汇编,由于没有抢占,所有不需要在中断中做特殊处理
.extern void *run_stack
.global enter_wd_task
enter_wd_task:
mrs r1, cpsr
str r1, [r0]
stmib r0!, {r4-r11, r12, r13, r14}
ldr r0, =wd_task_stack
add r0, r0, #(2048*4)
mov sp, r0
bl wd_task_main
.global exit_wd_task
exit_wd_task:
ldr r1, [r0]
msr cpsr, r1
add r0, r0, #4
ldmfd r0!, { r4-r11, r12, r13, pc}
// bx lr
// r0, the task_run stack, r1 the task stack
.global enter_task_schedule
enter_task_schedule:
mrs r2, cpsr
str r2, [r0]
stmib r0!, {r4-r11, r12, r13, r14}
ldr r2, [r1]
msr cpsr, r2
add r1, r1, #4
ldmfd r1!, {r4-r11, r12, r13, r14, pc}
.global exit_task_schedule
exit_task_schedule:
mov r2, sp
mrs r3, cpsr
stmfd r2!, {r14} //pc
stmfd r2!, {r3, r4-r11, r12, r13, r14}
str r2, [r1] //save task context
ldr r2, [r0]
msr cpsr, r2
add r0, r0, #4
ldmfd r0!, { r4-r11, r12, r13, pc}
.global exit_task_func
exit_task_func:
ldr r0, =run_stack
ldr r0, [r0]
ldr r2, [r0]
msr cpsr, r2
add r0, r0, #4
ldmfd r0!, { r4-r11, r12, r13, pc}
task_struct.h
#ifndef __TASK_STRUCT__
#define __TASK_STRUCT__
#include
#define DEFAULT_TASK_STACK_SIZE 1024
extern volatile unsigned int jiffies;
typedef struct arm_stack_struct {
unsigned int cpsr;
unsigned int r4;
unsigned int r5;
unsigned int r6;
unsigned int r7;
unsigned int r8;
unsigned int r9;
unsigned int r10;
unsigned int r11;
unsigned int r12;
unsigned int r13;
unsigned int lr;
unsigned int pc;
} ARM_STACK;
typedef struct task_struct {
unsigned int task_id;//control block id
unsigned int task_run_count;
void *task_stack_ptr;
void *task_stack_start;
void *task_stack_top;
unsigned int task_stack_size;
void (*task_entry)(void);
unsigned int task_state;
unsigned int task_cur_time;
unsigned int task_end_time;
struct list_node thread_list_node;
struct task_struct
*task_struct_next,
*task_struct_pre;
char *task_name;
}TASK_STRUCT;
//task state
#define TASK_INIT 1
#define TASK_READY 2
#define TASK_SUSPEND 3
#define TASK_SLEEP 4
#define TASK_RUN 5
#define TASK_DELETE 6
#define TASK_FINISH 7
int wd_task_init(void);
int wd_task_run(void);
void task_sleep(unsigned int delay);
int task_suspend(TASK_STRUCT *t);
int task_resume(TASK_STRUCT *t);
int wd_task_destroy(TASK_STRUCT *t);
TASK_STRUCT *wd_task_create(char *name, void (*entry_fun)(void), unsigned int stack_size);
void wd_task_finish();
#endif
task创建和任务调度代码
wd_task.c
#include
#include
#include
#define INT_MAXVAL 0xffffffff// for only 49days in 1ms
TASK_STRUCT * wd_task_created_ptr;
TASK_STRUCT * wd_task_created_head;
TASK_STRUCT * wd_current_task;
static unsigned int task_count_id = 0;
void *run_stack;
extern void exit_task_func();
static void insert_task_list(TASK_STRUCT *t)
{
TASK_STRUCT * tail;
if(wd_task_created_ptr)
{
tail = wd_task_created_ptr->task_struct_pre;
wd_task_created_ptr->task_struct_pre = t;
tail->task_struct_next = t;
t->task_struct_next = wd_task_created_ptr;
t->task_struct_pre = tail;
}
else
{
wd_task_created_ptr = t;
t->task_struct_next = t;
t->task_struct_pre = t;
}
}
static void remove_task_list(TASK_STRUCT *t)
{
if(t->task_struct_next == t || t->task_struct_pre == t)
{
t = NULL;
}
else
{
(t->task_struct_next)->task_struct_pre = t->task_struct_pre;
(t->task_struct_pre)->task_struct_next = t->task_struct_next;
if(wd_task_created_ptr == t)
wd_task_created_ptr = t->task_struct_next;
}
}
TASK_STRUCT *wd_task_create(char *name, void (*entry_fun)(void), unsigned int stack_size)
{
TASK_STRUCT *t;
TASK_STRUCT *p_task;
ARM_STACK *arm_frame;
void *p_stack;
unsigned int cpsr;
t = (TASK_STRUCT *)__malloc(sizeof(TASK_STRUCT));
if(!t)
return NULL;
memset(t, 0, sizeof(TASK_STRUCT));
if(stack_size == 0)
stack_size = DEFAULT_TASK_STACK_SIZE;
// stack_size = (stack_size + 3)&(~0x03);
p_stack = (void *)malloc(stack_size);
if(!p_stack)
return NULL;
t->task_stack_start = p_stack;
t->task_stack_ptr = p_stack;
t->task_stack_top = (void *)(((unsigned int)p_stack + stack_size)&~0x7);
t->task_stack_size = (unsigned int)(t->task_stack_top) - (unsigned int)(t->task_stack_start);
t->task_id = task_count_id++;
t->task_entry = entry_fun;
t->task_name = name;
t->task_state = TASK_INIT;
t->task_cur_time = jiffies;
t->task_end_time = 0;
t->task_run_count = 0;
t->task_struct_next = NULL;
t->task_struct_pre = NULL;
arm_frame = (struct arm_stack_struct *)(t->task_stack_top);
arm_frame --;
t->task_stack_ptr = (void *)arm_frame;
memset(arm_frame, 0, sizeof(*arm_frame));
__asm__ __volatile__("mrs %0, cpsr":"=r"(cpsr));
arm_frame->cpsr = cpsr;
arm_frame->lr = (unsigned int)wd_task_finish;
arm_frame->pc = (unsigned int)entry_fun;
arm_frame->r13 = (unsigned int)arm_frame;
if(!wd_task_created_head)
wd_task_created_head = t;
else{
p_task = wd_task_created_head;
while(p_task->task_struct_next)
{
p_task=p_task->task_struct_next;
}
p_task->task_struct_next = t;
}
return t;
//insert_task_list(t);
}
//task exec finished, will return to run_task.
void wd_task_finish()
{
wd_current_task->task_state = TASK_FINISH;
wd_current_task = NULL;
exit_task_func();
}
int wd_task_destroy(TASK_STRUCT *t)
{
if(t->task_state == TASK_FINISH || t->task_state == TASK_DELETE)
return NULL;
t->task_state = TASK_FINISH;
if(t == wd_current_task)
{
wd_current_task = NULL;
exit_task_func();
}
return 0;
}
static int wd_task_delete(TASK_STRUCT *t)
{
TASK_STRUCT *pt;
TASK_STRUCT *tmpt;
if(!t)
return -1;
if(t == wd_task_created_head)
{
t->task_state = TASK_DELETE;
wd_task_created_head = t->task_struct_next;
free(t->task_stack_start);
}
else
{
for(pt = wd_task_created_head; pt != NULL; pt = pt->task_struct_next)
{
if(t == pt->task_struct_next)
break;
}
if(t == pt->task_struct_next)
{
if(pt->task_struct_next->task_struct_next)
{
tmpt = pt->task_struct_next;
pt->task_struct_next = pt->task_struct_next->task_struct_next;
tmpt->task_state = TASK_DELETE;
free(tmpt->task_stack_start);
}
else
{
free(pt->task_struct_next->task_stack_start);
pt->task_struct_next->task_state = TASK_DELETE;
pt->task_struct_next = NULL;
}
}
}
return 0;
}
void dump_task_list()
{
TASK_STRUCT *t;
for(t = wd_task_created_head; t != NULL; t = t->task_struct_next)
{
printf("task:%s,stack_start:%08x,stack_ptr:%08x, shed_count:%d\n", t->task_name,(unsigned int)t->task_stack_start,(unsigned int)t->task_stack_ptr, t->task_run_count);
}
}
extern void enter_task_schedule(void *run_stack, void *task_stack);
extern void exit_task_schedule(void *run_stack, void *task_stack);
void task_sleep(unsigned int delay)
{
wd_current_task->task_state = TASK_SLEEP;
wd_current_task->task_end_time = jiffies + delay;
exit_task_schedule(run_stack, (void *)(&(wd_current_task->task_stack_ptr)));
}
int task_suspend(TASK_STRUCT *t)
{
// t->task_end_time = INT_MAXVAL;
if(t == NULL || t == wd_current_task)
{
t = wd_current_task;
wd_current_task = NULL;
}
else if(t->task_state == TASK_DELETE
|| t->task_state == TASK_SUSPEND
)
return 0;
t->task_state = TASK_SUSPEND;
exit_task_schedule(run_stack, (void *)(&(t->task_stack_ptr)));
return 0;
}
int task_resume(TASK_STRUCT *t)
{
if(t->task_state == TASK_INIT
|| t->task_state == TASK_READY
|| t->task_state == TASK_RUN
|| t->task_state == TASK_DELETE
)
return 0;
t->task_state = TASK_READY;
// t->task_end_time = INT_MAXVAL;
// if(t == wd_current_task)
// exit_task_schedule(run_stack, (void *)(&(t->task_stack_ptr)));
return 0;
}
int wd_task_init(void)
{
task_count_id = 0;
wd_task_created_ptr = NULL;
wd_task_created_head = NULL;
run_stack = (void *)malloc(1024);
if(!run_stack)
return -1;
return 0;
}
int wd_task_run(void)
{
TASK_STRUCT *t;
int task_mask;
if(!run_stack)
return -1;
if(!wd_task_created_head)
{
printf("No threadx");
return 0;
}
while(1)
{
task_mask = 0;
for(t = wd_task_created_head; t != NULL; t = t->task_struct_next)
{
task_mask |= t->task_state;
if(t->task_state == TASK_FINISH)
{
wd_task_delete(t);
break;
}
else if(t->task_state == TASK_INIT
|| t->task_state == TASK_READY
|| (t->task_state == TASK_SLEEP && t->task_end_time <= jiffies)
)
{
t->task_state = TASK_RUN;
t->task_run_count++;
wd_current_task = t;
if(t->task_state == TASK_SLEEP)
t->task_end_time = INT_MAXVAL;
enter_task_schedule(run_stack, t->task_stack_ptr);
break;
}else if(t->task_state == TASK_RUN)
{
printf("This is error\n");
while(1);
}
}
if(task_mask == 0)
{
printf("No threadx, will exit\n");
break;
}
}
return 0;
}
main.c
#include
#include
#include
void uart_init();
extern volatile int counter;
void delay(unsigned long count)
{
volatile unsigned long i = count;
while (i--);
}
void check_register(unsigned int arg1, unsigned int arg2)
{
printf("arg1=0x%08x, arg2=0x%08x\n", arg1, arg2);
}
extern void exit_wd_task(volatile unsigned int *p);
extern void enter_wd_task(volatile unsigned int *p);
//volatile unsigned int pre_context[20];
volatile unsigned int *wd_task_main_stack;
volatile unsigned int wd_task_stack[2048];
int test[100] = {0};
extern void switest(int arg);
extern int __bss_start;
void wd_test()
{
if(1)
{
wd_task_main_stack = (volatile unsigned int *)malloc(20*sizeof(int));
if(wd_task_main_stack == NULL)
{
printf("malloc error\n");
return;
}
enter_wd_task(wd_task_main_stack);
}
}
void wd_task_main()
{
printf("wd_task_main\n");
exit_wd_task(wd_task_main_stack);
}
TASK_STRUCT *t1;
TASK_STRUCT *t2;
TASK_STRUCT *t3;
TASK_STRUCT *t4;
TASK_STRUCT *t5;
void test1(void)
{
int i;
i = 0;
//while(1)
//{
printf("t1 = %d\n", ++i);
// task_sleep(5);
printf("t1_1 = %d\n", i);
dump_task_list();
printf("t1 game over\n");
//}
}
void test2(void)
{
int i;
i = 0;
while(1)
{
printf("t2 = %d\n", ++i);
task_sleep(10);
// printf("t2_1 = %d\n", i);
if(i == 50)
{
printf("t2 resume t3\n");
task_resume(t3);
printf("t2 break\n");
break;
}
}
}
void test3(void)
{
int i;
i = 0;
while(1)
{
printf("t3 = %d\n", ++i);
task_sleep(15);
// printf("t3_1 = %d\n", i);
if(i == 5)
{
printf("t3 suspend self\n");
task_suspend(NULL);
printf("t3 destroy t2\n");
wd_task_destroy(t2);
}
if(i == 10)
{
printf("t3 finished\n");
wd_task_finish();
}
}
}
void test4(void)
{
int i;
i = 0;
while(1)
{
printf("t4 = %d\n", ++i);
task_sleep(20);
// printf("t4_1 = %d\n", i);
if(i == 5)
{
printf("t1 is suspended\n");
task_suspend(t1);
}
if(i == 10)
{
printf("t1 is resumed\n");
task_resume(t1);
}
}
}
void test5(void)
{
int i;
i = 0;
while(1)
{
printf("t5\n");
dump_task_list();
task_sleep(10);
}
}
int main(void)
{
int temp = 0;
int i;
int ret;
uart_init();
timer_init();
enable_irq();
//printf("__bss_start:0x%08x, addr:0x%08x\n", __bss_start, &__bss_start);
wd_test();
printf("test over\n");
ret = wd_task_init();
if(ret < 0)
printf("task init fail\n");
t1 = wd_task_create("t1", test1, 1024);
t2 = wd_task_create("t2", test2, 1024);
t3 = wd_task_create("t3", test3, 1024);
t4 = wd_task_create("t4", test4, 1024);
t5 = wd_task_create("t5", test5, 1024);
wd_task_run();
while(1);
return 0;
}
下载链接:
http://download.csdn.net/detail/liujia2100/9437893
编译命令:make
运行命令: skyeye -e wd_task