0

我对微控制器编程还很陌生;我已经用 LPC1788 工作了几个星期了。

我最近遇到的一个问题是我的内存比我预期的要快得多。我已经通过测试我可以 malloc 有多大的连续内存块来测试似乎有多少内存可用,结果是 972 字节。分配从地址 0x10000000 开始(该板上的片上 SRAM 的开始位置应该在 64kB 左右)。

我目前正在开发的程序旨在充当一个简单的调试器,它利用 LCD 并允许向其打印消息。我有一个字符串会不断被新消息“添加到”,然后整个消息将打印在 LCD 上。当消息在屏幕下方的长度超过垂直边界时,它将删除最旧的消息(靠近顶部的消息),直到适合为止。但是,在它拒绝分配更多内存之前,我只能添加大约 7 条额外的消息。如果需要,该项目的 main.c 托管在http://pastebin.com/bwUdpnD3

早些时候,我还开始了一个使用 threadX RTOS 创建和执行多个线程的项目。当我尝试在该程序中使用 LCD 时,我发现那里的内存也非常有限。LCD 似乎存储了从 SDRAM 基地址开始的所有像素数据,但我不确定这是否与我使用的 SRAM 相同。

我需要的是一种分配足够内存的方法,以允许多个线程运行或存储大字符串,同时能够利用 LCD。一种可能是使用缓冲区或其他内存区域,但我不太确定如何做到这一点。任何帮助,将不胜感激。

tl;dr:当试图在 LCD 上打印大字符串时,SRAM 上的可分配内存很快就会用完。

编辑 1:发现变量 currMessage 存在内存泄漏。我认为现在已经解决了:

strcpy(&trimMessage[1], &currMessage[trimIndex+1]);

// Frees up the memory allocated to currMessage from last iteration
// before assigning new memory.
free(currMessage);
currMessage = malloc((msgSize - trimIndex) * sizeof(char));
for(int i=0; i < msgSize - trimIndex; i++)
{
  currMessage[i] = trimMessage[i];
}

编辑 2:实施内存泄漏修复。程序现在运行得更好了,我觉得很愚蠢。

4

1 回答 1

1

在嵌入式环境中选择使用动态内存分配时需要小心,尤其是在内存受限的情况下。您可以很容易地最终分割内存空间,使得剩下的最大空洞是 972 字节。

如果您必须从堆中分配,请执行一次,然后挂在内存上——几乎就像一个静态缓冲区。如果可能,请使用静态缓冲区并避免一起分配。如果您必须进行动态分配,则将其保持在固定大小的块中将有助于碎片化。

不幸的是,克服碎片问题确实需要一些工程努力。付出努力是值得的,而且它确实使系统更加健壮。

至于 SRAM 与 SDRAM,它们并不相同。我不熟悉threadX,也不熟悉他们是否为您的电路板提供电路板支持包(BSP),但总的来说,必须设置SDRAM。这意味着引导代码必须初始化内存控制器,设置时序,然后启用该空间。根据您的堆实现,您需要动态添加它,或者 - 更有可能 - 您需要使用指向它最终将存在的位置(在 SDRAM 空间中)的堆空间进行编译。然后,您必须确保在实际使用堆之前启动并配置和激活内存控制。

需要注意的另一件事是,您实际上可能正在从 SRAM 空间运行代码,并且其中一些空间还保留给处理器异常表。例如,整个空间可能不可用,并且可能通过两个不同的地址(0x00000000 和 0x10000000)存在。我知道在其他一些 ARM9 处理器中,这很常见。您可以从闪存启动,该闪存最初被映射到 0x00000000 空间,然后您就可以将引导程序复制到 SRAM 并将 SRAM 映射到该空间。那时,您可以启动到 Linux 之类的系统,它希望能够更新在 0 时停止运行的表。

顺便说一句,看起来您发布的代码中确实存在一些内存泄漏。也就是说, currentMessage 永远不会被释放......只会被新的指针覆盖。然后这些块将永远丢失。

于 2012-08-31T09:31:24.560 回答