📄 os_core.c
字号:
#include <AT89X52.H>
#include "os_core.h"
#include "main.h"
#include "task_switch.h"
#include "sem.h"
#include "q.h"
#include "uart.h"
//程序控制块
TCB OS_TCB[TASK_NUM];
//当前运行任务的优先级
uint8 OS_Current_ID;
//进入临界段计数器
uint8 OS_En_Cr_Count;
//任务就绪表
uint8 OS_TaskRdy_List;
//中断嵌套计数器
uint8 Int_count;
uint8 Task_Int_List;
//置位表
uint8 code OSMapTbl[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
////////////////////////////系统初始化//////////////////////////////////////////////////////
void OS_Init(void)
{
uint8 i ;
EA=0; //关中断
ET2=1; //接受定时器2中断
T2CON=0x00;
T2MOD=0x00;
RCAP2H=0xB1;
RCAP2L=0xE0; //定时时间为10ms
Int_count=0; //中断嵌套为0
OS_TaskRdy_List=0; //任务就绪表为0
OS_Task_Q_List=0;
OS_En_Cr_Count=0; //进入临界段为0次
Task_Int_List=0x00;
OS_TCB[0].Task_SP=SP+2; //初始化各任务的堆栈起始地址
for(i=1;i<TASK_NUM;i++)
OS_TCB[i].Task_SP=OS_TCB[i-1].Task_SP+(255-OS_TCB[0].Task_SP)/TASK_NUM;
}
///////////////////////////创建一个任务////////////////////////////////////////////////////////
void OS_Task_Create(uint8 Task_Prio,uint8 Task_ID, uint16 Task_PC,uint8 Stack_Bottom) reentrant
{
OS_ENTER_CRITICAL();
if(OS_TCB[Task_ID].Status== No_Exist)
{
OS_TCB[Task_ID].Status=Exist; /*任务存在*/
OS_EXIT_CRITICAL();
((uint8 idata *)Stack_Bottom)[0]=Task_PC; /*将任务入口地址保存在堆栈,压入低8位*/
((uint8 idata *)Stack_Bottom)[1]=Task_PC>>8; /*压入高8位*/
OS_TCB[Task_ID].Task_SP=Stack_Bottom+1; /*将该任务的堆栈栈顶地址保存*/
OS_TCB[Task_ID].Prio=Task_Prio; /*任务优先级*/
OS_TCB[Task_ID].Delay=0; /*任务初始不延时*/
OS_TaskRdy_List|=OSMapTbl[Task_ID]; /*任务就绪*/
return ;
}
OS_EXIT_CRITICAL();
}
////////////////////////////系统启动///////////////////////////////////////////////////////////
void OS_Start(void)
{
OS_Current_ID=TASK_NUM-1;
SP=OS_TCB[OS_Current_ID].Task_SP; /*修改堆栈指针;使其指向当前任务的堆栈段*/
TR2=1; /*启动定时器2*/
EA=1; /*开中断*/
}
////////////////////////////系统时钟处理函数//////////////////////////////////////////////////
void OS_TimeTick(void)
{
uint8 i;
for(i=0;i<TASK_NUM;i++) /*处理所有延时*/
{
if(OS_TCB[i].Delay) /*如果任务需要延时*/
{
OS_TCB[i].Delay--; /*延时时间减1*/
if(OS_TCB[i].Delay==0) /*如果延时时间到*/
{
OSSendSignal(i); /*中断中发信号,任务就绪*/
}
}
}
}
////////////////////////////////查找下一任务//////////////////////////////////////////////////
void OS_Find_Next_Task(void)
{
uint8 tempPrio,i;
tempPrio=OS_TCB[OS_Current_ID].Prio;
for(i=0;i<TASK_NUM-1;i++)
{
if((OS_TaskRdy_List&OSMapTbl[i])&&(OS_TCB[i].Prio<tempPrio))
{
goto bb;
}
}
for(i=OS_Current_ID;i<TASK_NUM-1;i++)
{
if((OS_TaskRdy_List&OSMapTbl[i])&&(OS_TCB[i].Prio==tempPrio)&&i!=OS_Current_ID)
{
goto bb;
}
}
if(i==TASK_NUM-1)
{
for(i=0;i<TASK_NUM-1;i++)
{
if(OS_TaskRdy_List&OSMapTbl[i])
{
break;
}
}
}
bb: OS_Current_ID=i;
}
///////////////////////////定时器2中断服务函数/////////////////////////////////////////////////
#pragma disable /* 除非最高优先级中断,否则,必须加上这一句 */
void Timer2ISR(void) interrupt 5
{
TF2=0; /*清中断标志TF2*/
Enter_Int();
#if EN_TIMER_SHARING > 0
OS_TimeTick(); /* 调用系统时钟处理函数 */
#else
OSSendSignal(TIME_ISR_TASK_ID); /* 唤醒ID为TIME_ISR_TASK_ID的任务*/
#endif
Exit_Int();
}
///////////////////////////任务中给指定任务发送信号///////////////////////////////////////////
void OSSendSignal(uint8 TaskId)
{
if (TaskId < TASK_NUM)
{
OS_ENTER_CRITICAL();
OS_TaskRdy_List|=OSMapTbl[TaskId ];/*任务就绪*/
OS_EXIT_CRITICAL();
if (Int_count==0) /*不在中断中*/
{
OSSched(); /*开始任务切换*/
}
}
}
//////////////////////////清除指定任务信号////////////////////////////////////////////////////
void OSClearSignal(uint8 TaskId)
{
if(TaskId <TASK_NUM)
{
OS_ENTER_CRITICAL();
OS_TaskRdy_List &= ~OSMapTbl[TaskId]; /*任务不就绪*/
OS_EXIT_CRITICAL();
if(TaskId==OS_Current_ID && Int_count==0) /*挂起自身并不在中断中*/
{
OSSched(); /*开始任务切换*/
}
}
}
//////////////////////////挂起指定任务////////////////////////////////////////////////////////
void OSTaskSuspend(uint8 TaskId)
{
if (TaskId <TASK_NUM)
{
OS_TCB[TaskId].Delay = 0; /*没有超时处理*/
OSClearSignal(TaskId); /*清除指定任务信号*/
}
}
/////////////////////////系统等待函数//////////////////////////////////////////////////////////
uint8 OSWait(uint8 typ, uint8 ticks)
{
OS_TCB[OS_Current_ID].Delay = ticks; /*设置超时时间*/
switch(typ)
{
case K_SIG: /*等待信号,即挂起自身*/
OSTaskSuspend(OS_Current_ID);
return SIG_EVENT;
case K_TMO:
SP++;
*((uint8 data * data *)SP) = ticks;
OSClearSignal(OS_Current_ID); /*等待超时,即延时一段时间*/
SP--;
ticks = (uint8 data *)(*((uint8 data *)SP));
if(ticks&&OS_TCB[OS_Current_ID].Delay==0) /*超时*/
{
return TMO_EVENT;
}
return SIG_EVENT;
default:
OS_TCB[OS_Current_ID].Delay = 0;
return NOT_OK;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -