DSP程序nandflash固化(四)——程序固化调试方法

  在介绍完AIS文件制作后,为确保DSP能正常启动,还需要进行调试。在这个过程中,有很多细节需要注意,笔者在调试过程中层遇到了很多问题,下面介绍笔者在调试AIS启动过程中的调试方法,读者可以参考。
  要确保DSP能从NANDFLASH启动,并执行AIS脚本,首先要保证硬件上的连接正确,这里需要设置DSP的启动模式为NANDFLASH启动,从EMIFA的CS2启动,那么如何查看DSP是从这里启动的呢,在DSP断电重启后,在CCS中连接仿真器,不执行程序直接可以查看DSP内部寄存器的值,这里需要查看BOOTCFG,确保在上电之后是NANDFLASH启动模式,智力BOOTCFG字段MODE=0x0111,另外,如果AIS脚本执行过程中遇到了错误,比如没有找到魔术字,指令使用不正确等,可以查看BOOTCMPLT寄存器的ERR字段,只有当ERR=0时表示AIS启动正常,如果不是可以参照下表进行错误定位。
Table 1. Debugging Boot Failures
 Value  Name  Description
0x1  ERR_UNKNOWN_COMMAND An invalid AIS command was received
  0x2 ERR_BAD_MAGIC_NUMBER The AIS magic number was not detected in UART boot mode
  0x3 ERR_TRANSMIT_SYNC Not used
  0x4 ERR_BAD_CRC Getting PCI Autoinit data failed, or exceeded maximum CRC failure in AIS parsing
  0x5 ERR_INVALID_ADDRESS_SIZE Invalid specified address width in first word of SPI master boot
  0x6 ERR_UNSUPPORTED_BOOTMODE The various boot pin configurations are invalid
  0x7 ERR_TIMEOUT_WAITING_FOR_HOST Timeout occurred in sending or receiving data (UART, PCI,UHPI modes)
  0x8 ERR_TIMEOUT_I2C_BUS_BUSY Timeout waiting for bus becoming free in I2C master boot
  0x9 ERR_TIMEOUT_MCBSP_SPI_RECEIVE Receive timeout in SPI master boot mode
  接下来调试解析COFF文件过程,首先查看文件头,可选头两个结构体数据。按二进制读取方式读取到.out文件的头28字节如下:
DSP程序nandflash固化(四)——程序固化调试方法 - 亦梦云烟 - 亦梦云烟的博客
 
  可以看到,fileSecNum=23,说明共有23个段落,但一般.cmd文件中没有这么段,说明处理定义的字段,还有些其他用途的段落页加入到文件中,在下载前需要剔除掉。fileByte=28,这说明该文件有可选文件头,fileTargetID=0x0099,前面提到过,如果不确定文件头解析对不对,可以参考这个值是不是0x0099,因为工程时使用C6000的芯片,那么这个值必然是0x0099如果不是肯定就是解析出错了。其他的字段基本不会用到。
  解析可选文件头:
DSP程序nandflash固化(四)——程序固化调试方法 - 亦梦云烟 - 亦梦云烟的博客
 
  着重查看optionExecut=145056,大概计算一下:145056/1024=141Kb,这就是代码的大小,在下载过程中需要使用至少这么大的FLASH空间,另外optionEntry=0x00023060有点不想程序入口地址,原来这是在定义结构体是定义的是int型数据,在解析时按照4字节整型读取,但实际上这个值是由两个16位地址组成,每个16位数据按小端模式存储,这样一来无论按照小端还是大端都无法解析正确,所以正能按照前面的教程中提到的方法进行解析。
     剩下的就是解析所有的段落了,首先需要各个段落头,然后根据段落头读取文件中的原始数据,先不急于整个文件的读取,首先一个段落头的查看,下面选取了几个段落:
第一段:
DSP程序nandflash固化(四)——程序固化调试方法 - 亦梦云烟 - 亦梦云烟的博客
 
第二段:
DSP程序nandflash固化(四)——程序固化调试方法 - 亦梦云烟 - 亦梦云烟的博客
 
第三段:
DSP程序nandflash固化(四)——程序固化调试方法 - 亦梦云烟 - 亦梦云烟的博客
第四段:
DSP程序nandflash固化(四)——程序固化调试方法 - 亦梦云烟 - 亦梦云烟的博客
 
