Что делать, если у меня закончилась флэш-память или SRAM?

Согласно документации Arduino, ATmega328 имеет 32 Кбайт флэш-памяти для загружаемого загрузчика + загруженного эскиза и только 2 Кбайт SRAM для данных времени выполнения. ATmega2560 имеет немного больше, всего 256 Кбайт и 8 КБ соответственно.

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

Что вы можете сделать, если закончите? Например. если ваш эскиз слишком велик, или вам нужно обрабатывать большое количество данных (например, строк) во время выполнения? Есть ли способ расширить Flash или SRAM?

24 голоса | спросил Peter Bloomfield 15 FebruaryEurope/MoscowbSat, 15 Feb 2014 05:09:33 +0400000000amSat, 15 Feb 2014 05:09:33 +040014 2014, 05:09:33

4 ответа


26

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

С точки зрения сокращения использования программного пространства (Flash), размер кода может быть довольно сложно оптимизировать, если вы неопытный, или если вы больше привыкли к программированию для настольных компьютеров, которые не имеют такого навыка , К сожалению, не существует подхода «волшебной пули», который будет работать для всех ситуаций, хотя это поможет, если серьезно подумать о том, что нужно для вашего эскиза . Если функция не нужна, выньте ее.

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

Оптимизация времени выполнения (SRAM), как правило, немного легче, когда вы привыкли к ней. Очень распространенная ошибка для начинающих программистов - использование слишком больших глобальных данных. Все, что объявлено в глобальном масштабе, будет существовать на протяжении всего жизненного цикла эскиза, и это не всегда необходимо. Если переменная используется только внутри одной функции, и она не должна сохраняться между вызовами, тогда сделайте ее локальной. Если значение должно быть разделено между функциями, подумайте, можете ли вы передать его как параметр, а не делать его глобальным. Таким образом, вы будете использовать SRAM только для этих переменных, когда вам это действительно нужно.

Другим убийцей для использования SRAM является обработка текста (например, с использованием класса String). Вообще говоря, вам следует избегать выполнения строковых операций, если это возможно. Это огромные болота памяти. Например, если вы отправляете много текста в последовательный, используйте несколько вызовов Serial.print () вместо использования конкатенации строк. Также попробуйте уменьшить количество строковых литералов в вашем коде, если это возможно.

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

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

Очевидно, что EEPROM довольно ограничен по размеру и скорости, но имеет ограниченное количество циклов записи. Это не отличное решение для ограничения данных, но этого может быть достаточно, чтобы облегчить нагрузку на Flash или SRAM. Также вполне возможно взаимодействовать с подобным внешним хранилищем, например с SD-картой.

Расширение
Если вы исчерпали все другие варианты, расширение может быть возможно. К сожалению, расширение флэш-памяти для увеличения программного пространства невозможно. Тем не менее, можно расширить SRAM. Это означает, что вы можете реорганизовать свой эскиз, чтобы уменьшить размер кода за счет увеличения размера данных.

Получение большего количества SRAM на самом деле довольно просто. Один из вариантов заключается в использовании одного или нескольких 23K256 фишек. Доступ к ним осуществляется через SPI, а библиотека SpiRAM помогает вам их использовать. Просто остерегайтесь, что они работают при 3,3 В не 5V!

Если вы используете Mega, вы можете использовать щиты расширения SRAM от Лагранжская точка или Прочные схемы .

ответил Peter Bloomfield 15 FebruaryEurope/MoscowbSat, 15 Feb 2014 05:09:33 +0400000000amSat, 15 Feb 2014 05:09:33 +040014 2014, 05:09:33
21

Когда вы загружаете свой код в Arduino, скажем, Uno, например, он расскажет вам, сколько байтов оно использует из доступного 32K. Вот сколько флэш-памяти у вас (думаю, компьютер жесткий диск). Пока ваша программа запущена, она использует то, что называется SRAM, и есть гораздо меньше доступного.

Иногда вы заметите, что ваша программа ведет себя странно в той точке, которую вы даже не коснулись в то время. Возможно, ваши последние изменения приводят к тому, что у него заканчивается память (SRAM). Вот несколько советов о том, как освободить некоторые SRAM.

Сохранение строк во Flash вместо SRAM.

Одна из самых распространенных вещей, которые я видел, - это чип, заканчивающийся памятью, потому что слишком много длинных строк.

Используйте функцию F () при использовании строк, чтобы они были сохранены во Flash вместо SRAM, так как у вас есть гораздо больше доступных.

Serial.println (F («Эта строка будет сохранена во флэш-памяти»));

Используйте правильные типы данных

Вы можете сохранить байт, переключившись с int (2 байта) на byte (1 байт). Беззнаковый байт даст вам 0-255, поэтому, если у вас есть номера, которые не превышают 255, сохраните байт!

Как узнать, что у меня заканчивается память?

Обычно вы будете наблюдать, как ваша программа ведет себя странно и задается вопросом, что пошло не так ... Вы ничего не изменили в коде рядом с точкой, где это испортилось, и что дает? У него заканчивается память.

Есть несколько функций, чтобы рассказать вам, сколько доступной памяти у вас есть.

Доступная память

