久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2086|回復(fù): 2
打印 上一主題 下一主題
收起左側(cè)

關(guān)于多任務(wù)調(diào)度時(shí),RETI執(zhí)行后PC本該是01A1,可怎么變?yōu)?101啊

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主



void OSStartTask() 函數(shù)中RETI執(zhí)行后PC本該是0x01A1,可怎么變?yōu)?x0101啊
下面是“建立一個(gè)屬于自己的 AVR 的 RTOS.pdf”中的程序
#include <avr/io.h>  
#include <avr/Interrupt.h>  
#include <avr/signal.h>  
unsigned char Stack[400];  

register unsigned char OSRdyTbl          asm("r2");    //任務(wù)運(yùn)行就緒表  
register unsigned char OSTaskRunningPrio asm("r3");    //正在運(yùn)行的任務(wù)  

#define OS_TASKS 3                    //設(shè)定運(yùn)行任務(wù)的數(shù)量  
struct TaskCtrBlock  
{  
  unsigned int OSTaskStackTop;  //保存任務(wù)的堆棧頂  
  unsigned int OSWaitTick;      //任務(wù)延時(shí)時(shí)鐘  
} 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<<TaskID;      //任務(wù)就緒表已經(jīng)準(zhǔn)備好  
}  

//開始任務(wù)調(diào)度,從最低優(yōu)先級的任務(wù)的開始  
void OSStartTask()         
{  
  OSTaskRunningPrio=OS_TASKS;  
  SP=TCB[OS_TASKS].OSTaskStackTop+17;  
  __asm__ __volatile__(    "reti"       " \t"  );   
}  

//進(jìn)行任務(wù)調(diào)度  
void OSSched(void)  
{   
   //  根據(jù)中斷時(shí)保存寄存器的次序入棧,模擬一次中斷后,入棧的情況   
  __asm__ __volatile__("PUSH __zero_reg__ \t");  //R1  
  __asm__ __volatile__("PUSH __tmp_reg__\t");  //R0   
  __asm__ __volatile__("IN   __tmp_reg__,__SREG__\t");  //保存狀態(tài)寄存器 SREG  
  __asm__ __volatile__("PUSH __tmp_reg__\t");  
  __asm__ __volatile__("CLR  __zero_reg__ \t");  //R0重新清零  
  __asm__ __volatile__("PUSH R18\t");  
  __asm__ __volatile__("PUSH R19\t");  
  __asm__ __volatile__("PUSH R20\t");  
  __asm__ __volatile__("PUSH R21\t");  
  __asm__ __volatile__("PUSH R22\t");  
  __asm__ __volatile__("PUSH R23\t");  
  __asm__ __volatile__("PUSH R24\t");  
  __asm__ __volatile__("PUSH R25\t");  
  __asm__ __volatile__("PUSH R26\t");  
  __asm__ __volatile__("PUSH R27\t");  
  __asm__ __volatile__("PUSH R30\t");      
  __asm__ __volatile__("PUSH R31\t");  

  __asm__ __volatile__("Int_OSSched: \t");  //當(dāng)中斷要求調(diào)度,直接進(jìn)入這里  
  __asm__ __volatile__("PUSH R28\t");  //R28與R29用于建立在堆棧上的指針  
  __asm__ __volatile__("PUSH R29\t");  //入棧完成  

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

  if(++OSTaskRunningPrio>=OS_TASKS) //輪流運(yùn)行各個(gè)任務(wù),沒有優(yōu)先級  
      OSTaskRunningPrio=0;  

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

    //根據(jù)中斷時(shí)的出棧次序      
  __asm__ __volatile__("POP  R29\t");      
  __asm__ __volatile__("POP  R28\t");         
  __asm__ __volatile__("POP  R31\t");      
  __asm__ __volatile__("POP  R30\t");      
  __asm__ __volatile__("POP  R27\t");      
  __asm__ __volatile__("POP  R26\t");      
  __asm__ __volatile__("POP  R25\t");      
  __asm__ __volatile__("POP  R24\t");      
  __asm__ __volatile__("POP  R23\t");      
  __asm__ __volatile__("POP  R22\t");      
  __asm__ __volatile__("POP  R21\t");      
  __asm__ __volatile__("POP  R20\t");      
  __asm__ __volatile__("POP  R19\t");  
  __asm__ __volatile__("POP  R18\t");  
  __asm__ __volatile__("POP  __tmp_reg__\t");      //SERG 出棧并恢復(fù)  
  __asm__ __volatile__("OUT  __SREG__,__tmp_reg__ \t");      //  
  __asm__ __volatile__("POP  __tmp_reg__ \t");      //R0 出棧  
  __asm__ __volatile__("POP  __zero_reg__ \t");      //R1 出棧  
  __asm__ __volatile__("RETI\t");     //返回并開中斷  
  //中斷時(shí)出棧完成  
}  


