您的位置:首页 > 其它

uc/os 时钟中断处理

2012-03-14 12:12 309 查看
//中断退出函数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,执行抢占任务的执行函数
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: