AVR105: эффективное сохранение параметров в памяти FLASH Печать
Добавил(а) microsin   

В даташите AVR105 рассматриваются вопросы хранения параметров в памяти FLASH:

• Быстрое сохранение параметров
• Износостойкое хранение – до 350 тысяч циклов записи
• Эффективность хранения с точки зрения энергопотребления
• Хранение параметров произвольного размера
• Надежность хранения параметров
• Опциональная верификация записанных параметров
• Опциональное восстановление после сбоя питания

Встраиваемые системы (embedded) полагаются на использование параметров, которые могут сохранять свое значение между сбросами (RESET) и пропаданиями питания. В некоторых системах эта статическая информация используется для инициализации системы в корректное состояние в момент запуска (start-up), в других системах это используется для лога истории системы или для накопления данных. С этой целью можно использовать память EEPROM, однако её скорость не может сравниться со скоростью памяти FLASH, когда нужно в одно и то же время сохранить несколько байт.

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

Этот апноут описывает, как реализовать щадящий к трате ресурса перезаписи метод хранения данных в памяти FLASH, используя возможность самопрограммирования микроконтроллеров AVR [2]. С помощью использования страницы FLASH целиком и метода доступа, похожего на кольцевой буфер, каждая одиночная ячейка памяти страницы FLASH не будет использоваться так же часто, как если бы использовалась одна ячейка вместо страницы. Этот метод увеличивает стойкость хранилища, экономя ценный ресурс перезаписей страницы, что гарантирует, что область хранения не будет изношена в течение расчетного срока эксплуатации. Величина экономии ресурса пропорциональна соотношению между размером сохраняемого параметра и размером страницы, выделенной под "буфер" хранения.

[Немного теории: как это работает]

Современная серия микроконтроллеров megaAVR® имеет возможность самопрограммирования, широко используемую для создания загрузчиков кода (bootloader). Это позволяет микроконтроллеру AVR перепрограммировать внутреннюю память программ FLASH. Память программ во всех AVR может использоваться для хранения констант, и теперь также параметров, потому что можно изменять содержимое FLASH во время работы программы (run-time).

Однако использование памяти FLASH для хранения параметров должно быть реализовано не настолько просто, как работа с EEPROM. Самопрограммирование предназначено для обновления программного обеспечения (firmware updating), однако гибкость этой технологии позволяет использовать её также и для обновления параметров. Эта секция дает базовую информацию о FLASH - что нужно для использования внутренней памяти программ AVR для хранения параметра.

Чтение FLASH во время записи (Read-While-Write). Память FLASH может быть перепрограммирована инструкцией SPM. Эта инструкция может выполняться только из секции загрузки FLASH (Boot section), расположенной в конце адресного пространства. Выполнение инструкции SPM из секции приложения (application section) не даст никакого эффекта. Секция приложения размещается начиная с адреса 0x0000, и продолжается до начала секции загрузки (см. рис. 1). Фьюзами можно выбрать 4 варианта размера секции загрузки. Абсолютные значения этих выбираемых размеров зависит от типа используемого AVR.

AVR105-Application-and-Boot-Sections

Рис. 1. Пример карты памяти FLASH микроконтроллера ATmega128 - секция приложения (Application Section) и секция загрузки (Boot Section).

Секция загрузки относится к области памяти, которую нельзя читать во время записи (так называемая No-Read-While-Write секция, NRWW). Приложение пользователя (рабочая часть firmware, выполняющая основные функции) всегда использует некоторую часть FLASH, которая может читаться во время записи (так называемая секция Read-While-Write, RWW, см. рис. 1). Однако секция приложения также может, в зависимости от размера секции загрузки, включать в себя некоторую часть NRWW. Когда выбран максимальный размер секции загрузки, то она занимает всю секцию NRWW, и таким образом секция приложения полностью занимает память RWW. Области NRWW и RWW имеют фиксированные размеры, которые не зависят от размера секции загрузки. Подробнее см. даташит на используемый микроконтроллер, раздел самопрограммирования.

