最近在调试GD32F4的bootloader程序发现了个奇怪的问题,之前在自己电脑上开发完成并测试没问题后,就提交了代码,但是同事拉取后编译出来的bootloader在跳转到app的时候会直接卡死,对比了一下他编译出来的bin和我这边的bin,同一份代码,同一个project编译出来的bin居然也有挺大差别的
首先还是猜测是编译器优化的问题,但他的和我的都是-O1,不过我还是试了下在自己电脑上改成-O0编译了bootloader,下载到板子里发现跳转时居然也卡住了。。。。。
串口打了个斜杠0就没下文了。。。。
跳转的函数是这样的
好吧,就只能去分析下这个-O1和-O0生成的bin有啥区别了
通过debug到这个函数,发现生成的汇编代码还是有挺大差别的,具体来说-O1的基本都是在用通用寄存器在操作数据
而-O0生成的就会用到栈指针来存取数据
其实分析到这里就挺明显的了,在-O0时,由于最后一步跳转时读取了sp+4里面的数据,但是在这之前sp的地址因设置了MSP而被手动改成了app的栈指针地址,所以它读出来的东西就已经不是之前保存起来的需要跳转的地址了,跳过去之后就会导致程序跑飞
最后,把__set_MSP给删掉后,在-O0的情况下也能正常跳转了
这里也有点奇怪,不重新设置栈指针居然也能跳转成功。。。(按正常流程应该要设的吧),而且看了下跳转后app的栈指针的确也是app的bin文件里指定的栈顶指针,并不是bootloader的栈顶指针,猜测可能在执行Reset_Handler到main函数之间会再次设置栈顶地址,毕竟在__main中会设置堆栈(不确定,望大佬指教)
因为之前出现了同样是-O1选项的两台电脑编译,生成的固件是不一样的,所以后面就在自己的电脑上不断切换-O1和-O0来编译做测试,一开始-O1生成的bin大小是8K左右,-O0生成的bin是14K左右,试了几次后,就发现-O1生成的bin变成了11k大小。。。虽说应该影响不大,但还是给自己提个醒,出问题时可以留意有没有可能是这个导致的