任务调度器代码:

任务调度器代码:

(1)头文件:任务控制块TCB定义、保存任务环境的入栽宏、恢复任务现场的出栽宏。
typedef struct
{
    unsigned char* task_stk_top;  //保存任务的栽顶
    unsigned char task_stack[100];//任务堆栽
      
}OS_TASK_TCB;

//任务现场保护,保存所有寄存器的宏
#define pushall() \
__asm__ __volatile__ ("push r1"   "\n\t");\
__asm__ __volatile__ ("push r0"   "\n\t");\
__asm__ __volatile__ ("in  r0, 0x3f"   "\n\t");\保存CPU状态寄存器
__asm__ __volatile__ ("push r0"   "\n\t");\
__asm__ __volatile__ ("eor r1, r1"   "\n\t");\WINAVR要求R1等于0
__asm__ __volatile__ ("push r2"   "\n\t");\
__asm__ __volatile__ ("push r3"   "\n\t");\
__asm__ __volatile__ ("push r4"   "\n\t");\
__asm__ __volatile__ ("push r5"   "\n\t");\
__asm__ __volatile__ ("push r6"   "\n\t");\
__asm__ __volatile__ ("push r7"   "\n\t");\
__asm__ __volatile__ ("push r8"   "\n\t");\
__asm__ __volatile__ ("push r9"   "\n\t");\
__asm__ __volatile__ ("push r10"   "\n\t");\
__asm__ __volatile__ ("push r11"   "\n\t");\
__asm__ __volatile__ ("push r12"   "\n\t");\
__asm__ __volatile__ ("push r13"   "\n\t");\
__asm__ __volatile__ ("push r14"   "\n\t");\
__asm__ __volatile__ ("push r15"   "\n\t");\
__asm__ __volatile__ ("push r16"   "\n\t");\
__asm__ __volatile__ ("push r17"   "\n\t");\
__asm__ __volatile__ ("push r18"   "\n\t");\
__asm__ __volatile__ ("push r19"   "\n\t");\
__asm__ __volatile__ ("push r20"   "\n\t");\
__asm__ __volatile__ ("push r21"   "\n\t");\
__asm__ __volatile__ ("push r22"   "\n\t");\
__asm__ __volatile__ ("push r23"   "\n\t");\
__asm__ __volatile__ ("push r24"   "\n\t");\
__asm__ __volatile__ ("push r25"   "\n\t");\
__asm__ __volatile__ ("push r26"   "\n\t");\
__asm__ __volatile__ ("push r27"   "\n\t");\
__asm__ __volatile__ ("push r28"   "\n\t");\
__asm__ __volatile__ ("push r29"   "\n\t");\
__asm__ __volatile__ ("push r30"   "\n\t");\
__asm__ __volatile__ ("push r31"   "\n\t");\

//恢复任务现场,弹出所有寄存器的宏
#define popall() \
__asm__ __volatile__ ("pop r31"   "\n\t");\
__asm__ __volatile__ ("pop r30"   "\n\t");\
__asm__ __volatile__ ("pop r29"   "\n\t");\
__asm__ __volatile__ ("pop r28"   "\n\t");\
__asm__ __volatile__ ("pop r27"   "\n\t");\
__asm__ __volatile__ ("pop r26"   "\n\t");\
__asm__ __volatile__ ("pop r25"   "\n\t");\
__asm__ __volatile__ ("pop r24"   "\n\t");\
__asm__ __volatile__ ("pop r23"   "\n\t");\
__asm__ __volatile__ ("pop r22"   "\n\t");\
__asm__ __volatile__ ("pop r21"   "\n\t");\
__asm__ __volatile__ ("pop r20"   "\n\t");\
__asm__ __volatile__ ("pop r19"   "\n\t");\
__asm__ __volatile__ ("pop r18"   "\n\t");\
__asm__ __volatile__ ("pop r17"   "\n\t");\
__asm__ __volatile__ ("pop r16"   "\n\t");\
__asm__ __volatile__ ("pop r15"   "\n\t");\
__asm__ __volatile__ ("pop r14"   "\n\t");\
__asm__ __volatile__ ("pop r13"   "\n\t");\
__asm__ __volatile__ ("pop r12"   "\n\t");\
__asm__ __volatile__ ("pop r11"   "\n\t");\
__asm__ __volatile__ ("pop r10"   "\n\t");\
__asm__ __volatile__ ("pop r9"   "\n\t");\
__asm__ __volatile__ ("pop r8"   "\n\t");\
__asm__ __volatile__ ("pop r7"   "\n\t");\
__asm__ __volatile__ ("pop r6"   "\n\t");\
__asm__ __volatile__ ("pop r5"   "\n\t");\
__asm__ __volatile__ ("pop r4"   "\n\t");\
__asm__ __volatile__ ("pop r3"   "\n\t");\
__asm__ __volatile__ ("pop r2"   "\n\t");\
__asm__ __volatile__ ("pop r0"   "\n\t");\
__asm__ __volatile__ ("out 0x3f, r0"   "\n\t");\恢复CPU状态寄存器
__asm__ __volatile__ ("pop r0"   "\n\t");\
__asm__ __volatile__ ("pop r1"   "\n\t");\
__asm__ __volatile__ ("RETI"   "\n\t");\
//******************************************************************

