钢格板厂家
免费服务热线

Free service

hotline

010-00000000
钢格板厂家
热门搜索:
行业资讯
当前位置:首页 > 行业资讯

DSP编程技巧之34答疑解惑哪家强之9

发布时间:2020-06-30 20:46:24 阅读: 来源:钢格板厂家

答疑解惑哪家强?当属我们EEPW最强。。。接下来继续我们的答疑解惑系列。

本文引用地址: 为什么一个看起来很简单的程序,链接的时候却要花费很长的时间?

导致这种现象的最主要的原因是类型合并(type merging)。那什么是类型合并呢?举个简单的例子,在头文件types.h中定义了结构sss,且所有的.c中中都引用了这个types.h。因此在编译之后,描述sss的调试类型信息被包含到每个目标文件之中(除非使用了--symdebug:none来禁用调试信息),因此在链接的时候,链接器会发现有很多个sss类型的副本;默认情况下,链接器使用类型合并把这么多sss类型合并为一个,从而使得最终输出的.out文件中只有一个sss类型,而不是很多个重复的副本,达到减小代码尺寸的目的,并且使得CCS在加载.out文件时也会花费更少的时间。然后,类型合并这个过程中需要大量的计算,因此导致了链接看起来需要花费很长的时间。

解决的方法有两个:

1. 禁用类型合并:使用链接器的-b选项(含义请参考。这样做的结果是链接的时间变短,但是.out文件变大,需要更长的时间来加载;如果在这个例子中sss的副本非常多,有可能需要很差的时间来加载.out文件。

2. 使用--symdebug:none选项来完全禁止把调试信息写入.out文件。这样做既可以减小链接时间,又可以减小.out的尺寸和缩短加载时间,但后果是代码的调试功能被大大削弱了。

59. 如何使用一个.cmd文件在含有不同的内部存储空间的芯片上来实现段的优先级?

假设有下面的状况:

器件1有64kb快速的内部存储,而器件2有128kb。现在我们有4个关键的代码段:

.text:_a : 20kb

.text:_b : 30kb

.text:_c : 20kb

.text:_d : 10kb

其中段a的运算重要性最高,段b的次之,以此类推。

给片内的快速存储器命名为IRAM,而片外的慢速存储器命名为SDRAM。假设在器件1上,我们必须把.text:_a和.text:_b保存在IRAM中以保证运行速度,而.text:_c和.text:_d则既可以保存在IRAM,也可以保存在SDRAM中。在器件2中,因为片上存储显著增大,可以把abcd四个段都保存在SDRAM中。此时我们可以使用下面的方式,使用同一个.cmd文件来完成段的分配:

这一段语句的作用有两个:

(1) 在分配存储空间时,按照顺序来确保配段的优先级。在.cmd文件中,如果需要保证段的优先级,则必须使用GROUP这个指令;如果不使用则段之间不会有优先级的关系,此时链接器会有效把长度最大的那个段优先分配空间,以最大程度地减少存储空间中的空隙。

(2) 自动在不相邻的存储空间IRAM和SDRAM中划分输出的段。两个大于号“>>”也是链接器的内部指令,它用来表明GROUP中的段可以被划分到不同的存储空间里。例如,当链接器在器件1上,发现在分配完.text:_a和.text:_b到IRAM中之后,发现.text:_c有20kb,IRAM的空间已经不足以存放它时,它会跳过把text:_c分配到IRAM上,而是把text:_c分配到SDRAM中;接下来链接器会继续尝试把text:_d给分配到IRAM中(如果text:_d的长度足够小的话)。而在器件2上,编译器会发现空间足够存放abcd四个段的时候,就把它们四个一起保存到IRAM中了。

如果我们使用下面的两种方式,结果会是什么样的呢?

使用这个方法仍然可以做到段的分割,即上面的第二条,然而它们之间空间分配的优先级没有办法保证,很有可能使得程序的性能受到影响。

使用这个方法仍然可以做到段的优先级,即上面的第一条,然而在器件1上这些段将无法全部保存到IRAM中,最终导致链接器的错误。。

60. 为什么需要开启链接器–w选项?

-w的含义是:在未定义的输出段被创建时产生警告信息。因此,如果我们在程序中创建了段,例如:

但是在cmd文件中没有明确段的类型(例如.text、.bss等),则链接器将有可能任意地给我们自定义的段分配一个地址控制,这将导致严重的运行时错误。例如,链接器有可能任意地把我们自定义的段给分配为FLASH这个段类型,但是实际上它们并不在Flash中运行,结果导致代码完全不执行。

使用-w选项将使得链接器必须提示我们有关段未定义的信息,从而避免上述问题的发生。

61. 链接器地址映射文件中的trampolines代表什么含义?

在链接之后,打开生成的.map文件,可以查看地址映射信息,如下图所示。

其中的TRAMPOLINES在英语里是“蹦床”的有意思,在这里的含义则是代表非直接跳转的向量。它的含义与蹦床运动是一样的,代码执行到trampoline之后会立刻跳转出,或者回弹。当跳转指令无法到达目的地时,链接器会自动产生trampoline, 然后我们就可以看到上图所示的那些信息了,它们的含义是:

callee:函数被调用。

addr:callee的地址。

tramp:链接器自动为trampoline所产生的名字。

addr:trampoline在存储器中的地址。

call addr:从trampoline产生的调用所使用的地址列表。

call info:包含最初调用的目标文件和输入段。如果目标文件保存在某个库中,则会把库文件的名字也显示出来。

62. 在C编译器中使用内联的汇编指令的情况下,为何代码的实时运行出错了?

在C代码中,我们可以使用asm()指令来插入汇编代码。如果插入的这段汇编代码修改了C代码所使用的运行环境中的寄存器,则会破坏C代码的数据,导致运行时出错。所有在C代码中使用内联的汇编代码时务必小心,不要破坏了程序的完整性。

潍坊工作服订制

沈阳制做防静电工作服

济宁工作服