Рекомендации по управлению стеком / памятью PIC18? - PullRequest
6 голосов
/ 04 ноября 2010

Ограниченный размер стека бюджетных PIC - это проблемная область, и я изменил свой код, чтобы приспособиться к этой реальности.В настоящее время я использую грубую парадигму группировки тесно связанных функций в модуле и объявления всех переменных глобальной статической в ​​модуле (чтобы уменьшить количество переменных, хранящихся в auto psect, и проблемы изменчивости актуальны только в ISR, которые я объясняю.) Я не делаю этого, потому что это хорошая практика, но реальность такова, что у вас есть ограниченное пространство для выделения всех локальных переменных функций, которые существуют во всем проекте.Является ли этот метод подходящим для встроенного мира 8/16-битных микросхем, если я обязательно приму необходимые меры предосторожности?Я также делаю такие вещи, как выделение> 256 байтов ОЗУ для Ethernet (я знаю, что это должно быть 1500 в качестве стандартного MTU, но у нас есть нестандартная ситуация и очень ограниченная ОЗУ) буферы, и мне приходится обращаться к этой памяти через указатели, чтобы я мог избежать семантикибанковской памяти.Я делаю это неправильно?Мое приложение работает, но я на 100% открыт для предложений по улучшению.[С]

Ответы [ 7 ]

4 голосов
/ 15 августа 2014

Я знаю, что об этом спрашивали 4 года назад, но до сих пор не ответили правильно. Я полагаю, что OP спрашивает, является ли их подход к работе с ограничением допустимого и / или наилучшего опыта компилятора HiTech PICC18 C. Как упомянуто в последующем комментарии, ограничение (довольно плохое и не очень хорошо рекламируемое Hitech) заключается в том, что «высокотехнологичный компилятор допускает только 256 байтов автоматических переменных». На самом деле ограничение хуже, чем это, поскольку оно составляет 256 байтов для локальных переменных и параметров. Предупреждение компоновщика, когда это превышено, также довольно загадочно. При условии, что функции находятся в разных ветвях дерева вызовов, компилятор может перекрывать переменные, чтобы повторно использовать пространство. Это означает, что вы можете иметь более 256 байтов. Но обратите внимание, что обработчик прерываний (или обработчики, если вы используете схему приоритетов) имеет свое собственное дерево вызовов, которое совместно использует 256-байтовый блок local / param.

Местные жители Два решения по сокращению пространства, необходимого для местных жителей: сделать глобальные локальные или сделать их статичными. Делая их статичными, вы сохраняете область действия одинаковой, и при условии, что функция не вызывается из прерываний, это безопасно (компилятор все равно не разрешает аренду). Это, вероятно, предпочтительный вариант. Недостатком является то, что компилятор не может повторно использовать местоположения этих переменных, чтобы уменьшить общее потребление памяти. Перемещение переменных в глобальную область позволяет повторное использование, но управление повторным использованием должно управляться программистом. Вероятно, лучший баланс - сделать простые переменные статичными, но сделать глобальные большие куски памяти, такие как строковые буферы, и аккуратно их использовать.

Будьте осторожны с инициализацией.

foo()
{
 int myvar = 5;
}

должно измениться на

foo()
{
 static int myvar;
 myvar = 5;
}

Параметры Если вы будете передавать большие объемы данных по дереву вызовов в параметрах, вы быстро столкнетесь с тем же ограничением в 256 байт. Лучшим вариантом здесь может быть передача указателя на глобально распределенную структуру / параметры «options». В качестве альтернативы вы можете иметь переменные глобальных настроек, которые устанавливаются главным вызывающим пользователем и читаются вызываемыми пользователями по дереву. Это действительно зависит от дизайна программного обеспечения, какой подход лучше.

Я боролся с теми же проблемами, что и OP, и я думаю, что в конечном итоге лучше всего отказаться от использования компилятора Hitech. Решение об оптимизации, принятое авторами компилятора для размещения всех локальных элементов / параметров в одном блоке, действительно действительно подходит для PICS очень малого размера памяти. Для больших PICS вы исчерпаете local / param до того, как достигнете размера оперативной памяти устройства. Затем вы должны начать взламывать свой код, чтобы он соответствовал компилятору, который является извращенным.