Разница между NRWW и RWW частями FLASH состоит в том, что во время очистки или записи страниц в RWW микроконтроллер AVR может продолжить выполнение кода, находящегося в памяти NRWW. Но это невозможно, когда очищаются или записываются страницы NRWW: ядро AVR зависает (halted), когда модифицируются страницы области NRWW памяти FLASH. Грубо говоря, код в секции загрузки может работать во время перепрограммирования секции приложения, если модифицируемая страница памяти принадлежит области RWW.

Следовательно, та часть кода, которая обновляет параметры в памяти FLASH, должна находиться в секции загрузки, и сами параметры должны находиться в области RWW секции приложения, если AVR продолжает работу во время обновления параметров. Это требуется, например, когда прерывания не должны быть заблокированы во время записи параметров.

Стирание и программирование ячейки FLASH. Память FLASH состоит из независимых ячеек, каждая представляет один бит. Принцип работы ячейки FLASH основан на технологии плавающего затвора транзистора: электрический заряд, "захваченный" затвором, определяет логическое значение бита которое может быть прочитано из ячейки FLASH. Не слишком упрощая, описать работу FLASH можно так: когда ячейка "стирается" (erasing), заряд помещается на затвор транзистора, и ячейка читается как лог. 1. "Программирование" FLASH эквивалентно снятию заряда с затвора, что переводит ячейку в состояние лог. 0. Запрограммировать (разрядить) можно только ту ячейку, которая стерта (заряжена).

При этом память FLASH имеет страничную организацию. Очистка и программирование FLASH, когда используется самопрограммирование, происходит постранично. Очистка FLASH выполняется на страницу целиком, и запись FLASH также может быть выполнена только для страницы целиком.

Обратите внимание, что биты могут быть запрограммированы индивидуально. Поскольку программируемые биты разряжаются, другие заряженные биты остаются заряженными. Любой незапрограммированный (заряженный) бит может быть запрограммирован позже. Таким образом, программирование байта, который уже был ранее запрограммирован, возможно и без стирания байта, если нужно обнулить его некоторые разряды. Результат получается в виде побитной операции AND между старым и новым значением байта.

Например, запись значения 0x01 в байт памяти FLASH (это 8 ячеек FLASH) требует, чтобы байт был сначала стерт, что переводит его в значение 0xFF. Для записи (программирования) значения 7 самых старших битов (ячеек FLASH) должны быть разряжены. Если не делать очистку перед записью, то иногда нельзя будет записать нужное значение: предположим, что старое значение байта было 0xFE, и в него программируется значение 0x01; в результате получится 0x00, так как без стирания младший бит нельзя изменить с 0 на 1.

Рабочий ресурс FLASH. Фактически параметр (1) может несколько раз сохранен на единственной странице памяти FLASH, выбранной для хранения параметра. При хранении параметра во FLASH нужно учитывать гарантированную износостойкость ячеек FLASH, которая составляет обычно около 10000 циклов стирания/записи. Каждая ячейка может быть стерта и запрограммирована 10000 раз. Таким образом, если параметр может быть записан 10 раз на одной странице, используя при этом каждый раз разные ячейки, то износостойкость памяти повысится в 10 раз, до 100000 циклов записи. Это потому, что каждая ячейка будет записана только 10000 раз, путем перемещения места хранения параметра на странице.

Примечание (1): под термином "параметр" в этом контексте понимается как один параметр, так и набор параметров. Так что под "параметром" можно понимать набор данных произвольного размера.

Время записи. Когда записывается EEPROM, то можно записать только 1 байт за одну операцию. Не так происходит с памятью FLASH, потому что записывается сразу страница целиком. Таким образом, с точки зрения быстродействия выгоднее использовать FLASH для хранения параметра, когда иногда размер параметра больше, чем 1 байт. Чем больше параметр, тем меньше будет время записи в пересчете на 1 сохраняемый байт.

Например, запись параметра типа long (4 байта) займет примерно 4 мс (не считая времени стирания, которое занимает такое же время). Таким образом, на 1 байт приходится 1 мс при записи параметра long во FLASH. Если сравнивать с EEPROM, то у неё запись данных такого же размера потребует 32 мс (2). Для EEPROM учтено время стирания, однако сравнение некорректно, поскольку стирание FLASH делается только тогда, когда были использованы все ячейки страницы FLASH. Рассмотрим хранение параметра во FLASH микроконтроллера ATmega128. Размер страницы для него составляет 256 байт. Таким образом, можно сохранить переменную long на одной странице всего 256/4 = 64 раз. На 64 записи будет задействовано только 1 стирание, так что средняя длительность стирания составит примерно 4 мс / 64, что совсем мало.

