DSP

TS101的嵌入式实时操作系统设计,嵌入式实时操作系统,中断处理,内存覆盖,TS101处理器

2019-07-13 17:00发布

基于TS101的嵌入式实时操作系统设计,嵌入式实时操作系统,中断处理,内存覆盖,TS101处理器 2007-05-31 10:46:10 来源: 作者: 【大 中 小】 浏览:296次 评论:0条 0 引言 随着半导体制造工艺的发展和计算机体系结构的改进,DSP处理芯片的处理能力越来越强大,控制的外围设备越来越多,软件算法也越来越复杂。对于DSP系统的软件开发,不仅要面对复杂的软件算法,同时还要把大部分精力放在各种外围设备和相关的硬件控制上,整个过程复杂而艰辛。因此,为这一类系统开发小巧精致、便于移植的嵌入式实时操作系统,具有实际的意义。本文参考开放源代码实时操作系统uC/OS-II,完成了基于ADI公司的ADSP-TigerSHARC101S(以下简称TS101)系列DSP芯片的嵌入式实时操作系统的设计和开发工作。 1 TS101芯片简介 TS101是美国ADI公司生产的一款高性能静态超标量处理器。ADSP-TS101S的内核指令周期为3.3ns,每周期能够执行4条指令、24个16-bit定点运算和6个浮点运算。内部有三条相互独立的128bit宽度的内部数据总线,每条总线各连接一个2MB内部存储器阵列,可提供4个字的数据、指令及I/O访问,以及14.4Gbytes/s的内部存储器带宽。 在ADSP-TS101内部的双运算模块中,每个均包含一个ALU、乘法器、64-bit移位器和32个字的寄存器组及相关的数据对齐缓冲器(DAB)。芯片中的双整数ALU(IALU)均有自己的31个字的寄存器组以用于数据寻址。此外,TS101中还带有一个带指令对齐缓冲器(IAB),以及分支目标缓冲器(BTB)和中断控制器的程序控制器,同时有三条相互独立的128bit宽度的内部数据总线以及片内6MB SRAM;TS101提供有与主机处理器、多处理器空间(DSP)、外部SRAM和SDRAM相连的外部端口和一个14通道DMA控制器、四个链路口、两个64bit问隔定时器和定时器计满引脚。芯片上一个与IEEE 1149.1兼容的JTAG接口可用于片上仿真。 2 基于TS101的嵌入式实时操作系统功能 本文介绍的基于TS101的嵌入式操作系统是参考源码公开的实时操作系统uC/OS-II来设计的,实际上,它和uC/OS-II一样,仅仅是一个实时内核,而不具有像GUI、TCP/IP协议栈等功能部件。它支持占先式多任务调度,并可提供有效的服务(如信号量、邮箱、队列、延时、超时等)。同时,在uC/OS-II基础上可引入高级操作系统中的进程和线程等概念。因此,本没计采用了进程与线程结合的方式,即将实现不同功能的任务视为进程,然后在任务内部进行细分,以划分为不同的线程。进程间的调度与切换在TS101内部存储区和外部扩展存储区(例如SDRAM)中进行,而线程间的调度与切换则在TS101内部存储区中实现。从本设计的整个TS101嵌入式实时系统来看,它的基本功能主要包括任务管理、中断管理、内存管理三方面内容。 在TS101嵌入式实时系统的三大块功能中,任务管理功能模块基本上是uC/OS-II的简单移植,本文主要针对中断处理和存储器管理两大部分进行设计说明。 3 TS101的中断处理 TS101的中断处理包括硬件中断和软件中断两大类,其中软件中断又包括软件异常中断和Debug中断。 3.1 硬件中断 TS101处理器不需要专门的堆栈指针来保存现场,器件中IALU的J、K寄存器都可以用作堆栈指针。在允许嵌套中断的中断服务程序中,可将中断返回地址(即RETIB)值保存到堆栈中,这样,在从RETIB读出返回地址后,系统将自动开启全局中断使能。但在保存相关的寄存器和RETI时本应禁止全局中断使能,所以这是在程序控制器将PC写入RETI时自动完成。如果系统不支持嵌套的硬件中断,则无需把处理器状态保存在堆栈中。中断一般根据寄存器RETI执行并在中断后返回,而不需要再对硬件中断的全局禁止位进行处理。 3.2 软件中断 (异常) 异常软件中断是在程序执行的过程中触发的。使能异常中断时,可将PMASK[62]置位,并将PC存储于RETS;而对于仿真异常,则将PMASK[63]置位,PC存储于DBUG中。当异常中断出现时,程序控制器将从寄存器IVSW指向的地址取址,仿真异常则从EMUIR寄存器取址,同时将指令流水的指令清空。 3.3 中断返回 中断返回是通过在中断服务程序中执行RTI指令来实现的。当然,这要求在响应中断服务程序时就将返回的地址保存在该寄存器中。通常要求至少在执行该指令前的8个指令周期就将返回地址放入在寄存器RETIB中,这样,分支缓冲BTB才能使用。 4 操作系统中断处理的实现 在本操作系统中,对于用户中断服务程序的处理过程,其示意代码和功能如表1所列。 事实上,用户应首先将处理器的寄存器压人当前堆栈[程序列表1中的(1)]。在进行中断处理时,操作系统需要知道用户在做中断服务,因此,用户应该调用OS_Int_Enter_C()将全局变量OSIntNesting[程序列表1中的(2)]直接加1。完成上述两步以后,用户就可以开始服务于引发中断的设备了[程序列表1中的(3)]。由于该操作系统允许中断嵌套,而且系统能跟踪嵌套层数OS-IntNesting。然而,为允许中断嵌套,在多数情况下,用户应在开中断之前先清中断源。调用脱离中断函数OS_Int_Exit_C()[程序列表1中的(4)]标志着中断服务子程序的终结,同时OSIntExit ()会将中断嵌套层数计数器减l。当嵌套计数器减到零时,所有中断,包括嵌套的中断便都完成了。此时操作系统要判定有没有优先级较高的任务被中断服务子程序(或任一嵌套的中断)唤醒。如果有高优先级的任务进入了就绪态,系统则返回到那个高优先级的任务,OS_Int_Exit_C()返回到调用点[程序列表1中的(5)]。保存的寄存器的值将在这时被恢复,然后在去执行中断返回指令[程序列表1中的(6)]。应当注意的是,如果调度被禁止(OSIntNesting>0),系统将返回到被中断的任务。 以上描述的详细解释如图1所示。图中,有时中断来到了[图1(1)],但还不能被处理器识别,这也许是因为中断被操作系统或用户应用程序关了,或者是因为处理器还没执行完当前的指令。一旦处理器响应了这个中断[图1(2)],处理器的中断向量将跳转到中断服务子程序[图1(3)]。中断服务子程序在处理器寄存器(也叫做CPU context)[图1(4)]中一旦保存完毕,用户中断服务子程序将通知操作系统进入中断服务子程序,办法是通过调用OS_Int_Enter_C()给OS-IntNesting加1[图1(5)]。然后用户中断服务代码开始执行[图1(6)]。应当注意的是,用户中断服务中做的事要尽可能地少,而把大部分工作留给任务去做。用户中断服务完成以后,要调用OS_Int_Exit_C()[图1(7)]。从时序图上可以看出,对被中断的任务来说,如果没有高优先级的任务被中断服务子程序激活而进入就绪态,OS_Int_Exit_C()只占用很短的运行时间。在这种情况下,CPU寄存器只是简单地恢复[图1(8)]并执行中断返回指令[图1(9)]。而如果中断服务子程序使一个高优先级的任务进入了就绪态,则OS_Int_Exit_C()将占用较长的运行时间,因为这时要进行任务切换[图1(10)]。新任务的寄存器内容要恢复并执行中断返回指令[图1(12)]。 5 存储器管理 在TS101的C环境下,可将内存划分为代码区(code)、数据区(data)、堆(heap)区和栈(stack)区。代码区用来存放用户代码,数据区用来存放全局变量和静态变量等数据,栈区用来存放临时变量等数据,堆区用来为用户提供动态内存分配。在编译器的链接描述文件(Linker DescriptonFile.LDF)中,可以手动划分各个内存分区的大小。在TS101所提供的库函数中已经包含了比较完备的内存管理函数(如常用的calloc,free,malloc和realloc等函数),可用于对内存进行基本管理。 在对操作系统进行设计的过程中,应将重心放在内存的扩展上,以便有效地使用外部存储器(例如SDRAM等)。为了实现内存扩展,本设计将一个大型任务看作一个进程,再将一个进程划分为不同的小线程。在系统的外部存储器中可以存放多个进程,而每次只将一个读人到内存中来运行。操作系统的主要管理对象是这个进程所划分的多个线程。这样,在一个系统中就可以运行多个进程,它们之间可以由程序进行由内存到外存或由外存到内存的切换控制,但在切换过程中需要花费一些时间代价。 5.1 外部存储器堆区的使用 TS101为用户提供了堆区,并提供有calloc、malloc、realloc和free等函数来对其进行管理和使用,同时用户可以通过手动修改链接描述文件以获得相对较大的堆区。然而,在默认情况下,用户所能使用的只是链接描述文件中所提供的那一块堆区,这对用户来说是远远不够的。如果用户在外部存储器上也能够像在内存中一样动态的开辟存储空间来进行使用,那将会带来极大的方便。幸运的是,TS101的编译系统提供了这一功能,用户只需要对系统提供的名为“ts_hdr.asm”的汇编文件和链接描述文件进行修改并编译“ts_hdr.asm”文件,再用生成的“ts_hdr.doj”文件代替链接描述文件中的“ts_hdr_TS101”即可。 以下将对文件的修改过程做简要的介绍。下面是TS101链接描述文件中对于默认堆区的描述,它定义了默认堆区的基址和堆区的大小: 在“ts_hdr.asm'’汇编文件中可对默认堆区进行操作,它的主要功能是为默认堆区规定ID号0,以便有新的堆区存在时方便使用。 ts_hdr.asm对默认堆栈进行编号的代码: · var=1df_defheap_base; · var=1df_defheap_size; · var=0; 对链接描述文件和汇编文件进行修改时,只需要在链接描述文件中对新的堆区进行描述并在汇编文件中对其进行编号即可。代码如下: 对新的堆栈区进行描述的代码可开辟于外部存储器之中(SDRAM)。并在新的堆栈中将其编号为1。按照以上步骤将文件修改完毕之后,用户就可以在外部存储区中动态地使用内存了。编译器还为动态内存的开辟提供了一系列的库函数。其具体程序还在内部存储器中的默认堆区动态开辟了大小为50的内存[6(1)],并在外部存储区中动态开辟了大小为256的内存[6(2)]。其程序如下: int*x,*y; x=heap_malloc (0,50); (1) y=heap_malloc (1,256); (2) 5.2 内存覆盖 通过TS101可将数量极大的程序代码放入外部存储器中。每次通过DMA传输方式读入少量的程序代码到内存来执行,这样既扩展了内存空间。又比将全部代码放入外部存储器节省时间,这种方式称为内存覆盖(overlay)。内存覆盖是一种多对一的内存映射技术,它可将多段代码存储在外部存储器划定的不同位置,但也可以在内存中的同一位置运行。代码在外部存储器的存储区称为“live”区,在内存中的运行区称为“run”区。 图2所示是overlay的使用结构图。由图可见,在外部存储器中,overlay1和overlay2可在内存中的同一区域中运行,而overlay3和overlay4也可以在内存的同一区域中运行。当主函数调用FUNC_B时,overlay2将被换入内存中运行,而当主函数调用FUNC_A时,再用overlay1置换over-lay2,overlay3和overlay4的使用与overlay1和over-lay2相同。代码在内存与外存之间的置换主要通过DMA传输来实现。 内存覆盖管理器是用户编写的用来将函数或数据载入内存的子程序,它们与链接器提供的PLIT{}指令配合使用可完成内存覆盖操作。内存覆盖管理器除了负责由外部存储器向内存的载入操作外,还应当负责建立堆栈保存寄存器的值,检查需要调用的函数是否已经在内存之中,以及利用DMA操作在其它函数执行时运行内存覆盖载入。 通过链接描述文件可对内存覆盖进行辅助操作。此操作需定义OVLY_one和OVLY_two两块overlay代码,其中OVLY_one包含函数FUNC_A.doj,而OVLY_two包含FUNC_B.doj和FUNC_C.doj,它们共同在MOCode的同一内存区域运行。在链接描述文件中对overlay进行操作的程序代码如下:                }>MOCode 在链接描述文件中,还可以通过定义PLIT{}指令来协助内存覆盖操作的完成。当主函数调用一个内存覆盖区的函数时,链接器将重新引导函数调用并进行操作。例如当主函数调用了内存覆盖函数FUNC_A时,链接器会将其自动转化为调用.plt_FUNC_A操作。此操作在函数执行之前先进行PLIT操作,并跳转到overlay管理器中执行,然后再执行函数A。下面是对PLIT进行操作的定义代码: 5.3 内存扩展的实现 操作系统提供了OS_Process_Sched()函数来完成这一操作,该函数中的进程切换函数顺序代码如下: (1) 将处于在内存中的进程的寄存器值压入堆栈; (2) 将处于内存中的进程的全部存储区内容由DMA方式放入外存: (3) 调用在外存中的进程的寄存器出栈函数; (4) 跳转到新的进程运行。 在进程调度中,一般首先将所有寄存器值压入当前进程堆栈中进行保存[顺序代码(1)],然后将内存进程存储区中的所有内容放入外部存储器中保存,以便当该进程重新进入内存运行时能够完全恢复原有运行环境[顺序代码(2)]。这里的所有内容是指与当前进程有关的数据,包括进程的堆栈、进程的全局变量、进程动态申请的内存块等等。调用外部存储器中的进程寄存器出栈函数[顺序代码(3)]主要是利用前面所述的内存覆盖技术来进行的,该寄存器的出栈函数一般放在外部存储器中,操作时可通过调用它使链接器跳转到内存覆盖管理器来完成外部存储器进程向内存的加载。但在这里要对内存覆盖管理器进行修改,并添加外部存储器中进程的全部数据的载入函数,然后,程序才能跳转到新的进程中开始运行[顺序代码(4)]。 6 结束语 本文在对嵌入式实时操作系统进行研究的基础上,完成了基于TS101DSP芯片的嵌入式实时操作系统的设计。所设计的系统体系结构主要参考的是开放源代码的实时操作系统uC/OS_II,并在此基础上,根据芯片本身的特点和实际应用的需要进行了创新和重设计,这主要体现在以下三方面: (1) 结合TS101芯片的特点,实现了中断处理部分的设计; (2) 放弃了一般操作系统对内存采取每一任务分配一块内存的方法,而是采用对内存进行分块管理,并采取所有任务公用同一块内存。对同一内存统一管理的方式; (3) 根据实际系统需要研究,并实现了内存覆盖技术,扩展了系统的存储空间。 当然,任何嵌入式操作系统的设计都有一个简单到详细的过程,需要逐步完善。本文只是完成了TS101嵌入式实时操作系统基本功能的实现。相信经过长期的实际模拟运行,定能建立起功能更加完善、结构更加稳固可靠的嵌入式实时操作系统。