專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> MCU設(shè)計(jì)實(shí)例 >> 瀏覽文章

自己寫單片機(jī)操做系統(tǒng)3-任務(wù)創(chuàng)建和調(diào)度

作者:huqin   來源:本站原創(chuàng)   點(diǎn)擊數(shù):  更新時(shí)間:2014年01月31日   【字體:
如果存在兩個(gè)或以上的任務(wù)調(diào)度就需要將棧保CPU的寄存器了。這個(gè)地方就是各個(gè)MCU不同的地方了。
這個(gè)要看MCU進(jìn)入中斷的流程才能知道棧需要怎么保護(hù)。

OS_STK* InitStkBuff(VOID_FUN_PTR task,OS_STK* pstk)
{
   pstk--;        
    *pstk = (U16)(((U32)task) >> 8);    存要執(zhí)行的函數(shù)
    pstk--;                                
    *pstk = 0xFFFF; //IY        存y寄存器
    (pstk)--;
    *pstk = 0x1111; //IX        存x寄存器
    pstk--;
    *pstk = 0xAA;//A;            存A
    ((U8*)pstk)--;        A和B都是8位的在寄存器中是一起放在一個(gè)16位中的、
    *pstk = 0xBB; //B        存B
    ((U8*)pstk)--; //在中斷中需要多保存一次page頁,所以需要留一個(gè)空間出來
   return pstk;
}
 void CreatTask(VOID_FUN_PTR task,OS_STK *pStk,U8 stkSize,U8 osPior)
{
 OsTaskObjTbl[osPior].Task = task;
 OsTaskObjTbl[osPior].TaskSp = pStk;
 OsTaskObjTbl[osPior].stkSize = stkSize;
 OsTaskObjTbl[osPior].taskDly = 0;
 OsTaskObjTbl[osPior].taskState = TASK_STATE_READY;
 OsTaskObjTbl[osPior].nextTask = IdelTask;
 OsTaskObjTbl[osPior].TaskSp = InitStkBuff(task,pStk);       將修改后的sp給到任務(wù)的sp中
}
 任務(wù)調(diào)度函數(shù)

void Os_Schel(void)
{
 U8 i;
 OldTask = HeadTask;
 for(i = 0;i < TASK_SIZE;i++)
 {
  if(OsTaskObjTbl[i].taskState == TASK_STATE_READY) 直接查看任務(wù)的狀態(tài),是否已經(jīng)就緒
  {
   HeadTask = &OsTaskObjTbl[i];
   break;
  }
 }
 if(i == TASK_SIZE)
 {
  HeadTask = IdelTask;
 }
 
 OS_TASK_SW();啟動(dòng)軟件中斷進(jìn)入中斷調(diào)度
}
__interrupt VectorNumber_Vswi void OSCtxSw(void)   //4為SWI中斷
{
    DisableInterrupts;              //關(guān)中斷
  // PTP = 0xAA;
   asm{
        ldaa $30                    //保存頁面寄存器,單片機(jī)16位最大的flash只能是64k。但是128k需要通過頁面寄存器切換
        psha
        STS Sp_bf            將當(dāng)前的sp賦值給sp_bf
       }
        OldTask->TaskSp = Sp_bf;    保存sp-bf
    Sp_bf = HeadTask->TaskSp;   取出sp的地址。
   asm{ 
        LDS Sp_bf                將sp-bf給SP  
        pula
        staa $30                  將頁面寄存器恢復(fù)
       }
    EnableInterrupts;             //開中斷   
}
這樣一個(gè)任務(wù)就調(diào)度出來了、
關(guān)閉窗口

相關(guān)文章