查看: 2078|回复: 0
打印 上一主题 下一主题

stm32f107vc金龙开发板 RT_Thread OS例程说明

[复制链接]
跳转到指定楼层
沙发
发表于 2015-5-28 15:12:02 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
[size=14.3999996185303px]RT_Thread OS 基本例程说明
[size=14.3999996185303px]        本文档主要针对RT-OS基本例程的说明,不对RT-OS的原理进行讲解,也不做移植的说明,因为RT-OS的论坛以及网站,已经对RT-OS的说明很详细,且有移植好的工程文件,移植教程里面也有详细的说明。所以这里我们只是根据下面链接的帖子里面的例程做一个总结,依据STM32F1进行编写的,这里我们把部分例程移植到我们的金龙107上面,
[size=14.3999996185303px]这些例程所用到的硬件只有串口,以及我们金龙107开发板的一个LED灯和一个按键,只需要用串口线把我们金龙107PC机连接起来,只需要一根串口线就可以完成RT-OS所有试验。其中LED灯是作为指示程序的运行,并没有其他作用,按键在其中一个例程中有用到。
[size=14.3999996185303px]例程已将Lwip移植到金龙107开发板上了,如果需要使用到网络可以在rtconfig.h文件里面将#define RT_USING_LWIP宏打开,同时在application.c文件中注释去掉修改如下:
[size=14.3999996185303px]
[size=14.3999996185303px]
[size=14.3999996185303px]跳线帽JP923,连接网线设置电脑IP192.168.1.203,开发板IP192.168.1.199。进入电脑命令提示符界面输入ping 192.168.1.199,显示如下信息,说明网络连接正常。
[size=14.3999996185303px]

[size=14.3999996185303px]1、动态线程的创建与删除
[size=14.3999996185303px]该例程主要说明动态线程的创建与删除,首先我们要在rtconfig.h中开启两个宏定义:
[size=14.3999996185303px]#define RT_USING_HEAP;开启此项可以创建动态线程和动态信号量,如果使用静态线程和静态信号量,则此项不是必要的。请注意这里的动态和静态,后面的例程大多用到动态线程或者信号量等,所以此项也是一直开启的,后面将不再赘述。
[size=14.3999996185303px]#define RT_USING_CONSOLE;本实验使用rt_kpriintf向串口打印按键信息,因此需要开启此项。后面的实验,都需要向串口输出数据,所以此项是必须的,我们就不再赘述。
[size=14.3999996185303px]另外还有一个宏定义,我们需要注意,就是:#define RT_TICK_PER_SECOND  100,这个宏定义的意思是,操作系统的100Tick1S,则一个OS Tick=10ms。后面的程序中我们使用的都是100,所以后面我们也将不再赘述此选项。
[size=14.3999996185303px]前面说过的,我们不对操作系统的解说,只是对程序的说明,如果对RT-OS不了解的地方,可以参考RT-Thread.pdfrtthread_manual.zh.pdf这两个文档,其中已经说的很详细。也可以到RT-OS官网上下载这两个文档。
[size=14.3999996185303px]下面开始讲解我们的程序,首先我们要定义两个指向动态线程的指针并建立线程入口函数,如图1-1所示。
[size=14.3999996185303px]
[size=14.3999996185303px]图1-1
[size=14.3999996185303px]        如图1-1所示,线程1首先打印信息,然后循环进行计数,并打印,延时1S继续循环。线程2首先也是打印信息,然后延时4S,然后删除线程1,并打印信息。
[size=14.3999996185303px]        下面看线程的创建,如图1-2所示。第一个线程是静态线程,上面提到的LED灯的闪烁,指示程序运行的作用。主要看下面的两个线程的创建下面的两个线程采用的是创建,而不是初始化,是不一样的。这是动态的线程,采用的是rt_thread_create()函数,返回的是线程控制块的地址。也就是我们上面定义的线程指针。
[size=14.3999996185303px]第一个参数是线程的名字,可以随意,
[size=14.3999996185303px]第二个参数是线程入口函数,
[size=14.3999996185303px]第三个参数是线程入口函数的参数,
[size=14.3999996185303px]第四个参数是线程的堆栈空间,
[size=14.3999996185303px]第五个参数是线程的优先级,
[size=14.3999996185303px]最后一个参数是时间片。
[size=14.3999996185303px]因为RT-OS支持时间片轮法,当两个线程优先级相同时,则采用时间片轮法进行线程的切换。最后判断线程是否创建成功,创建成功则给线程指针分配地址,则其不为空指针,然后启动线程即可。第二个线程一样。
[size=14.3999996185303px]
[size=14.3999996185303px]图1-2
[size=14.3999996185303px]结果分析:
[size=14.3999996185303px]        程序的执行结果如图1-3所示。
[size=14.3999996185303px]
[size=14.3999996185303px]图1-3
[size=14.3999996185303px]        上面是打印的RT-OS的信息,因为线程1的优先级比较高,所以先执行,打印一个数据,在线程1的循环中有一个延时,所以打印一次信息之后,要进行延时,则线程1挂起,执行线程2,打印成功创建线程2之后,线程2也进行了4S的延时,所以线程2挂起,等待线程1再运行三次,因为每次都是延时1S,当到了线程1打印出thread1 count: 1之后,再延时1S的时候,线程2的延时时间到,则执行线程2中的删除线程1代码,则线程1不再运行,线程2打印出信息之后,运行结束,并自行删除。
[size=14.3999996185303px]
[size=14.3999996185303px][size=14.3999996185303px]2、静态线程初始化与脱离
[size=14.3999996185303px]

