DSP课程设计报告计算机1073班邵占用.docx
- 文档编号:7183337
- 上传时间:2023-01-21
- 格式:DOCX
- 页数:15
- 大小:76.19KB
DSP课程设计报告计算机1073班邵占用.docx
《DSP课程设计报告计算机1073班邵占用.docx》由会员分享,可在线阅读,更多相关《DSP课程设计报告计算机1073班邵占用.docx(15页珍藏版)》请在冰豆网上搜索。
DSP课程设计报告计算机1073班邵占用
淮阴工学院
《DSP技术及应用》课程设计报告
选题名称:
UC/OS-II操作系统移植设计
系(院):
计算机工程学院
专业:
计算机科学与技术(嵌入式系统软件设计)
班级:
计算机1073班
姓名:
邵占用学号:
1071306120
指导教师:
马岱,常波
学年学期:
2009~2010学年第2学期
2010年6月12日
摘要:
uC/OSII(MicroControlOperationSystemTwo)是一个可以基于ROM运行的、可裁减的、抢占式实时多任务内核,具有高度可移植性,特别适合于微处理器和控制器,是和很多商业操作系统性能相当的实时操作系统(RTOS)。
为了提供最好的移植性能,uC/OSII最大程度上使用C语言进行开发,并且已经移植到近40多种处理器体系上,涵盖了从8位到64位各种CPU(包括DSP)。
是大多数高可靠嵌入式设备的首选。
uC/OSII可以简单的视为一个多任务调度器,在这个任务调度器之上完善并添加了和多任务操作系统相关的系统服务,如信号量、邮箱等。
其主要特点有公开源代码,代码结构清晰、明了,注释详尽,组织有条理,可移植性好,可裁剪,可固化。
内核属于抢占式,最多可以管理60个任务。
本文是将简单的操作系统uC/OSII移植到DSP处理器上,进行多任务,任务间通信和任务间同步等设计操作。
关键字:
uC/OSII;移植性;实时操作系统;任务调度器;抢占式;DSP
目录
1课程设计综述1
1.1课程设计概述1
1.2课程设计目的1
2课程设计基础知识1
2.1DSP简介1
2.2UC/OS-II简介2
2.3μC/OS-II移植模块分类4
3我的设计模块4
3.1四个汇编语言函数简介4
3.2OSStartHighRdy()函数5
3.3OSCtxSw()函数6
3.4OSIntCtxSw()函数8
3.5OSTickISR()函数11
4程序调试结果和分析13
总结14
参考文献15
1课程设计综述
1.1课程设计概述
UC/OS-II是一种源码公开的占先式实时多任务操作系统,除了与硬件相关的内容由汇编写成外其余都是由ANSIC写成,移植非常方便。
并且它是许多人学习RTOS的教程,是大多数高可靠嵌入式设备的首选。
我们的课学程设计也是学习如何正确的移植UC/OS-II。
1.2课程设计目的
a)了解嵌入式操作系统的一些基本概念;
b)学习uC/OS-II在DSP处理器上的移植过程。
c)了解DSP系统开发的基本思路及方法及C54汇编语言指令集。
d)学会撰写课程设计报告,学会对所学知识进行分析与总结。
2课程设计基础知识
2.1DSP简介
DSP芯片,也称数字信号处理器(DigitalSignalProcess,也简称DSP,后面大部分缩写均属此含义),是一种特别适合于进行数字信号处理的微处理器,它强调运算处理的实时性,因此DSP芯片除了具备普通微处理器所强调的高速运算和控制功能外,针对实时数字信号处理,在处理器结构、指令系统、数据流程上做了大的改动,其特点如下:
(a)DSP芯片普遍采用了数据总线和程序总线分离的哈佛结构及改进的哈佛结构,比传统处理器的冯・诺依曼结构有更高的指令执行速度。
(b)DSP芯片大多采用流水技术,即每条指令都有片内多个功能单元分别完成取指、译码、取数、执行等多个步骤,从而在不提高时钟频率的条件下减少了每条指令的执行时间。
(c)片内有多条总线可以同时进行取指令和多个数据存取操作,并且有辅助寄存器用于寻址,它们可以在寻址访问前或访问后自动修改内容,以指向下一个要访问的地址。
(d)DSP芯片大多带有DMA通道控制器以及串行通信口等,配合片内总线结构,数据块传送速度大大提高。
(e)配有中断处理器和定时控制器,可以方便地构成一个小规模系统。
(f)具有软、硬件等待功能,能与各种存取速度的存储器接口。
(g)针对滤波、相关、矩阵运算等需要大量乘法累加运算的特点,DSP芯片大都配有独立的乘法器和加法器,使得同一时钟周期内可以完成乘、累加两个运算。
(h)低功耗,一般为0.5∼4W,采用低功耗技术的DSP芯片只有0.1W,可用电池供电。
正是DSP芯片的以上特点决定了其运算速度比通用微处理器(MPU)要高,面对DSP的巨大市场和广阔发展前景,世界上几个大的半导体公司都在DSP上开展竞争,如AD、AT&T、Motorola、NEC、TI等公司都在全力开发和生产DSP芯片。
2.2UC/OS-II简介
UC/OS-II是一种免费公开源代码、结构小巧、具有可剥夺实时内核的实时操作系统。
uC/OS-II目标是实现一个基于优先级调度的抢占式的实时内核,并在这个内核之上提供最基本的系统服务,如信号量,邮箱,消息队列,内存管理,中断管理等
μC/OS-II可以大致分成核心部分、任务处理、时间处理、任务同步与通信,CPU的移植等5个部分,详见下图2-1:
图2-1µC/OS-II硬件和软件体系结构图
a)核心部分(OSCore.c)
是操作系统的处理核心,包括操作系统初始化、操作系统运行、中断进出的前导、时钟节拍、任务调度、事件处理等多部分。
能够维持系统基本工作的部分都在这里。
b)任务处理部分(OSTask.c)
任务处理部分中的内容都是与任务的操作密切相关的。
包括任务的建立、删除、挂起、恢复等等。
因为μC/OS-II是以任务为基本单位调度的,所以这部分内容也相当重要。
c)时钟部分(OSTime.c)
μC/OS-II中的最小时钟单位是timetick(时钟节拍)。
任务延时等操作是在这里完成的。
d)任务同步和通信部分
为事件处理部分,包括信号量、邮箱、邮箱队列、事件标志等部分;主要用于任务间的互相联系和对临界资源的访问。
e)与CPU的接口部分
是指μC/OS-II针对所使用的CPU的移植部分。
由于μC/OS-II是一个通用性的操作系统,所以对于关键问题上的实现,还是需要根据具体CPU的具体内容和要求作相应的移植。
这部分内容由于牵涉到SP等系统指针,所以通常用汇编语言编写。
主要包括中断级任务切换的底层实现、任务级任务切换的底层实现、时钟节拍的产生和处理、中断的相关处理部分等内容。
2.3μC/OS-II移植模块分类
从我们理解的处理器和C语言编译器的技术细节,移植µC/OS-Ⅱ的工作实际上是非常简单的。
移植工作包括以下几个内容:
用#define设置一个常量的值(OS_CPU.H)
声明10个数据类型(OS_CPU.H)
用#define声明三个宏(OS_CPU.H)
用C语言编写六个简单的函数(OS_CPU_C.C)
编写四个汇编语言函数(OS_CPU_A.ASM)
根据处理器的不同,一个移植实例可能需要编写或改写50至300行的代码,需要的时间从几个小时到一星期不等。
将uC/OS-II移植到DSP处理器上,需要完成的工作非常简单,修改三个和体系结构相关的文件即可,这三个文件是OS_CPU_C.c、OS_CPU_C.H以及OS_CPU_A.S。
我们这课程设计是由两个人做的,前面的定义头文件,定义数据类型,三个宏定义和用C语言编写的六个简单函数等前期工作是由我的合作伙伴冯绍诚来完成的。
而我这做其中最核心的部分四个汇编语言函数(OS_CPU_A.ASM)的编写和调试工作。
3我的设计模块
3.1四个汇编语言函数简介
C/OS-Ⅱ的移植实例要求用户编写四个简单的汇编语言函数(OS_CPU_A.ASM):
OSStartHighRdy()OSCtxSw()
OSIntCtxSw()OSTickISR()
如果用户的编译器支持插入汇编语言代码的话,用户就可以将所有与处理器相关的代码放到OS_CPU_C.C文件中,而不必再拥有一些分散的汇编语言文件。
3.2OSStartHighRdy()函数
使就绪状态的任务开始运行的函数叫做OSStart()。
在用户调用OSStart()之前,用户必须至少已经建立了自己的一个任务。
OSStartHighRdy()假设OSTCBHighRdy指向的是优先级最高的任务的任务控制块。
在µC/OS-Ⅱ中处于就绪状态的任务的堆栈结构看起来就像刚发生过中断并将所有的寄存器保存到堆栈中的情形一样。
要想运行最高优先级任务,用户所要做的是将所有处理器寄存器按顺序从任务堆栈中恢复出来,并且执行中断的返回。
为了简单一点,堆栈指针总是储存在任务控制块(即它的OS_TCB)的开头。
换句话说,也就是要想恢复的任务堆栈指针总是储存在OS_TCB的0偏址内存单元中。
voidOSStartHighRdy(void)
{
CalluserdefinableOSTaskSwHook();
Getthestackpointerofthetasktoresume:
Stackpointer=OSTCBHighRdy->OSTCBStkPtr;
OSRunning=TRUE;
Restoreallprocessorregistersfromthenewtask'sstack;
Executeareturnfrominterruptinstruction;
}
注意,OSStartHighRdy()必须调用OSTaskSwHook(),因为用户正在进行任务切换的部
分工作——用户在恢复最高优先级任务的寄存器。
而OSTaskSwHook()可以通过检查
OSRunning来知道是OSStartHighRdy()在调用它(OSRunning为FALSE)还是正常的任务切,换在调用它(OSRunning为TRUE)。
OSStartHighRdy()还必须在最高优先级任务恢复之前和调用OSTaskSwHook()之后设置OSRunning为TRUE。
其相关汇编程序代码如下:
_OSStartHighRdy:
CALL#_OSTaskSwHook;call_OSTaskSwHook
ST#1,*(_OSRunning);setOSRunningtry
LD*(_OSTCBHighRdy),A;OSTCBHighRdypointstotheTCBreadytorun
NOP;
NOP;
STLMA,AR0;AR0hastheTCBaddress
NOP;
NOP;
LD*AR0(0),A;*AR0hasthesp
NOP;
NOP;
STLMA,SP;loadthespfornewtask
NOP;needsomenopsforSPtotruelychanged
NOP;
CONTEXT_RESTORE;newtaskcontextisrestoredhere,noAhas*pdata,sppointto*task
NOP;
NOP;
RETE;runtask
3.3OSCtxSw()函数
任务级的切换问题是通过发软中断命令或依靠处理器执行陷阱指令来完成的。
中断服务例程,陷阱或异常处理例程的向量地址必须指向OSCtxSw()。
如果当前任务调用µC/OS-Ⅱ提供的系统服务,并使得更高优先级任务处于就绪状态,µC/OS-Ⅱ就会借助上面提到的向量地址找到OSCtxSw()。
在系统服务调用的最后,µC/OS-Ⅱ会调用OSSched(),并由此来推断当前任务不再是要运行的最重要的任务了。
OSSched()先将最高优先级任务的地址装载到OSTCBHighRdy中,再通过调用OS_TASK_SW()来执行软中断或陷阱指令。
注意,变量OSTCBCur早就包含了指向当前任务的任务控制块(OS_TCB)的指针。
软中断(或陷阱)指令会强制一些处理器寄存器(比如返回地址和处理器状态字)到当前任务的堆栈中,并使处理器执行OSCtxSw()。
OSCtxSw()的原型如程序清单所示。
这些代码必须写在汇编语言中,因为用户不能直接从C中访问CPU寄存器。
注意在OSCtxSw()和用户定义的函数OSTaskSwHook()的执行过程中,中断是禁止的。
voidOSCtxSw(void)
{
保存处理器寄存器;
将当前任务的堆栈指针保存到当前任务的OS_TCB中:
OSTCBCur->OSTCBStkPtr=Stackpointer;
调用用户定义的OSTaskSwHook();
OSTCBCur=OSTCBHighRdy;
OSPrioCur=OSPrioHighRdy;
得到需要恢复的任务的堆栈指针:
Stackpointer=OSTCBHighRdy->OSTCBStkPtr;
将所有处理器寄存器从新任务的堆栈中恢复出来;
执行中断返回指令;
}
其相关汇编程序代码如下:
_OSCtxSw:
CONTEXT_SAVE;saveallregistersonthecurrentstack
NOP;
NOP;
LDMSP,B;
LD*(_OSTCBCur),A;
NOP;
NOP;
STLMA,AR0;storethecurrsptoitstcb
NOP;
NOP;
STLB,*AR0(0);
NOP;
NOP;
CALL#_OSTaskSwHook;
;OSTCBCur=OSTCBHighRdy
;OSPrioCur=OSPrioHighRdy
LD*(_OSTCBHighRdy),A;
LD*(_OSPrioHighRdy),B;
NOP;
STLA,*(_OSTCBCur);
STLB,*(_OSPrioCur);;restoringthenewtask
STLMA,AR0;
NOP;
NOP;
LD*AR0(0),A;
NOP;
NOP;
STLMA,SP;loadthespfornewtask
NOP;needsomenopsforSPtotruelychanged
NOP;
CONTEXT_RESTORE;newtaskcontextisrestoredhere
NOP;
NOP;
RETE;
3.4OSIntCtxSw()函数
OSIntExit()通过调用OSIntCtxSw()来从ISR中执行切换功能。
因为OSIntCtxSw()是在ISR中被调用的,所以可以断定所有的处理器寄存器都被正确地保存到了被中断的任务的堆栈之中。
实际上除了我们需要的东西外,堆栈结构中还有其它的一些东西。
OSIntCtxSw()必须要清理堆栈,这样被中断的任务的堆栈结构内容才能满足我们的需要。
要想了解OSIntCtxSw(),用户可以看看µC/OS-Ⅱ调用该函数的过程。
用户可以参看图3-1来帮助理解下面的描述。
假定中断不能嵌套(即ISR不会被中断),中断是允许的,并且处理器正在执行任务级的代码。
当中断来临的时候,处理器会结束当前的指令,识别中断并且初始化中断处理过程,包括将处理器的状态寄存器和返回被中断的任务的地址保存到堆栈中[F8.2
(1)]。
至于究竟哪些寄存器保存到了堆栈上,以及保存的顺序是怎样的,并不重要。
图3-1在ISR执行过程中的堆栈内容图
接着,CPU会调用正确的ISR。
µC/OS-Ⅱ要求用户的ISR在开始时要保存剩下的处理器寄存器。
一旦寄存器保存好了,µC/OS-Ⅱ就要求用户或者调用OSIntEnter(),或者将变量OSIntNesting加1。
在这个时候,被中断任务的堆栈中只包含了被中断任务的寄存器内容。
现在,ISR可以执行中断服务了。
并且如果ISR发消息给任务(通过调用OSMboxPost()或OSQPost()),恢复任务(通过调用OSTaskResume()),或者调用OSTimeTick()或OSTimeDlyResume()的话,有可能使更高优先级的任务处于就绪状态。
OSIntCtxSw()的原型如程序清单下所示。
这些代码必须写在汇编语言中,因为用户不能直接从C语言中访问CPU寄存器。
如果用户的编译器支持插入汇编语言代码的话,用户就可以将OSIntCtxSw()代码放到OS_CPU_C.C文件中,而不放到OS_CPU_A.ASM文件中。
正如用户所看到的那样,除了第一行以外,OSIntCtxSw()的代码与OSCtxSw()是一样的。
这样在移植实例中,用户可以通过“跳转”到OSCtxSw()中来减少OSIntCtxSw()代码量。
voidOSIntCtxSw(void)
{
调整堆栈指针来去掉在调用:
OSIntExit(),
OSIntCtxSw()过程中压入堆栈的多余内容;
将当前任务堆栈指针保存到当前任务的OS_TCB中:
OSTCBCur->OSTCBStkPtr=堆栈指针;
调用用户定义的OSTaskSwHook();
OSTCBCur=OSTCBHighRdy;
OSPrioCur=OSPrioHighRdy;
得到需要恢复的任务的堆栈指针:
堆栈指针=OSTCBHighRdy->OSTCBStkPtr;
将所有处理器寄存器从新任务的堆栈中恢复出来;
执行中断返回指令;
}
其相关汇编程序代码如下:
_OSIntCtxSw:
FRAME4;adjustthesp,popupthereturnaddressofOSIntExit'scallerandOSIntCtxSw'scallerandtheevenword
POPMSP;restoretheoldSP(beforeeven/oddadjust)
NOP;
PSHMIMR;IMRisnotsavedbyCcompiler,addittothestack
NOP;
LDMSP,B;savesptoB
LD*(_OSTCBCur),A;
STLMA,AR0;storethecurrsptoitstcb
NOP;
NOP;
STLB,*AR0(0);
NOP;
NOP;
;calluser-definedOSTaskSwHook();
CALL#_OSTaskSwHook;
LD*(_OSTCBHighRdy),A;
LD*(_OSPrioHighRdy),B;
NOP;
STLA,*(_OSTCBCur);
STLB,*(_OSPrioCur);
;restoringthenewtask
NOP;
NOP;
STLMA,AR0;
NOP;
NOP;
LD*AR0(0),A;
NOP;
NOP;
STLMA,SP;loadthespfornewtask
NOP;needsomenopsforSPtotruelychanged
NOP;
CONTEXT_RESTORE;newtaskcontextisrestoredhere
NOP;
NOP;
RETE;
3.5OSTickISR()函数
µC/OS-Ⅱ要求用户提供一个时钟资源来实现时间的延时和期满功能。
时钟节拍应该每秒钟发生10-100次。
为了完成该任务,可以使用硬件时钟。
用户必须在开始多任务调度后(即调用OSStart()后)允许时钟节拍中断。
换句话说,就是用户应该在OSStart()运行后,µC/OS-Ⅱ启动运行的第一个任务中初始化节拍中断。
通常所犯的错误是在调用OSInit()和OSStart()之间允许时钟节拍中断。
时钟节拍ISR的原型如程序清单如下所示。
这些代码必须写在汇编语言中,因为用户不能直接从C语言中访问CPU寄存器。
如果用户的处理器可以通过单条指令来增加OSIntNesting,那么用户就没必要调用OSIntEnter()了。
增加OSIntNesting要比通过函数调用和返回快得多。
OSIntEnter()只增加OSIntNesting,并且作为临界段代码中受到保护。
voidOSTickISR(void)
{
保存处理器寄存器;
调用OSIntEnter()或者直接将OSIntNesting加1;
调用OSTimeTick();
调用OSIntExit();
恢复处理器寄存器;
执行中断返回指令;
}
其相关汇编程序代码如下:
_OSTaskStkInit:
LDMSP,B;tempsaveSPtoBL
STLMA,T;tempsave*tasktoT
LD*SP
(1),A;Ahas*pdatanow
NOP;
NOP;
SFTLA,8,A;tempsave*pdatatoBH
ADDA,8,B;
LD*SP
(2),A;Ahas*task_stack_top
NOP;
NOP;
STLMA,SP;changeSPtothetaskstack
LDMT,A;
NOP;
NOP;
PSHMAL;taskstartaddress
SFTLB,-16,A;Ahasthe*pdata
NOP;
NOP;
CONTEXT_SAVE;
LDMSP,A;thetopofthestack
STLMB,SP;restoretheSP
NOP;
NOP;
NOP;needsomenoopssoSPistrulyrestoredbeforeRET
RET;
4程序调试结果和分析
完成上述文件的修改和编写之后。
就可在CSS环境中对所有的源文件进行编译和连接,生成处理器中可执行的.out文件,通过仿真器直接连接到DSP的设计箱运行。
由于CCS提供了强大的调试功能,用户能够很清楚地了解μC/OS--II在处理器内的运行情况,可见数码管上数据按顺序的有效的移位操作,发光二极管也顺序的轮闪。
这设计结果也表明了我们设计是成功的。
这无疑也源于μC/OS-
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- DSP 课程设计 报告 计算机 1073 占用