(2)主函数main()代码,包括8个任务,调度程序,定义8个任务,每个任务对应一个LED灯的闪烁:
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "RTOS.h"

#define  LED_PORT   PORTA //LED端口定义
#define  LED_DDR    DDRA
#define  LED_PIN      PINA

//第1个任务定义
void task1( void )
{   
    unsigned char temp ;//任务1的局部变量
   
    //在任务1启动节拍定时器
    TCCR0 = 0X05;//定时器0初始化
    TIMSK = 0X01;                    
    TCNT0 = 0x00;

    sei();//打开全局中断
      
    while(1)
    {         
         temp++;  

         LED_PORT ^=0X01;
         for( unsigned char i=0; i<250; i++)
           _delay_ms(10);
    }     
}

//第2个任务定义
void task2(void)
{     
    while(1)
    {         
       LED_PORT ^=0X02;
       for( unsigned char i=0; i<250; i++)
         _delay_ms(10);
    }
}

//第3个任务定义
void task3(void)
{
    while(1)
    {        
       LED_PORT ^=0X04;
       for( unsigned char i=0; i<250; i++)
         _delay_ms(10);
    }
}

//第4个任务定义
void task4(void)
{
    while(1)
    {         
       LED_PORT ^=0X08;
       for( unsigned char i=0; i<250; i++)
         _delay_ms(10);
    }
}

//第5个任务定义
void task5(void)
{
    while(1)
    {        
       LED_PORT ^=0X10;
       for( unsigned char i=0; i<250; i++)
         _delay_ms(10);
    }
}

//第6个任务定义
void task6(void)
{
    while(1)
    {         
       LED_PORT ^=0X20;
       for( unsigned char i=0; i<250; i++)
         _delay_ms(10);
    }
}

//第7个任务定义
void task7(void)
{
    while(1)
    {         
      LED_PORT ^=0X40;
      for( unsigned char i=0; i<250; i++)
        _delay_ms(10);
    }
}

//第8个任务定义
void task8(void)
{
    while(1)
    {         
      LED_PORT ^=0X80;
      for( unsigned char i=0; i<250; i++)
         _delay_ms(10);
    }
}
//*******************************************************************

volatile unsigned char next_task = 0;//用来指出下一个运行的任务

//计数变量,在定时器0中断函数里加1,用来控制任务切换频率
volatile unsigned char count = 0;

volatile OS_TASK_TCB task_tcb[ 8 ];//定义8个任务的任务控制块TCB数组



