📄 arm_00_os_core.c
字号:
{
CopyOfIRQEN=IRQEN; //则将IRQEN跟FIQEN的值保存到备份中
CopyOfFIQEN=FIQEN;
FIQCLR=0xFFFFFFFF;
IRQCLR=0xFFFFFFFF; //将FIQEN跟IQREN清除
}
OSEnCrCount++; //进入临界段次数加1
}
//////////////////////////////////End of function//////////////////////////////////////////////
/**********************************************************************************************
功能:退出临界段
入口参数:无。
返回:无。
备注:无。
**********************************************************************************************/
void OSExitCritical(void)
{
if(OSEnCrCount>=1) //如果进入临界段的次数大于等于1次
{
OSEnCrCount--; //则次数减1
if(OSEnCrCount==0) //如果减次数减到0,则要开中断
{
FIQEN=CopyOfFIQEN; //设置所需要开的中断
IRQEN=CopyOfIRQEN;
}
}
}
//////////////////////////////////End of function//////////////////////////////////////////////
/**********************************************************************************************
功能:将pcb指向的任务从延时列表中删除
入口参数1:pcb。被指定的任务。
返回:0:删除失败。非0:删除成功。
备注:该函数使用前,应先进入临界段。
**********************************************************************************************/
uint32 DeleteFromDelayList(OSpcb *pcb)
{
if(pcb->Next==0){return 0;} //如果被删除的任务为表底,则不能删除,返回删除失败
if(pcb==OSDelayList) //如果被删除的pcb处于表头
{
OSDelayList=pcb->Next; //则延时表指向被删除任务pcb的下一个
OSDelayList->Prior=OSDelayList; //延时表的前趋指向它本身
}
else //如果被删除的任务pcb处于中间,则
{
pcb->Prior->Next=pcb->Next; //pcb的前趋的后趋,设置为pcb的后趋
pcb->Next->Prior=pcb->Prior; //pcb的后趋的前趋,设置为pcb的前趋
}
return (uint32)pcb; //返回被删除的任务pcb
}
//////////////////////////////////End of function//////////////////////////////////////////////
/**********************************************************************************************
功能:将pcb指向的任务从就绪态列表中删除
入口参数1:pcb。被指定的任务。
返回:0:删除失败。非0:删除成功。
备注:该函数使用前,应先进入临界段。
**********************************************************************************************/
uint32 DeleteFromReadyList(OSpcb * pcb)
{
if(pcb->Next==0)return 0; //如果被删除的任务为表底,则不能删除,返回删除失败
if(pcb==OSReadyList) //如果被删除的pcb处于表头
{
OSReadyList=pcb->Next; //则就绪表指向被删除任务pcb的下一个
OSReadyList->Prior=OSReadyList; //就绪表的前趋指向它本身
}
else //如果被删除的任务pcb处于中间,则
{
pcb->Prior->Next=pcb->Next; //pcb的前趋的后趋,设置为pcb的后趋
pcb->Next->Prior=pcb->Prior; //pcb的后趋的前趋,设置为pcb的前趋
}
return (uint32)pcb; //返回被删除的任务pcb
}
//////////////////////////////////End of function//////////////////////////////////////////////
/**********************************************************************************************
功能:将pcb指向的任务从挂起列表中删除
入口参数1:pcb。被指定的任务。
返回:0:删除失败。非0:删除成功。
备注:该函数使用前,应先进入临界段。
**********************************************************************************************/
uint32 DeleteFromSuspendList(OSpcb *pcb)
{
if(pcb->Next==0)return 0; //如果被删除的任务为表底,则不能删除,返回删除失败
if(pcb==OSSuspendList) //如果被删除的pcb处于表头
{
OSSuspendList=pcb->Next; //则挂起态表指向被删除任务pcb的下一个
OSSuspendList->Prior=OSSuspendList; //挂起态表的前趋指向它本身
}
else //如果被删除的任务pcb处于中间,则
{
pcb->Prior->Next=pcb->Next; //pcb的前趋的后趋,设置为pcb的后趋
pcb->Next->Prior=pcb->Prior; //pcb的后趋的前趋,设置为pcb的前趋
}
return (uint32)pcb; //返回被删除的任务pcb
}
//////////////////////////////////End of function//////////////////////////////////////////////
/**********************************************************************************************
功能:将pcb指向的任务插入到挂起列表中
入口参数1:pcb。被指定的任务。
返回:无。
备注:该函数使用前,应先进入临界段。
**********************************************************************************************/
void InsertToSuspendList(OSpcb * pcb)
{
pcb->Status=OSInSuspendStatus; //指定任务的状态设置为挂起状态
pcb->Next=OSSuspendList; //指定任务的后趋指向挂起态列表的表头
OSSuspendList->Prior=pcb; //挂起态任务列表的前趋指向指定任务pcb
OSSuspendList=pcb; //挂起态列表的表头设置为刚插入的指定任务
OSSuspendList->Prior=OSSuspendList; //挂起态列表表头的前趋指向它本身
}
//////////////////////////////////End of function//////////////////////////////////////////////
/**********************************************************************************************
功能:将pcb指向的任务插入到延时列表中
入口参数1:pcb。被指定的任务。
返回:无。
备注:该函数使用前,应先进入临界段。
**********************************************************************************************/
void InsertToDelayList(OSpcb * pcb)
{
pcb->Status=OSInDelayStatus; //指定任务的状态设置为延时状态
pcb->Next=OSDelayList; //指定任务的后趋指向延时态列表的表头
OSDelayList->Prior=pcb; //延时态任务列表的前趋指向指定任务pcb
OSDelayList=pcb; //延时态列表的表头设置为刚插入的指定任务
OSDelayList->Prior=OSDelayList; //延时态列表表头的前趋指向它本身
}
//////////////////////////////////End of function//////////////////////////////////////////////
/**********************************************************************************************
功能:将pcb指向的任务插入到就绪表中
入口参数1:pcb。被指定的任务。
返回:无。
备注:该函数使用前,应先进入临界段。
**********************************************************************************************/
void InsertToReadyList(OSpcb *pcb)
{
OSpcb * TempPcb; //用来查找就绪表,确定该插入到何处
pcb->Status=OSInReadyStatus; //指定任务的状态设置为就绪态
TempPcb=OSReadyList; //设置为就绪表表头
do
{
if((pcb->Priority)<=(TempPcb->Priority)) //如果要插入的任务优先级高于或者等于被查找到的任务,则将其插入
{
if(TempPcb==OSReadyList) //如果被插在表头位置
{
pcb->Next=OSReadyList; //指定任务的后趋指向就绪态列表的表头
OSReadyList->Prior=pcb; //就绪态列表的前趋指向指定任务pcb
OSReadyList=pcb; //就绪态列表的表头设置为刚插入的指定任务
OSReadyList->Prior=OSReadyList; //就绪态列表表头的前趋指向它本身
}
else //如果不是在表头
{
pcb->Next=TempPcb; //要插入的pcb的后趋为TempPcb
pcb->Prior=TempPcb->Prior; //要插入的pcb的前趋为TempPcb的前趋
TempPcb->Prior->Next=pcb; //TempPcb的前趋的后趋为pcb
TempPcb->Prior=pcb; //TempPcb的后趋为pcb
}
return; //返回
}
TempPcb=TempPcb->Next; //移到下一个
}while(TempPcb->Next); //直到就绪表表底为止
//如果到表低还未找到足够低的优先级,则将其插入到系统空闲任务的前面
pcb->Next=TempPcb; //要插入的pcb的后趋为TempPcb
pcb->Prior=TempPcb->Prior; //要插入的pcb的前趋为TempPcb的前趋
TempPcb->Prior->Next=pcb; //TempPcb的前趋的后趋为pcb
TempPcb->Prior=pcb; //TempPcb的后趋为pcb
return;
}
//////////////////////////////////End of function//////////////////////////////////////////////
/**********************************************************************************************
功能:创建一个任务。
入口参数1:TaskEntryAddr。任务入口地址。
入口参数2:StackLength。任务的堆栈长度。一个任务的进程控制块需要68字节,保护工作寄存器需要64字节,
另外还有函数调用等,因此一个任务至少需要140字节以上的堆栈空间。
入口参数3:Priority。任务优先级。值越小,优先级越高。系统保留0、1及0xFFFFFFF号优先级,用户不能使用这些优先级。
人口参数4:Mode。任务的代码模式。可选择为OS_ARM_MODE跟OS_THUMB_MODE。
入口参数5:TaskName。指向被创建任务的名字的字符指针。
返回:64位无符号整数。当任务创建成功时,低32位为任务堆栈的起始地址,也即是任务的PID号。高32为0。
当任务创建失败时,高32位不为0,可以判断任务创建失败的原因。
备注:无。
**********************************************************************************************/
uint64 OSTaskCreat(uint32 TaskEntryAddr,uint32 StackLength,uint32 Priority,uint32 Mode,uint8 *TaskName)
{
OSpcb * TempPcb;
uint32 StackAddr;
uint32 i;
OSEnterCritical(); //进入临界段
StackAddr=OSMalloc(StackLength); //根据需要的长度,申请一块内存
if(StackAddr==0) //如果申请内存失败
{
return OSMemoryLack; //返回错误号:内存不足
}
TempPcb=(OSpcb *)StackAddr; //TempPcb为堆栈起始地址
TempPcb->StackLength=StackLength; //保存任务堆栈长度
TempPcb->Priority=Priority; //设置任务优先级
TempPcb->Status=OSInDelayStatus; //设置任务状态。新创建的任务,总是处于延时态。延时时间为1个时钟节拍。
TempPcb->Delay=1; //任务延时为1个时钟节拍。任务创建后,一个时钟节拍后被转为就绪态
TempPcb->PID=StackAddr; //任务的PID被设置为任务的堆栈起始地址
TempPcb->TotalRunTime=0; //总运行时间为0
TempPcb->RunTimeInThisRefreshPeriod=0; //本秒内运行时间为0
TempPcb->WaitFor=0; //初始化不等待资源
TempPcb->Msg=0; //初始化没有接收到消息
for(i=0;i<15;i++) //设置任务的标题
{
TempPcb->Title[i]=TaskName[i];
if(TaskName[i]==0)break;
}
for(;i<15;i++) //传递进来的标题长度不足时,补空格。
{
TempPcb->Title[i]=' ';
}
TempPcb->Title[15]=0;
TempPcb->TaskSP=OSSetStack(StackAddr+StackLength,TaskEntryAddr,Mode); //设置好任务的堆栈,并将返回的堆栈地址保存起来
InsertToDelayList(TempPcb); //将任务插入到延时表中
TaskAmount++; //任务个数加1
OSExitCritical(); //退出临界段
return (uint32)TempPcb->PID; //任务创建成功,返回任务的PID
}
//////////////////////////////////End of function//////////////////////////////////////////////
/**********************************************************************************************
功能:任务延时NumOfTick个时钟节拍
入口参数1:NumOfTick。延迟的时钟节拍个数。
返回:无。
**********************************************************************************************/
void OSTaskDelay(uint32 NumOfTick)
{
OSEnterCritical(); //进入临界段
if(OSCurrentPcb->Next==(OSpcb *)0) //如果要将系统空闲任务挂起
{
OSEnterCritical(); //则退出临界段,返回。因为空闲任务不能被挂起!
return;
}
OSCurrentPcb->Delay=NumOfTick; //设置延时节拍数
DeleteFromReadyList(OSCurrentPcb); //将任务从就绪态表只删除
InsertToDelayList(OSCurrentPcb); //将其插入到延态时表中
OSExitCritical(); //退出临界段
OSTaskSwitch(); //任务切换
}
///////////////////////////////////////////////////////////////////////////////////////////////
/**********************************************************************************************
功能:将一个任务挂起。
入口参数:pcb。要挂起的任务的pcb。
返回:是否成功挂起。0:成功挂起。错误代码 NO_SUCH_A_TASK:没有这个任务;CAN_NOT_BE_SUSPENDED:指定的任务不能挂起
备注:无。
/*********************************************************************************************/
uint32 OSTaskSuspend(OSpcb * pcb)
{
OSpcb * TempPcb;
if(pcb==&OSReadyListBottom) //如果要挂起系统空闲任务,
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -