ARM如何讀寫Flash
我在ARM上裸機。 不使用任何嵌入式操作系統(tǒng)。
本文引用地址:http://m.butianyuan.cn/article/201611/316653.htm我的引導(dǎo)程序把我的程序放在 0x00000000,(這個地方是Flash) 在初始化的時候,我把代碼區(qū)的所有代碼copy到SDRAM里面去。然后跳到SDRAM( 0xc0000000 )里面去運行。此時我能否往 0x00000000及其后的address里面寫數(shù)據(jù)?
2.
不可以,在Flash 中執(zhí)行的代碼不可以改寫Flash的內(nèi)容,你可以在SDRAM中寫FLASH的內(nèi)容。參考bolb和intel strongarm的dm 程序
3.
應(yīng)該這樣說,flash由于本身的技術(shù)原因,擦寫過程中不能同時讀。所以,你不能在運行(讀代碼)的同時去改寫同一個flash芯片中的內(nèi)容。但你說的跳到sdram中去運行并改寫flash應(yīng)該是可以的。
還有,flash的寫操作不同于ram,是需要通過一系列的特定操作才完成的。這個你可以仔細看看flash芯片的手冊,不同的芯片可能會有區(qū)別。blob中可以找到具體的程序例子參考。
4.
我就是要擦除Flash. 然后寫Flash. 我現(xiàn)在是把代碼全部copy到SDRAM里面去。然后跳到SDRAM里面去運行。我現(xiàn)在也已經(jīng)這樣做了。 但是我在SDRAM里面運行,而且要寫Flash(包括讀ID ) 的時候。系統(tǒng)運行就亂了。 可能產(chǎn)生了異常。我不知道這個怎么解決?
5.
如果你確認程序能夠正確進入sdram運行了,最可能出問題的就是這段程序中的跳轉(zhuǎn)語句。你的跳轉(zhuǎn)是相對跳轉(zhuǎn)還是絕對跳轉(zhuǎn)?如果是絕對跳轉(zhuǎn),編譯的時候編譯器不會知道你以后會把程序挪地方,跳轉(zhuǎn)的目的地址還是在flash中。這樣就出錯了
6.
Sorry, 前面說錯了。是跳到SRAM里面。 不過差不多。
跳轉(zhuǎn)到SRAM里面后,如果不操作Flash. 到目前為止,好像沒有什么問題。都能正常運行。 但是只要操作Flash,就會死!
什么是相對跳轉(zhuǎn)?? 什么是絕對跳轉(zhuǎn)??
我用的指令是:
;;這兒是copy_rom_data
bl copy_romdata_to_sram
;; 這兒是跳轉(zhuǎn)到sram 里面去。
ldr pc, =0x600000ac
7.
機器級b和bl指令有一個限制:跳轉(zhuǎn)的范圍在當(dāng)前指令的+/-32Mb范圍內(nèi)。為什么?因為跳轉(zhuǎn)的目的地是以當(dāng)前的指令為起點的。這就是相對(于當(dāng)前地址)的跳轉(zhuǎn)。絕對跳轉(zhuǎn)就是直接指定目的地址的跳轉(zhuǎn),比如你直接給pc賦一個立即數(shù)值,就是絕對跳轉(zhuǎn)。你也可以用bx/blx Rm來實現(xiàn)絕對跳轉(zhuǎn)。
我其實對arm指令不熟,你自己琢磨一下吧。我只是說明了一種容易出現(xiàn)的錯誤,希望對你有幫助。
8.
設(shè)置tlb表了么?
在打開mmu之前,把00000000物理地址映射到另外一個地址例如e0000000,然后打開mmu,對e0000000操作,就是對flash操作
9.
沒有。 怎么設(shè)置TLB表? 能否給我一個sample code ?
10.
操作死機原因可能是:
1.在系統(tǒng)開始時,將Flash ROM 的映射屬性設(shè)置為uncache和unbuffer.參考Windows CE的Source Code
2.連接時的數(shù)據(jù)段,代碼段的地址是否正確.參考blob
3.數(shù)據(jù)段和bss段是已經(jīng)初始化正確.參考blob
4.如果還是失敗,初始化代碼用Multi ICE 拷貝到 SDRAM中直接調(diào)試運行。
注意:
1.最好不要使用ARM 提供的集成開發(fā)環(huán)境
2.再看一邊L7205的參考手冊。
3.看原理圖
4.看flash rom 的資料,如sst 、amd的源代碼
11.
你的中斷向量怎么處理的?有沒有把中斷向量映射到你的SRAM中去?
12.
因為程序運行中我不修改任何中斷向量. 我需要映射到SRAM去嗎?
----------------
不是說你是否修改中斷向量,而是說在你的代碼工作過程中會不會產(chǎn)生中斷
----------------
我的代碼在工作過程中 不產(chǎn)生中斷。因為我屏蔽了!
如果產(chǎn)生中斷會怎么樣?
---------------
如果發(fā)生中斷,那么cpu會去中斷向量表中訪問相應(yīng)的中斷向量并執(zhí)行,而此時你的Flash處于寫狀態(tài)
13.
只要寫Flash. 程序就不知道跑到什么地方去了。 我用的是Sharp的Flash. 讀廠家的ID 命令是 0x90. 寫這個命令時,就發(fā)生錯誤了。表現(xiàn)為程序沒有繼續(xù)運行下去。因為Flash位于0x0000000。
14.
你是否使用L7200或是L7205,如果是請注意,SRAM的大小和你的代碼大小
15.
我用的是Cirrus Logic EP7312. 我的代碼大小沒有超過SRAM的大小不到5K
16.
她的看法跟我一樣,你很可能有絕對跳轉(zhuǎn)的指令,使得你的程序運行到中途又跳回到flash中去了。
把你的代碼貼出來看看。應(yīng)該不長吧。
你用了blob嗎?
17.
中途跳轉(zhuǎn)到Flash中去了??? 但是如果我把讀Flash ID這段代碼注釋掉. 程序運行很正常阿!? 看看我這段代碼:
下面這段是初始化中的程序片斷:
。。。。。。。。。。
IMPORT Move_Program
BL Move_Program
ldr pc, =0x600000b8 ; 跳到C的入口處。
.........................
下面一段代碼是讀Flahs的ID的函數(shù):
void CheckFlash(void)
{
unsigned long* addr = (unsigned long*)0x00000000;
unsigned long MID;
unsigned long DeviceID;
*addr = 0x00900090;
MID = *addr;
if( MID == 0x00B0000B )
{
//display Manufacture ID
}
addr+=2;
DeviceID = *addr;
if( DeviceID == 0x00D000D0 )
{
// display "Device ID"
}
}
下面的代碼是復(fù)制程序到 SRAM.
void Move_Program(void)
{
unsigned long* rom_adr=(unsigned long*)0x00000000;
unsigned long* ram_adr=(unsigned long*)0x60000000;
int i;
int rom_size;
rom_size = (int)(rom_data_base-0x00000000);
for( i=0; i
{
*ram_adr++ = *rom_adr++;
}
}
18.
BL Move_Program
這句可是要返回到flash中的
--------------
這條指令( BL Move_Program ) 當(dāng)然回到Flash. 他的下條指令 : ldr pc, =0x600000b8 才是真正轉(zhuǎn)到SRAM里面去執(zhí)行。
-------------
19.
你在進入c代碼后到讀flash之前都做了那些事?
另外你可以試試能不能從flash中直接讀數(shù)據(jù)?
20.
在讀flash前,我做了LCD的初始化和相關(guān)的測試。 另外我可以直接讀flash中的數(shù)據(jù)(包括程序代碼等等)。
21.
MID = *addr;
if( MID == 0x00B0000B )
{
//display Manufacture ID
}
上面這段能顯示出來嗎?(應(yīng)該可以吧)
addr+=2;
這里,地址+2,好象不對吧,你的可是32位數(shù)據(jù)總線啊
DeviceID = *addr;
if( DeviceID == 0x00D000D0 )
{
// display "Device ID"
}
}
我想這里就飛了吧
給你一段讀的代碼
WRITE_FLASH(0x00000000,0x00980098);
OffSet=0x10<<2;
ReadData=READ_FLASH(0x0+OffSet);
//屬性Q
OffSet=0x11<<2;
ReadData=READ_FLASH(0x0+OffSet);
//屬性“R“
OffSet=0x12<<2;
ReadData=READ_FLASH(0x0+OffSet);
//屬性"Y“
22.
MID = *addr;
if( MID == 0x00B000B0 )
{
//display Manufacture ID
}
到這兒根本無法顯示!!
下面這個你說得對。
可以改成 : addr++; addr++;
23.
你用的什么編譯器?
unsigned long是多少位的?
還有,你確定你的CPU的MID是0x00B000B0?
最后,你用什么顯示ID的,最好用串口,如果是LCD的話,
可能是顯示語句造成的錯誤
---------------------------
我用ARM SDT 2.50.
unsigned long 是32Bit. unsigned int 也是 32Bit.
不是CPU 的MID. 是Flash的 Manufacture ID . 我確信 它是:
0x00B000B0
我用LCD顯示ID. 顯示驅(qū)動是我自己寫的。能正常顯示。
24.
把check_flash的匯編代碼貼出來。c程序里面看不出具體有了什么跳轉(zhuǎn)方式。
舉個例子:(用的是偽代碼)
jump 0x00000300
這樣一句語句不管你把它拷貝到哪里,他都一定會執(zhí)行到0x300這個地址去的.如果你的程序中有這樣的跳轉(zhuǎn),因為編譯的時候編譯器不知道你會把它拷貝到別的地方,必然填充的是當(dāng)前程序段內(nèi)的地址.而這個地址不會隨著你的代碼的搬移而改變.那么執(zhí)行到這一句的時候就又跳回去了.
代碼本身是沒錯的,錯就錯在它是不可移動的.
25.
我的Check_flash本來就是用C寫的。 因為我只是想簡單測試一下在我把ROM CODE搬到SRAM區(qū)后,能否操作Flash.
所以就那么簡單。
我想在編譯連接階段不會把具體的段地此也放在最后的代碼中。它總是在運行的時候把所在段的地址和它相加就是了。如果真的像你所說,那么我前面的代碼(在操作Flash之前)一定不能運行。但是實際情況正像我所料。我的LCD能工作。我的蜂鳴器能響。我的LED能閃爍。
26.
你還是沒有懂我的意思.
只要你的sram中能運行程序,它就可以寫flash.
如果不能,一定是你的程序出了問題.最常見的就是真正的"自己寫自己".因為編程時,flash的狀態(tài)不是普通的讀狀態(tài),所以處理器讀不到程序代碼,當(dāng)然就出錯了.
如果你做的都是對的,那么為什么會出錯呢?
你說過,你是在沒有操作系統(tǒng)的裸機上運行的,那么你的代碼一定不是一個可執(zhí)行程序,而是真正的機器代碼段.除了程序自己,沒有人會幫他設(shè)置什么運行時的段地址的.
沒有絕對跳轉(zhuǎn)的程序是可以移動的,有絕對跳轉(zhuǎn)的程序是不可移動的.
27.
你的意思是懷疑我的程序是否真的在SRAM里面運行? 還是懷疑我的Check_Flash有問題?
1)。 在Flash里面運行程序和在SRAM運行程序的速度是有很大差別的。 可以從運行的情況可以看出來。這點基本可以確定程序真的在SRAM運行。(否則也無法逾越這條指令:
ldr pc, =0x600000b8 )
2)。Check_Flash 真的有問題嗎? 我真的是用C寫的。
我再檢查他編譯以后的匯編代碼看看。
28.
那,下面就是用armcc 編譯產(chǎn)生的asm代碼。
====================================
CheckFlash
MOV a2,#0x90
ADD a2,a2,#0x900000
MOV a1,#0
STR a2,[a1,#0]
MOV a2,#0
ADD a3,pc,#L000198-.-8
B LCDDrawStr
L000198
DCB "Unkn"
DCB "ow F"
DCB "LASH"
DCB " DEV"
DCB "ICE