Введение
Несмотря на все преимущества микроконтроллеров серии STM32 [1], они всё же имеют определённый недостаток, который заключается в отсутствии электрически перепрограммируемой постоянной памяти EEPROM. Многие микроконтроллеры семейства AVR и PIC имеют такую память, и это позволяет без проблем решать некоторые задачи, связанные с оперативным изменением и долговременным хранением данных. К сожалению, в микроконтроллерах серии STM32 такой памяти нет. Но выход всё же существует. Например, можно подключить внешнюю память EEPROM через последовательный интерфейс I2C или SPI. Если же не хочется подключать дополнительную внешнюю микросхему, то в качестве энергонезависимой памяти в STM32 можно использовать энергонезависимые ячейки памяти BKP [2] или часть флэш-памяти, которая предназначена для хранения программ. Правда, запись в такую память со стороны процессора требует соблюдения определённых процедур. Тем не менее, это лучше, чем ничего.
Использование энергонезависимых ячеек памяти BKP возможно лишь при наличии внешней батареи питания. Кроме того, количество таких ячеек невелико, поэтому предпочтительнее вариант использования некоторой части флэш-памяти.
Поскольку STM32 имеет большой объём флэш-памяти, частичное её использование для хранения энергонезависимых данных не причинит больших неудобств. Необходимо ещё учесть, что количество циклов перезаписи для флэш-памяти ограничено 10 000 циклов, в отличие от 100 000 циклов обычной EEPROM памяти. Однако 10 000 циклов тоже немало, а если выделить для энергонезависимых данных несколько областей флэш-памяти и производить поочерёдное их использование, то количество циклов можно многократно увеличить.
Организация флэш-памяти
Флэш-память состоит из главной памяти (Main Memory), информационного блока (Information Block) и блока регистров интерфейса с флэш-памятью (Flash Memory Interface Registers).
Для записи данных во флэш-память STM32 используется блок FPEC (Flash Program and Erase Controller), то есть контроллер записи и стирания флэш-памяти.
Интерфейс с флэш-памятью обладает следующими особенностями:
- интерфейс чтения с буфером предварительной выборки (два слова по 64 бита);
- опционный байтовый загрузчик;
- операции программирования и стирания флэш-памяти;
- защита от записи и чтения.
В таблице 1 представлена адресная организация флэш-памяти младшего семейства микроконтроллеров серии STM32.

Первый блок представляет собой основную память, в которую записывается программа и другие данные. Блок основной памяти поделён на страницы объёмом несколько килобайт.
Информационный блок содержит в себе два раздела: системную память и опционные байты. В системной памяти хранится загрузчик, который позволяет программировать контроллер через последовательный порт USART. Этот раздел памяти невозможно удалить или модифицировать. Раздел опционных байт хранит информацию о защите основной памяти. Он позволяет включить или отключить защиту от чтения и записи данных в основную флэш-память.
Прочитать программно 32-разрядные данные с именем переменной data из флэш-памяти можно при помощи следующей команды: data=(*(__IO uint32_t*) address).
Записать данные в основную область флэш-памяти можно только после предварительного стирания этой области памяти. Кроме того, перед записью данных необходимо разрешить запись в специальном регистре блока FPEC.
Стирать флэш-память можно только кратно страницам, каждая из которых состоит из нескольких килобайт. При этом необходимо помнить, что во флэш-памяти записана и хранится программа микроконтроллера. Поэтому область для записи данных необходимо выбирать в свободном от кода программы пространстве флэш-памяти. Удобнее всего для этого использовать последние страницы памяти. Кроме того, необходимо регулярно следить, чтобы размер программы не перекрыл область пользовательских данных, учитывая размер страниц микроконтроллера.
Все разряды данных очищенной области флэш-памяти принимают единичное значение. По этому признаку можно определить очищена память или нет.
Запись в основную область флэш-памяти можно производить по любому адресу. Вначале записываются два младших байта слова, а затем два старших байта.
Перед стиранием или записью в память необходимо снять её блокировку, а после окончания процедуры стирания или записи установить блокировку. Для снятия блокировки флэш-памяти необходимо последовательно записать в регистр FLASH_KEYR два числа: 0x45670123 и 0xCDEF89AB. Если записать в этот регистр другие данные, то блокировку невозможно будет снять до полной перезагрузки микроконтроллера.
Регистры блока FPEC
Карта регистров блока контроллера записи и стирания флэш-памяти FPEC приведена в таблице 2. Рассмотрим состав и назначение регистров данного блока, принимающих участие в работе с флэш-памятью.