В итоге ... Да, ваш подход действителен. Но подумайте просто о том, чтобы сделать локальные объекты статичными, если это уместно, так как в целом уменьшение области действия делает ваш код более безопасным.

2 голосов
/ 13 августа 2013

В то время как компилятор C18 использовал несколько FSR (указателей) для управления стеком данных, похоже, что новый компилятор XC8 от Microchip использует скомпилированный стек, поэтому вы должны точно знать, сколько места занимает стек во время компиляции,Вы также будете точно знать, где хранится каждая переменная стека.Я прочитал все об этом в руководстве пользователя XC8 , и это звучит великолепно.Эта функция должна сделать этот вопрос спорным, если вы используете XC8.

1 голос
/ 04 ноября 2010

Мой опыт работы с компиляторами / компоновщиками для чипов с ограниченной памятью заключается в том, что, если вы не используете рекурсивные функции и не сообщаете об этом компилятору, то компилятор очень способен определить минимальный объем стекового пространства, нужен.
Я даже видел компиляторы, которые дают каждой переменной с автоматическим хранением глобально фиксированный адрес (без стека вообще), где несколько переменных были выделены для перекрывающейся памяти, пока их время жизни не перекрывалось.

Общие рекомендации при оптимизации (скорости или пространства): проводите измерения, чтобы доказать, что ваша оптимизация действительно имеет положительный эффект.

0 голосов
/ 05 декабря 2012

Этот миг звучит очевидно, но старайтесь не использовать 16-битные переменные на 8-битных прецессорах. 16-битные переменные хороши и необходимы для больших архитектур, но в ограниченных (8-битных) архитектурах 16-битная арифметика - быстрый способ быстро и оперативно исчерпать память RAM и ROM.

Если вы попытаетесь увеличить 16-битную переменную, компилятор будет включать 16-битную библиотеку приращений, которая в большинстве случаев потребляет много места.

Кроме того, старайтесь не делить и не умножать, поскольку для некоторых контроллеров они реализованы программно.

Лично я всегда иду на char, и когда мне нужна операция деления, используйте вращение 'n' раз, чтобы разделить на 2 n раз.

надеюсь, это поможет!

0 голосов
/ 13 января 2012

Немного поздно, но вы также должны внимательно посмотреть руководство пользователя компилятора C18 (если вы использовали этот компилятор).

Вы можете значительно уменьшить стек, статически выделяя локальные переменные (переопределяя ключевое слово auto). Более того, вы можете использовать оверлейный идентификатор хранилища, который позволяет размещать разные непересекающиеся переменные времени жизни на одном и том же адресе, минимизируя объем оперативной памяти. (Компилятор C18 должен работать в не расширенном режиме).

0 голосов
/ 04 ноября 2010

Лучше всего выбрать оборудование, соответствующее требованиям.

Существуют микроконтроллеры, которые стоят всего лишь на несколько долларов дороже, но экономят сотни или тысячи долларов на разработке.Если это развитие хобби, ваши усилия могут не учитываться.Но в реальном мире вы часто можете найти оборудование, которое разработано только с учетом затрат на оборудование.

Особенно PIC18 - не лучший пример для компактного кода, что также может быть проблемой с флэш-памятью.

0 голосов
/ 04 ноября 2010

Поскольку у вас почти не осталось памяти, вы должны считать каждый байт оперативной памяти. Использование локальных переменных (авто) позволяет повторно использовать память там, где она вам нужна (локально в функции). Когда вы перемещаете переменные в глобальное статическое адресное пространство, вы присваиваете каждой переменной уникальное пространство. Это потеря адресного пространства.

Компилятор Microchip позволяет разным переменным иметь один и тот же адрес. У меня нет документов под рукой, но это можно сделать с помощью прагмы.

Но вам нужен анализ требований к оперативной памяти. Когда вы видите, что стек не может содержать все переменные, но автоматические переменные уменьшат использование глобальной памяти, вам следует рассмотреть возможность увеличения размера стека с помощью кода запуска и сценария компоновщика.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...