由于某些原因,我的程序不能放在flash的0地址上,我将程序放在0x8000这个地址,在0地址上放的是一个用于引导的程序。使用keil uvision3开发,程序附在后面。
现在的情况是,我在app2的option里面设置target里的rom地址为0x8000,编译出来的hex文件我转换成bin以后发现在程序代码前有32k的0(最前面还有一些数据,应该是跳转程序),证明程序是被编译到了0x8000的地址上。
我将这样的app2直接下载到flash上,是可以正常运行的。
现在我将app1编译好后下载到flash的0地址,发现无法跳转到0x8000,也就是app2去运行。在两个程序中我都关闭了所有的中断,只是做一个单纯的跳转。
我也试过将0x8000以后的1kB的数据搬移到内存(0xc300000)去,然后用同样的方法跳转,但仍旧不能运行。 一个朋友告诉我说是keil的问题,他说用ads就完全没有这样的问题。我想应该还是我没找对方法
麻烦大侠们指点一下迷津
app1 (boot程序)
void ( *BootLoader)() ;
void main(void)
{
unsigned int i = 0;
rSYSCFG=CACHECFG;
Port_Init();
BATLLED_SET;
BATMLED_SET;
BATHLED_SET;
BootLoader = ( void (*)())0x8000; // Boot Prog Start theis Address
BootLoader();
return;
}
app2 (应用程序)
void main(void)
{
unsigned int i = 0;
Port_Init();
while(1)
{
if (i++&0x100000)
ERRORLED_SET;
else
ERRORLED_CLEAR;
}
return;
}
12 个解决方案
#1
你先试试APP1能不能运行吧。任何一个CPU总归要有个基本初始化,你直接一个main貌似不可行的。
#2
1. 可能是把app2空间擦掉了;
2. 在app1/bootloader最后加个while(1),跟踪以下看看;
3. 如果看看链接生成的map文件,0x8000位置和你预期的是否一致;正如楼上所说,链接的时候会有相应的初始化库函数被自动连接进去。
做这种东西需要研究linker/compiler以及系统是怎么初始化的,存储器怎么分配的的,数据段是如何从flash中拷到RAM中的。
2. 在app1/bootloader最后加个while(1),跟踪以下看看;
3. 如果看看链接生成的map文件,0x8000位置和你预期的是否一致;正如楼上所说,链接的时候会有相应的初始化库函数被自动连接进去。
做这种东西需要研究linker/compiler以及系统是怎么初始化的,存储器怎么分配的的,数据段是如何从flash中拷到RAM中的。
#3
app1是可以运行的,因为我在app1里面点了三个灯,可以验证
app2的空间应该没有被擦除,因为使用Flash Programmer先下载app2时提示擦除了扇区1~5,而下载app1时只提示擦除了扇区1。而app2因为是被编译到0x8000地址,所以应该是在扇区5上。
keil的工程在c代码之前都有个.s的汇编文件进行cpu的初始化。我的app1和app2的.s文件是完全一样的,所以我认为只要app1能够运行(3灯被点亮),那cpu就是初始化过了,应该可以直接跳转到app2的main函数部分开始运行。实际上app1的.s里最后也是一个简单的跳转:
但我直接在这里将LDR R0,=?C?INIT 改成LDR R0,=0x8000 也不行。。。
最让我郁闷的是,我单独下载app2,是可以运行的,反汇编发现LDR R0,=?C?INIT执行后R0的值是0x8069,于是我把app2的.s里直接改为LDR R0,=0x8069,运行没有问题。但我在app1里用LDR R0,=0x8069就完全没有效果,app1的.s和app2的.s文件是完全一样的啊,唯一的区别就在于R0,=?C?INIT两个程序的?C?INIT不一样。
难道真是keil在编译的时候有什么特殊的设置?由于公司收到过ads的法务函,所以盗版的ads都卸载了,这两天回家装个ads试试。。。。
现在在学习arm 汇编,希望能有所帮助。
也谢谢楼上两位,等了几天终于有人回帖了。。。。
app2的空间应该没有被擦除,因为使用Flash Programmer先下载app2时提示擦除了扇区1~5,而下载app1时只提示擦除了扇区1。而app2因为是被编译到0x8000地址,所以应该是在扇区5上。
keil的工程在c代码之前都有个.s的汇编文件进行cpu的初始化。我的app1和app2的.s文件是完全一样的,所以我认为只要app1能够运行(3灯被点亮),那cpu就是初始化过了,应该可以直接跳转到app2的main函数部分开始运行。实际上app1的.s里最后也是一个简单的跳转:
// Enter the C code
LDR R0,=?C?INIT
TST R0,#1 ; Bit-0 set: INIT is Thumb
LDREQ LR,=exit?A ; ARM Mode
LDRNE LR,=exit?T ; Thumb Mode
BX R0
ENDP
但我直接在这里将LDR R0,=?C?INIT 改成LDR R0,=0x8000 也不行。。。
最让我郁闷的是,我单独下载app2,是可以运行的,反汇编发现LDR R0,=?C?INIT执行后R0的值是0x8069,于是我把app2的.s里直接改为LDR R0,=0x8069,运行没有问题。但我在app1里用LDR R0,=0x8069就完全没有效果,app1的.s和app2的.s文件是完全一样的啊,唯一的区别就在于R0,=?C?INIT两个程序的?C?INIT不一样。
难道真是keil在编译的时候有什么特殊的设置?由于公司收到过ads的法务函,所以盗版的ads都卸载了,这两天回家装个ads试试。。。。
现在在学习arm 汇编,希望能有所帮助。
也谢谢楼上两位,等了几天终于有人回帖了。。。。
#4
位置0x8000的代码(函数入口)需要准确定位,另外你需要研究boot/app的向量表、数据段、堆栈、代码段都是怎么定位的,这就是要你看看map文件和linker使用的目的。
没具体做过arm芯片的东西,随便说说。
没具体做过arm芯片的东西,随便说说。
#5
你是不是两次烧写?
如果是烧两次, 那前面烧写的程序可能被擦掉了
如果是烧两次, 那前面烧写的程序可能被擦掉了
#6
不是可能被擦掉了, 而是肯定被擦了
#7
确实
太郁闷了。本来我们设计的原理图上使用的flash是S29GL064AB,这个flash的前8个扇区都是8k的,所以我把app2放在0x8000也就是扇区5上,而app1在0地址就是扇区1上,理论上是不会有问题的。 但实际上我们的机器上焊的flash是A29L160ATV,查了资料,这个flash的第一个扇区就有64k,这样app1和app2都位于扇区1上,所以app2会被擦除掉…………
但问题还是一样的,就是无法跳转到keil所编写的程序上运行。
昨天我使用ads重写了app2的内容,然后设置ro base和entry point为c700000,再把编译生成的bin放到0x1f6400这个位置上,然后在app1中将其从1f6400搬移到c700000,运行,完全正常。
但使用同样方法用keil编译app2(rom设置为c700000)就是没办法正常运行。
不知道有没有人使用keil for arm实现过两个程序直接的跳转,是不是有什么特殊的设置要做?
总的问题算是解决了,app2用ads重写就可以了,另外app2的存放地址只要放到0x10000之后就不会因为下载app1而被擦除。
但由于还有一些疑问,下周1结帖,谢谢楼上3位了
#8
进来学习学习。
#9
arm 裸奔 牛逼啊 我用ads的时候 是用44b0.s文件引导 main函数的然后在设置一下启动的.o文件有起始的位置 然而keil for arm我知道他编译的起始位置是怎么样搞的 好像没有ads好用啊
#10
关键是,你的下载工具是怎样处理Flash的擦除的.
很多工具在下载前会擦除整个器件,而不是仅仅只擦除它需要用到的扇区. 这样你的两次烧写就不会得到你希望的结果.
很多工具在下载前会擦除整个器件,而不是仅仅只擦除它需要用到的扇区. 这样你的两次烧写就不会得到你希望的结果.
#11
如果无法把两个...部分...弄到一起,你可能需要提供自己的烧写工具.....
#12
我自己编了个小工具把两个程序的bin文件拼接成一个文件,这样就可以一次性下载了
#1
你先试试APP1能不能运行吧。任何一个CPU总归要有个基本初始化,你直接一个main貌似不可行的。
#2
1. 可能是把app2空间擦掉了;
2. 在app1/bootloader最后加个while(1),跟踪以下看看;
3. 如果看看链接生成的map文件,0x8000位置和你预期的是否一致;正如楼上所说,链接的时候会有相应的初始化库函数被自动连接进去。
做这种东西需要研究linker/compiler以及系统是怎么初始化的,存储器怎么分配的的,数据段是如何从flash中拷到RAM中的。
2. 在app1/bootloader最后加个while(1),跟踪以下看看;
3. 如果看看链接生成的map文件,0x8000位置和你预期的是否一致;正如楼上所说,链接的时候会有相应的初始化库函数被自动连接进去。
做这种东西需要研究linker/compiler以及系统是怎么初始化的,存储器怎么分配的的,数据段是如何从flash中拷到RAM中的。
#3
app1是可以运行的,因为我在app1里面点了三个灯,可以验证
app2的空间应该没有被擦除,因为使用Flash Programmer先下载app2时提示擦除了扇区1~5,而下载app1时只提示擦除了扇区1。而app2因为是被编译到0x8000地址,所以应该是在扇区5上。
keil的工程在c代码之前都有个.s的汇编文件进行cpu的初始化。我的app1和app2的.s文件是完全一样的,所以我认为只要app1能够运行(3灯被点亮),那cpu就是初始化过了,应该可以直接跳转到app2的main函数部分开始运行。实际上app1的.s里最后也是一个简单的跳转:
但我直接在这里将LDR R0,=?C?INIT 改成LDR R0,=0x8000 也不行。。。
最让我郁闷的是,我单独下载app2,是可以运行的,反汇编发现LDR R0,=?C?INIT执行后R0的值是0x8069,于是我把app2的.s里直接改为LDR R0,=0x8069,运行没有问题。但我在app1里用LDR R0,=0x8069就完全没有效果,app1的.s和app2的.s文件是完全一样的啊,唯一的区别就在于R0,=?C?INIT两个程序的?C?INIT不一样。
难道真是keil在编译的时候有什么特殊的设置?由于公司收到过ads的法务函,所以盗版的ads都卸载了,这两天回家装个ads试试。。。。
现在在学习arm 汇编,希望能有所帮助。
也谢谢楼上两位,等了几天终于有人回帖了。。。。
app2的空间应该没有被擦除,因为使用Flash Programmer先下载app2时提示擦除了扇区1~5,而下载app1时只提示擦除了扇区1。而app2因为是被编译到0x8000地址,所以应该是在扇区5上。
keil的工程在c代码之前都有个.s的汇编文件进行cpu的初始化。我的app1和app2的.s文件是完全一样的,所以我认为只要app1能够运行(3灯被点亮),那cpu就是初始化过了,应该可以直接跳转到app2的main函数部分开始运行。实际上app1的.s里最后也是一个简单的跳转:
// Enter the C code
LDR R0,=?C?INIT
TST R0,#1 ; Bit-0 set: INIT is Thumb
LDREQ LR,=exit?A ; ARM Mode
LDRNE LR,=exit?T ; Thumb Mode
BX R0
ENDP
但我直接在这里将LDR R0,=?C?INIT 改成LDR R0,=0x8000 也不行。。。
最让我郁闷的是,我单独下载app2,是可以运行的,反汇编发现LDR R0,=?C?INIT执行后R0的值是0x8069,于是我把app2的.s里直接改为LDR R0,=0x8069,运行没有问题。但我在app1里用LDR R0,=0x8069就完全没有效果,app1的.s和app2的.s文件是完全一样的啊,唯一的区别就在于R0,=?C?INIT两个程序的?C?INIT不一样。
难道真是keil在编译的时候有什么特殊的设置?由于公司收到过ads的法务函,所以盗版的ads都卸载了,这两天回家装个ads试试。。。。
现在在学习arm 汇编,希望能有所帮助。
也谢谢楼上两位,等了几天终于有人回帖了。。。。
#4
位置0x8000的代码(函数入口)需要准确定位,另外你需要研究boot/app的向量表、数据段、堆栈、代码段都是怎么定位的,这就是要你看看map文件和linker使用的目的。
没具体做过arm芯片的东西,随便说说。
没具体做过arm芯片的东西,随便说说。
#5
你是不是两次烧写?
如果是烧两次, 那前面烧写的程序可能被擦掉了
如果是烧两次, 那前面烧写的程序可能被擦掉了
#6
不是可能被擦掉了, 而是肯定被擦了
#7
确实
太郁闷了。本来我们设计的原理图上使用的flash是S29GL064AB,这个flash的前8个扇区都是8k的,所以我把app2放在0x8000也就是扇区5上,而app1在0地址就是扇区1上,理论上是不会有问题的。 但实际上我们的机器上焊的flash是A29L160ATV,查了资料,这个flash的第一个扇区就有64k,这样app1和app2都位于扇区1上,所以app2会被擦除掉…………
但问题还是一样的,就是无法跳转到keil所编写的程序上运行。
昨天我使用ads重写了app2的内容,然后设置ro base和entry point为c700000,再把编译生成的bin放到0x1f6400这个位置上,然后在app1中将其从1f6400搬移到c700000,运行,完全正常。
但使用同样方法用keil编译app2(rom设置为c700000)就是没办法正常运行。
不知道有没有人使用keil for arm实现过两个程序直接的跳转,是不是有什么特殊的设置要做?
总的问题算是解决了,app2用ads重写就可以了,另外app2的存放地址只要放到0x10000之后就不会因为下载app1而被擦除。
但由于还有一些疑问,下周1结帖,谢谢楼上3位了
#8
进来学习学习。
#9
arm 裸奔 牛逼啊 我用ads的时候 是用44b0.s文件引导 main函数的然后在设置一下启动的.o文件有起始的位置 然而keil for arm我知道他编译的起始位置是怎么样搞的 好像没有ads好用啊
#10
关键是,你的下载工具是怎样处理Flash的擦除的.
很多工具在下载前会擦除整个器件,而不是仅仅只擦除它需要用到的扇区. 这样你的两次烧写就不会得到你希望的结果.
很多工具在下载前会擦除整个器件,而不是仅仅只擦除它需要用到的扇区. 这样你的两次烧写就不会得到你希望的结果.
#11
如果无法把两个...部分...弄到一起,你可能需要提供自己的烧写工具.....
#12
我自己编了个小工具把两个程序的bin文件拼接成一个文件,这样就可以一次性下载了