C6202ROM引导装载方式的研究
摘要:通过使用DMA方式访问程序存储区并实现程序的搬移,克服C6000指令系统的缺陷;并对C6000的C语言运行环境和仿真器变量初始化过程进行研究,采用自编程自初始化的方法,确保程序加载后能正常运行。
关键词:引导装载 DMA DSP
DSP系统的引导装载(Bootload)是指系统加电时,DSP将一段存储在外部的非易失性存储器的代码搬移到内部的高速存储器单元中执行。这样既利用了外部的存储单元扩展DSP本身有限的ROM资源,又充分发挥了DSP内部资源的效能。尽管用户代码可直接掩膜到内部ROM中,但一方面受容量和价格的限制,另一方面则不具有扩展性和不易升级。FLASH是一种高密度、非易失性的电可擦写存储器,十分适合低功耗、小尺寸和高性能的便携式系统。除了可以采用专用的硬件编程器把代码灌入FLASH中,也可以利用现成的DSP通过软件编程实现同样的功能,因此对整个系统的软件升级很方便。
图1 C62X方框图
TMS320C6000系列是TMS320系列产品中的新一代高性能DSPs芯片。由于其结构上(如图1)的特殊性,与C54系列的引导方式有很大差别。本文以C6202为例,介绍如何实现DSP正常的ROM引导。
1 C6202的ROM引导模式
C6202有两种存储器映射方式MAP0和MAP1。通过扩展总线的XD[4:0]利用上拉/下拉电阻进行复位时的芯片启动模式设置。本文将存储器映射方式设置为MAP1,即地址0处的存储器在内部,芯片自加载方式为8bit ROM方式,如图2的硬件连接。
javascript:window.open(this.src);" style="cursor:pointer;"/>
设置完芯片加载方式后,ROM加载的具体过程是:位于外部CE1空间的ROM(即图2中的FLASH)中的程序首先通过DMA搬入地址0处,尽管加载过程是在芯片复位信号被释放后才开始的,但是当芯片开始复位时,就开始准备上述传输了。用DMA进行的这一加载过程是一个单帧的数据块传输,数据块的大小为64KB。EMIF会根据芯片自加载方式的设置将相邻的8bit或16bit数据合为32bit指令。传输完成后,CPU退出复位状态,开始执行地址0处的指令。
2 硬件设计
本文仅给出DSP(TMS320C6202)与一片FLASH(AMD29VF040)的连接图,如图2。由DSP的相关输出管脚控制FLASH的擦除和读写。C6202的EMIF含有四个CE空间寄存器,由于ROM加载程序是从CE1空间搬入的,因此DSP的/CE1与FLASH的片选/CE相连。图2中只用到DSP的低8位数据线,如果自加载方式设置为16位或32位,可以通过DSP最低两位EA1和EA0的译码BE[3:0]片选,或者选用16bit或32bit的FLASH。
javascript:window.open(this.src);" style="cursor:pointer;"/>
3 软件设计
由于C6000的特殊结构,可以实现8条并行指令同时执行,除非对硬件结构非常了解的专业人员,才能充分利用硬件资源,将汇编语言的高效率发挥出来。若对实时性要求不是很高,采用C语言编程完全可以满足需要,且C6000的优化器优化效率很高。这样可以降低编程工作量,缩短开发周期,可移植性好。本文以通用的C语言编程为例,介绍DSP对FLASH编程以实现正常的ROM引导。
3.1 系统初始化
在运行C语言前,必须建立C运行时间环境(C runtime environment),确保C程序的正常运行。运行时间支持源程序库(runtime-support source library)rts.src包含一个boot.asm模块可以实现此功能。在连接器命令中使用-c或-cr选项,且将rts6200.lib作为其中一个连接文件,连接器自动调用boot.asm模块产生c_int00函数。在硬件复位中断产生以及系统工作时,先执行此函数。
javascript:window.open(this.src);" style="cursor:pointer;"/>
函数c_int00完成下面三个初始化任务:
(1)建立堆栈并初始化堆栈指针;
(2)初始化全局变量;
(3)运行主函数。
3.2 初始化变量
在程序运行前,全局变量必须初始化。编译器建立了.cinit段用来初始化全局变量和静态变量。
3.2.1 .cinit段
在.cinit段内有不同长度的初始化记录,每一个必须初始化的变量在.cinit段内都有一个对应的记录。如图3。
每个记录包含三部分:需要被初始化的变量的长度、变量的地址和变量初始值。
javascript:window.open(this.src);" style="cursor:pointer;"/>
3.2.2 运行时初始化变量
若在连接器中使用-c选项,则在程序开始运行时,函数c_int00初始化变量。具体过程如下:仿真器加载程序时,根据.cmd文件的定位,将.cinit段拷贝到C6202的程序存储区或数据存储区,并且用指针指向加载后的初始化表的首地址。当程序开始运行时,函数c_int00中的引导程序自动识别初始化表中的数据格式,初始化.bss段中对应的变量,完成初始化过程。如图4。
3.2.3 加载时初始化变量
若在连接器中使用-cr选项,连接器在.cinit段首设置STYP_COPY位。当仿真器加载程序时,加载器会判断这一位,识别目标文件中.cinit内的初始化记录格式并初始化.bss中的变量,而不是先将.cinit段拷贝到DSP的内存区域。如图5。
3.3 烧写FLASH
要想实现DSP ROM的正常加载,必须将程序存储区中的指令数据正确地写到FLASH里。图1中可以看出,访问片内程序存储器只有两个途径:CPU访问和DMA访问。CPU访问片内程序存储器是通过程序取指单元实现的,然后完成指令分配和指令译码。C6000没有提供任何对片内程序存储器操作的指令,因此不可能直接使用指令取出程序区的内容或者将数据写入程序区中。但是DMA可以访问片内数据存储区、片内程序存储区、片内集成外设、外接存储器等,可以在没有CPU参与的情况下完成映射存储空间中数据的搬移。因此,可以编写一个烧写FLASH的程序。在数据存储区开辟一个缓存区,使用DMA方式将程序区的内容读到这个缓存区,然后再使用指令将缓存区的内容烧写到FLASH内(具体的命令字和程序与C54类似)。如图6。
javascript:window.open(this.src);" style="cursor:pointer;"/>