分享

启动ucosii之八OSStatInit()

 筱肆 2014-03-25
分类: uCOSII 2013-05-24 14:40 256人阅读 评论(0) 收藏 举报

原型出自内核OS_CORE.C

//统计任务的初始化
#if OS_TASK_STAT_EN > 0
void  OSStatInit (void)
{
#if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
    OS_CPU_SR  cpu_sr;
#endif

//调用这个函数要注意,主要原因就是因为在OSStatInit()中调用OSTimeDly发生了任务的调度,而这一点特别容易被忽略掉
//ucosii时钟频率200hz,即1m 200个ticks时钟节拍
//延时2个ticks,也就是2/200=10ms       
    OSTimeDly(2);                                /* Synchronize with clock tick                        */

    OS_ENTER_CRITICAL();
    OSIdleCtr    = 0L;                           /* Clear idle counter                                 */
    OS_EXIT_CRITICAL();
    OSTimeDly(OS_TICKS_PER_SEC);                 /* Determine MAX. idle counter value for 1 second     */
    OS_ENTER_CRITICAL();
    OSIdleCtrMax = OSIdleCtr;                    /* Store maximum idle counter count in 1 second       */
    OSStatRdy    = TRUE;
    OS_EXIT_CRITICAL();
}
#endif

奋斗

原型出自OS_TIME.C
//uC/OS-Ⅱ提供了这样一个系统服务:申请该服务的任务可以延时一段时间,这段时间的长短是用时钟节拍的数目来确定的.
//实现这个系统服务的函数叫做OSTimeDly().调用该函数会使uC/OS-Ⅱ进行一次任务调度,并且执行下一个优先级最高的就绪态任务.
//任务调用OSTimeDly()后,一旦规定的时间期满或者有其它的任务通过调用OSTimeDlyResume()取消了延时,它就会马上进入就绪状态.
//注意,只有当该任务在所有就绪任务中具有最高的优先级时,它才会立即运行
void  OSTimeDly (INT16U ticks)//延迟指定时钟节拍
{
#if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
    OS_CPU_SR  cpu_sr;
#endif   


/*
任务控制块中定义的
优先级低3位,即prio&0x07
    INT8U          OSTCBX;             /* Bit position in group  corresponding to task priority (0..7) */
优先级高3位,即prio>>3
    INT8U          OSTCBY;             /* Index into ready table corresponding to task priority        */
OSMapTbl[prio&0x07],任务所在的列OSRdyTbl[OSTCBY]
    INT8U          OSTCBBitX;          /* Bit mask to access bit position in ready table               */
OSMapTbl[prio>>3],任务所在的组OSRdyGrp
    INT8U          OSTCBBitY;          /* Bit mask to access bit position in ready group               */

//优先级位图
extern  INT8U  const      OSMapTbl[];               /* Priority->Bit Mask lookup table                 */
//优先级索引
extern  INT8U  const      OSUnMapTbl[];             /* Priority->Index    lookup table                 */

*/
    if (ticks > 0) {                                                      /* 0 means no delay!         */
        OS_ENTER_CRITICAL();

//确定为当前任务延时
        if ((OSRdyTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0) {  /* Delay current task        */

//从就绪队列中剔除当前任务.对相应的行号取反相与,即清除任务
            OSRdyGrp &= ~OSTCBCur->OSTCBBitY;
        }
//这个延时节拍数会被保存在当前任务的OS_TCB中,并且通过OSTimeTick()每隔一个时钟节拍就减少一个延时节拍数.
        OSTCBCur->OSTCBDly = ticks;                                       /* Load ticks in TCB         */
        OS_EXIT_CRITICAL();

//最后,既然任务已经不再处于就绪状态,任务调度程序会执行下一个优先级最高的就绪任务
//执行任务级调度
        OS_Sched();                                                       /* Find next task to run!    */
    }
}
//在延时函数中,会取消任务的就绪状态而进入延时等待状态,调用OSSched()函数实现任务的调度,实现处理器使用权的让出

奋斗
原型出自内核OS_CORE.C
//uC/OS-II有两种任务调度器:任务级的调度器和中断级的调度器.
//任务级的调度器由函数OSSched()来实现;中断级的调度器由函数OSIntExit()来实现
void  OS_Sched (void)//其职责就是寻找优先级别最高的就绪任务作为待运行任务
{
#if OS_CRITICAL_METHOD == 3                            /* Allocate storage for CPU status register     */
    OS_CPU_SR  cpu_sr;
#endif   
    INT8U      y;


    OS_ENTER_CRITICAL();
    if ((OSIntNesting == 0) && (OSLockNesting == 0)) { /* Sched. only if all ISRs done & not locked    */

//获得最高优先级行号-与任务多少无关,总是找到最高优先级行号
/*
OSUnMapTbl[]共0xFF个元素,0x00~0xFF为索引,而OSUnMapTbl[]里的值就是通过分析索引得到的.
eg:索引0x50,二进制表示为0101 0000,然后从右边数,看第几位首先为1,则OSUnMapTbl[0x50]的值就为几.0101 0000从右起,第4位首先为1,所以有OSUnMapTbl[0x50]=4
eg:索引0x51,二进制为0101 0001,右起第0位为1,所以OSUnMapTbl[0x51]=0
优先级是从右至左,从上至下越来越低的,最低优先级给了空闲任务.
*/
        y             = OSUnMapTbl[OSRdyGrp];          /* Get pointer to HPT ready to run              */
/*
OSRdyTbl[OSRdyGrp]通过行号找到最高优先级任务
原理同上
*/
        OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);
        if (OSPrioHighRdy != OSPrioCur) {              /* No Ctx Sw if current task is highest rdy     */
            OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
            OSCtxSwCtr++;                              /* Increment context switch counter             */

//任务切换宏OS_CPU.H中定义
//#define  OS_TASK_SW()         asm  INT   uCOS
//通过用户设置的软中断0x80进入任务切换
/*
1. 任务切换都做了哪些事情:CPU寄存器内容切换.
2. ucos实现任务切换的方法:“通过执行软中断指令,或者依据处理器的不同,执行TRAP(陷阱)指令来实现的.
3. 为什么要通过”软中断“呢?通常的,处理器支持2种模式对应2种权限:用户级和特权级.”以提供一种存储器访问的保护机制,使得普通的用户程序不能意外地,甚至是恶意地执行涉及要害的操作.
简言之:任务A切换到B时需要保存cpu的”现场数据“使系统能够返回A;同时需要加载B的”现场数据“到cpu中,以使B回到被切换时的状态.而只有cpu的特权模式允许上述操作,由用户级进入特权级的惟一途径是触发异常(或中断).
*/
            OS_TASK_SW();                              /* Perform a context switch                     */
        }
    }
    OS_EXIT_CRITICAL();
}

更多 0
相关主题推荐
任务调度 处理器 二进制 索引 access
相关博文推荐
解决SQL Server 表或索引的碎片...
DirectX 12可以在哪些处理器、显...
ASCII、Unicode和UTF-8的...
ssssssss
Qt 连接数据库QODBC
java 服务 cpu 问题跟进
codeforces 405C
poj2777 Count Color线...

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多