TMS320VC5416并行自举的巧妙实现
*Ad_Temp=0x0055; //给地址0x2AAA,写数据0x0055
Ad_Temp=(uint *)(0x5555); //第三个写周期
*Ad_Temp=0x00A0; //给地址0x5555写数据0x00A0
*Ad=DQ; //给编程地址写编程数据
Again;Temp1=*Ad & 0x0040; //两次读D6(Toggle Bit)
Temp2=*Ad & 0x0040;
If(Temp1!=Temp2) //判断是否命令执行结束,否则继续读Toggle Bit
goto Again;
}
图2
3 TMS320VC5416的并行自举
通过在系统编程可以实现将执行代码写入FLASH。如果确定FLASH中用户程序代码的存储格式并正确自举以实现脱机运行是整个在系统编程的重点。
3.1 自举表
在介绍DSP并行自举过程之前,必须对DSP的自举表加以说明。必须对DSP的自举表加以说明。自举表需按照TI公司规定的格式来创建。该表中存放在DSP初始化时要用到的特殊寄存器如SWWSR、BSCR等的值、程序入口地址、各段的目标首地址和长度以及要执行的代码。
3.2 并知自举过程
完整的并行自举的流程图如图2所示。
SST39VF200 FLASH存储器是16位的,所以实际采用的是16位并行自举,DSP内部的引导程序从数据空间地址0xFFFF读取自举表首地址,最后从自举表中将可执行代码搬移到DSP对应的RAM中。
3.3 "两次下载法"实现并行自举
如何按照规定的自举表格式将表中的各项内容写入到外挂的FLASH中去?普通的做法是利用hex200.exe文件将*.out文件转换后*.hex格式,然后读取*.hex文件,将其写入FLASH。这里采用一种更简便的“两次下载法”将自举表写入FLASH,整个过程无需文件转换和文件读取,并且完成此过程的代码很小,几乎不占用DSP内部的存储空间。
所谓的“两次下载法”就是通过仿真器对DSP进行两次加载来完成自举表的建立。第一次加载用户希望自举的可执行代码,称为代码1,加载完后不运行此代码;紧接着加载建立自举表的代码,称为代码2。代码1是DSP脱机运行时的代码,代码2仅仅是把代码1按照自举表的格式写入到外部FLASH中的代码。需要注意的是,代码1和代码2在分配程序存储空间时不可以重叠,而且代码2的数据空间必须包含代码1和外部FLASH共同占用的空间,因为它要把代码1按访问数据的方法写到外部FLASH中。由于下载完代码1后并没有运行,而是紧接着下载代码2,两者的程序存储区又不重叠,因此下载完码2后,先前下载的代码1仍旧在DSP中,只是被代码2看成数据而已。“两次下载法”的具体操作步骤如下:
(1)将DSP的MP/MC引脚置高,让DSP工作在微处理器方式。
(2)将代码1通过仿真器下载到DSP中,但不运行该代码。
(3)将代码2通过仿真器下载到DSP中,运行此代码。
(4)代码2运行结束后,去掉仿真器,并将MP/MC引脚置低,让DSP工作在微型计算机方式。
(5)复位DSP,观察程序运行的结果是否正常。
“两次下载法”中两次代码的存储区分配情况如图3所示。
javascript:window.open(this.src);" style="cursor:pointer;"/>
图中,代码1中的数据段起始地址为0xA,数据段结束地址这0xB,代码段起始地址为0xC,代码段结束地址为0xD,其中0xB和0xC可以是同一地址,也可是不同地址;代码2中的数据段起始地址为0xG,数据段结束地址为0xFFFF,代码段起始地址为0xE,代码段结束地址为0xF,其中0xF和0xG可以是同一地址,也可以是不同地址。对TMS320VC5416而言,因其0x0000~0x7FFF对应的是内部的32K字空间,所以两个表中的地址大小关系为0xG<0xC<0xD<0x8000。
基于上述思想,假设代码1的程序段为0x4000~0x7FFF,数据段为0x3000~0x3FFF,代码2的程序段为0x2000~0x2FFF,数据段为0x3000~0xFF7F(需要注意的是,代码2的数据段必须包含代码1的代码段和FLASH所占据的地址空间,代码2的代码段绝对不能与代码1的代码段有重叠),外部FLASH占据的地址空间为0x8000~0xFF7F,自举表的首地址从0x8000开始,并且SWWSR和BSCR的值分别为0x0E38和0x8806,程序入口地址为0x004089,代码1长度为16K字,代码1的存放起始地址为0x004000,那么代码2在FLASH中建立自举表的程序如下:
UINT I; //定义临时变量
UINT *Addr1,*Addr2; //定义临时地址指针变量
Addr1=(uint *)0xffff;
Word_Program(Addr1,0x8000); //在数据空间0xffff地址写自举表起始地址0x8000
Addr1=(uint *)0x8000; //自举表首地址
Word_Program(Addr1,0x10AA); //自举总线宽度为16位,即第一个字为0x10AA
Addr1++; //累为地址
Word_Program(Addr1,0x0E38); //SWWSR的值
Addr1++; //累加地址
Word_Program(Addr1,0x8806); //BRSC的值
Addr1++; //累加地址
Word_Program(Addr1,0); //程序入口地址XPC为0
Addr1++; //累加地址
Word_Program(Addr1,0x4089); //程序入口地址PC为0x4089
Addr1++; //累加地址
Word_Program(Addr1,0x4000); //代码长度为0x4000
Addr1++; //累加地址
Word_Program(Addr1,0); //目标程序入口地址XPC为0
Addr1++;
Word_Program(Addr1,0x4000); //目标程序入口地址PC为0x4000
Addr1+; //累加地址
Addr2=(uint *)0x4000 //代码1起始地址
for(I=0;I<0x4000;I++) //写代码1到FLASH,长度为16K字
Word_Program(Addr1++,*(Addr1++));
Word_Program(Addr1,0x0000); //自举表结尾的一个字写入0x0000,自举表建立结束
代码2除了上面的自举表的建立外还包括FLASH的擦除和自举表数据的校验。需要注意的是,在对FLASH进行写操作之前,必须对其进行擦除,擦除部分的程序可参考前面的Word_Program()子函数。
这样,通过简单的“两次下载法”,利用代码2将要脱机运行的代码1以自举表的格式写到FLASH存储器中,校验正确后DSP即可脱机工作了。
采用“两次下载法”利用DSP自身对FLASH进行编程,可实现DSP的并行自举。这种在系统编程的DSP自举实现方式简单灵活。文中给出的硬件电路仅适用于程序代码小于32K字的系统中。在一般DSP系统中,都会有FPGA等可编程器件,利用它们可以灵活地对FLASH进行分页操作。这样,在程序量超过32K字的情况下,此方法也适用。