?? rtos.c
字號:
/************************************************************************************************************************
* RTOS.c
*
*
*
************************************************************************************************************************/
#include "RTOS.h"
/************************************************************************************************************************
函數名稱: OSTaskCreate
函數原型: void OSTaskCreate(void (*Task)(void),Uint_8bit *Stack,Uint_8bit TaskID)
函數功能: 建立任務
入口參數: *Task:任務函數地址;*Stack:任務堆棧指針;TaskID:任務優先級
出口參數: 無
有關說明:
創建時間: 2007年3月3日
修改時間:
************************************************************************************************************************/
void OSTaskCreate(void (*Task)(void),Uint_8bit *Stack,Uint_8bit TaskID)
{
Uint_8bit i;
*Stack--=(Uint_16bit)Task; /*將任務的地址低位壓入堆棧 */
*Stack--=(Uint_16bit)Task>>8; /*將任務的地址高位壓入堆棧 */
*Stack--=0x00; /*R1 __zero_reg__ */
*Stack--=0x00; /*R0 __tmp_reg__ */
*Stack--=0x80; /*SREG 在任務中,開啟全局中斷 */
for(i=0;i<14;i++)
*Stack--=i;
/*
在 avr-libc 中的 FAQ中的 What registers are used by the C compiler?
描述了寄存器的作用
*/
TCB[TaskID].OSTaskStackTop = (Uint_16bit)Stack;
/*
將人工堆棧的棧頂,保存到堆棧的數組中
*/
OSRdyTbl |= 0x01<<TaskID; /*任務就緒表已經準備好 */
}
/************************************************************************************************************************
函數名稱: OSStartTask
函數原型: void OSStartTask(void)
函數功能: 開始任務調度,從空閑任務開始運行
入口參數: 無
出口參數: 無
有關說明: 執行"reti"指令之后打開全局中斷
創建時間: 2007年3月3日
修改時間:
************************************************************************************************************************/
void OSStartTask(void)
{
OSPrioCur = OS_TASKS;
OSPrioHighRdy = OS_TASKS;
SP=TCB[OS_TASKS].OSTaskStackTop+17;
__asm__ __volatile__( "reti" "\n\t" );
}
/************************************************************************************************************************
函數名稱: OS_TASK_SW
函數原型: void OS_TASK_SW(void)
函數功能: 進行任務調度
入口參數: 無
出口參數: 無
有關說明: 中斷和任務都可以調用這個任務調度函數
創建時間: 2007年3月3日
修改時間:
************************************************************************************************************************/
void OS_TASK_SW(void)
{
__asm__ __volatile__("LDI R16,0x01 \n\t");
/*
清除中斷要求任務切換的標志位,設置正在任務切換標志位
*/
__asm__ __volatile__("SEI \n\t");
/*
開中斷,因為如果因中斷在任務調度中進行,要重新進行調度時,已經關中斷
*/
/* 根據中斷時保存寄存器的次序入棧,模擬一次中斷后,入棧的情況*/
__asm__ __volatile__("PUSH __zero_reg__ \n\t"); /*R1 */
__asm__ __volatile__("PUSH __tmp_reg__ \n\t"); /*R0 */
__asm__ __volatile__("IN __tmp_reg__,__SREG__ \n\t"); /*保存狀態寄存器SREG */
__asm__ __volatile__("PUSH __tmp_reg__ \n\t");
__asm__ __volatile__("CLR __zero_reg__ \n\t"); /*R0重新清零 */
__asm__ __volatile__("PUSH R18 \n\t");
__asm__ __volatile__("PUSH R19 \n\t");
__asm__ __volatile__("PUSH R20 \n\t");
__asm__ __volatile__("PUSH R21 \n\t");
__asm__ __volatile__("PUSH R22 \n\t");
__asm__ __volatile__("PUSH R23 \n\t");
__asm__ __volatile__("PUSH R24 \n\t");
__asm__ __volatile__("PUSH R25 \n\t");
__asm__ __volatile__("PUSH R26 \n\t");
__asm__ __volatile__("PUSH R27 \n\t");
__asm__ __volatile__("PUSH R30 \n\t");
__asm__ __volatile__("PUSH R31 \n\t");
__asm__ __volatile__("Int_OSSched: \n\t"); /*當中斷要求調度,直接進入這里 */
__asm__ __volatile__("SEI \n\t");
/*
開中斷,因為如果因中斷在任務調度中進行,已經關中斷
*/
__asm__ __volatile__("PUSH R28 \n\t"); /*R28與R29用于建立在堆棧上的指針 */
__asm__ __volatile__("PUSH R29 \n\t"); /*入棧完成 */
TCB[OSPrioCur].OSTaskStackTop=SP; /*將正在運行的任務的堆棧底保存 */
OSPrioCur = OSPrioHighRdy ; /*運行當前就緒表中的最高優先級任務 */
cli(); /*保護堆棧轉換,屬于臨界代碼,要保護 */
SP=TCB[OSPrioCur].OSTaskStackTop;
sei();
/*根據中斷時的出棧次序*/
__asm__ __volatile__("POP R29 \n\t");
__asm__ __volatile__("POP R28 \n\t");
__asm__ __volatile__("POP R31 \n\t");
__asm__ __volatile__("POP R30 \n\t");
__asm__ __volatile__("POP R27 \n\t");
__asm__ __volatile__("POP R26 \n\t");
__asm__ __volatile__("POP R25 \n\t");
__asm__ __volatile__("POP R24 \n\t");
__asm__ __volatile__("POP R23 \n\t");
__asm__ __volatile__("POP R22 \n\t");
__asm__ __volatile__("POP R21 \n\t");
__asm__ __volatile__("POP R20 \n\t");
__asm__ __volatile__("POP R19 \n\t");
__asm__ __volatile__("POP R18 \n\t");
__asm__ __volatile__("POP __tmp_reg__ \n\t"); /*SERG 出棧并恢復 */
__asm__ __volatile__("OUT __SREG__,__tmp_reg__ \n\t");
__asm__ __volatile__("POP __tmp_reg__ \n\t"); /*R0 出棧 */
__asm__ __volatile__("POP __zero_reg__ \n\t"); /*R1 出棧 */
/*中斷時出棧完成*/
__asm__ __volatile__("CLI \n\t"); /*關中斷 */
__asm__ __volatile__("SBRC R16,1 \n\t");
/*
SBRC當寄存器位為0則跳過下一條指令
檢查系統正在進行任務調度時,是否有中斷發生并進行要求任務調度,
如果中斷要求調度則重新進行一次任務調度。
0x02是中斷要求調度的標志位
*/
__asm__ __volatile__("RJMP OSSched \n\t"); /*重新調度 */
__asm__ __volatile__("LDI R16,0x00 \n\t");
/*
清除中斷要求任務切換的標志位,清除正在任務切換標志位,
表示任務切換已經完成。
*/
__asm__ __volatile__("RETI \n\t"); /*返回并開中斷 */
}
/************************************************************************************************************************
函數名稱: IntSwitch
函數原型: void IntSwitch(void)
函數功能: 從中斷退出并進行調度
入口參數: 無
出口參數: 無
有關說明: 當無中斷嵌套并且中斷中要求進行任務切換時才進行任務切換。
* 因為從中斷到運行下一個任務共調用了兩次子函數,所以要彈出四個入棧的PC
創建時間: 2007年3月3日
修改時間:
************************************************************************************************************************/
void IntSwitch(void)
{
if((OSCoreState == 0x02) && (OSIntNesting == 0))
{
/*
進入中斷時,已經保存了SREG和R0,R1,R18~R27,R30,R31,
所以沒有必要再保存一次了,直接跳轉到Int_OSSched進行下一個調度
*/
__asm__ __volatile__("POP R31 \n\t"); /*去除因調用子程序而入棧的PC*/
__asm__ __volatile__("POP R31 \n\t");
__asm__ __volatile__("POP R31 \n\t");
__asm__ __volatile__("POP R31 \n\t");
__asm__ __volatile__("LDI R16,0x01 \n\t");
/*
清除中斷要求任務切換的標志位,設置正在任務切換標志位
*/
__asm__ __volatile__("RJMP Int_OSSched \n\t"); /*重新調度 */
}
}
/************************************************************************************************************************
函數名稱: OSSched
函數原型: void OSSched(void)
函數功能: 任務調度器,進行任務調度
入口參數: 無
出口參數: 無
有關說明: 只有有更高優先級的任務就緒時才進行一次任務切換,否則不做切換
創建時間: 2007年3月7日
修改時間:
************************************************************************************************************************/
void OSSched (void)
{
OSFindPrioHighRdy(); /*找出就緒表中優先級最高的任務*/
if(OSPrioHighRdy != OSPrioCur) /*如果不是當前運行的任務,進行任務調度*/
{
OS_TASK_SW(); /*調度任務*/
}
}
/************************************************************************************************************************
函數名稱: OSTaskSuspend
函數原型: void OSTaskSuspend(Uint_8bit prio)
函數功能: 掛起任務
入口參數: prio:任務優先級
出口參數: 無
有關說明: 一個任務可以掛起本身也可以掛起其他任務
創建時間: 2007年3月3日
修改時間:
************************************************************************************************************************/
void OSTaskSuspend(Uint_8bit prio)
{
OS_ENTER_CRITICAL();
TCB[prio].OSWaitTick=0;
OSRdyTbl &= ~(0x01<<prio); /*從任務就緒表上去除標志位 */
if(OSPrioCur == prio) /*當要掛起的任務為當前任務 */
{
OS_EXIT_CRITICAL();
OSSched(); /*重新調度 */
return;
}
OS_EXIT_CRITICAL();
}
/************************************************************************************************************************
函數名稱: OSTaskResume
函數原型: void OSTaskResume(Uint_8bit prio)
函數功能: 恢復任務 可以讓被OSTaskSuspend或 OSTimeDly暫停的任務恢復
入口參數: prio:任務優先級
出口參數: 無
有關說明:
創建時間: 2007年3月3日
修改時間:
************************************************************************************************************************/
void OSTaskResume(Uint_8bit prio)
{
OS_ENTER_CRITICAL();
OSRdyTbl |= 0x01<<prio; /*從任務就緒表上重置標志位 */
TCB[prio].OSWaitTick=0; /*將時間計時設為0,到時 */
if(OSPrioCur > prio) /*當要當前任務的優先級低于重置位的任務的優先級 */
{
OS_EXIT_CRITICAL();
OSSched(); /*重新調度 */
return;
}
OS_EXIT_CRITICAL();
}
/************************************************************************************************************************
函數名稱: OSTimeDly
函數原型: void OSTimeDly(Uint_16bit ticks)
函數功能: 任務延時
入口參數: 延時的時間,任務時鐘的個數
出口參數: 無
有關說明: 如果延時65535(0xffff)則為無限延時
創建時間: 2007年3月3日
修改時間:
************************************************************************************************************************/
void OSTimeDly(Uint_16bit ticks)
{
if(ticks) /*當延時有效 */
{
OS_ENTER_CRITICAL();
OSRdyTbl &= ~(0x01<<OSPrioCur); /*把任務從就緒表中去掉*/
TCB[OSPrioCur].OSWaitTick=ticks;
OS_EXIT_CRITICAL();
OSSched(); /*重新調度 */
}
}
/************************************************************************************************************************
函數名稱: OSSemCreat
函數原型: void OSSemCreat(Uint_8bit Index,Uint_8bit Type)
函數功能: 初始化信號量
入口參數: Index:信號量的序號;Type:信號量類型
出口參數: 無
有關說明: Type為 0 信號量獨占型;1 信號量共享型
創建時間: 2007年3月3日
修改時間:
************************************************************************************************************************/
void OSSemCreat(Uint_8bit Index,Uint_8bit Type)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -