Проблемы выделения памяти с микроконтроллером LPC1788
Я довольно новичок в программировании микроконтроллеров; Я работаю с LPC1788 уже пару недель.
Одна проблема, с которой я столкнулся в последнее время, заключается в том, что у меня заканчивается память гораздо раньше, чем я ожидаю. Я проверил, какой объем памяти кажется доступным, проверив, насколько большой блок непрерывной памяти я могу распределить, и в результате получается 972 байта. Распределение выполняется, начиная с адреса 0x10000000 (начало встроенного SRAM, которое должно быть около 64 КБ на этой плате).
Программа, над которой я сейчас работаю, предназначена для простого отладчика, который использует ЖК-дисплей и позволяет печатать на нем сообщения. У меня есть одна строка, которая будет постоянно "добавляться" новыми сообщениями, а затем все сообщение будет напечатано на ЖК-дисплее. Когда длина сообщения вниз по экрану выходит за вертикальную границу, он удаляет самые старые сообщения (те, что находятся ближе к вершине), пока не уместится. Однако я могу добавить только около 7 дополнительных сообщений, прежде чем он откажется выделять больше памяти. При необходимости файл main.c для проекта размещается по адресу http://pastebin.com/bwUdpnD3
Ранее я также начал работу над проектом, использующим RTOS-поток ThreadX для создания и выполнения нескольких потоков. Когда я попытался включить в эту программу использование ЖК-дисплея, я обнаружил, что память там тоже очень ограничена. Кажется, на ЖК-дисплее хранятся все данные пикселей, начиная с базового адреса SDRAM, но я не уверен, что это то же самое, что и SRAM, который я использую.
Что мне нужно, так это способ выделить память, достаточную для того, чтобы функционировать несколько потоков или хранить большие строки, при этом используя ЖК-дисплей. Одной из возможностей может быть использование буферов или других областей памяти, но я не совсем уверен, как это сделать. Любая помощь будет оценена.
tl; dr: быстро исчерпывается выделяемая память на 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: Реализованы исправления утечки памяти. Теперь программа работает намного лучше, и я чувствую себя довольно глупо.
1 ответ
Вы должны быть осторожны при выборе использования динамического выделения памяти во встроенной среде, особенно с ограниченной памятью. Вы можете очень легко в конечном итоге фрагментировать пространство памяти, так что самая большая оставшаяся дыра составляет 972 байта.
Если вам нужно выделить из кучи, сделайте это один раз, а затем повесьте на память - почти как статический буфер. Если возможно, используйте статический буфер и избегайте выделения всего вместе. Если вам необходимо динамическое распределение, то его сохранение в фиксированных блоках поможет с фрагментацией.
К сожалению, для преодоления проблемы фрагментации требуются небольшие инженерные усилия. Это стоит усилий, и это делает систему намного более надежной.
Что касается SRAM против SDRAM, они не одинаковы. Я не знаком с threadX, и есть ли у них пакет поддержки платы (BSP) для вашей платы, но в целом SDRAM должен быть настроен. Это означает, что загрузочный код должен инициализировать контроллер памяти, настроить время и затем включить это пространство. В зависимости от вашей реализации кучи, вам нужно динамически добавить ее или - что более вероятно - вам нужно скомпилировать пространство кучи, указывающее, где оно в конечном итоге будет жить (в пространстве SDRAM). Затем вы должны убедиться, что настроили и активировали управляемую память, прежде чем фактически использовать кучу.
Еще одна вещь, на которую следует обратить внимание: возможно, вы выполняете код из пространства SRAM, и часть этого пространства также зарезервирована для таблиц исключений процессора. Это целое пространство может быть недоступно и может жить, например, по двум разным адресам (0x00000000 и 0x10000000). Я знаю, что в некоторых других процессорах ARM9 это распространено. Вы можете загрузиться с флэш-памяти, которая изначально отображается в пространство 0x00000000, а затем вы исполняете песню и танец, чтобы скопировать загрузчик в SRAM и отобразить SRAM в это пространство. В этот момент вы можете загрузить что-то вроде Linux, который ожидает обновления таблиц с нулевым значением.
Кстати, похоже, у вас есть некоторые утечки памяти в коде, который вы опубликовали. А именно, currentMessage никогда не освобождается... только перезаписывается новым указателем. Эти блоки затем теряются навсегда.