void IntSwitch(void)  
{      
  __asm__ __volatile__("POP  R31\t");  //去除因調(diào)用子程序而入棧的 PC  
  __asm__ __volatile__("POP  R31\t");  
  __asm__ __volatile__("RJMP Int_OSSched\t");  //重新調(diào)度  
}  

void TCN0Init(void)    // 計(jì)時(shí)器 0  
{  
  TCCR0 = 0;  
  TCCR0 |= (1<<CS02);  // 256預(yù)分頻  
  TIMSK |= (1<<TOIE0); // T0溢出中斷允許                    
  TCNT0 = 100;         // 置計(jì)數(shù)起始值      
}  

SIGNAL(SIG_OVERFLOW0)  
{  
  TCNT0=100;  
  IntSwitch();        //任務(wù)調(diào)度  
}  

void Task0()  
{  
  unsigned int j=0;  
  while(1)  
  {              
    PORTB=j++;  
    //OSTimeDly(50);  
  }  
}  

void Task1()  
{  
  unsigned int j=0;  
  while(1)  
  {  
    PORTC=j++;  
    //OSTimeDly(5);  
  }  
}  

void Task2()  
{  
  unsigned int j=0;  
  while(1)  
  {  
    PORTD=j++;   
    //OSTimeDly(5);   
  }  
}  

void TaskScheduler()  
{   
  while(1)  
  {         
     OSSched();      //反復(fù)進(jìn)行調(diào)度  
  }  
}  


int main(void)  
{      
  TCN0Init();  
  OSRdyTbl=0;  
  OSTaskCreate(Task0,&Stack[99],0);  
  OSTaskCreate(Task1,&Stack[199],1);  
  OSTaskCreate(Task2,&Stack[299],2);  
  OSTaskCreate(TaskScheduler,&Stack[399],OS_TASKS);  
  OSStartTask();  
}


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:157097 發(fā)表于 2017-1-9 11:47 | 只看該作者
為什么使用reti 中斷返回后,PC指針?biāo)傅牟皇窍氲降牡胤?/td>
回復(fù)

使用道具 舉報(bào)

板凳
ID:153041 發(fā)表于 2017-1-24 15:22 | 只看該作者
reti指令僅僅只是把當(dāng)前堆棧中的棧頂?shù)臄?shù)據(jù)彈出到PC指針寄存器;你要追查一下當(dāng)時(shí)堆棧的情況,初始化的時(shí)候?yàn)槭裁词?101.
回復(fù)

使用道具 舉報(bào)

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 久久99精品久久久久久国产越南 | 欧美性大战久久久久久久蜜臀 | 免费毛片网| 久久国产精99精产国高潮 | 中文字幕1区 | 日本黄色免费片 | 国产精品二区三区 | 超碰人人91| 四虎影视免费观看 | 久久精品二区亚洲w码 | 亚洲狠狠爱 | 免费黄网站在线观看 | 欧美一级在线 | 欧美激情一区二区三级高清视频 | 久久久久久久久久久丰满 | 久久久久久国产精品免费免费男同 | 在线观看亚洲精品 | 最新中文字幕久久 | 亚洲一区高清 | 免费国产一区二区 | 精品一区二区免费视频 | 亚洲成人自拍 | 国产91观看| 日韩免费高清视频 | av网站观看 | 国产免费一区二区三区免费视频 | 中国免费黄色片 | 精品国产青草久久久久96 | 欧日韩在线| 亚洲人在线观看视频 | 午夜精| 91最新在线视频 | 日韩中文一区二区三区 | 亚洲一区在线日韩在线深爱 | 国产ts人妖系列高潮 | 亚洲va国产日韩欧美精品色婷婷 | 国产欧美精品一区 | 日韩精品1区2区3区 成人黄页在线观看 | 国内精品久久精品 | 精品免费国产一区二区三区四区 | 视频在线一区二区 |