ucos在s3c2410上运行过程整体剖析-从main函数到UCOS初始化完毕
扫描二维码
随时随地手机看文章
下面要讲解的内容基本上都是c语言编写的了,还有一部分代码是用汇编写的。以下我就以这个系统移植的实验源码为例做详细讲解。讲解的方式是根据程序执行的顺序进行,如果感觉有什么难理解的地方,会做一个宏观讲解和分析。
好了废话不多说,进入main()函数之后做的事情有:
对硬件平台做进一步的初始化操作
对ucos操作系统做初始化操作
对硬件的初始化主要包括:
初始化时钟总线
初始化串口
初始化中断结构体的相关内容
初始化定时器
关于以上的时钟的,串口的,还有定时器的等硬件的具体初始化和使用我不想一一详细阐述,这些你都可以通过查看datasheet自己弄明白的。毕竟我想详细讲解的是UCOS这个操作系统,只不过有些硬件知识是不得不讲的。我这里只是做一个你查资料的一个索引。
关于时钟频率初始化的相关知识:一,你可以查看datasheet的第七章CLOCK & POWER MANAGEMENT的内容,也可以参考S3C-2410--2440完全开发流程的第十二个实验的相关知识和内容。
关于串口的你查看datasheet的第十一章uart的相关内容。
关于定时器的你查看datasheet的第十章PWM Timer。
关于中断结构体,这是ucos响应中断的统一接口。就是定义了一个结构体,里面包含了中断服务函数的指针,屏蔽和开启相应中断请求的函数指针等。整个中断的详细机制,我想在ARM平台的中断机制和ucos如何挂接的时候详细讲解。
现把main()函数的代码贴出来:
int main(void)
{
ARMTargetInit(); // do target (uHAL based ARM system) initialisation //
//初始化硬件平台
OSInit(); // needed by uC/OS-II //
//对ucos进行初始化
OSTaskCreate(Task1, (void *)0, (OS_STK *)&task1_Stack[STACKSIZE-1], Task1_Prio);
OSTaskCreate(Task2, (void *)0, (OS_STK *)&task2_Stack[STACKSIZE-1], Task2_Prio);
OSAddTask_Init(0);
OSStart(); // start the OS //
// never reached //
return 0;
}//main
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Task1(void *Id)
{
for(;;){
printf("run task1n");
OSTimeDly(1000);
}
}
void Task2(void *Id)
{
for(;;){
printf("run task2n");
OSTimeDly(3000);
}
}
关于初始化硬件平台的部分前面已经说明了查看哪些资料,就不多说了。
讲解关于ucos的初始化前,我要说一下这个ucos操作系统的相关知识,以及我讲解这个操作系统的基本方法。
我们都知道操作系统的目标就是充分利用计算机提供的硬件资源,合理进行调度并为用户提供友好的借口。这些资源包括处理器(cpu),内存,外围设备等,而其中ucos是一个嵌入式的实时操作系统,它主要管理和调度的资源就是cpu。我们将剖析它是怎么实现cpu的较高的利用率的,以及是如何实现实时性的。分析一下我们平时用电脑那种既能听歌又能同时打游戏这样的功能是怎么做到的。分析我们平时看到的现象和真实的实际情况有什么不同点。嘻嘻
我们都知道cpu的核心是一个叫晶振的东西,它能产生固有的脉冲频率,cpu就在这种信号下有规律的工作,那操作系统是谁给提供这种时序性那,答案是定时器,定时器以固定的时间向cpu发出中断请求,而ucos的一些功能都是在定时器的中断服务程序里实现的。所以定时器是操作系统必须的硬件,有了定时器操作系统才有了生命。才能实现实时性!!!
因此,我将通过两条线路来讲解ucos操作系统的执行流程:
一:正常的执行流程
二:被定时器中断后的中断服务程序
需要注意的是这两条线路是交叉执行的,因为定时器中断是周期性的,所以不论正常程序执行到什么地方定时器中断都有可能发生。其实,就是因为这种打断性才使操作系统的多任务调度有了基础。这个当你充分从整体的角度理解了ucos操作系统,你就知道了。
前面说了,ucos主要管理的是处理机的调度,那调度什么那?其实一个程序可能因为某些原因不能一直占有处理机,比如说他在等待一个资源,它再占用处理机那就相当于占着茅坑不拉屎。所以在有操作系统的时候,就可以有多个程序在不同的时间里占用cpu,这样有执行环境的程序,我们给他取个名字叫任务或者进程。而ucos就是决定什么时候该那个任务运行的。
所以,在分析源码之前还是要说明一个重要的概念,那就是任务(进程)。
相信大家对计算机能同时干这么多活这一现象可能存在疑问,那是什么机制让我们的电脑做到了真正的三心二意那,那当然属操作系统了。它管理着我们的电脑到底该干什么工作了?上一个工作干到什么程度了。我们也知道程序是一段有顺序的解决问题的指令。我们的机器里面只有一个CPU,但可能有很多解决问题的程序,他们肯定要争夺CPU这个资源,怎么管理他们,让他们有条不紊的运行下去那。这是我们今天要讨论的问题,怎么样,你有什么好的想法吗?
其实,这个问题也很简单,比如咱们现在先不说什么程序代码。我们先说一个类似的问题。
让你带着5个小孩玩,你的任务就是看护这5个小孩,让他们不打架,不受伤害,玩的开心。
而你现在只有一个游戏机,而你现在就面临着这样一种情况,怎么利用这一个游戏机让所有的孩子都能玩好又不产生矛盾。
要是我解决这个问题的话,我可能会这样去做,跟孩子们说:因为只有一个游戏机,你们5个只能轮流着玩这一个游戏机,没人玩半小时,那至于谁先玩的问题,我们这样,今天谁先来的这里谁就先玩(即谁今天来的早谁就先玩)。好了,这个问题到现在为止解决了。不,到真正实施的时候可能会遇到一些问题,比如一个孩子玩够了半个小时,是让他自己自愿提出来我玩的时间到了还是有你在旁边计时并强制让其给另一个孩子玩。还有每个孩子玩的游戏进度都不一样,你可能还要保存每一个孩子玩的进度问题,因为每一个孩子都只关心自己玩的游戏而不关心别的事情。当然,还有一些其他的问题,一个孩子特别不懂事,非要提前玩游戏机,你还要考虑这个问题。当然,在实施过程中还有很多问题,你能想一想还有其他什么问题可能在这个过程中遇到吗?
呵呵,看似一件很简单的事情,做起来还真有难度。其实很多事情都是这样,在一件事情还没有真正做之前做一些计划和方案是很难的,因为你不知道会遇到什么临时情况。但我们一般会做计划,并且要考虑所有可能遇到的情况以及遇到这些情况的处理方案。
好了,闲言少叙,回归到我们要处理很多程序争夺一个CPU的问题。显然,程序没有小孩那么智能,它不能听懂一些规则。因此,我们必须把这些规则具体化,即用程序代码去实现这些规则。因为计算机只认识程序。
好了,上面一直说程序,这个很好理解,也就是一个算法。那这个算法怎么才能体现出它的具体价值那,恩,这是一个事。比如,你写了一个程序计算两个10以内的两个数的加法。那你的目的很明确就是输入两个10以内的数,而得到这两个数的结果。你可以通过计算机的输入设备来进行输入,可以利用输出设备来进行输出结果。而程序在计算机运行一遍的这个过程所产生的效果是我们想要的。那把程序中的代码一一运行产生效果的这个过程,原来那一段静止的代码就一步步动起来了。当然它运行起来了肯定会需要一些环境,这些环境当然是计算机硬件提供的了,关于程序运行到底需要哪些具体的环境,我们下面具体探讨。那我们给这个正在在计算机内部执行的这个程序起个名字。叫什么那?
别人已经起好了,叫进程了,或者任务。
现在大家明白什么叫进程了吧,其实就是一段代码加上这段代码在计算机内部运行时所需要的所有环境。不管现在它运行没运行,一段程序加上可在计算机内部运行的能力,我们给他起了个名字叫进程(可能大概的意思是正在运行的程序吧)。
这是我对进程(任务)的理解。这是在计算机操作系统中对底层最基本的一个抽象。在上面说的带小孩玩的例子中,每一个小孩就是一个进程(任务)。我会在下一个章节中具体以UCOS为例,