免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3106 | 回复: 0
打印 上一主题 下一主题

stm32移植日志之五 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-09-03 21:20 |只看该作者 |倒序浏览
看本文请参考《都江堰操作系统与嵌入式系统设计》第15章,该书可在www.djyos.com下载。

    djyos使用gcc作为编译器,已经5年多了,要抛弃它,实在是一个艰难的抉择,需要下很大的决心。在移植日志中,专门为gcc写一篇,以示纪念。

    当初选择gcc做编译环境,是因为gcc支持的cpu种类繁多,可以简化djyos移植到其他cpu平台的工作,现在证明,这种想法大错特错!这次将djyos从ARM7移植到stm32的过程中,花了大量的时间折腾gcc后,仍未成功,而从0开始学习MDK到成功编译djyos,花费的时间竟然比花在gcc上的时间少得多。

    所以说,企图通过gcc简化cpu间移植工作是不现实的,新的cpu应该去学习它的专业开发环境,才是王道。也许,在linux环境下编译linux应用程序,gcc是最合适的,但用来编译非linux程序,gcc真的不适合。5年多来,gcc把我折腾得够呛,让gcc再去折腾djyos的用户,让我于心何忍!

    空口无凭,让事实说话,过去的就不说了,也没有留下什么记录,下面谈谈这次把djyos移植到stm32的过程中gcc给我的苦头。

牛头马嘴的出错信息
    我们知道,要使用gcc编译,就必须编写makefile和ld文件,这两个文件的书写规矩还真多,有些地方要用[tab]键,有些地方要用空格,有些地方又不允许空格,有些地方可以空行,有些地方不允许空行。违反了这些规矩,如果能给出正确的错误信息也行,可惜的是,给出的信息和真正的错误根本牛头不对马嘴!略举几例:

1、makefile中可以使用shell的printf命令,如果被打印的字符串有分行的话,空行是绝对不允许的,如果任意地方出现空行,可能的出错信息是:
   makefile:244: *** commands commence before first target.  Stop.    注:244行是文件末行
   也可能是:
   /usr/bin/sh: -c: line 0: unexpected EOF while looking for matching `"'

   你看着这些出错信息,是不是云里雾里?
2、在ld文件中,一个输出段描述如下:
   sec1 :
   {
      sec_base = . ;
      . =  addr;
      * (.text)
    } > region1
    上述代码中,但“sec_base=.”中的“.”代表的是绝对地址,“ .=addr ”中的“.”却是region1内的偏移地址。万幸的是,这个问题能够直接导致代码定位出错,调试的时候可以发现。
3、同样是ld文件中,地址必须升序排列,若有代码:
   sec2 :
   {
      . =  addr1;
      . =  addr2;
      * (.text)
    } > region2
    如果addr2<addr1,出错信息是:
debug.ld: xx1 cannot move location counter backwards (from xx2 to xx3)
其中:
xx1:文件最后一行的行号,不是出错行的行号
xx2:addr1+region2段起始地址。
xx3:addr2+region2段起始地址



生成了错误的代码

    如果说上述问题只是对你的考验的话——这么好的东西,不经九九八十一难,怎能轻易让你用!接下来的问题,就更严重了。

    一直使用的是gnuarm,经过一番煎熬后,终于编译成功了,加载调试吧!却发现根本无法调试,0地址并不是ld文件中指定的向量表,于是把可执行文件objdump出来,一看其中的内容,简直让人哭笑不得,gcc居然在向量表前面,0地址处放了这些东西:

00000000 <____divdf3_from_thumb>:

       0:      4778          bx    pc

       2:      46c0          nop                (mov r8, r

       4:      ea00274a       b     9d34 <__aeabi_ddiv>

00000008 <____asm_reset_switch_from_thumb>:

       8:      4778          bx    pc

       a:       46c0          nop                (mov r8, r

       c:      ea0003ed       b     fc8 <__asm_reset_switch>

这段代码有两个错误:

1、              这段代码是用来从thumb切换到arm状态的interwork代码段,在cm3中,企图切入arm状态,岂不是找死吗?fault伺候。

2、              它把这段代码放在0地址,谁都知道cm3中0地址应该是什么!

    虽然这两个是不可饶恕的错误,但我还是企图通过调整编译参数来解决问题,花了大量时间阅读gcc文档,并且经过无数次失败的试验后,我最终还是投降了。

      gnuarm不行,那换一个发行版本如何呢?于是安装了sourcery g++ lite,编译后,反汇编一看,OK,0地址正确地出现了向量表:

00000000 <_start>:

       0:      2000c000      .word      0x2000c000

       4:      00000012      .word      0x00000012

       8:      00000010      .word      0x00000010

       c:      00000010      .word      0x00000010

00000010 <rst_fault_handler>:

      10:      e7fe           b.n   10 <rst_fault_handler>

    大喜过望之余,马上加载调试,可一上来就陷入fault,通过跟踪调试,发现sourcery产生的代码,虽然没有在0地址添加interwork代码,但在所有的用C调用汇编函数的地方,用了比interwork稍微“聪明”点的blx:

    13f8:       f7ff ef64        blx   12c4 <__asm_reset_thread>

    看官,指令中目的地址的最低位是0,摆明要切入arm状态,在只支持thumb-2的cm3中,是不折不扣的非法指令,怪不得陷入fault了。

    我仍不死心,于是又安装了yagarto,结果一样令人失望。

    连正确地使用指令集都保证不了,这样的编译器,还有什么留恋的呢?还是从MDK或IAR中选一个吧。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP