uc/os 时钟中断处理

//中断退出函数OSInitExit(),标志着中断服务子程序的终结
void OSInitExit(void)
{
#if OS_CRITICAL_METHOD==3
OS_CPU_SR cpu_sr;
#endif
if(OSRunning==TRUE)
{
OS_ENTER_CRITICAL();
if(OSIntNesting>0)
{
OSIntNesting--; //中断嵌套层数计算器减一
}
if((OSIntNesting==0)&&(OSLockNesting==0))
{//所有ISR 执行完毕,而且调度没有加锁,则进行重现调度
OSIntExitY=OSUnMapTbl[OSRdyGrp]; //OSUnMapTbl是优先级判定表
OSPrioHighRby=(INT8U)((OSIntExitY<<3)+OSUnMapTbl[OSRdyTbl[OSIntExitY]]);
if(OSPrioHighRby!=OSPrioCur)
{//若当前任务不是最高优先级任务
OSTCBHighRby=OSTCBPrioTbL[OSPriohighRby];
OSCtxSwCtr++;//保持对上下文切换次数的记录
OSIntCtxSw();//进行中断级的上下文切换,OSIntCtxSw()
}
}
OS_EXIT_CRITICAL();
}
}

//C 语言时钟节拍函数OSTimeClick()
void OSTimeTick(void)
{
OS_TCB *ptcb;
OSTimeTickHook(); //用户定义的时钟节拍接口函数
ptcb=OSTCBList; //ptcb指向TCB 的头
while(ptcb->OSTCBPrio!=OS_IDLE_PRIO)
{//遍历TCB 联表中的每一个TCB
OS_ENTER_CRITICAL();
if(ptcb->OSTCBDly!=0)
{//对节拍延时计算值没有达到零的任务的处理
if(--ptcb->OSTCBDly==0)
{//对延时计算减一,若计数结束则满足条件
if(!(ptcb->OSTCBStat&OS_STAT_SUSPEND))//判断是否挂起
{
OSRdyGrp|=ptcb->OSTCBBitY; //没有被挂起
OSRdyTbl[ptcb->OSTCBY]|=ptcb->OSTCBBitX;//
}
else //确实被挂起的任务不会进入就绪态
{
ptcb->OSTCBDly=1;//使能再次判断挂起任务是否解除了挂起
}
}
}
ptcb=ptcb->OSTCBNext;//联表指针指向下一个TCB
OS_EXIT_CRITICAL();
}
OS_ENTER_CRITICAL();
OSOSTime++; //32位数加1操作通常使用多条指令,为临界区
OS_EXIT_CRITICAL();
}

//任务延时函数
void OSTimeDly(INT16U ticks)
{
#if OS_CRITICAL_METHOD==3
OS_CPU_SR cpu_sr;
#endif
if(ticks>0) //指定0值,则表明用户不想延时任务,函数立即返回到调用者
{
OS_ENTER_CRITICAL();
if((OSRdyTbl[OSTCBCur->OSTCBY]&=~OSTCBCur->OSTCBBitX)==0) //将当前任务从就绪表中移除
{
OSRdyGrp&=~OSTCBCur->OSTCBBitY;
}
OSTCBCur->OSTCBDly=ticks; //延时节拍数会被保存在当期的OS—TCB中
OS_EXIT_CRITICAL();
OS_Sched(); //任务调度程序
}
}

//任务延时函数,可提供更好的交互性
INT8U OSTimeDlyHMSM(INT8U hours,INT8U minutes,INT8U seconds,INT16U milli)
{
INT32U ticks;
INT16U loops;

if(hours>0||minutes>0||seconds>0||milli>0)
{
if(minutes>59)
{
return (OS_TIME_INVALID_MINUTES);
}
if(seconds>59)
{
return (OS_TIME_INVALID_SECONDS);
}
if(milli>999)
{
return (OS_TIME_INVALID_MILLI);
}
ticks=((INT32U)hours*3600L+(INT32U)minutes*60L+(INT32U)seconds)*OS_TICKS_PER_SEC+OS_TICKS_PER_SEC*((INT32U)milli+500L/
OS_TICKS_PER_SEC)/1000L;
loops=(INT16U)(ticks/65536L);
ticks=ticks%65536L;
OSTimeDly((INT16U)ticks);
while(loops>0)
{
OSTimeDly(32768);
OSTimeDly(32768);
loops--;
}
return (OS_NO_ERR);
}
return (OS_TIME_ZERO_DLY);
}



