Що я можу зробити, якщо у мене закінчиться Flash-пам'ять або SRAM?


28

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

У будь-якому випадку ці межі здаються досить невеликими, особливо в порівнянні з подібними за розмірами споживчими пристроями, наприклад смартфонами.

Що ти можеш зробити, якщо закінчишся? Наприклад, якщо ваш ескіз занадто великий, або вам потрібно обробити багато даних (наприклад, рядків) під час виконання? Чи є можливість розширити Flash або SRAM?


Спробуйте використовувати оптимальну оптимізацію. Деякі різні змінні обговорюються тут
TheDoctor

1
Використовуйте належні області застосування для своїх змінних, якщо цього ще не зробити, компілятор оптимізує використання оперативної пам’яті для вас, коли змінні не використовуються.
jippie

1
Насправді ви можете використовувати Teensy 3.2 (із програмним забезпеченням Teensyduino), який можна порівняти з Arduino. Зважаючи на те, що у вас не вистачає оперативної пам’яті / ПРОГМЕМИ, це означатиме, що ви ймовірно, що те, що ви намагаєтесь зробити, - це підштовхувати Arduino. A Teensy 3.2 не так вже й дорожче. але має: 32 біт, 72 МГц (wtf !?) 256 КБ флеш-пам’яті та 64 КБ оперативної пам’яті та 3x UART. Не більше програмної пам’яті, як ATmega2560, але оперативної пам’яті та збільшення швидкості повинно вистачити.
Пол

Відповіді:


30

Оптимізація
Програмування низького рівня для вбудованих систем сильно відрізняється від програмування для пристроїв загального призначення, таких як комп'ютери та мобільні телефони. Ефективність (з точки зору швидкості та простору) набагато важливіша, оскільки ресурси - це надбавка. Це означає, що найперше, що потрібно зробити, якщо у вас не вистачає місця, - це подивитися, які частини коду ви можете оптимізувати.

Щодо скорочення використання програмного простору (Flash), розмір коду може бути досить важким для оптимізації, якщо ви недосвідчені або якщо ви більше звикли програмувати настільні комп’ютери, які, як правило, не потребують цієї навички. На жаль, не існує підходу «магічної кулі», який би працював у будь-яких ситуаціях, хоча це допомагає, якщо ви серйозно розглядаєте те, що насправді має мати ваш ескіз . Якщо функція не потрібна, вийміть її.

Іноді також корисно визначити, де кілька частин вашого коду однакові (або дуже схожі). Можливо, ви зможете конденсувати їх у багаторазових функціях, які можна викликати з декількох місць. Однак майте на увазі, що іноді спроба зробити код занадто багаторазовим, насправді це робить його більш багатослівним. Це хитрий баланс, щоб досягти практики, яка, як правило, практикується. Витратити деякий час на перегляд того, як зміни коду впливають на вихід компілятора, може допомогти.

Оптимізація даних виконання (SRAM), як правило, трохи простіше, коли ви звикли до цього. Дуже поширеною проблемою для початківців програмістів є використання занадто багато глобальних даних. Все, що оголошено в глобальному масштабі, буде існувати протягом усього життя ескізу, і це не завжди потрібно. Якщо змінна використовується лише в одній функції і їй не потрібно зберігатись між дзвінками, то зробіть її локальною змінною. Якщо значення потрібно розділити між функціями, подумайте, чи можете ви передати його як параметр, а не робити його глобальним. Таким чином, ви будете використовувати SRAM лише для тих змінних, коли вам це потрібно.

Ще одним вбивцею для використання SRAM є обробка тексту (наприклад, використання Stringкласу). Взагалі кажучи, вам слід уникати операцій String, якщо це можливо. Вони - це масивні качани пам’яті. Наприклад, якщо ви виводите багато тексту в серійний цикл, використовуйте кілька дзвінків, Serial.print()а не використовуйте рядкове з'єднання. Спробуйте також зменшити кількість рядкових літералів у вашому коді, якщо можливо.

