打印

S3C6410移植日记之五---告别gcc

[复制链接]
5282|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
djyos|  楼主 | 2009-9-4 09:57 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    看本文请参考《都江堰操作系统与嵌入式系统设计》第15章,该书可在www.djyos.com下载。
    djyos使用gcc作为编译器,已经5年多了,要抛弃它,实在是一个艰难的抉择,需要下很大的决心。在移植日志中,专门为gcc写一篇,以示纪念。
    当初选择gcc做编译环境,是因为gcc支持的cpu种类繁多,可以简化djyos移植到其他cpu平台的工作,现在证明,这种想法大错特错!这次将djyosARM7移植到stm32的过程中,花了大量的时间折腾gcc后,仍未成功,而从0开始学习MDK到成功编译djyos,花费的时间竟然比花在gcc上的时间少得多。
    所以说,企图通过gcc简化cpu间移植工作是不现实的,新的cpu应该去学习它的专业开发环境,才是王道。也许,在linux环境下编译linux应用程序,gcc是最合适的,但用来编译非linux程序,gcc真的不适合。5年多来,gcc把我折腾得够呛,让gcc再去折腾djyos的用户,让我于心何忍!
    空口无凭,让事实说话,过去的就不说了,也没有留下什么记录,下面谈谈这次把djyos移植到stm32的过程中gcc给我的苦头。
牛头马嘴的出错信息
    我们知道,要使用gcc编译,就必须编写makefileld文件,这两个文件的书写规矩还真多,有些地方要用[tab]键,有些地方要用空格,有些地方又不允许空格,有些地方可以空行,有些地方不允许空行。违反了这些规矩,如果能给出正确的错误信息也行,可惜的是,给出的信息和真正的错误根本牛头不对马嘴!略举几例:
1makefile中可以使用shellprintf命令,如果被打印的字符串有分行的话,空行是绝对不允许的,如果任意地方出现空行,可能的出错信息是:
   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:文件最后一行的行号,不是出错行的行号
xx2addr1+region2段起始地址。
xx3addr2+region2段起始地址


生成了错误的代码

    如果说上述问题只是对你的考验的话——这么好的东西,不经九九八十一难,怎能轻易让你用!接下来的问题,就更严重了。
    一直使用的是gnuarm,经过一番煎熬后,终于编译成功了,加载调试吧!却发现根本无法调试,0地址并不是ld文件中指定的向量表,于是把可执行文件objdump出来,一看其中的内容,简直让人哭笑不得,gcc居然在向量表前面,0地址处放了这些东西:
00000000 <____divdf3_from_thumb>:
       0:      4778          bx    pc
       2:      46c0          nop                (mov r8, r8)
       4:      ea00274a       b     9d34 <__aeabi_ddiv>
00000008 <____asm_reset_switch_from_thumb>:
       8:      4778          bx    pc
       a:       46c0          nop                (mov r8, r8)
       c:      ea0003ed       b     fc8 <__asm_reset_switch>
这段代码有两个错误:
1、              这段代码是用来从thumb切换到arm状态的interwork代码段,在cm3中,企图切入arm状态,岂不是找死吗?fault伺候。
2、              它把这段代码放在0地址,谁都知道cm30地址应该是什么!
    虽然这两个是不可饶恕的错误,但我还是企图通过调整编译参数来解决问题,花了大量时间阅读gcc文档,并且经过无数次失败的试验后,我最终还是投降了。
      gnuarm不行,那换一个发行版本如何呢?于是安装了sourcery g++ lite,编译后,反汇编一看,OK0地址正确地出现了向量表:
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-2cm3中,是不折不扣的非法指令,怪不得陷入fault了。
    我仍不死心,于是又安装了yagarto,结果一样令人失望。
    连正确地使用指令集都保证不了,这样的编译器,还有什么留恋的呢?还是从MDKIAR中选一个吧。
沙发
香水城| | 2009-9-4 10:08 | 只看该作者
Linux与GCC的最大优点也是它最大的缺点,全世界各地都有人为它做贡献,集中了众多开发人员的智慧,这是其优点;正因为开发人员众多,造成软件的书写和使用没有统一个规范,随意性较高,造成理解和维护的巨大困难,这是其缺点。

下决心摆脱GCC是一个好的决定,但工作量肯定也是非常大的。

使用特权

评论回复
板凳
aozima| | 2009-9-4 11:01 | 只看该作者
我从开始ARM的时候就是一直用的GCC
没换过别的

但开始玩CM3的单片机后就没再用过GCC了..
GCC虽好,但也要合理选择呀

使用特权

评论回复
地板
mohanwei| | 2009-9-4 11:40 | 只看该作者
对普通电工来说,便宜没好货,免费更是没好货

对真正的高手来说,便宜免费都有好货……只是这种人太少了,我们大部分都是普通电工

使用特权

评论回复
5
ddb_21ic| | 2009-9-4 22:49 | 只看该作者
RIDE还是很好用
至少在我的3.23**版出了问题的情况下
很容易就换到了RIDE中

使用特权

评论回复
6
djyos|  楼主 | 2009-9-8 06:53 | 只看该作者
本帖最后由 djyos 于 2009-9-8 06:55 编辑

让菜鸟也能用会用用好OS,是djyos的目标之一,这包括OS本身和编译调试工具都要易学易用才行,从我自己多年使用gcc的经验看,gcc担当不起“易学易用”这个角色。为了降低用户学习使用的难度,我做了很多努力,写了许多关于建立和使用gcc编译环境的文档,但现在看来,还是必须抛弃之。

使用特权

评论回复
7
ddb_21ic| | 2009-9-8 13:33 | 只看该作者
ST的每个范例都有针对RIDE的版本
我自己也只是按照范例设置了几个选项,GCC就可以很好的编译了
当然,这种方法不算正统
Makefile+LD如果完全用手工写,确实不容易
但是,易学易用也要考虑价格,你的OS+App还能用免费版的Keil或IAR?
对于CM3,16KB很容易就超出了

使用特权

评论回复
8
ddb_21ic| | 2009-9-8 13:35 | 只看该作者
Makefile和LD文件也可以通过模板文件修改一下就能使用
并非必须每次都要重新写

使用特权

评论回复
9
djyos|  楼主 | 2009-9-8 15:52 | 只看该作者
本帖最后由 djyos 于 2009-9-8 15:53 编辑

楼上,你试过在gcc for cm3中用C语言调用汇编函数吗?不管我怎么折腾,gcc都生成“blx 偶数地址”这样的非法指令,一执行就陷入fault。

makefile和ld文件确实是改一下就能用,但我在改的过程中无意间多敲了一个空行,结果出来牛头不对马嘴的提示,搞了我大半天,你能预见djyos的用户会有多少这样的“无意间”吗?

使用特权

评论回复
10
byeyear| | 2009-9-11 14:54 | 只看该作者
gcc本身挺不错的,问题是没有好的集成开发环境;
C调汇编我没试过,我一般直接在C子程序里嵌汇编;
试试codeblocks+gcc吧
我用这个组合做qt程序 还是很不错的
gcc+keil做过arm7的项目,没有在cortex上用过
现在改iar了
研究gcc主要是担心将来公司会遇到版权问题

使用特权

评论回复
11
usecoolful| | 2009-9-13 21:00 | 只看该作者
LD需要手动修改,makefile可以自动生成,何必要全部手工呢?生成的不合适的话,可以再手动修改。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

60

主题

454

帖子

1

粉丝