打印

用ucos的小收获 1-2

[复制链接]
1299|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 qianlihu 于 2013-9-11 16:18 编辑


先说main函数。
     我们都说main函数是一个进程的入口函数,当然main只是一个名字,不过约定了他是入口函数——他便是入口函数。呵呵,其实一般情况下我们单片机上电以后都是从零地址开始逐条运行,只要我们把main函数的第一条指令下载到了零地址,cpu就会从main函数开始执行,可是C语言运行代码是需要栈的,这样如果第一条指令便进入了c代码,那堆栈寄存器(SP)便没有被设置,这样谁知道这个寄存器指向了哪?但是,其实这个也不必我们花心思,我们用的编译器,都给我们准备了一段代码,会为栈设一个合适的值的。这段代码的最后一句一般是个跳转语句,jump to main,so,这样便进入了我们的main函数。
再说程序的执行
一段程序运行起来需要两个基本的资源 cpu和内存。而一段代码在flash里面静静的躺着,如果不被调用,他便只好沉睡,可是他是怎样被调用的呢?其实呢,就是jump to fun();而跳转的过程,其实就是 把fun()函数的地址赋值给了PC寄存器,然后命令cpu从PC寄存器指向的地址取指令,这样,cpu就把在flash静静躺着的代码唤醒了,可是这样还不行,c代码执行是需要栈的,无奈只好再对SP寄存器下手,调节一下他指向的地址。

如图,一个前后台的程序大概就是这样,无论main函数多么里面有多少子函数,无论其cpu走过的地址是多么曲折,他最终是个死循环,而SP也只是在一段连续的内存上动态调节栈的容量,就是这样,我们的前后台系统就可以跑的相当欢快。

可是假如说我们主动的去改动PC和SP的内容会怎样呢?

我又画了两张图~~,假如我们理智(好吧理智这个词也不错)的改变了PC寄存器和SP寄存器的值(当然跳走之前要保存一下),这样便能完成从左图到右图的跨越,再在合适的时机跳回原来的地方,又完成了从右图到左图的跨越不是,这样对于左图来说,是不是神不知鬼不觉的偷偷溜走了一会而没被老师发现???
可是这样又有什么意义?意义呢就是,我们得到了两个死循环,两个啊。。。

如果我们总是能够在最合适的时候跳转在俩个死循环之间,这样从微观上讲是两个死循环分别独占CPU,可是从宏观上来讲,便是两个死循环并行运行了。

其实呢操作系统就是为了管理这种调转的,操作系统总是能够找到最好的时机让他跳转。

好吧,今天先写这些   9.10~
  
其实具体的跳转实现是复杂些的,要结合具体的硬件进行分析,因为我用的是cortex—M3,就基于这个单片机说一下他跳转的具体过程吧。

其实这个跳转的过程和中断动作非常像。当中断到达时,CPU执行跳转到中断入口地址,然后更新PC寄存器,嗯还是画个图吧~

file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/enhtmlclip/Image.png           file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/enhtmlclip/Image(1).png
中断发生时,CPU硬件会把psr,pc,lr,r12,r0-r3等八个寄存器入栈,所以栈一定是要增长的,当然中断执行过程中我们也有可能会使用一些局部变量,这样栈也会增长,不过到最后程序执行完毕,该出栈的还是会出栈,一切就会回到原来的样子。中断始终是要依靠在原来的栈地址的,这样呢就显得不够独立,但是M3其实有两个栈寄存器的MSP和PSP,假如有两个连续内存的栈空间,MSP指向其中一个,PSP指向另一个,而我们又可以利用CM3 的机制,在中断的时候使用MSP,以MSP初始指向的地址为基地址增长,平常的时候使用PSP,在PSP指向的基地址上增长,这样的话,我们就有了两个栈空间了。

file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/enhtmlclip/Image(2).png

这样是不是就和两个死循环的例子有点像了?其实呢,使用ucos的时候我们会为每一个死循环搞一个数组,也就是申请一段连续的内存,这样我们使用一个SP寄存器就能达到这样的目的的。只不过多了点麻烦事,需要我们人为的改变SP的值,不过无论如何我们有了独立的栈空间了。而ucos会为我们把sp的值设置好的。
这样我们可以这样想象,每个任务(死循环),可以看做另一个任务的中断,而我们平常写惯了前后台程序,在处理中断的时候不是总想着中断和主程序是异步的么?然后我们会谨慎的使用能被中断改变的全局变量~










相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

7

主题

34

帖子

1

粉丝