Уникайте рекурсії, якщо це можливо. Кожен раз, коли виконується рекурсивний дзвінок, стек стає глибше. Рефакторинг ваших рекурсивних функцій замість цього буде ітеративним.

Використовувати EEPROM
EEPROM застосовується для тривалого зберігання речей, які змінюються лише зрідка. Якщо вам потрібно скористатися великими списками або пошуковими таблицями фіксованих даних, то заздалегідь подумайте про їх збереження в EEPROM і лише витягніть те, що вам потрібно, коли це необхідно.

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

Розширення
Якщо ви вичерпали всі інші варіанти, то розширення може бути можливим. На жаль, розширення Flash-пам'яті для збільшення програмного простору неможливо. Тим НЕ менше, є можливість розширити SRAM. Це означає, що ви, можливо, зможете переробити ескіз для зменшення розміру коду за рахунок збільшення розміру даних.

Отримати більше SRAM насправді досить просто. Один з варіантів - використовувати один або кілька мікросхем 23K256 . Доступ до них здійснюється через SPI, і для їх використання є бібліотека SpiRAM . Тільки стережіться, що вони працюють на 3,3 В, а не на 5 В!

Якщо ви використовуєте Mega, ви також можете отримати екрани розширення SRAM від Lagrangian Point або Rugged Circuits .


1
Ви також можете зберігати постійні дані в пам'яті програми, а не SRAM, якщо у вас є проблеми з простором SRAM та вільною пам'яттю програми. Дивіться тут чи тут
Connor Wolf

1
Ще одна чудова альтернатива EEPROM - це карта SD. Він займає кілька портів вводу-виводу, але якщо вам потрібен великий шматок місця для, скажімо, даних карти чи подібного, їх можна легко замінити та редагувати за допомогою спеціальної програми на ПК.
Анонімний пінгвін

1
Не слід заохочувати людей використовувати SPI SRAM або розширення оперативної пам’яті, якщо у них мало пам'яті. Це просто марнотратство. Вибір більшого MCU був би дешевшим. Крім того, продуктивність може бути дуже поганою. Спершу слід зробити оцінку бального парку: якщо передбачуване використання оперативної пам’яті занадто близько до межі, то ви вибираєте неправильну платформу / мікроконтролер / платформу розвитку. Звичайно, хороше використання (зберігання рядків у спалах) та оптимізація (уникаючи використання деяких бібліотек) можуть бути справжніми змінами гри. Однак на даний момент я не бачу переваг використання платформи Arduino Software.
наступний хак

24

Коли ви завантажите свій код у свій Arduino, скажімо, наприклад, Uno, він підкаже, скільки байтів він використовує з наявних 32K. Ось скільки у вас флеш-пам’яті (думаю, жорсткий диск комп'ютера). Поки ваша програма працює, вона використовує те, що називається SRAM, і доступного набагато менше.

Іноді ви помітите, що ваша програма дивно поводиться в той момент, якого ви навіть не торкалися за деякий час. Можливо, ваші останні зміни призведуть до того, що у нього не вистачить пам'яті (SRAM). Ось кілька порад, як звільнити деякі SRAM.

Збереження рядків у Flash замість SRAM.

Одна з найпоширеніших речей, яку я бачив, - це чіп, що втрачає пам'ять, оскільки занадто багато довгих рядків.

Використовуйте F()функцію при використанні рядків, щоб вони зберігалися у Flash замість SRAM, оскільки у вас є набагато більше доступного.

Serial.println(F("This string will be stored in flash memory"));

Використовуйте правильні типи даних

Ви можете зберегти байт, перейшовши з int(2 байти) на byte(1 байт). Непідписаний байт дасть вам 0-255, тому якщо у вас є цифри, які не перевищують 255, збережіть байт!

Звідки я знаю, що мені не вистачає пам'яті?

Зазвичай ви спостерігаєте, як ваша програма поводиться дивно, і замислюєтеся, що пішло не так ... Ви нічого не змінили в коді поблизу точки, де вона псується, і що дає? У нього не вистачає пам'яті.

Існує пара функцій, щоб повідомити, скільки у вас є пам’яті.

Наявна пам'ять


Чи знаєте ви, чи F()річ є специфічною для Arduino функцією чи вона є в бібліотеках AVR? Ви також можете згадати PROGMEM const ....
jippie

Також ви можете використовувати бітові структури для подальшого зменшення простору, використовуваного вашими змінними 5eg, якщо ви маєте справу з великою кількістю булів).
jfpoilpret