ответил sachleen 15 FebruaryEurope/MoscowbSat, 15 Feb 2014 07:24:15 +0400000000amSat, 15 Feb 2014 07:24:15 +040014 2014, 07:24:15
15

В дополнение к тому, что сказали другие (о чем я полностью согласен), я бы посоветовал прочитать эту статью adafruit о памяти; это хорошо написано, объясняет многое о памяти и дает подсказки о том, как ее оптимизировать.

В конце прочитанного, я думаю, вы получите вполне полный ответ на свой вопрос.

Подводя итог, у вас есть две возможные цели оптимизации (в зависимости от того, где находятся проблемы с памятью):

  • Flash (т. е. память программ); для этого вы можете:
    • удалить мертвый код (например, любой код, который включен, но не используется) и неиспользуемые переменные (что также помогает с SRAM)
    • выдать дубликат кода
    • удалить загрузчик в целом (вы можете получить от 0,5 КБ для UNO и 2 или 4 К для других моделей Arduino); это имеет некоторые недостатки, хотя
  • SRAM (т.е. стек, куча и статические данные); для этого вы можете:
    • удалить неиспользуемые переменные
    • оптимизировать размер каждой переменной (например, не использовать длинные -4 байта - если вам нужно только int -2 байта)
    • используйте правильную область для ваших переменных (и, когда это возможно, предпочитайте стек для статических данных)
    • уменьшить размер буферов до строгого минимума
    • переместить постоянные данные в PROGMEM (т. е. ваши статические данные останутся во флэш-памяти и не будут скопированы в SRAM при запуске программы); это также относится к константным строкам, для которых вы можете использовать макрос F ())
    • избегать динамического распределения, если это не является абсолютно необходимым; вы избежите фрагментированной кучи , которая не может сжиматься даже после освобождения памяти

Также описывается дополнительный подход к сокращению использования SRAM (но редко используется, потому что он очень тяжелый при кодировании и не очень эффективен), он заключается в использовании EEPROM для хранения данных, созданных вашей программой, но не используемых до тех пор, пока позже когда происходят некоторые условия, когда данные могут быть загружены обратно из EEPROM.

ответил jfpoilpret 15 FebruaryEurope/MoscowbSat, 15 Feb 2014 21:28:24 +0400000000pmSat, 15 Feb 2014 21:28:24 +040014 2014, 21:28:24
8

Есть две вещи, которые можно сделать, если у вас закончилось хранение:

  • Как-то «оптимизируйте» свой код, чтобы ему было меньше памяти; или, по крайней мере, использует меньше определенного типа хранилища, на котором вы закончили (и использует больше того хранилища, которое у вас все еще есть). Или,
  • Добавить хранилище.

В Интернете есть множество советов о том, как сделать первый (и для подавляющего большинства людей, которые делают с Arduino, встроенное хранилище более чем достаточно после «оптимизации»). Поэтому я сосредоточусь на втором:

Есть 3 вещи, которые используют вспышку или SRAM; каждый из них требует немного другого подхода к добавлению хранилища:

  • переменная память: возможно расширение SRAM, как уже указывал sachleen. SRAM, FRAM и NVSRAM подходят для быстро меняющихся переменных. (Хотя в принципе вы можете использовать flash для хранения переменных, тогда вам нужно беспокоиться об износе флэш-памяти). SPI (последовательный протокол) является самым простым для подключения к Arduino. библиотека SpiRAM работает с Microchip 23K256 последовательный чип SRAM. Микросхема Ramtron FM25W256 серийная FRAM (теперь принадлежащая Cypress) также использует SPI. Cypress CY14B101 NVSRAM также использует SPI. Etc.

  • постоянные данные, которые все еще должны присутствовать при следующем включении питания: это почти так же просто, как расширение SRAM. Существует множество внешних устройств хранения EEPROM, FRAM, NVSRAM и FLASH . В настоящее время самая низкая стоимость на МБ - SD-карты (к которым можно получить доступ через SPI). Ramtron FM25W256 (см. Выше), Cypress CY14B101 (см. Выше) и т. Д. Также могут хранить постоянные данные. Многие экраны расширения включают в себя слот для SD-карты, и несколько библиотек и tutorials поддерживает чтение и запись на (flash) SD-карты. (Мы не можем использовать SRAM для этого, потому что SRAM забывает все, когда питание гаснет).

  • исполняемый код: К сожалению, расширение флеш-памяти Arduino для увеличения программного пространства невозможно. Тем не менее, программист всегда может реорганизовать эскиз, чтобы уменьшить размер кода за счет увеличения размера данных и сделать его несколько медленнее. (Теоретически вы могли бы перевести весь свой эскиз на какой-то интерпретируемый язык, сохранить эту версию своего эскиза на SD-карте и затем написать интерпретатор для этого языка, который работает на Arduino для извлечения и выполнения команд из SD-карта - Forth on Arduino , интерпретатор BASIC, интерпретатор Tom Napier Picaro, некоторые языки приложения и т. Д. .).

ответил David Cary 16 FebruaryEurope/MoscowbSun, 16 Feb 2014 01:21:34 +0400000000amSun, 16 Feb 2014 01:21:34 +040014 2014, 01:21:34

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132