UCOSII操作系统 第3课—UCOSII启动过程

UCOSII操作系统 第3课—UCOSII启动过程1、初始化UCOSII(1)在调用UCOSII在任何的其他的服务之前,UCOSII要求首先调用初始化函数OSInit();这个函数的目的就是在整个系统启动之前,初始化所有的变量和数据结构。(2)其中,在OSInit()函数中建立空闲任务OS_TaskIdle();这个任务总是处于就绪态的,空闲任务的优先级是设置为最低的。(3)调用OSInit以后,任务控制块缓冲池中有OS_MAX_TASKS个任务控制块,事件控制缓冲区中有OS_MAX_EVENTS个事件控制块,消息队列缓冲池OS_Q中有OS_MAX

大家好,又见面了,我是你们的朋友全栈君。

1、初始化UCOSII

(1)在调用UCOSII在任何的其他的服务之前,UCOSII要求首先调用初始化函数OSInit();这个函数的目的就是在整个系统启动之前,初始化所有的变量和数据结构。

(2)其中,在OSInit()函数中建立空闲任务OS_TaskIdle();
这个任务总是处于就绪态的,空闲任务的优先级是设置为最低的。

(3)调用OSInit以后,任务控制块缓冲池中有OS_MAX_TASKS个任务控制块,事件控制缓冲区中有OS_MAX_EVENTS个事件控制块,消息队列缓冲池OS_Q中有OS_MAX_QS个消息队列控制块等等。

2、UCOSII的启动过程

int main(void)
{ 
   
    OSInit(); /* 系统初始化*/  
    /* 创建主任务*/
    OSTaskCreate(MainTask, (void *)0, &MainTask_Stk[MainTask_StkSize-1], MainTask_Prio);
    OSStart(); /* 开始任务调度*/
    return 0;
}

(1)这是我们使用的一个移植到VS2013成功的UCOSII的代码工程。
里面有我们需要了解的启动UCOSII的全部的过程。

(2)刚刚说明的是OSInit()系统的初始化程序,就是为了初始化UCOSII启动过程的全部变量和一些内存池。

(3)通过调用OSTaskCreate()创建至少一个任务。
因为我们到时候,程序的指针SP,会跳出main.c的函数,那么如果不创建一个任务的话,那么程序的指针就会跑飞。

(4)OSStart()函数就是为了进行任务调度的,因为我们很快就会跳出main.c的函数,不会再跳进来,所以我们需要进行内部的指针跳出。

void  OSStart (void)
{ 
   
    if (OSRunning == OS_FALSE) { 
   
        OS_SchedNew();                               /* Find highest priority's task priority number */
        OSPrioCur     = OSPrioHighRdy;
        OSTCBHighRdy  = OSTCBPrioTbl[OSPrioHighRdy]; /* Point to highest priority task ready to run */
        OSTCBCur      = OSTCBHighRdy;
        OSStartHighRdy();                            /* Execute target specific code to start task */
    }
}

(1)这是UCOSII启动的一个关键的函数,此函数记录了我们操作系统是怎么进入多任务的状态的。

(2)解析:当OS的状态等于错误的状态的时候,把当前的最高优先级的任务赋值给OS的当前的优先级。

(3)最高优先级是通过位图来进行查找的,按上一讲已经完全说清楚获取最高优先级的算法。

(4)OSStartHighRdy()此函数是这个开始函数的关键,也就是这个地方进行任务的切换的,就是我们上一节课说明的进入中断,然后把CPU寄存器的值进行切换,从而跳转到最高优先级的任务当中。

void OSStartHighRdy()
{ 
   
    DWORD  dwID;
 
    OSInitTrace(100000);
 
    OS_ENTER_CRITICAL();
 
    OSTaskSwHook();
    ++OSRunning;
 
    OSCtxSwW32Event  = CreateEvent(NULL,FALSE,FALSE,NULL);
    OSCtxSwW32Handle = CreateThread( NULL, 0, OSCtxSwW32, 0, 0, &dwID );
 
    SetPriorityClass(OSCtxSwW32Handle,THREAD_PRIORITY_HIGHEST);
 
#ifdef SET_AFFINITY_MASK
    if( SetThreadAffinityMask( OSCtxSwW32Handle, 1 ) == 0 ) { 
   
#ifdef OS_CPU_TRACE
        OS_Printf("Error: SetThreadAffinityMask\n");
#endif
       }
#endif
 
    SetThreadPriority(OSCtxSwW32Handle,THREAD_PRIORITY_TIME_CRITICAL);
 
    OSTick32Handle = CreateThread( NULL, 0, OSTickW32, 0, 0, &dwID );
    SetPriorityClass(OSTick32Handle,THREAD_PRIORITY_HIGHEST);
 
#ifdef SET_AFFINITY_MASK
    if( SetThreadAffinityMask( OSTick32Handle, 1 ) == 0 ) 
    { 
   
#ifdef OS_CPU_TRACE
        OS_Printf("Error: SetThreadAffinityMask\n");
#endif
    }
#endif
 
    SetThreadPriority(OSTick32Handle,THREAD_PRIORITY_HIGHEST);
 
#ifdef WIN_MM_TICK
    timeGetDevCaps(&OSTimeCap, sizeof(OSTimeCap));
 
    if( OSTimeCap.wPeriodMin < WIN_MM_MIN_RES )
        OSTimeCap.wPeriodMin = WIN_MM_MIN_RES;
 
    timeBeginPeriod(OSTimeCap.wPeriodMin);
 
    OSTickEventHandle = CreateEvent(NULL, FALSE, FALSE, NULL);
    OSTickTimer       = timeSetEvent((1000/OS_TICKS_PER_SEC),OSTimeCap.wPeriodMin,(LPTIMECALLBACK)OSTickEventHandle, dwID,TIME_PERIODIC|TIME_CALLBACK_EVENT_SET);
#endif
 
 
    SS_SP = (OS_EMU_STK*) OSTCBHighRdy->OSTCBStkPtr;                      /* OSTCBCur = OSTCBHighRdy; */
                                                                          /* OSPrioCur = OSPrioHighRdy; */
    ResumeThread(SS_SP->Handle);
 
    OS_EXIT_CRITICAL();
 
    WaitForSingleObject(OSCtxSwW32Handle,INFINITE);
 
#ifdef WIN_MM_TICK
    timeKillEvent(OSTickTimer);
    timeEndPeriod(OSTimeCap.wPeriodMin);
    CloseHandle(OSTickEventHandle);
#endif
 
    CloseHandle(OSTick32Handle);
    CloseHandle(OSCtxSwW32Event);
}