;基S3C44BOX 处理器硬件平台的OSTickISR汇编程序
.GLOBAL OSTickISR
STMDB SP!,{R0-R11,LR}; 保存寄存器的值到栈
MRS R0,CPSR; 以下三条指令是关中断,置I 位为1
ORR R0,R0,#0x80
msr,CPSR_cxsf,R0
LDR R0,=I_ISPC 把IRQ模式下的中断悬挂寄存器I_ISPR地址存入R0的寄存器

LDR R1,=BIT_TIMER0; BIT_TIMER0是定时器0的写入位,在头文件中定义
STR R1,[R0] 定时器0的中断服务悬挂位被清
BL IrqStart 中断计数
BL OSTimeTick 检查所有被延时的进程控制块,将延时节拍计数减1
BL OSIntEXIT 退出中断,检查有无优先级更高的程序已经就绪,如果有,则置变量need_to_swap_context-1

LDR R0,=need_to_swap_context 取变量need_to_swap_context的地址
LDR R2,[R0] 将变量need_to_swap_context存入R0
CMP R2,#1 比较need_to_swap_context是否为1
LDREQ PC,=_CTX_SW; 如果是则跳转到_CTX_SW,进行上下文切换

_NOT_CTX_SW 无须进行上下文切换
LDMIA SP!,{R0-R11,LR} 恢复寄存器的值
SUBS PC,LR,#4 OSTickISR函数返回,返回地址等于LR -4

_CTX_SW 进行上下文切换
MOV R1,#0 将变量need_to_swap_context置为0
STR R1,[R0]
现在进行上下文切换
LDMIA SP!,{R0-R11,LR} 恢复寄存器的值和堆栈指针
SUB LR,LR,#4 返回地址等于LR-4
STR LR,SAVED_LR 保存被抢占程序的返回地址到标SAVED_LR所在的字


MRS LR,SPSR 用4条指令切换管理SVC模式
AND LR,LR,#OXFFFFFFE0
ORR LR,LR,#Ox13
MSR CPSR_CXSF,LR
现在进入SVC管理模式
STR R12,[SP,#-8] 暂时保存R12到栈指针-8的位置
LDR R12,SAVED_LR 从标号SAVED_LR的内存位置取被抢占任务PC到R12
STMFD SP!,{R12} 将R12(原任务的PC)存放到栈区
SUB SP,SP,#4 将栈指针下移一个元素,指向暂存R12字的位置
LDMIA SP!,{R12} 恢复R12寄存器的值,SP上移1个单元
STMFD SP!,{LR} 保存被抢占任务的连接寄存器LR
STMFD SP!,{R0-R12} 保存被抢占任务的R0-R12

MRS R4,CPSR
STMFD SP!,{R4} 保存CPSR
MRS R4,SPSR
STMFD SP!,{R4} 保存SPSR
以下四条指令完成OSPrioCur=OSPrioHighRby
LDR R4,addr_OSPrioCur
LDR R5,addr_OSPrioHighRdy
LDRB R6,[R5]
STRB R6,[R4]
以下三条指令完成将当前任务栈指针Sp存放到被抢占任务的TCB 中
LDR R4,addr_OSTCBCur
LDR R5,[R4]
LDR SP!,[R5] 将SP保存在被抢占任务的TCB第一个字段
以下三条指令得到最高优先级任务的TCB地址,并将它存入SP寄存器
LDR R6,addr_OSTCBHighRby
LDR R6,[R6]
LDR SP,[R6]
以下单条指令实现了TCB指针的福祉操作:OSTCBCur=OSTCBHighRdy
STR R6,[R4] 将抢占任务的TCB指针值给当前任务TCB 指针

LDMFD SP!,{R4} 恢复SPSR
MSR SPSR_cxsf,R4
LDMFD SP!,{R4} 恢复CPSR
MSR CPSR_cxsf,R4
LDMFD SP!,{R0-R12,LR,PC} 恢复寄存器R0-r12,LR和PC,执行抢占任务的执行函数
Live together,or Die alone!
原文地址:https://www.cnblogs.com/hzhida/p/2395678.html