[size=14.3999996185303px]该例程主要说明静态线程的初始化和脱离。上一节我们讲的是动态线程,这一节讲的是静态线程,这两种线程的建立有什么不同呢,请看图2-1所示。
[size=14.3999996185303px]
[size=14.3999996185303px]图2-1
[size=14.3999996185303px]        从图2-1中看出,静态线程的创建首先要定义线程的堆栈空间,以及定义一个线程控制块。而在动态线程建立的时候,只需要定义一个指向线程控制块的指针即可。这个实验和第一个实验动态线程的使用的实验现象基本上是一样的,一个是动态的,一个是静态的。第一个实验当删除线程1的时候,采用的是rt_thread_delete()函数,删除线程1,而这里采用的是rt_thread_detach()函数,使线程1脱离。这是两者不一样的地方,其次是在线程的创建的不一样。
[size=14.3999996185303px]如图2-2所示。我们看到,线程的创建采用的是rt_thread_init()函数,对线程进行初始化,返回的是线程是否创建成功,而动态线程则采用的是rt_thread_create()函数,进行创建线程,返回的是线程控制块的指针。且其中的参数也是不一样的。Rt_thread_init()函数的
[size=14.3999996185303px]第一个参数是线程控制块的地址,也就是上面我们定义的线程控制块的地址。
[size=14.3999996185303px]第二个参数是线程的名字,
[size=14.3999996185303px]第三个参数是线程的入口函数,
[size=14.3999996185303px]第四个参数是线程入口函数的参数,
[size=14.3999996185303px]第五个参数是线程堆栈空间的首地址,
[size=14.3999996185303px]第六个参数是线程堆栈空间的大小,
[size=14.3999996185303px]第七个参数是线程的优先级,
[size=14.3999996185303px]第八个参数是线程的时间片大小。
[size=14.3999996185303px]创建成功,则启动线程。
[size=14.3999996185303px]
[size=14.3999996185303px]图2-2
[size=14.3999996185303px]结果分析:
[size=14.3999996185303px]        如图2-3所示,是该程序的运行结果:该程序的运行结果和上一个实验的是类似的,也是在线程1运行一定时间之后,用线程2将线程1脱离或者删除。
[size=14.3999996185303px]
[size=14.3999996185303px]
[size=14.3999996185303px]
3、线程让出


本节主要说明的是线程的让出,而不是线程的删除或者脱离。线程的删除或者脱离之后,线程将不再运行,除非重新启动线程,而线程的让出,则只是暂时的把当前线程停止,让给其它就绪的线程,多用于有优先级相同的线程,否则,如果高优先级的线程就绪则直接抢占了,低优先级就绪,就算高优先级的线程让出,很快也会再次被高优先级的线程抢占。线程让出之后并不是线程被挂起了,线程依旧是就绪状态。所以说只对有优先级相同的线程有效。
上面两节我们说了静态线程的初始化和脱离,动态线程的创建以及删除。这节我们将不再说线程的创建或初始化等,只对程序和运行结果进行分析。如图3-1所示,是两个线程的入口函数。
3-1
        从图3-1中我们可以看到,线程1和线程2都是循环进行计数以及让出线程,不过线程1是先计数,然后让出线程,而线程2是先让出线程,在计数并打印。
        该例程需要注意的是,上面我们有提到线程的让出,只在相同优先级的任务之间的切换,所以这两个线程的优先级必须是一样的。
结果分析:
        如图3-2所示,是该程序的运行结果。从结果中我们可以看出,线程1首先计数并打印了两次,线程2才打印1次,后面的就是线程1和线程2的交替打印。线程1怎么会出现打印两次呢,是因为线程1先建立并启动,所以线程1先执行,首先打印1次,然后让出,线程2执行,线程2则先执行线程让出,这时候又变成线程1执行,然后线程1就又一次进行计数打印,而线程2一次也没有打印。待线程1打印结束之后,再次让出线程,这时候线程2才有机会计数并打印数据。所以后面就是交替的进行数据的打印。
        其实这个程序,打印到后面我们会发现又错了,不是交替打印,因为这个时候线程的时间片到了,所以线程被挂起了。
3-2



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入中科因仑

本版积分规则

快速回复 返回顶部 返回列表