陈俊凯,刘笑凯,周 林,冯国兵,徐一凤,刘书萌,王 龙
(中国电子信息产业集团有限公司第六研究所,北京 100083)
TMS320C6455是一款非常优秀的DSP处理芯片,由于内部没有Flash存储空间,离线运行时需要外部加载程序,因此在设计通用信号处理模块前,有必要研究DSP的加载方式。许多文献介绍了将执行程序加载到DSP内部L2RAM的设计方法,但是TMS320C6455的内部存储空间较小,只有32 KB的L1P程序空间、32 KB的L1D数据空间及2 MB的L2RAM。没有内部Flash[1],当代码量超过2 MB时,或者需要在L2RAM留出较大的数据空间时,将代码加载到内部L2RAM变得不可行,由于TMS320C6455设计有DDR2接口,可以扩展最大512 MB的外部存储空间。本文设计将代码加载到空间很大的外部DDR2芯片,缓解内部存储空间不足的矛盾。如图1所示,TMS320C6455通过EMIFA接口连接Flash芯片,通过DDR2接口外扩DDR2芯片,通过软件设计,使用户程序存储于Flash芯片,执行于DDR2芯片。
图1 TMS320C6455外部扩展DDR2和Flash芯片框图
开发人员在进行程序代码的仿真调试过程中,由于TMS320C6455的内部存储空间有限,可以尽可能地把代码和数据存储在外部存储空间DDR2上。使用DDR2存储空间的条件是,在CMD文件中将生成带代码及数据段映射到DDR2的存储空间上,还需要在调试代码之前,初始化TMS320C6455的DDR2配置寄存器。此时,可以借助GEL文件,通过仿真器初始化DDR2配置寄存器,然后在接口函数OnTargetConnect()中调用DDR2初始化函数,利用外部存储空间DDR2在线仿真调试代码。GEL文件中的初始化DDR2控制器代码如下:
init_ddr2()
{
*(int *)PERCFG1 = 0x00000003;
DDR_SDCFG = 0x00D38832;
DDR_SDRFC = 0x0000079E;
DDR_SDTIM1 = 0x3EDB4B91;
DDR_SDRIM2 = 0x00A2C722;
DDR_DDRPHYC = 0x00000006;
DDR_SDCFG = 0x00538832;
}
TMS6455引导模式包括外部Flash启动、主机接口启动、SRIO启动、IIC启动等多种启动方式[2-3],而在实际应用中,启动模式绝大多数为外部Flash启动方式。DSP在该方式下从外部EMIFA接口CS3模式下加载1 KB代码,然而1 KB大小的代码量无法满足系统需要。要达到DSP的高速运算,又不能将大量代码放在外部Flash中运行。因此,当用户代码长度大于1 KB时,需要使用二次加载[4]。即专门编写一段长度为1 KB的二次加载程序,在初始化时被加载到DSP。而这段程序的功能是从外部Flash的某个地址处将1 KB 以外的全部用户程序和数据拷贝到其运行地址处,如图2所示。
图2 DSP使用二次加载程序的加载过程
在DSP芯片复位期间,程序指针自动指向片内ROM中的Boot Loader的小程序,这个程序会根据相应的BOOTMODE管脚状态选择相应的程序加载方法,按照默认的时序将外部Flash中的程序搬移到DSP内部的RAM程序区中,通常被传输的是二次加载程序,传输完成后,运行二次加载程序,初始化关键的寄存器,然后将系统程序剩余代码和数据拷贝到指定的位置中[5-6]。本文介绍如何将系统程序和数据拷贝到DDR2中运行的设置方法,在二次加载程序的最后跳转到_c_int00处,初始化C运行时的环境,一旦运行到环境初始化完成,就开始运行用户代码。
TI的集成开发工具CCS编译链接后生成的.out文件是通用对象文件格式(Common Object File Format,COFF)的,不能直接烧录到外部Flash,因为Flash中保存的应该是原始的DSP机器码,即烧录的应该是DSP程序的二进制文件[3]。有几种方法可以实现文件格式的转换,一种是直接提取COFF文件中的原始数据部分。这种方法比较复杂,但是有助于理解.cmd文件的编写原理以及链接器的工作过程。还有一种方法是借助CCS自带的工具,在编译选项Build的Step选项卡的post-Build step Command文本框中,填写如下命令:
“MYM{CCE_INSTALL_ROOT}/utils/tiobj2bin/tiobj2bin.bat”
“MYM{BuildArtifactFileName}”
“MYM{BuildArtifactFileBaseName}.bin”
“MYM{CG_TOOL_ROOT}/bin/ofd6x.exe”
“MYM{CG_TOOL_ROOT}/bin/hex6x.exe”
“MYM{CCE_INSTALL_ROOT}/utils/tiobj2bin/mkhex4bin.exe”
在Debug目录下生成的.bin文件可以直接烧录到外部Flash中。
以上方法都需要进行格式转换,还有一种较为简单的方法,直接利用CCS开发工具将用户程序(包含二次加载程序)编译链接后生成的.out文件通过仿真器下载到与DSP连接的DDR2中,但是不运行程序。用户程序在DSP外部DDR2中就是以二进制的格式存储的机器码,可以直接通过在线编程的方法烧写到片外的Flash中。开发人员运行在线烧写Flash的程序(这个程序完成的功能是将代码写入到Flash),这里存在的风险就是烧写程序的存储区域与前面用户程序的存储区域相冲突,要注意在两个工程的cmd文件中存储区域不要重叠,如图3所示。
图3 程序在DSP+DDR2的存储分配方式
在用户工程的CMD文件中,也就是第一个工程中,将二次加载程序及用户程序配置在DSP外部DDR2空间中(0xE0000000~0xF0000000);在烧写Flash工程的CMD文件中,将代码配置在DSP内部L2RAM的空间,保证烧写Flash程序的.out文件下载下去之后不会与前面下载的目标工程的.out文件存储区域相冲突。然后运行烧写Flash程序,将前面下载的用户程序写入外部Flash芯片中。
二次加载程序实现的功能为:(1)初始化关键寄存器,如DDR2寄存器;(2)将用户程序的剩余代码和数据拷贝到指定位置;(3)搬移完代码之后,跳转到_c_int00处,开始执行用户代码。本文将代码段和数据段存放在DDR2空间。因此在编写二次加载程序时,搬移代码之前,需要初始化DDR2寄存器,才可以正常将代码搬移到DDR2空间中。同时查看用户工程map文件中代码段的大小,设置搬移代码BOOT_SIZE的值,注意汇编程序每次搬移是16位数据,所以BOOT_SIZE的大小等于真实代码段大小除以2,由于二次加载程序受限于1 KB字节的大小,因此二次加载程序采用更为简洁的汇编程序来实现。二次加载程序的代码大小、代码搬移地址、代码DDR2寄存器、EMIFA寄存器参数的设置如下:
BOOT_SIZE .equ 0x000FF000
FLASH_START .equ 0xB0000000
BOOT_START .equ 0xE0000000 ;DDR2
;EMIF config
EMIF_CF3CFG_R .equ 0x70000084
EMIF_AWCC_R .equ 0x700000A0
EMIF_CF3CFG_V .equ 0x012C8024
EMIF_AWCC_V .equ 0x40000380
;DDR config
PERCFG1_R .equ 0x02AC002C
DDR_MIDR_R .equ 0x78000000
DDR_SDCFG_R .equ 0x78000008
DDR_SDRFC_R .equ 0x7800000C
DDR_SDTIM1_R .equ 0x78000010
DDR_SDTIM2_R .equ 0x78000014
DDR_DDRPHYC_R .equ 0x780000E4
PERCFG1_V .equ 0x00000003
DDR_SDCFG_V1 .equ 0x00D38832
DDR_SDRFC_V .equ 0x000007A2
DDR_SDTIM1_V .equ 0x3EDB4B91
DDR_SDTIM2_V .equ 0x00A2C722
DDR_DDRPHYC_V .equ 0x00000006
DDR_SDCFG_V2 .equ 0x00538832
将上述参数以下面的汇编语句写入相应得寄存器地址,完成寄存器参数的配置:
MVKL EMIF_CF3CFG_R,A4
MVKH EMIF_CF3CFG_R,A4
MVKL EMIF_CF3CFG_V,B4
MVKH EMIF_CF3CFG_V,B4
STW B4,*A4
将DDR2的起始地址BOOT_START加载到A4寄存器,将Flash的起始地址FLASH_START加载到B4寄存器,代码搬移长度BOOT_SIZE加载到A0寄存器,然后下面的语句完成代码从Flash到DDR2的搬移过程。
_wait_loop:LDH *B4++[1],B5
SUB A0,1,A0
NOP 4
STH B5,*A4++[1]
[A0] B _wait_loop
NOP 5
搬移完成之后,跳转到_c_int00位置,启动程序。
MVKL.S2 _c_int00,B0
MVKH.S2 _c_int00,B0
B.S2 B0
NOP 5
用户程序和二次加载程序都编写完毕后,想要完成加载功能,还需要的就是烧写程序的编写了。写入Flash芯片之前需要先擦除掉原来的内容,再写入用户代码。擦除和写入操作驱动程序根据不同的Flash芯片有所不同。本文只给出烧写部分内容,CODE_SIZE为实际要烧写的用户程序大小:
#define CODE_SIZE 0x127fd1
#define DDR_ADDR 0xE0000000
#define FLASH_ADDR 0xB0000000
//擦除Flash
flash_Erase();
//烧写用户程序
Count= 0;
for(i = 0;i < CODE_SIZE;i++)
{
if(0!=flash_writes(FLASH_ADDR +i,*(unsigned char *)(DDR_ADDR +i)))
Count++;
}
本文详细介绍了TMS320C6455+DDR2的在线仿真及ROM加载模式,并给出了二次加载程序的汇编代码以及Flash烧写代码。通过上文的方法,可以实现将执行代码加载到DSP的外部存储空间DDR2上,用户代码受限于DSP内部存储空间的大小,有利于运行复杂度比较高得数据运算,其TMS320C6455+DDR2的硬件平台可以支撑起有大量运算需求的产品应用,在信息安全领域的密码方面[7-8],可以为对称密码算法(如AES、3DES)、公钥密码算法(如RSA算法、椭圆曲线算法)、消息摘要的哈希算法等大运算量的算法提供良好的硬件平台。