ucos操作系统ucos任务调度是怎么运行

温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
图1.无操作系统流程该流程中当串口接收到数据再调用LCD显示程序将数据显示出来,而图2展示了一种基于操作系统的方法。在该方法中串口接收数据和LCD显示程序均以为自己独占CPU,各自都只是执行自己相关部分的工作,而什么时候显示到LCD屏幕,什么时候又继续接收串口数据这个协调工作将由操作系统完成。图2 操作系统流程&从以上比较可以看出操作系统协调了不同功能程序以让他们共同完成同一个工作。同时操作系统又隔离了各个功能程序让它们的耦合程度降低。这样就方便设计人员编写各个功能模块,同时整个系统的结构也更加清晰。特别是系统逻辑结构复杂,功能模块较多的情况下操作系统的这一优点体现的更加明显。2.操纵系统让每一个任务都认为自己独占CPU,方便代码编写。同样采用上边的例子,无操作系统情况下我么需要在适当的时候分别调用串口接收数据程序和LCD显示程序,而有操作系统时我们只需要完成两个功能模块代码然后加入到操作系统就可以了。两个功能代码都是以无限循环的方式执行,结构显得就很简单。3.操作系统增加代码的移植性。这一点我认为在ucOS系统上体现得并不明显,对于其他系统例如android,linux等系统可以这样讲,因为他们基本上应该算是一个中等复杂系统,而ucOS是一个简单嵌入式系统。对于一个中等复杂系统它的底层硬件设备是有一定要求的,例如android设备,根据系统特性它就需要有GPS支持,显示屏支持,电子罗盘支持,摄像头支持这些支持都被列入android设备的系统内,它们以驱动的形式存在。而上层的应用程序通过调用底层的支持进而实现复杂的功能。而ucOS我认为它仅仅只是一个调度器,他的工作就是协调多个应用程序在单个MCU上"同时"运行而已,它几乎是没有驱动这个概念的。&
阅读(16373)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
loftPermalink:'',
id:'fks_082066',
blogTitle:'ucOS学习笔记(1)——为什么需要操作系统',
blogAbstract:'1.操作系统可以显著降低开发难度。操作系统帮我们协调多个程序之间的耦合关系,比如我们需要将串口的接收到的数据显示在一块LCD上。传统做法是如图1所示&:图1.无操作系统流程该流程中当串口接收到数据再调用LCD显示程序将数据显示出来,而图2展示了一种基于操作系统的方法。在该方法中串口接收数据和LCD显示程序均以为自己独占CPU,各自都只是执行自己相关部分的工作,而什么时候显示到LCD屏幕,什么时候又继续接收串口数据这个协调工作将由操作系统完成。',
blogTag:'操作系统,ucos',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:6,
publishTime:0,
permalink:'blog/static/',
commentCount:2,
mainCommentCount:2,
recommendCount:3,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'',
hmcon:'1',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}移植ucos之后,为何系统一直在执行空闲任务? - 维库电子市场网
移植ucos之后,为何系统一直在执行空闲任务?
作者:碧水长天 栏目:
移植ucos之后,为何系统一直在执行空闲任务?连接错误的问题已经解决,移植之后烧写入之后,未发现预计的输出,于是用axd调试,一加载映象文件之后,程序指针就自动停在OS_TaskIdle (void *pdata)函数的for循环的第一条语句(函数)OS_ENTER_CRITICAL();处。虽然main函数建立的两个向串口发送数据的任务,但是串口并没有收到数据。请问两个问题:1.为何用axd调试时,程序没有从代码的开始处等待用户操作而是跳转到其他的地方?2.这个ucos是来自网上的 uc/os-ii&&for 44B0X的代码,在编译出现错误之后,我在OS_CPU.H中定义了OS_CRITICAL_METHOD,并在ucos_ii.c中去掉所有的文件包含语句,编译和连接均通过,无错误和警告。为什么系统没有进入执行main中的两个任务而进入了空闲任务??我用的是44B0X的公板,请高手指点或提示,谢谢!下面是axd一加载映像文件就进入OS_TaskIdle任务的代码和main代码void&&OS_TaskIdle (void *pdata){//#if OS_CRITICAL_METHOD == 3&&&&&&&&&&&&&&&&&&&&&&/* Allocate storage for CPU status register&&&&&&&&&&&*///&&&&OS_CPU_SR&&cpu_//#endif&&&&&&&&&&&&&&&&pdata =&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&/* Prevent compiler warning for not using 'pdata'&&&&&*/&&&&for (;;) {&&&&&&&&OS_ENTER_CRITICAL();&&&&&&&&OSIdleCtr++;&&&&&&&&OS_EXIT_CRITICAL();&&&&&&&&OSTaskIdleHook();&&&&&&&&&&&&&&&&&&&&&&&&/* Call user definable HOOK&&&&&&&&&&&&&&&&&&&&&&&&&&&*/&&&&}}main函数如下:#define&&&&N_TASKS&&&&&&&&&&&&5&&&&&&&&&&&&&&&&&&&&//
of tasks#define&&&&TASK_STK_SIZE&&&&&&&&&&&&&&&&&&&&// Stack size, in sizeof OS_STK, or int 32bitOS_STK&&&&TaskStk[N_TASKS][TASK_STK_SIZE];&&&&// Tasks stacksvoid Task1(void *);void Task2(void *);int Main(int argc,
**argv){&&&&int&&&&task_1 = 0, task_2 = 1;&&&&sys_init();&&&&Uart_Printf(&\n ### Main Starts !\n&);&&&&OSInit();&&&&OSTaskCreate(Task1, &task_1, &TaskStk[0][TASK_STK_SIZE-1], 1);&&&&OSTaskCreate(Task2, &task_2, &TaskStk[1][TASK_STK_SIZE-1], 2);&&&&OSStart();&&&&return 0;}void Task1(void * pParam){&&&&Uart_Printf(& @@@ Task1 will starts time ticker !\n&);&&&&// enable Ticker, 16 ticks per second&&&&tick_init(7);&&&&// why start tick here? see uCOS-II Doc Chapter 8 :&&&&/* &&&&&You MUST enable ticker interrupts AFTER multitasking has started, i.e. after &&&&calling OSStart().&&In other words, you should initialize and tick interrupts in&&&&the first task that executes following a call to OSStart().&&A common mistake is&&&&to enable ticker interrupts between calling OSInit() and OSStart() ...&&&&&*/&&&&&&&&while(1)&&&&&&&&{&&&&&&&&OSSchedLock();&&&&&&&&printf( &@@@\n&);&&&&&&&&printf( &@@@&&task 1 running ... \n& );&&&&&&&&printf( &@@@&&&&&Q__Q&&&&\n& );&&&&&&&&printf( &@@@&&&&/____\\&&&\n& );&&&&&&&&printf( &@@@&&&&\\____/&&&\n& );&&&&&&&&printf( &@@@&&&&&/\\/\\&&&&\n& );&&&&&&&&printf( &@@@&&__(\\\\//)__ \n& );&&&&&&&&printf( &@@@&&&__/w w\\__& \n& );&&&&&&&&printf( &@@@\n& );&&&&&&&&printf( &@@@&&go to sleep 10 time-ticks\n& );&&&&&&&&printf( &@@@\n& );&&&&&&&&OSSchedUnlock();&&&&&&&&Sleep(7);&&&&}}void Task2(void * pParam){&&&&while(1)&&&&&&&&{&&&&&&&&OSSchedLock();&&&&&&&&printf( &+++ \n& );&&&&&&&&printf( &+++&&task 2 running ... \n& );&&&&&&&&printf( &+++&&qr \n& );&&&&&&&&printf( &+++ {/ o o \\} \n& );&&&&&&&&printf( &+++&&( (oo) ) \n& );&&&&&&&&printf( &+++&&&&&& \n& );&&&&&&&&printf( &+++ \n& );&&&&&&&&printf( &+++&&go to sleep 5 time-ticks\n& );&&&&&&&&printf( &+++ \n& );&&&&&&&&OSSchedUnlock();&&&&&&&&Sleep(3);&&&&}} * - 本贴最后修改时间: 20:11:57 修改者:碧水长天
作者: willyar_cn 于
22:58:00 发布:
就是重复定义啊在你的os_core.c和 ucos_ii.c有重复定义,也有可能你在INCLUDE文件时使用不合理。
作者: 碧水长天 于
23:40:00 发布:
谢谢willyar_cn的提醒我查了一下,发现将ucos_ii.c的文件改动如下(添加“//”的为改动痕迹),make时提示无错误,谢谢!------------------------ucos_ii.c---------------------#define&&OS_S&&&&&&&&&&&&&&&&&&&&&&&&&&&/* Declare
variables&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*///#include &includes.h&#define&&OS_CRITICAL_METHOD&&&&&2#define&&OS_MASTER_FILE&&&&&&&&&&&&&&&&&&&&&&//#include &os_core.c&//#include &os_mbox.c&//#include &os_mem.c&//#include &os_q.c&//#include &os_sem.c&//#include &os_task.c&//#include &os_time.c&//#include &os_mutex.c&
作者: 碧水长天 于
20:18:00 发布:
自己顶一下为节省论坛空间,我修改了主题贴,并提出两个新的疑惑请教大家。原来的标号多重定义的问题已经解决,主题贴中的图片是标号多重定义的错误的图示,我没有删除。请大家指点一下小弟,发现不能和高手面对面交流而一个人挤时间来学习ucos和arm真是进步缓慢,也许是我天资不佳吧,不过幸好还有论坛里热心的站友的指点。
作者: 碧水长天 于
16:48:00 发布:
问题已经解决44binit.s有缺陷,而编译没有发现,导致异常。
讨论内容:
Copyright &
浙ICP证030469号安全检查中...
请打开浏览器的javascript,然后刷新浏览器
< 浏览器安全检查中...
还剩 5 秒&查看: 881|回复: 0
注册时间最后登录阅读权限1积分212精华0帖子
侠客, 积分 212, 距离下一级还需 88 积分
UCOS内核结构学习笔记 转贴& &
呵呵,大家好,这是一位网友写的笔记,刚才初步整理了一下,希望对大家用。
◆ 任务,在UCOS-ii实时系统中,一个任务其实就是一个线程,该任务可以认为CPU完全属于它自己。UCOS-ii中的任务拥有自己的堆栈和CPU寄存器,并且赋予一定的优先级,在UCOS-ii中,它可能处于睡眠、就绪、运行、等待、中断服务状态之一。具体这5种状态的定义请看我的另一篇博文《UCOS Learning Notes N.O. 01》。
◆ 基于优先级的内核有两种:不可剥夺型和可剥夺型。不可剥夺型内核它要求每个任务互相合作,也称为合作型内核,每个任务不会被其它任务剥夺去,除非中断的到来,即便如此,当中断结束后,还是会回到原来被中断的程序,而不会切换到具有高优先级的任务中去,这样,高优先级的任务就不能够及时得到执行,所以它的实时性是比较差的。但是它有一个很重要的特点,就是它可以使用不可重入函数,因为每个任务必须执行完,才能释放CPU,这样它对其它任务调用可重入函数没有影响;同理在大多数情况下它无须使用信号量来保护资源。[补记:我们有时候写前后台的程序时,通常利用了分时的观念,即我们在延迟中执行其他代码,这从本质上也可以说是借鉴不可剥夺的内核特点来写的,至少它们有相同之处吧,不过这要球程序对自己的程序运行过程非常清楚,其实这也是正确使用UCOS实现它最优实时性的前提,不过这境界有点难咯,我自己也没有做到,让我们努力吧!]
& & 对于可剥夺型内核,只要高优先级任务一就绪,那它就会被执行,而当前正在执行的任务就会被挂起;正因为如此,对于系统的资源就不能像不可剥夺型那样去使用,而是在使用前必须检查是否可以使用,即互斥机制来保护临界资源,如果不用的话,那么如果低优先级在使用临界资源时,突然被高优先级把CPU给抢过去了,那么低优先级的临界资源就可能会被告优先级任务给破坏掉;可剥夺型的优点是是系统的响应时间得到了优化,且是可知的。
◆ 实时系统中,中断优先级反转这一问题是出现得最多的,这问题的本质其实也不能理解,就是低优先级的任务占有高优先级的任务所需要的资源,而使高优先级不得不等低优先级把资源释放才能执行。
◆ 任务控制块OS_TCB,它是一个有结构体组成的,每当一个任务被建立时,它就会被建立,并且和系统中的任务组成一个双向链表,它的第一个结构体成员是堆栈栈顶指针,这样做的好处避免在移植过程中出现不必要的偏移地址计算过程,节省了CPU的时间,由于它是一个双向链表,自然会有前向指针【指向前面一个任务控制块】和后向指针【指向后面一个任务控制块指针,最后一个任务块指针指向空指针】,还包含有与该任务优先级以及与优先级相关的数据成员和与该任务有关的事件、邮箱、队列等,其它的成员我暂时用不着,先PK掉,以后用时再看。在这个结构体中,我觉得应该值得时刻注意的是:任务堆栈指针,任务状态,任务优先级。
◆ 任务控制块的初始化,它其实就是从空任务控制块中取一个任务控制块,并对它的成员进行初始化。
◆ 任务的就绪表,我认为这时UCOS中的几个经典部分之一,记得我当时第一次看它时,发现这很奇妙,心中直夸作者的智慧。我们在创建任务时,系统跟住优先级来分配控制块和堆栈,首先系统会对优先级进行一个检查,如果该优先级没有被其它任务占有,那么它就分配给该任务;同时这很明显会出现一个问题,怎样去管理这些优先级以及怎样知道优先级的使用情况就成了该系统自然要解决的问题,该系统的作者很有智慧,发现了优先级的数字有这么一个功能,系统有64个优先级,由于我们的字节是8位的,呵呵,很明显来个8*8的矩阵,再仔细一看,原来一个优先级的位3~5的10进制数可以作为优先级在哪一组,位0~2的10进制数可以作为在该组中某位为1的位,然后一算,呵呵恰好是优先级的数,这种思维在UCOS中用了好几次。系统在进行任务切换时,是把CPU分配就绪表中优先级最高的任务,那怎样来找呢,因为我们已经知道优先级的数字有那么一个巧妙在里面,何不好好利用之呢,我们要想知道就绪任务的最高优先级的值,就要知道优先级所在的组以及所在列,我们先来找组,因为优先级的值越小优先级越高,那么无论就绪表中的表那几组为1,就绪任务肯定在最低一位为1所在的列中找,那么很自然我们可以这样来见表,依次从0~255开始来设,即优先级组的值为1时是在第几组,为253时又在第几组,这个表一建成,就是一个1*256的数组,再仔细看发现找列时也可以跟住这个表来查找,真是得来全不费功夫。优先级的低3位和3~5位都知道了,然后在跟住优先级就绪表的原理反过来就可以计算出就绪表中任务最高优先级的值拉。
◆& &&&OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()也可以用来保护应用程序中的临界代码;然而要特别小心,如果在调用一些如OSTimeDel()之类的功能函数之前关中断,应用程序将会死机;原因是任务被挂起一段时间,直到挂起时间到,但由于中断关掉了,时钟节拍中断一直得不到服务,显然所有的挂起类调用都有这样的问题,所以要特别小心。作为一条普遍适用的规则,调用UCOS-ii功能函数时,中断总是开着的。
◆& &&&任务调度,因为UCOS总是运行优先级最高的任务,而CPU的使用权转移到优先级最高的任务这一过程是通过任务调度来完成的,具体它的实现步骤在UCOS中其实现代码是比较简单的,首先是关中断,其次检查其调用是否来自中断或者至少调用了一次给任务调度上锁函数,并且没有释放锁,都将不能执行调度,否则发生死锁,简单说明一下,在中断中,肯定是不能调度的,应该不难理解,如果任务调用了上锁函数,但是又没有释放,即没有释放资源,那么很有可能其它任务需要那资源而发生优先级反转现象。然后在执行任务的切换。
◆ 任务级的任务切换和中断级的任务切换,其具体思路清参照我写得
◆ 给调度器上锁和开锁,给调度器上锁用于禁止任务调度,一般它开锁成对使用,其在UCOS中的实现代码很简单,只是要特别注意的是,上锁时要先关中断。
◆ 空闲任务,UCOS中至少要有一个任务,那就是空闲任务,不过其优先级最低,也就是说当其它任务没有进入就绪表时,它才运行,因为它总是处于就绪状态,它只是一个简单的计数器计数。在统计任务中要用到它。
◆ 统计任务,它就做一件事,就是计算CPU的利用率,可这过程我个人认为要一定的时间,因为里面尽是计算,并且牵涉到除法。在UCOS启动时,如果要启动统计任务,首先要把OS_CFG.H中的OS_TASK_STAT_EN设为1,那么这个任务就会建立,且一直处于就绪状态,并且刚开始时,由于空闲任务,肯定会运行的,运行多久,1秒,为什么是1秒,自己分析下代码就会明白啦,计数1秒又有什么用呢,为以后计算CPU的利用率提供一个基准值,因为这个值将会一直保存起来的,保存在哪,保存在统计任务的堆栈里,且不会改变,除非重新启动CPU;那么以后空闲任务不一定会有1秒的时间连续执行,空闲任务执行时,没次被其它任务抢走CPU时,它里面的计数器就会直接记录下CPU空闲的时间,怎么算呢,1s内它的计数值我们是知道的,那么CPU以后空闲的计数值我们也有记录,只是这些计算过程由统计任务来完成。
◆ UCOS的初始化,它首先是系统所用的全局变量比如上锁次数,中断次数,任务次数,任务切换次数等等的初始化,然后是就绪列表、任务控制块、事件控制块等的建立,其次是空闲任务或和统计任务的创建。
◆ UCOS的启动,找出就绪列表中的优先级最高的任务,并启动任务调度,且永不返回
Powered by查看: 2406|回复: 0
uC/OS-II,不能运行多任务
& & & & & & & & & & & & ucos无法运行多个任务的原因,检查原因:
存在5个问题,修改就可以了
(1)主要是在OSStart();前面缺少下列语句,系统老的时钟中断无任务切换功能:
OS_ENTER_CRITICAL();
PC_VectSet(0x08, OSTickISR);
PC_SetTickRate(OS_TICKS_PER_SEC);
OS_EXIT_CRITICAL();
由于ST的固件版本一直在更新,所以上面的代码仅作参考,只要明白代码所要表达的意思即可。
在firmware 版本v3.5的函数中实现的代码如下:
void OS_CPU_SysTickInit (void)
&&RCC_ClocksTypeDef rcc_& &// 获取系统频率
&&RCC_GetClocksFreq(&rcc_clocks);&&//配置HCLK作为SysTick时钟
&&SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
if(SysTick_Config((rcc_clocks.HCLK_Frequency / OS_TICKS_PER_SEC) -1)) //SysTick配置函数
while (1); }
(2)printf( )是DOS服务,不可重入,必须改成可重入的函数,如PC_DispStr()函数,或者写为
OS_ENTER_CRITICAL();
printf(&this is App_one,prio=10,Delay 6 second and startagain\n\n&);
OS_EXIT_CRITICAL();
等就可以了。原来的系统自带的那几个test程序,就都没有使用printf()函数。
这个一定要注意。大部分都是错在这个地方。调用系统函数的时候一定要搞清楚所调用的函数的功能和特性。
(3)另外OSTimeDlyHMSM(0,0,0,3000)是不允许的,要写为OSTimeDlyHMSM(0,0,3,0);
否则认为OSTimeDlyHMSM()参数无效而忽略,任务App_one不延时而长期循环,不切换。低级错误,不允许出现!
(4)因为prio=10,20,30,所以OS_CFG.H中要至少定义
#define OS_LOWEST_PRIO 32
否则某些低优先级任务被认为无效,不参与切换。在os配置中注意设置。
(5)高优先级任务一直占着CPU,低优先级任务得不到执行。每个任务都要释放一下CPU,在任务中加入一个系统延时函数就好了。
Powered by}

我要回帖

更多关于 ucos任务切换 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信