答疑解惑哪家强?当属咱们EEPW最强。。。接下来持续咱们的答疑解惑。
22. 除了运用编译器的优化选项之外,还能够运用什么办法进步程序的功用?
编译器的优化选项,只能在代码满意很多选项的要求时,才干得到较好的优化作用。在咱们编程的时分,首要要做到心里有数,尽可能运用一些高效的编程办法,例如运用右移操作替代除以2的倍数的操作,能够大幅度地削减代码运转时刻等。这些技巧很多是与C/C++的娴熟运用所相关的。此外,依据器材的特色,例如是否包含FPU、CLA等,把特定的代码放在不同的区域履行,也能起到进步程序功用的作用;依据代码对功用的要求,把它们运转在不同的方位,例如RAM快于Flash,Flash又快于XINTF等;在器材包含数学表的情况下,运用内建的数序函数库,而不是规范的C数学库等。在此咱们能够给出一些提示:
1) 代码运转在Flash中
必定要使能预读缓冲区,并装备恰当的等候状况。一般在各个器材的头文件与外设示例包里都有对应的比如。
2) 把时刻要害的代码和/常数数组等从Flash仿制到RAM中运转
在RAM中运转时,最大的指令周期比Flash中运转时要高,其履行速度也要快出不少,所以能够依据需求把实时功用要求较高的程序仿制到RAM中运转,详细的办法和实例能够参阅http://www.ti.com/general/docs/litabsmultiplefilelist.tsp?literatureNumber=spra958l下面的《Running an Application from Internal Flash Memory on the TMS320F28xxx DSP》。
3) 评价代码和数据的存储地址的区分,并依据需求批改链接文件
i. 假如某段代码和它所读取的数据坐落同一个物理内存区间中,则由于它们运用相同的地址总线等资源,无法一起拜访,形成了资源的抵触,这会下降程序的功用,所以最好把代码和数据保存在不同的内存区间中。
ii. 等候状况(wait)会下降体系功用,由于CPU会履行过多的无用状况且在此期间无法处理其他使命:当CPU读取或许拜访存储单元或许外设的时分,该存储器或许外设有可能在CPU默许分配的时刻内无法完结数据的传输,此刻就需求在CPU的ready信号中刺进等候状况,直到数据传输完结才干让CPU持续履行其他使命。C28x器材上,大部分的SARAM都是零等候的,但是在C2833x器材中,有一些模块却不是,例如某些Flash/OTP的拜访等。
iii. 假如在代码中很多运用两个数据缓冲区,则把两个数据缓冲区存放在不同的RAM模块中有可能会进步代码的功用,由于很多读写同一块RAM区间会发生更多的流水线阻滞,形成功用的下降。
4) 运用编译器中的一致内存方式–unified_memory
此方式把一切的存储空间界说为一个全体,这样编译器在编译时就能够运用RPT与PREAD指令来处理大部分的内存仿制调用和结构体的分配。
5) 运用Flash和外部存储器
假如代码需求在Flash或外部存储器中运转,则在编译时敞开-me选项。它将制止编译器运用快速分支指令(SBF/BF),转而运用一般的跳转指令(SB/B)。BF指令在默许情况下是被启用的,它能够将跳转分支运用的指令周期从7个下降到4个,在零等候状况的SAM中履行时,快速分支指令的预读特性使得它较为高效,但是在非零等候的存储器中履行时,SBF/BF的预读反而形成了功用的下降,此刻需求人为地对预读和等候进行规划。
6) 运用内联函数
在编译时敞开内联函数功用,则编译器会主动把屡次调用的函数进行内联,大大削减函数调用和回来操作所带来的开支。当然,依据“空间换时刻”的准则,敞开内联会增加必定的代码尺度。
23. 为什么一个char类型的数组中,每个元素都占用了16bit的地址?
这是由于在C28x上,字节(byte)和字(word)是等价的:也就是说它们都是16位或许说16比特(bit)宽的,即sizeof(int) == sizeof(char) == 1。
24. sizeof(int) == sizeof(char) == 1形似与ANSI规范是相违反的?
在ANSI/ISO的C界说中,sizeof操作符以字节方式给出了其操作数的存储巨细。ANSI/ISO还规则,sizeof操作符取char的值时,回来值为1。由于TMS320C28x中的字节是16位的,char也是16位的,所以sizeof的成果契合ANSI规范的。
作为弥补,选16位,而不是8位或许其他什么位数作为char的宽度,首要是为了一致寻址的便当,虽然在某种程度上说这增加了必定的存储器空间占用,或许说浪费了一些空间,由于它们在存储空间中制作了一些空泛。
25. 假如char是16位的,那么怎样高效地拜访8位的值?
能够运用__byte()和__mov_byte()这样的编译器内联函数。请参阅http://www.eepw.com.cn/article/265102.htm。
26. 编译成果提示undefined symbols,姓名中包含$符号,怎样破?
姓名中带美元符号的函数,例如FS$$MPY, FS$$TOL等,都是RTS库里的内置函数,编译器提示咱们这些函数未界说,标明咱们没有把对应的RTS库给加入到工程中,例如MPY是数学函数,需求增加相关的数学库,例如FPU数学库等。
27. 链接器提示“_c_int00 is not defined”,怎样破?
在http://www.eepw.com.cn/article/262926.htm这篇文章中,现已剖析了_c_int00的意义。找不到_c_int00的话,阐明咱们遗漏了包含它的RTS库,例如 rts2800_ml.lib、rts2800_fpu32.lib等候,这些RTS库的详细区别在答疑解惑的第15条中现已有对比了(http://www.eepw.com.cn/article/265108.htm)。
28. 新版本的编译器中,printf()/sprintf()函数形似要运用更多的栈?
这是由于printf()函数被从头批改了,以支撑多个级其他printf格局阐明符支撑和批改,以削减代码巨细和总内存巨细(包含bss)。printf由sprintf()直接调用,它运用一个400个元素的巨细的部分数组。为了保存一致性,printf()一向都在运用这么大的内存空间,而编译器也在尽量防止运用malloc()进行内存分配。与老版本所不同的的是,此数组曾经是静态的,而现在它被保存在.bss,而不是栈中;这样做的意图是,假如用户运用C I/O,则他们往往会在运用适宜尺度的栈的一起尽量减小.bss的运用。