问个44b0程序跳转的问题

时间:2022-05-02 19:23:46
44b0 + norflash
由于某些原因,我的程序不能放在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中的。  

#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里最后也是一个简单的跳转:

// 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芯片的东西,随便说说。

#5


你是不是两次烧写?

如果是烧两次, 那前面烧写的程序可能被擦掉了

#6


不是可能被擦掉了, 而是肯定被擦了

#7


引用 6 楼 Great_Bug 的回复:
不是可能被擦掉了, 而是肯定被擦了

确实

太郁闷了。本来我们设计的原理图上使用的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中的。  

#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里最后也是一个简单的跳转:

// 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芯片的东西,随便说说。

#5


你是不是两次烧写?

如果是烧两次, 那前面烧写的程序可能被擦掉了

#6


不是可能被擦掉了, 而是肯定被擦了

#7


引用 6 楼 Great_Bug 的回复:
不是可能被擦掉了, 而是肯定被擦了

确实

太郁闷了。本来我们设计的原理图上使用的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文件拼接成一个文件,这样就可以一次性下载了