|
摘要: TMS320VC5410的程序空间通常被限制在64K地址空间内, 当应用程序超出64K时, 则需增加目标系统存储区和附加逻辑, 实现对系统的扩展。介绍了如何配置及使用DSP/BIOS接口来实现扩展寻址功能, 分析了API函数调用和中断触发过程, 并以DSP并行自举引导方式实现程序的脱离仿真运行。
关键词: DSP/BIOS 扩展寻址 API 并行自举引导
1 DSP/BIOS 接口
DSP/BIOS 接口提供了基本的运行服务,如应用程序实时分析功能、时钟周期函数、I/O模块、优先级的任务调度等。 DSP/BIOS 接口提供支持汇编语言和C语言的API 接口函数,这些API 函数绝大部分都是用汇编语言实现的,因此汇编语言可以直接调用API,而C语言调用API 则要通过DSP/BIOS 的C封装器。应用程序通过调用API 函数来使用DSP/BIOS 接口,如软件中断、背景线程和中断服务程序等都可以调用DSP/BIOS 的函数。当DSP/BIOS 要调用用户的C语言函数时,则要通过函数链接器,如图1所示。
![]()
2 扩展程序空间
TMS320VC5410 的16位地址空间被划分为两块,低地址块定义为公共区(或未映射区),高地址块定义为映射区(或扩展区)。这两块的地址由目标系统的外部寄存器和存储区决定。值得注意的是,TMS320VC5410 的数据区没有扩展存储区。
用户可以在映射区上定义多个物理存储区,它们覆盖整个映射区,但彼此间不重叠。当使用存储区的扩展页时,内部16 位地址空间被扩展为32 位的地址进行寻址,高16 位代表扩展页的数目,低16 位代表局部的16 位地址。如使用扩展程序映射存储器(XPC)存放扩展页码,则XPC 存放在数据空间地址为0x1E 的位置,它的值要与.CMD链接文件中定义的扩展页码保持一致。图2 所示的是一个扩展3 页的程序区结构图。公共区的范围是0x0000-0x7FFF;映射区的范围是0x8000-0xFFFF;映射区为第一页,XPC 要为0才能访问该区;映射地址空间存放两个扩展页,扩展程序映射寄存器限定了映射地址,使得每个扩展页的每个单元具有唯一的地址。当访问扩展页时,映射区将被覆盖。
![]()
TMS320VC5410 的DSP/BIOS 不仅支持64K 程序页内的“近”访问模式,而且支持扩展程序的“远”访问模式,只需设置DSP/BIOS 的属性即可实现扩展程序的“远”访问。要注意的是,汇编语言写的API 只能在PAGE0 页调用,而C语言写的API 可以在任何页面调用。
3 中断
当中断产生时,DSP 的内部结构机制只能保存低16位页内的局部地址,而扩展寻址时程序地址需要23 位,这就意味着调用和返回时将超出64K(16位地址)的范围,因此必须考虑怎样保存和恢复扩展地址。解决的方法是用中断服务程序(ISR)保存XPC的值,确保能正确计算中断向量,为此中断向量表必须放在公共区或映射区的64K 程序页面上。当DSP/BIOS 在公共区上时,ISR 可以放在任何位置;如果不在公共区上,则ISR 必须放在PAGE0上。
当OVLY=0 时,为了能保证中断正确执行,必须在每一个页面上都要有中断向量表的拷贝。当OVLY=1 时,只需在公共页面上(如0x7F80)作一份中断向量表的拷贝就可以了。
4 程序实例
下面通过一个简单的例子介绍DSP/BIOS 如何实现程
序地址的扩展。本例中有三个软中断:时钟中断PRD_POST_SWI, 每100ms 触发SWI_PAGE1(或SWI_PAGE2)一次;SWI_PAGE1 完成置XF 高;SWI_PAGE2完成置XF 低。三个软中断执行的函数分别放在程序空间的不同页面上,即PRD_POST_SWI 放在公共页面上(XPC=0), Page1Func 和Page2Func 分别放在扩展程序页面1和2 上(XPC为1和2)。
![]()
5 DSP/BIOS 的配置
如要把DSP/BIOS 的程序映射到扩展程序空间,需要对其进行配置,步骤如下:
(1) 建立一个新配置文件。启动仿真软件(Code Composer Studio), 建立testfar.pjt 工程,通过File 中的New--DSP/BIOS Config 创建配置文件, 选用sd54.cdb (54X EVM)配置。
(2) 添加软件中断。右键打开软件中断管理器(Software Interrupt Manager), 选择Insert SWI, 创建SWI_PAGE1, 属性配置为:function:_Page1Func;priority2。用同样的方法
创建function为_Page2Func的SWI_PAGE2。右键打开定
时器功能管理器(Periodic Function Manage), 选择Insert PRD, 创建PRD_POST_SWI, 属性配置为:period(ticks):50, function:_PRD_Post_SWI, mode:continuous。
(3) 设置OVLY 位为1。打开System中的Global Settings 的属性页, 在PMST(6-0) 项中填入使第5位为1的值, 如MP=1, 填入0x60。
(4) 指定“远”调用模式。在Global Settings 属性页面的Function Call Model 选项中选择far, 使全局变量Callmodel 设置为far。
(5) 在公共区中重新分配中断向量表。双击System中的MEM, 右键打开VECT 的属性页, 在base 项中填入新的基地址, 如0x7F80。
(6) 配置扩展程序地址段。对于54X EVM 评估板, 已经有了两个扩展程序段EPROG0和EPROG1(如果没有的话, 则需添加这两个段, 选择Insert MEM, 添加两个扩展程序段, 重命名为EPROG0和EPROG1)。EPROG0属性为base:0x8000, len:0x4000, 勾去create a heap in this memory 选项, space:code;EPROG0与EPROG1的属性不同之处为base:0x18000。加入一个新的扩展程序段EPROG2,属性为base:0x28000, len:0x4000, space:code。
(7) 将目标代码链接到扩展程序段。 pragma 伪指令告诉编译器的预处理器如何处理函数,语法为#pragma CODE_SECTION(Page1Func,“.FarPage1”), 在名为“.FarPage1”的段中分配Page1Func的程序空间。这样,目标代码Page1Func 就被链接到.FarPage1 段的区域。
(8) 创建一个新的链接命令文件(testfar.cmd)。其主要功能是把testfarcfg.cmd 链接进去,并且告诉链接器把不同目标函数放在不同的扩展页面上。如:
![]()
(9) 保存配置文件为testfar.cdb, 然后将testfar.cdb、testfar.cmd、testfar.c 文件加入工程中。
(10) 配置编译器和汇编器支持远模式代码。打开菜单Project 中的Build Options 窗体, 选择Compiler 属性页, 点击Category 中的Advanced 选项, 勾选Use Far Calls(-mf)(C548 and higher)。此选项指定产生远调用代码模式。
(11) 在调试器内描述并激活扩展寻址功能。仿真器的调试软件需要激活扩展寻址功能才能支持长指令的执行和扩展存储区的读/ 写,方便地对使用扩展寻址的程序进行调试。所以使用通用扩展函数GEL_XMDef() 来定义映射寄存器(如XPC)和映射扩展空间的首地址。如当OVLY=1时, 扩展程序区从0x8000开始, 7 位XPC 放置在数据空间的0x1E 单元中, 并把下面两条语句加入到C5410.gel 文件的C5410_Init() 函数中。
GEL_XMDef(0,0x1e,1,0x8000,0x7f);
//0:映射程序空间;0x1e:XPC 的地址;XPC 在数据空间中;
//0x8000:映射首地址;0x7f:XPC 的大小,128页;
GEL_XMOn();// 使能扩展地址映射
6 DSP/BIOS 函数调用和中断触发过程
6.1 DSP/BIOS 函数调用过程
![]()
DSP/BIOS API 调用过程如图3 中的实线所示。具体过程如下:
(1) 产生PRD_F_swi, 短调用C 语言封装器的PRD_F_swi(), XPC=0。
(2)C 语言封装器触发PRD_POST_SWI 时钟软中断, 然后检测SWI_PAGE1, 产生执行DSP/BIOS调度表的分支。
(3)DSP/BIOS 调度表保存当前PRD_POST_SWI上下文信息,调用函数链接器以触发SWI_PAGE1。
(4)函数链接器远调用SWI_PAGE1,执行相应的函数(Page1Func),XPC=1。
(5)SWI_PAGE1 执行结束,远返回函数链接器。
(6)函数链接器又返回到DSP/BIOS 调度表。
(7)DSP/BIOS 调度表恢复PRD_POST_SWI 信息,返回到C 语言封装器。
(8)执行上述(1)和(2),第(3)步触发SWI_PAGE2,函数链接器远调用SWI_PAGE2,执行函数(Page2Func),XPC=2。
(9)SWI_PAGE2 执行结束,远返回函数链接器,然后顺序执行上述的第(6)和(7)。
6.2 中断触发过程
中断触发过程如图3中的虚线所示。
(1)PRD_F_swi 发生,CPU 把当前的16位PC 指针压入堆栈,在中断向量表中取指令。
(2)中断向量程序把当前的XPC 压入堆栈,产生一个配置中断服务程序的分支指令,执行中断服务程序,XPC=0。
(3)中断服务程序调用HWI_enter, 触发PRD_POST_SWI 软中断,接着调用HWI_exit 检测到SWI_PAGE1准备好, 开始调用DSP/BIOS 调度表。
(4)DSP/BIOS 调度表保存当前的上下文信息,调用函数链接器以触发SWI_PAGE1。
(5)函数链接器远调用SWI_PAGE1,执行相应的函数,此时XPC=1。SWI_PAGE1 执行完,远返回调用函数链接器,再到DSP/BIOS调度表,调度表恢复上下文信息,把程序指针交给PRD_POST_SWI 软中断。PRD_POST_SWI 结束。
(6)执行上述(1)、(2)步后,第(3)步检测到SWI_PAGE2 准备好,第(4)步触发SWI_PAGE2,第(5)步函数链接器远调用SWI_PAGE2,XPC=2,顺序执行下去,直到PRD_POST_SWI 结束。
7 并行自举引导的实现
TMS320VC5410 上电复位后,检查到DSP 处于MC(微计算机)工作方式, 从片内ROM 的0FF80h 起执行程序。0FF80h 地址存放的是中断向量表,它实为一条分支转移指令(BD 0F800h),使程序跳转至0F800h执行
自举引导程序(BootLoader)。并行自举引导是DSP 自举引导常用的一种方式, BootLoader 首先从地址为0FFFFh 的I/O 口读取自举表首地址的内容, 如果此内容不符合8位或16位的引导方式, 就从地址为0FFFFh的数据存储器读取, 进行8位或16位并行自举引导。若要完成自举引导功能,必须建立正确的自举表。
自举表的内容不仅包括欲加载的各段代码,而且包括各段代码的长度、各代码段存放的目标地址、程序入口地址等信息。自举表可由hex500 格式转换器自动生成。hex500 是一个通用程序,它将公共目标文件格式——COFF 文件转换成各种FLASH(或EPROM)的编程格式。因此,在使用hex500 工具之前,首先把testfar.pjt 进行编译、链接,生成COFF 格式的testfar.out 文件,然后再通过设置适当的选项生成用户所要求的自举表,如转换文件的格式、外部数据存储器的字宽等选项。把testfar.out 转换为testfar.hex 文件后, 再使用C 语言编写一个转换程序, 将hex 文件转换为DSP 烧写FLASH 程序能识别的文件格式。根据文件信息就可以完成自举表的内容,如表1 所示。最后使用FLASH 的擦除、读写等操作指令把表1 的内容烧入FLASH 中。 DSP 上电复位,便可完成并行自举引导。
![]()
整个引导过程为:上电复位后,判断MP/MC=0 处于微计算机工作方式,从片内ROM 的0FF80h 处执行中断向量表的分支转移指令(BD 0F800h), 使程序跳转至0F800h 处执行自举引导程序。自举引导程序完成初始化后读取数据空间的OFFFFh 地址的内容, 找到自举表首地址8000h, 从8000h 处开始读取内容, 首先是16位自举标记(10AA), 然后分别是寄存器SWWSR 及BSCR的内容、程序入口地址、代码段长度、存放代码段的目标地址等信息,根据这些信息把FLASH 中的8008H-A594H的程序搬运到片内RAM中, 然后把Page1Func和Page2Func 的代码搬运到0x18000 和0x28000处, 最后跳转至片内RAM的26FDH, 即PC 为26FDH, XPC 为0, 开始执程序。这样即完成程序的并行自举过程。
使用DSP/BIOS 可以很好地实现扩展寻址功能, 把程序烧写入FLASH 后, 复位DSP 使其处于MC 工作方式, 便可使用示波器测试XF引脚, 观察程序运行正确与否。
[/td]
[/tr]
|
|