Contiki 中的内存溢出

Memory overflow in Contiki

我正在开发一个需要 msp430 数学函数的应用程序。使用 powf、sqrt 等函数时,会发生内存溢出 (ROM)。一个这样的例子是,当我使用这个 float i 变量而不使用静态时,我的代码可以工作。

#include "contiki.h"

#include <stdio.h> /* For printf() */
#include <math.h>
#define DEBUG DEBUG_NONE
/*---------------------------------------------------------------------------*/
PROCESS(hello_world_process, "Hello world process");
AUTOSTART_PROCESSES(&hello_world_process);
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(hello_world_process, ev, data)
{
  PROCESS_BEGIN();
  float i;
  i = 2.1;
  printf("Hello, world\n");
  printf("%i\n", (int)powf(10,i));
  PROCESS_END();
}
/*---------------------------------------------------------------------------*/

但是在第二种情况下它不起作用...

#include "contiki.h"

#include <stdio.h> /* For printf() */
#include <math.h>
#define DEBUG DEBUG_NONE
static float i;
/*---------------------------------------------------------------------------*/
PROCESS(hello_world_process, "Hello world process");
AUTOSTART_PROCESSES(&hello_world_process);
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(hello_world_process, ev, data)
{
  PROCESS_BEGIN();
  i = 2.1;
  printf("Hello, world\n");
  printf("%i\n", (int)powf(10,i));
  PROCESS_END();
}
/*---------------------------------------------------------------------------*/

建议升级msp430-gcc,但可能会导致系统不稳定。还有其他有效处理内存溢出的建议吗?

可以遵循哪些方法来有效管理嵌入式系统中的内存。

在第一种情况下,符号 i 是局部的(在函数的堆栈帧上),因此编译器能够优化函数调用并计算 powf(10, 2.1) 的值在编译时。第二种情况,符号i定义在函数外。

优化器没有看到它没有被主进程外部的一些其他代码修改。因此它不会优化 powf ,你最终会尝试 link 具有浮点功能。由于 msp430 不支持硬件中的浮点数,linker 最终尝试向可执行文件中添加大量二进制代码。可执行文件太大,linking 失败。

升级编译器并不能神奇地解决问题。你需要释放一些内存。遵循 Contiki 配置指南:https://github.com/contiki-os/contiki/wiki/Reducing-Contiki-OS-firmware-size

如果您需要节省 RAM,您可以考虑减少:

QUEUEBUF_CONF_NUM:link层队列的包数。 4 可能是合理操作的下限。随着交通负荷的增加,例如更频繁的流量或更大的数据报,您将需要增加此参数。

NBR_TABLE_CONF_MAX_NEIGHBORS:邻居中的条目数table。大于最大网络密度的值是安全的。低于该值的值也有效,因为邻居 table 将自动关注相关邻居。但是太低的值会导致性能下降。

NETSTACK_MAX_ROUTE_ENTRIES:路由表项的个数,即在RPL非存储模式下,路由图中的link个数,在存储模式下,路由table元素。在网络根,这必须设置为最大网络大小。在非存储模式下,其他节点可以将此参数设置为0。在存储模式下,建议所有节点也为网络中的每个节点提供足够的条目。 UIP_CONF_BUFFER_SIZE:IPv6 缓冲区的大小。互操作性的最小值为 1280。在不使用大数据报的封闭系统中,将其降低到例如140可能是明智的。

SICSLOWPAN_CONF_FRAG: Enables/disables 6LoWPAN 碎片。如果您的所有流量都适合单个 link 层数据包,请禁用此选项。请注意,这也会节省一些重要的 ROM。 如果需要保存ROM,可以考虑以下:

UIP_CONF_TCP: Enables/disables TCP。确保在未使用 TCP 时禁用此功能。

UIP_CONF_UDP: Enables/disables UDP。确保在不使用 UDP 时禁用它。

SICSLOWPAN_CONF_FRAG:如上所述。如果不需要碎片则禁用。

LOG_CONF_LEVEL_*:日志占用ROM大。降低日志级别以节省更多。

还有许多其他参数会影响 RAM/ROM 使用。您可以检查 os/contiki-default-conf.h 以及特定于平台的 contiki-conf.h 文件以获取灵感。或者使用 .flashprof 和 .ramprof 来识别热点。

*Contiki wiki 教程中的回答:RAM 和 ROM 的使用 乔治·奥科诺穆