第五段
DSP程序nandflash固化(四)——程序固化调试方法 - 亦梦云烟 - 亦梦云烟的博客
 
  注意到secCharacter在CCS上显示的是字符串的地址,要查看字符串的内容需要另外定义一个表达是,这里定义为
(char*)Sec_header->secCharacter
  意思就是显示字符串地址的内容,可以看到,运行完23次循环后,每个段落都解析正确(段落名都正确了还能有错吗?),在运行过程中建议读者在细心的查看一下secFlag的值,最好转化成二进制,将所有的值与段名都列举出来你,最后你将会发现,需要下载的段落第6位和第7位都为1,这就是为什么程序中有一句判断将secFlag于0x60进行按位与操作。
     下面分析一下段落内容的提取,首先笔者将前几个段落的重要字段列举到一个表格中:
段序号
段中的主要字段
字段值
说明
1
段名
   
 
物理地址
0
 
 
大小
36
 
 
段数据指针
1154
=50+23*48
 
段标识
0x10
 
2
段名
.text
这个就是代码要存储的
 
物理地址
32
 
 
大小
123168
 
 
段数据指针
1190
=1154+36
 
段标识
0x520
 
3
段名
.const
 
 
物理地址
152424
 
 
大小
2396
 
 
段数据指针
124358
=1190+123168
 
段标识
0x340
 
4
段名
.data
已初始化数据段
 
物理地址
8
 
 
大小
0
 
 
段数据指针
0
 
 
段标识
0x380
 
5
段名
.bss
未初始化数据段
 
物理地址
157392
 
 
大小
332
 
 
段数据指针
0
 
 
段标识
0x380
 
6
段名
.cinit
 
 
物理地址
140016
 
 
大小
12404
 
 
段数据指针
126754
=124358+2396
 
段标识
0x340
 
7
段名
.pinit
 
 
物理地址
0
 
 
大小
0
 
 
段数据指针
139158
 
 
段标识
0x210
 
  注意总结,后面的段落的物理地址,段数据指针,段名之间的关系,下面给出几个计算公式:
段落数据指针1=sizeof(FILE_HEADER)+sizeof(OPTIONAL_FILE_HEADER)+
  fileHeader->secNum*sizeof(SECTION_HEADER );
段落数据指针2=段落数据指针1+secHeader->secPhyAddr;
  依次递推可以得到所有的数据。
  那么在需要下载那些段落呢,主要包括以下几个段落:
.text
.const
.data
.cinit
.switch
.tables
.vectors
用户自定义字段
  到这一步如果基本上没什么问题记下来就可以解析全部的.out文件到CCS了,在解析之前,我们来看看DSP程序在内存中是什么样的,debug连接DSP电路板,读取.text代码段处的地址,查看内存地址为.text定义的地址,笔者定义的是0x80400000,得到的数据为:
DSP程序nandflash固化(四)——程序固化调试方法 - 亦梦云烟 - 亦梦云烟的博客
 
  然后通过解析AIS,查看AIS的.text处的内存内容:
DSP程序nandflash固化(四)——程序固化调试方法 - 亦梦云烟 - 亦梦云烟的博客
 
  在第一行第六个数据开始是.text解析的AIS,在查看内存时,需要根据.text段落在.out文件中的位置来计算保存为AIS后所处的内存起始地址,可以看到,上下数据完全一致,依照此方法可以查看其它各段的情况,。
  当AIS脚本制作完成,就可以将AIS文件直接烧写进NANDFLASH了:
readaddr=0;
//writeblock=1;
writepage=0;
 
while (readaddr < AISsize)
{
     errors += EVM6424_NANDFLASH_writePage( writeblock,writepage, ( Uint32 )(AISbuffer + readaddr) );
 
     readaddr += NAND_PAGESIZE;
     writepage ++;
     if (writepage >= NAND_PAGES_PER_BLOCK)
     {
         writepage=0;
         writeblock++;
     }
}
  还是要强调一点,根据TI的手册,AIS文件必须放在第一块以后,至于为什么就不得而知了,照着做就对了。
  最后在魔术字后面填写对应的块大小和搜索起始位置即可:
((int *)AISbuffer)[1] = (AISsize/NAND_PAGESIZE+1);
((int *)AISbuffer)[2] = writeblock;
((int *)AISbuffer)[3] = 0;
  好了,可以重启上电了,当出现程序无法boot后,请读者再详细看一遍TI的手册或者本教程。
参考文献:
posted @ 2016-11-18 10:39  亦梦云烟  阅读(2900)  评论(0编辑  收藏  举报