В регистре FLASH_ACR используется лишь один третий разряд HLFCYA, который разрешает половинные циклы обращения к флэш-памяти, то есть 16-разрядными данными. Остальные биты этого регистра зарезервированы.
Регистр FLASH_KEYR используется для разблокировки флэш-памяти контроллера FPEC и обеспечивает сброс бита LOCK в регистре FLASH_CR. Разблокировка производится последовательной записью в этот регистр двух ключей: KEY1=0x45670123 и KEY2=0xCDEF89AB.
После записи ключа KEY1, а затем ключа KEY2 в данный регистр, бит LOCK будет сброшен, блок FPEC разблокирован, а регистр FLASH_CR станет доступным для записи.
После записи данных во флэш-память нужно программно установить бит LOCK. При необходимости снова записать данные, придётся опять выполнить процедуру разблокировки с помощью ключей KEY1 и KEY2.
В случае ошибки при записи ключей, блок FPEC заблокируется, и повторная запись верных ключей не сможет разблокировать его. В таком случае поможет только сброс микроконтроллера, после чего снова будет возможна процедура разблокировки блока FPEC.
Регистр FLASH_OPTKEYR используется для получения доступа к установке и сбросу разрядов в блоке опционных байт, которые изначально доступны только для чтения. Для получения возможности изменения данных в области опционных байт необходимо записать в регистр FLASH_OPTKEYR такую же последовательность ключей, что и для регистра FLASH_KEYR. После записи правильных ключей в регистре FLASH_CR будет установлен бит OPTWRE, который разрешает запись данных в область опционных байт флэш-памяти.
Регистр FLASH_SR содержит следующие специальные разряды:
- разряд 5 EOP (End of Operation) устанавливается аппаратно при успешном завершении операции записи или стирании флэш-памяти;
- разряд 4 WRPRTERR (Write Protection Error) устанавливается при попытке программирования защищённой от записи области памяти;
- разряд 2 PGERR (Programming Error) устанавливается при программировании, если данные по заданному адресу отличны от значения 0xFFFF, то есть не стёрты перед программированием;
- разряд 0 BSY (Busy) устанавливается во время операций записи и стирания флэш-памяти. Он аппаратно сбрасывается по окончании операций записи или стирания, а также при возникновении ошибки во время этих операций.
Все эти разряды сбрасываются записью в них единичного значения.
Регистр FLASH_CR имеет следующие разряды:
- разряд 12 EOPIE (End of Operation Interrupt Enable) разрешает генерацию прерывания после завершения операции записи или стирания данных во флэш-память;
- разряд 10 ERRIE (Error Interrupt Enable) разрешает генерацию прерывания при возникновении ошибок, то есть при установке бита PGERR или WRPRTERR в регистре FLASH_SR;
- разряд 9 OPTWRE (Option Bytes Write Enable) разрешает программирование опционных байт, устанавливается записью последовательности ключей в регистр FLASH_OPTKEYR, а сбрасывается программно;
- разряд 7 LOCK блокирует запись и стирание флэш-памяти;
- разряд 6 STRT запускает процедуру стирания флэш-памяти;
- разряд 5 OPTER разрешает процедуру стирания опционных байт;
- разряд 4 OPTPG разрешает процедуру программирования опционных байт;
- разряд 2 MER (Mass Erase) разрешает процедуру полного стирания флэш-памяти;
- разряд 1 PER (Page Erase) разрешает процедуру стирания одной страницы флэш-памяти;
- разряд 0 PG (Programming) разрешает процедуру программирования флэш-памяти.
Регистр FLASH_AR предназначен для задания адреса программируемой флэш-памяти. В нём указывается адрес, по которому будут записаны данные при программировании. Для стирания определённой страницы флэш-памяти в этот регистр необходимо записать любой из адресов, входящих в эту страницу, причём не обязательно начальный.
Регистры FLASH_OBR и FLASH_WRPR в операциях записи и стирания не задействованы. Они предназначены для установки защиты от несанкционированного доступа к коду программы, а также для некоторых других настроек.
Пример программы
Рассмотрим пример программы для стирания и программирования флэш-памяти непосредственно из работающего приложения, то есть в так называемом режиме IAP (In Application Programming).
Все процедуры стирания и записи флэш-памяти производятся с активным использованием рассмотренных выше регистров блока FPEC.
В листинге приведена программа, которая содержит все необходимые функции для работы с флэш-памятью, а так же главный модуль, осуществляющий стирание страницы флэш-памяти и запись в неё произвольных данных. Программа снабжена подробными комментариями, которые поясняют выполняемые процедуры.

На основе примера из листинга можно создать библиотечную функцию, которая будет эмулировать память EEPROM и может применяться по мере необходимости в любых программах для микроконтроллеров серии STM32.
Следует помнить о том, что для стирания и записи данных во флэш-память требуется определённое время, поэтому во время выполнения таких операций реакция микроконтроллера будет замедленной.
В качестве тренировки можно развить данную программу, дополнив её возможностью обмена данными через последовательный порт USART, который позволит производить нужные операции с флэш-памятью в режиме диалога с оператором.
Литература
- www.st.com.
- Вальпа О. Современные 32-разрядные ARM-микроконтроллеры серии STM32: блок резервных данных BKP. Современная электроника. № 3. 2014.
Если вам понравился материал, кликните значок — вы поможете нам узнать, каким статьям и новостям следует отдавать предпочтение. Если вы хотите обсудить материал —не стесняйтесь оставлять свои комментарии : возможно, они будут полезны другим нашим читателям!