17

Окрім того, що сказали інші (з чим я цілком згоден), я б радив прочитати цю статтю про пам’ять про пам’ять; це добре написано, пояснює багато речей щодо пам’яті та дає підказки щодо її оптимізації.

Наприкінці прочитаного, я думаю, ви отримаєте цілком повну відповідь на своє запитання.

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

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

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


1
Видалення мертвого коду - компілятор дійсно добре справляється з цим для вас - це не матиме ніякої різниці, якщо у вас буде багато коду, який ніколи не викликався. Якщо ви випадково зателефонували до коду, який вам не потрібен, то, звичайно, це інакше.
dethSwatch

9

Якщо у вас не вистачає пам’яті, можна зробити дві речі:

  • Якось «оптимізуйте» свій код, щоб він потребував меншої кількості пам’яті; або принаймні використовує менше конкретного типу пам’яті, у якого ви закінчилися (і використовує більше того типу пам’яті, якого у вас ще багато). Або,
  • Додайте більше пам’яті.

В Інтернеті є багато порад щодо того, як зробити перший (і для переважної більшості речей, які люди роблять з Arduino, вбудованого сховища більш ніж достатньо після "оптимізації"). Тож я зупинюсь на другому:

Є три речі, які використовують спалах або SRAM; кожен потребує дещо іншого підходу до додавання пам’яті:

  • змінне сховище: можна розширити SRAM, як уже вказував Sachleen. SRAM, FRAM і NVSRAM всі підходять для швидко мінливих змінних. (Хоча в принципі ви можете використовувати Flash для зберігання змінних, тоді вам доведеться турбуватися про зношеність спалаху). SPI (послідовний протокол) найпростіше підключити до Arduino. Бібліотека SpiRAM працює з мікросхемою послідовного SRAM Microchip 23K256 . Серійний чіп FRAM Ramtron FM25W256 (тепер належить Cypress) також використовує SPI. Cypress CY14B101 NVSRAM також використовує SPI. І т.д.

  • постійні дані, які ще мають бути при наступному включенні живлення: це майже так само просто, як і розширення SRAM. Є багато зовнішніх пристроїв зберігання даних EEPROM, FRAM, NVSRAM та FLASH . В даний час найнижчою ціною за МБ є флеш-карти SD (доступ до яких можна отримати через SPI). Ramtron FM25W256 (див. Вище), Cypress CY14B101 (див. Вище) тощо можуть також зберігати постійні дані. Багато екранів розширення містять слот для SD-карт, а кілька бібліотек та навчальних посібників підтримують читання та запис на (флеш) SD-карти. (Ми не можемо використовувати SRAM для цього, тому що SRAM забуває все, коли живлення згасає).

  • виконуваний код: На жаль, розширити флеш-пам’ять Arduino для збільшення програмного простору неможливо. Однак програміст завжди може переробляти ескіз, щоб зменшити розмір коду за рахунок збільшення розміру даних та змушування його працювати трохи повільніше. (Теоретично, ви можете зайти так далеко, як перекласти весь ескіз на якусь інтерпретовану мову, зберегти цю версію ескізу на SD-картці, а потім написати інтерпретатор для тієї мови, який працює на Arduino, щоб отримати та виконати інструкції з SD-карта - далі Arduino , перекладач BASIC, перекладач Пікаро Тома Нап'є, певна мова програми та ін.).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.