嵌入式系统设计课程报告UCOS移植.docx
- 文档编号:24956682
- 上传时间:2023-06-03
- 格式:DOCX
- 页数:34
- 大小:118.40KB
嵌入式系统设计课程报告UCOS移植.docx
《嵌入式系统设计课程报告UCOS移植.docx》由会员分享,可在线阅读,更多相关《嵌入式系统设计课程报告UCOS移植.docx(34页珍藏版)》请在冰豆网上搜索。
嵌入式系统设计课程报告UCOS移植
《嵌入式系统设计》课程报告
题目:
μC/OS-II在ES44B0实验平台上的的移植
姓名:
郭卫平
学号:
0905030314
所在院(系):
计算机科学与工程学院
专业班级:
信息安全专业2009级班
开课学期:
2012-2013-1学期
任课教师:
胡勇华
1.课题名称及其描述
μC/OS-II在ES44B0实验平台上的的移植
2.分析和总体设计
要使μC/OS-II正常运行,处理器必须满足以下要求:
●处理器的C编译器能产生可重入型代码;
●处理器支持中断,并且能产生定时中断(通常为10~100Hz);
●用C语言开/关中断;
●处理器能支持一定数量的数据存储硬件堆栈;
●处理器有将堆栈指针以及其它CPU寄存器的内容读出、并存储到堆栈或内存中去的指令。
SDT和ADS均能产生可重入代码;s3c44b0处理器支持中断,并有6个定时器,其中5个还具有PWM功能,全部可配置为基于中断;SDT和ADS均支持C语言内嵌汇编,可方便实现中断开/关;足够数量的硬件堆栈,并且THUMB状态下有push、pop,ARM状态下有LDM、STM指令用于保存和恢复现场。
综上可知,μC/OS-II完全可以移植到s3c44b0上。
S3C44B0处理器核具有SVC、USR、ABT、UND、IRQ、FIQ、SYS七种模式,其中除用户模式外其它均为特权模式。
其中管理、中止、未定义、中断和快中断模式与相应异常相联系,任务使用这些模式不太适合。
系统模式除了是特权模式外,其它与用户模式一样,因而可选为任务使用的模式只有用户模式和系统模式。
为了尽量减少任务代码错误对整个程序的影响,缺省的任务模式定为用户模式,可选为系统模式,同时提供接口使任务可以在这两种模式间切换。
另外,为了保护操作系统,还需要使用SVC模式。
SWI做为操作系统底层调用的接口。
这使底层接口函数与处理器状态无关,同时在任务调用相应的函数不需要知道函数位置,使用不同的功能号区分不同的函数。
S3c44b0处理器是ARM7TDMI内核,带T变量,具有两个指令集:
标准32位ARM指令集和16位Thumb指令集,两种指令集有不同的应用范围。
为了最大限度地支持芯片特性,任务应当可以使用任意一个指令集并可以自由切换,而且不同的任务应当可以使用不同的指令集。
3.详细设计与实现
μC/OS-II硬件软件体系结构
μC/OS-II处理器相关代码编写
Os_cpu.h的编写
Os_cpu.h中除了定义与编译器无关的数据类型、以及与处理器相关的μC/OS-II函数声明、常量和宏。
OS_STK是堆栈类型,实际上是整数类型,在后面用来定义堆栈和堆栈指针。
由于堆栈是32位的,所以把OS_STK定义为unsignedint类型,即四个字节。
μC/OS-II使用结构常量OS_STK_GROWTH中指定堆栈的生长方式:
置OS_STK_GROWTH为0表示堆栈从下往上长;置OS_STK_GROWTH为1表示堆栈从上(高地址)往下(低地址)长。
虽然ARM处理器核同时支持两种方式,但ADS的C语言编译器仅支持从上往下长,所以必须让OS_STK_GROWTH的值为1。
用定义(#define)常数OS_CRITICAL_METHOD可以选择具体使用哪种开关中断方法。
当OS_CRITICAL_METHOD==1时,如果调用μC/OS-II功能函数时,中断是关掉的,则从μC/OS-II函数返回时,中断就打开了。
若调用μC/OS-II功能函数之前已将中断关掉,那么用户往往希望从C/OS-II函数返回时,中断仍然是关着的。
这时,这种方法就不妥当。
但对于有些处理器,这可能是唯一选择。
第二种方法是在堆栈中保存中断的开/关状态,然后再关中断。
第三种方法是把当前处理器的状态字(PSW)保存在C函数的局部变量中(如OS_CPU_SR)。
关中断时保存,开中断时恢复。
在本移植方案中,我们选择第二种方法。
当然对于第三开关中断的方法,ARM处理器也是支持的。
Os_cpu_c.c的编写
μC/OS-II源代码中已经给出os_cpu_c.c模板。
首先,要修改其中的OSTaskStkInit()函数即可。
该函数对任务堆栈进行初始化。
堆栈内容从栈底到栈顶依次为PC(R14)、LR(R13)、R12~R0、OsEnterSum。
其中,OsEnterSum用于保存该任务关中断的次数,它在调用OS_ENTER_CRITICAL()时加1,在调用OS_EXIT_CRITICAL()时减1。
这样每个任务都可以独立控制本任务的中断允许状态,而不会影响其它任务的中断允许状态。
因此关中断和开中断就可以嵌套。
其次,如果必要,填充钩子函数。
模板文件中共有8个带“HOOK”字符串的函数,称为钩子函数。
这些函数都有对应的缺省“HOOK"的μC/OS-II调用与之对应。
所谓必要是指有些用户可能希望扩展这些μC/OS-II调用的功能。
如果简单地修改这些调用无疑会破坏μC/OS-II系统源代码,而通过HOOK函数既能保护系统源代码又使代码更加简洁。
当然,要把HOOK函数编译进目标代码中,还应该在OS_CFG.H中打开OS_CPU_HOOKS_EN宏。
最后,对于本移植方案,还在本文件中添加了三个函数。
OSStartHighRdy():
最终将调用os_cpu_s.s中的__OSStartHighRdy函数;_TaskIsARM():
将处理器切换到ARM状态,准备执行ARM指令任务;_TaskIsTHUMB()将处理器切换到THUMB状态,准备执行THUMB指令任务。
Os_cpu_s.s的编写
定义软件中断汇编接口函数SoftwareInterrupt和软件中断服务程序。
软件中断服务程序有多个,当被SoftwareInterrupt调用时通过软件中断号区分。
中断号的区分如下:
软件中断服务程序及其它相关函数的实现见附录。
μC/OS-II系统配置
主要是修改OS_CFG.H文件。
通过这个文件,可以实现对μC/OS-II进行裁减和相关优化。
这里使用默认设置(调试时将会修改这个文件,禁止统计功能以方便调试)。
关于INCLUDES.H
μC/OS-II要求所有.C文件的都要包含头文件includes.h,这样使得用户项目中的每个.C文件不用分别去考虑它实际上需要哪些头文件。
代价是它可能会包含一些实际不相关的头文件,这意味着每个文件的编译时间可能会增加。
另外,考虑到手动地在每个.C文件中包含需要的头文件有助于熟悉μC/OS-II移植工程的代码结构和调用关系,所以,移植中决定不使用包含includes.h的方式。
启动代码修改
将软件中断异常时,PC指到0x08处执行。
在该处安排跳转指令,以跳到SoftwareInterrupt执行。
代码详见附录。
定时器初始化
μC/OS-II要求定时中断频率为10~100Hz,通过查看s3c44b0手册:
OneTickTime=(prescalervalue+1)*(dividervalue)*(rTCNTB0-rTCMPB0)
÷MCLK。
本移植方案使用Timer0做为系统时钟,设置预分频值为0x16,置分频值为2,MCLK设为48MHz,所以得到OneTickTime26Hz。
代码见附录。
4.运行与测试
测试ADS(编译器、汇编器、及链接器)是否正常工作
由于移植时恰好将汇编文件后辍名命名为.s,这正好是ADS支持的后辍名,不用做修改。
去除掉一些语法误后,ADS没有报错,几本确定ADS能正常工作。
处理器相关函数验证
验证OSTaskStkInit()和OSStartHighRdy()函数
编写一个测试文件test.c,用于测试。
代码见附录。
其次,为了方便测试,禁止统计任务。
修改OS_CFG.H文件,设置OS_TASK_STAT_EN为0。
只让空闲任务工作,并单步执行,直到uC/OS-II切换到OS_TaskIdle()。
单步时跳过OSInit()函数,单步进入OSStart()函数。
一直单步运行到调用OSStartHighRdy(),然后单步进入OSStartHighRdy(),接着高调用__OSStartHighRdy()。
最后切换到汇编语言模式下,因为__OSStartHighRdy()是用汇编语句实现的。
__OSStartRdy()会开始运行第1个任务;而此时并没有任何应用任务.只有OS_TaskIdle()可以运行。
调试器在OS_TaskIdle()循环中运行,且在无限循环中执行数次次,并没有出现任务问题,说明OSTaskStkInit()和OSStartHighRdy()函数是成功的。
验证OSCtxSw()函数
在test.c中增加如下语句
#defineMainTaskPrio5//定义优先级为5
OS_STKMainTaskStk[MainTaskStkLengh];
voidMainTask(void*pdata)//MainTaskcreatetaks0andtask1
{
while
(1)
{
//OSTimeDly
(1);
}
}
然后在Main()中,OSInit()和OSStart()之间增加下语句
OSTaskCreate(MainTask,(void*)0,&MainTaskStk[MainTaskStkLengh-1],MainTaskPrio);
这样就在μC/OS-II添加了一个应用任务。
单步执行,直到__OSStartRdy()开始运行第1个任务,由于MainTask比空闲任务优先级高,所以应该先被执行。
然后一直执行while死循环。
结果在预期之内。
至此OSCtxSw()验证通过。
验证OSIntCtxSw()和OSTickISR()函数
这两个函数的调试都需要涉及到中断,需要硬件调试工具的支持,由于缺少必要的JTAG调试工具没有进行验证。
最后进行了增加应用程序后的的测试,测试结果如下图:
5.附录:
主要源代码
test.c
#include"bspinit.h"
#include
voidMain(void)
{
//板级初始化
Bsp_Init();
//初始化uC/OS
OSInit();
OSStart();
}
Os_cpu.h
#ifdefOS_CPU_GLOBALS
#defineOS_CPU_EXT
#else
#defineOS_CPU_EXTextern
#endif
/****************************************************************
*定义与编译器无关的数据类型
****************************************************************/
typedefunsignedcharBOOLEAN;/*布尔变量*/
typedefunsignedcharINT8U;/*无符号8位整型变量*/
typedefsignedcharINT8S;/*有符号8位整型变量*/
typedefunsignedshortINT16U;/*无符号16位整型变量*/
typedefsignedshortINT16S;/*有符号16位整型变量*/
typedefunsignedintINT32U;/*无符号32位整型变量*/
typedefsignedintINT32S;/*有符号32位整型变量*/
typedeffloatFP32;/*单精度浮点数(32位长度)*/
typedefdoubleFP64;/*双精度浮点数(64位长度)*/
typedefINT32UOS_STK;/*堆栈是32位宽度*/
/*以下是兼容UC/OSV1.XX的数据类型,在uC/OS-II没有使用*/
#defineBYTEINT8S
#defineUBYTEINT8U
#defineWORDINT16S
#defineUWORDINT16U
#defineLONGINT32S
#defineULONGINT32U
/****************************************************************
*与S3C44B0体系结构相关的一些定义
****************************************************************/
#defineOS_CRITICAL_METHOD2/*选择开、关中断的方式*/
__swi(0x00)voidOsSwiHandle1(intHandle);
__swi(0x01)void*OsSwiHandle2(intHandle,intIndex);
#defineOS_TASK_SW()OsSwiHandle1(0)/*任务级任务切换函数*/
#define_OSStartHighRdy()OsSwiHandle1(6)/*运行优先级最高的任务*/
#defineOS_ENTER_CRITICAL()OsSwiHandle1
(1)/*关中断*/
#defineOS_EXIT_CRITICAL()OsSwiHandle1
(2)/*开中断*/
#defineGetOSFunctionAddr(Index)OsSwiHandle2(10,Index)/*获取系统服务函数入口*/
#defineGetUsrFunctionAddr(Index)OsSwiHandle2(11,Index)/*获取自定义服务函数入口*/
#defineOSISRBegin()OsSwiHandle1(3)/*中断开始处理*/
#defineOSISRNeedSwap()OsSwiHandle1(9)/*判断中断是否需要切换*/
#defineChangeToSYSMode()OsSwiHandle1(4)/*任务切换到系统模式*/
#defineChangeToUSRMode()OsSwiHandle1(5)/*任务切换到用户模式*/
#defineTaskIsARM(prio)OsSwiHandle2(7,prio)/*任务代码是ARM代码*/
#defineTaskIsTHUMB(prio)OsSwiHandle2(8,prio)/*任务代码是THUMB*/
#defineOS_STK_GROWTH1/*堆栈是从上往下长的*/
#defineUSR32Mode0x10/*用户模式*/
#defineSYS32Mode0x1f/*系统模式*/
#defineNoInt0x80
#ifndefUSER_USING_MODE
#defineUSER_USING_MODEUSR32Mode/*任务缺省模式*/
#endif
#ifndefOS_SELF_EN
#defineOS_SELF_EN0/*允许返回OS与任务分别编译、固化*/
#endif
OS_CPU_EXTINT32UOsEnterSum;/*关中断计数器(开关中断的信号量)*/
/****************************************************************
**EndOfFile
****************************************************************/
Os_cpu_c.c
/****************************************************************
**
**--------------------------------------文件信息--------------------------------------------
**文件名:
os_cpu_c.c
**描述:
μCOS-II在lpc210x上的移植代码C语言部分,包括任务堆栈初始化代码和钩子函数等
**用ads1.2编译,必须使用ARM方式编译
**
****************************************************************/
#defineOS_CPU_GLOBALS
#include"config.h"
#ifOS_SELF_EN==0
intconst_OSFunctionAddr[1]={0};
intconst_UsrFunctionAddr[1]={0};
#endif
/****************************************************************
**函数名称:
OSTaskStkInit
**功能描述:
任务堆栈初始化代码,本函数调用失败会使系统崩溃
**输 入:
task:
任务开始执行的地址
**pdata:
传递给任务的参数
**ptos:
任务的堆栈开始位置
**opt:
附加参数,当前版本对于本函数无用,具体意义参见OSTaskCreateExt()的opt参数
**输 出:
栈顶指针位置
**全局变量:
**调用模块:
**
****************************************************************/
OS_STK*OSTaskStkInit(void(*task)(void*pd),void*pdata,OS_STK*ptos,INT16Uopt)
{
OS_STK*stk;
opt=opt;/*'opt'没有使用。
作用是避免编译器警告*/
stk=ptos;/*获取堆栈指针*/
/*建立任务环境,ADS1.2使用满递减堆栈*/
*stk=(OS_STK)task;/*pc*/
*--stk=(OS_STK)task;/*lr*/
*--stk=0;/*r12*/
*--stk=0;/*r11*/
*--stk=0;/*r10*/
*--stk=0;/*r9*/
*--stk=0;/*r8*/
*--stk=0;/*r7*/
*--stk=0;/*r6*/
*--stk=0;/*r5*/
*--stk=0;/*r4*/
*--stk=0;/*r3*/
*--stk=0;/*r2*/
*--stk=0;/*r1*/
*--stk=(unsignedint)pdata;/*r0,第一个参数使用R0传递*/
*--stk=(USER_USING_MODE|0x00);/*spsr,允许IRQ,FIQ中断*/
*--stk=0;/*关中断计数器OsEnterSum;*/
return(stk);
}
/****************************************************************
**函数名称:
OSStartHighRdy
**功能描述:
uC/OS-II启动时使用OSStartHighRdy运行第一个任务,
**实质是产生swi1指令
**输 入:
无
**输 出:
无
**全局变量:
无
**调用模块:
无
**
**----------------------------------------------------------------------------------------------
****************************************************************/
voidOSStartHighRdy(void)
{
_OSStartHighRdy();
}
/****************************************************************
**函数名称:
_TaskIsARM
**功能描述:
任务代码是ARM代码
**
**输 入:
无
**输 出:
无
**全局变量:
无
**调用模块:
无
**
****************************************************************/
void_TaskIsARM(INT8Uprio)
{
OS_TCB*ptcb;
if(prio<=OS_LOWEST_PRIO)
{
ptcb=OSTCBPrioTbl[prio];
if(ptcb!
=NULL)
{
ptcb->OSTCBStkPtr[1]&=~(1<<5);
}
}
}
/****************************************************************
**函数名称:
_TaskIsARM
**功能描述:
任务是THUMB代码
**
**输 入:
无
**输 出:
无
**全局变量:
无
**调用模块:
无
**
****************************************************************/
void_TaskIsTHUMB(INT8Uprio)
{
OS_TCB*ptcb;
if(prio<=OS_LOWEST_PRIO)
{
ptcb=OSTCBPrioTbl[prio];
if(ptcb!
=NULL)
{
ptcb->OSTCBStkPtr[1]|=(1<<5);
}
}
}
/*以下为一些钩子函数,全部为空函数。
具体说明请看相关资料*/
#ifOS_CPU_HOOKS_EN
/****************************************************************
*OSINITIALIZATIONHOOK
*(BEGINNING)
*
*Description:
ThisfunctioniscalledbyOSInit()atthebeginningofOSInit().
*
*Arguments:
none
*
*Note(s):
1)Interruptsshouldbedisabledduringthiscall.
**************************
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 嵌入式 系统 设计 课程 报告 UCOS 移植
![提示](https://static.bdocx.com/images/bang_tan.gif)