TMS320C6000DSP自动引导的方法和编程实现
3.1 命令文件
利用TI的代码产生工具,可以按照图2所示的步骤生成可执行文件(.out)。
汇编器接收汇编优化器或编译器产生的.asm文件,经过汇编后产生可重新分配地址的COFF格式的目标文件.obj。该格式文件包含了汇编器所生成的各个段(如表1所示),命令文件就是指导连接器如何将各段分配到相应的存储器中。编写命令文件时,有一点需要注意,那就是在很多情况下需要对某段说明两个不同的地址:加载地址和运行地址。加载地址决定了二进制程序代码的存储位置和程序的引导地址,但在运行过程中对于该段的任何引用则是以它的运行地址作为参考的。因此,当用户对某段分别说明了加载地址和运行地址时,只有将该段从加载地址复制到运行地址上,该段才可以被访问。
表1 编译器产生的默认代码段和数据段
段 名 | 段数据 | 段说明 | 建议分配方法 |
.text | 代码段 | 程序代码 | Load=ROM,Run=RAM |
.switch | 初始化数据段 | Switch语句跳转表 | Load=ROM,Run=RAM |
.bss,.far | 未初始化数据段 | c变.运行时从.cinit中自动初始化 | Load=Run=RAM |
.cinit,.pinit | 初始化数据段 | C变量和函数初始化表 | Load=Run=ROM |
.const | 初始化数据段 | 常量 | Load=Run=ROM |
.data,.cio,.sysmem | 未初始数据段 | 其它的.data段 | Load=Run=RAM |
在命令文件中,合理地分配.cinit段对于整个程序的正确运行起到关键的作用。在TI可查阅的文档和相关网站上,很少有涉及这方面内容的文章。经过反复实践,笔者取得了处理.cinit段的一些经验,请大家在下面的命令文件和用户引导程序中注意该段的处理过程。
下面是在实践中编写的命令文件(.cmd)
-c ;说明复位后的初始化方式
-stack 0x5000 ;说明堆的大小
-heap 0x400 ;说明栈的大小
-l rts6701.lib ;说明程序中引用的库文件
MEMORY ;将整个存储器分成具有不同名称的存储区域
{
VECS: origin = 0x00000000, len = 0x00000200
PMEM: origin = 0x00000200, len = 0x0000d000
PCINIT: origin = 0x0000d200, len = 0x00001e00
CE1VECS: origin=0x01400000, len = 0x00000200
CE1PMEM:origin = 0x01400200, len = 0x0000d000
CE1INIT: origin = 0x0140d200, len = 0x00001e00
CE3: origin = 0x03000000, len = 0x01000000
DRAM: origin = 0x80000000, len = 0x00010000
}
SECTIONS ;说明目标文件中各段的加载地址和运行地址
{
.myBootCode :load=CE1VECS, run=VECS
;用户的引导代码段
.text : load=CE1PMEM, run=PMEM
.cinit : load=CE1INIT, run=DRAM
;装载到ROM中,在片内数据区运行
.const > DRAM
.data > DRAM
.bss > DRAM
.sysmem > DRAM
.stack > DRAM
.far > CE3
}
3.2 编写用户引导代码
DSP加电复位后,自动从CE1空间中拷贝64K数据(程序代码)到地址0处,然后从0地址处开始执行指令。由于在命令文件中,将.cinit装载到外部ROM中,但其运行地址却在片内数据区,所以采用下面这段程序,其主要作用是将Cinit从外部ROM中搬到片内数据区,使其能在C编程环境下进行正确的初始化工作,保证程序的顺利进行。
.sect “.myBootCode”
;将用户引导代码分配到
myBootCode段中
.global myBootCode
.ref _c_int00
;C程序的入口地址
myBootCode
......
;EMIF寄存器和DMA寄存器初始化
;使用DMA方式将以原地址0x0000d200开始的0x380长的存储空间拷贝到目标地址上
mvkl DMA0_SRA ,A5 ;装载原地址0xd200
mvkl 0x0000d200, B4
mvkh DMA0_SRA ,A5
mvkh 0x0000d200m B4
stw B4,*A5
mvkl DMA0_DSA, A5 ;装载目标地址0x80000000
mvkl 0x80000000, A4
mvkh DMA0_DSA, A5
mvkh 0x80000000, A4
stw A4,*A5
mvkl DMA0_CNT A5 ;装载数据长度0x380(这个长度可以通过查看.map文件中.cinit的长度获得)
mvkl 0x00000380, B1
mvkh DMA0_CNT ,A5
mvkh 0x00000380, B1
;启动DMA开始传输
wait:
mvkl DMA0_PCR ,A5
mvkh DMA0_PCR ,A5
ldw *A5 ,B2
mvkl 0x0000000c,A5
mvkh 0x0000000c ,A5
and A5,B2,B2
b2 b wait
nop 5
;传输结束后,跳转到C程序的入口地址c_int00处,
开始执行程序
mvkl .s2 _c_int00B0
mvkh .s2 _c_int00B0
B .s2 B0
nop 5