DSP

DSP BootLoader(zz)

2019-07-13 10:31发布

      初学DSP时最头疼的事就是DSP的bootload问题,以前学51时只要把程序写好编译通过后就可以用烧写器直接将*.hex文件烧进单片机运行。但DSP内部不带FLASH RAM,它必须在复位期间将外部的程序加载到内部RAM之后才能运行。这有点像PC 的体系结构,PC 机中的引导加载程序由 BIOS(其本质就是一段固件程序)和位于硬盘 MBR 中的 OS Boot Loader(比如,LILO 和 GRUB 等)一起组成。BIOS 在完成硬件检测和资源分配后,将硬盘 MBR 中的 Boot Loader 读到系统的RAM 中,然后将控制权交给 OS Boot Loader。Boot Loader 的主要运行任务就是将内核映象从硬盘上读到 RAM 中,然后跳转到内核的入口点去运行,也即开始启动操作系统。我刚开始时就被这bootload搞的心焦如焚,仿真好的程序却不能脱机运行,最好还是老老实实看TI的DSP datasheet,经过一番周折总算搞定!为此我想把我的调试心得写出来与大家共享,一方面是避免初学者走弯路,另一方面是借此抛砖引玉望方家多斧正^_^。
      简单地说,bootloader就是在用户程序运行之前的一段小程序,通过这段小程序初始化硬件设备、建立内存空间的映射图,最终调用用户程序。这段小程序其实已固化在DSP芯片TMS320VC33内部ROM中,在TMS320C3X datasheet中有源码及功能流程图,我们只需知道它的功能流程即可。从流程图我们可以知道在DSP上电复位时只要DSP芯片引脚'MCBL/MP'为高电平,TMS320VC33就开始自动执行固化在内部ROM中的bootloader程序,然后根据外部中断引脚'INT3~INT0'判断用户程序的加载起始地址。
  管脚        电平                存储空间
  INT0        0                0x001000
  INT1        0                0x400000
  INT2        0                0xfff000
  INT3        0                串口       在我的系统应用中,我将程序存储在外部FLASH芯片39VF040中,它在系统中的起始地址为:0X400000,所以只要DSP复位时外部中断引脚'INT1'为低电平,bootloader程序就开始读取外部FLASH芯片39VF040中的用户程序并加载到DSP内部RAM中,加载完毕后就自动跳到用户程序的入口地址开始运行用户程序。从bootloader的流程图还可以知道,bootloadr加载用户程序时是有一定格式要求的,即存储在用户外部FLASH程序空间的数据结构的格式要求如下:
WORD        0        : 用户外部FLASH芯片数据宽度,如8,16,32位等
WORD        1        : 控制字,用来写入TMS320VC33的总线控制寄存器
WORD        2        : 数据块大小
WORD        3        :当前上载数据块将要装载到DSP内部RAM中的目标地址
WORD        4~N     :用户程序内容
      用户的程序分为多个数据块(因为DSP开发软件生成的目标文件是COFF格式),每块数据块起始都包含一个程序头,每个又包含两个内容:1、当前数据块大小,即32位格式的数据量。2、当前数据块在DSP内部RAM存储的起始地址。程序头之后就是用户的程序内容。
      讲到这里问题的关键就出来了:怎样产生这样的程序块呢?程序内容应该为哪种格式*.hex、*.bin、*.out?这也是我当初最头疼的问题。
      用TI公司的DSP开发软件Code Composer建立一个项目文件后,要做的第一件事就是编写*.cmd命令文件,命令文件有两个:一个是链接命令文件,另一个是boot引导表格式生成命令文件。       链接命令文件作用是分配各个程序段在DSP内部RAM中的存储位置,链接命令文件必须和项目文件名相同。例如项目online.mak的链接命令文件online.cmd如下所示:
-c //ROM初始化
-o online.out //产生online.out可执行文件
-m online.map //产生online.map映象文件
online.obj //链接的目标文件
-l rts30.lib //链入TMS320C3X运行支持库 MEMORY
{
 VECS: org=0x809fc1 len=0x3f //定义矢量的起始地址及空间的长度
 RAM0: org=0x809800 len=0x7c1 //定义堆栈起始地址及空间的长度
 RAM2: org=0x800000 len=0x8000 //定义用户程序数据空间
}
SECTIONS
{
 "vectors": load=VECS //将中断向量块安排在VECS空间
 .text:  load=RAM2 //将程序代码、常量、变量等数据块安排在RAM2空间
 .cinit:  load=RAM2
 .const:  load=RAM2
 .bss:  load=RAM2
 .stack:  load=RAM0 //将堆栈块安排在RAM0空间
}
      建立链接命令文件后,开发软件在对用户程序汇编链接生成目标文件的过程中,就会按照链接命令文件对输出的COFF格式的数据块自动选择存储器地址。
       boot引导表格式生成命令文件,这个文件名可以随意取,例如可取名为hex.cmd。先头讲到TMS320VC33的bootloader程序加载用户程序是有一定格式,boot引导表格式生成命令文件就是将用户的目标文件转换成符合要求的格式,举例如下:hex.cmd
online.out //要进行转换的目标文件
-map hex.map //生成映象文件
-boot //产生装载程序
-image //输出文件去掉地址映象
-i //建立INTEL十六进制文件的输出
-memwidth 8 //用户程序存储器的数据宽度
-cg 10e8h //总线控制字
-e 00803f86h    //程序装载完成后的执行地址即为_c_int00的地址,可查看online.map文件*/ ROMS //ROM的映射范围,及用户程序在外部FLASH中的地址空间
{
        FLASH1: org=0,len=10000h,romwidth=8,files={online1.hex}
        FLASH2: org=10000h,len=10000h,romwidth=8,files={online2.hex}
}
      写好格式转换命令文件后,在WINDOWS的命令提示符工具下用'cd'命令进入用户程序目标文件所在目录,然后运行hex30 hex.cmd即可根据格式命令文件hex.cmd的要求产生两个hex格式的文件online1.hex和online2.hex。其中hex30是DSP开发软件自带的程序。因为Intel格式中除了数据之外还有起始符、字节个数、起始地址、类型以及校验位等各种信息,并非纯粹数据的HEX格式表示。所以还不能直接烧进FLASH芯片,同样在命令提示符下运行hexbin程序,将online1.hex和online2.hex分别转换成online1.bin和online2.bin,就可得到纯粹数据格式的烧写文件,好了,只要把刚才两个文件烧进FLASH芯片,重启系统,OK!终于可以脱机运行程序了^_^!