//任务堆栽初始化函数,参数为:任务入口地址、任务序号(1-8)
unsigned char* stackinit( void (*task)( void ), unsigned char task_id )
{
    unsigned char* stk;
    unsigned int temp;      
      
    temp = (unsigned int)task;//任务入口地址     
      
    stk = &( task_tcb[task_id].task_stack[99] );//取得任务栽顶指针
    *stk-- = (unsigned char)(temp&0xff);//将任务入口地址入栽
    *stk-- = (unsigned char)(temp>>8);

    //以下是CPU所有寄存器初始化,为0值,
    *stk-- = (unsigned char)0x00;        /* R0  = 0x00 */
    *stk-- = (unsigned char)0x00;        /* R1  = 0x00 */
    *stk-- = (unsigned char)0x80;        /* R2  = 0x00 */
    *stk-- = (unsigned char)0x00;        /* R3  = 0x00 */
    *stk-- = (unsigned char)0x00;        /* R4  = 0x00 */
    *stk-- = (unsigned char)0x00;        /* R5  = 0x00 */
    *stk-- = (unsigned char)0x00;        /* R6  = 0x00 */
    *stk-- = (unsigned char)0x00;        /* R7  = 0x00 */
    *stk-- = (unsigned char)0x00;        /* R8  = 0x00 */
    *stk-- = (unsigned char)0x00;        /* R9  = 0x00 */
    *stk-- = (unsigned char)0x00;        /* R10 =      */
    *stk-- = (unsigned char)0x00;        /* R11 =      */
    *stk-- = (unsigned char)0x00;        /* R12 =      */
    *stk-- = (unsigned char)0x00;        /* R13 =      */
    *stk-- = (unsigned char)0x00;        /* R14 =      */
    *stk-- = (unsigned char)0x00;        /* R15 =      */
    *stk-- = (unsigned char)0x00;        /* R16 =      */
    *stk-- = (unsigned char)0x00;        /* R17 =      */
    *stk-- = (unsigned char)0x00;        /* R18 =      */
    *stk-- = (unsigned char)0x00;        /* R19 =      */
    *stk-- = (unsigned char)0x00;        /* R20 =      */
    *stk-- = (unsigned char)0x00;        /* R21 =      */
    *stk-- = (unsigned char)0x00;        /* R22 =      */
    *stk-- = (unsigned char)0x00;        /* R23 =      */
    *stk-- = (unsigned char)0x00;        /* R24 = 0x00 */
    *stk-- = (unsigned char)0x00;        /* R25 = 0x00 */
    *stk-- = (unsigned char)0x00;        /* R26 =      */
    *stk-- = (unsigned char)0x00;        /* R27 =      */
    *stk-- = (unsigned char)0x00;        /* R28 =      */
    *stk-- = (unsigned char)0x00;        /* R29 =      */
    *stk-- = (unsigned char)0x00;        /* R30 =      */
    *stk-- = (unsigned char)0x00;        /* R31 =      */
    *stk-- = (unsigned char)0x00;        /* SREG =    */
    return ( (unsigned char*)stk );//返回当前堆栈指针
}

//任务创建函数:
void taskcreat( void (*task)( void ), unsigned char task_id )
{
    unsigned char *temp;

    temp = stackinit( task, task_id );//堆栽初始化,并返回栽顶指针
     
    //初始化之后将堆栽栽顶指针保存在任务的TCB里,这个变量一直指向栽顶
    task_tcb[task_id].task_stk_top = temp;
}


//调度器启动函数,用于运行第一个任务
void OS_Start( void )
{     
    SP = task_tcb[0].task_stk_top + 33;//堆栽指针指向第一个任务

    //用中断返回指令将入口地址弹出到PC指针,运行第一个任务
    asm("RETI");
}

//定时器0的中断函数:作周期中断,每次中断,表示当前任务的时间片用完,将结束当前任务,调用下一个任务
//加上下面这句,WINAVR将不保存任何寄存器
void SIG_OVERFLOW0( void ) __attribute__ ( ( signal, naked ) );
SIGNAL( SIG_OVERFLOW0 )  
{     
    pushall( );//自己人工保存所有寄存器

    count++;   //每次中断加1
    if(count>100)//100时任务切换,count值可以调整任务切换频率
    {
         count = 0;//重新清0
         
         task_tcb[ next_task % 8 ].task_stk_top =SP;//保存当前任务的栽顶SP指针到当前任务的控制块TCB
           
         next_task++;指向下一个任务
               
         //堆栽指针指向下一个任务栽顶
         SP = task_tcb[ next_task % 8 ].task_stk_top;
    }

    popall( );//人工恢复所有寄存器
}


//main()函数
int main( void )
{   
    //LED灯控制端口设置
    LED_PORT=0Xff;
    LED_DDR =0Xff;     
      
    //创建并初始化8个任务
    taskcreat( task1, 0 );
    taskcreat( task2, 1 );
    taskcreat( task3, 2 );
    taskcreat( task4, 3 );
    taskcreat( task5, 4 );
    taskcreat( task6, 5 );
    taskcreat( task7, 6 );
    taskcreat( task8, 7 );
      
    OS_Start( );//开始运行任务
      
    while( 1 );   
}//****************************************************************

posted @ 2013-12-09 01:38  雨花梦  阅读(507)  评论(0编辑  收藏  举报