logo资料库

ucosii在VC++6.0环境下的调试.pdf

第1页 / 共8页
第2页 / 共8页
第3页 / 共8页
第4页 / 共8页
第5页 / 共8页
第6页 / 共8页
第7页 / 共8页
第8页 / 共8页
资料共8页,全文预览结束
之 by francis_hao yinghao1991@126.com 学习 ucosii 也有一段时间了,说实话,刚开始学习的时候感觉 很浮躁,恨不得一两天就把它学会。因为感觉自己能学习的时间不多 了。想趁着这段时间多学点东西。可是越着急越乱。教材匆匆翻了好 几遍却没留下什么印象。对一些基本的概念依旧不了解。忽然发现没 有了学习的感觉,因为之前在一些比赛中,需要在很短的时间里把所 需要的模块开发出来,即使你不明白其中原理。这样久了,我便也懒 惰了。知其然,不知其所以然。其实,快速开发是一种能力,却不是 学习的方法。平时的学习还是要踏实一点。步步精通才是好的。 我认真总结了下,便开始以新的态度对待它。把教材上的每一章 节都细细品读。我的教材主要是以下两本: 西安电子科技大学出版社的《嵌入式实时操作系统 uc/os-ii》 任哲老师的《嵌入式实时操作系统 uc/os-ii 原理及应用》 第一本是我们学校的教材,但是我感觉里面的内容过于详细,对 于初学者来说反而会造成适得其反的效果,让人不知就里。但作为手
册看还是很好的。任哲老师的书想必大家都熟悉,它的框架性很强, 看过一遍后,便对这个系统有了总体的认识。书中语言简洁明了,适 合初学者。 对于 ucosii 的学习就不说了,主要谈谈 ucosii 在 pc 上的移植, 在 VC++6.0 环境下的使用。 作为初学者,总是力求简洁明了,我在学习的时候,一定要把为 什么这样做想清楚。知道这样做的原因,或者还有没有其他的方法。 也算是从零开始吧,除去我那点薄弱的 c 语言功底。 开始的时候是从网上下载的工程,直接编译运行就可以了。当时 很高兴,觉得自己很厉害了,可是这毕竟是别人的东西。怎样建工程 自己还不会。于是我想只用 ucos-ii 源码,自己建一个工程,看看能 不能运行。如果能运行了,那么自己离成功也就不远了。 内核文件总共有 16 个,11 不需要改动。有三个与处理器有关, 两个与应用程序相关。我在工程中建了一个 source 文件夹,所有的 源文件都放在里面,那 11 个不需改动的文件放在 source\core 文件 夹中,与处理器有关的文件被改成了 os_cpu.h、os_cpu_c.c、 os_trace.c、os_trace.h 我们拿来用就好了,放在 source\cpu 中。 还有就是与应用有关的文件了,放在 source 文件夹下就好了。这样 的分类好处是方便对各类文件的管理。 我下载的工程的结构是这样的:
这个可以编译,运行一切正常,但是因为里面没有那些内核文件, 我感觉很费解,便在自己建的工程中将所有的文件都加进去了。 但是内核文件有个 os_dbg_r.c。这个我们过会再讲。
现在这样的文件结构才是作为初学者的我所能接受的,于是很兴 奋的点下编译,事情就变成这个样子了: 晕了,怎么会有这么多错误呢?而且好像都是连接错误。变量重 定义了。是 ucos_ii.obj 中的问题,.obj 文件存在就说明文件本身 编译没有错误。是连接的时候出的问题。我在网上搜索资料的时候发 现一篇讲编译器原理的文章,写的很好,把编译和连接讲的很形象, 文章放在附录中,在此表示感谢。 ucos-ii.c 有问题,于是把这个文件打开看
就是这个样子了,这个文件包含了所有的内核文件,怪不得会出 现重复定义。Jean J. Labrosse 是为了让工程更简洁。在建工程的 时候只需将 ucso_ii.c 添加在工程中即可。我们尝试一下
怎么样?验证了你的猜想了吧,这感觉,像做了一次福尔摩斯。 爽了。但是我们这里的真相不止一个,还可以这样: 添加除去 ucso_ii.c 外所有的内核文件也是可以的。 两种方法的区别:第一种方法,在文件中定义的结构体不会出现 在 Class View 中,第二种则会显示出来。 还有一个问题就是 os_dbg_r.c 这个文件干嘛用的??? 我也不知道,具体的道理我不知道,只知道是关于调试的,如果 你知道,麻烦发到我邮箱。万分感谢! 不过现在。。。 管它呢,我觉得不需要,所以我把它删掉。编译 一下,出现问题了。果然不是随便能删的。
在文件中找“OSDebugInit”: 好了,到文件中看看去。 条件编译!!! 追踪到 OS_DEBUG_EN 中的定义中: 啊,原来是这样。那么我们把这个调试允许位改为 0 会是怎么样呢? 恩。如你所想,一切 OK。好了,这个工程这样就算是建好了,你可 以在上面做各种实验。开启你的 ucos 之旅吧!
附录: 变量、函数、类,分为声明和定义,至于格式,不再多说。 编译器编译的时候,先单独编译每一个 cpp 文件,然后用连接器把他们连起来。 一个 cpp 文件要能完成自己范围内的东西的定义,即,运用自己已经定义的东西,或者 声明了的东西。声明了的东西等于告诉编译器,虽然这个东西我没定义,但是在其他地方定 义了(文件内或文件外),你就先将就我告诉你的它的特征(类型,函数返回类型,参数等) 来用它就好了。比如我的 cpp 声明了 int number,现在需要完成一个函数的定义, void func() { Number++; } 好了,这个 number,虽然编译器在编译 cpp 的时候没看到定义(number=?),但是编 译器看到了声明,好吧,我就当做你保证了它(number)的存在(会在其他地方定义),先 帮你编译,不过如果最后也找不到它的定义的话,可别怪我翻脸哦(连接的时候没有找到定 义)。 好了,当每个 cpp 文件都编译好了之后,链接器开始链接它们了,怎么链接呢?说白了 就是核对各个文件里声明的东西到底有没有定义。如果发现某个文件只有声明没有定义,那 么就报错(好小子,说好了世界上存在长这个样儿的家伙,现在人在哪里呢?)。 记得当初学 c++的时候,让要把文件分开,说是方便组织,然后是要分为.h 和.cpp,而 且严格要求一个写声明,一个写定义,现在知道了,并非非这样不可,这是一种类似于约定 的东西,这样你的一个 cpp 文件可以单独地包含其他文件的.h,即严格地包含了其他东西的 声明,而不包含其他东西的定义。为什么这样,后面会说。至于我们经常用到的#ifndef #define #endif,则保证了在头文件互相包含的过程中不会重复包含。注意,这仅仅保证了一个文件 (A)里不会重复包含多个相同文件(B),但并不表示同一个文件(B)不会被其他多个文件(A,C,D…) 包含! 这意味着什么呢?如果一个文件重复包含头文件(声明),会事代码膨胀而且没有意义, 所以要避免。而对于 B 同时被 A,C,D 等包含的情况,如果 B 是仅包含声明,并无大碍,仅仅 表示 A,C,D 都要用到 B 里面声明的东西,如此而已。但是如果 B 是一个包含定义的文件,麻 烦来了,B 文件里声明的东西,因为 A,C,D 均包含了它的定义(编译器检查不到,前面说了, 对每个 cpp 文件来说,编译是单独进行的,编译器假设每个声明都会定义,所以不检查), 于是出现了所谓的“重定义”,如果某个文件 E 包含了 B 里面被重定义的东西的声明,那么 在链接 E 的时候,该把这个声明链接到哪个定义上呢(虽然逻辑上你知道每个定义都是一样 的,因为都是包含相同的文件得到的,但是链接器并不知道,但不要因此认为它 SB)?显 然,这个时候只好报错。 现在可以解释为什么约定.h 只放声明,.cpp 只放定义了。.h 放声明,方便其他文件引用 它的声明部分而不会包含到其定义部分,避免了重定义,而将定义全部放在.cpp 里,避免与 声明混淆。 严格按照规范写程序的人(h cpp 声明 定义分离)可能难得遇到这种错误,所以深刻 理解的机会就少,可能偶尔遇到,也弄不懂是什么意思…(这段话自己理解)
分享到:
收藏