Примечание (2): в этом примере используется ATmega128, и время программирования EEPROM указано для него. Нужно иметь в виду, что время программирования может зависеть от типа микроконтроллера – для получения подробной информации пожалуйста обратитесь к даташиту на используемый микроконтроллер.

Можно сделать вывод, что чем больше размер параметра, тем хранилище FLASH эффективнее с точки зрения времени записи – можно больше времени тратить на режимы пониженного энергопотребления (sleep modes), что снижает энергопотребление.

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

[Время хранения данных в памяти FLASH]

Промежуток времени, когда программируемая память может удерживать в себе корректные значения данных, называется допустимым временем хранения данных (data retention). Память не может хранить данные бесконечно долго, потому что в ячейках памяти есть утечка заряда. Величина заряда в ячейке падает с течением времени, и может произойти так, что в какой-то ячейке заряд больше не соответствует логическому уровню, который должен храниться. Как стертые, так и запрограммированные биты могут иметь утечку друг на друга, что в результате приведет к непредсказуемому состоянию. Если время хранения истекло, то содержимое памяти FLASH становится ненадежным.

Уменьшение времени хранения из-за доступа на стирание и запись. Когда ячейки FLASH стираются и записываются, то они физически изнашиваются. Доступ на чтение не влияет на время хранения. При увеличении количества циклов стирания / записи (erase/write, E/W) увеличиваются утечки ячеек. В результате величина заряда портится быстрее, и данные становятся недостоверными раньше – другими словами, уменьшается допустимое время хранения. Если количество выполненных циклов E/W превышает гарантированное количество 10K циклов E/W, то время хранения уменьшается так, что становится меньше ожидаемых 20 лет.

В связи с хранилищем параметра в памяти FLASH важно знать, что страницы FLASH независимы друг от друга; если одна страница используется для сохранения параметра, то у неё может уменьшаться время хранения, но остальная часть FLASH, используемая под код программы, не получает уменьшение времени хранения в связи с уменьшающимся временем хранения страницы параметра.

[Как быть со сбоями питания]

Нужно иметь в виду, что встраиваемые системы могут эксплуатироваться в условиях проблем с питанием. Это одна из причин, по которой нужно использовать энергонезависимые типы памяти для параметров; это позволяет восстановить параметры после цикла выключения / включения питания.

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

Меры, которые предпринимаются для борьбы с повреждениями FLASH, напоминают методы, которые применяются для борьбы с порчей EEPROM. Чтобы избежать повреждения данных FLASH при неожиданном сбое питания рекомендуется всегда задействовать технологию детектирования пропадания питания (Brown-out Detection), когда используется самопрограммирование.

Использование самопрограммирования. Подробное описание процедуры самопрограммирования можно найти в даташите на микроконтроллер, и в апнуте AVR109 [2].

Важно помнить, что цикл записи во FLASH не прерывается при поступления внешнего сброса (External RESET) или сброса по сбою питания (Brown-out RESET). Только сброс по включению питания (Power-on RESET) остановит выполняющийся цикл записи FLASH. Следовательно, цикл записи будет продолжаться, пока это возможно, даже когда уровень напряжения питание упал ниже рекомендованного для работы минимума. Это не увеличивает риск повреждения данных, а наоборот, повышает вероятность того, что операция стирания/записи страницы памяти FLASH будет завершена.

[Реализация]

Предложенная реализация хранилища параметра на FLASH сделана с использованием компилятора IAR EWAVR 2.27b. Код может быть портирован на другие компиляторы, однако это может потребовать некоторой работы, поскольку в этом примере использовались некоторые встроенные (intrinsic) функции компиляторов IAR.

Цель примера кода - получить драйвер, который может быстро сохранить параметр из нескольких байт, и также повысить при этом износоустойчивость хранилища (как можно меньше расходовать ресурс E/W памяти FLASH). Повышение износоустойчивости хранилища зависит от размера параметра и размера используемой страницы FLASH. В примере кода использовалась 7-байтная структура параметра, которая сохраняется на странице микроконтроллера ATmega128. Размер страницы у этого микроконтроллера составляет 256 байт. Одна страница может содержать 35 копий параметра (256/7 = целое число 36), при этом остается место под флаги завершения записи. Гарантированная износоустойчивость (Endurance) хранилища составит:

