zoukankan      html  css  js  c++  java
  • 任务调度器代码:

    任务调度器代码:

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

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

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

    (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 );   
    }//****************************************************************

  • 相关阅读:
    Vue项目端口号占用
    理解vuex -- vue的状态管理模式
    2018-7-10杂记
    JS 数组操作总结
    JS 字符串操作总结
    【javascript练习题】函数
    【javascript练习题】this指针和作用域
    canal实时同步mysql binlog到rabbitmq
    Hexo+GitHub+Netlify一站式搭建属于自己的博客网站
    Git学习原版手稿
  • 原文地址:https://www.cnblogs.com/yuhuameng/p/3464563.html
Copyright © 2011-2022 走看看