做了一个比较简单的调度器. 可以多任务运行,不支持抢占。
由于这个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 <list.h> #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 <stdio.h> #include <malloc.h> #include <task_struct.h> #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 <stdio.h> #include <malloc.h> #include <task_struct.h> 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