1.
我在ARM上裸机。 不运用任何嵌入式操作体系。
我的引导程序把我的程序放在 0x00000000,(这个当地是Flash) 在初始化的时分,我把代码区的一切代码copy到SDRAM里边去。然后跳到SDRAM( 0xc0000000 )里边去运转。此刻我能否往 0x00000000及这今后的address里边写数据?
2.
不能够,在Flash 中履行的代码不能够改写Flash的内容,你能够在SDRAM中写FLASH的内容。参阅bolb和intel strongarm的dm 程序
3.
应该这样说,flash由于自身的技能原因,擦写过程中不能一起读。所以,你不能在运转(读代码)的一起去改写同一个flash芯片中的内容。但你说的跳到sdram中去运转并改写flash应该是能够的。
还有,flash的写操作不同于ram,是需求经过一系列的特定操作才完结的。这个你能够细心看看flash芯片的手册,不同的芯片或许会有差异。blob中能够找到详细的程序比方参阅。
4.
我便是要擦除Flash. 然后写Flash. 我现在是把代码悉数copy到SDRAM里边去。然后跳到SDRAM里边去运转。我现在也现已这样做了。 可是我在SDRAM里边运转,并且要写Flash(包含读ID ) 的时分。体系运转就乱了。 或许发生了反常。我不知道这个怎样处理?
5.
假如你承认程序能够正确进入sdram运转了,最或许出问题的便是这段程序中的跳转句子。你的跳转是相对跳转仍是肯定跳转?假如是肯定跳转,编译的时分编译器不会知道你今后会把程序挪当地,跳转的意图地址仍是在flash中。这样就犯错了
6.
Sorry, 前面说错了。是跳到SRAM里边。 不过差不多。
跳转到SRAM里边后,假如不操作Flash. 到目前为止,如同没有什么问题。都能正常运转。 可是只需操作Flash,就会死!
什么是相对跳转?? 什么是肯定跳转??
我用的指令是:
;;这儿是copy_rom_data
bl copy_romdata_to_sram
;; 这儿是跳转到sram 里边去。
ldr pc, =0x600000ac
7.
机器级b和bl指令有一个约束:跳转的规模在当时指令的+/-32Mb规模内。为什么?由于跳转的意图地是以当时的指令为起点的。这便是相对(于当时地址)的跳转。肯定跳转便是直接指定意图地址的跳转,比方你直接给pc赋一个当即数值,便是肯定跳转。你也能够用bx/blx Rm来完成肯定跳转。
我其实对arm指令不熟,你自己揣摩一下吧。我仅仅说明晰一种简略呈现的过错,期望对你有协助。
8.
设置tlb表了么?
在翻开mmu之前,把00000000物理地址映射到其他一个地址例如e0000000,然后翻开mmu,对e0000000操作,便是对flash操作
9.
没有。 怎样设置TLB表? 能否给我一个sample code ?
10.
操作死机原因或许是:
1.在体系开始时,将Flash ROM 的映射特点设置为uncache和unbuffer.参阅Windows CE的Source Code
2.衔接时的数据段,代码段的地址是否正确.参阅blob
3.数据段和bss段是现已初始化正确.参阅blob
4.假如仍是失利,初始化代码用Multi ICE 仿制到 SDRAM中直接调试运转。
留意:
1.最好不要运用ARM 供给的集成开发环境
2.再看一边L7205的参阅手册。
3.看原理图
4.看flash rom 的材料,如sst 、amd的源代码
11.
你的中止向量怎样处理的?有没有把中止向量映射到你的SRAM中去?
12.
由于程序运转中我不修正任何中止向量. 我需求映射到SRAM去吗?
—————-
不是说你是否修正中止向量,而是说在你的代码作业过程中会不会发生中止
—————-
我的代码在作业过程中 不发生中止。由于我屏蔽了!
假如发生中止会怎样样?
—————
假如发生中止,那么cpu会去中止向量表中拜访相应的中止向量并履行,而此刻你的Flash处于写状况
13.
只需写Flash. 程序就不知道跑到什么当地去了。 我用的是Sharp的Flash. 读厂家的ID 指令是 0x90. 写这个指令时,就发生过错了。表现为程序没有持续运转下去。由于Flash坐落0x0000000。
14.
你是否运用L7200或是L7205,假如是请留意,SRAM的巨细和你的代码巨细
15.
我用的是Cirrus Logic EP7312. 我的代码巨细没有超越SRAM的巨细不到5K
16.
她的观点跟我相同,你很或许有肯定跳转的指令,使得你的程序运转到半途又跳回到flash中去了。
把你的代码贴出来看看。应该不长吧。
你用了blob吗?
17.
半途跳转到Flash中去了??? 可是假如我把读Flash ID这段代码注释掉. 程序运转很正常阿!? 看看我这段代码:
下面这段是初始化中的程序片断:
。。。。。。。。。。
IMPORT Move_Program
BL Move_Program
ldr pc, =0x600000b8 ; 跳到C的入口处。
…………………….
下面一段代码是读Flahs的ID的函数:
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”
}
}
下面的代码是仿制程序到 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 ) 当然回到Flash. 他的下条指令 : ldr pc, =0x600000b8 才是真实转到SRAM里边去履行。
————-
19.
你在进入c代码后到读flash之前都做了那些事?
其他你能够试试能不能从flash中直接读数据?
20.
在读flash前,我做了LCD的初始化和相关的测验。 其他我能够直接读flash中的数据(包含程序代码等等)。
21.
MID = *addr;
if( MID == 0x00B0000B )
{
//display Manufacture ID
}
上面这段能显现出来吗?(应该能够吧)
addr+=2;
这儿,地址+2,好象不对吧,你的可是32位数据总线啊
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. 显现驱动是我自己写的。能正常显现。
24.
把check_flash的汇编代码贴出来。c程序里边看不出详细有了什么跳转办法。
举个比方:(用的是伪代码)
jump 0x00000300
这样一句句子不论你把它仿制到哪里,他都必定会履行到0x300这个地址去的.假如你的程序中有这样的跳转,由于编译的时分编译器不知道你会把它仿制到其他当地,必定填充的是当时程序段内的地址.而这个地址不会跟着你的代码的搬移而改动.那么履行到这一句的时分就又跳回去了.
代码自身是没错的,错就错在它是不行移动的.
25.
我的Check_flash原本便是用C写的。 由于我仅仅想简略测验一下在我把ROM CODE搬到SRAM区后,能否操作Flash.
所以就那么简略。
我想在编译衔接阶段不会把详细的段地此也放在最终的代码中。它总是在运转的时分把地点段的地址和它相加便是了。假如真的像你所说,那么我前面的代码(在操作Flash之前)必定不能运转。可是实际状况正像我所料。我的LCD能作业。我的蜂鸣器能响。我的LED能闪耀。
26.
你仍是没有懂我的意思.
只需你的sram中能运转程序,它就能够写flash.
假如不能,必定是你的程序出了问题.最常见的便是真实的”自己写自己”.由于编程时,flash的状况不是一般的读状况,所以处理器读不到程序代码,当然就犯错了.
假如你做的都是对的,那么为什么会犯错呢?
你说过,你是在没有操作体系的裸机上运转的,那么你的代码必定不是一个可履行程序,而是真实的机器代码段.除了程序自己,没有人会帮他设置什么运转时的段地址的.
没有肯定跳转的程序是能够移动的,有肯定跳转的程序是不行移动的.
27.
你的意思是置疑我的程序是否真的在SRAM里边运转? 仍是置疑我的Check_Flash有问题?
1)。 在Flash里边运转程序和在SRAM运转程序的速度是有很大差其他。 能够从运转的状况能够看出来。这点根本能够确认程序真的在SRAM运转。(不然也无法跨越这条指令:
ldr pc, =0x600000b8 )
2)。Check_Flash 真的有问题吗? 我真的是用C写的。
我再查看他编译今后的汇编代码看看。
28.
那,下面便是用armcc 编译发生的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\0″
===================================
留意。我把查看设备ID的那部分注释掉了。
从这个代码看,如同也没有问题。 你说呢?
29.
CheckFlash
MOV a2,#0x90
ADD a2,a2,#0x900000
MOV a1,#0
STR a2,[a1,#0]
假如在flash中履行,那么这一句之后,程序代码就读不到了,也便是程序飞掉了.
MOV a2,#0
ADD a3,pc,#L000198-.-8
B LCDDrawStr
L000198
DCB “Unkn”
DCB “ow F”
DCB “LASH”
DCB ” DEV”
DCB “ICE\0″
假如你的LCD显现是正常的.你试试在这段程序最初的当地把PC的值显现出来,看看是不是在flash中运转.
30.
MID = *addr;
if( MID == 0x00B000B0 )
{
你在这儿用串口先显现一下PC的值,看他是在Flash仍是
sdram里边,最好然后延时一会,看看作用
//display Manufacture ID
我置疑调用你的显现函数时分,回到Flash里边去了,假如能够,
在你的显现函数里边,也从串口输出PC的值,看看是在flash
仍是sdram里边
}
31.
我不知道你的编译器,不过象gcc的,c的函数名通常在汇编中看到的是加前缀_的c函数名. 象Move_Program的c函数,在汇编中是看不到的。在gcc中是在Move_Program前加asmlinkage。
32.
我调试过,我用LCD显现出PC. 请看:
在这个句子”*addr = 0x00900090″ 之前, PC都正常。显现成果为SRAM里边的地址(0x60000278), 可是假如一履行这个句子之后,PC 无法显现出来了(便是我调用了显现函数,但没有显现)。可是如同又能跑!由于LED在闪耀。(留意在这条句子之后,我加了LED 闪耀功用,以证明程序在跑 ) 很古怪。
33.
那便是你的显现函数有问题啦,不是程序跑飞了。
你再细心查查看详细的过错呈现在什么方位上吧。
你不是有指示灯吗,在显现函数的入口处参加PC的查看代码,看看PC是在什么规模,比方,在sram就平息指示灯,在flash中就点亮指示灯。
34.
谢谢各位! 我理解了。 哈哈~~~~~~~
原来是那些全局变量(字库)的地址还没有变。怪不得,在我写0x00000000之前,程序依然拜访的是Flash里边的ROM DATA. 然后在写0x00000000后, 此刻Flash的读写状况发生变化,可是程序依然要拜访Flash里边的ROM DATA. 这个时分问题就出来了。由于这个时分Flash或许无法正确读出ROM DATA. 所以LCD Driver无法正确拿到字库,因而无法正确显现。因而或许作如下修正就能够拉:
LCD Driver在运用肯定地址(便是 0x60000000 + 偏移 )
可是这样的话假如全局变量许多的话,或许有静态变量的话,就十分麻烦了。 有什么办法处理吗??
有劳各位了。 真的十分感谢各位。 给了许多提示和启示。
再次谢谢。 🙂
35.
可是这样的话假如全局变量许多的话,或许有静态变量的话,就十分麻烦了。 有什么办法处理吗??
能够用PIC,也便是动态衔接库运用的技能,我记住ppcboot用这种办法完成从Flash搬到RAM后,只需作简略的修补(Fixup),就能够在RAM中履行。
更简略的办法是把全局变量放到一个结构中,程序移动后调整结构指针就能够了。
36.
1.尽量用局部变量。
2.改写ld的参数(一般在makefile中,或许有一个独自的ldscript),把代码的开始地址改成你将要把它仿制曩昔的那个sram中的地址。
37.
OK. Very good.
我测验过了。能够改 -ro-base xxxxxx。
成功。