嵌入式系统实验指导书2UCOS部分.docx
《嵌入式系统实验指导书2UCOS部分.docx》由会员分享,可在线阅读,更多相关《嵌入式系统实验指导书2UCOS部分.docx(62页珍藏版)》请在冰点文库上搜索。
嵌入式系统实验指导书2UCOS部分
《嵌入式系统原理及应用》
——UCOS部分
实验指导书
华南师范大学物电学院
前言
随着芯片技术和电子产品智能化的飞速发展,嵌入式技术越来越受到人们的关注,应用领域几乎遍及所有的电子产品:
智能机器人、网络通信、军用设备、汽车导航、环境保护、智能仪器等等。
嵌入式系统融合了计算机软、硬件技术、通讯技术和半导体微电子技术,针对实际应用系统要求,将相应的计算机直接嵌入到应用系统中,并可针对应用需求对软、硬件进行优化、裁剪。
通过嵌入式系统课程的学习并结合本次实验,使学生了解嵌入式系统的开发方法和流程,熟悉ARM9-2410硬件平台及其应用处理机的使用方法,熟悉UCOS-II嵌入式操作系统的基本原理、概念。
并能针对ARM9-2410硬件平台、应用需求自行定制、优化UCOS-II操作系统,并独立编写可在ARM9-2410嵌入式设备上运行的应用程序。
所以本实验指导书为学习ARM9-2410硬件平台的学生,配合《嵌入式系统原理与应用》课程的教学,结合ARM9-2410硬件平台编写了这本实验指导书。
《嵌入式系统原理与应用》是一门实践性很强的课程,提高教学质量的一个重要环节是上机实习和训练,无论是学习汇编语言程序设计,还是学习嵌入式操作系统,不通过加强动手是不能获得预期效果的。
本实验指导书提供多个实验的指导性材料,有些实验还有一些有一定难度的选做项目,可以根据课时的安排和教学要求进行取舍。
为了达到某些实验的目的,书中提供的参考程序与实际应用中的程序会有些差别,所以不一定是最优的。
由于时间紧迫,需要赶课程进度与实验时间的同步,加上编者学识有限,书中定有不少欠妥、疏漏之处,还请同学们不吝指正,以利于我们在今后的教学中不断改进和提高。
“嵌入式系统”是一门新兴的课程,如何能让同学们更好地掌握这门新技术,我们也希望听到同学们意见和建议,以便我们能推出更合理的教学、实验方案。
在此谢谢同学们在本学期的支持!
实验须知
1.实验前必须阅读教科书的有关部分和本实验指导书,了解实验目的、内容、步骤,做好实验前的准备工作,编写好实验中要求自编或修改的程序;完成实验前要求完成的准备工作后方可以上机实验,否则不得上机操作。
2.严禁带电接线和接插元器件。
通电前须经过指导教师检查认可后方能通电。
3.不准随意拨弄各种与实验无关的旋钮和开关,凡与本次实验无关的任何设备都禁止动用和摸弄,注意安全。
4.实验中若损坏仪器或元器件,应及时向指导教师报告。
5.在实验室内保持安静和卫生,不得随意走动和喧哗,集中精力完成实验。
6.实验完成后,关掉电源,及时整理实验台桌面,保持环境整洁。
7.按规定认真完成实验报告,在规定的时间内缴上实验报告。
8.凡实验或实验报告未能按规定完成的学员,不能参加本课程的考试或考查。
嵌入式实验报告格式
实验报告标题
一、实验目的
二、实验内容
三、实验设计及调试:
(1)实验分析及内容。
(2)实验设计及调试步骤:
根据内容写出实验程序。
调试程序,观察结果。
(3)实验调试过程中所遇到的问题、解决问题的思路和解决的方法。
四、实验后的经验教训总结。
五、对实验课的建议
第一部分UCOS-II内核移植和裁减
1.1uC/OS-II移植实验
一、实验目的
1.了解uC/OS-II内核的基本原理和主要结构;
2.掌握将uC/OS-II内核移植到ARM处理器上的基本方法;
3.掌握uC/OS-II下基本多任务应用程序的编写。
1.学习uC/OS-II再ARM处理器上的移植过程;
二、实验内容
1.了解嵌入式操作系统的构架,以及具体的uC/OS-II的组成;
2.了解操作系统的移植方法。
三、实验设备
1.硬件:
JX44B0教学实验箱、PC机;
2.软件:
PC机操作系统Windows98(2000、XP)+ADTIDE集成开发环境。
二、实验原理
1.uC/OS-II
uC/OS-II在特定处理器上的移植工作绝大部分集中在多任务切换的实现上,因为这部分代码主要是用来保存和恢复处理器现场,许多操作如读写寄存器操作不能用C语言,只能使用特定的处理器的汇编语言来完成。
将uC/OS-II移植到ARM处理器上,需要完成的工作非常简单,修改三个和体系结构相关的文件即可,代码量大约是500行。
这三个文件是OS_CPU_C.c、OS_CPU_C.H以及OS_CPU_A.S,下面将分别说明。
移植步骤之一--基本的配置和定义
所有需要完成的基本配置和定义全部集中在os_cpu.h头文件中。
●定义与编译器相关的数据类型。
µCOS-II为了保证可移植性,程序中没有直接使用int,unsignedint等定义,而是自己定义了一套数据类型,如INT16U表示16位无符号整型,对于ARM这样的32位内核,INT16U是unsignedshort型,如果是16位的处理器,则是unsignedint型。
●定义允许和禁止中断宏。
●定义栈的增长方向。
用户规划好栈的增长方向后,定义符号OS_STK_GROWTH的值。
●定义OS_TASK_SW宏。
OS_TASK_SW宏是uC/OS-II从低优先级任务切换到高优先级任务时的调用,可以采用下面两种方式定义:
如果处理器支持软中断,可以使用软中断将中断向量指向OSCtxSw函数;或者直接调用OSCrxSw函数。
移植步骤之二--移植OS_CPU_A.ASM汇编代码文件
OS_CPU_A.ASM汇编代码文件有四个汇编函数需要移植。
OSStartHighRdy函数
本函数由OSStart函数调用,OSStart函数负责使就绪状态的任务开始运行,其中OSStartHighRdy负责获取新任务的堆栈指针,并从堆栈指针中恢复新任务的所有处理器寄存器。
函数要移植的原因就是因为它涉及到保存处理器寄存器到堆栈。
OSCtxSw函数
本函数由OS_TASK_SW宏调用,OS_TASK_SW宏由OSSched函数调用,OSSched函数负责任务之间的切换;OSCtxSw函数在OSSched函数中负责保存当前任务对应的处理器寄存器到堆栈中,并将任务中需要恢复的处理器寄存器从堆栈中恢复出来。
OSIntCtxSw函数
本函数由OSIntExit函数调用,OSIntExit函数由OSTickISR调用,负责在定时中断中的任务之间的切换,前面提到的函数OSCtxSw和本函数均负责任务之间的切换,区别主要在于是否在定时中断期间负责任务切换;OSIntCtxSw函数主要保存当前任务堆栈指针,并将新任务对应的处理器寄存器从堆栈中恢复出来。
OSTickISR函数
时间节拍函数,由定时中断产生,主要负责在进入时保存处理器寄存器,完成任务的切换,退出时恢复寄存器并返回。
移植步骤之三--移植OS_CPU_C.C标准C代码文件
移植µC/OS-II的第三步是移植C语言源代码文件OS_CPU_C.C,这个源文件中由6个函数需要移植:
OSTaskStkInit()
OSTaskCreateHook()
OSTaskDelHook()
OSTaskSwHook()
OSTaskStatHook()
OSTimeTickHook()
后面五个HooK函数,又称为钩子函数,主要用来扩展uC/OS-II功能。
但必须声明,并不一定要包含任何代码。
唯一必需移植的函数是OSTaskStkInit函数,这个函数在任务创建时被调用,它负责初始化任务的堆栈结构。
这个函数在大部分ARM处理器中移植时都可以采用一种形式。
1.2内核裁减实验
一、实验目的
1.本实验的目的让学生了解如何在uC/OS-II下裁减内核。
二、实验内容
1.裁减uC/OS-II内核。
三、预备知识
1.C语言的基础知识;
2.程序调试的基础知识和方法。
嵌入式操作系统的裁减的一个直接的目标是使得在满足现有功能的前提下,去掉一些不必要的功能,并对现有程序进行优化使得目标系统运行的代码尺寸尽可能小。
代码尺寸不仅仅和程序编程有关,而且也和所使用的库文件相关,不同的编译器编译uC/OS-II得到的代码尺寸通常都是不相同的。
在ARM系统中,硬件资源,尤其是存储器资源通常都比较丰富,而且uC/OS-II本省已经是比较小型化的一个操作系统。
因此,裁减功能在嵌入式操作系统中体现的并不是非常迫切。
本实验的目的就是在JXARM9-2410上进行uC/OS-II的裁减,以学习和理解操作系统裁减的概念和方法,这对于其它操作系统的移植都是很有帮助的。
四、实验设备
1.硬件:
JXARM9-2410教学实验箱、PC机;
2.软件:
PC机操作系统Windows98(2000、XP)+ADTIDE集成开发环境。
五、实验步骤
本实验是在µCOS-II系统实验的基础上进行的,选择其中用到uC/OS-II的信号量的工程(假设为u1),首先从裁减该功能开始。
1.观察当前uC/OS-II的大小
打开ucos工作区,并设置u1为当前活动工程,然后编译,编译成功后将在UCOS-II\debug目录下有一个u1.elf文件。
然后点击“Tools”->“elftobinary”菜单项,屏幕将出现一个Windows控制台窗口后立即消失,此时通过在Windows资源管理器中查看UCOS-II\debug目录,可以看到生成了一个u1.bin的文件,在该文件上点击右键菜单的“属性”选项,可以看到该文件的大小,这个大小就是u1过程生成的代码大小。
2.裁减信号量功能(功能裁减)
打开UCOS-II\os_cfg.h文件
将其中的
#defineOS_SEM_EN1
/*IncludecodeforSEMAPHORES*/
修改为:
#defineOS_SEM_EN0
/*IncludecodeforSEMAPHORES*/
然后选择“Build”->“Clean”和“Build”->“Build”菜单,在output窗口的build提
示栏中提示编译错误,如下所示:
--------------------Configuration:
u1-DEBUG--------------------
OS_CPU_C.c
UCOS_II.c
44blib.c
uhal.c
OS_CPU_A.S
ramstart.s
u1.c
E:
/UCOS-II/UCOS-II/u1.c:
Infunction`Main':
E:
/UCOS-II/UCOS-II/u1.c:
134:
warning:
assignmentmakespointerfromintegerwithoutacast
E:
/UCOS-II/UCOS-II/u1.c:
135:
warning:
assignmentmakespointerfromintegerwithoutacast
Link......
.\debug\u1.o(.text+0xd4):
Infunction`TaskLED':
E:
/UCOS-II/UCOS-II/u1.c:
74:
undefinedreferenceto`OSSemPend'
.\debug\u1.o(.text+0xf4):
E:
/UCOS-II/UCOS-II/u1.c:
81:
undefinedreferenceto`OSSemPost'
.\debug\u1.o(.text+0x138):
Infunction`TaskSEG':
E:
/UCOS-II/UCOS-II/u1.c:
100:
undefinedreferenceto`OSSemPend'
.\debug\u1.o(.text+0x158):
E:
/UCOS-II/UCOS-II/u1.c:
107:
undefinedreferenceto`OSSemPost'
.\debug\u1.o(.text+0x198):
Infunction`Main':
E:
/UCOS-II/UCOS-II/u1.c:
134:
undefinedreferenceto`OSSemCreate'
.\debug\u1.o(.text+0x1a8):
E:
/UCOS-II/UCOS-II/u1.c:
135:
undefinedreferenceto`OSSemCreate'
U1.elf-builduncompleted.
上面的提示显示在u1.c文件中调用的OSSemPend和OSSemPost函数没有定义,它们是信号量函数,由于在UCOS-II\os_cfg.h文件中将OS_SEM_EN定义为0,也就是将信号量功能屏蔽掉了,因此也就没有OSSemPend和OSSemPost函数实现,所以报错。
解决的方法是,在应用程序中不要使用信号量相关函数。
修改后,重新编译,提示成功。
此时已经去掉信号量功能,uC/OS-II以功能来换取少量的代码空间,这也是裁减的一种方法。
然后重新生成u1.bin并查看其大小,并和修改前对比。
第二部分µCOS-II系统实验
实验一µCOS-II任务基础实验
一、实验目的
1.理解任务管理的基本原理,了解任务的各个基本状态及其变迁过程;
2.掌握µCOS-II中任务管理的基本方法(创建、启动、挂起、解挂任务);
3.熟练使用µCOS-II任务管理的基本系统调用。
二、实验内容
建立两个任务Task1和Task2:
任务Task1不断地挂起自己,再被任务Task2解挂,两个任务不断地切换执行。
并在串口打印相应的信息。
用户可以通过串口进行观察。
三、实验设备
1.硬件:
JXARM9-2410教学实验箱、PC机;
2.软件:
PC机操作系统Windows98(2000、XP)
四、实验原理
一个任务通常是一个无限的循环,由于任务的执行是由操作系统内核调度的,因此任务是绝不会返回的,其返回参数必须定义成void。
在μC/OS-Ⅱ中,当一个运行着的任务使一个比它优先级高的任务进入了就绪态,当前任务的CPU使用权就会被抢占,高优先级任务会立刻得到CPU的控制权(在系统允许调度和任务切换的前提下)。
μC/OS-Ⅱ可以管理多达64个任务,但目前版本的μC/OS-Ⅱ有两个任务已经被系统占用了(即空闲任务和统计任务)。
必须给每个任务赋以不同的优先级,任务的优先级号就是任务编号(ID),优先级可以从0到OS_LOWEST_PRIORITY。
优先级号越低,任务的优先级越高。
μC/OS-Ⅱ总是运行进入就绪态的优先级最高的任务。
五、本实验中所用到的µC/OS-II相关函数
1.OSTaskCreate()
建立一个新任务。
任务的建立可以在多任务环境启动之前,也可以在正在运行的任务中建立。
中断处理程序中不能建立任务。
一个任务可以为无限循环的结构。
函数原型:
INT8UOSTaskCreate(void(*task)(void*pd),void*pdata,OS_STK*ptos,INT8Uprio);
参数说明:
task是指向任务代码首地址的指针。
Pdata指向一个数据结构,该结构用来在建立任务时向任务传递参数。
返回值:
OSTaskCreate()的返回值为下述之一:
OS_NO_ERR:
函数调用成功。
OS_PRIO_EXIST:
具有该优先级的任务已经存在。
OS_PRIO_INVALID:
参数指定的优先级大于OS_LOWEST_PRIO。
OS_NO_MORE_TCB:
系统中没有OS_TCB可以分配给任务了。
2.OSTaskSuspend()
无条件挂起一个任务。
调用此函数的任务也可以传递参数OS_PRIO_SELF,挂起调用任务本身。
当前任务挂起后,只有其他任务才能唤醒被挂起的任务。
任务挂起后,系统会重新进行任务调度,运行下一个优先级最高的就绪任务。
唤醒挂起任务需要调用函数OSTaskResume()。
任务的挂起是可以叠加到其他操作上的。
例如,任务被挂起时正在进行延时操作,那么任务的唤醒就需要两个条件:
延时的结束以及其他任务的唤醒操作。
又如,任务被挂起时正在等待信号量,当任务从信号量的等待对列中清除后也不能立即运行,而必须等到被唤醒后。
函数原型:
INT8UOSTaskSuspend(INT8Uprio);
参数说明:
prio为指定要获取挂起的任务优先级,也可以指定参数OS_PRIO_SELF,挂起任务本身。
此时,下一个优先级最高的就绪任务将运行。
返回值:
OSTaskSuspend()的返回值为下述之一:
OS_NO_ERR:
函数调用成功。
OS_TASK_SUSPEND_IDLE:
试图挂起μC/OS-II中的空闲任务(Idletask)。
此为非法操作。
OS_PRIO_INVALID:
参数指定的优先级大于OS_LOWEST_PRIO或没有设定OS_PRIO_SELF的值。
OS_TASK_SUSPEND_PRIO:
要挂起的任务不存在。
3.OSTaskResume()
唤醒一个用OSTaskSuspend()函数挂起的任务。
OSTaskResume()也是唯一能“解挂”挂起任务的函数。
函数原型:
INT8UOSTaskResume(INT8Uprio);
参数说明:
prio指定要唤醒任务的优先级。
返回值:
OSTaskResume()的返回值为下述之一:
OS_NO_ERR:
函数调用成功。
OS_TASK_RESUME_PRIO:
要唤醒的任务不存在。
OS_TASK_NOT_SUSPENDED:
要唤醒的任务不在挂起状态。
OS_PRIO_INVALID:
参数指定的优先级大于或等于OS_LOWEST_PRIO。
六、实验步骤
1.在PC机上运行windows自带的超级终端串口通信程序超级终端,设置超级终端:
波特率115200、1位停止位、无校验位、无硬件流控制。
2.新建一个工程u1,并将E:
\caderm\examples\UCOS-II下的文件复制到新建工程u1目录下,将目录中的Core(Csource和Core(Assemble)的文件加入到工程u1中(添加C源文件u1\OS_CPU_C.c,u1\UCOS_II.c,E:
\caderm\examples\common\2410lib.c,E:
\caderm\examples\common\interrupt.c,u1\uhal.c和asm源文件u1\OS_CPU_A.S,E:
\caderm\examples\asm\2410slib.s,E:
\caderm\examples\asm\2410init.s),并按照之前的硬件实验的工程设置去修改u1的工程设置;
3.新建一个文件u1.c,并将其添加到u1工程的App文件夹
4.打开u1.c文件,复制参考程序。
5.编译u1.c,如果出错,进行修改后再编译。
6.编译工程u1,如果出错,进行修改后再编译。
7.将u1下载并运行,在PC机上观察超级终端程序主窗口,可以看到如下界面:
任务Task1和Task2将被轮流调用。
Task1:
iwillSuspendbymyself.
Task2:
iamexecuting.
Task1:
iResumedbyTask2.
Task2:
iResumedTask1
Task1:
iwillSuspendbymyself.
Task2:
iamexecuting.
Task1:
iResumedbyTask2.
Task2:
iResumedTask1
Task1:
iwillSuspendbymyself.
Task2:
iamexecuting.
Task1:
iResumedbyTask2.
Task2:
iResumedTask1
Task1:
iwillSuspendbymyself.
Task2:
iamexecuting.
Task1:
iResumedbyTask2.
Task2:
iResumedTask1
......
8.理解参考程序,包括任务函数定义、任务建立、任务的优先级,任务的挂起和恢复、信号量的定义和赋初值等。
9.参考源代码,重新建立三个任务,每个任务控制一个led灯的亮和灭,使三个任务轮流调用,实现3个led灯的轮流亮灭。
(利用任务控制函数,例如:
OSTaskSuspend(),OSTaskResume(),来完成任务的轮流调用。
)
七、参考程序
#include"includes.h"/*uC/OSinterface*/
#include"option.h"
#include"2410lib.h"
#include"uhal.h"
/*任务栈*/
OS_STKStack1[STACKSIZE]={0,};//任务1任务栈
OS_STKStack2[STACKSIZE]={0,};//任务2任务栈
/*任务ID*/
charId1='1';//任务1ID
charId2='2';//任务2ID
/*任务处理函数*/
voidTask1(void*Id);//任务1任务处理函数
voidTask2(void*Id);//任务2任务处理函数
/*信号量*/
OS_EVENT*sem1;//信号量Sem1
/*
*Main函数.
*1、初始化目标系统,初始化硬件定时器等,与操作系统无关
*2、调用OSInit初始化uC/OS-II软件数据结构等,必须在打开时钟节拍中断之前调用
*3、创建一个信号量,Sem
*4、创建两个任务Task1和Task2,Task1的优先级为5,Task2的优先级为13,Task1的优先级高于Task2
*5、调用OSStart启动uC/OS-II
*/
voidMain(void)
{
/*
*目标系统初始化
*/
ARMTargetInit();
/*
*uC/OS-II软件初始化
*/
OSInit();
/*
*创建信号量sem1,sem1的初始值为1
*/
sem1=OSSemCreate
(1);
/*
*创建两个任务,Task1和Task2,Task1的优先级为5,Task2的优先级为13,Task1的优先级高于Task2
*/
OSTaskCreate(Task1,(void*)&Id1,(OS_STK*)&Stack1[STACKSIZE-1],5);
OSTaskCreate(Task2,(void*)&Id2,(OS_STK*)&Stack2[STACKSIZE-1],13)