• <li id="00i08"><input id="00i08"></input></li>
  • <sup id="00i08"><tbody id="00i08"></tbody></sup>
    <abbr id="00i08"></abbr>
  • 新聞中心

    EEPW首頁 > 嵌入式系統 > 設計應用 > 建立一個屬于自己的AVR的RTOS

    建立一個屬于自己的AVR的RTOS

    作者: 時間:2011-04-29 來源:網絡 收藏

    unsignedintOSWaitTick;//任務延時時鐘
    }TCB[OS_TASKS+1];

    //防止被編譯器占用
    registerunsignedchartempR4asm(r4);
    registerunsignedchartempR5asm(r5);
    registerunsignedchartempR6asm(r6);
    registerunsignedchartempR7asm(r7);
    registerunsignedchartempR8asm(r8);
    registerunsignedchartempR9asm(r9);
    registerunsignedchartempR10asm(r10);
    registerunsignedchartempR11asm(r11);
    registerunsignedchartempR12asm(r12);
    registerunsignedchartempR13asm(r13);
    registerunsignedchartempR14asm(r14);
    registerunsignedchartempR15asm(r15);
    registerunsignedchartempR16asm(r16);
    registerunsignedchartempR16asm(r17);


    //任務
    voidOSTaskCreate(void(*Task)(void),unsignedchar*Stack,unsignedcharTaskID)
    {
    unsignedchari;
    *Stack--=(unsignedint)Task>>8;//將任務的地址高位壓入堆棧,
    *Stack--=(unsignedint)Task;//將任務的地址低位壓入堆棧,

    *Stack--=0x00;//R1__zero_reg__
    *Stack--=0x00;//R0__tmp_reg__
    *Stack--=0x80;//SREG在任務中,開啟全局中斷
    for(i=0;i14;i++)//在avr-libc中的FAQ中的WhatregistersareusedbytheCcompiler?
    *Stack--=i;//描述了寄存器的作用
    TCB[TaskID].OSTaskStackTop=(unsignedint)Stack;//將人工堆棧的棧頂,保存到堆棧的數組中
    OSRdyTbl|=0x01TaskID;//任務就緒表已經準備好
    }

    //開始任務調度,從最低優先級的任務的開始
    voidOSStartTask()
    {
    OSTaskRunningPrio=OS_TASKS;
    SP=TCB[OS_TASKS].OSTaskStackTop+17;
    __asm____volatile__(retint);
    }

    //進行任務調度
    voidOSSched(void)
    {
    //根據中斷時保存寄存器的次序入棧,模擬一次中斷后,入棧的情況
    __asm____volatile__(PUSH__zero_reg__nt);//R1
    __asm____volatile__(PUSH__tmp_reg__nt);//R0
    __asm____volatile__(IN__tmp_reg__,__SREG__nt);//保存狀態寄存器SREG
    __asm____volatile__(PUSH__tmp_reg__nt);
    __asm____volatile__(CLR__zero_reg__nt);//R0重新清零
    __asm____volatile__(PUSHR18nt);
    __asm____volatile__(PUSHR19nt);
    __asm____volatile__(PUSHR20nt);
    __asm____volatile__(PUSHR21nt);
    __asm____volatile__(PUSHR22nt);
    __asm____volatile__(PUSHR23nt);
    __asm____volatile__(PUSHR24nt);
    __asm____volatile__(PUSHR25nt);
    __asm____volatile__(PUSHR26nt);
    __asm____volatile__(PUSHR27nt);
    __asm____volatile__(PUSHR30nt);
    __asm____volatile__(PUSHR31nt);
    __asm____volatile__(PUSHR28nt);//R28與R29用于在堆棧上的指針
    __asm____volatile__(PUSHR29nt);//入棧完成

    TCB[OSTaskRunningPrio].OSTaskStackTop=SP;//將正在運行的任務的堆棧底保存


    unsignedcharOSNextTaskID;//在現有堆棧上開設新的空間
    for(OSNextTaskID=0;//進行任務調度
    OSNextTaskIDOS_TASKS!(OSRdyTbl(0x01OSNextTaskID));
    OSNextTaskID++);
    OSTaskRunningPrio=OSNextTaskID;

    cli();//保護堆棧轉換
    SP=TCB[OSTaskRunningPrio].OSTaskStackTop;
    sei();

    //根據中斷時的出棧次序
    __asm____volatile__(POPR29nt);
    __asm____volatile__(POPR28nt);
    __asm____volatile__(POPR31nt);
    __asm____volatile__(POPR30nt);
    __asm____volatile__(POPR27nt);
    __asm____volatile__(POPR26nt);
    __asm____volatile__(POPR25nt);
    __asm____volatile__(POPR24nt);
    __asm____volatile__(POPR23nt);
    __asm____volatile__(POPR22nt);
    __asm____volatile__(POPR21nt);
    __asm____volatile__(POPR20nt);
    __asm____volatile__(POPR19nt);
    __asm____volatile__(POPR18nt);
    __asm____volatile__(POP__tmp_reg__nt);//SERG出棧并恢復
    __asm____volatile__(OUT__SREG__,__tmp_reg__nt);//
    __asm____volatile__(POP__tmp_reg__nt);//R0出棧
    __asm____volatile__(POP__zero_reg__nt);//R1出棧
    //中斷時出棧完成
    }

    voidOSTimeDly(unsignedintticks)
    {
    if(ticks)//當延時有效
    {
    OSRdyTbl=~(0x01OSTaskRunningPrio);
    TCB[OSTaskRunningPrio].OSWaitTick=ticks;
    OSSched();//從新調度
    }
    }


    voidTCN0Init(void)//計時器0
    {
    TCCR0=0;
    TCCR0|=(1CS02);//256預分頻
    TIMSK|=(1TOIE0);//T0溢出中斷允許
    TCNT0=100;//置計數起始值

    }


    SIGNAL(SIG_OVERFLOW0)
    {
    unsignedchari;
    for(i=0;iOS_TASKS;i++)//任務時鐘
    {
    if(TCB[i].OSWaitTick)
    {
    TCB[i].OSWaitTick--;
    if(TCB[i].OSWaitTick==0)//當任務時鐘到時,必須是由定時器減時的才行
    {
    OSRdyTbl|=(0x01i);//使任務在就緒表中置位
    }
    }
    }
    TCNT0=100;
    }

    voidTask0()
    {
    unsignedintj=0;
    while(1)
    {
    PORTB=j++;
    OSTimeDly(2);
    }
    }

    voidTask1()
    {
    unsignedintj=0;
    while(1)
    {
    PORTC=j++;
    OSTimeDly(4);
    }
    }

    voidTask2()
    {
    unsignedintj=0;
    while(1)
    {
    PORTD=j++;
    OSTimeDly(8);
    }
    }



    voidTaskScheduler()
    {
    while(1)
    {
    OSSched();//反復進行調度
    }
    }


    intmain(void)
    {
    TCN0Init();
    OSRdyTbl=0;
    OSTaskRunningPrio=0;
    OSTaskCreate(Task0,Stack[49],0);
    OSTaskCreate(Task1,Stack[99],1);
    OSTaskCreate(Task2,Stack[149],2);
    OSTaskCreate(TaskScheduler,Stack[199],OS_TASKS);
    OSStartTask();
    }

    在上面的例子中,一切變得很簡單,三個正在運行的主任務,都通過延時服務,主動放棄對CPU的控制權。
    在時間中斷中,對各個任務的的延時進行計時,如果某個任務的延時結束,將任務重新在就緒表中置位。
    最低級的系統任務TaskScheduler(),在三個主任務在放棄對CPU的控制權后開始不斷地進行調度。如果某個任務在就緒表中置位,通過調度,進入最高級別的任務中繼續運行。

    第五篇:完善的協作式的內核

    現在為上面的協作式內核添加一些OS中所必須的服務:
    1掛起和重新運行任務
    2信號量(在必要時候,可以擴展成郵箱和信息隊列)
    3延時


    #includeavr/io.h>
    #includeavr/Interrupt.h>
    #includeavr/signal.h>
    unsignedcharStack[400];

    registerunsignedcharOSRdyTblasm(r2);//任務運行就緒表
    registerunsignedcharOSTaskRunningPrioasm(r3);//正在運行的任務

    #defineOS_TASKS3//設定運行任務的數量
    structTaskCtrBlock
    {
    unsignedintOSTaskStackTop;//保存任務的堆棧頂
    unsignedintOSWaitTick;//任務延時時鐘
    }TCB[OS_TASKS+1];

    //防止被編譯器占用
    registerunsignedchartempR4asm(r4);
    registerunsignedchartempR5asm(r5);
    registerunsignedchartempR6asm(r6);
    registerunsignedchartempR7asm(r7);
    registerunsignedchartempR8asm(r8);
    registerunsignedchartempR9asm(r9);
    registerunsignedchartempR10asm(r10);
    registerunsignedchartempR11asm(r11);
    registerunsignedchartempR12asm(r12);
    registerunsignedchartempR13asm(r13);
    registerunsignedchartempR14asm(r14);
    registerunsignedchartempR15asm(r15);
    registerunsignedchartempR16asm(r16);
    registerunsignedchartempR16asm(r17);


    //任務
    voidOSTaskCreate(void(*Task)(void),unsignedchar*Stack,unsignedcharTaskID)
    {
    unsignedchari;
    *Stack--=(unsignedint)Task>>8;//將任務的地址高位壓入堆棧,
    *Stack--=(unsignedint)Task;//將任務的地址低位壓入堆棧,

    *Stack--=0x00;//R1__zero_reg__
    *Stack--=0x00;//R0__tmp_reg__
    *Stack--=0x80;

    //SREG在任務中,開啟全局中斷
    for(i=0;i14;i++)//在avr-libc中的FAQ中的WhatregistersareusedbytheCcompiler?
    *Stack--=i;//描述了寄存器的作用
    TCB[TaskID].OSTaskStackTop=(unsignedint)Stack;//將人工堆棧的棧頂,保存到堆棧的數組中
    OSRdyTbl|=0x01TaskID;//任務就緒表已經準備好
    }

    //開始任務調度,從最低優先級的任務的開始
    voidOSStartTask()
    {
    OSTaskRunningPrio=OS_TASKS;
    SP=TCB[OS_TASKS].OSTaskStackTop+17;
    __asm____volatile__(retint);
    }

    //進行任務調度
    voidOSSched(void)
    {
    //根據中斷時保存寄存器的次序入棧,模擬一次中斷后,入棧的情況
    __asm____volatile__(PUSH__zero_reg__nt);//R1
    __asm____volatile__(PUSH__tmp_reg__nt);//R0
    __asm____volatile__(IN__tmp_reg__,__SREG__nt);//保存狀態寄存器SREG
    __asm____volatile__(PUSH__tmp_reg__nt);
    __asm____volatile__(CLR__zero_reg__nt);//R0重新清零
    __asm____volatile__(PUSHR18nt);
    __asm____volatile__(PUSHR19nt);
    __asm____volatile__(PUSHR20nt);
    __asm____volatile__(PUSHR21nt);
    __asm____volatile__(PUSHR22nt);
    __asm____volatile__(PUSHR23nt);
    __asm____volatile__(PUSHR24nt);
    __asm____volatile__(PUSHR25nt);
    __asm____volatile__(PUSHR26nt);
    __asm____volatile__(PUSHR27nt);
    __asm____volatile__(PUSHR30nt);
    __asm____volatile__(PUSHR31nt);
    __asm____volatile__(PUSHR28nt);//R28與R29用于建立在堆棧上的指針


    評論


    相關推薦

    技術專區

    關閉
    主站蜘蛛池模板: 伊金霍洛旗| 淮阳县| 灵宝市| 莱西市| 樟树市| 兴仁县| 河北省| 富蕴县| 潜江市| 泗洪县| 封开县| 宜州市| 道孚县| 剑河县| 封开县| 岳普湖县| 静海县| 如东县| 奉化市| 乐平市| 讷河市| 专栏| 临安市| 黑山县| 武平县| 德令哈市| 鄂温| 磐石市| 龙泉市| 无棣县| 开化县| 彝良县| 越西县| 汝南县| 汉源县| 湟中县| 阳曲县| 神农架林区| 金华市| 习水县| 五寨县|