与速度优化不同,RAM 优化可能需要“这里一点点,那里一点点”贯穿整个代码。另一方面,结果可能是一些“容易实现的成果”。
数组和查找表
数组和查找表可能是很好的“容易实现的目标”。如果您可以从链接器获取内存映射,请检查 RAM 中的大型项目。
检查未正确使用 const 声明的查找表,这会将它们放入 RAM 而不是 ROM。尤其要注意指针的查找表,它需要在* 的正确一侧使用const,或者可能需要两个 const 声明。例如:
const my_struct_t * param_lookup[] = {...}; // Table is in RAM!
my_struct_t * const param_lookup[] = {...}; // In ROM
const char * const strings[] = {...}; // Two const may be needed; also in ROM
堆栈和堆
也许您的链接器配置为堆和堆栈保留了大量 RAM,比您的应用程序所需的要大。
如果你不使用堆,你可以消除它。
如果您测量您的堆栈使用情况并且它在分配范围内,您可以减少分配。对于 ARM 处理器,可以有多个堆栈,用于几种操作模式,您可能会发现分配给异常或中断操作模式的堆栈比需要的大。
其他
如果您已经检查了容易节省的费用,但仍然需要更多,您可能需要检查您的代码并“这里一点,那里一点”进行节省。您可以检查以下内容:
全局变量与局部变量
检查static 或全局变量的不必要使用,其中可以使用局部变量(在堆栈上)来代替。我见过在函数中需要一个小的临时数组的代码,它被声明为static,显然是因为“它会占用太多的堆栈空间”。如果这种情况在代码中发生的次数足够多,它实际上会节省总体内存使用量,以使这些变量再次成为本地变量。它可能需要增加堆栈大小,但会在减少的全局/静态变量上节省更多内存。 (作为附带的好处,这些函数更有可能是可重入的、线程安全的。)
较小的变量
可以更小的变量,例如int16_t (short) 或 int8_t (char) 而不是 int32_t (int)。
枚举变量大小
enum 变量大小可能比需要的大。我不记得 ARM 编译器通常做什么,但我过去使用的一些编译器默认将 enum 变量设为 2 个字节,尽管 enum 定义实际上只需要 1 个字节来存储其范围。检查编译器设置。
算法实现
重做你的算法。一些算法具有一系列可能的实现,具有速度/内存权衡。例如。 AES 加密可以使用即时密钥计算,这意味着您不必将整个扩展密钥保存在内存中。这样可以节省内存,但速度较慢。