此函数就是最终的函数,与硬件所在的平台是不一样的。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/139806.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 回溯法求解N皇后问题及其时间复杂度分析

    回溯法求解N皇后问题及其时间复杂度分析回溯法求解N皇后问题及其时间复杂度分析一、回溯法简介1.什么是回溯法?2.回溯法的时间复杂度分析蒙特卡罗方法蒙特卡罗方法在回溯法求解时间复杂度中的应用二、回溯法求解N皇后问题1.回溯法求解N皇后问题的过程2.回溯法求解N皇后问题的时间复杂度2.1求解时的效率分析回溯法进行效率分析的代码2.2时间复杂度分析一、回溯法简介1.什么是回溯法?  相信”迷宫”是许多人儿时的回忆,大家小时候一定都玩过迷宫游戏。我们从不用别人教导,都知道走迷宫的策略是:当遇到一个岔路口,会有以下两种情况:存

    2022年9月30日
    4
  • java 滤波算法_双边滤波算法

    java 滤波算法_双边滤波算法1、原理高斯滤波是以距离为权重,设计滤波模板作为滤波系数,只考虑了像素间的空间位置上的关系,因此滤波的结果会丢失边缘的信息。高斯滤波的缺陷如下图所示:平坦区域正常滤波,图像细节没有变化,而在突变的边缘上,因为只使用了距离来确定滤波权重,导致边缘被模糊。在高斯基础上,进一步优化,叠加了像素值的考虑,因此也就引出了双边滤波,一种非线性滤波,滤波效果对保留边缘更有效。为了理解双边滤波的距离和像素差两个影…

    2022年5月29日
    37
  • mp3格式音频文件结构解析图_mp3文件结构

    mp3格式音频文件结构解析图_mp3文件结构一、概述Layer-3音频文件,MPEG(MovingPictureExpertsGroup)在汉语中译为活动图像专家组,特指活动影音压缩标准,MPEG音频文件是MPEG1标准中的声音部分,也叫MPEG音频层,它根据压缩质量和编码复杂程度划分为三层,即Layer-1、Layer2、Layer3,且分别对应MP1、MP2、MP3这三种声音文件,并根据不同的用途,使用不同层次的编码

    2025年6月9日
    4
  • VLAN的特点及作用_vlan特点和作用有哪些

    VLAN的特点及作用_vlan特点和作用有哪些VLAN的作用:把同一物理局域网内的不同用户逻辑地划分成不同的广播域,有助于控制流量、减少设备投资、简化网络管理、提高网络的安全性。VLAN的特点:1)区段化:将一个网络进行区段化,减少每个区段的主机数量,提高网络性能;2)灵活性:一般情况下无须更改物理网络与增加新设备及更改布线系统;3)安全性:VLAN间的通讯是在受控的方式下完成的。转载于:https://www.cnb…

    2022年8月10日
    6
  • es6 模板字符串_es6 方法模板渲染

    es6 模板字符串_es6 方法模板渲染前言ES6(ES2015)为JavaScript引入了许多新特性,其中与字符串处理相关的一个新特性——模板字面量,提供了多行字符串、字符串模板的功能,相信很多人已经在使用了。字符串模板的基本使用很简单,今天就带大家来了解了解模板字符串。一、基本使用1、传统字符串传统做法需要使用大量的“”(双引号)和+来拼接才能得到我们需要的模版。但是这样是十分不方便的。并且存下一下几点缺陷:1)传统的字符串拼接不能正常换行2)传统的字符串拼接不能友好的插入变量3)传统的字符串拼接不能友好的处理单引号、双引

    2022年8月21日
    7
  • 文件服务器审计—首选Netwrix文件服务器审计工具

    文件服务器审计—首选Netwrix文件服务器审计工具文件服务器审计—首选Netwrix文件服务器审计工具为了遵守外部法规和确保业务连续性,企业需要审核他们的文件服务器,以确保防止敏感数据泄漏和未经授权的修改。看到论坛很多类似的讨论,而且微软自带的审计策略往往不能满足IT的所有需求。常常通过第三方的软件来实现文件服务器的审计功能。NetwrixWindows文件服务器工具有免费版本的变更通知工具以及收费版本的审计工具。可以自…

    2022年6月4日
    61

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号