在介紹完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字節如下:

可以看到,fileSecNum=23,說明共有23個段落,但一般.cmd文件中沒有這么段,說明處理定義的字段,還有些其他用途的段落頁加入到文件中,在下載前需要剔除掉。fileByte=28,這說明該文件有可選文件頭,fileTargetID=0x0099,前面提到過,如果不確定文件頭解析對不對,可以參考這個值是不是0x0099,因為工程時使用C6000的芯片,那么這個值必然是0x0099如果不是肯定就是解析出錯了。其他的字段基本不會用到。
解析可選文件頭:

着重查看optionExecut=145056,大概計算一下:145056/1024=141Kb,這就是代碼的大小,在下載過程中需要使用至少這么大的FLASH空間,另外optionEntry=0x00023060有點不想程序入口地址,原來這是在定義結構體是定義的是int型數據,在解析時按照4字節整型讀取,但實際上這個值是由兩個16位地址組成,每個16位數據按小端模式存儲,這樣一來無論按照小端還是大端都無法解析正確,所以正能按照前面的教程中提到的方法進行解析。
剩下的就是解析所有的段落了,首先需要各個段落頭,然后根據段落頭讀取文件中的原始數據,先不急於整個文件的讀取,首先一個段落頭的查看,下面選取了幾個段落:
第一段:

第二段:

第三段:

第四段:

第五段

注意到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,得到的數據為:

然后通過解析AIS,查看AIS的.text處的內存內容:

在第一行第六個數據開始是.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的手冊或者本教程。
參考文獻:
1. COFF文件分析提取器