1 DM642与Flash硬件连接
系统选用意法半导体公司的SST39VF080 Flash芯片,其容量为1 M×8 bit,8根数据线,20根地址线,与DM642的EMIF接口实现无缝连接,两者接线图如图1所示。DM642选择EMIF启动时,从CE1空间起始处(地址0x90000000)加载数据,所以外部Flash必须接在EMIF接口的CE1空间。
2 DM642加载方式研究
2.1 DM642自启动方式
DM642有三种启动方式,分别是Host boot、EMIF boot和No boot。系统上电或复位时通过采样引脚AEA[22:21]的电平来设置,具体配置如表1所示。
DM642选择Host boot启动方式时,系统上电复位后CPU将停止运行,其他设备正常运行。这期间,外部主机能够通过Host接口初始化CPU的存储器和内部的配置寄存器,主机完成初始化工作后,通过设置HPIC寄存器的DSPINT位,CPU即从0地址开始运行。选择No boot启动方式时,CPU直接从0地址运行程序。本文重点研究EMIF boot启动方式的加载过程。
2.2 EMIF boot加载过程
DM642系统的CE1空间外接Flash固态存储器,当选择从EMIF启动时,DM642芯片内部已完成固化的加载程序(也称一级bootloader)会自动从Flash空间(CE1空间,起始地址0x90000000)读取1 KB数据到内部RAM空间(起始地址0x00000000),然后跳转到0x00000000处执行。这个过程由DM642处理器自动完成,用户无法干预。
如果用户的应用程序很小(<1 KB),则直接通过系统的一级bootloader加载即可;但是用户的应用程序通常>1 KB,所以位于0x00000000地址的1 KB程序通常也是一个引导程序(又称二级bootloader),其作用是将应用程序从Flash中读出并放到内存中,然后跳转到c_int00()执行,这个过程也被称为二次加载。
3 二级bootloader程序设计
3.1 传统设计方案
二级bootloader需要完成3部分功能:
(1)初始化EMIF口,配置其寄存器;
(2)把Flash中1 KB以后的各程序段和数据拷贝到指定的存储物理地址中;
(3)跳到C程序入口点c_int00()运行。
传统的二级bootloader设计方案多通常基于TI公司提供的汇编例程移植实现,该方案要求设计者熟练掌握TI C6000系列DSP汇编语言,开发难度大、周期长。
3.2 C语言实现
二级bootloader采用汇编语言编写,是因为在引导过程中还未建立C语言的运行环境,包括系统堆栈定义、初始化堆栈、初始化全局和静态变量等。但是如果能够避开系统堆栈操作,仍然可以使用C语言编写二级bootloader程序。
这些与系统堆栈相关的操作主要有两方面:(1)定义局部变量时使用register修饰类型,表明是定义在寄存器中,而不是堆栈中;(2)不需进行函数调用,包括C库函数的调用。
把目标工程烧写到Flash中,数据在Flash中的分配如图2所示。其中,前1 KB空间(图中灰色部分)存放二级bootloader;地址0x90000400之后的Flash空间存放用户应用程序,从图2可知应用程序存储是以_c_int00()开始,以0x00000000结束,中间是各代码段和数据段。
基于上述Flash中数据分配,以下是对应的二级bootloader部分C语言程序代码:
#include <c6x.h>
#define Flash_CODE_ADDR 0x90000400
#pragma CODE_SECTION(boot, ".bootloader");
extern far void c_int00(void);
void boot(void)
{ register int code_i;
register int addr_ptr;
register int code_len;
register int code_addr;
//此处需要先初始化EMIF口;
// addr_ptr指向代码段1长度位置
addr_ptr = (int)(FLASH_CODE_ADDR+4);
for(; ;)
{
//代码段长度
code_len = *(volatile int *)addr_ptr;
addr_ptr += 4;
//代码段运行地址
code_addr = *(volatile int *)addr_ptr;
addr_ptr += 4;
if(code_len == 0x00000000)
{
//跳转到C语言入口
c_int00();
}
else
{
//把代码段从Flash中读到片内来
for(code_i=0;code_i<code_len;code_i++)
{
*(char *)(code_addr+code_i)
= *(char *)addr_ptr;
addr_ptr++;
}
}
}
}
程序中"#pragma CODE_SECTION(boot,".bootloader")语句的作用是将boot定位在.Bootloader段,然后在.cmd文件中将.bootloader段映射到片内起始1 KB内存区。此bootloader程序编译后体积为352 B,不会超过1 KB的限制。另外该程序是基于小端字节序编写,若系统为大端字节序,需要作少许修改。
使用C语言设计bootloader,极大提高了程序的可读性和移植性,加快了用户应用程序的开发。但其效率低于传统的汇编bootloader,所以从系统上电到加载完成运行所需时间略长。
3.3 程序烧写
在CCS中目标工程生成的是COFF格式(.out文件)。而Flash烧写工具一般只支持ASC II十六进制格式,所以,必须先用16进制转换工具将.out文件转换成.hex文件,再进行烧写。烧写目标程序的步骤为:
(1)编译生成目标工程的.out文件,在编译之前需进行如下操作: ①把上述C语言编写的bootloader程序添加到目标工程中去; ②修改目标工程的.cmd文件,将bootloader这段代码映射到片内起始1 KB内存区,目标工程中的其他代码放在后面。
(2)用16进制转换工具hex6x.exe从.out文件产生.hex文件。
(3)用Flashburn软件烧录.hex文件。
3.4 结果验证
系统采用自主研发的DM642硬件平台,为了验证C语言bootloader程序的可行性与稳定性,具体操作步骤如下:
(1)编写测试应用程序,其功能是通过串口循环向PC机发送预定的数据;
(2)按照上述方法把程序烧写到Flash中;
(3)断电,设置 AEA[22:21]为“11”,即EMIF boot启动方式;
(4)系统与PC串口连接、上电,查看PC机上的串口调试助手是否收到预定的数据。
验证时,若PC机上的串口调试助手收到的数据与DM642应用程序发送的数据一致,则表明该方案可行。重复验证操作,每次都能收到预定的数据,则表明该方案稳定。
本文的创新之处在于采用C语言实现了DM642的二级引导加载程序的设计,不再需要使用TI公司提供的汇编程序例程进行移植,提高了程序的可读性和移植性。在实际项目中已经证实了该方案可行性和稳定性,同时,该方案适用于TI C6000系列各种型号,可以在该系列不同器件中方便地移植,为基于DM642的实际应用开发提供了新的途径。