Endurance = endurance_одной_ячейки * количество_копий = 10000 * 35 = 350000 записей.

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

Дополнительно пример фокусируется на минимизации общего энергопотребления приложения с использованием хранилища на FLASH. Это достигается размещением параметра в области RWW памяти FLASH. Таким образом, можно продолжать выполнение кода из области NRWW памяти FLASH, пока обновляется параметр, что экономит процессорное время. Код сделан так, что прерывания могут продолжить работу, и управляемый прерываниями код, находящийся в области RWW, все еще может нормально работать.

Настраиваемые опции. Для повышения надежности метода сохранения параметра можно разрешить использование флагов writecompletion (сигнализация об успешном завершении записи параметра). Если это используется, запись параметра и флага места размещения параметра (который и является флагом write-completion) будет осуществляться за 2 раздельные операции записи. Благодаря этому можно определить, был ли параметр корректно записан - это так, если флаг write-completion запрограммирован. Однако по времени сохранение параметра и флага занимает в 2 раза больше времени в сравнении с одной операцией.

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

Опции управляются модулем кода FlashStorageDriver.c, и они по умолчанию разрешены.

Требования к микроконтроллеру. Пример предназначен для ATmega128, так что код адаптирован под конфигурацию этого чипа. Если пример будет использоваться с другими типами микроконтроллеров, то нужно изменить настройки командного файла линкера и связанную с типом устройства информацию в файле кода драйвера FlashStorageDriver.c.

[Описание кода firmware]

Драйвер состоит из 3 функций. Они описаны диаграммами алгоритма (рисунки 2, 3 и 4), комментарии к ним даны в последующих секциях.

FlashStorageInit. Процедура инициализации хранилища FLASH состоит из исследования состояния хранилища. Если параметр сохранен во временную память EEPROM (это вычисляется по флагу EEPROM Back-up Valid flag), то он будет восстановлен из EEPROM, и записан в хранилище FLASH. Иначе будет использоваться последняя используемая позиция в "буфере" FLASH, которая определяется по индексным флагам.

AVR105-FlashStorageInit

Рис. 2. Процесс инициализации FLASH-хранилища параметра.

FlashStorageWrite. Это подпрограмма, сохраняющая параметр. Сначала она проверяет, активен ли доступ к EEPROM. Если это так, то подпрограмма запретит прерывание EEPROM, и будет ожидать завершения текущей записи в EEPROM. Если страница параметра заполнена, то параметр сначала сохраняется в EEPROM. Затем FLASH-страница параметра будет стерта. Когда EEPROM удерживает параметр, флаг EEPROM Back-up Valid установлен. Как только процесс стирания FLASH-страницы параметра завершен, параметр записывается на FLASH-страницу параметра, и флаг EEPROM Back-up Valid очищается. После того, как параметр записан на страницу FLASH, соответствующий индексный бит параметра очищается. С помощью этого флага можно определить во время инициализации, что ячейка хранения параметра корректна. И наконец, прерывание EEPROM восстанавливается в свое исходное состояние.

В дополнение к вышеперечисленным операциям происходит управление доступом к области памяти RWW, так что после возврата из функции доступ на чтение памяти разрешен.

AVR105-FlashStorageWrite

Рис. 3. Процесс записи в FLASH-хранилище.

FlashStorageRead. Для рабочего приложения нельзя напрямую читать параметр из FLASH, потому что приложение не знает о текущем месторасположении параметра на странице FLASH. Поэтому для цели чтения параметра создана специальная функция FlashStorageRead. Сначала функция проверяет, активна ли в настоящее время операция записи инструкцией SPM, и затем читает и возвращает значение параметра, считанное с FLASH-страницы параметра.

AVR105-FlashStorageRead

Рис. 4. Процесс чтения из FLASH-хранилища.

[Ссылки]

1. AVR105: Power Efficient High Endurance Parameter Storage in Flash Memory site:atmel.com.
2. AVR109: самопрограммирование AVR.
3. 141229AVR103-AVR104-AVR105.zip - исходный код, документация.