最近在調試2410的過程中,經常出現(xiàn)程序跑飛的現(xiàn)象,跟蹤進行后發(fā)現(xiàn)。。。所以決定把它記錄下來。
現(xiàn)象:
調試用的是技創(chuàng)ARM仿真器(兼容multi-ICE)和ADS1.2,板子外擴NandFLASH(裝有Bootload)和SDRAM。當將程序燒到FLASH運行時會出現(xiàn)無規(guī)律的死機。用仿真器仿真時情況是這樣:當CPU復位后,第一次裝載程序執(zhí)行時,情況與燒到FLASH運行時一樣。但如果將運行的程序停下來(無論有無跑飛情況下),再重新裝載(CPU復位后第二次及以后裝載)時,運行到下述程序中的“msr cpsr_cxsf,r1”就跑飛。
bic r0,r0,#MODEMASK | NOINT ;IRQ、FIQ位清0
orr r1,r0,#SVCMODE
msr cpsr_cxsf,r1 ;SVCMode ;充許中斷后,使程序跑飛
ldr sp,=SVCStack
過程:
上面是啟動代碼中初始化堆棧處的程序,就是這里允許了中斷后,產生中斷才使程序跑飛的。打開MEMORY窗口,查看各中斷掛起寄存器,發(fā)現(xiàn)有定時器等中斷請求,此時我直接在MEMORY窗口中給該標志位寫“1”清除它們,INTPEND中的能清除,SRCPND清不掉,奇怪?原來目標CPU的定時器還在不停的運行著呢(習慣了51仿真的同志要注意這一點,哈哈!包括我)!剛一清除,又立即溢出了,盡管正處在停止運行的仿真狀態(tài)?,F(xiàn)在可以解釋為什么CPU復位后第一次裝載運行不會使程序跑飛了,因為復位后,各寄存器都變成初始態(tài),定時器也還沒有開啟,所以也就不會觸發(fā)中斷。而當開啟了定時器后,再裝載程序時,定時器已經溢出,觸發(fā)了中斷。那么為何一進中斷就會使程序跑飛呢?于是就在命令窗口中輸入br 0x18,再執(zhí)行程序,原來IRQ中斷入口0x18的內容已從原先的0xea000047被改成了0x6b736564,反匯編代碼如下:
00000018 [0x6b736564] * blvs 0x1cd95b0
CPU復位后的代碼如下:
00000018 [0xea000047] * b 0x13c
??!這怎么能被改掉!這不是NandFLASH的內容嗎?接著我就用MEMORY窗口觀察該處,再單步執(zhí)行我的程序,果然跟蹤到了修改該處的程序,可是沒有寫NandFLASH的操作,源程序如下:
typedef struct software_config_system
{
int software_flag;
CHAR curfont[20];
。。。。。。
} software_config, *s_config; //定義數(shù)據(jù)結構及其指針
unsignedCHAR InitsoftDescription(void)
{
if (s_config->software_flag != 0x2)
{
s_config->software_flag = 0x2; //給指針指向的地址處賦值
memcpy(s_config->curfont, "hanzi", 5);
。。。。。。
}
}
原來是定義了一個全局的結構指針變量(s_config),由于沒有對它進行賦值,而它默認的初始值為0,所以對他進行讀寫,也就對0x0開始處的地址進行讀寫。而且此時這段區(qū)間的NANDFLASH已被映射成Boot internelSRAM了,所以可以隨機讀寫(這點一定要注意)。
總結:
1.在仿真情況下(即使停止程序的運行),目標CPU的各外圍還是在工作的,如定時器等。
2.當將系統(tǒng)設計成NANDFLASH啟動時,0x0開始處的4K地址空間已是CPU的內部SRAM了,可以像其它RAM一樣隨意讀寫,此時定義全局的指針變量時,一定要記得賦值,否則就會修改這部分的代碼。
3.在用仿真器仿真時,可以在初始化堆棧的前面加一些關閉定時器及清中斷標志等代碼,以免在沒有復位CPU的情況下,程序還沒執(zhí)行到main函數(shù)就頻繁產生中斷。