zoukankan      html  css  js  c++  java
  • 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!
  • 相关阅读:
    Linux系统挂载存储只读改成读写
    Linux kernel调试方法
    Linux设备树文件结构与解析深度分析
    #undef常用法
    Linux驱动中的platform总线分析
    在根文件系统中查看设备树(有助于调试)
    友元及操作符重载
    STM32 FLASH 擦除(以及防止误擦除程序代码)、写入
    C++学习笔记49:栈
    C++学习笔记48:链表的基本操作
  • 原文地址:https://www.cnblogs.com/hzhida/p/2395678.html
Copyright © 2011-2022 走看看