在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > 建立一個AVR單片機RTOS(8)—占先式內(nèi)核(完善的服務(wù))

            建立一個AVR單片機RTOS(8)—占先式內(nèi)核(完善的服務(wù))

            作者: 時間:2016-12-03 來源:網(wǎng)絡(luò) 收藏
            第八篇:占先式內(nèi)核(完善的服務(wù))

            如果將前面所提到的占先式內(nèi)核和協(xié)作式內(nèi)核組合在一起,很容易就可以得到一個功能較為完善的占先式內(nèi)核,它的功能有:

            本文引用地址:http://www.biyoush.com/article/201612/325279.htm

            1,掛起和恢復(fù)任務(wù)

            2,任務(wù)延時

            3,信號量(包括共享型和獨占型)

            另外,在本例中,在各個任務(wù)中加入了從串口發(fā)送任務(wù)狀態(tài)的功能。

            #include <avr/io.h>

            #include

            #include

            unsigned char Stack[400];

            register unsigned char OSRdyTbl asm("r2"); //任務(wù)運行就緒表

            register unsigned char OSTaskRunningPrio asm("r3"); //正在運行的任務(wù)

            register unsigned char IntNum asm("r4"); //中斷嵌套計數(shù)器

            //只有當(dāng)中斷嵌套數(shù)為0,并且有中斷要求時,才能在退出中斷時,進行任務(wù)調(diào)度

            register unsigned char OSCoreState asm("r16"); //系統(tǒng)核心標(biāo)志位,R16編譯器沒有使用

            //只有大于R15的寄存器才能直接賦值例LDI R16,0x01

            //0x01正在任務(wù)切換0x02有中斷要求切換

            #define OS_TASKS 3 //設(shè)定運行任務(wù)的數(shù)量

            struct TaskCtrBlock

            {

            unsigned int OSTaskStackTop; //保存任務(wù)的堆棧頂

            unsigned int OSWaitTick; //任務(wù)延時時鐘

            } TCB[OS_TASKS+1];

            //防止被編譯器占用

            //register unsigned char tempR4 asm("r4");

            register unsigned char tempR5 asm("r5");

            register unsigned char tempR6 asm("r6");

            register unsigned char tempR7 asm("r7");

            register unsigned char tempR8 asm("r8");

            register unsigned char tempR9 asm("r9");

            register unsigned char tempR10 asm("r10");

            register unsigned char tempR11 asm("r11");

            register unsigned char tempR12 asm("r12");

            register unsigned char tempR13 asm("r13");

            register unsigned char tempR14 asm("r14");

            register unsigned char tempR15 asm("r15");

            //register unsigned char tempR16 asm("r16");

            register unsigned char tempR16 asm("r17");

            //建立任務(wù)

            void OSTaskCreate(void (*Task)(void),unsigned char *Stack,unsigned char TaskID)

            {

            unsigned char i;

            *Stack--=(unsigned int)Task>>8; //將任務(wù)的地址高位壓入堆棧,

            *Stack--=(unsigned int)Task; //將任務(wù)的地址低位壓入堆棧,

            *Stack--=0x00; //R1 __zero_reg__

            *Stack--=0x00; //R0 __tmp_reg__

            *Stack--=0x80;

            //SREG在任務(wù)中,開啟全局中斷

            for(i=0;i<14;i++) //在avr-libc中的FAQ中的What registers are used by the C compiler?

            *Stack--=i; //描述了寄存器的作用

            TCB[TaskID].OSTaskStackTop=(unsigned int)Stack; //將人工堆棧的棧頂,保存到堆棧的數(shù)組中

            OSRdyTbl|=0x01<

            }

            //開始任務(wù)調(diào)度,從最低優(yōu)先級的任務(wù)的開始

            void OSStartTask()

            {

            OSTaskRunningPrio=OS_TASKS;

            SP=TCB[OS_TASKS].OSTaskStackTop+17;

            __asm__ __volatile__( "reti" "nt" );

            }

            //進行任務(wù)調(diào)度

            void OSSched(void)

            {

            __asm__ __volatile__("LDI R16,0x01 nt");

            //清除中斷要求任務(wù)切換的標(biāo)志位,設(shè)置正在任務(wù)切換標(biāo)志位

            __asm__ __volatile__("SEI nt");

            //開中斷,因為如果因中斷在任務(wù)調(diào)度中進行,要重新進行調(diào)度時,已經(jīng)關(guān)中斷

            //根據(jù)中斷時保存寄存器的次序入棧,模擬一次中斷后,入棧的情況

            __asm__ __volatile__("PUSH __zero_reg__ nt"); //R1

            __asm__ __volatile__("PUSH __tmp_reg__ nt"); //R0

            __asm__ __volatile__("IN __tmp_reg__,__SREG__ nt"); //保存狀態(tài)寄存器SREG

            __asm__ __volatile__("PUSH __tmp_reg__ nt");

            __asm__ __volatile__("CLR __zero_reg__ nt"); //R0重新清零

            __asm__ __volatile__("PUSH R18 nt");

            __asm__ __volatile__("PUSH R19 nt");

            __asm__ __volatile__("PUSH R20 nt");

            __asm__ __volatile__("PUSH R21 nt");

            __asm__ __volatile__("PUSH R22 nt");

            __asm__ __volatile__("PUSH R23 nt");

            __asm__ __volatile__("PUSH R24 nt");

            __asm__ __volatile__("PUSH R25 nt");

            __asm__ __volatile__("PUSH R26 nt");

            __asm__ __volatile__("PUSH R27 nt");

            __asm__ __volatile__("PUSH R30 nt");

            __asm__ __volatile__("PUSH R31 nt");

            __asm__ __volatile__("Int_OSSched: nt"); //當(dāng)中斷要求調(diào)度,直接進入這里

            __asm__ __volatile__("SEI nt");

            //開中斷,因為如果因中斷在任務(wù)調(diào)度中進行,已經(jīng)關(guān)中斷

            __asm__ __volatile__("PUSH R28 nt"); //R28與R29用于建立在堆棧上的指針

            __asm__ __volatile__("PUSH R29 nt"); //入棧完成

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

            unsigned char OSNextTaskPrio; //在現(xiàn)有堆棧上開設(shè)新的空間

            for (OSNextTaskPrio = 0; //進行任務(wù)調(diào)度

            OSNextTaskPrio < OS_TASKS && !(OSRdyTbl & (0x01<

            OSNextTaskPrio++);

            OSTaskRunningPrio = OSNextTaskPrio ;

            cli(); //保護堆棧轉(zhuǎn)換

            SP=TCB[OSTaskRunningPrio].OSTaskStackTop;

            sei();

            //根據(jù)中斷時的出棧次序

            __asm__ __volatile__("POP R29 nt");

            __asm__ __volatile__("POP R28 nt");

            __asm__ __volatile__("POP R31 nt");

            __asm__ __volatile__("POP R30 nt");

            __asm__ __volatile__("POP R27 nt");

            __asm__ __volatile__("POP R26 nt");

            __asm__ __volatile__("POP R25 nt");

            __asm__ __volatile__("POP R24 nt");

            __asm__ __volatile__("POP R23 nt");

            __asm__ __volatile__("POP R22 nt");

            __asm__ __volatile__("POP R21 nt");

            __asm__ __volatile__("POP R20 nt");

            __asm__ __volatile__("POP R19 nt");

            __asm__ __volatile__("POP R18 nt");

            __asm__ __volatile__("POP __tmp_reg__ nt"); //SERG出棧并恢復(fù)

            __asm__ __volatile__("OUT __SREG__,__tmp_reg__ nt"); //

            __asm__ __volatile__("POP __tmp_reg__ nt"); //R0出棧

            __asm__ __volatile__("POP __zero_reg__ nt"); //R1出棧

            //中斷時出棧完成

            __asm__ __volatile__("CLI nt"); //關(guān)中斷

            __asm__ __volatile__("SBRC R16,1 nt"); //SBRC當(dāng)寄存器位為0剛跳過下一條指令

            //檢查是在調(diào)度時,是否有中斷要求任務(wù)調(diào)度0x02是中斷要求調(diào)度的標(biāo)志位

            __asm__ __volatile__("RJMP OSSched nt"); //重新調(diào)度

            __asm__ __volatile__("LDI R16,0x00 nt");

            //清除中斷要求任務(wù)切換的標(biāo)志位,清除正在任務(wù)切換標(biāo)志位

            __asm__ __volatile__("RETI nt"); //返回并開中斷

            }

            //從中斷退出并進行調(diào)度

            void IntSwitch(void)

            {

            //當(dāng)中斷無嵌套,并且沒有在切換任務(wù)的過程中,直接進行任務(wù)切換

            if(OSCoreState == 0x02 && IntNum==0)

            {

            //進入中斷時,已經(jīng)保存了SREG和R0,R1,R18~R27,R30,R31

            __asm__ __volatile__("POP R31 nt"); //去除因調(diào)用子程序而入棧的PC

            __asm__ __volatile__("POP R31 nt");

            __asm__ __volatile__("LDI R16,0x01 nt");

            //清除中斷要求任務(wù)切換的標(biāo)志位,設(shè)置正在任務(wù)切換標(biāo)志位

            __asm__ __volatile__("RJMP Int_OSSched nt"); //重新調(diào)度

            }

            }

            ////////////////////////////////////////////任務(wù)處理

            //掛起任務(wù)

            void OSTaskSuspend(unsigned char prio)

            {

            TCB[prio].OSWaitTick=0;

            OSRdyTbl &= ~(0x01<

            if(OSTaskRunningPrio==prio) //當(dāng)要掛起的任務(wù)為當(dāng)前任務(wù)

            OSSched(); //從新調(diào)度

            }

            //恢復(fù)任務(wù)可以讓被OSTaskSuspend或OSTimeDly暫停的任務(wù)恢復(fù)

            void OSTaskResume(unsigned char prio)

            {

            OSRdyTbl |= 0x01<

            TCB[prio].OSWaitTick=0; //將時間計時設(shè)為0,到時

            if(OSTaskRunningPrio>prio) //當(dāng)要當(dāng)前任務(wù)的優(yōu)先級低于重置位的任務(wù)的優(yōu)先級

            OSSched(); //從新調(diào)度//從新調(diào)度

            }

            //任務(wù)延時

            void OSTimeDly(unsigned int ticks)

            {

            if(ticks) //當(dāng)延時有效

            {

            OSRdyTbl &= ~(0x01<

            TCB[OSTaskRunningPrio].OSWaitTick=ticks;

            OSSched(); //從新調(diào)度

            }

            }

            //信號量

            struct SemBlk

            {

            unsigned char OSEventType; //型號0,信號量獨占型;1信號量共享型

            unsigned char OSEventState; //狀態(tài)0,不可用;1,可用

            unsigned char OSTaskPendTbl; //等待信號量的任務(wù)列表

            } Sem[10];

            //初始化信號量

            void OSSemCreat(unsigned char Index,unsigned char Type)

            {

            Sem[Index].OSEventType=Type; //型號0,信號量獨占型;1信號量共享型

            Sem[Index].OSTaskPendTbl=0;

            Sem[Index].OSEventState=0;

            }

            //任務(wù)等待信號量,掛起

            //當(dāng)Timeout==0xffff時,為無限延時

            unsigned char OSTaskSemPend(unsigned char Index,unsigned int Timeout)

            {

            //unsigned char i=0;

            if(Sem[Index].OSEventState) //信號量有效

            {

            if(Sem[Index].OSEventType==0) //如果為獨占型

            Sem[Index].OSEventState = 0x00; //信號量被獨占,不可用

            }

            else

            { //加入信號的任務(wù)等待表

            Sem[Index].OSTaskPendTbl |= 0x01<

            TCB[OSTaskRunningPrio].OSWaitTick=Timeout; //如延時為0,剛無限等待

            OSRdyTbl &= ~(0x01<

            OSSched(); //從新調(diào)度

            if(TCB[OSTaskRunningPrio].OSWaitTick==0 ) //超時,未能拿到資源

            return 0;

            }

            return 1;

            }

            //發(fā)送一個信號量,可以從任務(wù)或中斷發(fā)送

            void OSSemPost(unsigned char Index)

            {

            if(Sem[Index].OSEventType) //當(dāng)要求的信號量是共享型

            {

            Sem[Index].OSEventState=0x01; //使信號量有效

            OSRdyTbl |=Sem [Index].OSTaskPendTbl; //使在等待該信號的所有任務(wù)就緒Sem[Index].OSTaskPendTbl=0; //清空所有等待該信號的等待任務(wù)

            }

            else //當(dāng)要求的信號量為獨占型

            {

            unsigned char i;

            for (i = 0; i < OS_TASKS && !(Sem[Index].OSTaskPendTbl & (0x01<

            if(i < OS_TASKS) //如果有任務(wù)需要

            {

            Sem[Index].OSTaskPendTbl &= ~(0x01<

            OSRdyTbl |= 0x01<

            }

            else

            {

            Sem[Index].OSEventState =1; //使信號量有效

            }

            }

            }

            //從任務(wù)發(fā)送一個信號量,并進行調(diào)度

            void OSTaskSemPost(unsigned char Index)

            {

            OSSemPost(Index);

            OSSched();

            }

            //清除一個信號量,只對共享型的有用。

            //對于獨占型的信號量,在任務(wù)占用后,就交得不可以用了。

            void OSSemClean(unsigned char Index)

            {

            Sem[Index].OSEventState =0; //要求的信號量無效

            }

            void TCN0Init(void) //計時器0

            {

            TCCR0 = 0;

            TCCR0 |= (1<

            TIMSK |= (1<

            TCNT0 = 100; //置計數(shù)起始值

            }

            SIGNAL(SIG_OVERFLOW0)

            {

            IntNum++; //中斷嵌套+1

            sei(); //在中斷中,重開中斷

            unsigned char i;

            for(i=0;i

            {

            if(TCB[i].OSWaitTick && TCB[i].OSWaitTick!=0xffff)

            {

            TCB[i].OSWaitTick--;

            if(TCB[i].OSWaitTick==0) //當(dāng)任務(wù)時鐘到時,必須是由定時器減時的才行

            {

            OSRdyTbl |= (0x01<

            OSCoreState|=0x02; //要求任務(wù)切換的標(biāo)志位

            }

            }

            }

            TCNT0=100;

            cli();

            IntNum--; //中斷嵌套-1

            IntSwitch(); //進行任務(wù)調(diào)度

            }

            unsigned char __attribute__ ((progmem)) proStrA[]="Task ";

            unsigned char strA[20];

            SIGNAL(SIG_UART_RECV) //串口接收中斷

            {

            strA[0]=UDR;

            }

            /////////////////////////////////////串口發(fā)送

            unsigned char *pstr_UART_Send;

            unsigned int nUART_Sending=0;

            void UART_Send(unsigned char *Res,unsigned int Len) //發(fā)送字符串?dāng)?shù)組

            {

            if(Len>0)

            {

            pstr_UART_Send=Res; //發(fā)送字串的指針

            nUART_Sending=Len; //發(fā)送字串的長度

            UCSRB=0xB8; //發(fā)送中斷使能

            }

            }

            //SIGNAL在中斷期間,其它中斷禁止

            SIGNAL(SIG_UART_DATA) //串口發(fā)送數(shù)據(jù)中斷

            {

            IntNum++; //中斷嵌套+1,不充許中斷

            if(nUART_Sending) //如果未發(fā)完

            {

            UDR=*pstr_UART_Send; //發(fā)送字節(jié)

            pstr_UART_Send++; //發(fā)送字串的指針加1

            nUART_Sending--; //等待發(fā)送的字串?dāng)?shù)減1

            }

            if(nUART_Sending==0) //當(dāng)已經(jīng)發(fā)送完

            {

            OSSemPost(0);

            OSCoreState|=0x02; //要求任務(wù)切換的標(biāo)志位

            UCSRB=0x98;

            }

            cli(); //關(guān)發(fā)送中斷

            IntNum--;

            IntSwitch(); //進行任務(wù)調(diào)度

            }

            void UARTInit() //初始化串口

            {

            #define fosc 8000000 //晶振8 MHZ UBRRL=(fosc/16/(baud+1))%256;

            #define baud 9600 //波特率

            OSCCAL=0x97; //串口波特率校正值,從編程器中讀出

            //UCSRB=(1<

            UCSRB=0x98;

            //UCSRB=0x08;

            UBRRL=(fosc/16/(baud+1))%256;

            UBRRH=(fosc/16/(baud+1))/256;

            UCSRC=(1<

            UCSRB=0xB8;

            UDR=0;

            }

            //打印unsigned int到字符串中00000

            void strPUT_uInt(unsigned char *Des,unsigned int i)

            {

            unsigned char j;

            Des=Des+4;

            for(j=0;j<5;j++)

            {

            *Des=i%10+’0’;

            i=i/10;

            Des--;

            }

            }

            void strPUT_Star(unsigned char *Des,unsigned char i)

            {

            unsigned char j;

            for(j=0;j

            {

            *Des++=’*’;

            }

            *Des++=13;

            }

            unsigned int strPUT_TaskState(unsigned char *Des,unsigned char TaskID,unsigned char Num)

            {

            //unsigned int i=0;

            *(Des+4)=’0’+TaskID;

            strPUT_uInt(Des+6,Num);

            strPUT_Star(Des+12,TaskID);

            return 12+TaskID+1;

            }

            void Task0()

            {

            unsigned int j=0;

            while(1)

            {

            PORTB=j++;

            if(OSTaskSemPend(0,0xffff))

            {

            unsigned int m;

            m=strPUT_TaskState(strA,OSTaskRunningPrio,j);

            UART_Send(strA,m);

            }

            OSTimeDly(200);

            }

            }

            void Task1()

            {

            unsigned int j=0;

            while(1)

            {

            PORTC=j++;

            if(OSTaskSemPend(0,0xffff))

            {

            unsigned int m;

            m=strPUT_TaskState(strA,OSTaskRunningPrio,j);

            UART_Send(strA,m);

            }

            OSTimeDly(100);

            }

            }

            void Task2()

            {

            unsigned int j=0;

            while(1)

            {

            if(OSTaskSemPend(0,0xffff))

            {

            unsigned int m;

            m=strPUT_TaskState(strA,OSTaskRunningPrio,j);

            UART_Send(strA,m);

            }

            PORTD=j++;

            OSTimeDly(50);

            }

            }

            void TaskScheduler()

            {

            OSSched();

            while(1)

            {}

            }

            int main(void)

            {

            strlcpy_P(strA,proStrA,20);

            UARTInit();

            TCN0Init();

            OSRdyTbl=0;

            IntNum=0;

            OSTaskCreate(Task0,&Stack[99],0);

            OSTaskCreate(Task1,&Stack[199],1);

            OSTaskCreate(Task2,&Stack[299],2);

            OSTaskCreate(TaskScheduler,&Stack[399],OS_TASKS);

            OSStartTask();

            }



            評論


            技術(shù)專區(qū)

            關(guān)閉