固件升级思路

需要一个升级APP程序功能,但是又不想再Bootloader里面做,因为一开始没有设计BootLoader难过。 所以只能在APP添加一个Update模块了。

            Update的逻辑流程如下:

                                 

                  Update程序通过串口读取要升级的APP程序数据。

                  然后编写到ROM中。

 

                  因为CODE自己就在ROM中,为了防止把自己擦掉,所以Update要先把自己拷贝到RAM中去运行。

 

                  把CODE从ROM拷贝到RAM中去本以为要用汇编来写,其实用C语言就OK了。就是简单的Buf拷贝操作。

                  因为ARM的架构支持统一寻址模型:操作Device和操作RAM没有任何区别。

 

                 但是有个非常有趣的现象。

 

程序类似与:

//ROM中的Update地址

                src_addr=(int32u*)Update;

               //RAM中的Update地址

                dst_addr=(int32u*)(0xXXXXXXXX);

               //指针函数

                jump_addr=(jump_func_type)dst_addr;

 

                //拷贝update程序

                for(i=0; i<CODE_LENGTH; i++)

                    *dst_addr++=*src_addr++;

              

//跳转到RAM中去执行Update

                (*jump_addr)();

               我把程序地址拷贝到偶数地址,就是死活跳转不过去。。。

               我想是不是长跳转必须用汇编才行?

               

                偶然间分析一下APP.MAP文件,发现所有的Code都是thumb code。而且所有的函数地址都是奇数地址。

                突然间恍然大悟。因为thumb code指令,PC的最低位必须是1,所以跳转地址也必须是奇数才行。

                修改之后,果然可以跳转了。本以为这样万事大吉了。

 

               但是发现,只要代码稍微修改一下,就可能宕机(也就是不能跳转到Update中去了),多增加一点或者减少一点代码可能就好了。

              很是奇怪。

              

               还好有JTAG可以单步调试。最后发现,跳转的地址都是对的。

              又查看了生成的汇编文件。

              终于发现了问题的原因了:

                       虽然函数的跳转地址是奇数地址:比如 0x2000abc1;

                       但是函数的代码实际开始地址是:   0x2000abc0,也就是偶数地址。

 

                      也就是说Code是2字节对齐的。thumb指令是16位的。。所以比然是2字节对齐。

                     但是为什么代码的调用地址是奇数地址呢。因为ARM为了区分thumb指令和ARM指令,使用PC寄存器的最低位来区分的。如果最低位是1,则是thumb指令,如果是0则是ARM指令。

                      所以跳转地址是奇数地址,但是实际的代码的开始地址是偶数地址。

                      所以其实我少拷贝了一个BYTE的代码才导致了这么奇怪的BUG。

                     

             把拷贝代码从新修改后就OK了。

 

                src_addr=(int32u*)((int32u)Update - 1); //地址先减去一,拷贝代码的实际开始位置.

                dst_addr=(int32u*)(0xXXXXXXXX); //当然dst_addr也是偶数地址。

               重新修正jump_addr=((int32u)dst_addr+1); //跳转地址必须是奇数地址(这样CPU才知道是Thumb指令)

                for(i=0; i<CODE_LENGTH; i++)

                    *dst_addr++=*src_addr++;

 

转载自:http://blog.csdn.net/yuan1125/article/details/7273175

 

自己增加部分:

          一个极其讨厌的人分享给我的,此人已经挂了,呵呵

 

记录一下思路

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值