📄 os_c.c
字号:
#include "def.h"
#include "OS.H"
//********************************************************************************
volatile PointType CToAsmSP; //C/ASM传SP用
volatile U8 OS_TaskRunning; //当前正在运行的Task
volatile U8 CallTkSwCount=0x0; //进入任务切换令牌
volatile U32 OSTimerCount=0; //系统时钟
volatile U32 MUX=0; //互斥
volatile U8 TmpHpTk=OS_TaskNum-1; //临时最高优先级任务
U32 FIQLR,SVCLR,FIQSPSR;
//任务控制块
struct{
PointType OSTaskStackTop; //保存任务的堆栈顶
PointType OSTaskStackBottom; //堆栈空间底
U32 OSTaskStackNum; //堆栈占据的基本块数
U32 OSWaitTick; //任务延时时钟
U32 OSTaskState; //任务状态
U32 OSUSRTaskID; //用户任务ID&系统任务ID
} TCB[OS_TaskNum];
/****************************************************************************
调度
****************************************************************************/
void TkSw(void)
{
OS_ENTER_CRITICAL();
if(CallTkSwCount==0x0){AsmTkSw();}
}
/****************************************************************************
功能描述:时间片处理
****************************************************************************/
void OSTimer(void)
{
U8 i;
OSTimerCount++;
CallTkSwCount++;
for(i=0;i<OS_TaskNum;i++){
if(TCB[i].OSTaskState!=0 && TCB[i].OSTaskState!=3){ //判断任务是否已经结束或挂起
if(TCB[i].OSWaitTick>1) TCB[i].OSWaitTick--; //给等待的任务减去1个等待时间片
else TCB[i].OSTaskState=1; //如果任务等时间到,设为就绪态
}
}
IsrHook(); //用户中断处理
}
/****************************************************************************
IO调度
****************************************************************************/
/****************************************************************************
MSG调度
****************************************************************************/
/****************************************************************************
CPU调度
功能描述:进行任务调度_C;
因为操作了SP,所以关键在禁止多次进入本函数
****************************************************************************/
void CtrTaskkSw(void)
{
U8 i;
CallTkSwCount++; //任务级切换标记为禁止,本程序未执行完前不会再执行本程序
TCB[OS_TaskRunning].OSTaskStackTop=CToAsmSP; //将正在运行的任务的堆栈底保存
#if OS_CORF>0 //内核形式,>0抢先式,0循环式
for(i=0;i<OS_TaskNum;i++){if(TCB[i].OSTaskState==1) goto sc;}
#else
for(i=OS_TaskRunning+1;i<OS_TaskNum;i++){if(TCB[i].OSTaskState==1) goto sc;} //如果新任务不是就绪态,下一任务
for(i=0;i<OS_TaskRunning;i++){if(TCB[i].OSTaskState==1) goto sc;}
#endif
i=OS_TaskNum-1;
sc:
if(TmpHpTk!=OS_TaskNum-1){ //让临时最高优先级任务首先运行,实时任务
OS_TaskRunning=TmpHpTk; //主要用来快速响应中断下部
TmpHpTk=OS_TaskNum-1;
}
else {OS_TaskRunning=i;}
CToAsmSP=TCB[OS_TaskRunning].OSTaskStackTop; //设置将要运行的任务
CallTkSwCount=0;
}
/*******************************************************************************
功能描述:建立一个新任务;
IN: void (*Task)(void) 任务函数名称;USRTaskID 用户定义任务号
OUT:0成功;1 USRTaskID过大;2 任务已存在;3 堆栈溢出,任务太多
********************************************************************************/
extern void GETSP(void);
U8 OSCreateTask(void (*Task)(void),U8 USRTaskID,U32 TaskStackNum)
{
static PointType StackPTR=0;
if(StackPTR==0){
GETSP();
StackPTR=CToAsmSP-0x1000;
}
if(USRTaskID>=OS_TaskNum){return 1;}
OS_ENTER_CRITICAL();
if(TCB[USRTaskID].OSTaskState!=0) {
OS_EXIT_CRITICAL();
return 2;
}
if(StackPTR>0){
TCB[USRTaskID].OSTaskStackTop=StackPTR;
TCB[USRTaskID].OSTaskStackBottom=StackPTR-TaskStackNum*OS_StackUnit*sizeof(PointType);
StackPTR-=TaskStackNum*OS_StackUnit*sizeof(PointType);
}
else {
OS_EXIT_CRITICAL();
return 3;
}
//栈初始化
*(PointType *)(TCB[USRTaskID].OSTaskStackTop)=(PointType)Task; //ARM R15 将任务的地址(PC)压入堆栈
*(--(PointType *)TCB[USRTaskID].OSTaskStackTop)=(PointType)Task; //ARM R14 LR
*(--(PointType *)TCB[USRTaskID].OSTaskStackTop)=0x0; //ARM R12
*(--(PointType *)TCB[USRTaskID].OSTaskStackTop)=0x0; //ARM R11
*(--(PointType *)TCB[USRTaskID].OSTaskStackTop)=0x0; //ARM R10
*(--(PointType *)TCB[USRTaskID].OSTaskStackTop)=0x0; //ARM R09
*(--(PointType *)TCB[USRTaskID].OSTaskStackTop)=0x0; //ARM R08
*(--(PointType *)TCB[USRTaskID].OSTaskStackTop)=0x0; //ARM R07
*(--(PointType *)TCB[USRTaskID].OSTaskStackTop)=0x0; //ARM R06
*(--(PointType *)TCB[USRTaskID].OSTaskStackTop)=0x0; //ARM R05
*(--(PointType *)TCB[USRTaskID].OSTaskStackTop)=0x0; //ARM R04
*(--(PointType *)TCB[USRTaskID].OSTaskStackTop)=0x0; //ARM R03
*(--(PointType *)TCB[USRTaskID].OSTaskStackTop)=0x0; //ARM R02
*(--(PointType *)TCB[USRTaskID].OSTaskStackTop)=0x0; //ARM R01
*(--(PointType *)TCB[USRTaskID].OSTaskStackTop)=0x0; //ARM R00
*(--(PointType *)TCB[USRTaskID].OSTaskStackTop)=(SVCMODE|NOINT); //ARM SPSR
//任务控制块初始化
TCB[USRTaskID].OSTaskStackNum=TaskStackNum; //保存任务堆栈基本块数
TCB[USRTaskID].OSUSRTaskID=USRTaskID; //保存任务自身ID和用户设定ID
TCB[USRTaskID].OSTaskState=1; //任务运行=1,等待=2,挂起=3,结束=0,
TCB[USRTaskID].OSWaitTick=0; //任务等待多少个调度周期,0不等待
OS_EXIT_CRITICAL();
return 0;
}
/*******************************************************************************
功能描述:OS初始化;
********************************************************************************/
void OSInit(void)
{
U8 i;
OS_ENTER_CRITICAL();
for(i=0;i<OS_TaskNum;i++){
TCB[i].OSTaskState=0;
TCB[i].OSTaskStackTop=0;
TCB[i].OSTaskStackNum=0;
}
OSCreateTask(OSIdle,OS_TaskNum-1,0x2000);
}
/*******************************************************************************
功能描述:第一次开始任务;
注:从最低优先级(Task0)的任务的开始
********************************************************************************/
void OSStartTask(void)
{
OS_ENTER_CRITICAL();
OS_TaskRunning=0;
CToAsmSP=TCB[OS_TaskRunning].OSTaskStackTop;
StartHT(); //开始第一个任务
}
/*******************************************************************************
功能描述:延时关挂起任务;
IN:ticks 系统时钟片
OUT:无
********************************************************************************/
void OSDelay(U32 ticks)
{
if(ticks>0){ //当延时有效
OS_ENTER_CRITICAL();
TCB[OS_TaskRunning].OSTaskState=2;
TCB[OS_TaskRunning].OSWaitTick=ticks;
TkSw(); //从新调度
}
}
/*******************************************************************************
功能描述:删除任务;
输入:UsrTaskID 用户定义任务ID号
输出:1设置成功;0失败
*******************************************************************************/
U8 OSDelTask(U8 UsrTaskID)
{
OS_ENTER_CRITICAL();
TCB[UsrTaskID].OSTaskState=0;
if(UsrTaskID==OS_TaskRunning) {TkSw();} //将自已Del
else {
OS_EXIT_CRITICAL();
return 1;
}
return 0;
}
/******************************************************************************
功能描述:任务休眠
输入:UsrTaskID 用户定义任务ID号,TaskSleepTicks 休眠的时间片
输出:1 设置成功;0失败
注:如果TaskSleepTicks设为0,将唤醒Task
*******************************************************************************/
U8 OSSleepTask(U8 UsrTaskID,U32 TaskSleepTicks)
{
OS_ENTER_CRITICAL();
if(TaskSleepTicks>0){
TCB[UsrTaskID].OSTaskState=2;
TCB[UsrTaskID].OSWaitTick=TaskSleepTicks;
OS_EXIT_CRITICAL();
return 1;
}
OS_EXIT_CRITICAL();
return 0;
}
/******************************************************************************
功能描述:挂起任务;
输入:UsrTaskID 用户定义任务ID号
输出:1 设置成功;0 失败
*******************************************************************************/
U8 OSSuspendTask(U8 UsrTaskID)
{
OS_ENTER_CRITICAL();
TCB[UsrTaskID].OSTaskState=3;
if(UsrTaskID==OS_TaskRunning) {TkSw();} //自已Suspend
OS_EXIT_CRITICAL();
return 0;
}
/******************************************************************************
功能描述:恢复任务;
输入:UsrTaskID 用户定义任务ID号
输出:0 设置成功;1 失败
*******************************************************************************/
U8 OSResumTask(U8 UsrTaskID)
{
if(TCB[UsrTaskID].OSTaskState!=0){ //找出符合条件且还没有删除的任务
OS_ENTER_CRITICAL();
TCB[UsrTaskID].OSTaskState=2;
OS_EXIT_CRITICAL();
return 0;
}
return 1;
}
/******************************e********************************************************
功能描述:取得互斥信号量
IN:mux互斥号
zs:是否阻塞进程,0否, 1是
返回值:0获得资源,1:未取得资源
****************************************************************************************/
U8 GetMux(U8 mux,U8 zs)
{
P1:
OS_ENTER_CRITICAL();
if((MUX & (1<<mux))==0){
MUX |=(1<<mux); //取得互斥信号
OS_EXIT_CRITICAL();
return 0x0;
}
OS_EXIT_CRITICAL();
if(zs==1){
OSDelay(1);
goto P1;
}
return 0x1;
}
/******************************e********************************************************
功能描述:释放互斥信号
****************************************************************************************/
void FreeMux(U8 mux)
{
OS_ENTER_CRITICAL();
MUX &=~(1<<mux); //释放互斥信号
OS_EXIT_CRITICAL();
}
/**************************OSIdle********************************************************
功能描述:空闲;
****************************************************************************************/
void OSIdle(void)
{
while(1){
wdt_reset();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -