我的RTOS 之七 -- 调度器

做了一个比较简单的调度器. 可以多任务运行,不支持抢占。

由于这个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结构体和task运行状态的定义

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;
}

运行如图:

我的RTOS 之七 -- 调度器_第1张图片


下载链接:

http://download.csdn.net/detail/liujia2100/9437893

编译命令:make

运行命令: skyeye -e wd_task



你可能感兴趣的:(ARM&RTOS)