FLASH存储器的在系统编程及其在DSP系统中的应用
2009-04-02
作者:公茂忠 刘汉奎 徐殿国
摘 要:FLASH存储器的在系统编程技术及其基本命令,并结合TMS320C3X系列DSP的上电系统自动引导功能,介绍了利用该技术将用户程序代码烧写到FLASH存储器中的方法。该方法能够实现DSP系统上电后的用户程序自动引导。
关键词:FLASH存储器 DSP 在系统编程 上电引导
现在,数字信号处理器(DSP)正越来越多地应用到各种场合。而FLASH存储器已成为DSP系统的一个基本配置,主要用来存放用户程序代码。目前FLASH存储器正在从单纯的EPROM的替换件演变为许多电路系统中的不可缺少的组成部分。
将用户程序代码装入FLASH存储器的方法有三种。一种方法是要求供应商在存储器发货前将数据写入,但无法满足产品开发阶段用户修改程序的要求。另一种方法是用户使用编程器自己编程。但由于芯片制造工艺的提高,芯片集成度越来越高,FLASH存储器正在向小型化、贴片式发展,从而使表面贴装或PLCC封装的FLASH存储器难以利用编程器编程。第三种方法是将存储器安装到用户电路板上进行编程。这包括现在普遍采用的在系统编程(In System Programming,ISP)。这种编程方式是通过系统的微处理器实现对FLASH存储器的编程,不需要其它编程设备和附加编程电源,具有灵活、方便的优点,因此广泛应用在DSP系统中。本文结合TMS320C3X系列DSP的上电引导表的产生及烧写方法分析FLASH存储器的在系统编程技术。
1 FLASH存储器的在系统编程技术
1.1 AMF400B FLASH存储器简介
AMF400B 是AMD公司生产的FLASH存储器,这种FLASH存储器编程简单,下面以此为例对FLASH存储器的编程进行介绍。
AMF400B的主要特点有:仅需5V单电源供电便可使内部产生高电压进行编程和擦除操作;完全支持JEDEC单电源FLASH 存储器标准;支持在系统编程,用户只需向其命令寄存器写入标准的微处理器指令,具体编程、擦除操作便由内部电路实现;主系统可以通过查询特定的管脚或数据线监控编程、擦除操作是否完成;可以对某一扇区进行操作,而不影响其它部分的数据;有硬件数据保护功能,以防止误操作。
1.2 编程命令
虽然用户仅需向FLASH存储器的特定寄存器写入地址和数据命令,就可对FLASH存储器编程,但是如果写入的地址和数据错误或写入的顺序不正确,就会导致FLASH存储器复位。下面介绍几个最常用的编程命令。
读数据命令:该命令不需要特定的时序,在电路上电或内部编程擦除操作结束后,自动进入读数据状态。只需给出要读取的地址,即可读出该地址的内容。
复位命令:该命令使存储器复位,并进入读数据状态。向任何一个地址写入数据0xF0就能使FLASH存储器复位。在进行编程、擦除和自动选择命令模式之前,都应先复位。此外,在编程或擦除等正常操作中若出现错误,也应写复位命令退出。
自动选择命令:该命令可以使主系统读取存储器生产厂家、设备代码以及是否被保护等信息。
编程命令:该命令是一个4总线周期指令。以两个解锁周期开始,紧接着一个编程建立命令,最后是要编程的地址和数据。写完该地址和数据后,内置编程算法自动启动,进行FLASH存储器编程。编程算法完成后,进入读取数据状态。编程时序如表1所示。
擦除命令:该命令有片擦除和扇区擦除两种。两种擦除命令基本相似,片擦除指令用得较多,这里仅介绍片擦除指令。片擦除命令是一个6总线周期的操作,也以两个解锁周期开始,接着一个建立周期,再接着两个解锁周期,最后是擦除周期。该擦除命令启动内部擦除算法,自动完成擦除操作。其时序如表2所示。
由于只有擦除指令能使“0”变为“1”,而编程指令不能使“0”写为“1”,所以用户在进行FLASH存储器烧写时,应先擦除,再进行编程。
1.3 FLASH存储器操作的检查机制
对采用在系统编程的FLASH存储器,整个烧写过程都由用户控制,用户必须了解FLASH存储器的各状态位,以便知道编程或擦除是否完成。
FLASH内部提供了几个供用户读取的状态位。其中常用的有:数据线的DQ2(跳变位)、 DQ5(超时标志位)、DQ6(跳变位)、DQ7(数据查询位)和管脚RY/BY#。
有三种方法可以判断某种操作是否进行完。一种是判断管脚RY/BY#的状态。在编程、擦除或擦除悬挂操作过程中,RY/BY#管脚为“0”;操作完成后变为“1”。另一种是用DQ7和DQ5判断。DQ7位在编程或擦除过程中输出的是写入该位数据的反码,而当操作完成时,该位输出变为写入该位的数据,因此查询此位可以判断操作进程。但还要读取DQ5的状态,若为“1”,操作超时,应再读一次DQ7的状态,若DQ7输出仍不是写入的数据,则操作失败,应将FLASH复位。其流程如图1所示。还有一种是检测跳变位。在对FLASH存储器进行编程或擦除时,对任何地址进行连续的读会引起DQ6不断跳变,而一旦操作结束就停止跳变。其流程如图2所示。
1.4 FLASH存储器的操作程序
采用前面的命令字和操作进程检测方法,用户就可以用DSP编程语言编写FLASH存储器操作程序了。下面给出擦除和编程子程序的部分代码。
/*Sample codes for erase and program*/
cerase: PUSH DP
PUSH R0
.... /*擦除命令*/
chkc: LDI *AR0,R0
NOP /*检查擦除是否完成*/
NOP
XOR *AR0,R0
BNZ chkc
POP R0
POP DP
RETS
sprg: PUSH DP
PUSH R0
.... /*编程命令*/
chkp: LDI *-AR2(1),R0
NOP /*检查编程是否完成*/
NOP
XOR *-AR2(1),R0
BNZ chkp
POP R0
POP DP
RETS
2 TMS320C3X系列DSP的上电引导功能
实际DSP电路中,调试后的用户程序必须能够脱离仿真器独立运行,这就涉及到如何将用户程序代码编程到FLASH存储器中。用户程序执行有两种方式:一种是上电后用户程序直接在FLASH存储器中运行;另一种是上电后将用户程序从FLASH存储器引导到高速数据存储器中运行。由于第一种方式影响程序的运行速度,现在大多数实际电路都采用第二种方法。下面以TI公司的TMS320C3X系列DSP为例,说明如何由仿真器最初生成的可执行文件实现第二种方法的过程。
2.1 MS320C3X的上电引导程序和引导表
引导程序(boot loader)是在一些DSP(如C3X,C4X系列)片内固化的一个程序,它负责上电时初始化存储器。换句话说,它将程序从非易失性存储器(如EPROM或FLASH存储器)中调入系统的存储器中。
引导程序要调入的代码称为引导表(boot table)。引导表中除了包括源代码之外还,包含一些附加信息。这些信息指导引导程序的具体执行过程。一方面,存放引导表的介质一般都是物理总线宽度小的存储器(如8位,16位等),而DSP系统总线的宽度一般都是32位的(对C3X,C4X系列),因此就存在着代码的拆分与组合问题,这就需要一些附加信息来“告诉”引导程序;另一方面,TI的DSP的可执行文件是COFF格式的,它将程序代码分为很多不同的段(如.text,.bss,.const等),这些段的大小和存储地址都是不同的,因此也需要额外的信息来说明。因此可以说引导表是由程序代码和一些附加信息组成的一种数据结构。
每一种DSP,其引导表的数据结构也是不同的,但其基本结构差不多。具体来说引导表的格式主要由下面几部分组成:首先是一个包含引导表数据宽度和其它数据总线控制寄存器值的文件头;接着是COFF文件中各个段的数据,其中每个段又都包含一个该段的文件头来指示该段的代码长度及目标地址;最后是一个结束段,表明程序代码的结尾。
2.2 如何产生引导表
由于COFF文件格式与引导表格式对用户是透明的,因此用户可以自己编程由COFF格式生成引导表。这无疑是一项很繁琐的工作,幸好DSP公司一般都在它们的开发软件中提供了一个转换工具,如TI公司的HEX30工具。这样,用户需要做的只是提供一个命令文件,即可由转换工具生成可以上电引导的引导表。
在生成引导表时,应特别注意几个“字宽度”的概念。只有正确理解这几个概念,才能生成正确的引导表。首先是目标字宽度。它指COFF文件内原始数据的宽度,是指处理器的操作码长度。对特定DSP,该长度是固定的,不能改变。其次是数据宽度,可用-datawidth设定,它指在COFF文件中存有的某段数据的逻辑宽度。再次是存储器宽度,可用-memorywidth设定,它指存储器系统的物理宽度。最后是ROM宽度,用-romwidth设定。它指每块ROM设备的物理宽度,同时也对应HEX30工具输出文件的宽度。下面的例子可以说明这几个字宽度的概念。
例如,DSP为TMS320C32,用来存储程序的FLASH存储器是16位的,只用一块FLASH。则命令文件可以按如下编写:
/*Command file for the hex utility*/
prog.out ;COFF文件名
-boot ;引导所有段的内容
-i ;输出文件的格式
-memorywidth 16
-bootorg 1000h
ROMS
{
EPROM: org=1000H, len=2000H,
romwidth=16,files={prog.i0}
}
3 利用ISP对上电引导FLASH存储器编程
上述的命令文件中有一个选项-i,这是指定输出文件格式的选项。TI公司HEX工具可以支持多种格式,如ASCII-HEX、Intel、Motorola、TI-tagged、Tektronix等,这些文件都是文本格式的文件,都有固定的格式。以Intel格式为例,生成的文件的每行都有一9个字符的前缀,结尾有2个字符的检验位。若用EPROM编程器,则此文件就是编程器的输入文件,可以直接使用。但对前面所说的在系统编程,编程程序本身就是一段DSP程序,要想让此程序识别生成的引导表,还需要对文件进行转换。
由于编程程序也是一段DSP程序代码,最后生成的也是COFF格式,因此可以将引导表作为编程程序的一个初始化段,程序运行时将该段的内容写到FLASH所在的空间即可。
剩下的问题就是如何将HEX工具生成的文件转化为DSP程序能识别的文件格式。由前面的内容可知,每种格式的文件都包含自己独特的头文件,因此可以编写一段简单的C语言程序将这些与引导无关的“头”去掉,分离出引导表,然后按特定格式将这部分内容写成一个数据文件。在编程程序中,为引导表建立一个段,将此数据文件嵌入即可。这样,运行编程程序就能将引导表内容烧写到指定的FLASH存储器中。整个编程过程如图3所示。
例如,最初的COFF文件为prog.out,C语言程序将HEX工具生成的prog.i0文件转化为prog.dat,那么最后的烧写程序类似下面所给出的格式。
/*A sample FLASH programming routine*/
....
code .sect ″.FLASH″
.include prog.dat
....
_main:
.... /*初始化及擦除子程序*/
LDI @CODE_PTR,AR3 /*CODE_PTR的值是code*/
LDI code_len,AR4 /*要烧写的代码长度*/
CALL FLASH_mprg /*调用编程子程序*/
....
FLASH_mprg:
....
CALL sprg /*调用单个字编程子程序*/
BNZ FLASH_mprg
....
RETS
前面各部分,结合TMS320C3X系列DSP的上电引导功能,介绍了利用在系统编程技术将用户程序代码编写到FLASH存储器中的方法,给出了相应环节的程序流程图和部分操作的程序示例。通过实际TMS320C32的DSP电路调试实验,证明本文的方法能够实现FLASH存储器的在系统编程和DSP系统上电后的用户程序自动引导。
参考文献
1 TMS320C3X User’ Guide. Texas Instruments,1997
2 TMS320C3X/4X Assembly Language Tools User’s Guide.Texas Instruments,1997
3 Markus Levy. 闪速存储器设计工具概览. 电子设计技术EDN China, 1996(12):42~45
4 Antony Watts. 正确选择非易失性存储器.电子设计技术EDN China,1996(6):38~43