matter智能家居espc2-c3公司深圳乐鑫芯片代理商C语言存储资源优化,受限于尺寸、功耗以及成本等因素,嵌入式系统中存储资源 RAM和ROM通常不易扩展。特别在单处理器芯片系统中,程序和数据只能使用片内有限的存储资源,因此,在嵌人式系统软件开发过程中,常常需要优化资源的使用,减少程序对存储资源的需求。
1.ROM空间优化
在嵌人式系统中,用ROM 保存二进制程序代码和程序中所需的数据,系统中的ROM 空间分为代码空间和数据空间。
(1)代码空间
通常优化程序代码长度的方法有两个:一是使用指令长度小的指令集;二是优化程序,减少指令数。
RISC-V 指令集架构中包括扩展指令集“C”。“C”是压缩指令集模块,指令长度为 16 位。在完成相同操作的情况下,使用 RISC-V 压缩指令集“C”的程序长度是使用32 位指令集的一半。例如,matter智能家居espc2-c3公司深圳乐鑫芯片代理商RV32I 两个数相加指令“add rd,rd,rsl”的长度是32位,而“C”指令“c.add rd,rs1”的长度是 16位。
一些通过简化运算提高程序速度的优化方法同时也缩短程序的长度。用更简单的算法替代复杂算法,可以减少程序指令数。在参数值确定或在数值有限的情况下,可以用简单计算替代复杂运算。例如,计算a³时,用乘法“b=a* a * a”替换指数函数“b=pow(a,3,0f)”后,计算部分由 100 多条指令减少到2条指令。
另外,一些加速程序的优化方法会增加程序的指令数。例如,循环展开、内联函数等手段将增加程序代码的长度。matter智能家居espc2-c3公司深圳乐鑫芯片代理商使用此类方法对程序进行优化时需要权衡程序行速度和空间的问题,在空间允许的情况下进行速度优化。
(2) 数据空间
ROM中所保存的程序运行时所需的数据通常包括变量初始值、常和其他数据,通过修改数据类型、调整数据结构等方法可以优化 ROM 中数据空间的大小。
不同数据类型占用存储空间的大小不同。选择与变量数值范围相应的数据类型将会提高数据空间的利用效率。例如,灰度图像每个像素的取值范围是0~255,如果将图像数组类型声明为 int image[][],则每个像素占用4字节,其中3个高位字节中的数据为 0。matter智能家居espc2-c3公司深圳乐鑫芯片代理商如果将图像数组类型声明为 unsigned char image[][],则每个像素占用1字节,内存空间得到充分应用。
“空洞”是编译器自动添加的没有被使用的内存空间。“空洞”中可能会存在一些随机数据或者为 0。优化数据结构可以减少或消除数据结构空间中的“空洞”。例如,在缺省情况下,编译器为数据结构和结构体中的成员分配空间时做对齐处理。例如,short a 以双字节对齐,inta以4字节对齐。结构体本身则以处理器支持的自然边界对齐。RISC-V RV32I处理器的自然边界宽度是4字节。优化结构体内成员的顺序,可以减少结构体中的“空洞”,缩短结构体所占用的内存空间的长度。
如图8.5所示,在图(a)中声明结构体 mydatal,图(b)是编译器为结构 mydatal分配的存储空间格式,结构体总长度为 12 字节。其中,“x”处是编译器添加的“空洞”,共有4字节“空洞”。
(a)结构体声明
struct mydatal {
char a;
int b;
char c;
short d;
}
(b)存储分配格式
地址 +0 +1 +2 +3
+0 a[7:0] x x x
+4 b[7:0] b[15:8] b[16:23] b[24:31]
+8 c[7:0] x d[15:8] d[7:0]
图 8.5 结构体声明(1)
将图8.5(a)中的结构体调整成员顺序得到如图 8.6(a)所示的结构体 mydata2译器为结构体 mydata2分配的存储空间,格式如图 8.6(b)所示,共 8 字节。matter智能家居espc2-c3公司深圳乐鑫芯片代理商调整成员顺序后,消除了“空洞”,结构体减少了 4 字节长度。
(a)结构体声明
struct mydata2{
char a;
char c;
short d;
int b;
}
(b)存储分配格式
地址 +0 +1 +2 +3
+0 a[7:0] c[7:0] d[15:8] d[7:0]
+4 b[7:0] b[15:8] b[23:16] b[31:24]
图8.6结构体声明(2)
在结构体添加关键字“packaged”,将结构体声明为紧致型结构。编译器对结构体中的成员不做对齐处理,不添加“空洞”,顺序排列。使用“packaged”能够缩短结构体总长度,但数据不对其将会增加处理器运行过程中访问数据时的开销。
2.RAM空间优化
matter智能家居espc2-c3公司深圳乐鑫芯片代理商在嵌入式系统中,程序运行时处理器可以从 ROM 取指令,也可以从 RAM 取指令。如果运行时程序代码在 ROM 中,则系统 RAM 只需提供序中的变量空间和程序运行时动态申请的空间。如果系统要求在 RAM 运行程序,则RAM还需提程序代码空间。
将编译器生成程序过程中分配的空间称为静态空间,而在程序运行过程中分配的空间称为动态空间。静态空间在整个程序活动期间内都有效,动态空间在程序运行时申请和释放。
在程序中应尽量使用动态内存空间,提高内存使用效率。
在示8.11(a)中,图像处理函数 void imageproc 分配了 3个图像数组空间,在函数活动期间占用3*M*N字节。在示例 8.11(b)中,函数 void imageproc 内,在需要时用malloc 申请空间,然后用free 释放,在函数活动期间大占用2*M*N字节。可见,使用动态申请内存更有利于优化内存空间。
示例8.11:内存空间分配。
(a)
void imageproc(......)
{
char a[m][N];
char b[M][N];
char c[M][N];
......
func1(a,b);
......
func2(b,c);
.....
}
--------------------------------------------------------
(b)
void imageproc(......)
{
char *a,*b,*c;
a=(char *)malloc(.--):
b=(char *)malloc(...);
......
func1(a, b);
free(a);
......
c=(char *)malloc(...);
func2(b,c);
......
free(b);
free(c);
}
优化数据类型和数据结构的方法同样也可用于优化 RAM空间。